Scripts/AQ20: Implement Andorov's event (#31512)

Closes #9636

(cherry picked from commit 20927ba78f6a3a68df1cf432c188462d70692fbe)
This commit is contained in:
offl
2026-06-29 22:35:57 +02:00
committed by Shauren
parent cf9c07d9c8
commit 34f14f269b
8 changed files with 605 additions and 76 deletions
@@ -0,0 +1,166 @@
--
SET @SPAWN_GROUP_ID := 333; -- 1
SET @CGUID := 142800; -- 5
UPDATE `creature` SET `StringId` = 'GeneralRajaxxWave1' WHERE `guid` IN (144611,144653,144610,144656,144655,144654,144676);
UPDATE `creature` SET `StringId` = 'GeneralRajaxxWave2' WHERE `guid` IN (144619,144617,144616,144660,144659,144658,144677);
UPDATE `creature` SET `StringId` = 'GeneralRajaxxWave3' WHERE `guid` IN (144614,144613,144612,144618,144657,144615,144674);
UPDATE `creature` SET `StringId` = 'GeneralRajaxxWave4' WHERE `guid` IN (144665,144662,144661,144626,144625,144623,144675);
UPDATE `creature` SET `StringId` = 'GeneralRajaxxWave5' WHERE `guid` IN (144622,144621,144620,144664,144624,144663,144652);
UPDATE `creature` SET `StringId` = 'GeneralRajaxxWave6' WHERE `guid` IN (144631,144670,144630,144672,144671,144669,144673);
UPDATE `creature` SET `StringId` = 'GeneralRajaxxWave7' WHERE `guid` IN (144629,144628,144627,144668,144667,144666,144651);
UPDATE `creature` SET `spawntimesecs` = 604800 WHERE `id` IN (15385,15386,15388,15389,15390,15391,15392,15344,15387);
DELETE FROM `creature_formations` WHERE `leaderGUID` IN (144611,144619,144614,144665,144622,144631,144629);
INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES
(144611,144611,0,0,3,0,0),
(144611,144653,0,0,3,0,0),
(144611,144610,0,0,3,0,0),
(144611,144656,0,0,3,0,0),
(144611,144655,0,0,3,0,0),
(144611,144654,0,0,3,0,0),
(144611,144676,0,0,3,0,0),
(144619,144619,0,0,3,0,0),
(144619,144617,0,0,3,0,0),
(144619,144616,0,0,3,0,0),
(144619,144660,0,0,3,0,0),
(144619,144659,0,0,3,0,0),
(144619,144658,0,0,3,0,0),
(144619,144677,0,0,3,0,0),
(144614,144614,0,0,3,0,0),
(144614,144613,0,0,3,0,0),
(144614,144612,0,0,3,0,0),
(144614,144618,0,0,3,0,0),
(144614,144657,0,0,3,0,0),
(144614,144615,0,0,3,0,0),
(144614,144674,0,0,3,0,0),
(144665,144665,0,0,3,0,0),
(144665,144662,0,0,3,0,0),
(144665,144661,0,0,3,0,0),
(144665,144626,0,0,3,0,0),
(144665,144625,0,0,3,0,0),
(144665,144623,0,0,3,0,0),
(144665,144675,0,0,3,0,0),
(144622,144622,0,0,3,0,0),
(144622,144621,0,0,3,0,0),
(144622,144620,0,0,3,0,0),
(144622,144664,0,0,3,0,0),
(144622,144624,0,0,3,0,0),
(144622,144663,0,0,3,0,0),
(144622,144652,0,0,3,0,0),
(144631,144631,0,0,3,0,0),
(144631,144670,0,0,3,0,0),
(144631,144630,0,0,3,0,0),
(144631,144672,0,0,3,0,0),
(144631,144671,0,0,3,0,0),
(144631,144669,0,0,3,0,0),
(144631,144673,0,0,3,0,0),
(144629,144629,0,0,3,0,0),
(144629,144628,0,0,3,0,0),
(144629,144627,0,0,3,0,0),
(144629,144668,0,0,3,0,0),
(144629,144667,0,0,3,0,0),
(144629,144666,0,0,3,0,0),
(144629,144651,0,0,3,0,0);
DELETE FROM `spawn_group` WHERE `spawnId` BETWEEN @CGUID+0 AND @CGUID+4 AND `spawnType` = 0;
INSERT INTO `spawn_group` (`groupId`, `spawnType`, `spawnId`) VALUES
(@SPAWN_GROUP_ID+0,0,@CGUID+0),
(@SPAWN_GROUP_ID+0,0,@CGUID+1),
(@SPAWN_GROUP_ID+0,0,@CGUID+2),
(@SPAWN_GROUP_ID+0,0,@CGUID+3),
(@SPAWN_GROUP_ID+0,0,@CGUID+4);
DELETE FROM `spawn_group_template` WHERE `groupId` = @SPAWN_GROUP_ID+0;
INSERT INTO `spawn_group_template` (`groupId`, `groupName`, `groupFlags`) VALUES
(@SPAWN_GROUP_ID+0,"Ruins of Ahn'Qiraj - Lieutenant General Andorov",4);
-- These positions are not default, no CreateObject2
DELETE FROM `creature` WHERE `guid` BETWEEN @CGUID+0 AND @CGUID+4;
INSERT INTO `creature` (`guid`,`id`,`map`,`zoneId`,`areaId`,`spawnDifficulties`,`phaseId`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`wander_distance`,`curHealthPct`,`MovementType`,`unit_flags`,`ScriptName`,`StringId`,`VerifiedBuild`) VALUES
(@CGUID+0,15471,509,0,0,'3',0,0,1,-8624.473,1471.7743,32.0758,2.3319497,604800,0,100,0,0x8200,'',NULL,0),
(@CGUID+1,15473,509,0,0,'3',0,0,1,-8624.473,1471.7743,32.0758,2.3319497,604800,0,100,0,0x8200,'',NULL,0),
(@CGUID+2,15473,509,0,0,'3',0,0,1,-8624.473,1471.7743,32.0758,2.3319497,604800,0,100,0,0x8200,'',NULL,0),
(@CGUID+3,15473,509,0,0,'3',0,0,1,-8624.473,1471.7743,32.0758,2.3319497,604800,0,100,0,0x8200,'',NULL,0),
(@CGUID+4,15473,509,0,0,'3',0,0,1,-8624.473,1471.7743,32.0758,2.3319497,604800,0,100,0,0x8200,'',NULL,0);
DELETE FROM `creature_formations` WHERE `leaderGUID` = @CGUID+0;
INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES
(@CGUID+0,@CGUID+0,0,0,515,0,0),
(@CGUID+0,@CGUID+1,5,75,515,0,0),
(@CGUID+0,@CGUID+2,5,285,515,0,0),
(@CGUID+0,@CGUID+3,5,330,515,0,0),
(@CGUID+0,@CGUID+4,5,30,515,0,0);
DELETE FROM `creature_template_movement` WHERE `CreatureId` = 15471;
INSERT INTO `creature_template_movement` (`CreatureId`, `InteractionPauseTimer`) VALUES
(15471,0);
UPDATE `creature_template_addon` SET `SheathState` = 1 WHERE `entry` IN (15471,15473);
DELETE FROM `creature_template_gossip` WHERE `CreatureID` = 15471;
UPDATE `creature_template` SET `RegenHealth` = 0, `ScriptName` = 'npc_andorov' WHERE `entry` = 15471;
UPDATE `creature_template` SET `RegenHealth` = 0 WHERE `entry` = 15473;
-- First path is incomplete
DELETE FROM `waypoint_path` WHERE `PathId` IN (4,5);
INSERT INTO `waypoint_path` (`PathId`, `MoveType`, `Flags`, `Velocity`, `Comment`) VALUES
(4,1,0,NULL,'Migrated from refactor'),
(5,1,0,NULL,'Migrated from refactor');
DELETE FROM `waypoint_path_node` WHERE `PathId` IN (4,5);
INSERT INTO `waypoint_path_node` (`PathId`, `NodeId`, `PositionX`, `PositionY`, `PositionZ`, `Orientation`, `Delay`) VALUES
(4,1,-8679.187,1535.1178,31.96736,NULL,0),
(4,2,-8701.477,1561.7574,32.17472,NULL,0),
(4,3,-8720.072,1580.9626,21.511324,NULL,0),
(4,4,-8746.162,1603.494,21.613367,NULL,0),
(4,5,-8780.431,1617.8787,21.455776,NULL,0),
(4,6,-8823.478,1624.6688,19.80574,NULL,0),
(4,7,-8855.329,1637.9473,19.790516,NULL,0),
(4,8,-8870.721,1648.4009,21.511328,5.637413501739501953,1),
(5,1,-8886.095,1598.713,21.4053,NULL,0),
(5,2,-8904.383,1578.6167,21.511332,NULL,0),
(5,3,-8920.576,1551.9479,21.407932,NULL,0),
(5,4,-8939.951,1551.127,21.566868,NULL,0);
DELETE FROM `gossip_menu` WHERE `MenuID` = 6629 AND `TextID` = 7883;
DELETE FROM `gossip_menu` WHERE `MenuID` = 7048 AND `TextID` IN (7883,8305);
INSERT INTO `gossip_menu` (`MenuID`, `TextID`, `VerifiedBuild`) VALUES
(6629,7883,0);
DELETE FROM `creature_text` WHERE `CreatureID` = 15471;
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(15471,0,0,"Remember, Rajaxx, when I said I'd kill you last?",14,0,100,22,0,0,11028,0,"Lieutenant General Andorov"),
(15471,1,0,"I lied...",14,0,100,0,0,0,11477,0,"Lieutenant General Andorov"),
(15471,2,0,"They come now. Try not to get yourself killed, young blood.",14,0,100,22,0,0,11012,0,"Lieutenant General Andorov"),
(15471,3,0,"Come get some!",12,0,100,25,0,0,11478,0,"Lieutenant General Andorov"),
(15471,4,0,"Kill first, ask questions later... Incoming!",14,0,100,45,0,0,11032,0,"Lieutenant General Andorov"),
(15471,5,0,"My work here is done. I'll be sure to let Mar'alith and the others at Cenarion Hold know that you helped me out a little. Be careful in here, you don't have me holdin' your hand past this point.",14,0,100,0,0,0,11560,0,"Lieutenant General Andorov");
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 15473;
DELETE FROM `smart_scripts` WHERE `entryorguid` = 15473 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
(15473,0,0,0,0,0,100,0,5000,10000,5000,15000,0,11,16856,0,0,0,0,0,2,0,0,0,0,0,0,0,0,"Kaldorei Elite - In Combat - Cast 'Mortal Strike'"),
(15473,0,1,0,0,0,100,0,10000,15000,10000,20000,0,11,26350,0,0,0,0,0,2,0,0,0,0,0,0,0,0,"Kaldorei Elite - In Combat - Cast 'Cleave'");
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 15344;
UPDATE `creature_template_difficulty` SET `GoldMin` = 0, `GoldMax` = 0 WHERE `entry` = 15344;
DELETE FROM `smart_scripts` WHERE `entryorguid` IN (15344,15387) 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
(15344,0,0,0,37,0,100,0,0,0,0,0,0,116,5,0,0,0,0,0,1,0,0,0,0,0,0,0,0,"Swarmguard Needler - On AI Initialize - Set Corpse Delay"),
(15344,0,1,0,0,0,100,0,5000,10000,5000,10000,0,11,40504,0,0,0,0,0,2,0,0,0,0,0,0,0,0,"Swarmguard Needler - In Combat - Cast 'Cleave'"),
(15387,0,0,0,37,0,100,0,0,0,0,0,0,116,5,0,0,0,0,0,1,0,0,0,0,0,0,0,0,"Qiraji Warrior - On AI Initialize - Set Corpse Delay"),
(15387,0,1,0,0,0,100,0,10000,15000,10000,15000,0,11,10966,0,0,0,0,0,2,0,0,0,0,0,0,0,0,"Qiraji Warrior - In Combat - Cast 'Uppercut'"),
(15387,0,2,0,0,0,100,0,10000,20000,15000,25000,0,11,15588,0,0,0,0,0,1,0,0,0,0,0,0,0,0,"Qiraji Warrior - In Combat - Cast 'Thunderclap'"),
(15387,0,3,0,2,0,100,1,0,25,0,0,0,11,8599,0,0,0,0,0,1,0,0,0,0,0,0,0,0,"Qiraji Warrior - Between 0-25% Health - Cast 'Enrage' (No Repeat)"),
(15387,0,4,0,83,0,100,0,8599,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,"Qiraji Warrior - On Spell Cast 'Enrage' - Say Line 0");
@@ -17,7 +17,6 @@
#include "ScriptMgr.h"
#include "InstanceScript.h"
#include "ObjectAccessor.h"
#include "ruins_of_ahnqiraj.h"
#include "ScriptedCreature.h"
#include "SpellInfo.h"
@@ -230,7 +229,7 @@ struct npc_buru_egg : public ScriptedAI
void JustEngagedWith(Unit* who) override
{
if (Creature* buru = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_BURU)))
if (Creature* buru = _instance->GetCreature(DATA_BURU))
if (!buru->IsInCombat())
buru->AI()->AttackStart(who);
}
@@ -22,7 +22,6 @@
#include "ScriptMgr.h"
#include "Containers.h"
#include "InstanceScript.h"
#include "ObjectAccessor.h"
#include "ruins_of_ahnqiraj.h"
#include "ScriptedCreature.h"
#include "SpellInfo.h"
@@ -93,13 +92,6 @@ struct boss_kurinnaxx : public BossAI
Talk(EMOTE_FRENZY);
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
if (Creature* ossirian = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_OSSIRIAN)))
ossirian->AI()->Talk(SAY_KURINAXX_DEATH);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
@@ -35,7 +35,8 @@ enum Texts
SAY_INTRO = 1,
SAY_AGGRO = 2,
SAY_SLAY = 3,
SAY_DEATH = 4
SAY_DEATH = 4,
SAY_KURINAXX_DEATH = 5
};
enum Spells
@@ -67,6 +68,12 @@ enum Events
EVENT_STOMP = 3
};
enum OssirianMisc
{
NPC_SAND_VORTEX = 15428,
NPC_OSSIRIAN_TRIGGER = 15590
};
uint8 const NUM_CRYSTALS = 12;
Position CrystalCoordinates[NUM_CRYSTALS] =
@@ -145,6 +152,9 @@ class boss_ossirian : public CreatureScript
if (Creature* Trigger = ObjectAccessor::GetCreature(*me, TriggerGUID))
if (!Trigger->HasUnitState(UNIT_STATE_CASTING))
Trigger->CastSpell(Trigger, SpellWeakness[urand(0, 4)], false);
if (action == ACTION_KURINNAXX_DEFEATED && me->IsAlive())
Talk(SAY_KURINAXX_DEATH);
}
void JustEngagedWith(Unit* who) override
@@ -89,6 +89,37 @@ struct boss_rajaxx : public BossAI
Talk(EMOTE_FRENZY);
}
void DoAction(int32 action) override
{
if (!me->IsAlive())
return;
switch (action)
{
case ACTION_WAVE_STARTS_3:
Talk(SAY_WAVE_3);
break;
case ACTION_WAVE_STARTS_4:
Talk(SAY_WAVE_4);
break;
case ACTION_WAVE_STARTS_5:
Talk(SAY_WAVE_5);
break;
case ACTION_WAVE_STARTS_6:
Talk(SAY_WAVE_6);
break;
case ACTION_WAVE_STARTS_7:
Talk(SAY_WAVE_7);
break;
case ACTION_RAJAXX_ENTER:
Talk(SAY_INTRO);
DoZoneInCombat();
break;
default:
break;
}
}
void KilledUnit(Unit* /*victim*/) override
{
Talk(SAY_SLAY);
@@ -17,10 +17,24 @@
#include "ScriptMgr.h"
#include "Creature.h"
#include "CreatureAI.h"
#include "InstanceScript.h"
#include "Map.h"
#include "ruins_of_ahnqiraj.h"
#include <algorithm>
DungeonEncounterData const encounters[] =
static constexpr ObjectData creatureData[] =
{
{ NPC_KURINAXX, DATA_KURINNAXX },
{ NPC_RAJAXX, DATA_RAJAXX },
{ NPC_MOAM, DATA_MOAM },
{ NPC_BURU, DATA_BURU },
{ NPC_AYAMISS, DATA_AYAMISS },
{ NPC_OSSIRIAN, DATA_OSSIRIAN },
{ NPC_ANDOROV, DATA_ANDOROV }
};
static constexpr DungeonEncounterData encounters[] =
{
{ DATA_KURINNAXX, {{ 718 }} },
{ DATA_RAJAXX, {{ 719 }} },
@@ -30,6 +44,23 @@ DungeonEncounterData const encounters[] =
{ DATA_OSSIRIAN, {{ 723 }} }
};
struct RajaxxWave
{
std::string_view StringId;
int32 BossActionIdOnClear;
};
static constexpr std::array<RajaxxWave, 7> RajaxxWaves =
{{
{ "GeneralRajaxxWave1", 0 },
{ "GeneralRajaxxWave2", ACTION_WAVE_STARTS_3 },
{ "GeneralRajaxxWave3", ACTION_WAVE_STARTS_4 },
{ "GeneralRajaxxWave4", ACTION_WAVE_STARTS_5 },
{ "GeneralRajaxxWave5", ACTION_WAVE_STARTS_6 },
{ "GeneralRajaxxWave6", ACTION_WAVE_STARTS_7 },
{ "GeneralRajaxxWave7", ACTION_RAJAXX_ENTER }
}};
class instance_ruins_of_ahnqiraj : public InstanceMapScript
{
public:
@@ -40,32 +71,46 @@ class instance_ruins_of_ahnqiraj : public InstanceMapScript
instance_ruins_of_ahnqiraj_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
{
SetHeaders(DataHeader);
SetBossNumber(NUM_ENCOUNTER);
SetBossNumber(EncounterCount);
LoadObjectData(creatureData, {});
AndorovEventState = NOT_STARTED;
LoadDungeonEncounterData(encounters);
}
void OnCreatureCreate(Creature* creature) override
{
switch (creature->GetEntry())
InstanceScript::OnCreatureCreate(creature);
auto rajaxxWave = std::ranges::find_if(RajaxxWaves, [creature](std::string_view stringId) { return creature->HasStringId(stringId); }, &RajaxxWave::StringId);
if (rajaxxWave != RajaxxWaves.end())
WaveGuidList[std::ranges::distance(RajaxxWaves.begin(), rajaxxWave)].insert(creature->GetGUID());
}
void OnUnitDeath(Unit* unit) override
{
InstanceScript::OnUnitDeath(unit);
if (unit->GetTypeId() != TYPEID_UNIT)
return;
auto rajaxxWave = std::ranges::find_if(RajaxxWaves, [creature = unit->ToCreature()](std::string_view stringId) { return creature->HasStringId(stringId); }, &RajaxxWave::StringId);
if (rajaxxWave != RajaxxWaves.end())
{
case NPC_KURINAXX:
_kurinaxxGUID = creature->GetGUID();
break;
case NPC_RAJAXX:
_rajaxxGUID = creature->GetGUID();
break;
case NPC_MOAM:
_moamGUID = creature->GetGUID();
break;
case NPC_BURU:
_buruGUID = creature->GetGUID();
break;
case NPC_AYAMISS:
_ayamissGUID = creature->GetGUID();
break;
case NPC_OSSIRIAN:
_ossirianGUID = creature->GetGUID();
break;
std::ptrdiff_t waveIndex = std::ranges::distance(RajaxxWaves.begin(), rajaxxWave);
if (WaveGuidList[waveIndex].erase(unit->GetGUID()) && WaveGuidList[waveIndex].empty())
{
// start next wave
if (waveIndex + 1 < std::ranges::ssize(WaveGuidList))
for (ObjectGuid guid : WaveGuidList[waveIndex + 1])
if (Creature* creature = instance->GetCreature(guid))
if (creature->IsAlive() && !creature->IsInCombat())
creature->AI()->DoZoneInCombat();
if (rajaxxWave->BossActionIdOnClear)
if (Creature* rajaxx = GetCreature(DATA_RAJAXX))
rajaxx->AI()->DoAction(rajaxxWave->BossActionIdOnClear);
}
}
}
@@ -74,46 +119,79 @@ class instance_ruins_of_ahnqiraj : public InstanceMapScript
if (!InstanceScript::SetBossState(bossId, state))
return false;
switch (bossId)
{
case DATA_KURINNAXX:
if (state == DONE)
{
instance->SpawnGroupSpawn(SPAWN_GROUP_ANDOROV);
if (Creature* ossirian = GetCreature(DATA_OSSIRIAN))
ossirian->AI()->DoAction(ACTION_KURINNAXX_DEFEATED);
}
break;
case DATA_RAJAXX:
if (state == DONE)
{
/// @todo: This part requires additional research. Here we check if Andorov's event was started
/// and only then change it to finished to enable vendor. Otherwise players can complete
/// Rajaxx's encounter without Andorov and then talk to him to buy items, doubt that should happen
if (GetData(DATA_ANDOROV_EVENT_STATE) == IN_PROGRESS)
{
SetData(DATA_ANDOROV_EVENT_STATE, DONE);
if (Creature* andorov = GetCreature(DATA_ANDOROV))
andorov->AI()->DoAction(ACTION_RAJAXX_DEFEATED);
}
}
break;
}
return true;
}
void SetData(uint32 type, uint32 data) override
{
if (type == DATA_ANDOROV_EVENT_STATE)
{
AndorovEventState = data;
if (data == IN_PROGRESS)
{
// Wave 1
for (ObjectGuid guid : WaveGuidList[0])
if (Creature* creature = instance->GetCreature(guid))
if (creature->IsAlive() && !creature->IsInCombat())
creature->AI()->DoZoneInCombat();
}
}
}
uint32 GetData(uint32 type) const override
{
if (type == DATA_ANDOROV_EVENT_STATE)
return AndorovEventState;
return 0;
}
void SetGuidData(uint32 type, ObjectGuid data) override
{
if (type == DATA_PARALYZED)
_paralyzedGUID = data;
ParalyzedGUID = data;
}
ObjectGuid GetGuidData(uint32 type) const override
{
switch (type)
{
case DATA_KURINNAXX:
return _kurinaxxGUID;
case DATA_RAJAXX:
return _rajaxxGUID;
case DATA_MOAM:
return _moamGUID;
case DATA_BURU:
return _buruGUID;
case DATA_AYAMISS:
return _ayamissGUID;
case DATA_OSSIRIAN:
return _ossirianGUID;
case DATA_PARALYZED:
return _paralyzedGUID;
}
if (type == DATA_PARALYZED)
return ParalyzedGUID;
return ObjectGuid::Empty;
}
private:
ObjectGuid _kurinaxxGUID;
ObjectGuid _rajaxxGUID;
ObjectGuid _moamGUID;
ObjectGuid _buruGUID;
ObjectGuid _ayamissGUID;
ObjectGuid _ossirianGUID;
ObjectGuid _paralyzedGUID;
protected:
uint8 AndorovEventState;
GuidSet WaveGuidList[7];
ObjectGuid ParalyzedGUID;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
@@ -16,9 +16,248 @@
*/
#include "ScriptMgr.h"
#include "InstanceScript.h"
#include "MotionMaster.h"
#include "Player.h"
#include "ruins_of_ahnqiraj.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
#include "SpellAuras.h"
#include "SpellScript.h"
#include "Unit.h"
/*
* Some quick facts about the event:
*
* Event can be completed with or without Andorov, waves will be engaged one after one
* Looks like waves aren't linked in some order, for example engaging and killing all waves at once will engage Rajaxx
without any issues. Engaging and killing several waves at once will engage next wave. It is unclear what happens if
random waves are engaged and killed, probably linked to them waves will be engaged. As well it is unclear what happens
if waves are engaged and killed in reverse order
* There is a bug on retail when all waves respawn. It is unclear how exactly waves should respawn, NYI
* According to patch notes, Andorov should respawn after 15 min if killed, NYI
* It is unclear if next wave should be started after specific amount of time even if previous is not yet defeated
* Entire event requires additional research since some things may be missing or implemented wrongly
*/
enum AndorovTexts
{
SAY_PROGRESS_1 = 0,
SAY_PROGRESS_2 = 1,
SAY_PROGRESS_3 = 2,
SAY_PROGRESS_4 = 3,
SAY_PROGRESS_5 = 4,
SAY_PROGRESS_6 = 5
};
enum AndorovSpells
{
SPELL_STRIKE = 22591,
SPELL_BASH = 25515,
SPELL_AURA_OF_COMMAND = 25516
};
enum AndorovEvents
{
EVENT_INTRO_1 = 1,
EVENT_PROGRESS_1,
EVENT_PROGRESS_2,
EVENT_PROGRESS_3,
EVENT_PROGRESS_4,
EVENT_PROGRESS_5,
EVENT_PROGRESS_6,
EVENT_OUTRO_1,
EVENT_OUTRO_2,
EVENT_STRIKE,
EVENT_BASH,
EVENT_AURA_OF_COMMAND
};
enum AndorovMisc
{
PATH_SPAWN = 4,
PATH_EVENT = 5,
GOSSIP_MENU_NOT_STARTED = 6629,
GOSSIP_MENU_IN_PROGRESS = 7048,
GOSSIP_MENU_FINISHED = 7047,
NPC_KALDOREI_ELITE = 15473
};
// 15471 - Lieutenant General Andorov
struct npc_andorov : public ScriptedAI
{
npc_andorov(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
void JustAppeared() override
{
_events.ScheduleEvent(EVENT_INTRO_1, 0s);
}
void Reset() override
{
_combatEvents.Reset();
}
void JustEngagedWith(Unit* /*who*/) override
{
_combatEvents.ScheduleEvent(EVENT_STRIKE, 10s, 15s);
_combatEvents.ScheduleEvent(EVENT_BASH, 15s, 25s);
_combatEvents.ScheduleEvent(EVENT_AURA_OF_COMMAND, 10s, 20s);
}
void WaypointPathEnded(uint32 /*waypointId*/, uint32 pathId) override
{
if (pathId == PATH_EVENT)
_events.ScheduleEvent(EVENT_PROGRESS_3, 0s);
}
void DoAction(int32 action) override
{
/// @todo: This part is guessed, nothing is changed when Rajaxx is defeated
/// but we want to enable vendor, perform emote and despawn. Maybe it is delayed a little?
if (action == ACTION_RAJAXX_DEFEATED && me->IsAlive())
_events.ScheduleEvent(EVENT_OUTRO_1, 0s);
}
void UpdateAI(uint32 diff) override
{
if (!me->IsInCombat())
{
_events.Update(diff);
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_INTRO_1:
me->SetGossipMenuId(GOSSIP_MENU_NOT_STARTED);
me->SetVendor(UNIT_NPC_FLAG_VENDOR, false);
me->GetMotionMaster()->MovePath(PATH_SPAWN, false);
break;
case EVENT_PROGRESS_1:
{
me->SetGossipMenuId(GOSSIP_MENU_IN_PROGRESS);
_instance->SetData(DATA_ANDOROV_EVENT_STATE, SPECIAL);
Talk(SAY_PROGRESS_1);
std::vector<Creature*> elites;
GetCreatureListWithEntryInGrid(elites, me, NPC_KALDOREI_ELITE, 50.0f);
for (Creature* elite : elites)
elite->SetImmuneToNPC(false);
me->SetImmuneToNPC(false);
_events.ScheduleEvent(EVENT_PROGRESS_2, 3s);
break;
}
case EVENT_PROGRESS_2:
Talk(SAY_PROGRESS_2);
me->GetMotionMaster()->MovePath(PATH_EVENT, false);
break;
case EVENT_PROGRESS_3:
Talk(SAY_PROGRESS_3);
_events.ScheduleEvent(EVENT_PROGRESS_4, 4s);
break;
case EVENT_PROGRESS_4:
Talk(SAY_PROGRESS_4);
_events.ScheduleEvent(EVENT_PROGRESS_5, 6s);
break;
case EVENT_PROGRESS_5:
Talk(SAY_PROGRESS_5);
_events.ScheduleEvent(EVENT_PROGRESS_6, 1s);
break;
case EVENT_PROGRESS_6:
{
_instance->SetData(DATA_ANDOROV_EVENT_STATE, IN_PROGRESS);
std::vector<Creature*> elites;
GetCreatureListWithEntryInGrid(elites, me, NPC_KALDOREI_ELITE, 50.0f);
for (Creature* elite : elites)
elite->SetEmoteState(EMOTE_STATE_READY1H);
me->SetEmoteState(EMOTE_STATE_READY1H);
break;
}
case EVENT_OUTRO_1:
me->SetGossipMenuId(GOSSIP_MENU_FINISHED);
me->SetVendor(UNIT_NPC_FLAG_VENDOR, true);
_events.ScheduleEvent(EVENT_OUTRO_2, 2min);
break;
case EVENT_OUTRO_2:
{
Talk(SAY_PROGRESS_6);
std::vector<Creature*> elites;
GetCreatureListWithEntryInGrid(elites, me, NPC_KALDOREI_ELITE, 50.0f);
for (Creature* elite : elites)
elite->DespawnOrUnsummon();
me->DespawnOrUnsummon();
break;
}
default:
break;
}
}
}
if (!UpdateVictim())
return;
_combatEvents.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = _combatEvents.ExecuteEvent())
{
switch (eventId)
{
case EVENT_STRIKE:
DoCastVictim(SPELL_STRIKE);
_combatEvents.Repeat(10s, 15s);
break;
case EVENT_BASH:
DoCastVictim(SPELL_BASH);
_combatEvents.Repeat(20s, 25s);
break;
case EVENT_AURA_OF_COMMAND:
DoCastSelf(SPELL_AURA_OF_COMMAND);
_combatEvents.Repeat(30s, 50s);
break;
default:
break;
}
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
}
bool OnGossipSelect(Player* player, uint32 menuId, uint32 /*gossipListId*/) override
{
if (menuId == GOSSIP_MENU_NOT_STARTED)
{
/// @todo: This part requires additional research.
/// What should happen if event wasn't started but Rajaxx was defeated?
if (_instance->GetBossState(DATA_RAJAXX) != DONE)
{
CloseGossipMenuFor(player);
_events.ScheduleEvent(EVENT_PROGRESS_1, 0s);
}
}
return false;
}
private:
EventMap _events;
EventMap _combatEvents;
InstanceScript* _instance;
};
enum AQ20Itch
{
@@ -50,5 +289,6 @@ class spell_ruins_of_ahnqiraj_itch : public AuraScript
void AddSC_ruins_of_ahnqiraj()
{
RegisterAQ20CreatureAI(npc_andorov);
RegisterSpellScript(spell_ruins_of_ahnqiraj_itch);
}
@@ -23,17 +23,20 @@
#define AQ20ScriptName "instance_ruins_of_ahnqiraj"
#define DataHeader "AQR"
uint32 constexpr EncounterCount = 6;
enum AQRDataTypes
{
DATA_KURINNAXX = 0,
DATA_RAJAXX = 1,
DATA_MOAM = 2,
DATA_BURU = 3,
DATA_AYAMISS = 4,
DATA_OSSIRIAN = 5,
NUM_ENCOUNTER = 6,
DATA_KURINNAXX = 0,
DATA_RAJAXX = 1,
DATA_MOAM = 2,
DATA_BURU = 3,
DATA_AYAMISS = 4,
DATA_OSSIRIAN = 5,
DATA_PARALYZED = 7
DATA_ANDOROV_EVENT_STATE,
DATA_ANDOROV,
DATA_PARALYZED
};
enum AQRCreatures
@@ -44,15 +47,8 @@ enum AQRCreatures
NPC_BURU = 15370,
NPC_AYAMISS = 15369,
NPC_OSSIRIAN = 15339,
NPC_HIVEZARA_HORNET = 15934,
NPC_HIVEZARA_SWARMER = 15546,
NPC_HIVEZARA_LARVA = 15555,
NPC_SAND_VORTEX = 15428,
NPC_OSSIRIAN_TRIGGER = 15590,
NPC_HATCHLING = 15521,
NPC_LARVA = 15555,
NPC_SWARMER = 15546,
NPC_HORNET = 15934
NPC_ANDOROV = 15471
};
enum AQRGameObjectIds
@@ -60,6 +56,23 @@ enum AQRGameObjectIds
GO_OSSIRIAN_CRYSTAL = 180619
};
enum AQRSpawnGroups
{
SPAWN_GROUP_ANDOROV = 333
};
enum AQRActionIds
{
ACTION_WAVE_STARTS_3 = 0,
ACTION_WAVE_STARTS_4 = 1,
ACTION_WAVE_STARTS_5 = 2,
ACTION_WAVE_STARTS_6 = 3,
ACTION_WAVE_STARTS_7 = 4,
ACTION_RAJAXX_ENTER = 5,
ACTION_KURINNAXX_DEFEATED = 6,
ACTION_RAJAXX_DEFEATED = 7
};
template <class AI, class T>
inline AI* GetAQ20AI(T* obj)
{