Scripts/AQ40: Rewrite Fankriss (#31200)

This commit is contained in:
offl
2025-08-16 15:35:22 +03:00
committed by GitHub
parent 126fa17de9
commit 60c8dc17bc
3 changed files with 177 additions and 170 deletions

View File

@@ -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;

View File

@@ -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

View File

@@ -15,202 +15,175 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* 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,
// Enrage for his spawns
SPELL_ENRAGE = 28798
SPELL_SUMMON_WORM_1 = 518,
SPELL_SUMMON_WORM_2 = 25831,
SPELL_SUMMON_WORM_3 = 25832,
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
};
class boss_fankriss : public CreatureScript
enum FankrissEvents
{
public:
boss_fankriss() : CreatureScript("boss_fankriss") { }
EVENT_MORTAL_WOUND = 1,
EVENT_SUMMON_WORM,
EVENT_ENTANGLE
};
CreatureAI* GetAI(Creature* creature) const override
// 15510 - Fankriss the Unyielding
struct boss_fankriss : public BossAI
{
boss_fankriss(Creature* creature) : BossAI(creature, DATA_FRANKRIS), _wormsSpawnPerWave(0), _entanglePerWave(0) { }
std::vector<uint32> SummonWormSpells = { SPELL_SUMMON_WORM_1, SPELL_SUMMON_WORM_2, SPELL_SUMMON_WORM_3 };
std::vector<uint32> EntangleSpells = { SPELL_ENTANGLE_1, SPELL_ENTANGLE_2, SPELL_ENTANGLE_3 };
void Reset() override
{
return GetAQ40AI<boss_fankrissAI>(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)
BossAI::JustEngagedWith(who);
events.ScheduleEvent(EVENT_MORTAL_WOUND, 2s, 6s);
events.ScheduleEvent(EVENT_SUMMON_WORM, 30s, 50s);
events.ScheduleEvent(EVENT_ENTANGLE, 15s, 20s);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
Initialize();
}
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;
void Reset() override
{
Initialize();
_Reset();
}
void SummonSpawn(Unit* victim)
{
if (!victim)
return;
int Rand = 10 + (rand32() % 10);
float RandX = 0.f;
float RandY = 0.f;
switch (rand32() % 2)
switch (eventId)
{
case 0: RandX = 0.0f - Rand; break;
case 1: RandX = 0.0f + Rand; break;
}
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);
}
void UpdateAI(uint32 diff) override
{
//Return since we have no target
if (!UpdateVictim())
return;
//MortalWound_Timer
if (MortalWound_Timer <= diff)
{
DoCastVictim(SPELL_MORTAL_WOUND);
MortalWound_Timer = urand(10000, 20000);
} else MortalWound_Timer -= diff;
//Summon 1-3 Spawns of Fankriss at random time.
if (SpawnSpawns_Timer <= diff)
{
switch (urand(0, 2))
case EVENT_MORTAL_WOUND:
DoCastVictim(SPELL_MORTAL_WOUND);
events.Repeat(4s, 12s);
break;
case EVENT_SUMMON_WORM:
{
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;
DoCastSelf(SummonWormSpells[_wormsSpawnPerWave - 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))
--_wormsSpawnPerWave;
if (!_wormsSpawnPerWave)
{
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;
}
_wormsSpawnPerWave = urand(1, 3);
Trinity::Containers::RandomShuffle(SummonWormSpells);
events.Repeat(20s, 70s);
}
SpawnHatchlings_Timer = urand(45000, 60000);
} else SpawnHatchlings_Timer -= diff;
else
events.Repeat(5s, 20s);
break;
}
case EVENT_ENTANGLE:
{
Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true);
if (!target)
target = me->GetVictim();
if (target)
DoCast(target, EntangleSpells[_entanglePerWave - 1]);
--_entanglePerWave;
if (!_entanglePerWave)
{
_entanglePerWave = urand(1, 3);
Trinity::Containers::RandomShuffle(EntangleSpells);
events.Repeat(25s, 55s);
}
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);
}