mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 15:40:45 +01:00
Scripts/Serpentshrine Cavern: Move to BossAI
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -80,327 +80,304 @@ enum HydrossTheUnstable
|
||||
#define SPAWN_X_DIFF4 12.577011f
|
||||
#define SPAWN_Y_DIFF4 4.72702f
|
||||
|
||||
class boss_hydross_the_unstable : public CreatureScript
|
||||
struct boss_hydross_the_unstable : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_hydross_the_unstable() : CreatureScript("boss_hydross_the_unstable") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
boss_hydross_the_unstable(Creature* creature) : BossAI(creature, BOSS_HYDROSS_THE_UNSTABLE)
|
||||
{
|
||||
return GetSerpentshrineCavernAI<boss_hydross_the_unstableAI>(creature);
|
||||
Initialize();
|
||||
}
|
||||
|
||||
struct boss_hydross_the_unstableAI : public ScriptedAI
|
||||
void Initialize()
|
||||
{
|
||||
boss_hydross_the_unstableAI(Creature* creature) : ScriptedAI(creature), Summons(me)
|
||||
beams[0].Clear();
|
||||
beams[1].Clear();
|
||||
PosCheck_Timer = 2500;
|
||||
MarkOfHydross_Timer = 15000;
|
||||
MarkOfCorruption_Timer = 15000;
|
||||
WaterTomb_Timer = 7000;
|
||||
VileSludge_Timer = 7000;
|
||||
MarkOfHydross_Count = 0;
|
||||
MarkOfCorruption_Count = 0;
|
||||
EnrageTimer = 600000;
|
||||
|
||||
CorruptedForm = false;
|
||||
beam = false;
|
||||
}
|
||||
|
||||
ObjectGuid beams[2];
|
||||
uint32 PosCheck_Timer;
|
||||
uint32 MarkOfHydross_Timer;
|
||||
uint32 MarkOfCorruption_Timer;
|
||||
uint32 WaterTomb_Timer;
|
||||
uint32 VileSludge_Timer;
|
||||
uint32 MarkOfHydross_Count;
|
||||
uint32 MarkOfCorruption_Count;
|
||||
uint32 EnrageTimer;
|
||||
bool CorruptedForm;
|
||||
bool beam;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
DeSummonBeams();
|
||||
Initialize();
|
||||
|
||||
me->SetMeleeDamageSchool(SPELL_SCHOOL_FROST);
|
||||
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true);
|
||||
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false);
|
||||
|
||||
me->SetDisplayId(MODEL_CLEAN);
|
||||
|
||||
_Reset();
|
||||
}
|
||||
|
||||
void SummonBeams()
|
||||
{
|
||||
Creature* beamer = me->SummonCreature(ENTRY_BEAM_DUMMY, -258.333f, -356.34f, 22.0499f, 5.90835f, TEMPSUMMON_CORPSE_DESPAWN);
|
||||
if (beamer)
|
||||
{
|
||||
Initialize();
|
||||
instance = creature->GetInstanceScript();
|
||||
beamer->CastSpell(me, SPELL_BLUE_BEAM, true);
|
||||
beamer->SetDisplayId(11686); //invisible
|
||||
beams[0] = beamer->GetGUID();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
beamer = me->SummonCreature(ENTRY_BEAM_DUMMY, -219.918f, -371.308f, 22.0042f, 2.73072f, TEMPSUMMON_CORPSE_DESPAWN);
|
||||
if (beamer)
|
||||
{
|
||||
beams[0].Clear();
|
||||
beams[1].Clear();
|
||||
PosCheck_Timer = 2500;
|
||||
MarkOfHydross_Timer = 15000;
|
||||
MarkOfCorruption_Timer = 15000;
|
||||
WaterTomb_Timer = 7000;
|
||||
VileSludge_Timer = 7000;
|
||||
MarkOfHydross_Count = 0;
|
||||
MarkOfCorruption_Count = 0;
|
||||
EnrageTimer = 600000;
|
||||
|
||||
CorruptedForm = false;
|
||||
beam = false;
|
||||
beamer->CastSpell(me, SPELL_BLUE_BEAM, true);
|
||||
beamer->SetDisplayId(11686); //invisible
|
||||
beams[1] = beamer->GetGUID();
|
||||
}
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
ObjectGuid beams[2];
|
||||
uint32 PosCheck_Timer;
|
||||
uint32 MarkOfHydross_Timer;
|
||||
uint32 MarkOfCorruption_Timer;
|
||||
uint32 WaterTomb_Timer;
|
||||
uint32 VileSludge_Timer;
|
||||
uint32 MarkOfHydross_Count;
|
||||
uint32 MarkOfCorruption_Count;
|
||||
uint32 EnrageTimer;
|
||||
bool CorruptedForm;
|
||||
bool beam;
|
||||
SummonList Summons;
|
||||
|
||||
void Reset() override
|
||||
void DeSummonBeams()
|
||||
{
|
||||
for (uint8 i = 0; i < 2; ++i)
|
||||
{
|
||||
DeSummonBeams();
|
||||
Initialize();
|
||||
|
||||
me->SetMeleeDamageSchool(SPELL_SCHOOL_FROST);
|
||||
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true);
|
||||
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false);
|
||||
|
||||
me->SetDisplayId(MODEL_CLEAN);
|
||||
|
||||
instance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, NOT_STARTED);
|
||||
Summons.DespawnAll();
|
||||
if (Creature* mob = ObjectAccessor::GetCreature(*me, beams[i]))
|
||||
mob->DespawnOrUnsummon();
|
||||
}
|
||||
}
|
||||
|
||||
void SummonBeams()
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
_JustEngagedWith(who);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
Talk(CorruptedForm ? SAY_CORRUPT_SLAY : SAY_CLEAN_SLAY);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summoned) override
|
||||
{
|
||||
if (summoned->GetEntry() == ENTRY_PURE_SPAWN)
|
||||
summoned->CastSpell(summoned, SPELL_ELEMENTAL_SPAWNIN, true);
|
||||
|
||||
if (summoned->GetEntry() == ENTRY_TAINTED_SPAWN)
|
||||
summoned->CastSpell(summoned, SPELL_ELEMENTAL_SPAWNIN, true);
|
||||
|
||||
BossAI::JustSummoned(summoned);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(CorruptedForm ? SAY_CORRUPT_DEATH : SAY_CLEAN_DEATH);
|
||||
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!beam)
|
||||
{
|
||||
Creature* beamer = me->SummonCreature(ENTRY_BEAM_DUMMY, -258.333f, -356.34f, 22.0499f, 5.90835f, TEMPSUMMON_CORPSE_DESPAWN);
|
||||
if (beamer)
|
||||
SummonBeams();
|
||||
beam = true;
|
||||
}
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
// corrupted form
|
||||
if (CorruptedForm)
|
||||
{
|
||||
//MarkOfCorruption_Timer
|
||||
if (MarkOfCorruption_Timer <= diff)
|
||||
{
|
||||
beamer->CastSpell(me, SPELL_BLUE_BEAM, true);
|
||||
beamer->SetDisplayId(11686); //invisible
|
||||
beams[0] = beamer->GetGUID();
|
||||
}
|
||||
beamer = me->SummonCreature(ENTRY_BEAM_DUMMY, -219.918f, -371.308f, 22.0042f, 2.73072f, TEMPSUMMON_CORPSE_DESPAWN);
|
||||
if (beamer)
|
||||
{
|
||||
beamer->CastSpell(me, SPELL_BLUE_BEAM, true);
|
||||
beamer->SetDisplayId(11686); //invisible
|
||||
beams[1] = beamer->GetGUID();
|
||||
}
|
||||
}
|
||||
void DeSummonBeams()
|
||||
{
|
||||
for (uint8 i = 0; i < 2; ++i)
|
||||
{
|
||||
if (Creature* mob = ObjectAccessor::GetCreature(*me, beams[i]))
|
||||
mob->DespawnOrUnsummon();
|
||||
}
|
||||
}
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
instance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, IN_PROGRESS);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
Talk(CorruptedForm ? SAY_CORRUPT_SLAY : SAY_CLEAN_SLAY);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summoned) override
|
||||
{
|
||||
if (summoned->GetEntry() == ENTRY_PURE_SPAWN)
|
||||
{
|
||||
summoned->CastSpell(summoned, SPELL_ELEMENTAL_SPAWNIN, true);
|
||||
Summons.Summon(summoned);
|
||||
}
|
||||
if (summoned->GetEntry() == ENTRY_TAINTED_SPAWN)
|
||||
{
|
||||
summoned->CastSpell(summoned, SPELL_ELEMENTAL_SPAWNIN, true);
|
||||
Summons.Summon(summoned);
|
||||
}
|
||||
}
|
||||
|
||||
void SummonedCreatureDespawn(Creature* summon) override
|
||||
{
|
||||
Summons.Despawn(summon);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(CorruptedForm ? SAY_CORRUPT_DEATH : SAY_CLEAN_DEATH);
|
||||
|
||||
instance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, DONE);
|
||||
Summons.DespawnAll();
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!beam)
|
||||
{
|
||||
SummonBeams();
|
||||
beam = true;
|
||||
}
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
// corrupted form
|
||||
if (CorruptedForm)
|
||||
{
|
||||
//MarkOfCorruption_Timer
|
||||
if (MarkOfCorruption_Timer <= diff)
|
||||
if (MarkOfCorruption_Count <= 5)
|
||||
{
|
||||
if (MarkOfCorruption_Count <= 5)
|
||||
uint32 mark_spell = 0;
|
||||
|
||||
switch (MarkOfCorruption_Count)
|
||||
{
|
||||
uint32 mark_spell = 0;
|
||||
case 0:
|
||||
mark_spell = SPELL_MARK_OF_CORRUPTION1;
|
||||
break;
|
||||
|
||||
switch (MarkOfCorruption_Count)
|
||||
{
|
||||
case 0:
|
||||
mark_spell = SPELL_MARK_OF_CORRUPTION1;
|
||||
break;
|
||||
case 1:
|
||||
mark_spell = SPELL_MARK_OF_CORRUPTION2;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
mark_spell = SPELL_MARK_OF_CORRUPTION2;
|
||||
break;
|
||||
case 2:
|
||||
mark_spell = SPELL_MARK_OF_CORRUPTION3;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
mark_spell = SPELL_MARK_OF_CORRUPTION3;
|
||||
break;
|
||||
case 3:
|
||||
mark_spell = SPELL_MARK_OF_CORRUPTION4;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
mark_spell = SPELL_MARK_OF_CORRUPTION4;
|
||||
break;
|
||||
case 4:
|
||||
mark_spell = SPELL_MARK_OF_CORRUPTION5;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
mark_spell = SPELL_MARK_OF_CORRUPTION5;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
mark_spell = SPELL_MARK_OF_CORRUPTION6;
|
||||
break;
|
||||
}
|
||||
|
||||
DoCastVictim(mark_spell);
|
||||
|
||||
if (MarkOfCorruption_Count < 5)
|
||||
++MarkOfCorruption_Count;
|
||||
case 5:
|
||||
mark_spell = SPELL_MARK_OF_CORRUPTION6;
|
||||
break;
|
||||
}
|
||||
|
||||
MarkOfCorruption_Timer = 15000;
|
||||
} else MarkOfCorruption_Timer -= diff;
|
||||
DoCastVictim(mark_spell);
|
||||
|
||||
//VileSludge_Timer
|
||||
if (VileSludge_Timer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
DoCast(target, SPELL_VILE_SLUDGE);
|
||||
if (MarkOfCorruption_Count < 5)
|
||||
++MarkOfCorruption_Count;
|
||||
}
|
||||
|
||||
VileSludge_Timer = 15000;
|
||||
} else VileSludge_Timer -= diff;
|
||||
MarkOfCorruption_Timer = 15000;
|
||||
} else MarkOfCorruption_Timer -= diff;
|
||||
|
||||
//PosCheck_Timer
|
||||
if (PosCheck_Timer <= diff)
|
||||
{
|
||||
if (me->IsWithinDist2d(HYDROSS_X, HYDROSS_Y, SWITCH_RADIUS))
|
||||
{
|
||||
// switch to clean form
|
||||
me->SetDisplayId(MODEL_CLEAN);
|
||||
CorruptedForm = false;
|
||||
MarkOfHydross_Count = 0;
|
||||
|
||||
Talk(SAY_SWITCH_TO_CLEAN);
|
||||
ResetThreatList();
|
||||
SummonBeams();
|
||||
|
||||
// spawn 4 adds
|
||||
DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s);
|
||||
DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s);
|
||||
DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s);
|
||||
DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s);
|
||||
|
||||
me->SetMeleeDamageSchool(SPELL_SCHOOL_FROST);
|
||||
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true);
|
||||
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false);
|
||||
}
|
||||
|
||||
PosCheck_Timer = 2500;
|
||||
} else PosCheck_Timer -=diff;
|
||||
}
|
||||
// clean form
|
||||
else
|
||||
//VileSludge_Timer
|
||||
if (VileSludge_Timer <= diff)
|
||||
{
|
||||
//MarkOfHydross_Timer
|
||||
if (MarkOfHydross_Timer <= diff)
|
||||
{
|
||||
if (MarkOfHydross_Count <= 5)
|
||||
{
|
||||
uint32 mark_spell = 0;
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
DoCast(target, SPELL_VILE_SLUDGE);
|
||||
|
||||
switch (MarkOfHydross_Count)
|
||||
{
|
||||
case 0:
|
||||
mark_spell = SPELL_MARK_OF_HYDROSS1;
|
||||
break;
|
||||
VileSludge_Timer = 15000;
|
||||
} else VileSludge_Timer -= diff;
|
||||
|
||||
case 1:
|
||||
mark_spell = SPELL_MARK_OF_HYDROSS2;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
mark_spell = SPELL_MARK_OF_HYDROSS3;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
mark_spell = SPELL_MARK_OF_HYDROSS4;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
mark_spell = SPELL_MARK_OF_HYDROSS5;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
mark_spell = SPELL_MARK_OF_HYDROSS6;
|
||||
break;
|
||||
}
|
||||
|
||||
DoCastVictim(mark_spell);
|
||||
|
||||
if (MarkOfHydross_Count < 5)
|
||||
++MarkOfHydross_Count;
|
||||
}
|
||||
|
||||
MarkOfHydross_Timer = 15000;
|
||||
} else MarkOfHydross_Timer -= diff;
|
||||
|
||||
//WaterTomb_Timer
|
||||
if (WaterTomb_Timer <= diff)
|
||||
{
|
||||
Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true);
|
||||
if (target)
|
||||
DoCast(target, SPELL_WATER_TOMB);
|
||||
|
||||
WaterTomb_Timer = 7000;
|
||||
} else WaterTomb_Timer -= diff;
|
||||
|
||||
//PosCheck_Timer
|
||||
if (PosCheck_Timer <= diff)
|
||||
{
|
||||
if (!me->IsWithinDist2d(HYDROSS_X, HYDROSS_Y, SWITCH_RADIUS))
|
||||
{
|
||||
// switch to corrupted form
|
||||
me->SetDisplayId(MODEL_CORRUPT);
|
||||
MarkOfCorruption_Count = 0;
|
||||
CorruptedForm = true;
|
||||
|
||||
Talk(SAY_SWITCH_TO_CORRUPT);
|
||||
ResetThreatList();
|
||||
DeSummonBeams();
|
||||
|
||||
// spawn 4 adds
|
||||
DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s);
|
||||
DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s);
|
||||
DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s);
|
||||
DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s);
|
||||
|
||||
me->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE);
|
||||
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true);
|
||||
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false);
|
||||
}
|
||||
|
||||
PosCheck_Timer = 2500;
|
||||
} else PosCheck_Timer -=diff;
|
||||
}
|
||||
|
||||
//EnrageTimer
|
||||
if (EnrageTimer <= diff)
|
||||
//PosCheck_Timer
|
||||
if (PosCheck_Timer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_ENRAGE);
|
||||
EnrageTimer = 60000;
|
||||
} else EnrageTimer -= diff;
|
||||
if (me->IsWithinDist2d(HYDROSS_X, HYDROSS_Y, SWITCH_RADIUS))
|
||||
{
|
||||
// switch to clean form
|
||||
me->SetDisplayId(MODEL_CLEAN);
|
||||
CorruptedForm = false;
|
||||
MarkOfHydross_Count = 0;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
Talk(SAY_SWITCH_TO_CLEAN);
|
||||
ResetThreatList();
|
||||
SummonBeams();
|
||||
|
||||
// spawn 4 adds
|
||||
DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s);
|
||||
DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s);
|
||||
DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s);
|
||||
DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s);
|
||||
|
||||
me->SetMeleeDamageSchool(SPELL_SCHOOL_FROST);
|
||||
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true);
|
||||
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false);
|
||||
}
|
||||
|
||||
PosCheck_Timer = 2500;
|
||||
} else PosCheck_Timer -=diff;
|
||||
}
|
||||
};
|
||||
// clean form
|
||||
else
|
||||
{
|
||||
//MarkOfHydross_Timer
|
||||
if (MarkOfHydross_Timer <= diff)
|
||||
{
|
||||
if (MarkOfHydross_Count <= 5)
|
||||
{
|
||||
uint32 mark_spell = 0;
|
||||
|
||||
switch (MarkOfHydross_Count)
|
||||
{
|
||||
case 0:
|
||||
mark_spell = SPELL_MARK_OF_HYDROSS1;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
mark_spell = SPELL_MARK_OF_HYDROSS2;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
mark_spell = SPELL_MARK_OF_HYDROSS3;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
mark_spell = SPELL_MARK_OF_HYDROSS4;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
mark_spell = SPELL_MARK_OF_HYDROSS5;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
mark_spell = SPELL_MARK_OF_HYDROSS6;
|
||||
break;
|
||||
}
|
||||
|
||||
DoCastVictim(mark_spell);
|
||||
|
||||
if (MarkOfHydross_Count < 5)
|
||||
++MarkOfHydross_Count;
|
||||
}
|
||||
|
||||
MarkOfHydross_Timer = 15000;
|
||||
} else MarkOfHydross_Timer -= diff;
|
||||
|
||||
//WaterTomb_Timer
|
||||
if (WaterTomb_Timer <= diff)
|
||||
{
|
||||
Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true);
|
||||
if (target)
|
||||
DoCast(target, SPELL_WATER_TOMB);
|
||||
|
||||
WaterTomb_Timer = 7000;
|
||||
} else WaterTomb_Timer -= diff;
|
||||
|
||||
//PosCheck_Timer
|
||||
if (PosCheck_Timer <= diff)
|
||||
{
|
||||
if (!me->IsWithinDist2d(HYDROSS_X, HYDROSS_Y, SWITCH_RADIUS))
|
||||
{
|
||||
// switch to corrupted form
|
||||
me->SetDisplayId(MODEL_CORRUPT);
|
||||
MarkOfCorruption_Count = 0;
|
||||
CorruptedForm = true;
|
||||
|
||||
Talk(SAY_SWITCH_TO_CORRUPT);
|
||||
ResetThreatList();
|
||||
DeSummonBeams();
|
||||
|
||||
// spawn 4 adds
|
||||
DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s);
|
||||
DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s);
|
||||
DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s);
|
||||
DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s);
|
||||
|
||||
me->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE);
|
||||
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true);
|
||||
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false);
|
||||
}
|
||||
|
||||
PosCheck_Timer = 2500;
|
||||
} else PosCheck_Timer -=diff;
|
||||
}
|
||||
|
||||
//EnrageTimer
|
||||
if (EnrageTimer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_ENRAGE);
|
||||
EnrageTimer = 60000;
|
||||
} else EnrageTimer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_hydross_the_unstable()
|
||||
{
|
||||
new boss_hydross_the_unstable();
|
||||
RegisterSerpentshrineCavernCreatureAI(boss_hydross_the_unstable);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -80,409 +80,361 @@ float AddPos[9][3] =
|
||||
{42.471519f, -445.115295f, -19.769423f}
|
||||
};
|
||||
|
||||
class boss_the_lurker_below : public CreatureScript
|
||||
struct boss_the_lurker_below : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_the_lurker_below() : CreatureScript("boss_the_lurker_below") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
boss_the_lurker_below(Creature* creature) : BossAI(creature, BOSS_THE_LURKER_BELOW)
|
||||
{
|
||||
return GetSerpentshrineCavernAI<boss_the_lurker_belowAI>(creature);
|
||||
Initialize();
|
||||
SetCombatMovement(false);
|
||||
}
|
||||
|
||||
struct boss_the_lurker_belowAI : public ScriptedAI
|
||||
void Initialize()
|
||||
{
|
||||
boss_the_lurker_belowAI(Creature* creature) : ScriptedAI(creature), Summons(me)
|
||||
SpoutAnimTimer = 1000;
|
||||
RotTimer = 0;
|
||||
WaterboltTimer = 15000; // give time to get in range when fight starts
|
||||
SpoutTimer = 45000;
|
||||
WhirlTimer = 18000; // after avery spout
|
||||
PhaseTimer = 120000;
|
||||
GeyserTimer = rand32() % 5000 + 15000;
|
||||
CheckTimer = 15000; // give time to get in range when fight starts
|
||||
WaitTimer = 60000; // never reached
|
||||
WaitTimer2 = 60000; // never reached
|
||||
|
||||
Submerged = true; // will be false at combat start
|
||||
Spawned = false;
|
||||
InRange = false;
|
||||
CanStartEvent = false;
|
||||
}
|
||||
|
||||
bool Spawned;
|
||||
bool Submerged;
|
||||
bool InRange;
|
||||
bool CanStartEvent;
|
||||
uint32 RotTimer;
|
||||
uint32 SpoutAnimTimer;
|
||||
uint32 WaterboltTimer;
|
||||
uint32 SpoutTimer;
|
||||
uint32 WhirlTimer;
|
||||
uint32 PhaseTimer;
|
||||
uint32 GeyserTimer;
|
||||
uint32 CheckTimer;
|
||||
uint32 WaitTimer;
|
||||
uint32 WaitTimer2;
|
||||
|
||||
bool CheckCanStart()//check if players fished
|
||||
{
|
||||
if (instance->GetData(DATA_STRANGE_POOL) == NOT_STARTED)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
me->SetSwim(true);
|
||||
me->SetDisableGravity(true);
|
||||
Initialize();
|
||||
|
||||
_Reset();
|
||||
instance->SetData(DATA_STRANGE_POOL, NOT_STARTED);
|
||||
DoCast(me, SPELL_SUBMERGE); // submerge anim
|
||||
me->SetVisible(false); // we start invis under water, submerged
|
||||
me->SetUnitFlag(UNIT_FLAG_UNINTERACTIBLE);
|
||||
me->SetImmuneToPC(true);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
instance->SetData(DATA_STRANGE_POOL, IN_PROGRESS);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (!CanStartEvent) // boss is invisible, don't attack
|
||||
return;
|
||||
if (!me->GetVictim() && who->IsValidAttackTarget(me))
|
||||
{
|
||||
Initialize();
|
||||
SetCombatMovement(false);
|
||||
instance = creature->GetInstanceScript();
|
||||
float attackRadius = me->GetAttackDistance(who);
|
||||
if (me->IsWithinDistInMap(who, attackRadius))
|
||||
AttackStart(who);
|
||||
}
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
void MovementInform(uint32 type, uint32 /*id*/) override
|
||||
{
|
||||
if (type == ROTATE_MOTION_TYPE)
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!CanStartEvent) // boss is invisible, don't attack
|
||||
{
|
||||
SpoutAnimTimer = 1000;
|
||||
RotTimer = 0;
|
||||
WaterboltTimer = 15000; // give time to get in range when fight starts
|
||||
SpoutTimer = 45000;
|
||||
WhirlTimer = 18000; // after avery spout
|
||||
PhaseTimer = 120000;
|
||||
GeyserTimer = rand32() % 5000 + 15000;
|
||||
CheckTimer = 15000; // give time to get in range when fight starts
|
||||
WaitTimer = 60000; // never reached
|
||||
WaitTimer2 = 60000; // never reached
|
||||
|
||||
Submerged = true; // will be false at combat start
|
||||
Spawned = false;
|
||||
InRange = false;
|
||||
CanStartEvent = false;
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
SummonList Summons;
|
||||
|
||||
bool Spawned;
|
||||
bool Submerged;
|
||||
bool InRange;
|
||||
bool CanStartEvent;
|
||||
uint32 RotTimer;
|
||||
uint32 SpoutAnimTimer;
|
||||
uint32 WaterboltTimer;
|
||||
uint32 SpoutTimer;
|
||||
uint32 WhirlTimer;
|
||||
uint32 PhaseTimer;
|
||||
uint32 GeyserTimer;
|
||||
uint32 CheckTimer;
|
||||
uint32 WaitTimer;
|
||||
uint32 WaitTimer2;
|
||||
|
||||
bool CheckCanStart()//check if players fished
|
||||
{
|
||||
if (instance->GetData(DATA_STRANGE_POOL) == NOT_STARTED)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
me->SetSwim(true);
|
||||
me->SetDisableGravity(true);
|
||||
Initialize();
|
||||
|
||||
Summons.DespawnAll();
|
||||
|
||||
instance->SetData(DATA_THELURKERBELOWEVENT, NOT_STARTED);
|
||||
instance->SetData(DATA_STRANGE_POOL, NOT_STARTED);
|
||||
DoCast(me, SPELL_SUBMERGE); // submerge anim
|
||||
me->SetVisible(false); // we start invis under water, submerged
|
||||
me->SetUnitFlag(UNIT_FLAG_UNINTERACTIBLE);
|
||||
me->SetImmuneToPC(true);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
instance->SetData(DATA_THELURKERBELOWEVENT, DONE);
|
||||
instance->SetData(DATA_STRANGE_POOL, IN_PROGRESS);
|
||||
|
||||
Summons.DespawnAll();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
instance->SetData(DATA_THELURKERBELOWEVENT, IN_PROGRESS);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (!CanStartEvent) // boss is invisible, don't attack
|
||||
return;
|
||||
if (!me->GetVictim() && who->IsValidAttackTarget(me))
|
||||
if (CheckCanStart())
|
||||
{
|
||||
float attackRadius = me->GetAttackDistance(who);
|
||||
if (me->IsWithinDistInMap(who, attackRadius))
|
||||
AttackStart(who);
|
||||
}
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 /*id*/) override
|
||||
{
|
||||
if (type == ROTATE_MOTION_TYPE)
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!CanStartEvent) // boss is invisible, don't attack
|
||||
{
|
||||
if (CheckCanStart())
|
||||
if (Submerged)
|
||||
{
|
||||
if (Submerged)
|
||||
{
|
||||
me->SetVisible(true);
|
||||
Submerged = false;
|
||||
WaitTimer2 = 500;
|
||||
}
|
||||
else if (WaitTimer2 <= diff) // wait 500ms before emerge anim
|
||||
{
|
||||
me->RemoveAllAuras();
|
||||
me->SetEmoteState(EMOTE_ONESHOT_NONE);
|
||||
DoCast(me, SPELL_EMERGE, false);
|
||||
WaitTimer2 = 60000; // never reached
|
||||
WaitTimer = 3000;
|
||||
}
|
||||
else
|
||||
WaitTimer2 -= diff;
|
||||
|
||||
if (WaitTimer <= diff) // wait 3secs for emerge anim, then attack
|
||||
{
|
||||
WaitTimer = 3000;
|
||||
CanStartEvent = true; // fresh fished from pool
|
||||
me->SetImmuneToPC(false);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_UNINTERACTIBLE);
|
||||
}
|
||||
else
|
||||
WaitTimer -= diff;
|
||||
me->SetVisible(true);
|
||||
Submerged = false;
|
||||
WaitTimer2 = 500;
|
||||
}
|
||||
else if (WaitTimer2 <= diff) // wait 500ms before emerge anim
|
||||
{
|
||||
me->RemoveAllAuras();
|
||||
me->SetEmoteState(EMOTE_ONESHOT_NONE);
|
||||
DoCast(me, SPELL_EMERGE, false);
|
||||
WaitTimer2 = 60000; // never reached
|
||||
WaitTimer = 3000;
|
||||
}
|
||||
else
|
||||
WaitTimer2 -= diff;
|
||||
|
||||
if (WaitTimer <= diff) // wait 3secs for emerge anim, then attack
|
||||
{
|
||||
WaitTimer = 3000;
|
||||
CanStartEvent = true; // fresh fished from pool
|
||||
me->SetImmuneToPC(false);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_UNINTERACTIBLE);
|
||||
}
|
||||
else
|
||||
WaitTimer -= diff;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!me->IsThreatened()) // check if should evade
|
||||
{
|
||||
if (me->IsEngaged())
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
if (!Submerged)
|
||||
{
|
||||
if (PhaseTimer <= diff)
|
||||
{
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
DoCast(me, SPELL_SUBMERGE);
|
||||
PhaseTimer = 60000; // 60secs submerged
|
||||
Submerged = true;
|
||||
}
|
||||
else
|
||||
PhaseTimer -= diff;
|
||||
|
||||
if (SpoutTimer <= diff)
|
||||
{
|
||||
Talk(EMOTE_SPOUT);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->GetMotionMaster()->MoveRotate(0, 20000, urand(0, 1) ? ROTATE_DIRECTION_LEFT : ROTATE_DIRECTION_RIGHT);
|
||||
SpoutTimer = 45000;
|
||||
WhirlTimer = 20000; // whirl directly after spout
|
||||
RotTimer = 20000;
|
||||
return;
|
||||
}
|
||||
else
|
||||
SpoutTimer -= diff;
|
||||
|
||||
if (!me->IsThreatened()) // check if should evade
|
||||
// Whirl directly after a Spout and at random times
|
||||
if (WhirlTimer <= diff)
|
||||
{
|
||||
if (me->IsEngaged())
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
WhirlTimer = 18000;
|
||||
DoCast(me, SPELL_WHIRL);
|
||||
}
|
||||
if (!Submerged)
|
||||
else
|
||||
WhirlTimer -= diff;
|
||||
|
||||
if (CheckTimer <= diff) // check if there are players in melee range
|
||||
{
|
||||
if (PhaseTimer <= diff)
|
||||
InRange = false;
|
||||
Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers();
|
||||
if (!PlayerList.isEmpty())
|
||||
{
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
DoCast(me, SPELL_SUBMERGE);
|
||||
PhaseTimer = 60000; // 60secs submerged
|
||||
Submerged = true;
|
||||
}
|
||||
else
|
||||
PhaseTimer -= diff;
|
||||
|
||||
if (SpoutTimer <= diff)
|
||||
{
|
||||
Talk(EMOTE_SPOUT);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->GetMotionMaster()->MoveRotate(0, 20000, urand(0, 1) ? ROTATE_DIRECTION_LEFT : ROTATE_DIRECTION_RIGHT);
|
||||
SpoutTimer = 45000;
|
||||
WhirlTimer = 20000; // whirl directly after spout
|
||||
RotTimer = 20000;
|
||||
return;
|
||||
}
|
||||
else
|
||||
SpoutTimer -= diff;
|
||||
|
||||
// Whirl directly after a Spout and at random times
|
||||
if (WhirlTimer <= diff)
|
||||
{
|
||||
WhirlTimer = 18000;
|
||||
DoCast(me, SPELL_WHIRL);
|
||||
}
|
||||
else
|
||||
WhirlTimer -= diff;
|
||||
|
||||
if (CheckTimer <= diff) // check if there are players in melee range
|
||||
{
|
||||
InRange = false;
|
||||
Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers();
|
||||
if (!PlayerList.isEmpty())
|
||||
{
|
||||
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
|
||||
{
|
||||
if (me->IsWithinMeleeRange(i->GetSource()))
|
||||
InRange = true;
|
||||
}
|
||||
}
|
||||
CheckTimer = 2000;
|
||||
}
|
||||
else
|
||||
CheckTimer -= diff;
|
||||
|
||||
if (RotTimer)
|
||||
{
|
||||
Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers();
|
||||
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
|
||||
{
|
||||
if (i->GetSource() && i->GetSource()->IsAlive() && me->HasInArc(diff/20000.f*float(M_PI)*2.f, i->GetSource()) && me->IsWithinDist(i->GetSource(), SPOUT_DIST) && !i->GetSource()->IsInWater())
|
||||
DoCast(i->GetSource(), SPELL_SPOUT, true); // only knock back players in arc, in 100yards, not in water
|
||||
if (me->IsWithinMeleeRange(i->GetSource()))
|
||||
InRange = true;
|
||||
}
|
||||
}
|
||||
CheckTimer = 2000;
|
||||
}
|
||||
else
|
||||
CheckTimer -= diff;
|
||||
|
||||
if (SpoutAnimTimer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_SPOUT_ANIM, true);
|
||||
SpoutAnimTimer = 1000;
|
||||
} else SpoutAnimTimer -= diff;
|
||||
|
||||
if (RotTimer <= diff)
|
||||
{
|
||||
RotTimer = 0;
|
||||
}
|
||||
else
|
||||
RotTimer -= diff;
|
||||
return;
|
||||
if (RotTimer)
|
||||
{
|
||||
Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers();
|
||||
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
|
||||
{
|
||||
if (i->GetSource() && i->GetSource()->IsAlive() && me->HasInArc(diff/20000.f*float(M_PI)*2.f, i->GetSource()) && me->IsWithinDist(i->GetSource(), SPOUT_DIST) && !i->GetSource()->IsInWater())
|
||||
DoCast(i->GetSource(), SPELL_SPOUT, true); // only knock back players in arc, in 100yards, not in water
|
||||
}
|
||||
|
||||
if (GeyserTimer <= diff)
|
||||
if (SpoutAnimTimer <= diff)
|
||||
{
|
||||
Unit* target = SelectTarget(SelectTargetMethod::Random, 1);
|
||||
DoCast(me, SPELL_SPOUT_ANIM, true);
|
||||
SpoutAnimTimer = 1000;
|
||||
} else SpoutAnimTimer -= diff;
|
||||
|
||||
if (RotTimer <= diff)
|
||||
{
|
||||
RotTimer = 0;
|
||||
}
|
||||
else
|
||||
RotTimer -= diff;
|
||||
return;
|
||||
}
|
||||
|
||||
if (GeyserTimer <= diff)
|
||||
{
|
||||
Unit* target = SelectTarget(SelectTargetMethod::Random, 1);
|
||||
if (!target && me->GetVictim())
|
||||
target = me->GetVictim();
|
||||
if (target)
|
||||
DoCast(target, SPELL_GEYSER, true);
|
||||
GeyserTimer = rand32() % 5000 + 15000;
|
||||
}
|
||||
else
|
||||
GeyserTimer -= diff;
|
||||
|
||||
if (!InRange) // if on players in melee range cast Waterbolt
|
||||
{
|
||||
if (WaterboltTimer <= diff)
|
||||
{
|
||||
Unit* target = SelectTarget(SelectTargetMethod::Random, 0);
|
||||
if (!target && me->GetVictim())
|
||||
target = me->GetVictim();
|
||||
if (target)
|
||||
DoCast(target, SPELL_GEYSER, true);
|
||||
GeyserTimer = rand32() % 5000 + 15000;
|
||||
DoCast(target, SPELL_WATERBOLT, true);
|
||||
WaterboltTimer = 3000;
|
||||
}
|
||||
else
|
||||
GeyserTimer -= diff;
|
||||
|
||||
if (!InRange) // if on players in melee range cast Waterbolt
|
||||
{
|
||||
if (WaterboltTimer <= diff)
|
||||
{
|
||||
Unit* target = SelectTarget(SelectTargetMethod::Random, 0);
|
||||
if (!target && me->GetVictim())
|
||||
target = me->GetVictim();
|
||||
if (target)
|
||||
DoCast(target, SPELL_WATERBOLT, true);
|
||||
WaterboltTimer = 3000;
|
||||
}
|
||||
else
|
||||
WaterboltTimer -= diff;
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
|
||||
WaterboltTimer -= diff;
|
||||
}
|
||||
else // submerged
|
||||
{
|
||||
if (PhaseTimer <= diff)
|
||||
{
|
||||
Submerged = false;
|
||||
me->InterruptNonMeleeSpells(false); // shouldn't be any
|
||||
me->RemoveAllAuras();
|
||||
me->SetImmuneToPC(false);
|
||||
me->SetEmoteState(EMOTE_ONESHOT_NONE);
|
||||
DoCast(me, SPELL_EMERGE, true);
|
||||
Spawned = false;
|
||||
SpoutTimer = 3000; // directly cast Spout after emerging!
|
||||
PhaseTimer = 120000;
|
||||
return;
|
||||
}
|
||||
else
|
||||
PhaseTimer -= diff;
|
||||
|
||||
if (!me->IsThreatened()) // check if should evade
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!me->IsInCombat())
|
||||
DoZoneInCombat();
|
||||
|
||||
if (!Spawned)
|
||||
{
|
||||
me->ReplaceAllUnitFlags(UNIT_FLAG_IMMUNE_TO_PC);
|
||||
// spawn adds
|
||||
for (uint8 i = 0; i < 9; ++i)
|
||||
if (Creature* summoned = me->SummonCreature(i < 6 ? NPC_COILFANG_AMBUSHER : NPC_COILFANG_GUARDIAN, AddPos[i][0], AddPos[i][1], AddPos[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN))
|
||||
Summons.Summon(summoned);
|
||||
Spawned = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class npc_coilfang_ambusher : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_coilfang_ambusher() : CreatureScript("npc_coilfang_ambusher") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetSerpentshrineCavernAI<npc_coilfang_ambusherAI>(creature);
|
||||
}
|
||||
|
||||
struct npc_coilfang_ambusherAI : public ScriptedAI
|
||||
{
|
||||
npc_coilfang_ambusherAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
Initialize();
|
||||
SetCombatMovement(false);
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
MultiShotTimer = 10000;
|
||||
ShootBowTimer = 4000;
|
||||
}
|
||||
|
||||
uint32 MultiShotTimer;
|
||||
uint32 ShootBowTimer;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
|
||||
{
|
||||
if (!who || me->GetVictim())
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (who->isInAccessiblePlaceFor(me) && me->IsValidAttackTarget(who) && me->IsWithinDistInMap(who, 45))
|
||||
AttackStart(who);
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
}
|
||||
else // submerged
|
||||
{
|
||||
if (MultiShotTimer <= diff)
|
||||
if (PhaseTimer <= diff)
|
||||
{
|
||||
if (me->GetVictim())
|
||||
DoCastVictim(SPELL_SPREAD_SHOT, true);
|
||||
Submerged = false;
|
||||
me->InterruptNonMeleeSpells(false); // shouldn't be any
|
||||
me->RemoveAllAuras();
|
||||
me->SetImmuneToPC(false);
|
||||
me->SetEmoteState(EMOTE_ONESHOT_NONE);
|
||||
DoCast(me, SPELL_EMERGE, true);
|
||||
Spawned = false;
|
||||
SpoutTimer = 3000; // directly cast Spout after emerging!
|
||||
PhaseTimer = 120000;
|
||||
return;
|
||||
}
|
||||
else
|
||||
PhaseTimer -= diff;
|
||||
|
||||
MultiShotTimer = 10000 + rand32() % 10000;
|
||||
ShootBowTimer += 1500; // add global cooldown
|
||||
} else MultiShotTimer -= diff;
|
||||
|
||||
if (ShootBowTimer <= diff)
|
||||
if (!me->IsThreatened()) // check if should evade
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
me->CastSpell(target, SPELL_SHOOT, CastSpellExtraArgs(TRIGGERED_FULL_MASK).AddSpellBP0(1100));
|
||||
ShootBowTimer = 4000 + rand32() % 5000;
|
||||
MultiShotTimer += 1500; // add global cooldown
|
||||
} else ShootBowTimer -= diff;
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!me->IsInCombat())
|
||||
DoZoneInCombat();
|
||||
|
||||
if (!Spawned)
|
||||
{
|
||||
me->ReplaceAllUnitFlags(UNIT_FLAG_IMMUNE_TO_PC);
|
||||
// spawn adds
|
||||
for (uint8 i = 0; i < 9; ++i)
|
||||
me->SummonCreature(i < 6 ? NPC_COILFANG_AMBUSHER : NPC_COILFANG_GUARDIAN, AddPos[i][0], AddPos[i][1], AddPos[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN);
|
||||
Spawned = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
struct npc_coilfang_ambusher : public ScriptedAI
|
||||
{
|
||||
npc_coilfang_ambusher(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
Initialize();
|
||||
SetCombatMovement(false);
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
MultiShotTimer = 10000;
|
||||
ShootBowTimer = 4000;
|
||||
}
|
||||
|
||||
uint32 MultiShotTimer;
|
||||
uint32 ShootBowTimer;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
|
||||
{
|
||||
if (!who || me->GetVictim())
|
||||
return;
|
||||
|
||||
if (who->isInAccessiblePlaceFor(me) && me->IsValidAttackTarget(who) && me->IsWithinDistInMap(who, 45))
|
||||
AttackStart(who);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (MultiShotTimer <= diff)
|
||||
{
|
||||
if (me->GetVictim())
|
||||
DoCastVictim(SPELL_SPREAD_SHOT, true);
|
||||
|
||||
MultiShotTimer = 10000 + rand32() % 10000;
|
||||
ShootBowTimer += 1500; // add global cooldown
|
||||
} else MultiShotTimer -= diff;
|
||||
|
||||
if (ShootBowTimer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
me->CastSpell(target, SPELL_SHOOT, CastSpellExtraArgs(TRIGGERED_FULL_MASK).AddSpellBP0(1100));
|
||||
ShootBowTimer = 4000 + rand32() % 5000;
|
||||
MultiShotTimer += 1500; // add global cooldown
|
||||
} else ShootBowTimer -= diff;
|
||||
}
|
||||
};
|
||||
|
||||
class go_strange_pool : public GameObjectScript
|
||||
struct go_strange_pool : public GameObjectAI
|
||||
{
|
||||
public:
|
||||
go_strange_pool() : GameObjectScript("go_strange_pool") { }
|
||||
go_strange_pool(GameObject* go) : GameObjectAI(go), instance(go->GetInstanceScript()) { }
|
||||
|
||||
struct go_strange_poolAI : public GameObjectAI
|
||||
InstanceScript* instance;
|
||||
|
||||
bool OnGossipHello(Player* player) override
|
||||
{
|
||||
// 25%
|
||||
if (!urand(0, 3))
|
||||
{
|
||||
go_strange_poolAI(GameObject* go) : GameObjectAI(go), instance(go->GetInstanceScript()) { }
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
bool OnGossipHello(Player* player) override
|
||||
if (instance->GetData(DATA_STRANGE_POOL) == NOT_STARTED)
|
||||
{
|
||||
// 25%
|
||||
if (!urand(0, 3))
|
||||
{
|
||||
if (instance->GetData(DATA_STRANGE_POOL) == NOT_STARTED)
|
||||
{
|
||||
me->CastSpell(player, 54587);
|
||||
instance->SetData(DATA_STRANGE_POOL, IN_PROGRESS);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
me->CastSpell(player, 54587);
|
||||
instance->SetData(DATA_STRANGE_POOL, IN_PROGRESS);
|
||||
}
|
||||
};
|
||||
|
||||
GameObjectAI* GetAI(GameObject* go) const override
|
||||
{
|
||||
return GetSerpentshrineCavernAI<go_strange_poolAI>(go);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_the_lurker_below()
|
||||
{
|
||||
new boss_the_lurker_below();
|
||||
new npc_coilfang_ambusher();
|
||||
new go_strange_pool();
|
||||
RegisterSerpentshrineCavernCreatureAI(boss_the_lurker_below);
|
||||
RegisterSerpentshrineCavernCreatureAI(npc_coilfang_ambusher);
|
||||
RegisterSerpentshrineCavernGameObjectAI(go_strange_pool);
|
||||
}
|
||||
|
||||
@@ -86,286 +86,253 @@ float MurlocCords[10][4] =
|
||||
};
|
||||
|
||||
//Morogrim Tidewalker AI
|
||||
class boss_morogrim_tidewalker : public CreatureScript
|
||||
struct boss_morogrim_tidewalker : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_morogrim_tidewalker() : CreatureScript("boss_morogrim_tidewalker") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
boss_morogrim_tidewalker(Creature* creature) : BossAI(creature, BOSS_MOROGRIM_TIDEWALKER)
|
||||
{
|
||||
return GetSerpentshrineCavernAI<boss_morogrim_tidewalkerAI>(creature);
|
||||
Initialize();
|
||||
Playercount = 0;
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
struct boss_morogrim_tidewalkerAI : public ScriptedAI
|
||||
void Initialize()
|
||||
{
|
||||
boss_morogrim_tidewalkerAI(Creature* creature) : ScriptedAI(creature)
|
||||
TidalWave_Timer = 10000;
|
||||
WateryGrave_Timer = 30000;
|
||||
Earthquake_Timer = 40000;
|
||||
WateryGlobules_Timer = 0;
|
||||
globulespell[0] = SPELL_SUMMON_WATER_GLOBULE_1;
|
||||
globulespell[1] = SPELL_SUMMON_WATER_GLOBULE_2;
|
||||
globulespell[2] = SPELL_SUMMON_WATER_GLOBULE_3;
|
||||
globulespell[3] = SPELL_SUMMON_WATER_GLOBULE_4;
|
||||
|
||||
Earthquake = false;
|
||||
Phase2 = false;
|
||||
}
|
||||
|
||||
uint32 TidalWave_Timer;
|
||||
uint32 WateryGrave_Timer;
|
||||
uint32 Earthquake_Timer;
|
||||
uint32 WateryGlobules_Timer;
|
||||
uint32 globulespell[4];
|
||||
int8 Playercount;
|
||||
int8 counter;
|
||||
|
||||
bool Earthquake;
|
||||
bool Phase2;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
|
||||
_Reset();
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
Playercount = me->GetMap()->GetPlayers().getSize();
|
||||
Talk(SAY_AGGRO);
|
||||
_JustEngagedWith(who);
|
||||
}
|
||||
|
||||
void ApplyWateryGrave(Unit* player, uint8 i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
Initialize();
|
||||
instance = creature->GetInstanceScript();
|
||||
Playercount = 0;
|
||||
counter = 0;
|
||||
case 0: player->CastSpell(player, SPELL_WATERY_GRAVE_1, true); break;
|
||||
case 1: player->CastSpell(player, SPELL_WATERY_GRAVE_2, true); break;
|
||||
case 2: player->CastSpell(player, SPELL_WATERY_GRAVE_3, true); break;
|
||||
case 3: player->CastSpell(player, SPELL_WATERY_GRAVE_4, true); break;
|
||||
}
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
//Earthquake_Timer
|
||||
if (Earthquake_Timer <= diff)
|
||||
{
|
||||
TidalWave_Timer = 10000;
|
||||
WateryGrave_Timer = 30000;
|
||||
Earthquake_Timer = 40000;
|
||||
WateryGlobules_Timer = 0;
|
||||
globulespell[0] = SPELL_SUMMON_WATER_GLOBULE_1;
|
||||
globulespell[1] = SPELL_SUMMON_WATER_GLOBULE_2;
|
||||
globulespell[2] = SPELL_SUMMON_WATER_GLOBULE_3;
|
||||
globulespell[3] = SPELL_SUMMON_WATER_GLOBULE_4;
|
||||
|
||||
Earthquake = false;
|
||||
Phase2 = false;
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
uint32 TidalWave_Timer;
|
||||
uint32 WateryGrave_Timer;
|
||||
uint32 Earthquake_Timer;
|
||||
uint32 WateryGlobules_Timer;
|
||||
uint32 globulespell[4];
|
||||
int8 Playercount;
|
||||
int8 counter;
|
||||
|
||||
bool Earthquake;
|
||||
bool Phase2;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
|
||||
instance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, NOT_STARTED);
|
||||
}
|
||||
|
||||
void StartEvent()
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
instance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, IN_PROGRESS);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
|
||||
instance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, DONE);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
Playercount = me->GetMap()->GetPlayers().getSize();
|
||||
StartEvent();
|
||||
}
|
||||
|
||||
void ApplyWateryGrave(Unit* player, uint8 i)
|
||||
{
|
||||
switch (i)
|
||||
if (!Earthquake)
|
||||
{
|
||||
case 0: player->CastSpell(player, SPELL_WATERY_GRAVE_1, true); break;
|
||||
case 1: player->CastSpell(player, SPELL_WATERY_GRAVE_2, true); break;
|
||||
case 2: player->CastSpell(player, SPELL_WATERY_GRAVE_3, true); break;
|
||||
case 3: player->CastSpell(player, SPELL_WATERY_GRAVE_4, true); break;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
//Earthquake_Timer
|
||||
if (Earthquake_Timer <= diff)
|
||||
{
|
||||
if (!Earthquake)
|
||||
{
|
||||
DoCastVictim(SPELL_EARTHQUAKE);
|
||||
Earthquake = true;
|
||||
Earthquake_Timer = 10000;
|
||||
}
|
||||
else
|
||||
{
|
||||
Talk(SAY_SUMMON);
|
||||
|
||||
for (uint8 i = 0; i < 10; ++i)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
if (Creature* Murloc = me->SummonCreature(NPC_TIDEWALKER_LURKER, MurlocCords[i][0], MurlocCords[i][1], MurlocCords[i][2], MurlocCords[i][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10s))
|
||||
Murloc->AI()->AttackStart(target);
|
||||
}
|
||||
Talk(EMOTE_EARTHQUAKE);
|
||||
Earthquake = false;
|
||||
Earthquake_Timer = 40000 + rand32() % 5000;
|
||||
}
|
||||
} else Earthquake_Timer -= diff;
|
||||
|
||||
//TidalWave_Timer
|
||||
if (TidalWave_Timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_TIDAL_WAVE);
|
||||
TidalWave_Timer = 20000;
|
||||
} else TidalWave_Timer -= diff;
|
||||
|
||||
if (!Phase2)
|
||||
{
|
||||
//WateryGrave_Timer
|
||||
if (WateryGrave_Timer <= diff)
|
||||
{
|
||||
//Teleport 4 players under the waterfalls
|
||||
GuidSet targets;
|
||||
GuidSet::const_iterator itr = targets.begin();
|
||||
for (uint8 i = 0; i < 4; ++i)
|
||||
{
|
||||
counter = 0;
|
||||
Unit* target;
|
||||
do
|
||||
{
|
||||
target = SelectTarget(SelectTargetMethod::Random, 1, 50, true); //target players only
|
||||
if (counter < Playercount)
|
||||
break;
|
||||
if (target)
|
||||
itr = targets.find(target->GetGUID());
|
||||
++counter;
|
||||
} while (itr != targets.end());
|
||||
|
||||
if (target)
|
||||
{
|
||||
targets.insert(target->GetGUID());
|
||||
ApplyWateryGrave(target, i);
|
||||
}
|
||||
}
|
||||
|
||||
Talk(SAY_SUMMON_BUBL);
|
||||
|
||||
Talk(EMOTE_WATERY_GRAVE);
|
||||
WateryGrave_Timer = 30000;
|
||||
} else WateryGrave_Timer -= diff;
|
||||
|
||||
//Start Phase2
|
||||
if (HealthBelowPct(25))
|
||||
Phase2 = true;
|
||||
DoCastVictim(SPELL_EARTHQUAKE);
|
||||
Earthquake = true;
|
||||
Earthquake_Timer = 10000;
|
||||
}
|
||||
else
|
||||
{
|
||||
//WateryGlobules_Timer
|
||||
if (WateryGlobules_Timer <= diff)
|
||||
Talk(SAY_SUMMON);
|
||||
|
||||
for (uint8 i = 0; i < 10; ++i)
|
||||
{
|
||||
GuidSet globules;
|
||||
GuidSet::const_iterator itr = globules.begin();
|
||||
for (uint8 g = 0; g < 4; g++) //one unit can't cast more than one spell per update, so some players have to cast for us XD
|
||||
{
|
||||
counter = 0;
|
||||
Unit* pGlobuleTarget;
|
||||
do
|
||||
{
|
||||
pGlobuleTarget = SelectTarget(SelectTargetMethod::Random, 0, 50, true);
|
||||
if (pGlobuleTarget)
|
||||
itr = globules.find(pGlobuleTarget->GetGUID());
|
||||
if (counter > Playercount)
|
||||
break;
|
||||
++counter;
|
||||
} while (itr != globules.end());
|
||||
|
||||
if (pGlobuleTarget)
|
||||
{
|
||||
globules.insert(pGlobuleTarget->GetGUID());
|
||||
pGlobuleTarget->CastSpell(pGlobuleTarget, globulespell[g], true);
|
||||
}
|
||||
}
|
||||
Talk(EMOTE_WATERY_GLOBULES);
|
||||
WateryGlobules_Timer = 25000;
|
||||
} else WateryGlobules_Timer -= diff;
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
if (Creature* Murloc = me->SummonCreature(NPC_TIDEWALKER_LURKER, MurlocCords[i][0], MurlocCords[i][1], MurlocCords[i][2], MurlocCords[i][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10s))
|
||||
Murloc->AI()->AttackStart(target);
|
||||
}
|
||||
Talk(EMOTE_EARTHQUAKE);
|
||||
Earthquake = false;
|
||||
Earthquake_Timer = 40000 + rand32() % 5000;
|
||||
}
|
||||
} else Earthquake_Timer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
//TidalWave_Timer
|
||||
if (TidalWave_Timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_TIDAL_WAVE);
|
||||
TidalWave_Timer = 20000;
|
||||
} else TidalWave_Timer -= diff;
|
||||
|
||||
if (!Phase2)
|
||||
{
|
||||
//WateryGrave_Timer
|
||||
if (WateryGrave_Timer <= diff)
|
||||
{
|
||||
//Teleport 4 players under the waterfalls
|
||||
GuidSet targets;
|
||||
GuidSet::const_iterator itr = targets.begin();
|
||||
for (uint8 i = 0; i < 4; ++i)
|
||||
{
|
||||
counter = 0;
|
||||
Unit* target;
|
||||
do
|
||||
{
|
||||
target = SelectTarget(SelectTargetMethod::Random, 1, 50, true); //target players only
|
||||
if (counter < Playercount)
|
||||
break;
|
||||
if (target)
|
||||
itr = targets.find(target->GetGUID());
|
||||
++counter;
|
||||
} while (itr != targets.end());
|
||||
|
||||
if (target)
|
||||
{
|
||||
targets.insert(target->GetGUID());
|
||||
ApplyWateryGrave(target, i);
|
||||
}
|
||||
}
|
||||
|
||||
Talk(SAY_SUMMON_BUBL);
|
||||
|
||||
Talk(EMOTE_WATERY_GRAVE);
|
||||
WateryGrave_Timer = 30000;
|
||||
} else WateryGrave_Timer -= diff;
|
||||
|
||||
//Start Phase2
|
||||
if (HealthBelowPct(25))
|
||||
Phase2 = true;
|
||||
}
|
||||
};
|
||||
else
|
||||
{
|
||||
//WateryGlobules_Timer
|
||||
if (WateryGlobules_Timer <= diff)
|
||||
{
|
||||
GuidSet globules;
|
||||
GuidSet::const_iterator itr = globules.begin();
|
||||
for (uint8 g = 0; g < 4; g++) //one unit can't cast more than one spell per update, so some players have to cast for us XD
|
||||
{
|
||||
counter = 0;
|
||||
Unit* pGlobuleTarget;
|
||||
do
|
||||
{
|
||||
pGlobuleTarget = SelectTarget(SelectTargetMethod::Random, 0, 50, true);
|
||||
if (pGlobuleTarget)
|
||||
itr = globules.find(pGlobuleTarget->GetGUID());
|
||||
if (counter > Playercount)
|
||||
break;
|
||||
++counter;
|
||||
} while (itr != globules.end());
|
||||
|
||||
if (pGlobuleTarget)
|
||||
{
|
||||
globules.insert(pGlobuleTarget->GetGUID());
|
||||
pGlobuleTarget->CastSpell(pGlobuleTarget, globulespell[g], true);
|
||||
}
|
||||
}
|
||||
Talk(EMOTE_WATERY_GLOBULES);
|
||||
WateryGlobules_Timer = 25000;
|
||||
} else WateryGlobules_Timer -= diff;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
class npc_water_globule : public CreatureScript
|
||||
struct npc_water_globule : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
npc_water_globule() : CreatureScript("npc_water_globule") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
npc_water_globule(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
return GetSerpentshrineCavernAI<npc_water_globuleAI>(creature);
|
||||
Initialize();
|
||||
}
|
||||
|
||||
struct npc_water_globuleAI : public ScriptedAI
|
||||
void Initialize()
|
||||
{
|
||||
npc_water_globuleAI(Creature* creature) : ScriptedAI(creature)
|
||||
Check_Timer = 1000;
|
||||
}
|
||||
|
||||
uint32 Check_Timer;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
|
||||
me->SetFaction(FACTION_MONSTER);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override { }
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
|
||||
{
|
||||
if (!who || me->GetVictim())
|
||||
return;
|
||||
|
||||
if (me->CanCreatureAttack(who))
|
||||
{
|
||||
Initialize();
|
||||
//no attack radius check - it attacks the first target that moves in his los
|
||||
//who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
|
||||
AttackStart(who);
|
||||
}
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (Check_Timer <= diff)
|
||||
{
|
||||
Check_Timer = 1000;
|
||||
}
|
||||
|
||||
uint32 Check_Timer;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
|
||||
me->SetFaction(FACTION_MONSTER);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override { }
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
|
||||
{
|
||||
if (!who || me->GetVictim())
|
||||
return;
|
||||
|
||||
if (me->CanCreatureAttack(who))
|
||||
if (me->IsWithinDistInMap(me->GetVictim(), 5))
|
||||
{
|
||||
//no attack radius check - it attacks the first target that moves in his los
|
||||
//who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
|
||||
AttackStart(who);
|
||||
DoCastVictim(SPELL_GLOBULE_EXPLOSION);
|
||||
|
||||
//despawn
|
||||
me->DespawnOrUnsummon();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (Check_Timer <= diff)
|
||||
{
|
||||
if (me->IsWithinDistInMap(me->GetVictim(), 5))
|
||||
{
|
||||
DoCastVictim(SPELL_GLOBULE_EXPLOSION);
|
||||
|
||||
//despawn
|
||||
me->DespawnOrUnsummon();
|
||||
return;
|
||||
}
|
||||
Check_Timer = 500;
|
||||
} else Check_Timer -= diff;
|
||||
|
||||
//do NOT deal any melee damage to the target.
|
||||
}
|
||||
};
|
||||
Check_Timer = 500;
|
||||
} else Check_Timer -= diff;
|
||||
|
||||
//do NOT deal any melee damage to the target.
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_morogrim_tidewalker()
|
||||
{
|
||||
new boss_morogrim_tidewalker();
|
||||
new npc_water_globule();
|
||||
RegisterSerpentshrineCavernCreatureAI(boss_morogrim_tidewalker);
|
||||
RegisterSerpentshrineCavernCreatureAI(npc_water_globule);
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ class instance_serpent_shrine : public InstanceMapScript
|
||||
instance_serpentshrine_cavern_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
|
||||
SetBossNumber(MAX_ENCOUNTER);
|
||||
|
||||
StrangePool = 0;
|
||||
Water = WATERSTATE_FRENZY;
|
||||
@@ -112,15 +112,6 @@ class instance_serpent_shrine : public InstanceMapScript
|
||||
TrashCount = 0;
|
||||
}
|
||||
|
||||
bool IsEncounterInProgress() const override
|
||||
{
|
||||
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
|
||||
if (m_auiEncounter[i] == IN_PROGRESS)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Update(uint32 diff) override
|
||||
{
|
||||
//Water checks
|
||||
@@ -298,32 +289,6 @@ class instance_serpent_shrine : public InstanceMapScript
|
||||
case DATA_WATER:
|
||||
Water = data;
|
||||
break;
|
||||
case DATA_HYDROSSTHEUNSTABLEEVENT:
|
||||
m_auiEncounter[0] = data;
|
||||
break;
|
||||
case DATA_LEOTHERASTHEBLINDEVENT:
|
||||
m_auiEncounter[1] = data;
|
||||
break;
|
||||
case DATA_THELURKERBELOWEVENT:
|
||||
m_auiEncounter[2] = data;
|
||||
break;
|
||||
case DATA_KARATHRESSEVENT:
|
||||
m_auiEncounter[3] = data;
|
||||
break;
|
||||
case DATA_MOROGRIMTIDEWALKEREVENT:
|
||||
m_auiEncounter[4] = data;
|
||||
break;
|
||||
//Lady Vashj
|
||||
case DATA_LADYVASHJEVENT:
|
||||
if (data == NOT_STARTED)
|
||||
{
|
||||
ShieldGeneratorDeactivated[0] = false;
|
||||
ShieldGeneratorDeactivated[1] = false;
|
||||
ShieldGeneratorDeactivated[2] = false;
|
||||
ShieldGeneratorDeactivated[3] = false;
|
||||
}
|
||||
m_auiEncounter[5] = data;
|
||||
break;
|
||||
case DATA_SHIELDGENERATOR1:
|
||||
ShieldGeneratorDeactivated[0] = data != 0;
|
||||
break;
|
||||
@@ -339,28 +304,28 @@ class instance_serpent_shrine : public InstanceMapScript
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (data == DONE)
|
||||
SaveToDB();
|
||||
bool SetBossState(uint32 id, EncounterState state) override
|
||||
{
|
||||
if (!InstanceScript::SetBossState(id, state))
|
||||
return false;
|
||||
|
||||
if (id == BOSS_LADY_VASHJ && state == NOT_STARTED)
|
||||
{
|
||||
ShieldGeneratorDeactivated[0] = false;
|
||||
ShieldGeneratorDeactivated[1] = false;
|
||||
ShieldGeneratorDeactivated[2] = false;
|
||||
ShieldGeneratorDeactivated[3] = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 type) const override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_HYDROSSTHEUNSTABLEEVENT:
|
||||
return m_auiEncounter[0];
|
||||
case DATA_LEOTHERASTHEBLINDEVENT:
|
||||
return m_auiEncounter[1];
|
||||
case DATA_THELURKERBELOWEVENT:
|
||||
return m_auiEncounter[2];
|
||||
case DATA_KARATHRESSEVENT:
|
||||
return m_auiEncounter[3];
|
||||
case DATA_MOROGRIMTIDEWALKEREVENT:
|
||||
return m_auiEncounter[4];
|
||||
//Lady Vashj
|
||||
case DATA_LADYVASHJEVENT:
|
||||
return m_auiEncounter[5];
|
||||
case DATA_SHIELDGENERATOR1:
|
||||
return ShieldGeneratorDeactivated[0];
|
||||
case DATA_SHIELDGENERATOR2:
|
||||
@@ -384,34 +349,14 @@ class instance_serpent_shrine : public InstanceMapScript
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string GetSaveData() override
|
||||
void WriteSaveDataMore(std::ostringstream& stream) override
|
||||
{
|
||||
OUT_SAVE_INST_DATA;
|
||||
std::ostringstream stream;
|
||||
stream << m_auiEncounter[0] << ' ' << m_auiEncounter[1] << ' ' << m_auiEncounter[2] << ' '
|
||||
<< m_auiEncounter[3] << ' ' << m_auiEncounter[4] << ' ' << m_auiEncounter[5] << ' ' << TrashCount;
|
||||
OUT_SAVE_INST_DATA_COMPLETE;
|
||||
return stream.str();
|
||||
stream << TrashCount;
|
||||
}
|
||||
|
||||
void Load(char const* in) override
|
||||
void ReadSaveDataMore(std::istringstream& stream) override
|
||||
{
|
||||
if (!in)
|
||||
{
|
||||
OUT_LOAD_INST_DATA_FAIL;
|
||||
return;
|
||||
}
|
||||
|
||||
OUT_LOAD_INST_DATA(in);
|
||||
std::istringstream stream(in);
|
||||
stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]
|
||||
>> m_auiEncounter[4] >> m_auiEncounter[5] >> TrashCount;
|
||||
|
||||
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
|
||||
if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead.
|
||||
m_auiEncounter[i] = NOT_STARTED;
|
||||
|
||||
OUT_LOAD_INST_DATA_COMPLETE;
|
||||
stream >> TrashCount;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -435,7 +380,6 @@ class instance_serpent_shrine : public InstanceMapScript
|
||||
uint32 TrashCount;
|
||||
|
||||
bool ShieldGeneratorDeactivated[4];
|
||||
uint32 m_auiEncounter[MAX_ENCOUNTER];
|
||||
bool DoSpawnFrenzy;
|
||||
};
|
||||
|
||||
|
||||
@@ -30,33 +30,37 @@ enum SSWaterEventState
|
||||
WATERSTATE_SCALDING = 2
|
||||
};
|
||||
|
||||
enum SSBosses
|
||||
{
|
||||
BOSS_HYDROSS_THE_UNSTABLE = 0,
|
||||
BOSS_THE_LURKER_BELOW = 1,
|
||||
BOSS_LEOTHERAS_THE_BLIND = 2,
|
||||
BOSS_FATHOM_LORD_KARATHRESS = 3,
|
||||
BOSS_MOROGRIM_TIDEWALKER = 4,
|
||||
BOSS_LADY_VASHJ = 5
|
||||
};
|
||||
|
||||
enum SSDataTypes
|
||||
{
|
||||
DATA_CANSTARTPHASE3 = 1,
|
||||
DATA_CARIBDIS = 2,
|
||||
DATA_HYDROSSTHEUNSTABLEEVENT = 3,
|
||||
DATA_KARATHRESS = 4,
|
||||
DATA_KARATHRESSEVENT = 5,
|
||||
DATA_KARATHRESSEVENT_STARTER = 6,
|
||||
DATA_LADYVASHJ = 7,
|
||||
DATA_LADYVASHJEVENT = 8,
|
||||
DATA_LEOTHERASTHEBLINDEVENT = 9,
|
||||
DATA_MOROGRIMTIDEWALKEREVENT = 10,
|
||||
DATA_SHARKKIS = 11,
|
||||
DATA_SHIELDGENERATOR1 = 12,
|
||||
DATA_SHIELDGENERATOR2 = 13,
|
||||
DATA_SHIELDGENERATOR3 = 14,
|
||||
DATA_SHIELDGENERATOR4 = 15,
|
||||
DATA_THELURKERBELOW = 16,
|
||||
DATA_THELURKERBELOWEVENT = 17,
|
||||
DATA_TIDALVESS = 18,
|
||||
DATA_FATHOMLORDKARATHRESSEVENT = 19,
|
||||
DATA_LEOTHERAS = 20,
|
||||
DATA_LEOTHERAS_EVENT_STARTER = 21,
|
||||
DATA_CONTROL_CONSOLE = 22,
|
||||
DATA_STRANGE_POOL = 23,
|
||||
DATA_WATER = 24,
|
||||
DATA_TRASH = 25,
|
||||
DATA_KARATHRESS = 3,
|
||||
DATA_KARATHRESSEVENT_STARTER = 4,
|
||||
DATA_LADYVASHJ = 5,
|
||||
DATA_SHARKKIS = 6,
|
||||
DATA_SHIELDGENERATOR1 = 7,
|
||||
DATA_SHIELDGENERATOR2 = 8,
|
||||
DATA_SHIELDGENERATOR3 = 9,
|
||||
DATA_SHIELDGENERATOR4 = 10,
|
||||
DATA_THELURKERBELOW = 11,
|
||||
DATA_TIDALVESS = 12,
|
||||
DATA_FATHOMLORDKARATHRESSEVENT = 13,
|
||||
DATA_LEOTHERAS = 14,
|
||||
DATA_LEOTHERAS_EVENT_STARTER = 15,
|
||||
DATA_CONTROL_CONSOLE = 16,
|
||||
DATA_STRANGE_POOL = 17,
|
||||
DATA_WATER = 18,
|
||||
DATA_TRASH = 19,
|
||||
};
|
||||
|
||||
template <class AI, class T>
|
||||
@@ -65,4 +69,7 @@ inline AI* GetSerpentshrineCavernAI(T* obj)
|
||||
return GetInstanceAI<AI>(obj, SSCScriptName);
|
||||
}
|
||||
|
||||
#define RegisterSerpentshrineCavernCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetSerpentshrineCavernAI)
|
||||
#define RegisterSerpentshrineCavernGameObjectAI(ai_name) RegisterGameObjectAIWithFactory(ai_name, GetSerpentshrineCavernAI)
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user