Converting EasternKingdoms/ZulAman and EasternKingdoms/ZulGurub.
Need to recheck tomorrow. :) --HG-- branch : trunk
This commit is contained in:
@@ -59,411 +59,421 @@ EndScriptData */
|
||||
#define SE_LOC_Y_MAX 1435
|
||||
#define SE_LOC_Y_MIN 1370
|
||||
|
||||
struct boss_akilzonAI : public ScriptedAI
|
||||
class boss_akilzon : public CreatureScript
|
||||
{
|
||||
boss_akilzonAI(Creature *c) : ScriptedAI(c)
|
||||
{
|
||||
SpellEntry *TempSpell = GET_SPELL(SPELL_ELECTRICAL_DAMAGE);
|
||||
if (TempSpell)
|
||||
TempSpell->EffectBasePoints[1] = 49;//disable bugged lightning until fixed in core
|
||||
pInstance = c->GetInstanceData();
|
||||
}
|
||||
ScriptedInstance *pInstance;
|
||||
public:
|
||||
|
||||
uint64 BirdGUIDs[8];
|
||||
uint64 TargetGUID;
|
||||
uint64 CycloneGUID;
|
||||
uint64 CloudGUID;
|
||||
|
||||
uint32 StaticDisruption_Timer;
|
||||
uint32 GustOfWind_Timer;
|
||||
uint32 CallLighting_Timer;
|
||||
uint32 ElectricalStorm_Timer;
|
||||
uint32 SummonEagles_Timer;
|
||||
uint32 Enrage_Timer;
|
||||
|
||||
uint32 StormCount;
|
||||
uint32 StormSequenceTimer;
|
||||
|
||||
bool isRaining;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_AKILZONEVENT, NOT_STARTED);
|
||||
|
||||
StaticDisruption_Timer = urand(10000,20000); //10 to 20 seconds (bosskillers)
|
||||
GustOfWind_Timer = urand(20000,30000); //20 to 30 seconds(bosskillers)
|
||||
CallLighting_Timer = urand(10000,20000); //totaly random timer. can't find any info on this
|
||||
ElectricalStorm_Timer = 60000; //60 seconds(bosskillers)
|
||||
Enrage_Timer = 10*MINUTE*IN_MILLISECONDS; //10 minutes till enrage(bosskillers)
|
||||
SummonEagles_Timer = 99999;
|
||||
|
||||
TargetGUID = 0;
|
||||
CloudGUID = 0;
|
||||
CycloneGUID = 0;
|
||||
DespawnSummons();
|
||||
for (uint8 i = 0; i < 8; ++i)
|
||||
BirdGUIDs[i] = 0;
|
||||
|
||||
StormCount = 0;
|
||||
StormSequenceTimer = 0;
|
||||
|
||||
isRaining = false;
|
||||
|
||||
SetWeather(WEATHER_STATE_FINE, 0.0f);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit * /*who*/)
|
||||
{
|
||||
me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_ONAGGRO);
|
||||
//DoZoneInCombat();
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_AKILZONEVENT, IN_PROGRESS);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*Killer*/)
|
||||
{
|
||||
me->MonsterYell(SAY_ONDEATH,LANG_UNIVERSAL,NULL);
|
||||
DoPlaySoundToSet(me, SOUND_ONDEATH);
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_AKILZONEVENT, DONE);
|
||||
DespawnSummons();
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/)
|
||||
{
|
||||
switch (urand(0,1))
|
||||
boss_akilzon()
|
||||
: CreatureScript("boss_akilzon")
|
||||
{
|
||||
case 0:
|
||||
me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_ONSLAY1);
|
||||
break;
|
||||
case 1:
|
||||
me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_ONSLAY2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DespawnSummons()
|
||||
{
|
||||
for (uint8 i = 0; i < 8; ++i)
|
||||
struct boss_akilzonAI : public ScriptedAI
|
||||
{
|
||||
Unit* bird = Unit::GetUnit(*me,BirdGUIDs[i]);
|
||||
if (bird && bird->isAlive())
|
||||
boss_akilzonAI(Creature *c) : ScriptedAI(c)
|
||||
{
|
||||
bird->SetVisibility(VISIBILITY_OFF);
|
||||
bird->setDeathState(JUST_DIED);
|
||||
SpellEntry *TempSpell = GET_SPELL(SPELL_ELECTRICAL_DAMAGE);
|
||||
if (TempSpell)
|
||||
TempSpell->EffectBasePoints[1] = 49;//disable bugged lightning until fixed in core
|
||||
pInstance = c->GetInstanceData();
|
||||
}
|
||||
}
|
||||
}
|
||||
ScriptedInstance *pInstance;
|
||||
|
||||
void SetWeather(uint32 weather, float grade)
|
||||
{
|
||||
Map* pMap = me->GetMap();
|
||||
if (!pMap->IsDungeon())
|
||||
return;
|
||||
uint64 BirdGUIDs[8];
|
||||
uint64 TargetGUID;
|
||||
uint64 CycloneGUID;
|
||||
uint64 CloudGUID;
|
||||
|
||||
WorldPacket data(SMSG_WEATHER, (4+4+4));
|
||||
data << uint32(weather) << float(grade) << uint8(0);
|
||||
uint32 StaticDisruption_Timer;
|
||||
uint32 GustOfWind_Timer;
|
||||
uint32 CallLighting_Timer;
|
||||
uint32 ElectricalStorm_Timer;
|
||||
uint32 SummonEagles_Timer;
|
||||
uint32 Enrage_Timer;
|
||||
|
||||
pMap->SendToPlayers(&data);
|
||||
}
|
||||
uint32 StormCount;
|
||||
uint32 StormSequenceTimer;
|
||||
|
||||
void HandleStormSequence(Unit *Cloud) // 1: begin, 2-9: tick, 10: end
|
||||
{
|
||||
if (StormCount < 10 && StormCount > 1)
|
||||
{
|
||||
// deal damage
|
||||
int32 bp0 = 800;
|
||||
for (uint8 i = 2; i < StormCount; ++i)
|
||||
bp0 *= 2;
|
||||
|
||||
CellPair p(Trinity::ComputeCellPair(me->GetPositionX(), me->GetPositionY()));
|
||||
Cell cell(p);
|
||||
cell.data.Part.reserved = ALL_DISTRICT;
|
||||
cell.SetNoCreate();
|
||||
|
||||
std::list<Unit *> tempUnitMap;
|
||||
bool isRaining;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(me, me, 999);
|
||||
Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(me, tempUnitMap, u_check);
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_AKILZONEVENT, NOT_STARTED);
|
||||
|
||||
TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
|
||||
TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
|
||||
StaticDisruption_Timer = urand(10000,20000); //10 to 20 seconds (bosskillers)
|
||||
GustOfWind_Timer = urand(20000,30000); //20 to 30 seconds(bosskillers)
|
||||
CallLighting_Timer = urand(10000,20000); //totaly random timer. can't find any info on this
|
||||
ElectricalStorm_Timer = 60000; //60 seconds(bosskillers)
|
||||
Enrage_Timer = 10*MINUTE*IN_MILLISECONDS; //10 minutes till enrage(bosskillers)
|
||||
SummonEagles_Timer = 99999;
|
||||
|
||||
cell.Visit(p, world_unit_searcher, *(me->GetMap()));
|
||||
cell.Visit(p, grid_unit_searcher, *(me->GetMap()));
|
||||
TargetGUID = 0;
|
||||
CloudGUID = 0;
|
||||
CycloneGUID = 0;
|
||||
DespawnSummons();
|
||||
for (uint8 i = 0; i < 8; ++i)
|
||||
BirdGUIDs[i] = 0;
|
||||
|
||||
StormCount = 0;
|
||||
StormSequenceTimer = 0;
|
||||
|
||||
isRaining = false;
|
||||
|
||||
SetWeather(WEATHER_STATE_FINE, 0.0f);
|
||||
}
|
||||
//dealdamege
|
||||
for (std::list<Unit*>::const_iterator i = tempUnitMap.begin(); i != tempUnitMap.end(); ++i)
|
||||
|
||||
void EnterCombat(Unit * /*who*/)
|
||||
{
|
||||
if (!Cloud->IsWithinDist(*i, 6, false))
|
||||
me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_ONAGGRO);
|
||||
//DoZoneInCombat();
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_AKILZONEVENT, IN_PROGRESS);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*Killer*/)
|
||||
{
|
||||
me->MonsterYell(SAY_ONDEATH,LANG_UNIVERSAL,NULL);
|
||||
DoPlaySoundToSet(me, SOUND_ONDEATH);
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_AKILZONEVENT, DONE);
|
||||
DespawnSummons();
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/)
|
||||
{
|
||||
switch (urand(0,1))
|
||||
{
|
||||
Cloud->CastCustomSpell(*i, 43137, &bp0, NULL, NULL, true, 0, 0, me->GetGUID());
|
||||
case 0:
|
||||
me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_ONSLAY1);
|
||||
break;
|
||||
case 1:
|
||||
me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_ONSLAY2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// visual
|
||||
float x,y,z;
|
||||
z = me->GetPositionZ();
|
||||
for (uint8 i = 0; i < 5+rand()%5; ++i)
|
||||
|
||||
void DespawnSummons()
|
||||
{
|
||||
x = 343+rand()%60;
|
||||
y = 1380+rand()%60;
|
||||
if (Unit *trigger = me->SummonTrigger(x, y, z, 0, 2000))
|
||||
for (uint8 i = 0; i < 8; ++i)
|
||||
{
|
||||
trigger->setFaction(35);
|
||||
trigger->SetMaxHealth(100000);
|
||||
trigger->SetHealth(100000);
|
||||
trigger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
Unit* bird = Unit::GetUnit(*me,BirdGUIDs[i]);
|
||||
if (bird && bird->isAlive())
|
||||
{
|
||||
bird->SetVisibility(VISIBILITY_OFF);
|
||||
bird->setDeathState(JUST_DIED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetWeather(uint32 weather, float grade)
|
||||
{
|
||||
Map* pMap = me->GetMap();
|
||||
if (!pMap->IsDungeon())
|
||||
return;
|
||||
|
||||
WorldPacket data(SMSG_WEATHER, (4+4+4));
|
||||
data << uint32(weather) << float(grade) << uint8(0);
|
||||
|
||||
pMap->SendToPlayers(&data);
|
||||
}
|
||||
|
||||
void HandleStormSequence(Unit *Cloud) // 1: begin, 2-9: tick, 10: end
|
||||
{
|
||||
if (StormCount < 10 && StormCount > 1)
|
||||
{
|
||||
// deal damage
|
||||
int32 bp0 = 800;
|
||||
for (uint8 i = 2; i < StormCount; ++i)
|
||||
bp0 *= 2;
|
||||
|
||||
CellPair p(Trinity::ComputeCellPair(me->GetPositionX(), me->GetPositionY()));
|
||||
Cell cell(p);
|
||||
cell.data.Part.reserved = ALL_DISTRICT;
|
||||
cell.SetNoCreate();
|
||||
|
||||
std::list<Unit *> tempUnitMap;
|
||||
|
||||
{
|
||||
Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(me, me, 999);
|
||||
Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(me, tempUnitMap, u_check);
|
||||
|
||||
TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
|
||||
TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
|
||||
|
||||
cell.Visit(p, world_unit_searcher, *(me->GetMap()));
|
||||
cell.Visit(p, grid_unit_searcher, *(me->GetMap()));
|
||||
}
|
||||
//dealdamege
|
||||
for (std::list<Unit*>::const_iterator i = tempUnitMap.begin(); i != tempUnitMap.end(); ++i)
|
||||
{
|
||||
if (!Cloud->IsWithinDist(*i, 6, false))
|
||||
{
|
||||
Cloud->CastCustomSpell(*i, 43137, &bp0, NULL, NULL, true, 0, 0, me->GetGUID());
|
||||
}
|
||||
}
|
||||
// visual
|
||||
float x,y,z;
|
||||
z = me->GetPositionZ();
|
||||
for (uint8 i = 0; i < 5+rand()%5; ++i)
|
||||
{
|
||||
x = 343+rand()%60;
|
||||
y = 1380+rand()%60;
|
||||
if (Unit *trigger = me->SummonTrigger(x, y, z, 0, 2000))
|
||||
{
|
||||
trigger->setFaction(35);
|
||||
trigger->SetMaxHealth(100000);
|
||||
trigger->SetHealth(100000);
|
||||
trigger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
if (Cloud)
|
||||
Cloud->CastCustomSpell(trigger, /*43661*/43137, &bp0, NULL, NULL,true, 0, 0, Cloud->GetGUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
++StormCount;
|
||||
if (StormCount > 10)
|
||||
{
|
||||
StormCount = 0; // finish
|
||||
SummonEagles_Timer = 5000;
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
CloudGUID = 0;
|
||||
if (Cloud)
|
||||
Cloud->CastCustomSpell(trigger, /*43661*/43137, &bp0, NULL, NULL,true, 0, 0, Cloud->GetGUID());
|
||||
Cloud->DealDamage(Cloud, Cloud->GetHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
|
||||
SetWeather(WEATHER_STATE_FINE, 0.0f);
|
||||
isRaining = false;
|
||||
}
|
||||
StormSequenceTimer = 1000;
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (StormCount)
|
||||
{
|
||||
Unit *pTarget = Unit::GetUnit(*me, CloudGUID);
|
||||
if (!pTarget || !pTarget->isAlive())
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
else if (Unit* Cyclone = Unit::GetUnit(*me, CycloneGUID))
|
||||
Cyclone->CastSpell(pTarget, 25160, true); // keep casting or...
|
||||
|
||||
if (StormSequenceTimer <= diff)
|
||||
HandleStormSequence(pTarget);
|
||||
else
|
||||
StormSequenceTimer -= diff;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (Enrage_Timer <= diff)
|
||||
{
|
||||
me->MonsterYell(SAY_ONENRAGE, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_ONENRAGE);
|
||||
DoCast(me, SPELL_BERSERK, true);
|
||||
Enrage_Timer = 600000;
|
||||
} else Enrage_Timer -= diff;
|
||||
|
||||
if (StaticDisruption_Timer <= diff)
|
||||
{
|
||||
Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1);
|
||||
if (!pTarget) pTarget = me->getVictim();
|
||||
TargetGUID = pTarget->GetGUID();
|
||||
DoCast(pTarget, SPELL_STATIC_DISRUPTION, false);
|
||||
me->SetInFront(me->getVictim());
|
||||
StaticDisruption_Timer = (10+rand()%8)*1000; // < 20s
|
||||
|
||||
/*if (float dist = me->IsWithinDist3d(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 5.0f) dist = 5.0f;
|
||||
SDisruptAOEVisual_Timer = 1000 + floor(dist / 30 * 1000.0f);*/
|
||||
} else StaticDisruption_Timer -= diff;
|
||||
|
||||
if (GustOfWind_Timer <= diff)
|
||||
{
|
||||
Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1);
|
||||
if (!pTarget) pTarget = me->getVictim();
|
||||
DoCast(pTarget, SPELL_GUST_OF_WIND);
|
||||
GustOfWind_Timer = (20+rand()%10)*1000; //20 to 30 seconds(bosskillers)
|
||||
} else GustOfWind_Timer -= diff;
|
||||
|
||||
if (CallLighting_Timer <= diff)
|
||||
{
|
||||
DoCast(me->getVictim(), SPELL_CALL_LIGHTNING);
|
||||
CallLighting_Timer = (12 + rand()%5)*1000; //totaly random timer. can't find any info on this
|
||||
} else CallLighting_Timer -= diff;
|
||||
|
||||
if (!isRaining && ElectricalStorm_Timer < 8000 + rand()%5000)
|
||||
{
|
||||
SetWeather(WEATHER_STATE_HEAVY_RAIN, 0.9999f);
|
||||
isRaining = true;
|
||||
}
|
||||
|
||||
if (ElectricalStorm_Timer <= diff) {
|
||||
Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true);
|
||||
if (!pTarget)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
pTarget->CastSpell(pTarget, 44007, true);//cloud visual
|
||||
DoCast(pTarget, SPELL_ELECTRICAL_STORM, false);//storm cyclon + visual
|
||||
float x,y,z;
|
||||
pTarget->GetPosition(x,y,z);
|
||||
if (pTarget)
|
||||
{
|
||||
pTarget->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING);
|
||||
pTarget->SendMonsterMove(x,y,me->GetPositionZ()+15,0);
|
||||
}
|
||||
Unit *Cloud = me->SummonTrigger(x, y, me->GetPositionZ()+16, 0, 15000);
|
||||
if (Cloud)
|
||||
{
|
||||
CloudGUID = Cloud->GetGUID();
|
||||
Cloud->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING);
|
||||
Cloud->StopMoving();
|
||||
Cloud->SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f);
|
||||
Cloud->setFaction(35);
|
||||
Cloud->SetMaxHealth(9999999);
|
||||
Cloud->SetHealth(9999999);
|
||||
Cloud->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
ElectricalStorm_Timer = 60000; //60 seconds(bosskillers)
|
||||
StormCount = 1;
|
||||
StormSequenceTimer = 0;
|
||||
} else ElectricalStorm_Timer -= diff;
|
||||
|
||||
if (SummonEagles_Timer <= diff)
|
||||
{
|
||||
me->MonsterYell(SAY_ONSUMMON, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_ONSUMMON);
|
||||
|
||||
float x, y, z;
|
||||
me->GetPosition(x, y, z);
|
||||
|
||||
for (uint8 i = 0; i < 8; ++i)
|
||||
{
|
||||
Unit* bird = Unit::GetUnit(*me,BirdGUIDs[i]);
|
||||
if (!bird) //they despawned on die
|
||||
{
|
||||
if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
|
||||
{
|
||||
x = pTarget->GetPositionX() + irand(-10,10);
|
||||
y = pTarget->GetPositionY() + irand(-10,10);
|
||||
z = pTarget->GetPositionZ() + urand(16,20);
|
||||
if (z > 95)
|
||||
z = 95 - urand(0,5);
|
||||
}
|
||||
Creature *pCreature = me->SummonCreature(MOB_SOARING_EAGLE, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
|
||||
if (pCreature)
|
||||
{
|
||||
pCreature->AddThreat(me->getVictim(), 1.0f);
|
||||
pCreature->AI()->AttackStart(me->getVictim());
|
||||
BirdGUIDs[i] = pCreature->GetGUID();
|
||||
}
|
||||
}
|
||||
}
|
||||
SummonEagles_Timer = 999999;
|
||||
} else SummonEagles_Timer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return new boss_akilzonAI(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class mob_akilzon_eagle : public CreatureScript
|
||||
{
|
||||
public:
|
||||
|
||||
mob_akilzon_eagle()
|
||||
: CreatureScript("mob_akilzon_eagle")
|
||||
{
|
||||
}
|
||||
|
||||
struct mob_akilzon_eagleAI : public ScriptedAI
|
||||
{
|
||||
mob_akilzon_eagleAI(Creature *c) : ScriptedAI(c) {}
|
||||
|
||||
uint32 EagleSwoop_Timer;
|
||||
bool arrived;
|
||||
uint32 TargetGUID;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
EagleSwoop_Timer = 5000 + rand()%5000;
|
||||
arrived = true;
|
||||
TargetGUID = 0;
|
||||
me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit * /*who*/) {DoZoneInCombat();}
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/) {}
|
||||
|
||||
void MovementInform(uint32, uint32)
|
||||
{
|
||||
arrived = true;
|
||||
if (TargetGUID)
|
||||
{
|
||||
if (Unit *pTarget = Unit::GetUnit(*me, TargetGUID))
|
||||
DoCast(pTarget, SPELL_EAGLE_SWOOP, true);
|
||||
TargetGUID = 0;
|
||||
me->SetSpeed(MOVE_RUN, 1.2f);
|
||||
EagleSwoop_Timer = 5000 + rand()%5000;
|
||||
}
|
||||
}
|
||||
}
|
||||
++StormCount;
|
||||
if (StormCount > 10)
|
||||
{
|
||||
StormCount = 0; // finish
|
||||
SummonEagles_Timer = 5000;
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
CloudGUID = 0;
|
||||
if (Cloud)
|
||||
Cloud->DealDamage(Cloud, Cloud->GetHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
|
||||
SetWeather(WEATHER_STATE_FINE, 0.0f);
|
||||
isRaining = false;
|
||||
}
|
||||
StormSequenceTimer = 1000;
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (StormCount)
|
||||
{
|
||||
Unit *pTarget = Unit::GetUnit(*me, CloudGUID);
|
||||
if (!pTarget || !pTarget->isAlive())
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
else if (Unit* Cyclone = Unit::GetUnit(*me, CycloneGUID))
|
||||
Cyclone->CastSpell(pTarget, 25160, true); // keep casting or...
|
||||
if (EagleSwoop_Timer <= diff)
|
||||
EagleSwoop_Timer = 0;
|
||||
else
|
||||
EagleSwoop_Timer -= diff;
|
||||
|
||||
if (StormSequenceTimer <= diff)
|
||||
HandleStormSequence(pTarget);
|
||||
else
|
||||
StormSequenceTimer -= diff;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (Enrage_Timer <= diff)
|
||||
{
|
||||
me->MonsterYell(SAY_ONENRAGE, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_ONENRAGE);
|
||||
DoCast(me, SPELL_BERSERK, true);
|
||||
Enrage_Timer = 600000;
|
||||
} else Enrage_Timer -= diff;
|
||||
|
||||
if (StaticDisruption_Timer <= diff)
|
||||
{
|
||||
Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1);
|
||||
if (!pTarget) pTarget = me->getVictim();
|
||||
TargetGUID = pTarget->GetGUID();
|
||||
DoCast(pTarget, SPELL_STATIC_DISRUPTION, false);
|
||||
me->SetInFront(me->getVictim());
|
||||
StaticDisruption_Timer = (10+rand()%8)*1000; // < 20s
|
||||
|
||||
/*if (float dist = me->IsWithinDist3d(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 5.0f) dist = 5.0f;
|
||||
SDisruptAOEVisual_Timer = 1000 + floor(dist / 30 * 1000.0f);*/
|
||||
} else StaticDisruption_Timer -= diff;
|
||||
|
||||
if (GustOfWind_Timer <= diff)
|
||||
{
|
||||
Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1);
|
||||
if (!pTarget) pTarget = me->getVictim();
|
||||
DoCast(pTarget, SPELL_GUST_OF_WIND);
|
||||
GustOfWind_Timer = (20+rand()%10)*1000; //20 to 30 seconds(bosskillers)
|
||||
} else GustOfWind_Timer -= diff;
|
||||
|
||||
if (CallLighting_Timer <= diff)
|
||||
{
|
||||
DoCast(me->getVictim(), SPELL_CALL_LIGHTNING);
|
||||
CallLighting_Timer = (12 + rand()%5)*1000; //totaly random timer. can't find any info on this
|
||||
} else CallLighting_Timer -= diff;
|
||||
|
||||
if (!isRaining && ElectricalStorm_Timer < 8000 + rand()%5000)
|
||||
{
|
||||
SetWeather(WEATHER_STATE_HEAVY_RAIN, 0.9999f);
|
||||
isRaining = true;
|
||||
}
|
||||
|
||||
if (ElectricalStorm_Timer <= diff) {
|
||||
Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true);
|
||||
if (!pTarget)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
pTarget->CastSpell(pTarget, 44007, true);//cloud visual
|
||||
DoCast(pTarget, SPELL_ELECTRICAL_STORM, false);//storm cyclon + visual
|
||||
float x,y,z;
|
||||
pTarget->GetPosition(x,y,z);
|
||||
if (pTarget)
|
||||
{
|
||||
pTarget->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING);
|
||||
pTarget->SendMonsterMove(x,y,me->GetPositionZ()+15,0);
|
||||
}
|
||||
Unit *Cloud = me->SummonTrigger(x, y, me->GetPositionZ()+16, 0, 15000);
|
||||
if (Cloud)
|
||||
{
|
||||
CloudGUID = Cloud->GetGUID();
|
||||
Cloud->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING);
|
||||
Cloud->StopMoving();
|
||||
Cloud->SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f);
|
||||
Cloud->setFaction(35);
|
||||
Cloud->SetMaxHealth(9999999);
|
||||
Cloud->SetHealth(9999999);
|
||||
Cloud->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
ElectricalStorm_Timer = 60000; //60 seconds(bosskillers)
|
||||
StormCount = 1;
|
||||
StormSequenceTimer = 0;
|
||||
} else ElectricalStorm_Timer -= diff;
|
||||
|
||||
if (SummonEagles_Timer <= diff)
|
||||
{
|
||||
me->MonsterYell(SAY_ONSUMMON, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_ONSUMMON);
|
||||
|
||||
float x, y, z;
|
||||
me->GetPosition(x, y, z);
|
||||
|
||||
for (uint8 i = 0; i < 8; ++i)
|
||||
{
|
||||
Unit* bird = Unit::GetUnit(*me,BirdGUIDs[i]);
|
||||
if (!bird) //they despawned on die
|
||||
if (arrived)
|
||||
{
|
||||
if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
|
||||
{
|
||||
x = pTarget->GetPositionX() + irand(-10,10);
|
||||
y = pTarget->GetPositionY() + irand(-10,10);
|
||||
z = pTarget->GetPositionZ() + urand(16,20);
|
||||
if (z > 95)
|
||||
z = 95 - urand(0,5);
|
||||
}
|
||||
Creature *pCreature = me->SummonCreature(MOB_SOARING_EAGLE, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
|
||||
if (pCreature)
|
||||
{
|
||||
pCreature->AddThreat(me->getVictim(), 1.0f);
|
||||
pCreature->AI()->AttackStart(me->getVictim());
|
||||
BirdGUIDs[i] = pCreature->GetGUID();
|
||||
float x, y, z;
|
||||
if (EagleSwoop_Timer)
|
||||
{
|
||||
x = pTarget->GetPositionX() + irand(-10,10);
|
||||
y = pTarget->GetPositionY() + irand(-10,10);
|
||||
z = pTarget->GetPositionZ() + urand(10,15);
|
||||
if (z > 95)
|
||||
z = 95 - urand(0,5);
|
||||
}
|
||||
else
|
||||
{
|
||||
pTarget->GetContactPoint(me, x, y, z);
|
||||
z += 2;
|
||||
me->SetSpeed(MOVE_RUN, 5.0f);
|
||||
TargetGUID = pTarget->GetGUID();
|
||||
}
|
||||
me->GetMotionMaster()->MovePoint(0, x, y, z);
|
||||
arrived = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
SummonEagles_Timer = 999999;
|
||||
} else SummonEagles_Timer -= diff;
|
||||
};
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
struct mob_soaring_eagleAI : public ScriptedAI
|
||||
{
|
||||
mob_soaring_eagleAI(Creature *c) : ScriptedAI(c) {}
|
||||
|
||||
uint32 EagleSwoop_Timer;
|
||||
bool arrived;
|
||||
uint32 TargetGUID;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
EagleSwoop_Timer = 5000 + rand()%5000;
|
||||
arrived = true;
|
||||
TargetGUID = 0;
|
||||
me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit * /*who*/) {DoZoneInCombat();}
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/) {}
|
||||
|
||||
void MovementInform(uint32, uint32)
|
||||
{
|
||||
arrived = true;
|
||||
if (TargetGUID)
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
if (Unit *pTarget = Unit::GetUnit(*me, TargetGUID))
|
||||
DoCast(pTarget, SPELL_EAGLE_SWOOP, true);
|
||||
TargetGUID = 0;
|
||||
me->SetSpeed(MOVE_RUN, 1.2f);
|
||||
EagleSwoop_Timer = 5000 + rand()%5000;
|
||||
return new mob_akilzon_eagleAI(creature);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if (EagleSwoop_Timer <= diff)
|
||||
EagleSwoop_Timer = 0;
|
||||
else
|
||||
EagleSwoop_Timer -= diff;
|
||||
|
||||
if (arrived)
|
||||
{
|
||||
if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
|
||||
{
|
||||
float x, y, z;
|
||||
if (EagleSwoop_Timer)
|
||||
{
|
||||
x = pTarget->GetPositionX() + irand(-10,10);
|
||||
y = pTarget->GetPositionY() + irand(-10,10);
|
||||
z = pTarget->GetPositionZ() + urand(10,15);
|
||||
if (z > 95)
|
||||
z = 95 - urand(0,5);
|
||||
}
|
||||
else
|
||||
{
|
||||
pTarget->GetContactPoint(me, x, y, z);
|
||||
z += 2;
|
||||
me->SetSpeed(MOVE_RUN, 5.0f);
|
||||
TargetGUID = pTarget->GetGUID();
|
||||
}
|
||||
me->GetMotionMaster()->MovePoint(0, x, y, z);
|
||||
arrived = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//Soaring Eagle
|
||||
CreatureAI* GetAI_mob_soaring_eagle(Creature* pCreature)
|
||||
{
|
||||
return new mob_soaring_eagleAI(pCreature);
|
||||
}
|
||||
|
||||
CreatureAI* GetAI_boss_akilzon(Creature* pCreature)
|
||||
{
|
||||
return new boss_akilzonAI(pCreature);
|
||||
}
|
||||
|
||||
void AddSC_boss_akilzon()
|
||||
{
|
||||
Script *newscript = NULL;
|
||||
|
||||
newscript = new Script;
|
||||
newscript->Name = "boss_akilzon";
|
||||
newscript->GetAI = &GetAI_boss_akilzon;
|
||||
newscript->RegisterSelf();
|
||||
|
||||
newscript = new Script;
|
||||
newscript->Name = "mob_akilzon_eagle";
|
||||
newscript->GetAI = &GetAI_mob_soaring_eagle;
|
||||
newscript->RegisterSelf();
|
||||
new boss_akilzon();
|
||||
new mob_akilzon_eagle();
|
||||
}
|
||||
|
||||
|
||||
@@ -73,331 +73,342 @@ enum PhaseHalazzi
|
||||
PHASE_ENRAGE = 5
|
||||
};
|
||||
|
||||
struct boss_halazziAI : public ScriptedAI
|
||||
class boss_halazzi : public CreatureScript
|
||||
{
|
||||
boss_halazziAI(Creature *c) : ScriptedAI(c)
|
||||
{
|
||||
pInstance = c->GetInstanceData();
|
||||
// need to find out what controls totem's spell cooldown
|
||||
SpellEntry *TempSpell = GET_SPELL(SPELL_LIGHTNING);
|
||||
if (TempSpell && TempSpell->CastingTimeIndex != 5)
|
||||
TempSpell->CastingTimeIndex = 5; // 2000 ms casting time
|
||||
}
|
||||
public:
|
||||
|
||||
ScriptedInstance *pInstance;
|
||||
|
||||
uint32 FrenzyTimer;
|
||||
uint32 SaberlashTimer;
|
||||
uint32 ShockTimer;
|
||||
uint32 TotemTimer;
|
||||
uint32 CheckTimer;
|
||||
uint32 BerserkTimer;
|
||||
|
||||
uint32 TransformCount;
|
||||
|
||||
PhaseHalazzi Phase;
|
||||
|
||||
uint64 LynxGUID;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_HALAZZIEVENT, NOT_STARTED);
|
||||
|
||||
TransformCount = 0;
|
||||
BerserkTimer = 600000;
|
||||
CheckTimer = 1000;
|
||||
|
||||
DoCast(me, SPELL_DUAL_WIELD, true);
|
||||
|
||||
Phase = PHASE_NONE;
|
||||
EnterPhase(PHASE_LYNX);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit * /*who*/)
|
||||
{
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_HALAZZIEVENT, IN_PROGRESS);
|
||||
|
||||
me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_AGGRO);
|
||||
|
||||
EnterPhase(PHASE_LYNX);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon)
|
||||
{
|
||||
summon->AI()->AttackStart(me->getVictim());
|
||||
if (summon->GetEntry() == MOB_SPIRIT_LYNX)
|
||||
LynxGUID = summon->GetGUID();
|
||||
}
|
||||
|
||||
void DamageTaken(Unit * /*done_by*/, uint32 &damage)
|
||||
{
|
||||
if (damage >= me->GetHealth() && Phase != PHASE_ENRAGE)
|
||||
damage = 0;
|
||||
}
|
||||
|
||||
void SpellHit(Unit*, const SpellEntry *spell)
|
||||
{
|
||||
if (spell->Id == SPELL_TRANSFORM_SPLIT2)
|
||||
EnterPhase(PHASE_HUMAN);
|
||||
}
|
||||
|
||||
void AttackStart(Unit *who)
|
||||
{
|
||||
if (Phase != PHASE_MERGE) ScriptedAI::AttackStart(who);
|
||||
}
|
||||
|
||||
void EnterPhase(PhaseHalazzi NextPhase)
|
||||
{
|
||||
switch(NextPhase)
|
||||
boss_halazzi()
|
||||
: CreatureScript("boss_halazzi")
|
||||
{
|
||||
case PHASE_LYNX:
|
||||
case PHASE_ENRAGE:
|
||||
if (Phase == PHASE_MERGE)
|
||||
{
|
||||
DoCast(me, SPELL_TRANSFORM_MERGE, true);
|
||||
me->Attack(me->getVictim(), true);
|
||||
me->GetMotionMaster()->MoveChase(me->getVictim());
|
||||
}
|
||||
if (Creature *Lynx = Unit::GetCreature(*me, LynxGUID))
|
||||
Lynx->DisappearAndDie();
|
||||
me->SetMaxHealth(600000);
|
||||
me->SetHealth(600000 - 150000 * TransformCount);
|
||||
FrenzyTimer = 16000;
|
||||
SaberlashTimer = 20000;
|
||||
ShockTimer = 10000;
|
||||
TotemTimer = 12000;
|
||||
break;
|
||||
case PHASE_SPLIT:
|
||||
me->MonsterYell(YELL_SPLIT, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_SPLIT);
|
||||
DoCast(me, SPELL_TRANSFORM_SPLIT, true);
|
||||
break;
|
||||
case PHASE_HUMAN:
|
||||
//DoCast(me, SPELL_SUMMON_LYNX, true);
|
||||
DoSpawnCreature(MOB_SPIRIT_LYNX, 5,5,0,0, TEMPSUMMON_CORPSE_DESPAWN, 0);
|
||||
me->SetMaxHealth(400000);
|
||||
me->SetHealth(400000);
|
||||
ShockTimer = 10000;
|
||||
TotemTimer = 12000;
|
||||
break;
|
||||
case PHASE_MERGE:
|
||||
if (Unit *pLynx = Unit::GetUnit(*me, LynxGUID))
|
||||
{
|
||||
me->MonsterYell(YELL_MERGE, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_MERGE);
|
||||
pLynx->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
|
||||
pLynx->GetMotionMaster()->Clear();
|
||||
pLynx->GetMotionMaster()->MoveFollow(me, 0, 0);
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->GetMotionMaster()->MoveFollow(pLynx, 0, 0);
|
||||
++TransformCount;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Phase = NextPhase;
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (BerserkTimer <= diff)
|
||||
{
|
||||
me->MonsterYell(YELL_BERSERK, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_BERSERK);
|
||||
DoCast(me, SPELL_BERSERK, true);
|
||||
BerserkTimer = 60000;
|
||||
} else BerserkTimer -= diff;
|
||||
|
||||
if (Phase == PHASE_LYNX || Phase == PHASE_ENRAGE)
|
||||
{
|
||||
if (SaberlashTimer <= diff)
|
||||
{
|
||||
// A tank with more than 490 defense skills should receive no critical hit
|
||||
//DoCast(me, 41296, true);
|
||||
DoCast(me->getVictim(), SPELL_SABER_LASH, true);
|
||||
//me->RemoveAurasDueToSpell(41296);
|
||||
SaberlashTimer = 30000;
|
||||
} else SaberlashTimer -= diff;
|
||||
|
||||
if (FrenzyTimer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_FRENZY);
|
||||
FrenzyTimer = urand(10000,15000);
|
||||
} else FrenzyTimer -= diff;
|
||||
|
||||
if (Phase == PHASE_LYNX)
|
||||
if (CheckTimer <= diff)
|
||||
{
|
||||
if (me->GetHealth() * 4 < me->GetMaxHealth() * (3 - TransformCount))
|
||||
EnterPhase(PHASE_SPLIT);
|
||||
CheckTimer = 1000;
|
||||
} else CheckTimer -= diff;
|
||||
}
|
||||
|
||||
if (Phase == PHASE_HUMAN || Phase == PHASE_ENRAGE)
|
||||
struct boss_halazziAI : public ScriptedAI
|
||||
{
|
||||
if (TotemTimer <= diff)
|
||||
boss_halazziAI(Creature *c) : ScriptedAI(c)
|
||||
{
|
||||
DoCast(me, SPELL_SUMMON_TOTEM);
|
||||
TotemTimer = 20000;
|
||||
} else TotemTimer -= diff;
|
||||
pInstance = c->GetInstanceData();
|
||||
// need to find out what controls totem's spell cooldown
|
||||
SpellEntry *TempSpell = GET_SPELL(SPELL_LIGHTNING);
|
||||
if (TempSpell && TempSpell->CastingTimeIndex != 5)
|
||||
TempSpell->CastingTimeIndex = 5; // 2000 ms casting time
|
||||
}
|
||||
|
||||
if (ShockTimer <= diff)
|
||||
ScriptedInstance *pInstance;
|
||||
|
||||
uint32 FrenzyTimer;
|
||||
uint32 SaberlashTimer;
|
||||
uint32 ShockTimer;
|
||||
uint32 TotemTimer;
|
||||
uint32 CheckTimer;
|
||||
uint32 BerserkTimer;
|
||||
|
||||
uint32 TransformCount;
|
||||
|
||||
PhaseHalazzi Phase;
|
||||
|
||||
uint64 LynxGUID;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0))
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_HALAZZIEVENT, NOT_STARTED);
|
||||
|
||||
TransformCount = 0;
|
||||
BerserkTimer = 600000;
|
||||
CheckTimer = 1000;
|
||||
|
||||
DoCast(me, SPELL_DUAL_WIELD, true);
|
||||
|
||||
Phase = PHASE_NONE;
|
||||
EnterPhase(PHASE_LYNX);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit * /*who*/)
|
||||
{
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_HALAZZIEVENT, IN_PROGRESS);
|
||||
|
||||
me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_AGGRO);
|
||||
|
||||
EnterPhase(PHASE_LYNX);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon)
|
||||
{
|
||||
summon->AI()->AttackStart(me->getVictim());
|
||||
if (summon->GetEntry() == MOB_SPIRIT_LYNX)
|
||||
LynxGUID = summon->GetGUID();
|
||||
}
|
||||
|
||||
void DamageTaken(Unit * /*done_by*/, uint32 &damage)
|
||||
{
|
||||
if (damage >= me->GetHealth() && Phase != PHASE_ENRAGE)
|
||||
damage = 0;
|
||||
}
|
||||
|
||||
void SpellHit(Unit*, const SpellEntry *spell)
|
||||
{
|
||||
if (spell->Id == SPELL_TRANSFORM_SPLIT2)
|
||||
EnterPhase(PHASE_HUMAN);
|
||||
}
|
||||
|
||||
void AttackStart(Unit *who)
|
||||
{
|
||||
if (Phase != PHASE_MERGE) ScriptedAI::AttackStart(who);
|
||||
}
|
||||
|
||||
void EnterPhase(PhaseHalazzi NextPhase)
|
||||
{
|
||||
switch(NextPhase)
|
||||
{
|
||||
if (pTarget->IsNonMeleeSpellCasted(false))
|
||||
DoCast(pTarget, SPELL_EARTHSHOCK);
|
||||
else
|
||||
DoCast(pTarget, SPELL_FLAMESHOCK);
|
||||
ShockTimer = 10000 + rand()%5000;
|
||||
case PHASE_LYNX:
|
||||
case PHASE_ENRAGE:
|
||||
if (Phase == PHASE_MERGE)
|
||||
{
|
||||
DoCast(me, SPELL_TRANSFORM_MERGE, true);
|
||||
me->Attack(me->getVictim(), true);
|
||||
me->GetMotionMaster()->MoveChase(me->getVictim());
|
||||
}
|
||||
if (Creature *Lynx = Unit::GetCreature(*me, LynxGUID))
|
||||
Lynx->DisappearAndDie();
|
||||
me->SetMaxHealth(600000);
|
||||
me->SetHealth(600000 - 150000 * TransformCount);
|
||||
FrenzyTimer = 16000;
|
||||
SaberlashTimer = 20000;
|
||||
ShockTimer = 10000;
|
||||
TotemTimer = 12000;
|
||||
break;
|
||||
case PHASE_SPLIT:
|
||||
me->MonsterYell(YELL_SPLIT, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_SPLIT);
|
||||
DoCast(me, SPELL_TRANSFORM_SPLIT, true);
|
||||
break;
|
||||
case PHASE_HUMAN:
|
||||
//DoCast(me, SPELL_SUMMON_LYNX, true);
|
||||
DoSpawnCreature(MOB_SPIRIT_LYNX, 5,5,0,0, TEMPSUMMON_CORPSE_DESPAWN, 0);
|
||||
me->SetMaxHealth(400000);
|
||||
me->SetHealth(400000);
|
||||
ShockTimer = 10000;
|
||||
TotemTimer = 12000;
|
||||
break;
|
||||
case PHASE_MERGE:
|
||||
if (Unit *pLynx = Unit::GetUnit(*me, LynxGUID))
|
||||
{
|
||||
me->MonsterYell(YELL_MERGE, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_MERGE);
|
||||
pLynx->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
|
||||
pLynx->GetMotionMaster()->Clear();
|
||||
pLynx->GetMotionMaster()->MoveFollow(me, 0, 0);
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->GetMotionMaster()->MoveFollow(pLynx, 0, 0);
|
||||
++TransformCount;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else ShockTimer -= diff;
|
||||
Phase = NextPhase;
|
||||
}
|
||||
|
||||
if (Phase == PHASE_HUMAN)
|
||||
if (CheckTimer <= diff)
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (BerserkTimer <= diff)
|
||||
{
|
||||
if (((me->GetHealth()*100) / me->GetMaxHealth() <= 20)/*me->GetHealth() * 10 < me->GetMaxHealth()*/)
|
||||
EnterPhase(PHASE_MERGE);
|
||||
else
|
||||
me->MonsterYell(YELL_BERSERK, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_BERSERK);
|
||||
DoCast(me, SPELL_BERSERK, true);
|
||||
BerserkTimer = 60000;
|
||||
} else BerserkTimer -= diff;
|
||||
|
||||
if (Phase == PHASE_LYNX || Phase == PHASE_ENRAGE)
|
||||
{
|
||||
if (SaberlashTimer <= diff)
|
||||
{
|
||||
// A tank with more than 490 defense skills should receive no critical hit
|
||||
//DoCast(me, 41296, true);
|
||||
DoCast(me->getVictim(), SPELL_SABER_LASH, true);
|
||||
//me->RemoveAurasDueToSpell(41296);
|
||||
SaberlashTimer = 30000;
|
||||
} else SaberlashTimer -= diff;
|
||||
|
||||
if (FrenzyTimer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_FRENZY);
|
||||
FrenzyTimer = urand(10000,15000);
|
||||
} else FrenzyTimer -= diff;
|
||||
|
||||
if (Phase == PHASE_LYNX)
|
||||
if (CheckTimer <= diff)
|
||||
{
|
||||
if (me->GetHealth() * 4 < me->GetMaxHealth() * (3 - TransformCount))
|
||||
EnterPhase(PHASE_SPLIT);
|
||||
CheckTimer = 1000;
|
||||
} else CheckTimer -= diff;
|
||||
}
|
||||
|
||||
if (Phase == PHASE_HUMAN || Phase == PHASE_ENRAGE)
|
||||
{
|
||||
if (TotemTimer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_SUMMON_TOTEM);
|
||||
TotemTimer = 20000;
|
||||
} else TotemTimer -= diff;
|
||||
|
||||
if (ShockTimer <= diff)
|
||||
{
|
||||
if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0))
|
||||
{
|
||||
if (pTarget->IsNonMeleeSpellCasted(false))
|
||||
DoCast(pTarget, SPELL_EARTHSHOCK);
|
||||
else
|
||||
DoCast(pTarget, SPELL_FLAMESHOCK);
|
||||
ShockTimer = 10000 + rand()%5000;
|
||||
}
|
||||
} else ShockTimer -= diff;
|
||||
|
||||
if (Phase == PHASE_HUMAN)
|
||||
if (CheckTimer <= diff)
|
||||
{
|
||||
if (((me->GetHealth()*100) / me->GetMaxHealth() <= 20)/*me->GetHealth() * 10 < me->GetMaxHealth()*/)
|
||||
EnterPhase(PHASE_MERGE);
|
||||
else
|
||||
{
|
||||
Unit *Lynx = Unit::GetUnit(*me, LynxGUID);
|
||||
if (Lynx && ((Lynx->GetHealth()*100) / Lynx->GetMaxHealth() <= 20)/*Lynx->GetHealth() * 10 < Lynx->GetMaxHealth()*/)
|
||||
EnterPhase(PHASE_MERGE);
|
||||
}
|
||||
CheckTimer = 1000;
|
||||
} else CheckTimer -= diff;
|
||||
}
|
||||
|
||||
if (Phase == PHASE_MERGE)
|
||||
{
|
||||
if (CheckTimer <= diff)
|
||||
{
|
||||
Unit *Lynx = Unit::GetUnit(*me, LynxGUID);
|
||||
if (Lynx && ((Lynx->GetHealth()*100) / Lynx->GetMaxHealth() <= 20)/*Lynx->GetHealth() * 10 < Lynx->GetMaxHealth()*/)
|
||||
EnterPhase(PHASE_MERGE);
|
||||
}
|
||||
CheckTimer = 1000;
|
||||
} else CheckTimer -= diff;
|
||||
}
|
||||
|
||||
if (Phase == PHASE_MERGE)
|
||||
{
|
||||
if (CheckTimer <= diff)
|
||||
{
|
||||
Unit *Lynx = Unit::GetUnit(*me, LynxGUID);
|
||||
if (Lynx)
|
||||
{
|
||||
Lynx->GetMotionMaster()->MoveFollow(me, 0, 0);
|
||||
me->GetMotionMaster()->MoveFollow(Lynx, 0, 0);
|
||||
if (me->IsWithinDistInMap(Lynx, 6.0f))
|
||||
{
|
||||
if (TransformCount < 3)
|
||||
EnterPhase(PHASE_LYNX);
|
||||
else
|
||||
EnterPhase(PHASE_ENRAGE);
|
||||
}
|
||||
if (Lynx)
|
||||
{
|
||||
Lynx->GetMotionMaster()->MoveFollow(me, 0, 0);
|
||||
me->GetMotionMaster()->MoveFollow(Lynx, 0, 0);
|
||||
if (me->IsWithinDistInMap(Lynx, 6.0f))
|
||||
{
|
||||
if (TransformCount < 3)
|
||||
EnterPhase(PHASE_LYNX);
|
||||
else
|
||||
EnterPhase(PHASE_ENRAGE);
|
||||
}
|
||||
}
|
||||
CheckTimer = 1000;
|
||||
} else CheckTimer -= diff;
|
||||
}
|
||||
CheckTimer = 1000;
|
||||
} else CheckTimer -= diff;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/)
|
||||
{
|
||||
switch (urand(0,1))
|
||||
void KilledUnit(Unit* /*victim*/)
|
||||
{
|
||||
switch (urand(0,1))
|
||||
{
|
||||
case 0:
|
||||
me->MonsterYell(YELL_KILL_ONE, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_KILL_ONE);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
me->MonsterYell(YELL_KILL_TWO, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_KILL_TWO);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*Killer*/)
|
||||
{
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_HALAZZIEVENT, DONE);
|
||||
|
||||
me->MonsterYell(YELL_DEATH, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_DEATH);
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
case 0:
|
||||
me->MonsterYell(YELL_KILL_ONE, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_KILL_ONE);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
me->MonsterYell(YELL_KILL_TWO, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_KILL_TWO);
|
||||
break;
|
||||
return new boss_halazziAI(creature);
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*Killer*/)
|
||||
{
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_HALAZZIEVENT, DONE);
|
||||
|
||||
me->MonsterYell(YELL_DEATH, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_DEATH);
|
||||
}
|
||||
};
|
||||
|
||||
// Spirits Lynx AI
|
||||
|
||||
struct boss_spiritlynxAI : public ScriptedAI
|
||||
class mob_halazzi_lynx : public CreatureScript
|
||||
{
|
||||
boss_spiritlynxAI(Creature *c) : ScriptedAI(c) {}
|
||||
public:
|
||||
|
||||
uint32 FrenzyTimer;
|
||||
uint32 shredder_timer;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
FrenzyTimer = urand(30000,50000); //frenzy every 30-50 seconds
|
||||
shredder_timer = 4000;
|
||||
}
|
||||
|
||||
void DamageTaken(Unit * /*done_by*/, uint32 &damage)
|
||||
{
|
||||
if (damage >= me->GetHealth())
|
||||
damage = 0;
|
||||
}
|
||||
|
||||
void AttackStart(Unit *who)
|
||||
{
|
||||
if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
|
||||
ScriptedAI::AttackStart(who);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit * /*who*/) {/*DoZoneInCombat();*/}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (FrenzyTimer <= diff)
|
||||
mob_halazzi_lynx()
|
||||
: CreatureScript("mob_halazzi_lynx")
|
||||
{
|
||||
DoCast(me, SPELL_LYNX_FRENZY);
|
||||
FrenzyTimer = urand(30000,50000); //frenzy every 30-50 seconds
|
||||
} else FrenzyTimer -= diff;
|
||||
}
|
||||
|
||||
if (shredder_timer <= diff)
|
||||
struct mob_halazzi_lynxAI : public ScriptedAI
|
||||
{
|
||||
DoCast(me->getVictim(), SPELL_SHRED_ARMOR);
|
||||
shredder_timer = 4000;
|
||||
} else shredder_timer -= diff;
|
||||
mob_halazzi_lynxAI(Creature *c) : ScriptedAI(c) {}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
uint32 FrenzyTimer;
|
||||
uint32 shredder_timer;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
FrenzyTimer = urand(30000,50000); //frenzy every 30-50 seconds
|
||||
shredder_timer = 4000;
|
||||
}
|
||||
|
||||
void DamageTaken(Unit * /*done_by*/, uint32 &damage)
|
||||
{
|
||||
if (damage >= me->GetHealth())
|
||||
damage = 0;
|
||||
}
|
||||
|
||||
void AttackStart(Unit *who)
|
||||
{
|
||||
if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
|
||||
ScriptedAI::AttackStart(who);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit * /*who*/) {/*DoZoneInCombat();*/}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (FrenzyTimer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_LYNX_FRENZY);
|
||||
FrenzyTimer = urand(30000,50000); //frenzy every 30-50 seconds
|
||||
} else FrenzyTimer -= diff;
|
||||
|
||||
if (shredder_timer <= diff)
|
||||
{
|
||||
DoCast(me->getVictim(), SPELL_SHRED_ARMOR);
|
||||
shredder_timer = 4000;
|
||||
} else shredder_timer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return new mob_halazzi_lynxAI(creature);
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI_boss_halazziAI(Creature* pCreature)
|
||||
{
|
||||
return new boss_halazziAI (pCreature);
|
||||
}
|
||||
|
||||
CreatureAI* GetAI_boss_spiritlynxAI(Creature* pCreature)
|
||||
{
|
||||
return new boss_spiritlynxAI (pCreature);
|
||||
}
|
||||
|
||||
void AddSC_boss_halazzi()
|
||||
{
|
||||
Script *newscript;
|
||||
newscript = new Script;
|
||||
newscript->Name = "boss_halazzi";
|
||||
newscript->GetAI = &GetAI_boss_halazziAI;
|
||||
newscript->RegisterSelf();
|
||||
|
||||
newscript = new Script;
|
||||
newscript->Name = "mob_halazzi_lynx";
|
||||
newscript->GetAI = &GetAI_boss_spiritlynxAI;
|
||||
newscript->RegisterSelf();
|
||||
new boss_halazzi();
|
||||
new mob_halazzi_lynx();
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -90,364 +90,371 @@ float NalorakkWay[8][3] =
|
||||
#define YELL_SHIFTEDTOBEAR "You call on da beast, you gonna get more dan you bargain for!"
|
||||
#define SOUND_YELL_TOBEAR 12072
|
||||
|
||||
struct boss_nalorakkAI : public ScriptedAI
|
||||
class boss_nalorakk : public CreatureScript
|
||||
{
|
||||
boss_nalorakkAI(Creature *c) : ScriptedAI(c)
|
||||
{
|
||||
MoveEvent = true;
|
||||
MovePhase = 0;
|
||||
pInstance = c->GetInstanceData();
|
||||
}
|
||||
public:
|
||||
|
||||
ScriptedInstance *pInstance;
|
||||
|
||||
uint32 BrutalSwipe_Timer;
|
||||
uint32 Mangle_Timer;
|
||||
uint32 Surge_Timer;
|
||||
|
||||
uint32 LaceratingSlash_Timer;
|
||||
uint32 RendFlesh_Timer;
|
||||
uint32 DeafeningRoar_Timer;
|
||||
|
||||
uint32 ShapeShift_Timer;
|
||||
uint32 Berserk_Timer;
|
||||
|
||||
bool inBearForm;
|
||||
bool MoveEvent;
|
||||
bool inMove;
|
||||
uint32 MovePhase;
|
||||
uint32 waitTimer;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
if (MoveEvent)
|
||||
boss_nalorakk()
|
||||
: CreatureScript("boss_nalorakk")
|
||||
{
|
||||
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
|
||||
inMove = false;
|
||||
waitTimer = 0;
|
||||
me->SetSpeed(MOVE_RUN,2);
|
||||
me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
}else
|
||||
{
|
||||
(*me).GetMotionMaster()->MovePoint(0,NalorakkWay[7][0],NalorakkWay[7][1],NalorakkWay[7][2]);
|
||||
}
|
||||
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_NALORAKKEVENT, NOT_STARTED);
|
||||
|
||||
Surge_Timer = 15000 + rand()%5000;
|
||||
BrutalSwipe_Timer = 7000 + rand()%5000;
|
||||
Mangle_Timer = 10000 + rand()%5000;
|
||||
ShapeShift_Timer = 45000 + rand()%5000;
|
||||
Berserk_Timer = 600000;
|
||||
|
||||
inBearForm = false;
|
||||
// me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 5122); // TODO: find the correct equipment id
|
||||
}
|
||||
|
||||
void SendAttacker(Unit *pTarget)
|
||||
{
|
||||
std::list<Creature*> templist;
|
||||
float x, y, z;
|
||||
me->GetPosition(x, y, z);
|
||||
|
||||
struct boss_nalorakkAI : public ScriptedAI
|
||||
{
|
||||
CellPair pair(Trinity::ComputeCellPair(x, y));
|
||||
Cell cell(pair);
|
||||
cell.data.Part.reserved = ALL_DISTRICT;
|
||||
cell.SetNoCreate();
|
||||
|
||||
Trinity::AllFriendlyCreaturesInGrid check(me);
|
||||
Trinity::CreatureListSearcher<Trinity::AllFriendlyCreaturesInGrid> searcher(me, templist, check);
|
||||
|
||||
TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AllFriendlyCreaturesInGrid>, GridTypeMapContainer> cSearcher(searcher);
|
||||
|
||||
cell.Visit(pair, cSearcher, *(me->GetMap()));
|
||||
}
|
||||
|
||||
if (!templist.size())
|
||||
return;
|
||||
|
||||
for (std::list<Creature*>::const_iterator i = templist.begin(); i != templist.end(); ++i)
|
||||
{
|
||||
if ((*i) && me->IsWithinDistInMap((*i),25))
|
||||
boss_nalorakkAI(Creature *c) : ScriptedAI(c)
|
||||
{
|
||||
(*i)->SetNoCallAssistance(true);
|
||||
(*i)->AI()->AttackStart(pTarget);
|
||||
MoveEvent = true;
|
||||
MovePhase = 0;
|
||||
pInstance = c->GetInstanceData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who)
|
||||
{
|
||||
if (!MoveEvent)
|
||||
ScriptedAI::AttackStart(who);
|
||||
}
|
||||
ScriptedInstance *pInstance;
|
||||
|
||||
void MoveInLineOfSight(Unit *who)
|
||||
{
|
||||
if (!MoveEvent)
|
||||
{
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (me->IsHostileTo(who))
|
||||
uint32 BrutalSwipe_Timer;
|
||||
uint32 Mangle_Timer;
|
||||
uint32 Surge_Timer;
|
||||
|
||||
uint32 LaceratingSlash_Timer;
|
||||
uint32 RendFlesh_Timer;
|
||||
uint32 DeafeningRoar_Timer;
|
||||
|
||||
uint32 ShapeShift_Timer;
|
||||
uint32 Berserk_Timer;
|
||||
|
||||
bool inBearForm;
|
||||
bool MoveEvent;
|
||||
bool inMove;
|
||||
uint32 MovePhase;
|
||||
uint32 waitTimer;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
if (!inMove)
|
||||
if (MoveEvent)
|
||||
{
|
||||
switch(MovePhase)
|
||||
{
|
||||
case 0:
|
||||
if (me->IsWithinDistInMap(who, 50))
|
||||
{
|
||||
me->MonsterYell(YELL_NALORAKK_WAVE1, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE1);
|
||||
|
||||
(*me).GetMotionMaster()->MovePoint(1,NalorakkWay[1][0],NalorakkWay[1][1],NalorakkWay[1][2]);
|
||||
MovePhase ++;
|
||||
inMove = true;
|
||||
|
||||
SendAttacker(who);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (me->IsWithinDistInMap(who, 40))
|
||||
{
|
||||
me->MonsterYell(YELL_NALORAKK_WAVE2, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE2);
|
||||
|
||||
(*me).GetMotionMaster()->MovePoint(3,NalorakkWay[3][0],NalorakkWay[3][1],NalorakkWay[3][2]);
|
||||
MovePhase ++;
|
||||
inMove = true;
|
||||
|
||||
SendAttacker(who);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (me->IsWithinDistInMap(who, 40))
|
||||
{
|
||||
me->MonsterYell(YELL_NALORAKK_WAVE3, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE3);
|
||||
|
||||
(*me).GetMotionMaster()->MovePoint(6,NalorakkWay[6][0],NalorakkWay[6][1],NalorakkWay[6][2]);
|
||||
MovePhase ++;
|
||||
inMove = true;
|
||||
|
||||
SendAttacker(who);
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
if (me->IsWithinDistInMap(who, 50))
|
||||
{
|
||||
SendAttacker(who);
|
||||
|
||||
me->MonsterYell(YELL_NALORAKK_WAVE4, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE4);
|
||||
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
|
||||
|
||||
MoveEvent = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EnterCombat(Unit * /*who*/)
|
||||
{
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_NALORAKKEVENT, IN_PROGRESS);
|
||||
|
||||
me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_YELL_AGGRO);
|
||||
DoZoneInCombat();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*Killer*/)
|
||||
{
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_NALORAKKEVENT, DONE);
|
||||
|
||||
me->MonsterYell(YELL_DEATH,LANG_UNIVERSAL,NULL);
|
||||
DoPlaySoundToSet(me, SOUND_YELL_DEATH);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/)
|
||||
{
|
||||
switch (urand(0,1))
|
||||
{
|
||||
case 0:
|
||||
me->MonsterYell(YELL_KILL_ONE, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_YELL_KILL_ONE);
|
||||
break;
|
||||
case 1:
|
||||
me->MonsterYell(YELL_KILL_TWO, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_YELL_KILL_TWO);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id)
|
||||
{
|
||||
if (MoveEvent)
|
||||
{
|
||||
if (type != POINT_MOTION_TYPE)
|
||||
return;
|
||||
|
||||
if (!inMove)
|
||||
return;
|
||||
|
||||
if (MovePhase != id)
|
||||
return;
|
||||
|
||||
switch(MovePhase)
|
||||
{
|
||||
case 2:
|
||||
me->SetOrientation(3.1415*2);
|
||||
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
|
||||
inMove = false;
|
||||
return;
|
||||
case 1:
|
||||
case 3:
|
||||
case 4:
|
||||
case 6:
|
||||
MovePhase ++;
|
||||
waitTimer = 1;
|
||||
inMove = true;
|
||||
return;
|
||||
case 5:
|
||||
me->SetOrientation(3.1415*0.5);
|
||||
inMove = false;
|
||||
return;
|
||||
case 7:
|
||||
me->SetOrientation(3.1415*0.5);
|
||||
inMove = false;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if (waitTimer)
|
||||
{
|
||||
if (inMove)
|
||||
if (waitTimer <= diff)
|
||||
{
|
||||
(*me).GetMotionMaster()->MovementExpired();
|
||||
(*me).GetMotionMaster()->MovePoint(MovePhase,NalorakkWay[MovePhase][0],NalorakkWay[MovePhase][1],NalorakkWay[MovePhase][2]);
|
||||
waitTimer = 0;
|
||||
} else waitTimer -= diff;
|
||||
}
|
||||
me->SetSpeed(MOVE_RUN,2);
|
||||
me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
}else
|
||||
{
|
||||
(*me).GetMotionMaster()->MovePoint(0,NalorakkWay[7][0],NalorakkWay[7][1],NalorakkWay[7][2]);
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_NALORAKKEVENT, NOT_STARTED);
|
||||
|
||||
if (Berserk_Timer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_BERSERK, true);
|
||||
me->MonsterYell(YELL_BERSERK, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_YELL_BERSERK);
|
||||
Berserk_Timer = 600000;
|
||||
} else Berserk_Timer -= diff;
|
||||
|
||||
if (ShapeShift_Timer <= diff)
|
||||
{
|
||||
if (inBearForm)
|
||||
{
|
||||
// me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 5122);
|
||||
me->MonsterYell(YELL_SHIFTEDTOTROLL, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_YELL_TOTROLL);
|
||||
me->RemoveAurasDueToSpell(SPELL_BEARFORM);
|
||||
Surge_Timer = 15000 + rand()%5000;
|
||||
BrutalSwipe_Timer = 7000 + rand()%5000;
|
||||
Mangle_Timer = 10000 + rand()%5000;
|
||||
ShapeShift_Timer = 45000 + rand()%5000;
|
||||
Berserk_Timer = 600000;
|
||||
|
||||
inBearForm = false;
|
||||
// me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 5122); // TODO: find the correct equipment id
|
||||
}
|
||||
else
|
||||
{
|
||||
// me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 0);
|
||||
me->MonsterYell(YELL_SHIFTEDTOBEAR, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_YELL_TOBEAR);
|
||||
DoCast(me, SPELL_BEARFORM, true);
|
||||
LaceratingSlash_Timer = 2000; // dur 18s
|
||||
RendFlesh_Timer = 3000; // dur 5s
|
||||
DeafeningRoar_Timer = 5000 + rand()%5000; // dur 2s
|
||||
ShapeShift_Timer = 20000 + rand()%5000; // dur 30s
|
||||
inBearForm = true;
|
||||
}
|
||||
} else ShapeShift_Timer -= diff;
|
||||
|
||||
if (!inBearForm)
|
||||
{
|
||||
if (BrutalSwipe_Timer <= diff)
|
||||
void SendAttacker(Unit *pTarget)
|
||||
{
|
||||
DoCast(me->getVictim(), SPELL_BRUTALSWIPE);
|
||||
BrutalSwipe_Timer = 7000 + rand()%5000;
|
||||
} else BrutalSwipe_Timer -= diff;
|
||||
std::list<Creature*> templist;
|
||||
float x, y, z;
|
||||
me->GetPosition(x, y, z);
|
||||
|
||||
if (Mangle_Timer <= diff)
|
||||
{
|
||||
if (me->getVictim() && !me->getVictim()->HasAura(SPELL_MANGLEEFFECT))
|
||||
{
|
||||
DoCast(me->getVictim(), SPELL_MANGLE);
|
||||
Mangle_Timer = 1000;
|
||||
CellPair pair(Trinity::ComputeCellPair(x, y));
|
||||
Cell cell(pair);
|
||||
cell.data.Part.reserved = ALL_DISTRICT;
|
||||
cell.SetNoCreate();
|
||||
|
||||
Trinity::AllFriendlyCreaturesInGrid check(me);
|
||||
Trinity::CreatureListSearcher<Trinity::AllFriendlyCreaturesInGrid> searcher(me, templist, check);
|
||||
|
||||
TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AllFriendlyCreaturesInGrid>, GridTypeMapContainer> cSearcher(searcher);
|
||||
|
||||
cell.Visit(pair, cSearcher, *(me->GetMap()));
|
||||
}
|
||||
else Mangle_Timer = 10000 + rand()%5000;
|
||||
} else Mangle_Timer -= diff;
|
||||
|
||||
if (Surge_Timer <= diff)
|
||||
if (!templist.size())
|
||||
return;
|
||||
|
||||
for (std::list<Creature*>::const_iterator i = templist.begin(); i != templist.end(); ++i)
|
||||
{
|
||||
if ((*i) && me->IsWithinDistInMap((*i),25))
|
||||
{
|
||||
(*i)->SetNoCallAssistance(true);
|
||||
(*i)->AI()->AttackStart(pTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who)
|
||||
{
|
||||
me->MonsterYell(YELL_SURGE, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_YELL_SURGE);
|
||||
Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 45, true);
|
||||
if (pTarget)
|
||||
DoCast(pTarget, SPELL_SURGE);
|
||||
Surge_Timer = 15000 + rand()%5000;
|
||||
} else Surge_Timer -= diff;
|
||||
}
|
||||
else
|
||||
if (!MoveEvent)
|
||||
ScriptedAI::AttackStart(who);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit *who)
|
||||
{
|
||||
if (!MoveEvent)
|
||||
{
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (me->IsHostileTo(who))
|
||||
{
|
||||
if (!inMove)
|
||||
{
|
||||
switch(MovePhase)
|
||||
{
|
||||
case 0:
|
||||
if (me->IsWithinDistInMap(who, 50))
|
||||
{
|
||||
me->MonsterYell(YELL_NALORAKK_WAVE1, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE1);
|
||||
|
||||
(*me).GetMotionMaster()->MovePoint(1,NalorakkWay[1][0],NalorakkWay[1][1],NalorakkWay[1][2]);
|
||||
MovePhase ++;
|
||||
inMove = true;
|
||||
|
||||
SendAttacker(who);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (me->IsWithinDistInMap(who, 40))
|
||||
{
|
||||
me->MonsterYell(YELL_NALORAKK_WAVE2, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE2);
|
||||
|
||||
(*me).GetMotionMaster()->MovePoint(3,NalorakkWay[3][0],NalorakkWay[3][1],NalorakkWay[3][2]);
|
||||
MovePhase ++;
|
||||
inMove = true;
|
||||
|
||||
SendAttacker(who);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (me->IsWithinDistInMap(who, 40))
|
||||
{
|
||||
me->MonsterYell(YELL_NALORAKK_WAVE3, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE3);
|
||||
|
||||
(*me).GetMotionMaster()->MovePoint(6,NalorakkWay[6][0],NalorakkWay[6][1],NalorakkWay[6][2]);
|
||||
MovePhase ++;
|
||||
inMove = true;
|
||||
|
||||
SendAttacker(who);
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
if (me->IsWithinDistInMap(who, 50))
|
||||
{
|
||||
SendAttacker(who);
|
||||
|
||||
me->MonsterYell(YELL_NALORAKK_WAVE4, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE4);
|
||||
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
|
||||
|
||||
MoveEvent = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EnterCombat(Unit * /*who*/)
|
||||
{
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_NALORAKKEVENT, IN_PROGRESS);
|
||||
|
||||
me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_YELL_AGGRO);
|
||||
DoZoneInCombat();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*Killer*/)
|
||||
{
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_NALORAKKEVENT, DONE);
|
||||
|
||||
me->MonsterYell(YELL_DEATH,LANG_UNIVERSAL,NULL);
|
||||
DoPlaySoundToSet(me, SOUND_YELL_DEATH);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/)
|
||||
{
|
||||
switch (urand(0,1))
|
||||
{
|
||||
case 0:
|
||||
me->MonsterYell(YELL_KILL_ONE, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_YELL_KILL_ONE);
|
||||
break;
|
||||
case 1:
|
||||
me->MonsterYell(YELL_KILL_TWO, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_YELL_KILL_TWO);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id)
|
||||
{
|
||||
if (MoveEvent)
|
||||
{
|
||||
if (type != POINT_MOTION_TYPE)
|
||||
return;
|
||||
|
||||
if (!inMove)
|
||||
return;
|
||||
|
||||
if (MovePhase != id)
|
||||
return;
|
||||
|
||||
switch(MovePhase)
|
||||
{
|
||||
case 2:
|
||||
me->SetOrientation(3.1415*2);
|
||||
inMove = false;
|
||||
return;
|
||||
case 1:
|
||||
case 3:
|
||||
case 4:
|
||||
case 6:
|
||||
MovePhase ++;
|
||||
waitTimer = 1;
|
||||
inMove = true;
|
||||
return;
|
||||
case 5:
|
||||
me->SetOrientation(3.1415*0.5);
|
||||
inMove = false;
|
||||
return;
|
||||
case 7:
|
||||
me->SetOrientation(3.1415*0.5);
|
||||
inMove = false;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if (waitTimer)
|
||||
{
|
||||
if (inMove)
|
||||
if (waitTimer <= diff)
|
||||
{
|
||||
(*me).GetMotionMaster()->MovementExpired();
|
||||
(*me).GetMotionMaster()->MovePoint(MovePhase,NalorakkWay[MovePhase][0],NalorakkWay[MovePhase][1],NalorakkWay[MovePhase][2]);
|
||||
waitTimer = 0;
|
||||
} else waitTimer -= diff;
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (Berserk_Timer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_BERSERK, true);
|
||||
me->MonsterYell(YELL_BERSERK, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_YELL_BERSERK);
|
||||
Berserk_Timer = 600000;
|
||||
} else Berserk_Timer -= diff;
|
||||
|
||||
if (ShapeShift_Timer <= diff)
|
||||
{
|
||||
if (inBearForm)
|
||||
{
|
||||
// me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 5122);
|
||||
me->MonsterYell(YELL_SHIFTEDTOTROLL, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_YELL_TOTROLL);
|
||||
me->RemoveAurasDueToSpell(SPELL_BEARFORM);
|
||||
Surge_Timer = 15000 + rand()%5000;
|
||||
BrutalSwipe_Timer = 7000 + rand()%5000;
|
||||
Mangle_Timer = 10000 + rand()%5000;
|
||||
ShapeShift_Timer = 45000 + rand()%5000;
|
||||
inBearForm = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 0);
|
||||
me->MonsterYell(YELL_SHIFTEDTOBEAR, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_YELL_TOBEAR);
|
||||
DoCast(me, SPELL_BEARFORM, true);
|
||||
LaceratingSlash_Timer = 2000; // dur 18s
|
||||
RendFlesh_Timer = 3000; // dur 5s
|
||||
DeafeningRoar_Timer = 5000 + rand()%5000; // dur 2s
|
||||
ShapeShift_Timer = 20000 + rand()%5000; // dur 30s
|
||||
inBearForm = true;
|
||||
}
|
||||
} else ShapeShift_Timer -= diff;
|
||||
|
||||
if (!inBearForm)
|
||||
{
|
||||
if (BrutalSwipe_Timer <= diff)
|
||||
{
|
||||
DoCast(me->getVictim(), SPELL_BRUTALSWIPE);
|
||||
BrutalSwipe_Timer = 7000 + rand()%5000;
|
||||
} else BrutalSwipe_Timer -= diff;
|
||||
|
||||
if (Mangle_Timer <= diff)
|
||||
{
|
||||
if (me->getVictim() && !me->getVictim()->HasAura(SPELL_MANGLEEFFECT))
|
||||
{
|
||||
DoCast(me->getVictim(), SPELL_MANGLE);
|
||||
Mangle_Timer = 1000;
|
||||
}
|
||||
else Mangle_Timer = 10000 + rand()%5000;
|
||||
} else Mangle_Timer -= diff;
|
||||
|
||||
if (Surge_Timer <= diff)
|
||||
{
|
||||
me->MonsterYell(YELL_SURGE, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_YELL_SURGE);
|
||||
Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 45, true);
|
||||
if (pTarget)
|
||||
DoCast(pTarget, SPELL_SURGE);
|
||||
Surge_Timer = 15000 + rand()%5000;
|
||||
} else Surge_Timer -= diff;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (LaceratingSlash_Timer <= diff)
|
||||
{
|
||||
DoCast(me->getVictim(), SPELL_LACERATINGSLASH);
|
||||
LaceratingSlash_Timer = 18000 + rand()%5000;
|
||||
} else LaceratingSlash_Timer -= diff;
|
||||
|
||||
if (RendFlesh_Timer <= diff)
|
||||
{
|
||||
DoCast(me->getVictim(), SPELL_RENDFLESH);
|
||||
RendFlesh_Timer = 5000 + rand()%5000;
|
||||
} else RendFlesh_Timer -= diff;
|
||||
|
||||
if (DeafeningRoar_Timer <= diff)
|
||||
{
|
||||
DoCast(me->getVictim(), SPELL_DEAFENINGROAR);
|
||||
DeafeningRoar_Timer = 15000 + rand()%5000;
|
||||
} else DeafeningRoar_Timer -= diff;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
if (LaceratingSlash_Timer <= diff)
|
||||
{
|
||||
DoCast(me->getVictim(), SPELL_LACERATINGSLASH);
|
||||
LaceratingSlash_Timer = 18000 + rand()%5000;
|
||||
} else LaceratingSlash_Timer -= diff;
|
||||
|
||||
if (RendFlesh_Timer <= diff)
|
||||
{
|
||||
DoCast(me->getVictim(), SPELL_RENDFLESH);
|
||||
RendFlesh_Timer = 5000 + rand()%5000;
|
||||
} else RendFlesh_Timer -= diff;
|
||||
|
||||
if (DeafeningRoar_Timer <= diff)
|
||||
{
|
||||
DoCast(me->getVictim(), SPELL_DEAFENINGROAR);
|
||||
DeafeningRoar_Timer = 15000 + rand()%5000;
|
||||
} else DeafeningRoar_Timer -= diff;
|
||||
return new boss_nalorakkAI(creature);
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI_boss_nalorakk(Creature* pCreature)
|
||||
{
|
||||
return new boss_nalorakkAI (pCreature);
|
||||
}
|
||||
|
||||
void AddSC_boss_nalorakk()
|
||||
{
|
||||
Script *newscript;
|
||||
newscript = new Script;
|
||||
newscript->Name = "boss_nalorakk";
|
||||
newscript->GetAI = &GetAI_boss_nalorakk;
|
||||
newscript->RegisterSelf();
|
||||
new boss_nalorakk();
|
||||
}
|
||||
|
||||
|
||||
@@ -140,486 +140,500 @@ static TransformStruct Transform[] =
|
||||
{SOUND_TRANSFORM_TO_DRAGONHAWK, YELL_TRANSFORM_TO_DRAGONHAWK, SPELL_SHAPE_OF_THE_DRAGONHAWK, SPELL_SHAPE_OF_THE_LYNX}
|
||||
};
|
||||
|
||||
struct boss_zuljinAI : public ScriptedAI
|
||||
class boss_zuljin : public CreatureScript
|
||||
{
|
||||
boss_zuljinAI(Creature *c) : ScriptedAI(c), Summons(me)
|
||||
{
|
||||
pInstance = c->GetInstanceData();
|
||||
}
|
||||
ScriptedInstance *pInstance;
|
||||
public:
|
||||
|
||||
uint64 SpiritGUID[4];
|
||||
uint64 ClawTargetGUID;
|
||||
uint64 TankGUID;
|
||||
|
||||
uint32 Phase;
|
||||
uint32 health_20;
|
||||
|
||||
uint32 Intro_Timer;
|
||||
uint32 Berserk_Timer;
|
||||
|
||||
uint32 Whirlwind_Timer;
|
||||
uint32 Grievous_Throw_Timer;
|
||||
|
||||
uint32 Creeping_Paralysis_Timer;
|
||||
uint32 Overpower_Timer;
|
||||
|
||||
uint32 Claw_Rage_Timer;
|
||||
uint32 Lynx_Rush_Timer;
|
||||
uint32 Claw_Counter;
|
||||
uint32 Claw_Loop_Timer;
|
||||
|
||||
uint32 Flame_Whirl_Timer;
|
||||
uint32 Flame_Breath_Timer;
|
||||
uint32 Pillar_Of_Fire_Timer;
|
||||
|
||||
SummonList Summons;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_ZULJINEVENT, NOT_STARTED);
|
||||
|
||||
Phase = 0;
|
||||
|
||||
health_20 = me->GetMaxHealth()*0.2;
|
||||
|
||||
Intro_Timer = 37000;
|
||||
Berserk_Timer = 600000;
|
||||
|
||||
Whirlwind_Timer = 7000;
|
||||
Grievous_Throw_Timer = 8000;
|
||||
|
||||
Creeping_Paralysis_Timer = 7000;
|
||||
Overpower_Timer = 0;
|
||||
|
||||
Claw_Rage_Timer = 5000;
|
||||
Lynx_Rush_Timer = 14000;
|
||||
Claw_Loop_Timer = 0;
|
||||
Claw_Counter = 0;
|
||||
|
||||
Flame_Whirl_Timer = 5000;
|
||||
Flame_Breath_Timer = 6000;
|
||||
Pillar_Of_Fire_Timer = 7000;
|
||||
|
||||
ClawTargetGUID = 0;
|
||||
TankGUID = 0;
|
||||
|
||||
Summons.DespawnAll();
|
||||
|
||||
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 47174);
|
||||
//me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, 218172674);
|
||||
//me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit * /*who*/)
|
||||
{
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_ZULJINEVENT, IN_PROGRESS);
|
||||
|
||||
DoZoneInCombat();
|
||||
|
||||
me->MonsterYell(YELL_INTRO,LANG_UNIVERSAL,NULL);
|
||||
DoPlaySoundToSet(me, SOUND_INTRO);
|
||||
SpawnAdds();
|
||||
EnterPhase(0);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/)
|
||||
{
|
||||
if (Intro_Timer)
|
||||
return;
|
||||
|
||||
switch (urand(0,1))
|
||||
boss_zuljin()
|
||||
: CreatureScript("boss_zuljin")
|
||||
{
|
||||
case 0:
|
||||
me->MonsterYell(YELL_KILL_ONE, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_KILL_ONE);
|
||||
break;
|
||||
case 1:
|
||||
me->MonsterYell(YELL_KILL_TWO, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_KILL_TWO);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*Killer*/)
|
||||
{
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_ZULJINEVENT, DONE);
|
||||
|
||||
me->MonsterYell(YELL_DEATH, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_DEATH);
|
||||
Summons.DespawnEntry(CREATURE_COLUMN_OF_FIRE);
|
||||
|
||||
if (Unit *Temp = Unit::GetUnit(*me, SpiritGUID[3]))
|
||||
Temp->SetUInt32Value(UNIT_FIELD_BYTES_1,UNIT_STAND_STATE_DEAD);
|
||||
}
|
||||
|
||||
void AttackStart(Unit *who)
|
||||
{
|
||||
if (Phase == 2)
|
||||
AttackStartNoMove(who);
|
||||
else
|
||||
ScriptedAI::AttackStart(who);
|
||||
}
|
||||
|
||||
void DoMeleeAttackIfReady()
|
||||
{
|
||||
if (!me->IsNonMeleeSpellCasted(false))
|
||||
struct boss_zuljinAI : public ScriptedAI
|
||||
{
|
||||
if (me->isAttackReady() && me->IsWithinMeleeRange(me->getVictim()))
|
||||
boss_zuljinAI(Creature *c) : ScriptedAI(c), Summons(me)
|
||||
{
|
||||
if (Phase == 1 && !Overpower_Timer)
|
||||
{
|
||||
uint32 health = me->getVictim()->GetHealth();
|
||||
me->AttackerStateUpdate(me->getVictim());
|
||||
if (me->getVictim() && health == me->getVictim()->GetHealth())
|
||||
{
|
||||
DoCast(me->getVictim(), SPELL_OVERPOWER, false);
|
||||
Overpower_Timer = 5000;
|
||||
}
|
||||
} else me->AttackerStateUpdate(me->getVictim());
|
||||
me->resetAttackTimer();
|
||||
pInstance = c->GetInstanceData();
|
||||
}
|
||||
}
|
||||
}
|
||||
ScriptedInstance *pInstance;
|
||||
|
||||
void SpawnAdds()
|
||||
{
|
||||
Creature *pCreature = NULL;
|
||||
for (uint8 i = 0; i < 4; ++i)
|
||||
{
|
||||
pCreature = me->SummonCreature(SpiritInfo[i].entry, SpiritInfo[i].x, SpiritInfo[i].y, SpiritInfo[i].z, SpiritInfo[i].orient, TEMPSUMMON_DEAD_DESPAWN, 0);
|
||||
if (pCreature)
|
||||
uint64 SpiritGUID[4];
|
||||
uint64 ClawTargetGUID;
|
||||
uint64 TankGUID;
|
||||
|
||||
uint32 Phase;
|
||||
uint32 health_20;
|
||||
|
||||
uint32 Intro_Timer;
|
||||
uint32 Berserk_Timer;
|
||||
|
||||
uint32 Whirlwind_Timer;
|
||||
uint32 Grievous_Throw_Timer;
|
||||
|
||||
uint32 Creeping_Paralysis_Timer;
|
||||
uint32 Overpower_Timer;
|
||||
|
||||
uint32 Claw_Rage_Timer;
|
||||
uint32 Lynx_Rush_Timer;
|
||||
uint32 Claw_Counter;
|
||||
uint32 Claw_Loop_Timer;
|
||||
|
||||
uint32 Flame_Whirl_Timer;
|
||||
uint32 Flame_Breath_Timer;
|
||||
uint32 Pillar_Of_Fire_Timer;
|
||||
|
||||
SummonList Summons;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
pCreature->CastSpell(pCreature, SPELL_SPIRIT_AURA, true);
|
||||
pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
|
||||
pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
SpiritGUID[i] = pCreature->GetGUID();
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_ZULJINEVENT, NOT_STARTED);
|
||||
|
||||
Phase = 0;
|
||||
|
||||
health_20 = me->GetMaxHealth()*0.2;
|
||||
|
||||
Intro_Timer = 37000;
|
||||
Berserk_Timer = 600000;
|
||||
|
||||
Whirlwind_Timer = 7000;
|
||||
Grievous_Throw_Timer = 8000;
|
||||
|
||||
Creeping_Paralysis_Timer = 7000;
|
||||
Overpower_Timer = 0;
|
||||
|
||||
Claw_Rage_Timer = 5000;
|
||||
Lynx_Rush_Timer = 14000;
|
||||
Claw_Loop_Timer = 0;
|
||||
Claw_Counter = 0;
|
||||
|
||||
Flame_Whirl_Timer = 5000;
|
||||
Flame_Breath_Timer = 6000;
|
||||
Pillar_Of_Fire_Timer = 7000;
|
||||
|
||||
ClawTargetGUID = 0;
|
||||
TankGUID = 0;
|
||||
|
||||
Summons.DespawnAll();
|
||||
|
||||
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 47174);
|
||||
//me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, 218172674);
|
||||
//me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DespawnAdds()
|
||||
{
|
||||
for (uint8 i = 0; i < 4; ++i)
|
||||
{
|
||||
Unit* Temp = NULL;
|
||||
if (SpiritGUID[i])
|
||||
void EnterCombat(Unit * /*who*/)
|
||||
{
|
||||
if (Temp = Unit::GetUnit(*me, SpiritGUID[i]))
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_ZULJINEVENT, IN_PROGRESS);
|
||||
|
||||
DoZoneInCombat();
|
||||
|
||||
me->MonsterYell(YELL_INTRO,LANG_UNIVERSAL,NULL);
|
||||
DoPlaySoundToSet(me, SOUND_INTRO);
|
||||
SpawnAdds();
|
||||
EnterPhase(0);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/)
|
||||
{
|
||||
if (Intro_Timer)
|
||||
return;
|
||||
|
||||
switch (urand(0,1))
|
||||
{
|
||||
Temp->SetVisibility(VISIBILITY_OFF);
|
||||
Temp->setDeathState(DEAD);
|
||||
case 0:
|
||||
me->MonsterYell(YELL_KILL_ONE, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_KILL_ONE);
|
||||
break;
|
||||
case 1:
|
||||
me->MonsterYell(YELL_KILL_TWO, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_KILL_TWO);
|
||||
break;
|
||||
}
|
||||
}
|
||||
SpiritGUID[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void JustSummoned(Creature *summon)
|
||||
{
|
||||
Summons.Summon(summon);
|
||||
}
|
||||
|
||||
void SummonedCreatureDespawn(Creature *summon)
|
||||
{
|
||||
Summons.Despawn(summon);
|
||||
}
|
||||
|
||||
void EnterPhase(uint32 NextPhase)
|
||||
{
|
||||
switch(NextPhase)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
DoTeleportTo(CENTER_X, CENTER_Y, CENTER_Z, 100);
|
||||
DoResetThreat();
|
||||
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0);
|
||||
me->RemoveAurasDueToSpell(Transform[Phase].unaura);
|
||||
DoCast(me, Transform[Phase].spell);
|
||||
me->MonsterYell(Transform[Phase].text, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, Transform[Phase].sound);
|
||||
if (Phase > 0)
|
||||
void JustDied(Unit* /*Killer*/)
|
||||
{
|
||||
if (Unit *Temp = Unit::GetUnit(*me, SpiritGUID[Phase - 1]))
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_ZULJINEVENT, DONE);
|
||||
|
||||
me->MonsterYell(YELL_DEATH, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_DEATH);
|
||||
Summons.DespawnEntry(CREATURE_COLUMN_OF_FIRE);
|
||||
|
||||
if (Unit *Temp = Unit::GetUnit(*me, SpiritGUID[3]))
|
||||
Temp->SetUInt32Value(UNIT_FIELD_BYTES_1,UNIT_STAND_STATE_DEAD);
|
||||
}
|
||||
if (Unit *Temp = Unit::GetUnit(*me, SpiritGUID[NextPhase - 1]))
|
||||
Temp->CastSpell(me, SPELL_SIPHON_SOUL, false); // should m cast on temp
|
||||
if (NextPhase == 2)
|
||||
|
||||
void AttackStart(Unit *who)
|
||||
{
|
||||
me->GetMotionMaster()->Clear();
|
||||
DoCast(me, SPELL_ENERGY_STORM, true); // enemy aura
|
||||
if (Phase == 2)
|
||||
AttackStartNoMove(who);
|
||||
else
|
||||
ScriptedAI::AttackStart(who);
|
||||
}
|
||||
|
||||
void DoMeleeAttackIfReady()
|
||||
{
|
||||
if (!me->IsNonMeleeSpellCasted(false))
|
||||
{
|
||||
if (me->isAttackReady() && me->IsWithinMeleeRange(me->getVictim()))
|
||||
{
|
||||
if (Phase == 1 && !Overpower_Timer)
|
||||
{
|
||||
uint32 health = me->getVictim()->GetHealth();
|
||||
me->AttackerStateUpdate(me->getVictim());
|
||||
if (me->getVictim() && health == me->getVictim()->GetHealth())
|
||||
{
|
||||
DoCast(me->getVictim(), SPELL_OVERPOWER, false);
|
||||
Overpower_Timer = 5000;
|
||||
}
|
||||
} else me->AttackerStateUpdate(me->getVictim());
|
||||
me->resetAttackTimer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpawnAdds()
|
||||
{
|
||||
Creature *pCreature = NULL;
|
||||
for (uint8 i = 0; i < 4; ++i)
|
||||
{
|
||||
Creature* Vortex = DoSpawnCreature(CREATURE_FEATHER_VORTEX, 0, 0, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
|
||||
if (Vortex)
|
||||
pCreature = me->SummonCreature(SpiritInfo[i].entry, SpiritInfo[i].x, SpiritInfo[i].y, SpiritInfo[i].z, SpiritInfo[i].orient, TEMPSUMMON_DEAD_DESPAWN, 0);
|
||||
if (pCreature)
|
||||
{
|
||||
Vortex->CastSpell(Vortex, SPELL_CYCLONE_PASSIVE, true);
|
||||
Vortex->CastSpell(Vortex, SPELL_CYCLONE_VISUAL, true);
|
||||
Vortex->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
Vortex->SetSpeed(MOVE_RUN, 1.0f);
|
||||
Vortex->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0));
|
||||
DoZoneInCombat(Vortex);
|
||||
pCreature->CastSpell(pCreature, SPELL_SPIRIT_AURA, true);
|
||||
pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
|
||||
pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
SpiritGUID[i] = pCreature->GetGUID();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
me->AI()->AttackStart(me->getVictim());
|
||||
if (NextPhase == 3)
|
||||
|
||||
void DespawnAdds()
|
||||
{
|
||||
me->RemoveAurasDueToSpell(SPELL_ENERGY_STORM);
|
||||
Summons.DespawnEntry(CREATURE_FEATHER_VORTEX);
|
||||
me->GetMotionMaster()->MoveChase(me->getVictim());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Phase = NextPhase;
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if (!TankGUID)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (me->GetHealth() < health_20 * (4 - Phase))
|
||||
EnterPhase(Phase + 1);
|
||||
}
|
||||
|
||||
if (Berserk_Timer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_BERSERK, true);
|
||||
me->MonsterYell(YELL_BERSERK, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_BERSERK);
|
||||
Berserk_Timer = 60000;
|
||||
} else Berserk_Timer -= diff;
|
||||
|
||||
switch (Phase)
|
||||
{
|
||||
case 0:
|
||||
if (Intro_Timer)
|
||||
{
|
||||
if (Intro_Timer <= diff)
|
||||
for (uint8 i = 0; i < 4; ++i)
|
||||
{
|
||||
me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_AGGRO);
|
||||
Intro_Timer = 0;
|
||||
} else Intro_Timer -= diff;
|
||||
}
|
||||
|
||||
if (Whirlwind_Timer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_WHIRLWIND);
|
||||
Whirlwind_Timer = 15000 + rand()%5000;
|
||||
} else Whirlwind_Timer -= diff;
|
||||
|
||||
if (Grievous_Throw_Timer <= diff)
|
||||
{
|
||||
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
|
||||
DoCast(pTarget, SPELL_GRIEVOUS_THROW, false);
|
||||
Grievous_Throw_Timer = 10000;
|
||||
} else Grievous_Throw_Timer -= diff;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (Creeping_Paralysis_Timer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_CREEPING_PARALYSIS);
|
||||
Creeping_Paralysis_Timer = 20000;
|
||||
} else Creeping_Paralysis_Timer -= diff;
|
||||
|
||||
if (Overpower_Timer <= diff)
|
||||
{
|
||||
// implemented in DoMeleeAttackIfReady()
|
||||
Overpower_Timer = 0;
|
||||
} else Overpower_Timer -= diff;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
return;
|
||||
|
||||
case 3:
|
||||
if (Claw_Rage_Timer <= diff)
|
||||
{
|
||||
if (!TankGUID)
|
||||
{
|
||||
if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
|
||||
Unit* Temp = NULL;
|
||||
if (SpiritGUID[i])
|
||||
{
|
||||
TankGUID = me->getVictim()->GetGUID();
|
||||
me->SetSpeed(MOVE_RUN, 5.0f);
|
||||
AttackStart(pTarget); // change victim
|
||||
Claw_Rage_Timer = 0;
|
||||
Claw_Loop_Timer = 500;
|
||||
Claw_Counter = 0;
|
||||
}
|
||||
}
|
||||
else if (!Claw_Rage_Timer) // do not do this when Lynx_Rush
|
||||
{
|
||||
if (Claw_Loop_Timer <= diff)
|
||||
{
|
||||
Unit *pTarget = me->getVictim();
|
||||
if (!pTarget || !pTarget->isTargetableForAttack()) pTarget = Unit::GetUnit(*me, TankGUID);
|
||||
if (!pTarget || !pTarget->isTargetableForAttack()) pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0);
|
||||
if (pTarget)
|
||||
if (Temp = Unit::GetUnit(*me, SpiritGUID[i]))
|
||||
{
|
||||
AttackStart(pTarget);
|
||||
if (me->IsWithinMeleeRange(pTarget))
|
||||
{
|
||||
DoCast(pTarget, SPELL_CLAW_RAGE_DAMAGE, true);
|
||||
++Claw_Counter;
|
||||
if (Claw_Counter == 12)
|
||||
{
|
||||
Claw_Rage_Timer = 15000 + rand()%5000;
|
||||
me->SetSpeed(MOVE_RUN, 1.2f);
|
||||
AttackStart(Unit::GetUnit(*me, TankGUID));
|
||||
TankGUID = 0;
|
||||
return;
|
||||
}
|
||||
else
|
||||
Claw_Loop_Timer = 500;
|
||||
}
|
||||
Temp->SetVisibility(VISIBILITY_OFF);
|
||||
Temp->setDeathState(DEAD);
|
||||
}
|
||||
else
|
||||
{
|
||||
EnterEvadeMode(); // if (pTarget)
|
||||
return;
|
||||
}
|
||||
} else Claw_Loop_Timer -= diff;
|
||||
} //if (TankGUID)
|
||||
} else Claw_Rage_Timer -= diff;
|
||||
|
||||
if (Lynx_Rush_Timer <= diff)
|
||||
{
|
||||
if (!TankGUID)
|
||||
{
|
||||
if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
|
||||
{
|
||||
TankGUID = me->getVictim()->GetGUID();
|
||||
me->SetSpeed(MOVE_RUN, 5.0f);
|
||||
AttackStart(pTarget); // change victim
|
||||
Lynx_Rush_Timer = 0;
|
||||
Claw_Counter = 0;
|
||||
}
|
||||
SpiritGUID[i] = 0;
|
||||
}
|
||||
else if (!Lynx_Rush_Timer)
|
||||
}
|
||||
|
||||
void JustSummoned(Creature *summon)
|
||||
{
|
||||
Summons.Summon(summon);
|
||||
}
|
||||
|
||||
void SummonedCreatureDespawn(Creature *summon)
|
||||
{
|
||||
Summons.Despawn(summon);
|
||||
}
|
||||
|
||||
void EnterPhase(uint32 NextPhase)
|
||||
{
|
||||
switch(NextPhase)
|
||||
{
|
||||
Unit *pTarget = me->getVictim();
|
||||
if (!pTarget || !pTarget->isTargetableForAttack())
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
DoTeleportTo(CENTER_X, CENTER_Y, CENTER_Z, 100);
|
||||
DoResetThreat();
|
||||
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0);
|
||||
me->RemoveAurasDueToSpell(Transform[Phase].unaura);
|
||||
DoCast(me, Transform[Phase].spell);
|
||||
me->MonsterYell(Transform[Phase].text, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, Transform[Phase].sound);
|
||||
if (Phase > 0)
|
||||
{
|
||||
pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0);
|
||||
AttackStart(pTarget);
|
||||
if (Unit *Temp = Unit::GetUnit(*me, SpiritGUID[Phase - 1]))
|
||||
Temp->SetUInt32Value(UNIT_FIELD_BYTES_1,UNIT_STAND_STATE_DEAD);
|
||||
}
|
||||
if (pTarget)
|
||||
if (Unit *Temp = Unit::GetUnit(*me, SpiritGUID[NextPhase - 1]))
|
||||
Temp->CastSpell(me, SPELL_SIPHON_SOUL, false); // should m cast on temp
|
||||
if (NextPhase == 2)
|
||||
{
|
||||
if (me->IsWithinMeleeRange(pTarget))
|
||||
me->GetMotionMaster()->Clear();
|
||||
DoCast(me, SPELL_ENERGY_STORM, true); // enemy aura
|
||||
for (uint8 i = 0; i < 4; ++i)
|
||||
{
|
||||
DoCast(pTarget, SPELL_LYNX_RUSH_DAMAGE, true);
|
||||
++Claw_Counter;
|
||||
if (Claw_Counter == 9)
|
||||
Creature* Vortex = DoSpawnCreature(CREATURE_FEATHER_VORTEX, 0, 0, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
|
||||
if (Vortex)
|
||||
{
|
||||
Lynx_Rush_Timer = 15000 + rand()%5000;
|
||||
me->SetSpeed(MOVE_RUN, 1.2f);
|
||||
AttackStart(Unit::GetUnit(*me, TankGUID));
|
||||
TankGUID = 0;
|
||||
Vortex->CastSpell(Vortex, SPELL_CYCLONE_PASSIVE, true);
|
||||
Vortex->CastSpell(Vortex, SPELL_CYCLONE_VISUAL, true);
|
||||
Vortex->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
Vortex->SetSpeed(MOVE_RUN, 1.0f);
|
||||
Vortex->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0));
|
||||
DoZoneInCombat(Vortex);
|
||||
}
|
||||
else
|
||||
AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0));
|
||||
}
|
||||
}
|
||||
else
|
||||
me->AI()->AttackStart(me->getVictim());
|
||||
if (NextPhase == 3)
|
||||
{
|
||||
EnterEvadeMode(); // if (pTarget)
|
||||
return;
|
||||
me->RemoveAurasDueToSpell(SPELL_ENERGY_STORM);
|
||||
Summons.DespawnEntry(CREATURE_FEATHER_VORTEX);
|
||||
me->GetMotionMaster()->MoveChase(me->getVictim());
|
||||
}
|
||||
} //if (TankGUID)
|
||||
} else Lynx_Rush_Timer -= diff;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Phase = NextPhase;
|
||||
}
|
||||
|
||||
break;
|
||||
case 4:
|
||||
if (Flame_Whirl_Timer <= diff)
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
DoCast(me, SPELL_FLAME_WHIRL);
|
||||
Flame_Whirl_Timer = 12000;
|
||||
}Flame_Whirl_Timer -= diff;
|
||||
if (!TankGUID)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (Pillar_Of_Fire_Timer <= diff)
|
||||
{
|
||||
if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
|
||||
DoCast(pTarget, SPELL_SUMMON_PILLAR);
|
||||
Pillar_Of_Fire_Timer = 10000;
|
||||
} else Pillar_Of_Fire_Timer -= diff;
|
||||
if (me->GetHealth() < health_20 * (4 - Phase))
|
||||
EnterPhase(Phase + 1);
|
||||
}
|
||||
|
||||
if (Flame_Breath_Timer <= diff)
|
||||
{
|
||||
if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
|
||||
me->SetInFront(pTarget);
|
||||
DoCast(me, SPELL_FLAME_BREATH);
|
||||
Flame_Breath_Timer = 10000;
|
||||
} else Flame_Breath_Timer -= diff;
|
||||
break;
|
||||
if (Berserk_Timer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_BERSERK, true);
|
||||
me->MonsterYell(YELL_BERSERK, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_BERSERK);
|
||||
Berserk_Timer = 60000;
|
||||
} else Berserk_Timer -= diff;
|
||||
|
||||
default:
|
||||
break;
|
||||
switch (Phase)
|
||||
{
|
||||
case 0:
|
||||
if (Intro_Timer)
|
||||
{
|
||||
if (Intro_Timer <= diff)
|
||||
{
|
||||
me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL);
|
||||
DoPlaySoundToSet(me, SOUND_AGGRO);
|
||||
Intro_Timer = 0;
|
||||
} else Intro_Timer -= diff;
|
||||
}
|
||||
|
||||
if (Whirlwind_Timer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_WHIRLWIND);
|
||||
Whirlwind_Timer = 15000 + rand()%5000;
|
||||
} else Whirlwind_Timer -= diff;
|
||||
|
||||
if (Grievous_Throw_Timer <= diff)
|
||||
{
|
||||
if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
|
||||
DoCast(pTarget, SPELL_GRIEVOUS_THROW, false);
|
||||
Grievous_Throw_Timer = 10000;
|
||||
} else Grievous_Throw_Timer -= diff;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (Creeping_Paralysis_Timer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_CREEPING_PARALYSIS);
|
||||
Creeping_Paralysis_Timer = 20000;
|
||||
} else Creeping_Paralysis_Timer -= diff;
|
||||
|
||||
if (Overpower_Timer <= diff)
|
||||
{
|
||||
// implemented in DoMeleeAttackIfReady()
|
||||
Overpower_Timer = 0;
|
||||
} else Overpower_Timer -= diff;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
return;
|
||||
|
||||
case 3:
|
||||
if (Claw_Rage_Timer <= diff)
|
||||
{
|
||||
if (!TankGUID)
|
||||
{
|
||||
if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
|
||||
{
|
||||
TankGUID = me->getVictim()->GetGUID();
|
||||
me->SetSpeed(MOVE_RUN, 5.0f);
|
||||
AttackStart(pTarget); // change victim
|
||||
Claw_Rage_Timer = 0;
|
||||
Claw_Loop_Timer = 500;
|
||||
Claw_Counter = 0;
|
||||
}
|
||||
}
|
||||
else if (!Claw_Rage_Timer) // do not do this when Lynx_Rush
|
||||
{
|
||||
if (Claw_Loop_Timer <= diff)
|
||||
{
|
||||
Unit *pTarget = me->getVictim();
|
||||
if (!pTarget || !pTarget->isTargetableForAttack()) pTarget = Unit::GetUnit(*me, TankGUID);
|
||||
if (!pTarget || !pTarget->isTargetableForAttack()) pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0);
|
||||
if (pTarget)
|
||||
{
|
||||
AttackStart(pTarget);
|
||||
if (me->IsWithinMeleeRange(pTarget))
|
||||
{
|
||||
DoCast(pTarget, SPELL_CLAW_RAGE_DAMAGE, true);
|
||||
++Claw_Counter;
|
||||
if (Claw_Counter == 12)
|
||||
{
|
||||
Claw_Rage_Timer = 15000 + rand()%5000;
|
||||
me->SetSpeed(MOVE_RUN, 1.2f);
|
||||
AttackStart(Unit::GetUnit(*me, TankGUID));
|
||||
TankGUID = 0;
|
||||
return;
|
||||
}
|
||||
else
|
||||
Claw_Loop_Timer = 500;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EnterEvadeMode(); // if (pTarget)
|
||||
return;
|
||||
}
|
||||
} else Claw_Loop_Timer -= diff;
|
||||
} //if (TankGUID)
|
||||
} else Claw_Rage_Timer -= diff;
|
||||
|
||||
if (Lynx_Rush_Timer <= diff)
|
||||
{
|
||||
if (!TankGUID)
|
||||
{
|
||||
if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
|
||||
{
|
||||
TankGUID = me->getVictim()->GetGUID();
|
||||
me->SetSpeed(MOVE_RUN, 5.0f);
|
||||
AttackStart(pTarget); // change victim
|
||||
Lynx_Rush_Timer = 0;
|
||||
Claw_Counter = 0;
|
||||
}
|
||||
}
|
||||
else if (!Lynx_Rush_Timer)
|
||||
{
|
||||
Unit *pTarget = me->getVictim();
|
||||
if (!pTarget || !pTarget->isTargetableForAttack())
|
||||
{
|
||||
pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0);
|
||||
AttackStart(pTarget);
|
||||
}
|
||||
if (pTarget)
|
||||
{
|
||||
if (me->IsWithinMeleeRange(pTarget))
|
||||
{
|
||||
DoCast(pTarget, SPELL_LYNX_RUSH_DAMAGE, true);
|
||||
++Claw_Counter;
|
||||
if (Claw_Counter == 9)
|
||||
{
|
||||
Lynx_Rush_Timer = 15000 + rand()%5000;
|
||||
me->SetSpeed(MOVE_RUN, 1.2f);
|
||||
AttackStart(Unit::GetUnit(*me, TankGUID));
|
||||
TankGUID = 0;
|
||||
}
|
||||
else
|
||||
AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EnterEvadeMode(); // if (pTarget)
|
||||
return;
|
||||
}
|
||||
} //if (TankGUID)
|
||||
} else Lynx_Rush_Timer -= diff;
|
||||
|
||||
break;
|
||||
case 4:
|
||||
if (Flame_Whirl_Timer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_FLAME_WHIRL);
|
||||
Flame_Whirl_Timer = 12000;
|
||||
}Flame_Whirl_Timer -= diff;
|
||||
|
||||
if (Pillar_Of_Fire_Timer <= diff)
|
||||
{
|
||||
if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
|
||||
DoCast(pTarget, SPELL_SUMMON_PILLAR);
|
||||
Pillar_Of_Fire_Timer = 10000;
|
||||
} else Pillar_Of_Fire_Timer -= diff;
|
||||
|
||||
if (Flame_Breath_Timer <= diff)
|
||||
{
|
||||
if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
|
||||
me->SetInFront(pTarget);
|
||||
DoCast(me, SPELL_FLAME_BREATH);
|
||||
Flame_Breath_Timer = 10000;
|
||||
} else Flame_Breath_Timer -= diff;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!TankGUID)
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return new boss_zuljinAI(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class mob_zuljin_vortex : public CreatureScript
|
||||
{
|
||||
public:
|
||||
|
||||
mob_zuljin_vortex()
|
||||
: CreatureScript("mob_zuljin_vortex")
|
||||
{
|
||||
}
|
||||
|
||||
if (!TankGUID)
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
struct mob_zuljin_vortexAI : public ScriptedAI
|
||||
{
|
||||
mob_zuljin_vortexAI(Creature *c) : ScriptedAI(c) {}
|
||||
|
||||
void Reset() {}
|
||||
|
||||
void EnterCombat(Unit * /*pTarget*/) {}
|
||||
|
||||
void SpellHit(Unit *caster, const SpellEntry *spell)
|
||||
{
|
||||
if (spell->Id == SPELL_ZAP_INFORM)
|
||||
DoCast(caster, SPELL_ZAP_DAMAGE, true);
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 /*diff*/)
|
||||
{
|
||||
//if the vortex reach the target, it change his target to another player
|
||||
if (me->IsWithinMeleeRange(me->getVictim()))
|
||||
AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0));
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return new mob_zuljin_vortexAI(creature);
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI_boss_zuljin(Creature* pCreature)
|
||||
{
|
||||
return new boss_zuljinAI (pCreature);
|
||||
}
|
||||
|
||||
struct feather_vortexAI : public ScriptedAI
|
||||
{
|
||||
feather_vortexAI(Creature *c) : ScriptedAI(c) {}
|
||||
|
||||
void Reset() {}
|
||||
|
||||
void EnterCombat(Unit * /*pTarget*/) {}
|
||||
|
||||
void SpellHit(Unit *caster, const SpellEntry *spell)
|
||||
{
|
||||
if (spell->Id == SPELL_ZAP_INFORM)
|
||||
DoCast(caster, SPELL_ZAP_DAMAGE, true);
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 /*diff*/)
|
||||
{
|
||||
//if the vortex reach the target, it change his target to another player
|
||||
if (me->IsWithinMeleeRange(me->getVictim()))
|
||||
AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0));
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI_feather_vortexAI(Creature* pCreature)
|
||||
{
|
||||
return new feather_vortexAI (pCreature);
|
||||
}
|
||||
|
||||
void AddSC_boss_zuljin()
|
||||
{
|
||||
Script *newscript;
|
||||
newscript = new Script;
|
||||
newscript->Name = "boss_zuljin";
|
||||
newscript->GetAI = &GetAI_boss_zuljin;
|
||||
newscript->RegisterSelf();
|
||||
|
||||
newscript = new Script;
|
||||
newscript->Name = "mob_zuljin_vortex";
|
||||
newscript->GetAI = &GetAI_feather_vortexAI;
|
||||
newscript->RegisterSelf();
|
||||
new boss_zuljin();
|
||||
new mob_zuljin_vortex();
|
||||
}
|
||||
|
||||
|
||||
@@ -51,272 +51,277 @@ static SHostageInfo HostageInfo[] =
|
||||
|
||||
};
|
||||
|
||||
struct instance_zulaman : public ScriptedInstance
|
||||
class instance_zulaman : public InstanceMapScript
|
||||
{
|
||||
instance_zulaman(Map* pMap) : ScriptedInstance(pMap) {Initialize();};
|
||||
|
||||
uint64 HarkorsSatchelGUID;
|
||||
uint64 TanzarsTrunkGUID;
|
||||
uint64 AshlisBagGUID;
|
||||
uint64 KrazsPackageGUID;
|
||||
|
||||
uint64 HexLordGateGUID;
|
||||
uint64 ZulJinGateGUID;
|
||||
uint64 AkilzonDoorGUID;
|
||||
uint64 ZulJinDoorGUID;
|
||||
uint64 HalazziDoorGUID;
|
||||
|
||||
uint32 QuestTimer;
|
||||
uint16 BossKilled;
|
||||
uint16 QuestMinute;
|
||||
uint16 ChestLooted;
|
||||
|
||||
uint32 m_auiEncounter[MAX_ENCOUNTER];
|
||||
uint32 RandVendor[RAND_VENDOR];
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
|
||||
|
||||
HarkorsSatchelGUID = 0;
|
||||
TanzarsTrunkGUID = 0;
|
||||
AshlisBagGUID = 0;
|
||||
KrazsPackageGUID = 0;
|
||||
|
||||
HexLordGateGUID = 0;
|
||||
ZulJinGateGUID = 0;
|
||||
AkilzonDoorGUID = 0;
|
||||
HalazziDoorGUID = 0;
|
||||
ZulJinDoorGUID = 0;
|
||||
|
||||
QuestTimer = 0;
|
||||
QuestMinute = 21;
|
||||
BossKilled = 0;
|
||||
ChestLooted = 0;
|
||||
|
||||
for (uint8 i = 0; i < RAND_VENDOR; ++i)
|
||||
RandVendor[i] = NOT_STARTED;
|
||||
}
|
||||
|
||||
bool IsEncounterInProgress() const
|
||||
{
|
||||
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
|
||||
if (m_auiEncounter[i] == IN_PROGRESS) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* pCreature, bool /*add*/)
|
||||
{
|
||||
switch(pCreature->GetEntry())
|
||||
public:
|
||||
instance_zulaman()
|
||||
: InstanceMapScript("instance_zulaman")
|
||||
{
|
||||
case 23578://janalai
|
||||
case 23863://zuljin
|
||||
case 24239://hexlord
|
||||
case 23577://halazzi
|
||||
case 23576://nalorakk
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnGameObjectCreate(GameObject* pGo, bool /*add*/)
|
||||
{
|
||||
switch(pGo->GetEntry())
|
||||
struct instance_zulaman_InstanceMapScript : public ScriptedInstance
|
||||
{
|
||||
case 186303: HalazziDoorGUID = pGo->GetGUID(); break;
|
||||
case 186304: ZulJinGateGUID = pGo->GetGUID(); break;
|
||||
case 186305: HexLordGateGUID = pGo->GetGUID(); break;
|
||||
case 186858: AkilzonDoorGUID = pGo->GetGUID(); break;
|
||||
case 186859: ZulJinDoorGUID = pGo->GetGUID(); break;
|
||||
instance_zulaman_InstanceMapScript(Map* pMap) : ScriptedInstance(pMap) {Initialize();};
|
||||
|
||||
case 187021: HarkorsSatchelGUID = pGo->GetGUID(); break;
|
||||
case 186648: TanzarsTrunkGUID = pGo->GetGUID(); break;
|
||||
case 186672: AshlisBagGUID = pGo->GetGUID(); break;
|
||||
case 186667: KrazsPackageGUID = pGo->GetGUID(); break;
|
||||
default: break;
|
||||
uint64 HarkorsSatchelGUID;
|
||||
uint64 TanzarsTrunkGUID;
|
||||
uint64 AshlisBagGUID;
|
||||
uint64 KrazsPackageGUID;
|
||||
|
||||
}
|
||||
CheckInstanceStatus();
|
||||
}
|
||||
uint64 HexLordGateGUID;
|
||||
uint64 ZulJinGateGUID;
|
||||
uint64 AkilzonDoorGUID;
|
||||
uint64 ZulJinDoorGUID;
|
||||
uint64 HalazziDoorGUID;
|
||||
|
||||
void SummonHostage(uint8 num)
|
||||
{
|
||||
if (!QuestMinute)
|
||||
return;
|
||||
uint32 QuestTimer;
|
||||
uint16 BossKilled;
|
||||
uint16 QuestMinute;
|
||||
uint16 ChestLooted;
|
||||
|
||||
Map::PlayerList const &PlayerList = instance->GetPlayers();
|
||||
if (PlayerList.isEmpty())
|
||||
return;
|
||||
uint32 m_auiEncounter[MAX_ENCOUNTER];
|
||||
uint32 RandVendor[RAND_VENDOR];
|
||||
|
||||
Map::PlayerList::const_iterator i = PlayerList.begin();
|
||||
if (Player* i_pl = i->getSource())
|
||||
{
|
||||
if (Unit* Hostage = i_pl->SummonCreature(HostageInfo[num].npc, HostageInfo[num].x, HostageInfo[num].y, HostageInfo[num].z, HostageInfo[num].o, TEMPSUMMON_DEAD_DESPAWN, 0))
|
||||
void Initialize()
|
||||
{
|
||||
Hostage->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
|
||||
Hostage->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
|
||||
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
|
||||
|
||||
HarkorsSatchelGUID = 0;
|
||||
TanzarsTrunkGUID = 0;
|
||||
AshlisBagGUID = 0;
|
||||
KrazsPackageGUID = 0;
|
||||
|
||||
HexLordGateGUID = 0;
|
||||
ZulJinGateGUID = 0;
|
||||
AkilzonDoorGUID = 0;
|
||||
HalazziDoorGUID = 0;
|
||||
ZulJinDoorGUID = 0;
|
||||
|
||||
QuestTimer = 0;
|
||||
QuestMinute = 21;
|
||||
BossKilled = 0;
|
||||
ChestLooted = 0;
|
||||
|
||||
for (uint8 i = 0; i < RAND_VENDOR; ++i)
|
||||
RandVendor[i] = NOT_STARTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CheckInstanceStatus()
|
||||
{
|
||||
if (BossKilled >= 4)
|
||||
HandleGameObject(HexLordGateGUID, true);
|
||||
|
||||
if (BossKilled >= 5)
|
||||
HandleGameObject(ZulJinGateGUID, true);
|
||||
}
|
||||
|
||||
std::string GetSaveData()
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << "S " << BossKilled << " " << ChestLooted << " " << QuestMinute;
|
||||
char* data = new char[ss.str().length()+1];
|
||||
strcpy(data, ss.str().c_str());
|
||||
//sLog.outError("TSCR: Zul'aman saved, %s.", data);
|
||||
return data;
|
||||
}
|
||||
|
||||
void Load(const char* load)
|
||||
{
|
||||
if (!load) return;
|
||||
std::istringstream ss(load);
|
||||
//sLog.outError("TSCR: Zul'aman loaded, %s.", ss.str().c_str());
|
||||
char dataHead; // S
|
||||
uint16 data1, data2, data3;
|
||||
ss >> dataHead >> data1 >> data2 >> data3;
|
||||
//sLog.outError("TSCR: Zul'aman loaded, %d %d %d.", data1, data2, data3);
|
||||
if (dataHead == 'S')
|
||||
{
|
||||
BossKilled = data1;
|
||||
ChestLooted = data2;
|
||||
QuestMinute = data3;
|
||||
} else sLog.outError("TSCR: Zul'aman: corrupted save data.");
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 data)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case DATA_NALORAKKEVENT:
|
||||
m_auiEncounter[0] = data;
|
||||
if (data == DONE)
|
||||
bool IsEncounterInProgress() const
|
||||
{
|
||||
if (QuestMinute)
|
||||
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
|
||||
if (m_auiEncounter[i] == IN_PROGRESS) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* pCreature, bool /*add*/)
|
||||
{
|
||||
switch(pCreature->GetEntry())
|
||||
{
|
||||
QuestMinute += 15;
|
||||
DoUpdateWorldState(3106, QuestMinute);
|
||||
case 23578://janalai
|
||||
case 23863://zuljin
|
||||
case 24239://hexlord
|
||||
case 23577://halazzi
|
||||
case 23576://nalorakk
|
||||
default: break;
|
||||
}
|
||||
SummonHostage(0);
|
||||
}
|
||||
break;
|
||||
case DATA_AKILZONEVENT:
|
||||
m_auiEncounter[1] = data;
|
||||
HandleGameObject(AkilzonDoorGUID, data != IN_PROGRESS);
|
||||
if (data == DONE)
|
||||
|
||||
void OnGameObjectCreate(GameObject* pGo, bool /*add*/)
|
||||
{
|
||||
if (QuestMinute)
|
||||
switch(pGo->GetEntry())
|
||||
{
|
||||
QuestMinute += 10;
|
||||
DoUpdateWorldState(3106, QuestMinute);
|
||||
case 186303: HalazziDoorGUID = pGo->GetGUID(); break;
|
||||
case 186304: ZulJinGateGUID = pGo->GetGUID(); break;
|
||||
case 186305: HexLordGateGUID = pGo->GetGUID(); break;
|
||||
case 186858: AkilzonDoorGUID = pGo->GetGUID(); break;
|
||||
case 186859: ZulJinDoorGUID = pGo->GetGUID(); break;
|
||||
|
||||
case 187021: HarkorsSatchelGUID = pGo->GetGUID(); break;
|
||||
case 186648: TanzarsTrunkGUID = pGo->GetGUID(); break;
|
||||
case 186672: AshlisBagGUID = pGo->GetGUID(); break;
|
||||
case 186667: KrazsPackageGUID = pGo->GetGUID(); break;
|
||||
default: break;
|
||||
|
||||
}
|
||||
SummonHostage(1);
|
||||
}
|
||||
break;
|
||||
case DATA_JANALAIEVENT:
|
||||
m_auiEncounter[2] = data;
|
||||
if (data == DONE) SummonHostage(2);
|
||||
break;
|
||||
case DATA_HALAZZIEVENT:
|
||||
m_auiEncounter[3] = data;
|
||||
HandleGameObject(HalazziDoorGUID, data != IN_PROGRESS);
|
||||
if (data == DONE) SummonHostage(3);
|
||||
break;
|
||||
case DATA_HEXLORDEVENT:
|
||||
m_auiEncounter[4] = data;
|
||||
if (data == IN_PROGRESS)
|
||||
HandleGameObject(HexLordGateGUID, false);
|
||||
else if (data == NOT_STARTED)
|
||||
CheckInstanceStatus();
|
||||
break;
|
||||
case DATA_ZULJINEVENT:
|
||||
m_auiEncounter[5] = data;
|
||||
HandleGameObject(ZulJinDoorGUID, data != IN_PROGRESS);
|
||||
break;
|
||||
case DATA_CHESTLOOTED:
|
||||
++ChestLooted;
|
||||
SaveToDB();
|
||||
break;
|
||||
case TYPE_RAND_VENDOR_1:
|
||||
RandVendor[0] = data;
|
||||
break;
|
||||
case TYPE_RAND_VENDOR_2:
|
||||
RandVendor[1] = data;
|
||||
break;
|
||||
}
|
||||
|
||||
if (data == DONE)
|
||||
{
|
||||
++BossKilled;
|
||||
if (QuestMinute && BossKilled >= 4)
|
||||
{
|
||||
QuestMinute = 0;
|
||||
DoUpdateWorldState(3104, 0);
|
||||
}
|
||||
CheckInstanceStatus();
|
||||
SaveToDB();
|
||||
}
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case DATA_NALORAKKEVENT: return m_auiEncounter[0];
|
||||
case DATA_AKILZONEVENT: return m_auiEncounter[1];
|
||||
case DATA_JANALAIEVENT: return m_auiEncounter[2];
|
||||
case DATA_HALAZZIEVENT: return m_auiEncounter[3];
|
||||
case DATA_HEXLORDEVENT: return m_auiEncounter[4];
|
||||
case DATA_ZULJINEVENT: return m_auiEncounter[5];
|
||||
case DATA_CHESTLOOTED: return ChestLooted;
|
||||
case TYPE_RAND_VENDOR_1: return RandVendor[0];
|
||||
case TYPE_RAND_VENDOR_2: return RandVendor[1];
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Update(uint32 diff)
|
||||
{
|
||||
if (QuestMinute)
|
||||
{
|
||||
if (QuestTimer <= diff)
|
||||
void SummonHostage(uint8 num)
|
||||
{
|
||||
if (!QuestMinute)
|
||||
return;
|
||||
|
||||
Map::PlayerList const &PlayerList = instance->GetPlayers();
|
||||
if (PlayerList.isEmpty())
|
||||
return;
|
||||
|
||||
Map::PlayerList::const_iterator i = PlayerList.begin();
|
||||
if (Player* i_pl = i->getSource())
|
||||
{
|
||||
if (Unit* Hostage = i_pl->SummonCreature(HostageInfo[num].npc, HostageInfo[num].x, HostageInfo[num].y, HostageInfo[num].z, HostageInfo[num].o, TEMPSUMMON_DEAD_DESPAWN, 0))
|
||||
{
|
||||
Hostage->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
|
||||
Hostage->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CheckInstanceStatus()
|
||||
{
|
||||
if (BossKilled >= 4)
|
||||
HandleGameObject(HexLordGateGUID, true);
|
||||
|
||||
if (BossKilled >= 5)
|
||||
HandleGameObject(ZulJinGateGUID, true);
|
||||
}
|
||||
|
||||
std::string GetSaveData()
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << "S " << BossKilled << " " << ChestLooted << " " << QuestMinute;
|
||||
char* data = new char[ss.str().length()+1];
|
||||
strcpy(data, ss.str().c_str());
|
||||
//sLog.outError("TSCR: Zul'aman saved, %s.", data);
|
||||
return data;
|
||||
}
|
||||
|
||||
void Load(const char* load)
|
||||
{
|
||||
if (!load) return;
|
||||
std::istringstream ss(load);
|
||||
//sLog.outError("TSCR: Zul'aman loaded, %s.", ss.str().c_str());
|
||||
char dataHead; // S
|
||||
uint16 data1, data2, data3;
|
||||
ss >> dataHead >> data1 >> data2 >> data3;
|
||||
//sLog.outError("TSCR: Zul'aman loaded, %d %d %d.", data1, data2, data3);
|
||||
if (dataHead == 'S')
|
||||
{
|
||||
BossKilled = data1;
|
||||
ChestLooted = data2;
|
||||
QuestMinute = data3;
|
||||
} else sLog.outError("TSCR: Zul'aman: corrupted save data.");
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 data)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case DATA_NALORAKKEVENT:
|
||||
m_auiEncounter[0] = data;
|
||||
if (data == DONE)
|
||||
{
|
||||
if (QuestMinute)
|
||||
{
|
||||
QuestMinute += 15;
|
||||
DoUpdateWorldState(3106, QuestMinute);
|
||||
}
|
||||
SummonHostage(0);
|
||||
}
|
||||
break;
|
||||
case DATA_AKILZONEVENT:
|
||||
m_auiEncounter[1] = data;
|
||||
HandleGameObject(AkilzonDoorGUID, data != IN_PROGRESS);
|
||||
if (data == DONE)
|
||||
{
|
||||
if (QuestMinute)
|
||||
{
|
||||
QuestMinute += 10;
|
||||
DoUpdateWorldState(3106, QuestMinute);
|
||||
}
|
||||
SummonHostage(1);
|
||||
}
|
||||
break;
|
||||
case DATA_JANALAIEVENT:
|
||||
m_auiEncounter[2] = data;
|
||||
if (data == DONE) SummonHostage(2);
|
||||
break;
|
||||
case DATA_HALAZZIEVENT:
|
||||
m_auiEncounter[3] = data;
|
||||
HandleGameObject(HalazziDoorGUID, data != IN_PROGRESS);
|
||||
if (data == DONE) SummonHostage(3);
|
||||
break;
|
||||
case DATA_HEXLORDEVENT:
|
||||
m_auiEncounter[4] = data;
|
||||
if (data == IN_PROGRESS)
|
||||
HandleGameObject(HexLordGateGUID, false);
|
||||
else if (data == NOT_STARTED)
|
||||
CheckInstanceStatus();
|
||||
break;
|
||||
case DATA_ZULJINEVENT:
|
||||
m_auiEncounter[5] = data;
|
||||
HandleGameObject(ZulJinDoorGUID, data != IN_PROGRESS);
|
||||
break;
|
||||
case DATA_CHESTLOOTED:
|
||||
++ChestLooted;
|
||||
SaveToDB();
|
||||
break;
|
||||
case TYPE_RAND_VENDOR_1:
|
||||
RandVendor[0] = data;
|
||||
break;
|
||||
case TYPE_RAND_VENDOR_2:
|
||||
RandVendor[1] = data;
|
||||
break;
|
||||
}
|
||||
|
||||
if (data == DONE)
|
||||
{
|
||||
++BossKilled;
|
||||
if (QuestMinute && BossKilled >= 4)
|
||||
{
|
||||
QuestMinute = 0;
|
||||
DoUpdateWorldState(3104, 0);
|
||||
}
|
||||
CheckInstanceStatus();
|
||||
SaveToDB();
|
||||
}
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case DATA_NALORAKKEVENT: return m_auiEncounter[0];
|
||||
case DATA_AKILZONEVENT: return m_auiEncounter[1];
|
||||
case DATA_JANALAIEVENT: return m_auiEncounter[2];
|
||||
case DATA_HALAZZIEVENT: return m_auiEncounter[3];
|
||||
case DATA_HEXLORDEVENT: return m_auiEncounter[4];
|
||||
case DATA_ZULJINEVENT: return m_auiEncounter[5];
|
||||
case DATA_CHESTLOOTED: return ChestLooted;
|
||||
case TYPE_RAND_VENDOR_1: return RandVendor[0];
|
||||
case TYPE_RAND_VENDOR_2: return RandVendor[1];
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Update(uint32 diff)
|
||||
{
|
||||
QuestMinute--;
|
||||
SaveToDB();
|
||||
QuestTimer += 60000;
|
||||
if (QuestMinute)
|
||||
{
|
||||
DoUpdateWorldState(3104, 1);
|
||||
DoUpdateWorldState(3106, QuestMinute);
|
||||
} else DoUpdateWorldState(3104, 0);
|
||||
if (QuestTimer <= diff)
|
||||
{
|
||||
QuestMinute--;
|
||||
SaveToDB();
|
||||
QuestTimer += 60000;
|
||||
if (QuestMinute)
|
||||
{
|
||||
DoUpdateWorldState(3104, 1);
|
||||
DoUpdateWorldState(3106, QuestMinute);
|
||||
} else DoUpdateWorldState(3104, 0);
|
||||
}
|
||||
QuestTimer -= diff;
|
||||
}
|
||||
}
|
||||
QuestTimer -= diff;
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
InstanceData* GetInstanceData_instance_zulaman(Map* pMap)
|
||||
{
|
||||
return new instance_zulaman(pMap);
|
||||
}
|
||||
InstanceData* GetInstanceData(InstanceMap* pMap) const
|
||||
{
|
||||
return new instance_zulaman_InstanceMapScript(pMap);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_instance_zulaman()
|
||||
{
|
||||
Script *newscript;
|
||||
newscript = new Script;
|
||||
newscript->Name = "instance_zulaman";
|
||||
newscript->GetInstanceData = &GetInstanceData_instance_zulaman;
|
||||
newscript->RegisterSelf();
|
||||
new instance_zulaman();
|
||||
}
|
||||
|
||||
|
||||
@@ -38,64 +38,75 @@ EndContentData */
|
||||
#define SPELL_PUSH_MOJO 43923
|
||||
#define ENTRY_FOREST_FROG 24396
|
||||
|
||||
struct npc_forest_frogAI : public ScriptedAI
|
||||
class npc_forest_frog : public CreatureScript
|
||||
{
|
||||
npc_forest_frogAI(Creature* c) : ScriptedAI(c)
|
||||
{
|
||||
pInstance = c->GetInstanceData();
|
||||
}
|
||||
public:
|
||||
|
||||
ScriptedInstance *pInstance;
|
||||
|
||||
void Reset() {}
|
||||
|
||||
void EnterCombat(Unit * /*who*/) {}
|
||||
|
||||
void DoSpawnRandom()
|
||||
{
|
||||
if (pInstance)
|
||||
npc_forest_frog()
|
||||
: CreatureScript("npc_forest_frog")
|
||||
{
|
||||
uint32 cEntry = 0;
|
||||
switch(rand()%10)
|
||||
}
|
||||
|
||||
struct npc_forest_frogAI : public ScriptedAI
|
||||
{
|
||||
npc_forest_frogAI(Creature* c) : ScriptedAI(c)
|
||||
{
|
||||
case 0: cEntry = 24397; break; //Mannuth
|
||||
case 1: cEntry = 24403; break; //Deez
|
||||
case 2: cEntry = 24404; break; //Galathryn
|
||||
case 3: cEntry = 24405; break; //Adarrah
|
||||
case 4: cEntry = 24406; break; //Fudgerick
|
||||
case 5: cEntry = 24407; break; //Darwen
|
||||
case 6: cEntry = 24445; break; //Mitzi
|
||||
case 7: cEntry = 24448; break; //Christian
|
||||
case 8: cEntry = 24453; break; //Brennan
|
||||
case 9: cEntry = 24455; break; //Hollee
|
||||
pInstance = c->GetInstanceData();
|
||||
}
|
||||
|
||||
if (!pInstance->GetData(TYPE_RAND_VENDOR_1))
|
||||
if (rand()%10 == 1) cEntry = 24408; //Gunter
|
||||
if (!pInstance->GetData(TYPE_RAND_VENDOR_2))
|
||||
if (rand()%10 == 1) cEntry = 24409; //Kyren
|
||||
ScriptedInstance *pInstance;
|
||||
|
||||
if (cEntry) me->UpdateEntry(cEntry);
|
||||
void Reset() {}
|
||||
|
||||
if (cEntry == 24408) pInstance->SetData(TYPE_RAND_VENDOR_1,DONE);
|
||||
if (cEntry == 24409) pInstance->SetData(TYPE_RAND_VENDOR_2,DONE);
|
||||
}
|
||||
}
|
||||
void EnterCombat(Unit * /*who*/) {}
|
||||
|
||||
void SpellHit(Unit *caster, const SpellEntry *spell)
|
||||
{
|
||||
if (spell->Id == SPELL_REMOVE_AMANI_CURSE && caster->GetTypeId() == TYPEID_PLAYER && me->GetEntry() == ENTRY_FOREST_FROG)
|
||||
void DoSpawnRandom()
|
||||
{
|
||||
if (pInstance)
|
||||
{
|
||||
uint32 cEntry = 0;
|
||||
switch(rand()%10)
|
||||
{
|
||||
case 0: cEntry = 24397; break; //Mannuth
|
||||
case 1: cEntry = 24403; break; //Deez
|
||||
case 2: cEntry = 24404; break; //Galathryn
|
||||
case 3: cEntry = 24405; break; //Adarrah
|
||||
case 4: cEntry = 24406; break; //Fudgerick
|
||||
case 5: cEntry = 24407; break; //Darwen
|
||||
case 6: cEntry = 24445; break; //Mitzi
|
||||
case 7: cEntry = 24448; break; //Christian
|
||||
case 8: cEntry = 24453; break; //Brennan
|
||||
case 9: cEntry = 24455; break; //Hollee
|
||||
}
|
||||
|
||||
if (!pInstance->GetData(TYPE_RAND_VENDOR_1))
|
||||
if (rand()%10 == 1) cEntry = 24408; //Gunter
|
||||
if (!pInstance->GetData(TYPE_RAND_VENDOR_2))
|
||||
if (rand()%10 == 1) cEntry = 24409; //Kyren
|
||||
|
||||
if (cEntry) me->UpdateEntry(cEntry);
|
||||
|
||||
if (cEntry == 24408) pInstance->SetData(TYPE_RAND_VENDOR_1,DONE);
|
||||
if (cEntry == 24409) pInstance->SetData(TYPE_RAND_VENDOR_2,DONE);
|
||||
}
|
||||
}
|
||||
|
||||
void SpellHit(Unit *caster, const SpellEntry *spell)
|
||||
{
|
||||
if (spell->Id == SPELL_REMOVE_AMANI_CURSE && caster->GetTypeId() == TYPEID_PLAYER && me->GetEntry() == ENTRY_FOREST_FROG)
|
||||
{
|
||||
//increase or decrease chance of mojo?
|
||||
if (rand()%99 == 50) DoCast(caster, SPELL_PUSH_MOJO, true);
|
||||
else DoSpawnRandom();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
//increase or decrease chance of mojo?
|
||||
if (rand()%99 == 50) DoCast(caster, SPELL_PUSH_MOJO, true);
|
||||
else DoSpawnRandom();
|
||||
return new npc_forest_frogAI(creature);
|
||||
}
|
||||
}
|
||||
};
|
||||
CreatureAI* GetAI_npc_forest_frog(Creature* pCreature)
|
||||
{
|
||||
return new npc_forest_frogAI (pCreature);
|
||||
}
|
||||
|
||||
/*######
|
||||
## npc_zulaman_hostage
|
||||
@@ -106,89 +117,79 @@ CreatureAI* GetAI_npc_forest_frog(Creature* pCreature)
|
||||
static uint32 HostageEntry[] = {23790, 23999, 24024, 24001};
|
||||
static uint32 ChestEntry[] = {186648, 187021, 186672, 186667};
|
||||
|
||||
struct npc_zulaman_hostageAI : public ScriptedAI
|
||||
class npc_zulaman_hostage : public CreatureScript
|
||||
{
|
||||
npc_zulaman_hostageAI(Creature *c) : ScriptedAI(c) {IsLoot = false;}
|
||||
bool IsLoot;
|
||||
uint64 PlayerGUID;
|
||||
void Reset() {}
|
||||
void EnterCombat(Unit * /*who*/) {}
|
||||
void JustDied(Unit* /*who*/)
|
||||
{
|
||||
Player* pPlayer = Unit::GetPlayer(*me, PlayerGUID);
|
||||
if (pPlayer) pPlayer->SendLoot(me->GetGUID(), LOOT_CORPSE);
|
||||
}
|
||||
void UpdateAI(const uint32 /*diff*/)
|
||||
{
|
||||
if (IsLoot)
|
||||
DoCast(me, 7, false);
|
||||
}
|
||||
};
|
||||
public:
|
||||
|
||||
bool GossipHello_npc_zulaman_hostage(Player* pPlayer, Creature* pCreature)
|
||||
{
|
||||
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HOSTAGE1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GossipSelect_npc_zulaman_hostage(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction)
|
||||
{
|
||||
if (uiAction == GOSSIP_ACTION_INFO_DEF + 1)
|
||||
pPlayer->CLOSE_GOSSIP_MENU();
|
||||
|
||||
if (!pCreature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP))
|
||||
return true;
|
||||
pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
|
||||
|
||||
ScriptedInstance* pInstance = pCreature->GetInstanceData();
|
||||
if (pInstance)
|
||||
{
|
||||
//uint8 progress = pInstance->GetData(DATA_CHESTLOOTED);
|
||||
pInstance->SetData(DATA_CHESTLOOTED, 0);
|
||||
float x, y, z;
|
||||
pCreature->GetPosition(x, y, z);
|
||||
uint32 entry = pCreature->GetEntry();
|
||||
for (uint8 i = 0; i < 4; ++i)
|
||||
npc_zulaman_hostage()
|
||||
: CreatureScript("npc_zulaman_hostage")
|
||||
{
|
||||
if (HostageEntry[i] == entry)
|
||||
{
|
||||
pCreature->SummonGameObject(ChestEntry[i], x-2, y, z, 0, 0, 0, 0, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*Creature* summon = pCreature->SummonCreature(HostageInfo[progress], x-2, y, z, 0, TEMPSUMMON_DEAD_DESPAWN, 0);
|
||||
if (summon)
|
||||
{
|
||||
CAST_AI(npc_zulaman_hostageAI, summon->AI())->PlayerGUID = pPlayer->GetGUID();
|
||||
CAST_AI(npc_zulaman_hostageAI, summon->AI())->IsLoot = true;
|
||||
summon->SetDisplayId(10056);
|
||||
summon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
|
||||
summon->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
|
||||
}*/
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
CreatureAI* GetAI_npc_zulaman_hostage(Creature* pCreature)
|
||||
{
|
||||
return new npc_zulaman_hostageAI(pCreature);
|
||||
}
|
||||
struct npc_zulaman_hostageAI : public ScriptedAI
|
||||
{
|
||||
npc_zulaman_hostageAI(Creature *c) : ScriptedAI(c) {IsLoot = false;}
|
||||
bool IsLoot;
|
||||
uint64 PlayerGUID;
|
||||
void Reset() {}
|
||||
void EnterCombat(Unit * /*who*/) {}
|
||||
void JustDied(Unit* /*who*/)
|
||||
{
|
||||
Player* pPlayer = Unit::GetPlayer(*me, PlayerGUID);
|
||||
if (pPlayer) pPlayer->SendLoot(me->GetGUID(), LOOT_CORPSE);
|
||||
}
|
||||
void UpdateAI(const uint32 /*diff*/)
|
||||
{
|
||||
if (IsLoot)
|
||||
DoCast(me, 7, false);
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return new npc_zulaman_hostageAI(creature);
|
||||
}
|
||||
|
||||
bool OnGossipHello(Player* pPlayer, Creature* pCreature)
|
||||
{
|
||||
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HOSTAGE1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnGossipSelect(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction)
|
||||
{
|
||||
if (uiAction == GOSSIP_ACTION_INFO_DEF + 1)
|
||||
pPlayer->CLOSE_GOSSIP_MENU();
|
||||
|
||||
if (!pCreature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP))
|
||||
return true;
|
||||
pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
|
||||
|
||||
ScriptedInstance* pInstance = pCreature->GetInstanceData();
|
||||
if (pInstance)
|
||||
{
|
||||
//uint8 progress = pInstance->GetData(DATA_CHESTLOOTED);
|
||||
pInstance->SetData(DATA_CHESTLOOTED, 0);
|
||||
float x, y, z;
|
||||
pCreature->GetPosition(x, y, z);
|
||||
uint32 entry = pCreature->GetEntry();
|
||||
for (uint8 i = 0; i < 4; ++i)
|
||||
{
|
||||
if (HostageEntry[i] == entry)
|
||||
{
|
||||
pCreature->SummonGameObject(ChestEntry[i], x-2, y, z, 0, 0, 0, 0, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_zulaman()
|
||||
{
|
||||
Script *newscript;
|
||||
|
||||
newscript = new Script;
|
||||
newscript->Name = "npc_forest_frog";
|
||||
newscript->GetAI = &GetAI_npc_forest_frog;
|
||||
newscript->RegisterSelf();
|
||||
|
||||
newscript = new Script;
|
||||
newscript->Name = "npc_zulaman_hostage";
|
||||
newscript->GetAI = &GetAI_npc_zulaman_hostage;
|
||||
newscript->pGossipHello = &GossipHello_npc_zulaman_hostage;
|
||||
newscript->pGossipSelect = &GossipSelect_npc_zulaman_hostage;
|
||||
newscript->RegisterSelf();
|
||||
new npc_forest_frog();
|
||||
new npc_zulaman_hostage();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user