From 60c8dc17bcf1504196c2e3442442391a63c855fd Mon Sep 17 00:00:00 2001
From: offl <11556157+offl@users.noreply.github.com>
Date: Sat, 16 Aug 2025 15:35:22 +0300
Subject: Scripts/AQ40: Rewrite Fankriss (#31200)
---
sql/updates/world/3.3.5/2025_08_16_01_world.sql | 32 +++
src/server/game/Spells/SpellMgr.cpp | 4 +-
.../Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp | 297 ++++++++++-----------
3 files changed, 170 insertions(+), 163 deletions(-)
create mode 100644 sql/updates/world/3.3.5/2025_08_16_01_world.sql
diff --git a/sql/updates/world/3.3.5/2025_08_16_01_world.sql b/sql/updates/world/3.3.5/2025_08_16_01_world.sql
new file mode 100644
index 00000000000..d6a1e422a25
--- /dev/null
+++ b/sql/updates/world/3.3.5/2025_08_16_01_world.sql
@@ -0,0 +1,32 @@
+--
+DELETE FROM `spell_target_position` WHERE `ID` IN (518,25831,25832,26630,26631,26632,720,731,1121);
+INSERT INTO `spell_target_position` (`ID`, `EffectIndex`, `MapID`, `PositionX`, `PositionY`, `PositionZ`, `Orientation`, `VerifiedBuild`) VALUES
+(518,0,531,-8028.5,1050.9,-54,0,0),
+(25831,0,531,-8158.03,1139.3,-83.95,0,0),
+(25832,0,531,-8029.25,1237.78,-85.2285,0,0),
+(720,0,531,-8043.6,1254.1,-84.3,0,0),
+(731,0,531,-8003,1222.9,-82.1,0,0),
+(1121,0,531,-8022.3,1149,-89.1,0,0),
+(26630,0,531,-8043.6,1254.1,-84.2167,0,0),
+(26631,0,531,-8003,1222.9,-82.0167,0,0),
+(26632,0,531,-8022.3,1149,-89.0167,0,0);
+
+UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 15962;
+DELETE FROM `smart_scripts` WHERE `entryorguid` IN (15630,15962) AND `source_type` = 0;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`event_param5`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_param4`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(15630,0,0,0,37,0,100,0,0,0,0,0,0,116,2,0,0,0,0,0,1,0,0,0,0,0,0,0,0,"Spawn of Fankriss - On AI Initialize - Set Corpse Delay"),
+(15630,0,1,0,11,0,100,0,0,0,0,0,0,38,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,"Spawn of Fankriss - On Spawn - Set In Combat With Zone"),
+(15630,0,2,0,60,0,100,1,20000,20000,0,0,0,11,26662,0,0,0,0,0,1,0,0,0,0,0,0,0,0,"Spawn of Fankriss - On Update - Cast 'Berserk'"),
+
+(15962,0,0,0,37,0,100,0,0,0,0,0,0,116,2,0,0,0,0,0,1,0,0,0,0,0,0,0,0,"Vekniss Hatchling - On AI Initialize - Set Corpse Delay"),
+(15962,0,1,0,11,0,100,0,0,0,0,0,0,38,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,"Vekniss Hatchling - On Spawn - Set In Combat With Zone");
+
+DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_fankriss_entangle';
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(720, 'spell_fankriss_entangle'),
+(731, 'spell_fankriss_entangle'),
+(1121, 'spell_fankriss_entangle');
+
+UPDATE `creature_template` SET `speed_run` = 2.14285714286 WHERE `entry` = 15510;
+UPDATE `creature_template` SET `speed_run` = 1.71428571429 WHERE `entry` = 15630;
+UPDATE `creature_template` SET `speed_run` = 1.42857142857 WHERE `entry` = 15962;
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 5dd878fdddb..154faee4783 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -3173,7 +3173,9 @@ void SpellMgr::LoadSpellInfoCorrections()
ApplySpellFix({
42818, // Headless Horseman - Wisp Flight Port
42821, // Headless Horseman - Wisp Flight Missile
- 17678 // Despawn Spectral Combatants
+ 17678, // Despawn Spectral Combatants
+ 720, // Entangle
+ 731 // Entangle
}, [](SpellInfo* spellInfo)
{
spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(6); // 100 yards
diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp
index d13b84e3719..4625edb8525 100644
--- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp
+++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp
@@ -15,202 +15,175 @@
* with this program. If not, see .
*/
-/* ScriptData
-SDName: Boss_Fankriss
-SD%Complete: 100
-SDComment: sound not implemented
-SDCategory: Temple of Ahn'Qiraj
-EndScriptData */
+/*
+ * Timers requires to be revisited
+ */
#include "ScriptMgr.h"
+#include "Containers.h"
#include "ScriptedCreature.h"
+#include "SpellInfo.h"
+#include "SpellScript.h"
#include "temple_of_ahnqiraj.h"
-#include "TemporarySummon.h"
-#define SOUND_SENTENCE_YOU 8588
-#define SOUND_SERVE_TO 8589
-#define SOUND_LAWS 8590
-#define SOUND_TRESPASS 8591
-#define SOUND_WILL_BE 8592
-
-enum Spells
+enum FankrissSpells
{
- SPELL_MORTAL_WOUND = 28467,
- SPELL_ROOT = 28858,
+ SPELL_MORTAL_WOUND = 25646,
+
+ SPELL_SUMMON_WORM_1 = 518,
+ SPELL_SUMMON_WORM_2 = 25831,
+ SPELL_SUMMON_WORM_3 = 25832,
- // Enrage for his spawns
- SPELL_ENRAGE = 28798
+ SPELL_ENTANGLE_1 = 720,
+ SPELL_ENTANGLE_2 = 731,
+ SPELL_ENTANGLE_3 = 1121,
+
+ SPELL_SPAWN_HATCHLING_1 = 26630,
+ SPELL_SPAWN_HATCHLING_2 = 26631,
+ SPELL_SPAWN_HATCHLING_3 = 26632
+};
+
+enum FankrissEvents
+{
+ EVENT_MORTAL_WOUND = 1,
+ EVENT_SUMMON_WORM,
+ EVENT_ENTANGLE
};
-class boss_fankriss : public CreatureScript
+// 15510 - Fankriss the Unyielding
+struct boss_fankriss : public BossAI
{
-public:
- boss_fankriss() : CreatureScript("boss_fankriss") { }
+ boss_fankriss(Creature* creature) : BossAI(creature, DATA_FRANKRIS), _wormsSpawnPerWave(0), _entanglePerWave(0) { }
- CreatureAI* GetAI(Creature* creature) const override
+ std::vector SummonWormSpells = { SPELL_SUMMON_WORM_1, SPELL_SUMMON_WORM_2, SPELL_SUMMON_WORM_3 };
+ std::vector EntangleSpells = { SPELL_ENTANGLE_1, SPELL_ENTANGLE_2, SPELL_ENTANGLE_3 };
+
+ void Reset() override
{
- return GetAQ40AI(creature);
+ _Reset();
+ _wormsSpawnPerWave = urand(1, 3);
+ Trinity::Containers::RandomShuffle(SummonWormSpells);
+ _entanglePerWave = urand(1, 3);
+ Trinity::Containers::RandomShuffle(EntangleSpells);
}
- struct boss_fankrissAI : public BossAI
+ void JustEngagedWith(Unit* who) override
{
- boss_fankrissAI(Creature* creature) : BossAI(creature, DATA_FRANKRIS)
- {
- Initialize();
- }
+ BossAI::JustEngagedWith(who);
- void Initialize()
- {
- MortalWound_Timer = urand(10000, 15000);
- SpawnHatchlings_Timer = urand(6000, 12000);
- SpawnSpawns_Timer = urand(15000, 45000);
- }
-
- uint32 MortalWound_Timer;
- uint32 SpawnHatchlings_Timer;
- uint32 SpawnSpawns_Timer;
+ events.ScheduleEvent(EVENT_MORTAL_WOUND, 2s, 6s);
+ events.ScheduleEvent(EVENT_SUMMON_WORM, 30s, 50s);
+ events.ScheduleEvent(EVENT_ENTANGLE, 15s, 20s);
+ }
- void Reset() override
- {
- Initialize();
- _Reset();
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- void SummonSpawn(Unit* victim)
- {
- if (!victim)
- return;
+ events.Update(diff);
- int Rand = 10 + (rand32() % 10);
- float RandX = 0.f;
- float RandY = 0.f;
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- switch (rand32() % 2)
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
{
- case 0: RandX = 0.0f - Rand; break;
- case 1: RandX = 0.0f + Rand; break;
- }
+ case EVENT_MORTAL_WOUND:
+ DoCastVictim(SPELL_MORTAL_WOUND);
+ events.Repeat(4s, 12s);
+ break;
+ case EVENT_SUMMON_WORM:
+ {
+ DoCastSelf(SummonWormSpells[_wormsSpawnPerWave - 1]);
- Rand = 10 + (rand32() % 10);
- switch (rand32() % 2)
- {
- case 0: RandY = 0.0f - Rand; break;
- case 1: RandY = 0.0f + Rand; break;
- }
- Rand = 0;
- Creature* Spawn = DoSpawnCreature(15630, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30s);
- if (Spawn)
- Spawn->AI()->AttackStart(victim);
- }
+ --_wormsSpawnPerWave;
- void UpdateAI(uint32 diff) override
- {
- //Return since we have no target
- if (!UpdateVictim())
- return;
+ if (!_wormsSpawnPerWave)
+ {
+ _wormsSpawnPerWave = urand(1, 3);
+ Trinity::Containers::RandomShuffle(SummonWormSpells);
+ events.Repeat(20s, 70s);
+ }
+ else
+ events.Repeat(5s, 20s);
+ break;
+ }
+ case EVENT_ENTANGLE:
+ {
+ Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true);
- //MortalWound_Timer
- if (MortalWound_Timer <= diff)
- {
- DoCastVictim(SPELL_MORTAL_WOUND);
- MortalWound_Timer = urand(10000, 20000);
- } else MortalWound_Timer -= diff;
+ if (!target)
+ target = me->GetVictim();
- //Summon 1-3 Spawns of Fankriss at random time.
- if (SpawnSpawns_Timer <= diff)
- {
- switch (urand(0, 2))
- {
- case 0:
- SummonSpawn(SelectTarget(SelectTargetMethod::Random, 0));
- break;
- case 1:
- SummonSpawn(SelectTarget(SelectTargetMethod::Random, 0));
- SummonSpawn(SelectTarget(SelectTargetMethod::Random, 0));
- break;
- case 2:
- SummonSpawn(SelectTarget(SelectTargetMethod::Random, 0));
- SummonSpawn(SelectTarget(SelectTargetMethod::Random, 0));
- SummonSpawn(SelectTarget(SelectTargetMethod::Random, 0));
- break;
- }
- SpawnSpawns_Timer = urand(30000, 60000);
- } else SpawnSpawns_Timer -= diff;
+ if (target)
+ DoCast(target, EntangleSpells[_entanglePerWave - 1]);
- // Teleporting Random Target to one of the three tunnels and spawn 4 hatchlings near the gamer.
- //We will only telport if fankriss has more than 3% of hp so teleported gamers can always loot.
- if (HealthAbovePct(3))
- {
- if (SpawnHatchlings_Timer <= diff)
- {
- if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
+ --_entanglePerWave;
+
+ if (!_entanglePerWave)
{
- DoCast(target, SPELL_ROOT);
-
- if (GetThreat(target))
- ModifyThreatByPercent(target, -100);
-
- Creature* Hatchling = nullptr;
- switch (urand(0, 2))
- {
- case 0:
- DoTeleportPlayer(target, -8106.0142f, 1289.2900f, -74.419533f, 5.112f);
- Hatchling = me->SummonCreature(15962, target->GetPositionX()-3, target->GetPositionY()-3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15s);
- if (Hatchling)
- Hatchling->AI()->AttackStart(target);
- Hatchling = me->SummonCreature(15962, target->GetPositionX()-3, target->GetPositionY()+3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15s);
- if (Hatchling)
- Hatchling->AI()->AttackStart(target);
- Hatchling = me->SummonCreature(15962, target->GetPositionX()-5, target->GetPositionY()-5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15s);
- if (Hatchling)
- Hatchling->AI()->AttackStart(target);
- Hatchling = me->SummonCreature(15962, target->GetPositionX()-5, target->GetPositionY()+5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15s);
- if (Hatchling)
- Hatchling->AI()->AttackStart(target);
- break;
- case 1:
- DoTeleportPlayer(target, -7990.135354f, 1155.1907f, -78.849319f, 2.608f);
- Hatchling = me->SummonCreature(15962, target->GetPositionX() - 3, target->GetPositionY() - 3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15s);
- if (Hatchling)
- Hatchling->AI()->AttackStart(target);
- Hatchling = me->SummonCreature(15962, target->GetPositionX()-3, target->GetPositionY()+3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15s);
- if (Hatchling)
- Hatchling->AI()->AttackStart(target);
- Hatchling = me->SummonCreature(15962, target->GetPositionX()-5, target->GetPositionY()-5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15s);
- if (Hatchling)
- Hatchling->AI()->AttackStart(target);
- Hatchling = me->SummonCreature(15962, target->GetPositionX()-5, target->GetPositionY()+5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15s);
- if (Hatchling)
- Hatchling->AI()->AttackStart(target);
- break;
- case 2:
- DoTeleportPlayer(target, -8159.7753f, 1127.9064f, -76.868660f, 0.675f);
- Hatchling = me->SummonCreature(15962, target->GetPositionX() - 3, target->GetPositionY() - 3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15s);
- if (Hatchling)
- Hatchling->AI()->AttackStart(target);
- Hatchling = me->SummonCreature(15962, target->GetPositionX()-3, target->GetPositionY()+3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15s);
- if (Hatchling)
- Hatchling->AI()->AttackStart(target);
- Hatchling = me->SummonCreature(15962, target->GetPositionX()-5, target->GetPositionY()-5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15s);
- if (Hatchling)
- Hatchling->AI()->AttackStart(target);
- Hatchling = me->SummonCreature(15962, target->GetPositionX()-5, target->GetPositionY()+5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15s);
- if (Hatchling)
- Hatchling->AI()->AttackStart(target);
- break;
- }
+ _entanglePerWave = urand(1, 3);
+ Trinity::Containers::RandomShuffle(EntangleSpells);
+ events.Repeat(25s, 55s);
}
- SpawnHatchlings_Timer = urand(45000, 60000);
- } else SpawnHatchlings_Timer -= diff;
+ else
+ events.Repeat(5s, 10s);
+ break;
+ }
+ default:
+ break;
}
- DoMeleeAttackIfReady();
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+private:
+ uint8 _wormsSpawnPerWave;
+ uint8 _entanglePerWave;
+};
+
+// 720, 731, 1121 - Entangle
+class spell_fankriss_entangle : public SpellScript
+{
+ PrepareSpellScript(spell_fankriss_entangle);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_SPAWN_HATCHLING_1, SPELL_SPAWN_HATCHLING_2, SPELL_SPAWN_HATCHLING_3 });
+ }
+
+ void HandleAfterCast()
+ {
+ switch (GetSpellInfo()->Id)
+ {
+ case SPELL_ENTANGLE_1:
+ GetCaster()->CastSpell(GetCaster(), SPELL_SPAWN_HATCHLING_1, true);
+ break;
+ case SPELL_ENTANGLE_2:
+ GetCaster()->CastSpell(GetCaster(), SPELL_SPAWN_HATCHLING_2, true);
+ break;
+ case SPELL_ENTANGLE_3:
+ GetCaster()->CastSpell(GetCaster(), SPELL_SPAWN_HATCHLING_3, true);
+ break;
+ default:
+ break;
}
- };
+ }
+ void Register() override
+ {
+ AfterCast += SpellCastFn(spell_fankriss_entangle::HandleAfterCast);
+ }
};
void AddSC_boss_fankriss()
{
- new boss_fankriss();
+ RegisterAQ40CreatureAI(boss_fankriss);
+ RegisterSpellScript(spell_fankriss_entangle);
}
--
cgit v1.2.3