Big re-organization of repository [W.I.P]

This commit is contained in:
Yehonal
2016-08-11 20:25:27 +02:00
parent c62a72c0a8
commit 0f85ce1c54
3016 changed files with 1271 additions and 1 deletions

View File

@@ -1,260 +0,0 @@
/*
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "hyjal.h"
#include "hyjal_trash.h"
enum Spells
{
SPELL_CARRION_SWARM = 31306,
SPELL_SLEEP = 31298,
SPELL_VAMPIRIC_AURA = 38196,
SPELL_INFERNO = 31299,
SPELL_IMMOLATION = 31303,
SPELL_INFERNO_EFFECT = 31302,
};
enum Texts
{
SAY_ONDEATH = 0,
SAY_ONSLAY = 1,
SAY_SWARM = 2,
SAY_SLEEP = 3,
SAY_INFERNO = 4,
SAY_ONAGGRO = 5,
};
class boss_anetheron : public CreatureScript
{
public:
boss_anetheron() : CreatureScript("boss_anetheron") { }
CreatureAI* GetAI(Creature* creature) const
{
return GetInstanceAI<boss_anetheronAI>(creature);
}
struct boss_anetheronAI : public hyjal_trashAI
{
boss_anetheronAI(Creature* creature) : hyjal_trashAI(creature)
{
instance = creature->GetInstanceScript();
go = false;
}
uint32 SwarmTimer;
uint32 SleepTimer;
uint32 AuraTimer;
uint32 InfernoTimer;
bool go;
void Reset()
{
damageTaken = 0;
SwarmTimer = 45000;
SleepTimer = 60000;
AuraTimer = 5000;
InfernoTimer = 45000;
if (IsEvent)
instance->SetData(DATA_ANETHERONEVENT, NOT_STARTED);
}
void EnterCombat(Unit* /*who*/)
{
if (IsEvent)
instance->SetData(DATA_ANETHERONEVENT, IN_PROGRESS);
Talk(SAY_ONAGGRO);
}
void KilledUnit(Unit* who)
{
if (who->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_ONSLAY);
}
void WaypointReached(uint32 waypointId)
{
if (waypointId == 7)
{
Unit* target = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_JAINAPROUDMOORE));
if (target && target->IsAlive())
me->AddThreat(target, 0.0f);
}
}
void JustDied(Unit* killer)
{
hyjal_trashAI::JustDied(killer);
if (IsEvent)
instance->SetData(DATA_ANETHERONEVENT, DONE);
Talk(SAY_ONDEATH);
}
void UpdateAI(uint32 diff)
{
if (IsEvent)
{
//Must update npc_escortAI
npc_escortAI::UpdateAI(diff);
if (!go)
{
go = true;
AddWaypoint(0, 4896.08f, -1576.35f, 1333.65f);
AddWaypoint(1, 4898.68f, -1615.02f, 1329.48f);
AddWaypoint(2, 4907.12f, -1667.08f, 1321.00f);
AddWaypoint(3, 4963.18f, -1699.35f, 1340.51f);
AddWaypoint(4, 4989.16f, -1716.67f, 1335.74f);
AddWaypoint(5, 5026.27f, -1736.89f, 1323.02f);
AddWaypoint(6, 5037.77f, -1770.56f, 1324.36f);
AddWaypoint(7, 5067.23f, -1789.95f, 1321.17f);
Start(false, true);
SetDespawnAtEnd(false);
}
}
//Return since we have no target
if (!UpdateVictim())
return;
if (SwarmTimer <= diff)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(target, SPELL_CARRION_SWARM);
SwarmTimer = urand(45000, 60000);
Talk(SAY_SWARM);
} else SwarmTimer -= diff;
if (SleepTimer <= diff)
{
for (uint8 i = 0; i < 3; ++i)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
target->CastSpell(target, SPELL_SLEEP, true);
}
SleepTimer = 60000;
Talk(SAY_SLEEP);
} else SleepTimer -= diff;
if (AuraTimer <= diff)
{
DoCast(me, SPELL_VAMPIRIC_AURA, true);
AuraTimer = urand(10000, 20000);
} else AuraTimer -= diff;
if (InfernoTimer <= diff)
{
DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_INFERNO);
InfernoTimer = 45000;
Talk(SAY_INFERNO);
} else InfernoTimer -= diff;
DoMeleeAttackIfReady();
}
};
};
class npc_towering_infernal : public CreatureScript
{
public:
npc_towering_infernal() : CreatureScript("npc_towering_infernal") { }
CreatureAI* GetAI(Creature* creature) const
{
return GetInstanceAI<npc_towering_infernalAI>(creature);
}
struct npc_towering_infernalAI : public ScriptedAI
{
npc_towering_infernalAI(Creature* creature) : ScriptedAI(creature)
{
instance = creature->GetInstanceScript();
AnetheronGUID = instance->GetData64(DATA_ANETHERON);
}
uint32 ImmolationTimer;
uint32 CheckTimer;
uint64 AnetheronGUID;
InstanceScript* instance;
void Reset()
{
DoCast(me, SPELL_INFERNO_EFFECT);
ImmolationTimer = 5000;
CheckTimer = 5000;
}
void EnterCombat(Unit* /*who*/)
{
}
void KilledUnit(Unit* /*victim*/)
{
}
void JustDied(Unit* /*killer*/)
{
}
void MoveInLineOfSight(Unit* who)
{
if (me->IsWithinDist(who, 50) && !me->IsInCombat() && me->IsValidAttackTarget(who))
AttackStart(who);
}
void UpdateAI(uint32 diff)
{
if (CheckTimer <= diff)
{
if (AnetheronGUID)
{
Creature* boss = ObjectAccessor::GetCreature(*me, AnetheronGUID);
if (!boss || (boss && boss->isDead()))
{
me->setDeathState(JUST_DIED);
me->RemoveCorpse();
return;
}
}
CheckTimer = 5000;
} else CheckTimer -= diff;
//Return since we have no target
if (!UpdateVictim())
return;
if (ImmolationTimer <= diff)
{
DoCast(me, SPELL_IMMOLATION);
ImmolationTimer = 5000;
} else ImmolationTimer -= diff;
DoMeleeAttackIfReady();
}
};
};
void AddSC_boss_anetheron()
{
new boss_anetheron();
new npc_towering_infernal();
}

View File

@@ -1,644 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* ScriptData
SDName: Boss_Archimonde
SD%Complete: 85
SDComment: Doomfires not completely offlike due to core limitations for random moving. Tyrande and second phase not fully implemented.
SDCategory: Caverns of Time, Mount Hyjal
EndScriptData */
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "hyjal.h"
#include "SpellAuras.h"
#include "hyjal_trash.h"
#include "Player.h"
enum Texts
{
SAY_AGGRO = 1,
SAY_DOOMFIRE = 2,
SAY_AIR_BURST = 3,
SAY_SLAY = 4,
SAY_ENRAGE = 5,
SAY_DEATH = 6,
SAY_SOUL_CHARGE = 7,
};
enum Spells
{
SPELL_DENOUEMENT_WISP = 32124,
SPELL_ANCIENT_SPARK = 39349,
SPELL_PROTECTION_OF_ELUNE = 38528,
SPELL_DRAIN_WORLD_TREE = 39140,
SPELL_DRAIN_WORLD_TREE_2 = 39141,
SPELL_FINGER_OF_DEATH = 31984,
SPELL_HAND_OF_DEATH = 35354,
SPELL_AIR_BURST = 32014,
SPELL_GRIP_OF_THE_LEGION = 31972,
SPELL_DOOMFIRE_STRIKE = 31903, //summons two creatures
SPELL_DOOMFIRE_SPAWN = 32074,
SPELL_DOOMFIRE = 31945,
SPELL_SOUL_CHARGE_YELLOW = 32045,
SPELL_SOUL_CHARGE_GREEN = 32051,
SPELL_SOUL_CHARGE_RED = 32052,
SPELL_UNLEASH_SOUL_YELLOW = 32054,
SPELL_UNLEASH_SOUL_GREEN = 32057,
SPELL_UNLEASH_SOUL_RED = 32053,
SPELL_FEAR = 31970,
};
enum Summons
{
CREATURE_DOOMFIRE = 18095,
CREATURE_DOOMFIRE_SPIRIT = 18104,
CREATURE_ANCIENT_WISP = 17946,
CREATURE_CHANNEL_TARGET = 22418,
};
Position const NordrassilLoc = {5503.713f, -3523.436f, 1608.781f, 0.0f};
class npc_ancient_wisp : public CreatureScript
{
public:
npc_ancient_wisp() : CreatureScript("npc_ancient_wisp") { }
CreatureAI* GetAI(Creature* creature) const
{
return GetInstanceAI<npc_ancient_wispAI>(creature);
}
struct npc_ancient_wispAI : public ScriptedAI
{
npc_ancient_wispAI(Creature* creature) : ScriptedAI(creature)
{
instance = creature->GetInstanceScript();
ArchimondeGUID = 0;
}
InstanceScript* instance;
uint64 ArchimondeGUID;
uint32 CheckTimer;
void Reset()
{
CheckTimer = 1000;
ArchimondeGUID = instance->GetData64(DATA_ARCHIMONDE);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
}
void EnterCombat(Unit* /*who*/) { }
void DamageTaken(Unit*, uint32 &damage, DamageEffectType, SpellSchoolMask)
{
damage = 0;
}
void UpdateAI(uint32 diff)
{
if (CheckTimer <= diff)
{
if (Unit* Archimonde = ObjectAccessor::GetUnit(*me, ArchimondeGUID))
{
if (Archimonde->HealthBelowPct(2) || !Archimonde->IsAlive())
DoCast(me, SPELL_DENOUEMENT_WISP);
else
DoCast(Archimonde, SPELL_ANCIENT_SPARK);
}
CheckTimer = 1000;
} else CheckTimer -= diff;
}
};
};
/* This script is merely a placeholder for the Doomfire that triggers Doomfire spell. It will
MoveChase the Doomfire Spirit always, until despawn (AttackStart is called upon it's spawn) */
class npc_doomfire : public CreatureScript
{
public:
npc_doomfire() : CreatureScript("npc_doomfire") { }
CreatureAI* GetAI(Creature* creature) const
{
return new npc_doomfireAI(creature);
}
struct npc_doomfireAI : public ScriptedAI
{
npc_doomfireAI(Creature* creature) : ScriptedAI(creature) { }
void Reset() { }
void MoveInLineOfSight(Unit* /*who*/) { }
void EnterCombat(Unit* /*who*/) { }
void DamageTaken(Unit*, uint32 &damage, DamageEffectType, SpellSchoolMask)
{
damage = 0;
}
};
};
/* This is the script for the Doomfire Spirit Mob. This mob simply follow players or
travels in random directions if target cannot be found. */
class npc_doomfire_targetting : public CreatureScript
{
public:
npc_doomfire_targetting() : CreatureScript("npc_doomfire_targetting") { }
CreatureAI* GetAI(Creature* creature) const
{
return new npc_doomfire_targettingAI(creature);
}
struct npc_doomfire_targettingAI : public ScriptedAI
{
npc_doomfire_targettingAI(Creature* creature) : ScriptedAI(creature) { }
uint64 TargetGUID;
uint32 ChangeTargetTimer;
void Reset()
{
TargetGUID = 0;
ChangeTargetTimer = 5000;
}
void MoveInLineOfSight(Unit* who)
{
//will update once TargetGUID is 0. In case noone actually moves(not likely) and this is 0
//when UpdateAI needs it, it will be forced to select randomPoint
if (!TargetGUID && who->GetTypeId() == TYPEID_PLAYER)
TargetGUID = who->GetGUID();
}
void EnterCombat(Unit* /*who*/) { }
void DamageTaken(Unit*, uint32 &damage, DamageEffectType, SpellSchoolMask)
{
damage = 0;
}
void UpdateAI(uint32 diff)
{
if (ChangeTargetTimer <= diff)
{
if (Unit* temp = ObjectAccessor::GetUnit(*me, TargetGUID))
{
me->GetMotionMaster()->MoveFollow(temp, 0.0f, 0.0f);
TargetGUID = 0;
}
else
{
Position pos;
me->GetRandomNearPosition(pos, 40);
me->GetMotionMaster()->MovePoint(0, pos.m_positionX, pos.m_positionY, pos.m_positionZ);
}
ChangeTargetTimer = 5000;
} else ChangeTargetTimer -= diff;
}
};
};
/* Finally, Archimonde's script. His script isn't extremely complex, most are simply spells on timers.
The only complicated aspect of the battle is Finger of Death and Doomfire, with Doomfire being the
hardest bit to code. Finger of Death is simply a distance check - if no one is in melee range, then
select a random target and cast the spell on them. However, if someone IS in melee range, and this
is NOT the main tank (creature's victim), then we aggro that player and they become the new victim.
For Doomfire, we summon a mob (Doomfire Spirit) for the Doomfire mob to follow. It's spirit will
randomly select it's target to follow and then we create the random movement making it unpredictable. */
class boss_archimonde : public CreatureScript
{
public:
boss_archimonde() : CreatureScript("boss_archimonde") { }
CreatureAI* GetAI(Creature* creature) const
{
return GetInstanceAI<boss_archimondeAI>(creature);
}
struct boss_archimondeAI : public hyjal_trashAI
{
boss_archimondeAI(Creature* creature) : hyjal_trashAI(creature)
{
instance = creature->GetInstanceScript();
}
InstanceScript* instance;
uint64 DoomfireSpiritGUID;
uint64 WorldTreeGUID;
uint32 DrainNordrassilTimer;
uint32 FearTimer;
uint32 AirBurstTimer;
uint32 GripOfTheLegionTimer;
uint32 DoomfireTimer;
uint32 SoulChargeTimer;
uint8 SoulChargeCount;
uint32 MeleeRangeCheckTimer;
uint32 HandOfDeathTimer;
uint32 SummonWispTimer;
uint8 WispCount;
uint32 EnrageTimer;
uint32 CheckDistanceTimer;
bool Enraged;
bool BelowTenPercent;
bool HasProtected;
bool IsChanneling;
void Reset()
{
instance->SetData(DATA_ARCHIMONDEEVENT, NOT_STARTED);
DoomfireSpiritGUID = 0;
damageTaken = 0;
WorldTreeGUID = 0;
DrainNordrassilTimer = 0;
FearTimer = 42000;
AirBurstTimer = 30000;
GripOfTheLegionTimer = urand(5000, 25000);
DoomfireTimer = 20000;
SoulChargeTimer = urand(2000, 30000);
SoulChargeCount = 0;
MeleeRangeCheckTimer = 15000;
HandOfDeathTimer = 2000;
WispCount = 0; // When ~30 wisps are summoned, Archimonde dies
EnrageTimer = 600000; // 10 minutes
CheckDistanceTimer = 30000; // This checks if he's too close to the World Tree (75 yards from a point on the tree), if true then he will enrage
SummonWispTimer = 0;
Enraged = false;
BelowTenPercent = false;
HasProtected = false;
IsChanneling = false;
}
void EnterCombat(Unit* /*who*/)
{
me->InterruptSpell(CURRENT_CHANNELED_SPELL);
Talk(SAY_AGGRO);
DoZoneInCombat();
instance->SetData(DATA_ARCHIMONDEEVENT, IN_PROGRESS);
}
void KilledUnit(Unit* victim)
{
Talk(SAY_SLAY);
if (victim && victim->GetTypeId() == TYPEID_PLAYER)
GainSoulCharge(victim->ToPlayer());
}
void GainSoulCharge(Player* victim)
{
switch (victim->getClass())
{
case CLASS_PRIEST:
case CLASS_PALADIN:
case CLASS_WARLOCK:
victim->CastSpell(me, SPELL_SOUL_CHARGE_RED, true);
break;
case CLASS_MAGE:
case CLASS_ROGUE:
case CLASS_WARRIOR:
victim->CastSpell(me, SPELL_SOUL_CHARGE_YELLOW, true);
break;
case CLASS_DRUID:
case CLASS_SHAMAN:
case CLASS_HUNTER:
victim->CastSpell(me, SPELL_SOUL_CHARGE_GREEN, true);
break;
}
SoulChargeTimer = urand(2000, 30000);
++SoulChargeCount;
}
void JustDied(Unit* killer)
{
hyjal_trashAI::JustDied(killer);
Talk(SAY_DEATH);
instance->SetData(DATA_ARCHIMONDEEVENT, DONE);
instance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, me->GetEntry(), 1, me); }
bool CanUseFingerOfDeath()
{
// First we check if our current victim is in melee range or not.
Unit* victim = me->GetVictim();
if (victim && me->IsWithinDistInMap(victim, me->GetAggroRange(victim)))
return false;
ThreatContainer::StorageType const &threatlist = me->getThreatManager().getThreatList();
if (threatlist.empty())
return false;
std::list<Unit*> targets;
ThreatContainer::StorageType::const_iterator itr = threatlist.begin();
for (; itr != threatlist.end(); ++itr)
{
Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid());
if (unit && unit->IsAlive())
targets.push_back(unit);
}
if (targets.empty())
return false;
targets.sort(Trinity::ObjectDistanceOrderPred(me));
Unit* target = targets.front();
if (target)
{
if (!me->IsWithinDistInMap(target, me->GetAggroRange(target)))
return true; // Cast Finger of Death
else // This target is closest, he is our new tank
me->AddThreat(target, me->getThreatManager().getThreat(me->GetVictim()));
}
return false;
}
void JustSummoned(Creature* summoned)
{
if (summoned->GetEntry() == CREATURE_ANCIENT_WISP)
summoned->AI()->AttackStart(me);
else
{
summoned->setFaction(me->getFaction());
summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
}
if (summoned->GetEntry() == CREATURE_DOOMFIRE_SPIRIT)
{
DoomfireSpiritGUID = summoned->GetGUID();
}
if (summoned->GetEntry() == CREATURE_DOOMFIRE)
{
summoned->CastSpell(summoned, SPELL_DOOMFIRE_SPAWN, false);
summoned->CastSpell(summoned, SPELL_DOOMFIRE, true, 0, 0, me->GetGUID());
if (Unit* DoomfireSpirit = ObjectAccessor::GetUnit(*me, DoomfireSpiritGUID))
{
summoned->GetMotionMaster()->MoveFollow(DoomfireSpirit, 0.0f, 0.0f);
DoomfireSpiritGUID = 0;
}
}
}
//this is code doing close to what the summoning spell would do (spell 31903)
void SummonDoomfire(Unit* target)
{
me->SummonCreature(CREATURE_DOOMFIRE_SPIRIT,
target->GetPositionX()+15.0f, target->GetPositionY()+15.0f, target->GetPositionZ(), 0,
TEMPSUMMON_TIMED_DESPAWN, 27000);
me->SummonCreature(CREATURE_DOOMFIRE,
target->GetPositionX()-15.0f, target->GetPositionY()-15.0f, target->GetPositionZ(), 0,
TEMPSUMMON_TIMED_DESPAWN, 27000);
}
void UnleashSoulCharge()
{
me->InterruptNonMeleeSpells(false);
bool HasCast = false;
uint32 chargeSpell = 0;
uint32 unleashSpell = 0;
switch (urand(0, 2))
{
case 0:
chargeSpell = SPELL_SOUL_CHARGE_RED;
unleashSpell = SPELL_UNLEASH_SOUL_RED;
break;
case 1:
chargeSpell = SPELL_SOUL_CHARGE_YELLOW;
unleashSpell = SPELL_UNLEASH_SOUL_YELLOW;
break;
case 2:
chargeSpell = SPELL_SOUL_CHARGE_GREEN;
unleashSpell = SPELL_UNLEASH_SOUL_GREEN;
break;
}
if (me->HasAura(chargeSpell))
{
me->RemoveAuraFromStack(chargeSpell);
DoCastVictim(unleashSpell);
HasCast = true;
SoulChargeCount--;
}
if (HasCast)
SoulChargeTimer = urand(2000, 30000);
}
void UpdateAI(uint32 diff)
{
if (!me->IsInCombat())
{
// Do not let the raid skip straight to Archimonde. Visible and hostile ONLY if Azagalor is finished.
if ((instance->GetData(DATA_AZGALOREVENT) < DONE) && (me->IsVisible() || (me->getFaction() != 35)))
{
me->SetVisible(false);
me->setFaction(35);
}
else if ((instance->GetData(DATA_AZGALOREVENT) >= DONE) && (!me->IsVisible() || (me->getFaction() == 35)))
{
me->setFaction(1720);
me->SetVisible(true);
}
if (DrainNordrassilTimer <= diff)
{
if (!IsChanneling)
{
Creature* temp = me->SummonCreature(CREATURE_CHANNEL_TARGET, NordrassilLoc, TEMPSUMMON_TIMED_DESPAWN, 1200000);
if (temp)
WorldTreeGUID = temp->GetGUID();
if (Unit* Nordrassil = ObjectAccessor::GetUnit(*me, WorldTreeGUID))
{
Nordrassil->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
Nordrassil->SetDisplayId(11686);
DoCast(Nordrassil, SPELL_DRAIN_WORLD_TREE);
IsChanneling = true;
}
}
if (Unit* Nordrassil = ObjectAccessor::GetUnit(*me, WorldTreeGUID))
{
Nordrassil->CastSpell(me, SPELL_DRAIN_WORLD_TREE_2, true);
DrainNordrassilTimer = 1000;
}
} else DrainNordrassilTimer -= diff;
}
if (!UpdateVictim())
return;
if (me->HealthBelowPct(10) && !BelowTenPercent && !Enraged)
BelowTenPercent = true;
if (!Enraged)
{
if (EnrageTimer <= diff)
{
if (HealthAbovePct(10))
{
me->GetMotionMaster()->Clear(false);
me->GetMotionMaster()->MoveIdle();
Enraged = true;
Talk(SAY_ENRAGE);
}
} else EnrageTimer -= diff;
if (CheckDistanceTimer <= diff)
{
// To simplify the check, we simply summon a Creature in the location and then check how far we are from the creature
Creature* Check = me->SummonCreature(CREATURE_CHANNEL_TARGET, NordrassilLoc, TEMPSUMMON_TIMED_DESPAWN, 2000);
if (Check)
{
Check->SetVisible(false);
if (me->IsWithinDistInMap(Check, 75))
{
me->GetMotionMaster()->Clear(false);
me->GetMotionMaster()->MoveIdle();
Enraged = true;
Talk(SAY_ENRAGE);
}
}
CheckDistanceTimer = 5000;
} else CheckDistanceTimer -= diff;
}
if (BelowTenPercent)
{
if (!HasProtected)
{
me->GetMotionMaster()->Clear(false);
me->GetMotionMaster()->MoveIdle();
//all members of raid must get this buff
DoCastVictim(SPELL_PROTECTION_OF_ELUNE, true);
HasProtected = true;
Enraged = true;
}
if (SummonWispTimer <= diff)
{
DoSpawnCreature(CREATURE_ANCIENT_WISP, float(rand()%40), float(rand()%40), 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
SummonWispTimer = 1500;
++WispCount;
} else SummonWispTimer -= diff;
if (WispCount >= 30)
Unit::DealDamage(me, me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
}
if (Enraged)
{
if (HandOfDeathTimer <= diff)
{
DoCastVictim(SPELL_HAND_OF_DEATH);
HandOfDeathTimer = 2000;
} else HandOfDeathTimer -= diff;
return; // Don't do anything after this point.
}
if (SoulChargeCount)
{
if (SoulChargeTimer <= diff)
UnleashSoulCharge();
else SoulChargeTimer -= diff;
}
if (GripOfTheLegionTimer <= diff)
{
DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), SPELL_GRIP_OF_THE_LEGION);
GripOfTheLegionTimer = urand(5000, 25000);
} else GripOfTheLegionTimer -= diff;
if (AirBurstTimer <= diff)
{
Talk(SAY_AIR_BURST);
DoCast(SelectTarget(SELECT_TARGET_RANDOM, 1), SPELL_AIR_BURST);//not on tank
AirBurstTimer = urand(25000, 40000);
} else AirBurstTimer -= diff;
if (FearTimer <= diff)
{
DoCastVictim(SPELL_FEAR);
FearTimer = 42000;
} else FearTimer -= diff;
if (DoomfireTimer <= diff)
{
Talk(SAY_DOOMFIRE);
Unit* temp = SelectTarget(SELECT_TARGET_RANDOM, 1);
if (!temp)
temp = me->GetVictim();
//replace with spell cast 31903 once implicitTarget 73 implemented
SummonDoomfire(temp);
//supposedly three doomfire can be up at the same time
DoomfireTimer = 20000;
} else DoomfireTimer -= diff;
if (MeleeRangeCheckTimer <= diff)
{
if (CanUseFingerOfDeath())
{
DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), SPELL_FINGER_OF_DEATH);
MeleeRangeCheckTimer = 1000;
}
MeleeRangeCheckTimer = 5000;
} else MeleeRangeCheckTimer -= diff;
DoMeleeAttackIfReady();
}
void WaypointReached(uint32 /*waypointId*/) { }
};
};
void AddSC_boss_archimonde()
{
new boss_archimonde();
new npc_doomfire();
new npc_doomfire_targetting();
new npc_ancient_wisp();
}

View File

@@ -1,278 +0,0 @@
/*
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "hyjal.h"
#include "hyjal_trash.h"
enum Spells
{
SPELL_RAIN_OF_FIRE = 31340,
SPELL_DOOM = 31347,
SPELL_HOWL_OF_AZGALOR = 31344,
SPELL_CLEAVE = 31345,
SPELL_BERSERK = 26662,
SPELL_THRASH = 12787,
SPELL_CRIPPLE = 31406,
SPELL_WARSTOMP = 31408,
};
enum Texts
{
SAY_ONDEATH = 0,
SAY_ONSLAY = 1,
SAY_DOOM = 2, // Not used?
SAY_ONAGGRO = 3,
};
class boss_azgalor : public CreatureScript
{
public:
boss_azgalor() : CreatureScript("boss_azgalor") { }
CreatureAI* GetAI(Creature* creature) const
{
return GetInstanceAI<boss_azgalorAI>(creature);
}
struct boss_azgalorAI : public hyjal_trashAI
{
boss_azgalorAI(Creature* creature) : hyjal_trashAI(creature)
{
instance = creature->GetInstanceScript();
go = false;
}
uint32 RainTimer;
uint32 DoomTimer;
uint32 HowlTimer;
uint32 CleaveTimer;
uint32 EnrageTimer;
bool enraged;
bool go;
void Reset()
{
damageTaken = 0;
RainTimer = 20000;
DoomTimer = 50000;
HowlTimer = 30000;
CleaveTimer = 10000;
EnrageTimer = 600000;
enraged = false;
if (IsEvent)
instance->SetData(DATA_AZGALOREVENT, NOT_STARTED);
}
void EnterCombat(Unit* /*who*/)
{
if (IsEvent)
instance->SetData(DATA_AZGALOREVENT, IN_PROGRESS);
Talk(SAY_ONAGGRO);
}
void KilledUnit(Unit* /*victim*/)
{
Talk(SAY_ONSLAY);
}
void WaypointReached(uint32 waypointId)
{
if (waypointId == 7 && instance)
{
Unit* target = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_THRALL));
if (target && target->IsAlive())
me->AddThreat(target, 0.0f);
}
}
void JustDied(Unit* killer)
{
hyjal_trashAI::JustDied(killer);
if (IsEvent)
instance->SetData(DATA_AZGALOREVENT, DONE);
Talk(SAY_ONDEATH);
}
void UpdateAI(uint32 diff)
{
if (IsEvent)
{
//Must update npc_escortAI
npc_escortAI::UpdateAI(diff);
if (!go)
{
go = true;
AddWaypoint(0, 5492.91f, -2404.61f, 1462.63f);
AddWaypoint(1, 5531.76f, -2460.87f, 1469.55f);
AddWaypoint(2, 5554.58f, -2514.66f, 1476.12f);
AddWaypoint(3, 5554.16f, -2567.23f, 1479.90f);
AddWaypoint(4, 5540.67f, -2625.99f, 1480.89f);
AddWaypoint(5, 5508.16f, -2659.2f, 1480.15f);
AddWaypoint(6, 5489.62f, -2704.05f, 1482.18f);
AddWaypoint(7, 5457.04f, -2726.26f, 1485.10f);
Start(false, true);
SetDespawnAtEnd(false);
}
}
//Return since we have no target
if (!UpdateVictim())
return;
if (RainTimer <= diff)
{
DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 30, true), SPELL_RAIN_OF_FIRE);
RainTimer = 20000+rand()%15000;
} else RainTimer -= diff;
if (DoomTimer <= diff)
{
DoCast(SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true), SPELL_DOOM);//never on tank
DoomTimer = 45000+rand()%5000;
} else DoomTimer -= diff;
if (HowlTimer <= diff)
{
DoCast(me, SPELL_HOWL_OF_AZGALOR);
HowlTimer = 30000;
} else HowlTimer -= diff;
if (CleaveTimer <= diff)
{
DoCastVictim(SPELL_CLEAVE);
CleaveTimer = 10000+rand()%5000;
} else CleaveTimer -= diff;
if (EnrageTimer < diff && !enraged)
{
me->InterruptNonMeleeSpells(false);
DoCast(me, SPELL_BERSERK, true);
enraged = true;
EnrageTimer = 600000;
} else EnrageTimer -= diff;
DoMeleeAttackIfReady();
}
};
};
class npc_lesser_doomguard : public CreatureScript
{
public:
npc_lesser_doomguard() : CreatureScript("npc_lesser_doomguard") { }
CreatureAI* GetAI(Creature* creature) const
{
return GetInstanceAI<npc_lesser_doomguardAI>(creature);
}
struct npc_lesser_doomguardAI : public hyjal_trashAI
{
npc_lesser_doomguardAI(Creature* creature) : hyjal_trashAI(creature)
{
instance = creature->GetInstanceScript();
AzgalorGUID = instance->GetData64(DATA_AZGALOR);
}
uint32 CrippleTimer;
uint32 WarstompTimer;
uint32 CheckTimer;
uint64 AzgalorGUID;
InstanceScript* instance;
void Reset()
{
CrippleTimer = 50000;
WarstompTimer = 10000;
DoCast(me, SPELL_THRASH);
CheckTimer = 5000;
}
void EnterCombat(Unit* /*who*/)
{
}
void KilledUnit(Unit* /*victim*/)
{
}
void WaypointReached(uint32 /*waypointId*/)
{
}
void MoveInLineOfSight(Unit* who)
{
if (me->IsWithinDist(who, 50) && !me->IsInCombat() && me->IsValidAttackTarget(who))
AttackStart(who);
}
void JustDied(Unit* /*killer*/)
{
}
void UpdateAI(uint32 diff)
{
if (CheckTimer <= diff)
{
if (AzgalorGUID)
{
Creature* boss = ObjectAccessor::GetCreature(*me, AzgalorGUID);
if (!boss || (boss && boss->isDead()))
{
me->setDeathState(JUST_DIED);
me->RemoveCorpse();
return;
}
}
CheckTimer = 5000;
} else CheckTimer -= diff;
//Return since we have no target
if (!UpdateVictim())
return;
if (WarstompTimer <= diff)
{
DoCast(me, SPELL_WARSTOMP);
WarstompTimer = 10000+rand()%5000;
} else WarstompTimer -= diff;
if (CrippleTimer <= diff)
{
DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_CRIPPLE);
CrippleTimer = 25000+rand()%5000;
} else CrippleTimer -= diff;
DoMeleeAttackIfReady();
}
};
};
void AddSC_boss_azgalor()
{
new boss_azgalor();
new npc_lesser_doomguard();
}

View File

@@ -1,230 +0,0 @@
/*
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "SpellAuraEffects.h"
#include "SpellScript.h"
#include "hyjal.h"
#include "hyjal_trash.h"
enum Spells
{
SPELL_CLEAVE = 31436,
SPELL_WARSTOMP = 31480,
SPELL_MARK = 31447,
SPELL_MARK_DAMAGE = 31463
};
enum Texts
{
SAY_ONSLAY = 0,
SAY_MARK = 1,
SAY_ONAGGRO = 2,
};
enum Sounds
{
SOUND_ONDEATH = 11018,
};
class boss_kazrogal : public CreatureScript
{
public:
boss_kazrogal() : CreatureScript("boss_kazrogal") { }
CreatureAI* GetAI(Creature* creature) const
{
return GetInstanceAI<boss_kazrogalAI>(creature);
}
struct boss_kazrogalAI : public hyjal_trashAI
{
boss_kazrogalAI(Creature* creature) : hyjal_trashAI(creature)
{
instance = creature->GetInstanceScript();
go = false;
}
uint32 CleaveTimer;
uint32 WarStompTimer;
uint32 MarkTimer;
uint32 MarkTimerBase;
bool go;
void Reset()
{
damageTaken = 0;
CleaveTimer = 5000;
WarStompTimer = 15000;
MarkTimer = 45000;
MarkTimerBase = 45000;
if (IsEvent)
instance->SetData(DATA_KAZROGALEVENT, NOT_STARTED);
}
void EnterCombat(Unit* /*who*/)
{
if (IsEvent)
instance->SetData(DATA_KAZROGALEVENT, IN_PROGRESS);
Talk(SAY_ONAGGRO);
}
void KilledUnit(Unit* /*victim*/)
{
Talk(SAY_ONSLAY);
}
void WaypointReached(uint32 waypointId)
{
if (waypointId == 7 && instance)
{
Unit* target = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_THRALL));
if (target && target->IsAlive())
me->AddThreat(target, 0.0f);
}
}
void JustDied(Unit* killer)
{
hyjal_trashAI::JustDied(killer);
if (IsEvent)
instance->SetData(DATA_KAZROGALEVENT, DONE);
DoPlaySoundToSet(me, SOUND_ONDEATH);
}
void UpdateAI(uint32 diff)
{
if (IsEvent)
{
//Must update npc_escortAI
npc_escortAI::UpdateAI(diff);
if (!go)
{
go = true;
AddWaypoint(0, 5492.91f, -2404.61f, 1462.63f);
AddWaypoint(1, 5531.76f, -2460.87f, 1469.55f);
AddWaypoint(2, 5554.58f, -2514.66f, 1476.12f);
AddWaypoint(3, 5554.16f, -2567.23f, 1479.90f);
AddWaypoint(4, 5540.67f, -2625.99f, 1480.89f);
AddWaypoint(5, 5508.16f, -2659.2f, 1480.15f);
AddWaypoint(6, 5489.62f, -2704.05f, 1482.18f);
AddWaypoint(7, 5457.04f, -2726.26f, 1485.10f);
Start(false, true);
SetDespawnAtEnd(false);
}
}
//Return since we have no target
if (!UpdateVictim())
return;
if (CleaveTimer <= diff)
{
DoCast(me, SPELL_CLEAVE);
CleaveTimer = 6000+rand()%15000;
} else CleaveTimer -= diff;
if (WarStompTimer <= diff)
{
DoCast(me, SPELL_WARSTOMP);
WarStompTimer = 60000;
} else WarStompTimer -= diff;
if (MarkTimer <= diff)
{
DoCastAOE(SPELL_MARK);
MarkTimerBase -= 5000;
if (MarkTimerBase < 5500)
MarkTimerBase = 5500;
MarkTimer = MarkTimerBase;
Talk(SAY_MARK);
} else MarkTimer -= diff;
DoMeleeAttackIfReady();
}
};
};
class spell_mark_of_kazrogal : public SpellScriptLoader
{
public:
spell_mark_of_kazrogal() : SpellScriptLoader("spell_mark_of_kazrogal") { }
class spell_mark_of_kazrogal_SpellScript : public SpellScript
{
PrepareSpellScript(spell_mark_of_kazrogal_SpellScript);
void FilterTargets(std::list<WorldObject*>& targets)
{
targets.remove_if(Trinity::PowerCheck(POWER_MANA, false));
}
void Register()
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mark_of_kazrogal_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
}
};
class spell_mark_of_kazrogal_AuraScript : public AuraScript
{
PrepareAuraScript(spell_mark_of_kazrogal_AuraScript);
bool Validate(SpellInfo const* /*spell*/)
{
if (!sSpellMgr->GetSpellInfo(SPELL_MARK_DAMAGE))
return false;
return true;
}
void OnPeriodic(AuraEffect const* aurEff)
{
Unit* target = GetTarget();
if (target->GetPower(POWER_MANA) == 0)
{
target->CastSpell(target, SPELL_MARK_DAMAGE, true, NULL, aurEff);
// Remove aura
SetDuration(0);
}
}
void Register()
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_mark_of_kazrogal_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_MANA_LEECH);
}
};
SpellScript* GetSpellScript() const
{
return new spell_mark_of_kazrogal_SpellScript();
}
AuraScript* GetAuraScript() const
{
return new spell_mark_of_kazrogal_AuraScript();
}
};
void AddSC_boss_kazrogal()
{
new boss_kazrogal();
new spell_mark_of_kazrogal();
}

View File

@@ -1,164 +0,0 @@
/*
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "hyjal.h"
#include "hyjal_trash.h"
enum Spells
{
SPELL_FROST_ARMOR = 31256,
SPELL_DEATH_AND_DECAY = 31258,
SPELL_FROST_NOVA = 31250,
SPELL_ICEBOLT = 31249
};
enum Texts
{
SAY_ONDEATH = 0,
SAY_ONSLAY = 1,
SAY_DECAY = 2,
SAY_NOVA = 3,
SAY_ONAGGRO = 4
};
class boss_rage_winterchill : public CreatureScript
{
public:
boss_rage_winterchill() : CreatureScript("boss_rage_winterchill") { }
CreatureAI* GetAI(Creature* creature) const
{
return GetInstanceAI<boss_rage_winterchillAI>(creature);
}
struct boss_rage_winterchillAI : public hyjal_trashAI
{
boss_rage_winterchillAI(Creature* creature) : hyjal_trashAI(creature)
{
instance = creature->GetInstanceScript();
go = false;
}
uint32 FrostArmorTimer;
uint32 DecayTimer;
uint32 NovaTimer;
uint32 IceboltTimer;
bool go;
void Reset()
{
damageTaken = 0;
FrostArmorTimer = 37000;
DecayTimer = 45000;
NovaTimer = 15000;
IceboltTimer = 10000;
if (IsEvent)
instance->SetData(DATA_RAGEWINTERCHILLEVENT, NOT_STARTED);
}
void EnterCombat(Unit* /*who*/)
{
if (IsEvent)
instance->SetData(DATA_RAGEWINTERCHILLEVENT, IN_PROGRESS);
Talk(SAY_ONAGGRO);
}
void KilledUnit(Unit* /*victim*/)
{
Talk(SAY_ONSLAY);
}
void WaypointReached(uint32 waypointId)
{
if (waypointId == 7 && instance)
{
Unit* target = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_JAINAPROUDMOORE));
if (target && target->IsAlive())
me->AddThreat(target, 0.0f);
}
}
void JustDied(Unit* killer)
{
hyjal_trashAI::JustDied(killer);
if (IsEvent)
instance->SetData(DATA_RAGEWINTERCHILLEVENT, DONE);
Talk(SAY_ONDEATH);
}
void UpdateAI(uint32 diff)
{
if (IsEvent)
{
//Must update npc_escortAI
npc_escortAI::UpdateAI(diff);
if (!go)
{
go = true;
AddWaypoint(0, 4896.08f, -1576.35f, 1333.65f);
AddWaypoint(1, 4898.68f, -1615.02f, 1329.48f);
AddWaypoint(2, 4907.12f, -1667.08f, 1321.00f);
AddWaypoint(3, 4963.18f, -1699.35f, 1340.51f);
AddWaypoint(4, 4989.16f, -1716.67f, 1335.74f);
AddWaypoint(5, 5026.27f, -1736.89f, 1323.02f);
AddWaypoint(6, 5037.77f, -1770.56f, 1324.36f);
AddWaypoint(7, 5067.23f, -1789.95f, 1321.17f);
Start(false, true);
SetDespawnAtEnd(false);
}
}
//Return since we have no target
if (!UpdateVictim())
return;
if (FrostArmorTimer <= diff)
{
DoCast(me, SPELL_FROST_ARMOR);
FrostArmorTimer = 40000+rand()%20000;
} else FrostArmorTimer -= diff;
if (DecayTimer <= diff)
{
DoCastVictim(SPELL_DEATH_AND_DECAY);
DecayTimer = 60000+rand()%20000;
Talk(SAY_DECAY);
} else DecayTimer -= diff;
if (NovaTimer <= diff)
{
DoCastVictim(SPELL_FROST_NOVA);
NovaTimer = 30000+rand()%15000;
Talk(SAY_NOVA);
} else NovaTimer -= diff;
if (IceboltTimer <= diff)
{
DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 40, true), SPELL_ICEBOLT);
IceboltTimer = 11000+rand()%20000;
} else IceboltTimer -= diff;
DoMeleeAttackIfReady();
}
};
};
void AddSC_boss_rage_winterchill()
{
new boss_rage_winterchill();
}

View File

@@ -1,262 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* ScriptData
SDName: Hyjal
SD%Complete: 80
SDComment: gossip text id's unknown
SDCategory: Caverns of Time, Mount Hyjal
EndScriptData */
/* ContentData
npc_jaina_proudmoore
npc_thrall
npc_tyrande_whisperwind
EndContentData */
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
#include "hyjalAI.h"
#include "Player.h"
#define GOSSIP_ITEM_BEGIN_ALLY "My companions and I are with you, Lady Proudmoore."
#define GOSSIP_ITEM_ANETHERON "We are ready for whatever Archimonde might send our way, Lady Proudmoore."
#define GOSSIP_ITEM_BEGIN_HORDE "I am with you, Thrall."
#define GOSSIP_ITEM_AZGALOR "We have nothing to fear."
#define GOSSIP_ITEM_RETREAT "We can't keep this up. Let's retreat!"
#define GOSSIP_ITEM_TYRANDE "Aid us in defending Nordrassil"
#define ITEM_TEAR_OF_GODDESS 24494
#define GOSSIP_ITEM_GM1 "[GM] Toggle Debug Timers"
class npc_jaina_proudmoore : public CreatureScript
{
public:
npc_jaina_proudmoore() : CreatureScript("npc_jaina_proudmoore") { }
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
{
player->PlayerTalkClass->ClearMenus();
hyjalAI* ai = CAST_AI(hyjalAI, creature->AI());
switch (action)
{
case GOSSIP_ACTION_INFO_DEF + 1:
ai->StartEvent(player);
break;
case GOSSIP_ACTION_INFO_DEF + 2:
ai->FirstBossDead = true;
ai->WaveCount = 9;
ai->StartEvent(player);
break;
case GOSSIP_ACTION_INFO_DEF + 3:
ai->Retreat();
break;
case GOSSIP_ACTION_INFO_DEF:
ai->Debug = !ai->Debug;
//TC_LOG_DEBUG("scripts", "HyjalAI - Debug mode has been toggled");
break;
}
return true;
}
bool OnGossipHello(Player* player, Creature* creature)
{
hyjalAI* ai = CAST_AI(hyjalAI, creature->AI());
if (ai->EventBegun)
return false;
uint32 RageEncounter = ai->GetInstanceData(DATA_RAGEWINTERCHILLEVENT);
uint32 AnetheronEncounter = ai->GetInstanceData(DATA_ANETHERONEVENT);
if (RageEncounter == NOT_STARTED)
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEGIN_ALLY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
else if (RageEncounter == DONE && AnetheronEncounter == NOT_STARTED)
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ANETHERON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
else if (RageEncounter == DONE && AnetheronEncounter == DONE)
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RETREAT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
if (player->IsGameMaster())
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_ITEM_GM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
player->SEND_GOSSIP_MENU(907, creature->GetGUID());
return true;
}
CreatureAI* GetAI(Creature* creature) const
{
if (!creature->GetInstanceScript())
return NULL;
hyjalAI* ai = new hyjalAI(creature);
ai->Reset();
ai->EnterEvadeMode();
ai->Spells[0].SpellId = SPELL_BLIZZARD;
ai->Spells[0].Cooldown = urand(15000, 35000);
ai->Spells[0].TargetType = TARGETTYPE_RANDOM;
ai->Spells[1].SpellId = SPELL_PYROBLAST;
ai->Spells[1].Cooldown = urand(5500, 9500);
ai->Spells[1].TargetType = TARGETTYPE_RANDOM;
ai->Spells[2].SpellId = SPELL_SUMMON_ELEMENTALS;
ai->Spells[2].Cooldown = urand(15000, 45000);
ai->Spells[2].TargetType = TARGETTYPE_SELF;
return ai;
}
};
class npc_thrall : public CreatureScript
{
public:
npc_thrall() : CreatureScript("npc_thrall") { }
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
{
player->PlayerTalkClass->ClearMenus();
hyjalAI* ai = CAST_AI(hyjalAI, creature->AI());
ai->DeSpawnVeins();//despawn the alliance veins
switch (action)
{
case GOSSIP_ACTION_INFO_DEF + 1:
ai->StartEvent(player);
break;
case GOSSIP_ACTION_INFO_DEF + 2:
ai->FirstBossDead = true;
ai->WaveCount = 9;
ai->StartEvent(player);
break;
case GOSSIP_ACTION_INFO_DEF + 3:
ai->Retreat();
break;
case GOSSIP_ACTION_INFO_DEF:
ai->Debug = !ai->Debug;
//TC_LOG_DEBUG("scripts", "HyjalAI - Debug mode has been toggled");
break;
}
return true;
}
bool OnGossipHello(Player* player, Creature* creature)
{
hyjalAI* ai = CAST_AI(hyjalAI, creature->AI());
if (ai->EventBegun)
return false;
uint32 AnetheronEvent = ai->GetInstanceData(DATA_ANETHERONEVENT);
// Only let them start the Horde phases if Anetheron is dead.
if (AnetheronEvent == DONE && ai->GetInstanceData(DATA_ALLIANCE_RETREAT))
{
uint32 KazrogalEvent = ai->GetInstanceData(DATA_KAZROGALEVENT);
uint32 AzgalorEvent = ai->GetInstanceData(DATA_AZGALOREVENT);
if (KazrogalEvent == NOT_STARTED)
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEGIN_HORDE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
else if (KazrogalEvent == DONE && AzgalorEvent == NOT_STARTED)
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AZGALOR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
else if (AzgalorEvent == DONE)
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RETREAT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
}
if (player->IsGameMaster())
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_ITEM_GM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
player->SEND_GOSSIP_MENU(907, creature->GetGUID());
return true;
}
CreatureAI* GetAI(Creature* creature) const
{
if (!creature->GetInstanceScript())
return NULL;
hyjalAI* ai = new hyjalAI(creature);
ai->Reset();
ai->EnterEvadeMode();
ai->Spells[0].SpellId = SPELL_CHAIN_LIGHTNING;
ai->Spells[0].Cooldown = urand(3000, 8000);
ai->Spells[0].TargetType = TARGETTYPE_VICTIM;
ai->Spells[1].SpellId = SPELL_SUMMON_DIRE_WOLF;
ai->Spells[1].Cooldown = urand(6000, 41000);
ai->Spells[1].TargetType = TARGETTYPE_RANDOM;
return ai;
}
};
class npc_tyrande_whisperwind : public CreatureScript
{
public:
npc_tyrande_whisperwind() : CreatureScript("npc_tyrande_whisperwind") { }
CreatureAI* GetAI(Creature* creature) const
{
if (!creature->GetInstanceScript())
return NULL;
hyjalAI* ai = new hyjalAI(creature);
ai->Reset();
ai->EnterEvadeMode();
return ai;
}
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
{
player->PlayerTalkClass->ClearMenus();
if (action == GOSSIP_ACTION_INFO_DEF)
{
ItemPosCountVec dest;
uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_TEAR_OF_GODDESS, 1);
if (msg == EQUIP_ERR_OK)
if (Item* item = player->StoreNewItem(dest, ITEM_TEAR_OF_GODDESS, true))
player->SendNewItem(item, 1, true, false, true);
player->SEND_GOSSIP_MENU(907, creature->GetGUID());
}
return true;
}
bool OnGossipHello(Player* player, Creature* creature)
{
hyjalAI* ai = CAST_AI(hyjalAI, creature->AI());
uint32 AzgalorEvent = ai->GetInstanceData(DATA_AZGALOREVENT);
// Only let them get item if Azgalor is dead.
if (AzgalorEvent == DONE && !player->HasItemCount(ITEM_TEAR_OF_GODDESS))
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TYRANDE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
player->SEND_GOSSIP_MENU(907, creature->GetGUID());
return true;
}
};
void AddSC_hyjal()
{
new npc_jaina_proudmoore();
new npc_thrall();
new npc_tyrande_whisperwind();
}

View File

@@ -1,93 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DEF_HYJAL_H
#define DEF_HYJAL_H
#define ERROR_INST_DATA "TSCR: Instance data not set properly for Mount Hyjal. Encounters will be buggy."
uint32 const EncounterCount = 5;
enum DataTypes
{
DATA_ANETHERON = 1,
DATA_ANETHERONEVENT = 2,
DATA_ARCHIMONDE = 3,
DATA_ARCHIMONDEEVENT = 4,
DATA_AZGALOR = 5,
DATA_AZGALOREVENT = 6,
DATA_JAINAPROUDMOORE = 7,
DATA_KAZROGAL = 8,
DATA_KAZROGALEVENT = 9,
DATA_RAGEWINTERCHILL = 10,
DATA_RAGEWINTERCHILLEVENT = 11,
DATA_THRALL = 12,
DATA_TYRANDEWHISPERWIND = 13,
DATA_TRASH = 14,
DATA_RESET_TRASH_COUNT = 15,
DATA_ALLIANCE_RETREAT = 16,
DATA_HORDE_RETREAT = 17,
DATA_RAIDDAMAGE = 18,
DATA_RESET_RAIDDAMAGE = 19,
TYPE_RETREAT = 20
};
enum WorldStateIds
{
WORLD_STATE_WAVES = 2842,
WORLD_STATE_ENEMY = 2453,
WORLD_STATE_ENEMYCOUNT = 2454
};
enum CreaturesIds
{
// Trash Mobs summoned in waves
NECROMANCER = 17899,
ABOMINATION = 17898,
GHOUL = 17895,
BANSHEE = 17905,
CRYPT_FIEND = 17897,
GARGOYLE = 17906,
FROST_WYRM = 17907,
GIANT_INFERNAL = 17908,
FEL_STALKER = 17916,
JAINA = 17772,
THRALL = 17852,
TYRANDE = 17948,
// Bosses summoned after every 8 waves
RAGE_WINTERCHILL = 17767,
ANETHERON = 17808,
KAZROGAL = 17888,
AZGALOR = 17842,
ARCHIMONDE = 17968,
NPC_WORLD_TRIGGER_TINY = 21987
};
enum GameobjectIds
{
GO_HORDE_ENCAMPMENT_PORTAL = 182060,
GO_NIGHT_ELF_VILLAGE_PORTAL = 182061,
GO_ANCIENT_GEM = 185557,
GO_ANCIENT_VEIN = 185557,
GO_ROARING_FLAME = 182592
};
#endif

View File

@@ -1,208 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SC_HYJALAI_H
#define SC_HYJALAI_H
#include "hyjal.h"
#include "ScriptedEscortAI.h"
#define HYJAL_AI_MAX_SPELLS 3
enum SpellIds
{
SPELL_TELEPORT_VISUAL = 41232,
SPELL_MASS_TELEPORT = 16807,
//Spells for Jaina
SPELL_BRILLIANCE_AURA = 31260, // The database must handle this spell via creature_addon(it should, but is removed in evade..)
SPELL_BLIZZARD = 31266,
SPELL_PYROBLAST = 31263,
SPELL_SUMMON_ELEMENTALS = 31264,
//Thrall spells
SPELL_CHAIN_LIGHTNING = 31330,
SPELL_SUMMON_DIRE_WOLF = 31331
};
struct Wave
{
uint32 Mob[18]; // Stores Creature Entries to be summoned in Waves
uint32 WaveTimer; // The timer before the next wave is summoned
bool IsBoss; // Simply used to inform the wave summoner that the next wave contains a boss to halt all waves after that
};
const Wave AllianceWaves[]= // Waves that will be summoned in the Alliance Base
{ // Rage Winterchill Wave 1-8
{{GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, 0, 0, 0, 0, 0, 0, 0, 0}, 120000, false},
{{GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, 0, 0, 0, 0, 0, 0}, 120000, false},
{{GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, 0, 0, 0, 0, 0, 0}, 120000, false},
{{GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0}, 120000, false},
{{GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0}, 120000, false},
{{GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0}, 120000, false},
{{GHOUL, GHOUL, GHOUL, GHOUL, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0}, 120000, false},
{{GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, 0, 0, 0, 0}, 180000, false},
// All 8 Waves are summoned, summon Rage Winterchill, next few waves are for Anetheron
{{RAGE_WINTERCHILL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, true},
// Anetheron Wave 1-8
{{GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, 0, 0, 0, 0, 0, 0, 0, 0}, 120000, false},
{{GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0}, 120000, false},
{{GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0}, 120000, false},
{{NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0}, 120000, false},
{{GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, NECROMANCER, NECROMANCER, BANSHEE, BANSHEE, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0}, 120000, false},
{{GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0}, 120000, false},
{{CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, BANSHEE, BANSHEE, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, GHOUL, GHOUL, 0, 0, 0, 0}, 120000, false},
{{GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 0, 0}, 180000, false},
// All 8 Waves are summoned, summon Anatheron
{{ANETHERON, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, true}
};
const Wave HordeWaves[]= // Waves that are summoned in the Horde base
{ // Kaz'Rogal Wave 1-8
{{GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0}, 180000, false},
{{GHOUL, GHOUL, GHOUL, GHOUL, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, 0, 0, 0, 0}, 180000, false},
{{GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, 0, 0, 0, 0}, 180000, false},
{{CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, NECROMANCER, NECROMANCER, 0, 0, 0, 0}, 180000, false},
{{GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0}, 180000, false},
{{GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, FROST_WYRM, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180000, false},
{{GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, FROST_WYRM, 0, 0, 0, 0, 0, 0, 0}, 180000, false},
{{GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0}, 240000, false},
// All 8 Waves are summoned, summon Kaz'Rogal, next few waves are for Azgalor
{{KAZROGAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, true},
// Azgalor Wave 1-8
{{ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0}, 180000, false},
{{GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, FROST_WYRM, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, 0, 0, 0, 0}, 180000, false},
{{GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, 0, 0, 0, 0}, 180000, false},
{{GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, 0, 0, 0, 0}, 180000, false},
{{FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0}, 180000, false},
{{NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, BANSHEE, BANSHEE, BANSHEE, BANSHEE, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0}, 180000, false},
{{GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, FEL_STALKER, FEL_STALKER, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, 0, 0, 0, 0}, 180000, false},
{{CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, FEL_STALKER, FEL_STALKER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, BANSHEE, BANSHEE, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0}, 240000, false},
// All 8 Waves are summoned, summon Azgalor
{{AZGALOR, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, true}
};
enum TargetType // Used in the spell cast system for the AI
{
TARGETTYPE_SELF = 0,
TARGETTYPE_RANDOM = 1,
TARGETTYPE_VICTIM = 2,
};
enum YellId
{
ATTACKED = 0, // Used when attacked and set in combat
BEGIN = 1, // Used when the event is begun
INCOMING = 2, // Used to warn the raid that another wave phase is coming
RALLY = 3, // Used to rally the raid and warn that the next wave has been summoned
FAILURE = 4, // Used when raid has failed (unsure where to place)
SUCCESS = 5, // Used when the raid has sucessfully defeated a wave phase
DEATH = 6, // Used on death
};
struct hyjalAI : public npc_escortAI
{
hyjalAI(Creature* creature);
void Reset(); // Generically used to reset our variables. Do *not* call in EnterEvadeMode as this may make problems if the raid is still in combat
void EnterEvadeMode(); // Send creature back to spawn location and evade.
void EnterCombat(Unit* /*who*/); // Used to reset cooldowns for our spells and to inform the raid that we're under attack
void UpdateAI(uint32 diff); // Called to summon waves, check for boss deaths and to cast our spells.
void JustDied(Unit* /*killer*/); // Called on death, informs the raid that they have failed.
void SetFaction(uint32 _faction) // Set the faction to either Alliance or Horde in Hyjal
{
Faction = _faction;
}
void Retreat(); // "Teleport" (teleport visual + set invisible) all friendly creatures away from the base.
void SpawnVeins();
void DeSpawnVeins();
void JustSummoned(Creature* summoned);
void SummonedCreatureDespawn(Creature* summoned);
void HideNearPos(float x, float y);
void RespawnNearPos(float x, float y);
void WaypointReached(uint32 waypointId);
void DoOverrun(uint32 faction, const uint32 diff);
void MoveInLineOfSight(Unit* who);
void SummonCreature(uint32 entry, float Base[4][3]); // Summons a creature for that wave in that base
// Summons the next wave, calls SummonCreature
void SummonNextWave(const Wave wave[18], uint32 Count, float Base[4][3]);
void StartEvent(Player* player); // Begins the event by gossip click
uint32 GetInstanceData(uint32 Event); // Gets instance data for this instance, used to check if raid has gotten past a certain point and can access the next phase
public:
InstanceScript* instance;
uint64 PlayerGUID;
uint64 BossGUID[2];
uint64 VeinGUID[14];
uint32 NextWaveTimer;
uint32 WaveCount;
uint32 CheckTimer;
uint32 Faction;
uint32 EnemyCount;
uint32 RetreatTimer;
bool EventBegun;
bool FirstBossDead;
bool SecondBossDead;
bool Summon;
bool bRetreat;
bool Debug;
bool VeinsSpawned[2];
uint8 InfernalCount;
SummonList Summons;
bool Overrun;
bool Teleported;
bool WaitForTeleport;
uint32 TeleportTimer;
uint32 OverrunCounter;
uint32 OverrunCounter2;
uint32 InfernalPoint;
uint32 RespawnTimer;
bool DoRespawn;
bool DoHide;
bool IsDummy;
uint32 MassTeleportTimer;
bool DoMassTeleport;
uint64 DummyGuid;
struct Spell
{
uint32 SpellId;
uint32 Cooldown;
uint32 TargetType;
} Spells[HYJAL_AI_MAX_SPELLS];
private:
uint32 SpellTimer[3];
//std::list<uint64> CreatureList;
};
#endif

View File

@@ -1,51 +0,0 @@
/*
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SC_HYJAL_TRASH_AI_H
#define SC_HYJAL_TRASH_AI_H
#include "hyjal.h"
#include "ScriptedEscortAI.h"
#define MINRAIDDAMAGE 700000//minimal damage before trash can drop loot and reputation, resets if faction leader dies
struct hyjal_trashAI : public npc_escortAI
{
hyjal_trashAI(Creature* creature);
void UpdateAI(uint32 diff);
void JustDied(Unit* /*killer*/);
void DamageTaken(Unit* done_by, uint32 &damage, DamageEffectType, SpellSchoolMask);
public:
InstanceScript* instance;
bool IsEvent;
uint32 Delay;
uint32 LastOverronPos;
bool IsOverrun;
bool SetupOverrun;
uint32 OverrunType;
uint8 faction;
bool useFlyPath;
uint32 damageTaken;
float DummyTarget[3];
//private:
};
#endif

View File

@@ -1,333 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* ScriptData
SDName: Instance_Mount_Hyjal
SD%Complete: 100
SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Hyjal Scripts
SDCategory: Caverns of Time, Mount Hyjal
EndScriptData */
#include "ScriptMgr.h"
#include "InstanceScript.h"
#include "ScriptedCreature.h"
#include "hyjal_trash.h"
#include "Player.h"
#include "WorldPacket.h"
#include "Opcodes.h"
#include "Chat.h"
/* Battle of Mount Hyjal encounters:
0 - Rage Winterchill event
1 - Anetheron event
2 - Kaz'rogal event
3 - Azgalor event
4 - Archimonde event
*/
#define YELL_EFFORTS "All of your efforts have been in vain, for the draining of the World Tree has already begun. Soon the heart of your world will beat no more."
#define YELL_EFFORTS_NAME "Archimonde"
class instance_hyjal : public InstanceMapScript
{
public:
instance_hyjal() : InstanceMapScript("instance_hyjal", 534) { }
InstanceScript* GetInstanceScript(InstanceMap* map) const
{
return new instance_mount_hyjal_InstanceMapScript(map);
}
struct instance_mount_hyjal_InstanceMapScript : public InstanceScript
{
instance_mount_hyjal_InstanceMapScript(Map* map) : InstanceScript(map) { }
void Initialize()
{
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
m_uiAncientGemGUID.clear();
RageWinterchill = 0;
Anetheron = 0;
Kazrogal = 0;
Azgalor = 0;
Archimonde = 0;
JainaProudmoore = 0;
Thrall = 0;
TyrandeWhisperwind = 0;
HordeGate = 0;
ElfGate = 0;
RaidDamage = 0;
Trash = 0;
hordeRetreat = 0;
allianceRetreat = 0;
ArchiYell = false;
}
bool IsEncounterInProgress() const
{
for (uint8 i = 0; i < EncounterCount; ++i)
if (m_auiEncounter[i] == IN_PROGRESS)
return true;
return false;
}
void OnGameObjectCreate(GameObject* go)
{
switch (go->GetEntry())
{
case GO_HORDE_ENCAMPMENT_PORTAL:
HordeGate = go->GetGUID();
if (allianceRetreat)
HandleGameObject(0, true, go);
else
HandleGameObject(0, false, go);
break;
case GO_NIGHT_ELF_VILLAGE_PORTAL:
ElfGate = go->GetGUID();
if (hordeRetreat)
HandleGameObject(0, true, go);
else
HandleGameObject(0, false, go);
break;
case GO_ANCIENT_GEM:
m_uiAncientGemGUID.push_back(go->GetGUID());
break;
}
}
void OnCreatureCreate(Creature* creature)
{
switch (creature->GetEntry())
{
case RAGE_WINTERCHILL: RageWinterchill = creature->GetGUID(); break;
case ANETHERON: Anetheron = creature->GetGUID(); break;
case KAZROGAL: Kazrogal = creature->GetGUID(); break;
case AZGALOR: Azgalor = creature->GetGUID(); break;
case ARCHIMONDE: Archimonde = creature->GetGUID(); break;
case JAINA: JainaProudmoore = creature->GetGUID(); break;
case THRALL: Thrall = creature->GetGUID(); break;
case TYRANDE: TyrandeWhisperwind = creature->GetGUID(); break;
}
}
uint64 GetData64(uint32 identifier) const
{
switch (identifier)
{
case DATA_RAGEWINTERCHILL: return RageWinterchill;
case DATA_ANETHERON: return Anetheron;
case DATA_KAZROGAL: return Kazrogal;
case DATA_AZGALOR: return Azgalor;
case DATA_ARCHIMONDE: return Archimonde;
case DATA_JAINAPROUDMOORE: return JainaProudmoore;
case DATA_THRALL: return Thrall;
case DATA_TYRANDEWHISPERWIND: return TyrandeWhisperwind;
}
return 0;
}
void SetData(uint32 type, uint32 data)
{
switch (type)
{
case DATA_RAGEWINTERCHILLEVENT:
m_auiEncounter[0] = data;
break;
case DATA_ANETHERONEVENT:
m_auiEncounter[1] = data;
break;
case DATA_KAZROGALEVENT:
m_auiEncounter[2] = data;
break;
case DATA_AZGALOREVENT:
{
m_auiEncounter[3] = data;
if (data == DONE)
{
if (ArchiYell)
break;
ArchiYell = true;
Creature* creature = instance->GetCreature(Azgalor);
if (creature)
{
Creature* unit = creature->SummonCreature(NPC_WORLD_TRIGGER_TINY, creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 10000);
Map* map = creature->GetMap();
if (map->IsDungeon() && unit)
{
unit->SetVisible(false);
Map::PlayerList const &PlayerList = map->GetPlayers();
if (PlayerList.isEmpty())
return;
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
{
if (i->GetSource())
{
WorldPacket packet;
ChatHandler::BuildChatPacket(packet, CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, unit, i->GetSource(), YELL_EFFORTS);
i->GetSource()->GetSession()->SendPacket(&packet);
WorldPacket data2(SMSG_PLAY_SOUND, 4);
data2 << 10986;
i->GetSource()->GetSession()->SendPacket(&data2);
}
}
}
}
}
}
break;
case DATA_ARCHIMONDEEVENT:
m_auiEncounter[4] = data;
break;
case DATA_RESET_TRASH_COUNT:
Trash = 0;
break;
case DATA_TRASH:
if (data)
Trash = data;
else
Trash--;
DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, Trash);
break;
case TYPE_RETREAT:
if (data == SPECIAL)
{
if (!m_uiAncientGemGUID.empty())
{
for (std::list<uint64>::const_iterator itr = m_uiAncientGemGUID.begin(); itr != m_uiAncientGemGUID.end(); ++itr)
{
//don't know how long it expected
DoRespawnGameObject(*itr, DAY);
}
}
}
break;
case DATA_ALLIANCE_RETREAT:
allianceRetreat = data;
HandleGameObject(HordeGate, true);
SaveToDB();
break;
case DATA_HORDE_RETREAT:
hordeRetreat = data;
HandleGameObject(ElfGate, true);
SaveToDB();
break;
case DATA_RAIDDAMAGE:
RaidDamage += data;
if (RaidDamage >= MINRAIDDAMAGE)
RaidDamage = MINRAIDDAMAGE;
break;
case DATA_RESET_RAIDDAMAGE:
RaidDamage = 0;
break;
}
// TC_LOG_DEBUG("scripts", "Instance Hyjal: Instance data updated for event %u (Data=%u)", type, data);
if (data == DONE)
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
saveStream << m_auiEncounter[0] << ' ' << m_auiEncounter[1] << ' ' << m_auiEncounter[2] << ' '
<< m_auiEncounter[3] << ' ' << m_auiEncounter[4]
<< ' ' << allianceRetreat << ' ' << hordeRetreat
<< ' ' << RaidDamage;
str_data = saveStream.str();
SaveToDB();
OUT_SAVE_INST_DATA_COMPLETE;
}
}
uint32 GetData(uint32 type) const
{
switch (type)
{
case DATA_RAGEWINTERCHILLEVENT: return m_auiEncounter[0];
case DATA_ANETHERONEVENT: return m_auiEncounter[1];
case DATA_KAZROGALEVENT: return m_auiEncounter[2];
case DATA_AZGALOREVENT: return m_auiEncounter[3];
case DATA_ARCHIMONDEEVENT: return m_auiEncounter[4];
case DATA_TRASH: return Trash;
case DATA_ALLIANCE_RETREAT: return allianceRetreat;
case DATA_HORDE_RETREAT: return hordeRetreat;
case DATA_RAIDDAMAGE: return RaidDamage;
}
return 0;
}
std::string GetSaveData()
{
return str_data;
}
void Load(const char* in)
{
if (!in)
{
OUT_LOAD_INST_DATA_FAIL;
return;
}
OUT_LOAD_INST_DATA(in);
std::istringstream loadStream(in);
loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] >> m_auiEncounter[4] >> allianceRetreat >> hordeRetreat >> RaidDamage;
for (uint8 i = 0; i < EncounterCount; ++i)
if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as IN_PROGRESS - reset it instead.
m_auiEncounter[i] = NOT_STARTED;
OUT_LOAD_INST_DATA_COMPLETE;
}
protected:
uint32 m_auiEncounter[EncounterCount];
std::string str_data;
std::list<uint64> m_uiAncientGemGUID;
uint64 RageWinterchill;
uint64 Anetheron;
uint64 Kazrogal;
uint64 Azgalor;
uint64 Archimonde;
uint64 JainaProudmoore;
uint64 Thrall;
uint64 TyrandeWhisperwind;
uint64 HordeGate;
uint64 ElfGate;
uint32 Trash;
uint32 hordeRetreat;
uint32 allianceRetreat;
uint32 RaidDamage;
bool ArchiYell;
};
};
void AddSC_instance_mount_hyjal()
{
new instance_hyjal();
}

View File

@@ -1,147 +0,0 @@
/*
REWRITTEN FROM SCRATCH BY XINEF, IT OWNS NOW!
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "culling_of_stratholme.h"
#include "SpellInfo.h"
enum Spells
{
SPELL_CURSE_OF_EXERTION = 52772,
SPELL_WOUNDING_STRIKE_N = 52771,
SPELL_WOUNDING_STRIKE_H = 58830,
SPELL_TIME_STOP = 58848,
SPELL_TIME_WARP = 52766,
SPELL_TIME_STEP_N = 52737,
SPELL_TIME_STEP_H = 58829,
};
enum Events
{
EVENT_SPELL_CURSE_OF_EXERTION = 1,
EVENT_SPELL_WOUNDING_STRIKE = 2,
EVENT_SPELL_TIME_STOP = 3,
EVENT_SPELL_TIME_WARP = 4,
EVENT_TIME_WARP = 5,
};
enum Yells
{
SAY_INTRO = 0,
SAY_AGGRO = 1,
SAY_TIME_WARP = 2,
SAY_SLAY = 3,
SAY_DEATH = 4
};
class boss_epoch : public CreatureScript
{
public:
boss_epoch() : CreatureScript("boss_epoch") { }
CreatureAI* GetAI(Creature* creature) const
{
return new boss_epochAI (creature);
}
struct boss_epochAI : public ScriptedAI
{
boss_epochAI(Creature* c) : ScriptedAI(c)
{
}
EventMap events;
uint8 warps;
void Reset()
{
events.Reset();
warps = 0;
}
void EnterCombat(Unit* /*who*/)
{
Talk(SAY_AGGRO);
events.ScheduleEvent(EVENT_SPELL_CURSE_OF_EXERTION, 9000);
events.ScheduleEvent(EVENT_SPELL_WOUNDING_STRIKE, 3000);
events.ScheduleEvent(EVENT_SPELL_TIME_WARP, 25000);
if (IsHeroic())
events.ScheduleEvent(EVENT_SPELL_TIME_STOP, 20000);
}
void SpellHitTarget(Unit* target, const SpellInfo* spellInfo)
{
if (spellInfo->Id == SPELL_TIME_STEP_H || spellInfo->Id == SPELL_TIME_STEP_N)
{
if (target == me)
return;
if (warps >= 2)
{
warps = 0;
return;
}
warps++;
me->CastSpell(target, DUNGEON_MODE(SPELL_TIME_STEP_N, SPELL_TIME_STEP_H), true);
}
}
void UpdateAI(uint32 diff)
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.GetEvent())
{
case EVENT_SPELL_CURSE_OF_EXERTION:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true))
me->CastSpell(target, SPELL_CURSE_OF_EXERTION, false);
events.RepeatEvent(9000);
break;
case EVENT_SPELL_WOUNDING_STRIKE:
me->CastSpell(me->GetVictim(), DUNGEON_MODE(SPELL_WOUNDING_STRIKE_N, SPELL_WOUNDING_STRIKE_H), false);
events.RepeatEvent(6000);
break;
case EVENT_SPELL_TIME_STOP:
me->CastSpell(me, SPELL_TIME_STOP, false);
events.RepeatEvent(20000);
break;
case EVENT_SPELL_TIME_WARP:
Talk(SAY_TIME_WARP);
me->CastSpell(me, SPELL_TIME_WARP, false);
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true))
me->CastSpell(target, DUNGEON_MODE(SPELL_TIME_STEP_N, SPELL_TIME_STEP_H), true);
events.RepeatEvent(25000);
break;
}
DoMeleeAttackIfReady();
}
void JustDied(Unit* /*killer*/)
{
Talk(SAY_DEATH);
}
void KilledUnit(Unit* victim)
{
if (!urand(0,1))
return;
Talk(SAY_SLAY);
}
};
};
void AddSC_boss_epoch()
{
new boss_epoch();
}

View File

@@ -1,147 +0,0 @@
/*
REWRITTEN FROM SCRATCH BY XINEF, IT OWNS NOW!
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "culling_of_stratholme.h"
enum Spells
{
SPELL_CORRUPTING_BLIGHT = 60588,
SPELL_VOID_STRIKE = 60590,
SPELL_CORRUPTION_OF_TIME_AURA = 60451,
SPELL_CORRUPTION_OF_TIME_CHANNEL = 60422,
};
enum Events
{
EVENT_SPELL_CORRUPTING_BLIGHT = 1,
EVENT_SPELL_VOID_STRIKE = 2,
};
enum Yells
{
SAY_AGGRO = 0,
SAY_DEATH = 1,
SAY_FAIL = 2
};
class boss_infinite_corruptor : public CreatureScript
{
public:
boss_infinite_corruptor() : CreatureScript("boss_infinite_corruptor") { }
CreatureAI* GetAI(Creature* creature) const
{
return new boss_infinite_corruptorAI(creature);
}
struct boss_infinite_corruptorAI : public ScriptedAI
{
boss_infinite_corruptorAI(Creature* c) : ScriptedAI(c), summons(me)
{
}
EventMap events;
SummonList summons;
uint32 beamTimer;
void Reset()
{
events.Reset();
summons.DespawnAll();
if (InstanceScript* pInstance = me->GetInstanceScript())
if (pInstance->GetData(DATA_GUARDIANTIME_EVENT) == 0)
me->DespawnOrUnsummon(500);
me->SummonCreature(NPC_TIME_RIFT, 2337.6f, 1270.0f, 132.95f, 2.79f);
me->SummonCreature(NPC_GUARDIAN_OF_TIME, 2319.3f, 1267.7f, 132.8f, 1.0f);
beamTimer = 1;
}
void JustSummoned(Creature* cr) { summons.Summon(cr); }
void EnterCombat(Unit* /*who*/)
{
me->InterruptNonMeleeSpells(false);
events.ScheduleEvent(EVENT_SPELL_VOID_STRIKE, 8000);
events.ScheduleEvent(EVENT_SPELL_CORRUPTING_BLIGHT, 12000);
Talk(SAY_AGGRO);
}
void JustDied(Unit* /*killer*/)
{
Talk(SAY_DEATH);
for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
if (Creature* cr = ObjectAccessor::GetCreature(*me, (*itr)))
{
if (cr->GetEntry() == NPC_TIME_RIFT)
cr->DespawnOrUnsummon(1000);
else
{
cr->DespawnOrUnsummon(5000);
cr->RemoveAllAuras();
cr->MonsterSay("You have my thanks for saving my existence in this timeline. Now i must report back to my superiors. They must know immediately of what i just experienced.", LANG_UNIVERSAL, 0);
}
}
if (InstanceScript* pInstance = me->GetInstanceScript())
pInstance->SetData(DATA_SHOW_INFINITE_TIMER, 0);
}
void DoAction(int32 param)
{
if (!me->IsAlive())
return;
if (param == ACTION_RUN_OUT_OF_TIME)
{
Talk(SAY_FAIL);
summons.DespawnAll();
me->DespawnOrUnsummon(500);
}
}
void UpdateAI(uint32 diff)
{
if (beamTimer)
{
beamTimer += diff;
if (beamTimer >= 2000)
{
me->CastSpell(me, SPELL_CORRUPTION_OF_TIME_CHANNEL, true);
beamTimer = 0;
}
}
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.GetEvent())
{
case EVENT_SPELL_VOID_STRIKE:
me->CastSpell(me->GetVictim(), SPELL_VOID_STRIKE, false);
events.RepeatEvent(8000);
break;
case EVENT_SPELL_CORRUPTING_BLIGHT:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true))
me->CastSpell(target, SPELL_CORRUPTING_BLIGHT, false);
events.RepeatEvent(12000);
break;
}
DoMeleeAttackIfReady();
}
};
};
void AddSC_boss_infinite_corruptor()
{
new boss_infinite_corruptor();
}

View File

@@ -1,164 +0,0 @@
/*
REWRITTEN FROM SCRATCH BY XINEF, IT OWNS NOW!
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "culling_of_stratholme.h"
#include "Player.h"
enum Spells
{
SPELL_CARRION_SWARM_N = 52720,
SPELL_CARRION_SWARM_H = 58852,
SPELL_MIND_BLAST_N = 52722,
SPELL_MIND_BLAST_H = 58850,
SPELL_SLEEP_N = 52721,
SPELL_SLEEP_H = 58849,
SPELL_VAMPIRIC_TOUCH = 52723,
};
enum Events
{
EVENT_SPELL_CARRION_SWARM = 1,
EVENT_SPELL_MIND_BLAST = 2,
EVENT_SPELL_SLEEP = 3,
EVENT_SPELL_VAMPIRIC_TOUCH = 4,
};
enum Yells
{
SAY_AGGRO = 2,
SAY_KILL = 3,
SAY_SLAY = 4,
SAY_SLEEP = 5,
SAY_30HEALTH = 6,
SAY_15HEALTH = 7,
SAY_ESCAPE_SPEECH_1 = 8,
SAY_ESCAPE_SPEECH_2 = 9,
SAY_OUTRO = 10
};
class boss_mal_ganis : public CreatureScript
{
public:
boss_mal_ganis() : CreatureScript("boss_mal_ganis") { }
CreatureAI* GetAI(Creature* creature) const
{
return new boss_mal_ganisAI (creature);
}
struct boss_mal_ganisAI : public ScriptedAI
{
boss_mal_ganisAI(Creature* c) : ScriptedAI(c)
{
finished = false;
}
EventMap events;
bool finished;
void Reset()
{
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true);
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK_DEST, true);
events.Reset();
if (finished)
{
Talk(SAY_OUTRO);
me->DespawnOrUnsummon(20000);
}
}
void EnterCombat(Unit* /*who*/)
{
Talk(SAY_AGGRO);
events.ScheduleEvent(EVENT_SPELL_CARRION_SWARM, 6000);
events.ScheduleEvent(EVENT_SPELL_MIND_BLAST, 11000);
events.ScheduleEvent(EVENT_SPELL_SLEEP, 20000);
events.ScheduleEvent(EVENT_SPELL_VAMPIRIC_TOUCH, 15000);
}
void JustDied(Unit* /*killer*/)
{
}
void KilledUnit(Unit* victim)
{
if (!urand(0,1))
return;
Talk(SAY_SLAY);
}
void DamageTaken(Unit* who, uint32 &damage, DamageEffectType, SpellSchoolMask)
{
if (!finished && damage >= me->GetHealth())
{
damage = 0;
finished = true;
me->SetRegeneratingHealth(false);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->SetReactState(REACT_PASSIVE);
if (InstanceScript* pInstance = me->GetInstanceScript())
{
if (Creature* cr = ObjectAccessor::GetCreature(*me, pInstance->GetData64(DATA_ARTHAS)))
cr->AI()->DoAction(ACTION_KILLED_MALGANIS);
// give credit to players
me->CastSpell(me, 58630, true);
}
// quest completion
if (who)
if (Player* player = who->GetCharmerOrOwnerPlayerOrPlayerItself())
player->RewardPlayerAndGroupAtEvent(31006, player); // Royal Escort quest, Mal'ganis bunny
EnterEvadeMode();
}
}
void UpdateAI(uint32 diff)
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.GetEvent())
{
case EVENT_SPELL_CARRION_SWARM:
me->CastSpell(me->GetVictim(), DUNGEON_MODE(SPELL_CARRION_SWARM_N, SPELL_CARRION_SWARM_H), false);
events.RepeatEvent(7000);
break;
case EVENT_SPELL_MIND_BLAST:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true))
me->CastSpell(target, DUNGEON_MODE(SPELL_MIND_BLAST_N, SPELL_MIND_BLAST_H), false);
events.RepeatEvent(6000);
break;
case EVENT_SPELL_SLEEP:
Talk(SAY_SLEEP);
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true))
me->CastSpell(target, DUNGEON_MODE(SPELL_SLEEP_N, SPELL_SLEEP_H), false);
events.RepeatEvent(17000);
break;
case EVENT_SPELL_VAMPIRIC_TOUCH:
me->CastSpell(me, SPELL_VAMPIRIC_TOUCH, true);
events.RepeatEvent(30000);
break;
}
DoMeleeAttackIfReady();
}
};
};
void AddSC_boss_mal_ganis()
{
new boss_mal_ganis();
}

View File

@@ -1,110 +0,0 @@
/*
REWRITTEN FROM SCRATCH BY XINEF, IT OWNS NOW!
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "culling_of_stratholme.h"
enum Spells
{
SPELL_CONSTRICTING_CHAINS_N = 52696,
SPELL_CONSTRICTING_CHAINS_H = 58823,
SPELL_DISEASE_EXPULSION_N = 52666,
SPELL_DISEASE_EXPULSION_H = 58824,
SPELL_FRENZY = 58841,
};
enum Events
{
EVENT_SPELL_CONSTRICTING_CHAINS = 1,
EVENT_SPELL_DISEASE_EXPULSION = 2,
EVENT_SPELL_FRENZY = 3,
};
enum Yells
{
SAY_AGGRO = 0,
SAY_SLAY = 1,
SAY_SPAWN = 2,
SAY_DEATH = 3
};
class boss_meathook : public CreatureScript
{
public:
boss_meathook() : CreatureScript("boss_meathook") { }
CreatureAI* GetAI(Creature* creature) const
{
return new boss_meathookAI (creature);
}
struct boss_meathookAI : public ScriptedAI
{
boss_meathookAI(Creature* c) : ScriptedAI(c)
{
Talk(SAY_SPAWN);
}
EventMap events;
void Reset() { events.Reset(); }
void EnterCombat(Unit* /*who*/)
{
Talk(SAY_AGGRO);
events.RescheduleEvent(EVENT_SPELL_CONSTRICTING_CHAINS, 15000);
events.RescheduleEvent(EVENT_SPELL_DISEASE_EXPULSION, 4000);
events.RescheduleEvent(EVENT_SPELL_FRENZY, 20000);
}
void JustDied(Unit* /*killer*/)
{
Talk(SAY_DEATH);
}
void KilledUnit(Unit* victim)
{
if (!urand(0,1))
return;
Talk(SAY_SLAY);
}
void UpdateAI(uint32 diff)
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.GetEvent())
{
case EVENT_SPELL_DISEASE_EXPULSION:
me->CastSpell(me, DUNGEON_MODE(SPELL_DISEASE_EXPULSION_N, SPELL_DISEASE_EXPULSION_H), false);
events.RepeatEvent(6000);
break;
case EVENT_SPELL_FRENZY:
me->CastSpell(me, SPELL_FRENZY, false);
events.RepeatEvent(20000);
break;
case EVENT_SPELL_CONSTRICTING_CHAINS:
if (Unit *pTarget = SelectTarget(SELECT_TARGET_BOTTOMAGGRO, 0, 50.0f, true))
me->CastSpell(pTarget, DUNGEON_MODE(SPELL_CONSTRICTING_CHAINS_N, SPELL_CONSTRICTING_CHAINS_H), false);
events.RepeatEvent(14000);
break;
}
DoMeleeAttackIfReady();
}
};
};
void AddSC_boss_meathook()
{
new boss_meathook();
}

View File

@@ -1,187 +0,0 @@
/*
REWRITTEN FROM SCRATCH BY XINEF, IT OWNS NOW!
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "culling_of_stratholme.h"
#include "SpellScript.h"
enum Spells
{
SPELL_SHADOW_BOLT_N = 57725,
SPELL_SHADOW_BOLT_H = 58827,
SPELL_STEAL_FLESH_CHANNEL = 52708,
SPELL_STEAL_FLESH_TARGET = 52711,
SPELL_STEAL_FLESH_CASTER = 52712,
SPELL_SUMMON_GHOULS = 52451,
SPELL_EXPLODE_GHOUL_N = 52480,
SPELL_EXPLODE_GHOUL_H = 58825,
SPELL_CURSE_OF_TWISTED_FAITH = 58845,
};
enum Events
{
EVENT_SPELL_SHADOW_BOLT = 1,
EVENT_SPELL_STEAL_FLESH = 2,
EVENT_SPELL_SUMMON_GHOULS = 3,
EVENT_EXPLODE_GHOUL = 4,
EVENT_SPELL_CURSE = 5,
};
enum Yells
{
SAY_AGGRO = 0,
SAY_SPAWN = 1,
SAY_SLAY = 2,
SAY_DEATH = 3,
SAY_EXPLODE_GHOUL = 4,
SAY_STEAL_FLESH = 5,
SAY_SUMMON_GHOULS = 6
};
class boss_salramm : public CreatureScript
{
public:
boss_salramm() : CreatureScript("boss_salramm") { }
CreatureAI* GetAI(Creature* creature) const
{
return new boss_salrammAI (creature);
}
struct boss_salrammAI : public ScriptedAI
{
boss_salrammAI(Creature* c) : ScriptedAI(c), summons(me)
{
Talk(SAY_SPAWN);
}
EventMap events;
SummonList summons;
void Reset()
{
events.Reset();
summons.DespawnAll();
}
void JustSummoned(Creature* cr) { summons.Summon(cr); }
void EnterCombat(Unit* /*who*/)
{
Talk(SAY_AGGRO);
events.ScheduleEvent(EVENT_SPELL_SHADOW_BOLT, 7000);
events.ScheduleEvent(EVENT_SPELL_STEAL_FLESH, 11000);
events.ScheduleEvent(EVENT_SPELL_SUMMON_GHOULS, 16000);
events.ScheduleEvent(EVENT_EXPLODE_GHOUL, 22000);
if (IsHeroic())
events.ScheduleEvent(EVENT_SPELL_CURSE, 25000);
}
void JustDied(Unit* /*killer*/)
{
summons.DespawnAll();
Talk(SAY_DEATH);
}
void KilledUnit(Unit* victim)
{
if (!urand(0,1))
return;
Talk(SAY_SLAY);
}
void ExplodeGhoul()
{
for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
if (Creature* cr = ObjectAccessor::GetCreature(*me, (*itr)))
if (cr->IsAlive())
{
me->CastSpell(cr, DUNGEON_MODE(SPELL_EXPLODE_GHOUL_N, SPELL_EXPLODE_GHOUL_H), false);
return;
}
}
void UpdateAI(uint32 diff)
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.GetEvent())
{
case EVENT_SPELL_SHADOW_BOLT:
me->CastSpell(me->GetVictim(), DUNGEON_MODE(SPELL_SHADOW_BOLT_N, SPELL_SHADOW_BOLT_H), false);
events.RepeatEvent(10000);
break;
case EVENT_SPELL_STEAL_FLESH:
if (!urand(0,2))
Talk(SAY_STEAL_FLESH);
me->CastSpell(me->GetVictim(), SPELL_STEAL_FLESH_CHANNEL, false);
events.RepeatEvent(12000);
break;
case EVENT_SPELL_SUMMON_GHOULS:
if (!urand(0,2))
Talk(SAY_SUMMON_GHOULS);
me->CastSpell(me, SPELL_SUMMON_GHOULS, false);
events.RepeatEvent(10000);
break;
case EVENT_EXPLODE_GHOUL:
if (!urand(0,2))
Talk(SAY_EXPLODE_GHOUL);
ExplodeGhoul();
events.RepeatEvent(15000);
break;
case EVENT_SPELL_CURSE:
me->CastSpell(me->GetVictim(), SPELL_CURSE_OF_TWISTED_FAITH, false);
events.RepeatEvent(30000);
break;
}
DoMeleeAttackIfReady();
}
};
};
class spell_boss_salramm_steal_flesh : public SpellScriptLoader
{
public:
spell_boss_salramm_steal_flesh() : SpellScriptLoader("spell_boss_salramm_steal_flesh") { }
class spell_boss_salramm_steal_flesh_AuraScript : public AuraScript
{
PrepareAuraScript(spell_boss_salramm_steal_flesh_AuraScript);
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
Unit* caster = GetCaster();
Unit* target = GetUnitOwner();
if (caster)
{
caster->CastSpell(caster, SPELL_STEAL_FLESH_CASTER, true);
caster->CastSpell(target, SPELL_STEAL_FLESH_TARGET, true);
}
}
void Register()
{
AfterEffectRemove += AuraEffectRemoveFn(spell_boss_salramm_steal_flesh_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const
{
return new spell_boss_salramm_steal_flesh_AuraScript();
}
};
void AddSC_boss_salramm()
{
new boss_salramm();
new spell_boss_salramm_steal_flesh();
}

View File

@@ -1,171 +0,0 @@
/*
REWRITTEN FROM SCRATCH BY XINEF, IT OWNS NOW!
*/
#ifndef DEF_CULLING_OF_STRATHOLME_H
#define DEF_CULLING_OF_STRATHOLME_H
enum Data
{
DATA_ARTHAS_EVENT,
DATA_GUARDIANTIME_EVENT,
// Communication
DATA_SHOW_CRATES,
DATA_CRATE_COUNT,
DATA_START_WAVES,
DATA_SHOW_INFINITE_TIMER,
DATA_ARTHAS_REPOSITION,
};
enum Data64
{
DATA_ARTHAS,
DATA_INFINITE,
DATA_SHKAF_GATE,
DATA_EXIT_GATE,
};
enum Creatures
{
NPC_MEATHOOK = 26529,
NPC_SALRAMM = 26530,
NPC_EPOCH = 26532,
NPC_MAL_GANIS = 26533,
NPC_INFINITE = 32273,
NPC_ARTHAS = 26499,
NPC_JAINA = 26497,
NPC_UTHER = 26528,
NPC_GUARDIAN_OF_TIME = 32281,
NPC_TIME_RIFT = 28409,
NPC_CHROMIE_MIDDLE = 27915,
NPC_GRAIN_CREATE_TRIGGER = 30996,
NPC_HOURGLASS = 28656,
};
enum GameObjects
{
GO_SHKAF_GATE = 188686,
GO_EXIT_GATE = 191788,
GO_MALGANIS_CHEST_N = 190663,
GO_MALGANIS_CHEST_H = 193597,
GO_SUSPICIOUS_CRATE = 190094,
GO_PLAGUED_CRATE = 190095,
};
enum WorldStatesCoT
{
WORLDSTATE_SHOW_CRATES = 3479,
WORLDSTATE_CRATES_REVEALED = 3480,
WORLDSTATE_WAVE_COUNT = 3504,
WORLDSTATE_TIME_GUARDIAN = 3931,
WORLDSTATE_TIME_GUARDIAN_SHOW = 3932,
};
enum CrateSpells
{
SPELL_CRATES_CREDIT = 58109,
SPELL_ARCANE_DISRUPTION = 49590,
SPELL_HUMAN_FEMALE = 35483,
SPELL_HUMAN_MALE = 35482,
};
enum EventPositions
{
EVENT_POS_CHROMIE = 0,
EVENT_POS_HOURGLASS = 1,
EVENT_SRC_UTHER,
EVENT_SRC_JAINA,
EVENT_SRC_HORSE1,
EVENT_SRC_HORSE2,
EVENT_SRC_HORSE3,
EVENT_DST_UTHER,
EVENT_DST_HORSE1,
EVENT_DST_HORSE2,
EVENT_DST_HORSE3,
EVENT_POS_RETREAT,
EVENT_SRC_TOWN_CITYMAN1,
EVENT_SRC_TOWN_CITYMAN2,
EVENT_DST_CITYMAN,
EVENT_SRC_MALGANIS,
EVENT_SRC_MEATHOOK,
EVENT_SRC_SALRAMM,
EVENT_SRC_HALL_CITYMAN1,
EVENT_SRC_HALL_CITYMAN2,
EVENT_SRC_HALL_CITYMAN3,
EVENT_SRC_EPOCH,
EVENT_DST_EPOCH,
EVENT_SRC_CORRUPTOR,
EVENT_SRC_MALGANIS_FINAL,
};
enum ArthasPhase
{
COS_PROGRESS_NOT_STARTED = 0,
COS_PROGRESS_CRATES_FOUND = 1,
COS_PROGRESS_START_INTRO = 2,
COS_PROGRESS_FINISHED_INTRO = 3,
COS_PROGRESS_FINISHED_CITY_INTRO = 4,
COS_PROGRESS_KILLED_MEATHOOK = 5,
COS_PROGRESS_KILLED_SALRAMM = 6,
COS_PROGRESS_REACHED_TOWN_HALL = 7,
COS_PROGRESS_KILLED_EPOCH = 8,
COS_PROGRESS_LAST_CITY = 9,
COS_PROGRESS_BEFORE_MALGANIS = 10,
COS_PROGRESS_FINISHED = 11,
};
enum Actions
{
ACTION_START_EVENT = 1,
ACTION_START_CITY = 2,
ACTION_KILLED_SALRAMM = 3,
ACTION_START_TOWN_HALL = 4,
ACTION_START_SECRET_PASSAGE = 5,
ACTION_START_LAST_CITY = 6,
ACTION_RUN_OUT_OF_TIME = 7,
ACTION_START_MALGANIS = 8,
ACTION_KILLED_MALGANIS = 9,
};
const Position LeaderIntroPos1 = {1938.05f, 1289.79f, 145.38f, 3.18f};
const Position LeaderIntroPos2 = {2050.66f, 1287.33f, 142.67f, M_PI};
const Position LeaderIntroPos2special = {2092.15f, 1276.65f, 140.52f, 0.22f};
const Position LeaderIntroPos3 = {2365.63f, 1194.84f, 131.97f, 0.0f};
const Position LeaderIntroPos4 = {2423.12f, 1119.43f, 148.07f, 0.0f};
const Position LeaderIntroPos5 = {2540.48f, 1129.06f, 130.86f, 0.0f};
const Position LeaderIntroPos6 = {2327.39f, 1412.47f, 127.69f, 0.0f};
const Position EventPos[] =
{
{1813.298f, 1283.578f, 142.326f, 3.878161f}, // chromie
{1809.46f, 1286.05f, 142.62f, 4.8f}, // hourglass
{1795.76f, 1271.54f, 140.61f, 0.21f}, // source for uther
{1895.48f, 1292.66f, 143.706f, 0.023475f}, // source for jaina
{1788.38f, 1273.7f, 140.15f, 0.2f}, // source for horses
{1788.76f, 1271.54f, 140.62f, 0.21f},
{1788.74f, 1267.38f, 140.18f, 0.11f},
{1897.6f, 1285.5f, 143.44f, 0.32f}, // dest for uther
{1888.56f, 1289.95f, 143.8f, 0.01f}, // dest for horses
{1888.94f, 1285.41f, 143.69f, 0.08f},
{1889.55f, 1279.95f, 143.62f, 0.1f},
{1751.9f, 1262.45f, 137.62f, 3.35f}, // retreat position after intro (uther + horses)
{2091.977f, 1275.021f, 140.757f, 0.558f}, // source for town city man 1
{2093.514f, 1275.842f, 140.408f, 3.801f}, // 2
{2089.04f, 1277.98f, 140.85f, 2.35f}, // cityman dest pos
{2117.349f, 1288.624f, 136.271f, 1.37f}, // malganis city intro
{2351.45f, 1197.81f, 130.45f, 3.83f}, // meathook spawn position
{2351.45f, 1197.81f, 130.45f, 3.83f}, // salramm spawn position
{2398.14f, 1207.81f, 134.04f, 5.15f}, // source for hall city man 1
{2403.22f, 1205.54f, 134.04f, 3.31f}, // 2
{2400.82f, 1201.69f, 134.01f, 1.53f}, // 3
{2463.131f, 1115.391f, 152.473f, 3.41f}, // epoch spawn position
{2451.809f, 1112.901f, 149.220f, 3.36f}, // epoch move pos
{2329.07f, 1276.98f, 132.68f, 4.0f}, // infinite corruptor pos
{2298.25f, 1500.56f, 128.37f, 4.95f} // malganis final pos
};
#endif

View File

@@ -1,422 +0,0 @@
/*
REWRITTEN FROM SCRATCH BY XINEF, IT OWNS NOW!
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "CreatureTextMgr.h"
#include "culling_of_stratholme.h"
#include "Player.h"
#include "TemporarySummon.h"
#include "SpellInfo.h"
class instance_culling_of_stratholme : public InstanceMapScript
{
public:
instance_culling_of_stratholme() : InstanceMapScript("instance_culling_of_stratholme", 595) { }
InstanceScript* GetInstanceScript(InstanceMap* pMap) const
{
return new instance_culling_of_stratholme_InstanceMapScript(pMap);
}
struct instance_culling_of_stratholme_InstanceMapScript : public InstanceScript
{
instance_culling_of_stratholme_InstanceMapScript(Map* pMap) : InstanceScript(pMap)
{
// NPCs
_arthasGUID = 0;
_infiniteGUID = 0;
// GOs
_shkafGateGUID = 0;
_exitGateGUID = 0;
// Instance
_crateCount = 0;
_showCrateTimer = 0;
_guardianTimer = 0;
_respawnAndReposition = false;
_encounterState = COS_PROGRESS_NOT_STARTED;
_loadTimer = 0;
}
bool IsEncounterInProgress() const
{
return false;
}
void FillInitialWorldStates(WorldPacket& data)
{
data << uint32(WORLDSTATE_SHOW_CRATES) << uint32(0);
data << uint32(WORLDSTATE_CRATES_REVEALED) << uint32(_crateCount);
data << uint32(WORLDSTATE_WAVE_COUNT) << uint32(0);
data << uint32(WORLDSTATE_TIME_GUARDIAN) << uint32(25);
data << uint32(WORLDSTATE_TIME_GUARDIAN_SHOW) << uint32(0);
}
void OnPlayerEnter(Player* plr)
{
if (instance->GetPlayersCountExceptGMs() == 1)
SetData(DATA_ARTHAS_REPOSITION, 2);
EnsureGridLoaded();
if (plr->getRace() != RACE_HUMAN && plr->getRace() != RACE_DWARF && plr->getRace() != RACE_GNOME)
plr->CastSpell(plr, ((plr->getGender() == GENDER_MALE) ? SPELL_HUMAN_MALE : SPELL_HUMAN_FEMALE), true);
}
void OnCreatureCreate(Creature* creature)
{
switch (creature->GetEntry())
{
case NPC_ARTHAS:
_arthasGUID = creature->GetGUID();
if (_encounterState == COS_PROGRESS_FINISHED)
creature->SetVisible(false);
else
Reposition(creature);
break;
case NPC_INFINITE:
_infiniteGUID = creature->GetGUID();
break;
}
}
void OnGameObjectCreate(GameObject* go)
{
switch (go->GetEntry())
{
case GO_SHKAF_GATE:
_shkafGateGUID = go->GetGUID();
if (_encounterState >= COS_PROGRESS_KILLED_EPOCH)
go->SetGoState(GO_STATE_ACTIVE);
break;
case GO_EXIT_GATE:
_exitGateGUID = go->GetGUID();
if (_encounterState == COS_PROGRESS_FINISHED)
go->SetGoState(GO_STATE_ACTIVE);
break;
}
}
void SetData(uint32 type, uint32 data)
{
switch (type)
{
case DATA_SHOW_CRATES:
DoUpdateWorldState(WORLDSTATE_SHOW_CRATES, data);
return;
case DATA_SHOW_INFINITE_TIMER:
if (!instance->IsHeroic() || !_guardianTimer)
return;
DoUpdateWorldState(WORLDSTATE_TIME_GUARDIAN_SHOW, data);
DoUpdateWorldState(WORLDSTATE_TIME_GUARDIAN, uint32(_guardianTimer / (MINUTE*IN_MILLISECONDS)));
if (data == 0)
{
_guardianTimer = 0;
SaveToDB();
}
else if (!_infiniteGUID)
instance->SummonCreature(NPC_INFINITE, EventPos[EVENT_SRC_CORRUPTOR]);
return;
case DATA_START_WAVES:
DoUpdateWorldState(WORLDSTATE_WAVE_COUNT, 1);
if (instance->IsHeroic())
{
DoUpdateWorldState(WORLDSTATE_TIME_GUARDIAN_SHOW, true);
_guardianTimer = 26*MINUTE*IN_MILLISECONDS;
if (!_infiniteGUID)
instance->SummonCreature(NPC_INFINITE, EventPos[EVENT_SRC_CORRUPTOR]);
}
return;
case DATA_CRATE_COUNT:
_crateCount++;
if (_crateCount == 5)
{
Map::PlayerList const &PlayerList = instance->GetPlayers();
if (!PlayerList.isEmpty())
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
i->GetSource()->KilledMonsterCredit(NPC_GRAIN_CREATE_TRIGGER, 0);
_showCrateTimer++;
if (GetData(DATA_ARTHAS_EVENT) < COS_PROGRESS_CRATES_FOUND)
SetData(DATA_ARTHAS_EVENT, COS_PROGRESS_CRATES_FOUND);
}
DoUpdateWorldState(WORLDSTATE_CRATES_REVEALED, _crateCount);
return;
case DATA_ARTHAS_EVENT:
// Start Event
_encounterState = data;
if (data == COS_PROGRESS_START_INTRO)
{
if (Creature *arthas = instance->GetCreature(_arthasGUID))
arthas->AI()->DoAction(ACTION_START_EVENT);
}
else if (data == COS_PROGRESS_KILLED_SALRAMM)
{
if (Creature *arthas = instance->GetCreature(_arthasGUID))
arthas->AI()->DoAction(ACTION_KILLED_SALRAMM);
}
break;
case DATA_ARTHAS_REPOSITION:
if (data == 2)
_respawnAndReposition = true;
else if (Creature *arthas = instance->GetCreature(_arthasGUID))
Reposition(arthas);
return;
}
if (type == DATA_ARTHAS_EVENT)
SaveToDB();
}
uint32 GetData(uint32 type) const
{
switch (type)
{
case DATA_ARTHAS_EVENT:
return _encounterState;
case DATA_GUARDIANTIME_EVENT:
return _guardianTimer;
}
return 0;
}
uint64 GetData64(uint32 identifier) const
{
switch (identifier)
{
case DATA_SHKAF_GATE:
return _shkafGateGUID;
case DATA_ARTHAS:
return _arthasGUID;
case DATA_EXIT_GATE:
return _exitGateGUID;
}
return 0;
}
void Update(uint32 diff)
{
if (_loadTimer)
{
_loadTimer += diff;
if (_loadTimer > 3000)
{
UpdateEventState();
_loadTimer = 0;
}
}
// Used when arthas dies
if (_respawnAndReposition)
{
if (Creature *arthas = instance->GetCreature(_arthasGUID))
{
if (!arthas->IsAlive())
{
EnsureGridLoaded();
arthas->setDeathState(DEAD);
arthas->Respawn();
}
else
{
arthas->AI()->Reset();
_respawnAndReposition = false;
}
}
}
// Used after 5-th crates is revealed
if (_showCrateTimer)
{
_showCrateTimer += diff;
if (_showCrateTimer >= 20000)
{
UpdateEventState();
_showCrateTimer = 0; // just to be sure
}
}
// Used to display how much time players have
if (_guardianTimer)
{
uint32 div = uint32(_guardianTimer / (MINUTE*IN_MILLISECONDS));
_guardianTimer -= diff;
uint32 divAfter = uint32(_guardianTimer / (MINUTE*IN_MILLISECONDS));
if (divAfter == 0)
{
_guardianTimer = 0;
DoUpdateWorldState(WORLDSTATE_TIME_GUARDIAN_SHOW, 0);
// Inform infinite we run out of time
if (instance->IsHeroic() && _infiniteGUID)
if (Creature* cr = instance->GetCreature(_infiniteGUID))
cr->AI()->DoAction(ACTION_RUN_OUT_OF_TIME);
}
else if (div > divAfter)
{
if (divAfter == 5)
ChromieWhisper(1);
else if (divAfter == 1)
ChromieWhisper(2);
DoUpdateWorldState(WORLDSTATE_TIME_GUARDIAN, divAfter);
SaveToDB();
}
}
}
void UpdateEventState()
{
if (_encounterState > COS_PROGRESS_NOT_STARTED)
{
// Summon Chromie and global whisper
instance->SummonCreature(NPC_CHROMIE_MIDDLE, EventPos[EVENT_POS_CHROMIE]);
instance->SummonCreature(NPC_HOURGLASS, EventPos[EVENT_POS_HOURGLASS]);
if (_encounterState == COS_PROGRESS_CRATES_FOUND ||
_encounterState == COS_PROGRESS_START_INTRO)
{
ChromieWhisper(0);
// hide crates count
DoUpdateWorldState(WORLDSTATE_SHOW_CRATES, 0);
_showCrateTimer = 0;
_encounterState = COS_PROGRESS_CRATES_FOUND;
}
}
}
void ChromieWhisper(uint8 textId)
{
if (!instance->GetPlayers().isEmpty())
if (Player* player = instance->GetPlayers().getFirst()->GetSource())
{
Position pos;
player->GetPosition(&pos);
if (Creature* cr = instance->SummonCreature(NPC_CHROMIE_MIDDLE, pos))
{
cr->SetVisible(false);
cr->DespawnOrUnsummon(1000);
sCreatureTextMgr->SendChat(cr, textId, player, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_MAP);
}
}
}
void Reposition(Creature* arthas)
{
switch (GetData(DATA_ARTHAS_EVENT))
{
case COS_PROGRESS_FINISHED_INTRO:
arthas->UpdatePosition(LeaderIntroPos2, true);
arthas->SetHomePosition(LeaderIntroPos2);
arthas->SetFacingTo(LeaderIntroPos2.GetOrientation());
break;
case COS_PROGRESS_FINISHED_CITY_INTRO:
case COS_PROGRESS_KILLED_MEATHOOK:
case COS_PROGRESS_KILLED_SALRAMM:
arthas->UpdatePosition(LeaderIntroPos2special, true);
arthas->SetHomePosition(LeaderIntroPos2special);
arthas->SetFacingTo(LeaderIntroPos2special.GetOrientation());
break;
case COS_PROGRESS_REACHED_TOWN_HALL:
arthas->UpdatePosition(LeaderIntroPos3, true);
arthas->SetHomePosition(LeaderIntroPos3);
arthas->SetFacingTo(LeaderIntroPos3.GetOrientation());
break;
case COS_PROGRESS_KILLED_EPOCH:
arthas->UpdatePosition(LeaderIntroPos4, true);
arthas->SetHomePosition(LeaderIntroPos4);
arthas->SetFacingTo(LeaderIntroPos4.GetOrientation());
break;
case COS_PROGRESS_LAST_CITY:
arthas->UpdatePosition(LeaderIntroPos5, true);
arthas->SetHomePosition(LeaderIntroPos5);
arthas->SetFacingTo(LeaderIntroPos5.GetOrientation());
break;
case COS_PROGRESS_BEFORE_MALGANIS:
arthas->UpdatePosition(LeaderIntroPos6, true);
arthas->SetHomePosition(LeaderIntroPos6);
arthas->SetFacingTo(LeaderIntroPos6.GetOrientation());
break;
}
}
void EnsureGridLoaded()
{
instance->LoadGrid(LeaderIntroPos1.GetPositionX(), LeaderIntroPos1.GetPositionY());
instance->LoadGrid(LeaderIntroPos2.GetPositionX(), LeaderIntroPos2.GetPositionY());
instance->LoadGrid(LeaderIntroPos3.GetPositionX(), LeaderIntroPos3.GetPositionY());
instance->LoadGrid(LeaderIntroPos4.GetPositionX(), LeaderIntroPos4.GetPositionY());
instance->LoadGrid(LeaderIntroPos5.GetPositionX(), LeaderIntroPos5.GetPositionY());
instance->LoadGrid(LeaderIntroPos6.GetPositionX(), LeaderIntroPos6.GetPositionY());
}
std::string GetSaveData()
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
saveStream << "C S " << _encounterState << ' ' << _guardianTimer;
OUT_SAVE_INST_DATA_COMPLETE;
return saveStream.str();
}
void Load(const char* in)
{
if (!in)
{
OUT_LOAD_INST_DATA_FAIL;
return;
}
OUT_LOAD_INST_DATA(in);
char dataHead1, dataHead2;
uint32 data0, data1;
std::istringstream loadStream(in);
loadStream >> dataHead1 >> dataHead2 >> data0 >> data1;
if (dataHead1 == 'C' && dataHead2 == 'S')
{
_encounterState = data0;
_guardianTimer = data1;
//UpdateEventState();
_loadTimer++;
}
else
OUT_LOAD_INST_DATA_FAIL;
OUT_LOAD_INST_DATA_COMPLETE;
}
private:
// NPCs
uint64 _arthasGUID;
uint64 _infiniteGUID;
// GOs
uint64 _shkafGateGUID;
uint64 _exitGateGUID;
uint32 _encounterState;
uint32 _crateCount;
uint32 _showCrateTimer;
uint32 _guardianTimer;
bool _respawnAndReposition;
uint32 _loadTimer;
};
};
void AddSC_instance_culling_of_stratholme()
{
new instance_culling_of_stratholme();
}

View File

@@ -1,213 +0,0 @@
/*
REWRITTEN BY XINEF
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "old_hillsbrad.h"
enum CaptainSkarloc
{
SAY_ENTER = 0,
SAY_TAUNT = 1,
SAY_SLAY = 2,
SAY_DEATH = 3,
SPELL_HOLY_LIGHT = 29427,
SPELL_CLEANSE = 29380,
SPELL_HAMMER_OF_JUSTICE = 13005,
SPELL_HOLY_SHIELD = 31904,
SPELL_DEVOTION_AURA = 8258,
SPELL_CONSECRATION = 38385,
WAYPOINTS_COUNT = 4,
EVENT_INITIAL_TALK = 1,
EVENT_START_FIGHT = 2,
EVENT_SPELL_CLEANSE = 10,
EVENT_SPELL_HAMMER = 11,
EVENT_SPELL_HOLY_LIGHT = 12,
EVENT_SPELL_HOLY_SHIELD = 13,
EVENT_SPELL_CONSECRATION = 14
};
const Position startPath[WAYPOINTS_COUNT] =
{
{2008.38f, 281.57f, 65.70f, 0.0f},
{2035.71f, 271.38f, 63.495f, 0.0f},
{2049.12f, 252.31f, 62.855f, 0.0f},
{2058.77f, 236.04f, 63.92f, 0.0f}
};
class boss_captain_skarloc : public CreatureScript
{
public:
boss_captain_skarloc() : CreatureScript("boss_captain_skarloc") { }
CreatureAI* GetAI(Creature* creature) const
{
return GetInstanceAI<boss_captain_skarlocAI>(creature);
}
struct boss_captain_skarlocAI : public ScriptedAI
{
boss_captain_skarlocAI(Creature* creature) : ScriptedAI(creature), summons(me) { }
EventMap events;
EventMap events2;
SummonList summons;
void Reset()
{
events.Reset();
events2.Reset();
summons.DespawnAll();
}
void JustSummoned(Creature* summon)
{
summons.Summon(summon);
if (Creature* thrall = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetData64(DATA_THRALL_GUID)))
thrall->AI()->JustSummoned(summon);
summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
if (summon->GetEntry() == NPC_SKARLOC_MOUNT)
return;
if (summons.size() == 1)
summon->GetMotionMaster()->MovePoint(0, 2060.788f, 237.301f, 63.999f);
else
summon->GetMotionMaster()->MovePoint(0, 2056.870f, 234.853f, 63.839f);
}
void InitializeAI()
{
ScriptedAI::InitializeAI();
Movement::PointsArray path;
path.push_back(G3D::Vector3(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()));
for (uint8 i = 0; i < WAYPOINTS_COUNT; ++i)
path.push_back(G3D::Vector3(startPath[i].GetPositionX(), startPath[i].GetPositionY(), startPath[i].GetPositionZ()));
me->GetMotionMaster()->MoveSplinePath(&path);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
me->Mount(SKARLOC_MOUNT_MODEL);
}
void MovementInform(uint32 type, uint32 id)
{
if (type != ESCORT_MOTION_TYPE)
return;
// Xinef: we can rely here on internal counting
if (id == 1)
{
me->SummonCreature(NPC_DURNHOLDE_MAGE, 2038.549f, 273.303f, 63.420f, 5.30f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_DURNHOLDE_VETERAN, 2032.810f, 269.416f, 63.561f, 5.30f, TEMPSUMMON_MANUAL_DESPAWN);
}
else if (id == 2)
{
me->SummonCreature(NPC_SKARLOC_MOUNT, 2049.12f, 252.31f, 62.855f, me->GetOrientation(), TEMPSUMMON_MANUAL_DESPAWN);
me->Dismount();
me->SetWalk(true);
for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
if (Creature* summon = ObjectAccessor::GetCreature(*me, *itr))
summon->SetWalk(true);
}
if (me->movespline->Finalized())
{
events2.ScheduleEvent(EVENT_INITIAL_TALK, 500);
events2.ScheduleEvent(EVENT_START_FIGHT, 8000);
}
}
void EnterCombat(Unit* /*who*/)
{
me->CastSpell(me, SPELL_DEVOTION_AURA, true);
events.ScheduleEvent(EVENT_SPELL_HOLY_LIGHT, 15000);
events.ScheduleEvent(EVENT_SPELL_CLEANSE, 6000);
events.ScheduleEvent(EVENT_SPELL_HAMMER, 20000);
events.ScheduleEvent(EVENT_SPELL_HOLY_SHIELD, 10000);
if (IsHeroic())
events.ScheduleEvent(EVENT_SPELL_CONSECRATION, 1000);
}
void KilledUnit(Unit* victim)
{
Talk(SAY_SLAY);
}
void JustDied(Unit* /*killer*/)
{
Talk(SAY_DEATH);
me->GetInstanceScript()->SetData(DATA_ESCORT_PROGRESS, ENCOUNTER_PROGRESS_SKARLOC_KILLED);
me->GetInstanceScript()->SetData(DATA_THRALL_ADD_FLAG, 0);
}
void UpdateAI(uint32 diff)
{
events2.Update(diff);
switch (events2.ExecuteEvent())
{
case EVENT_INITIAL_TALK:
Talk(SAY_ENTER);
break;
case EVENT_START_FIGHT:
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
me->SetInCombatWithZone();
for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
if (Creature* summon = ObjectAccessor::GetCreature(*me, *itr))
if (summon->GetEntry() != NPC_SKARLOC_MOUNT)
{
summon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
summon->SetInCombatWithZone();
}
break;
}
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_SPELL_HOLY_LIGHT:
me->CastSpell(me, SPELL_HOLY_LIGHT, false);
events.ScheduleEvent(EVENT_SPELL_HOLY_LIGHT, 20000);
break;
case EVENT_SPELL_CLEANSE:
if (roll_chance_i(33))
Talk(SAY_TAUNT);
me->CastSpell(me, SPELL_CLEANSE, false);
events.ScheduleEvent(EVENT_SPELL_CLEANSE, 10000);
break;
case EVENT_SPELL_HAMMER:
me->CastSpell(me->GetVictim(), SPELL_HAMMER_OF_JUSTICE, false);
events.ScheduleEvent(EVENT_SPELL_HAMMER, 30000);
break;
case EVENT_SPELL_HOLY_SHIELD:
me->CastSpell(me, SPELL_CLEANSE, false);
events.ScheduleEvent(SPELL_HOLY_SHIELD, 30000);
break;
case EVENT_SPELL_CONSECRATION:
me->CastSpell(me, SPELL_CONSECRATION, false);
events.ScheduleEvent(EVENT_SPELL_CONSECRATION, 20000);
break;
}
DoMeleeAttackIfReady();
}
};
};
void AddSC_boss_captain_skarloc()
{
new boss_captain_skarloc();
}

View File

@@ -1,114 +0,0 @@
/*
REWRITTEN BY XINEF
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "old_hillsbrad.h"
enum EpochHunter
{
SAY_AGGRO = 3,
SAY_SLAY = 4,
SAY_BREATH = 5,
SAY_DEATH = 6,
SPELL_SAND_BREATH = 31914,
SPELL_IMPENDING_DEATH = 31916,
SPELL_MAGIC_DISRUPTION_AURA = 33834,
SPELL_WING_BUFFET = 31475,
EVENT_SPELL_SAND_BREATH = 1,
EVENT_SPELL_IMPENDING_DEATH = 2,
EVENT_SPELL_DISRUPTION = 3,
EVENT_SPELL_WING_BUFFET = 4
};
class boss_epoch_hunter : public CreatureScript
{
public:
boss_epoch_hunter() : CreatureScript("boss_epoch_hunter") { }
CreatureAI* GetAI(Creature* creature) const
{
return GetInstanceAI<boss_epoch_hunterAI>(creature);
}
struct boss_epoch_hunterAI : public ScriptedAI
{
boss_epoch_hunterAI(Creature* creature) : ScriptedAI(creature) { }
EventMap events;
void Reset()
{
}
void EnterCombat(Unit* /*who*/)
{
Talk(SAY_AGGRO);
events.ScheduleEvent(EVENT_SPELL_SAND_BREATH, 8000);
events.ScheduleEvent(EVENT_SPELL_IMPENDING_DEATH, 2000);
events.ScheduleEvent(EVENT_SPELL_DISRUPTION, 20000);
events.ScheduleEvent(EVENT_SPELL_WING_BUFFET, 14000);
}
void KilledUnit(Unit* victim)
{
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
}
void JustDied(Unit* killer)
{
if (killer == me)
return;
Talk(SAY_DEATH);
me->GetInstanceScript()->SetData(DATA_ESCORT_PROGRESS, ENCOUNTER_PROGRESS_EPOCH_KILLED);
if (Creature* taretha = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetData64(DATA_TARETHA_GUID)))
taretha->AI()->DoAction(me->GetEntry());
}
void UpdateAI(uint32 diff)
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_SPELL_SAND_BREATH:
if (roll_chance_i(50))
Talk(SAY_BREATH);
me->CastSpell(me->GetVictim(), SPELL_SAND_BREATH, false);
events.ScheduleEvent(EVENT_SPELL_SAND_BREATH, 20000);
break;
case EVENT_SPELL_IMPENDING_DEATH:
me->CastSpell(me->GetVictim(), SPELL_IMPENDING_DEATH, false);
events.ScheduleEvent(EVENT_SPELL_IMPENDING_DEATH, 30000);
break;
case EVENT_SPELL_WING_BUFFET:
me->CastSpell(me, SPELL_WING_BUFFET, false);
events.ScheduleEvent(EVENT_SPELL_WING_BUFFET, 30000);
break;
case EVENT_SPELL_DISRUPTION:
me->CastSpell(me, SPELL_MAGIC_DISRUPTION_AURA, false);
events.ScheduleEvent(EVENT_SPELL_DISRUPTION, 30000);
break;
}
DoMeleeAttackIfReady();
}
};
};
void AddSC_boss_epoch_hunter()
{
new boss_epoch_hunter();
}

View File

@@ -1,159 +0,0 @@
/*
REWRITTEN BY XINEF
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "old_hillsbrad.h"
#include "MoveSplineInit.h"
#include "SmartScriptMgr.h"
enum LieutenantDrake
{
SAY_ENTER = 0,
SAY_AGGRO = 1,
SAY_SLAY = 2,
SAY_MORTAL = 3,
SAY_SHOUT = 4,
SAY_DEATH = 5,
SPELL_WHIRLWIND = 31909,
SPELL_EXPLODING_SHOT = 33792,
SPELL_HAMSTRING = 9080,
SPELL_MORTAL_STRIKE = 31911,
SPELL_FRIGHTENING_SHOUT = 33789,
EVENT_WHIRLWIND = 1,
EVENT_FRIGHTENING_SHOUT = 2,
EVENT_MORTAL_STRIKE = 3,
EVENT_HAMSTRING = 4,
EVENT_EXPLODING_SHOT = 5
};
class boss_lieutenant_drake : public CreatureScript
{
public:
boss_lieutenant_drake() : CreatureScript("boss_lieutenant_drake") { }
CreatureAI* GetAI(Creature* creature) const
{
return new boss_lieutenant_drakeAI(creature);
}
struct boss_lieutenant_drakeAI : public ScriptedAI
{
boss_lieutenant_drakeAI(Creature* creature) : ScriptedAI(creature)
{
pathPoints.clear();
WPPath* path = sSmartWaypointMgr->GetPath(me->GetEntry());
if (!path || path->empty())
return;
pathPoints.push_back(G3D::Vector3(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()));
uint32 wpCounter = 1;
WPPath::const_iterator itr;
while ((itr = path->find(wpCounter++)) != path->end())
{
WayPoint* wp = itr->second;
pathPoints.push_back(G3D::Vector3(wp->x, wp->y, wp->z));
}
}
void InitializeAI()
{
ScriptedAI::InitializeAI();
//Talk(SAY_ENTER);
JustReachedHome();
}
void JustReachedHome()
{
me->SetWalk(true);
Movement::MoveSplineInit init(me);
init.MovebyPath(pathPoints);
init.SetCyclic();
init.Launch();
}
void Reset()
{
events.Reset();
}
void EnterCombat(Unit* /*who*/)
{
Talk(SAY_AGGRO);
events.ScheduleEvent(EVENT_WHIRLWIND, 4000);
events.ScheduleEvent(EVENT_FRIGHTENING_SHOUT, 14000);
events.ScheduleEvent(EVENT_MORTAL_STRIKE, 9000);
events.ScheduleEvent(EVENT_HAMSTRING, 18000);
events.ScheduleEvent(EVENT_EXPLODING_SHOT, 1000);
}
void KilledUnit(Unit* victim)
{
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
}
void JustDied(Unit* /*killer*/)
{
Talk(SAY_DEATH);
if (InstanceScript* instance = me->GetInstanceScript())
instance->SetData(DATA_ESCORT_PROGRESS, ENCOUNTER_PROGRESS_DRAKE_KILLED);
}
void UpdateAI(uint32 diff)
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_WHIRLWIND:
me->CastSpell(me, SPELL_WHIRLWIND, false);
events.ScheduleEvent(EVENT_WHIRLWIND, 25000);
break;
case EVENT_EXPLODING_SHOT:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 40.0f))
me->CastSpell(target, SPELL_EXPLODING_SHOT, false);
events.ScheduleEvent(EVENT_EXPLODING_SHOT, 25000);
break;
case EVENT_MORTAL_STRIKE:
if (roll_chance_i(40))
Talk(SAY_MORTAL);
me->CastSpell(me->GetVictim(), SPELL_MORTAL_STRIKE, false);
events.ScheduleEvent(EVENT_MORTAL_STRIKE, 10000);
break;
case EVENT_FRIGHTENING_SHOUT:
if (roll_chance_i(40))
Talk(SAY_SHOUT);
me->CastSpell(me, SPELL_FRIGHTENING_SHOUT, false);
events.ScheduleEvent(EVENT_FRIGHTENING_SHOUT, 25000);
break;
case EVENT_HAMSTRING:
me->CastSpell(me->GetVictim(), SPELL_HAMSTRING, false);
events.ScheduleEvent(EVENT_HAMSTRING, 25000);
break;
}
DoMeleeAttackIfReady();
}
private:
EventMap events;
Movement::PointsArray pathPoints;
};
};
void AddSC_boss_lieutenant_drake()
{
new boss_lieutenant_drake();
}

View File

@@ -1,345 +0,0 @@
/*
REWRITTEN BY XINEF
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "InstanceScript.h"
#include "old_hillsbrad.h"
#include "Player.h"
const Position instancePositions[INSTANCE_POSITIONS_COUNT] =
{
{2188.18f, 228.90f, 53.025f, 1.77f}, // Orcs Gather Point 1
{2103.23f, 93.55f, 53.096f, 3.78f}, // Orcs Gather Point 2
{2128.43f, 71.01f, 64.42f, 1.74f} // Lieutenant Drake Summon Position
};
const Position thrallPositions[THRALL_POSITIONS_COUNT] =
{
{2181.37f, 119.15f, 89.45f, 5.75f}, // After wearing armor
{2096.09f, 195.91f, 65.22f, 2.45f}, // After Fourth Ambush
{2062.9f, 229.93f, 64.454f, 2.45f}, // After Captain Skarloc death
{2486.91f, 626.356f, 58.0761f, 0.0f}, // Arrived at Tarren Mill
{2660.47f, 659.223f, 62.0f, 5.78f} // Taretha Met
};
class instance_old_hillsbrad : public InstanceMapScript
{
public:
instance_old_hillsbrad() : InstanceMapScript("instance_old_hillsbrad", 560) { }
InstanceScript* GetInstanceScript(InstanceMap* map) const
{
return new instance_old_hillsbrad_InstanceMapScript(map);
}
struct instance_old_hillsbrad_InstanceMapScript : public InstanceScript
{
instance_old_hillsbrad_InstanceMapScript(Map* map) : InstanceScript(map) { }
void Initialize()
{
_encounterProgress = 0;
_barrelCount = 0;
_attemptsCount = 0;
_thrallGUID = 0;
_tarethaGUID = 0;
_initalFlamesSet.clear();
_finalFlamesSet.clear();
_prisonersSet.clear();
_events.Reset();
}
void OnPlayerEnter(Player* player)
{
if (instance->GetPlayersCountExceptGMs() == 1)
CleanupInstance();
EnsureGridLoaded();
if (_encounterProgress < ENCOUNTER_PROGRESS_BARRELS)
player->SendUpdateWorldState(WORLD_STATE_BARRELS_PLANTED, _barrelCount);
}
void CleanupInstance()
{
if (_encounterProgress == ENCOUNTER_PROGRESS_NONE)
return;
_events.ScheduleEvent(EVENT_INITIAL_BARRELS_FLAME, 0);
_events.ScheduleEvent(EVENT_FINAL_BARRELS_FLAME, 0);
if (_encounterProgress == ENCOUNTER_PROGRESS_BARRELS)
_events.ScheduleEvent(EVENT_SUMMON_LIEUTENANT, 0);
else
SetData(DATA_THRALL_REPOSITION, 2);
}
void OnCreatureCreate(Creature* creature)
{
switch (creature->GetEntry())
{
case NPC_THRALL:
_thrallGUID = creature->GetGUID();
if (_encounterProgress == ENCOUNTER_PROGRESS_FINISHED)
creature->SetVisible(false);
else
Reposition(creature);
break;
case NPC_ORC_PRISONER:
_prisonersSet.insert(creature->GetGUID());
break;
case NPC_TARETHA:
if (_encounterProgress == ENCOUNTER_PROGRESS_FINISHED)
creature->SetVisible(false);
_tarethaGUID = creature->GetGUID();
break;
}
}
void OnGameObjectCreate(GameObject* gameobject)
{
switch (gameobject->GetEntry())
{
case GO_BARREL:
if (_encounterProgress >= ENCOUNTER_PROGRESS_BARRELS)
gameobject->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
break;
case GO_PRISON_DOOR:
if (_encounterProgress >= ENCOUNTER_PROGRESS_THRALL_ARMORED)
gameobject->SetGoState(GO_STATE_ACTIVE);
break;
case GO_ROARING_FLAME:
// Xinef: hack in DB to distinguish final / initial flames
if (gameobject->GetPhaseMask() & 0x2)
_finalFlamesSet.insert(gameobject->GetGUID());
else
_initalFlamesSet.insert(gameobject->GetGUID());
break;
}
}
void SetData(uint32 type, uint32 data)
{
switch (type)
{
case DATA_THRALL_REPOSITION:
if (data > 1)
_events.ScheduleEvent(EVENT_THRALL_REPOSITION, data == 2 ? 0 : 10000);
else if (Creature* thrall = instance->GetCreature(_thrallGUID))
Reposition(thrall);
return;
case DATA_ESCORT_PROGRESS:
_encounterProgress = data;
SaveToDB();
break;
case DATA_BOMBS_PLACED:
{
if (_barrelCount >= 5 || _encounterProgress > ENCOUNTER_PROGRESS_NONE)
return;
DoUpdateWorldState(WORLD_STATE_BARRELS_PLANTED, ++_barrelCount);
if (_barrelCount == 5)
{
_events.ScheduleEvent(EVENT_INITIAL_BARRELS_FLAME, 4000);
_events.ScheduleEvent(EVENT_FINAL_BARRELS_FLAME, 12000);
_events.ScheduleEvent(EVENT_SUMMON_LIEUTENANT, 18000);
}
break;
}
case DATA_THRALL_ADD_FLAG:
if (Creature* thrall = instance->GetCreature(_thrallGUID))
thrall->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
break;
}
}
uint32 GetData(uint32 data) const
{
if (data == DATA_ESCORT_PROGRESS)
return _encounterProgress;
else if (data == DATA_ATTEMPTS_COUNT)
return _attemptsCount;
return 0;
}
uint64 GetData64(uint32 data) const
{
if (data == DATA_THRALL_GUID)
return _thrallGUID;
else if (data == DATA_TARETHA_GUID)
return _tarethaGUID;
return 0;
}
void Update(uint32 diff)
{
_events.Update(diff);
switch (_events.ExecuteEvent())
{
case EVENT_INITIAL_BARRELS_FLAME:
{
instance->LoadGrid(instancePositions[0].GetPositionX(), instancePositions[0].GetPositionY());
instance->LoadGrid(instancePositions[1].GetPositionX(), instancePositions[1].GetPositionY());
for (std::set<uint64>::const_iterator itr = _prisonersSet.begin(); itr != _prisonersSet.end(); ++itr)
if (Creature* orc = instance->GetCreature(*itr))
{
uint8 index = orc->GetDistance(instancePositions[0]) < 80.0f ? 0 : 1;
Position pos(instancePositions[index]);
orc->MovePosition(pos, frand(1.0f, 3.0f) + 15.0f * (float)rand_norm(), (float)rand_norm() * static_cast<float>(2 * M_PI));
orc->GetMotionMaster()->MovePoint(1, pos);
orc->SetStandState(UNIT_STAND_STATE_STAND);
}
for (std::set<uint64>::const_iterator itr = _initalFlamesSet.begin(); itr != _initalFlamesSet.end(); ++itr)
if (GameObject* gobject = instance->GetGameObject(*itr))
{
gobject->SetRespawnTime(0);
gobject->UpdateObjectVisibility(true);
}
break;
}
case EVENT_FINAL_BARRELS_FLAME:
{
instance->LoadGrid(instancePositions[0].GetPositionX(), instancePositions[0].GetPositionY());
instance->LoadGrid(instancePositions[1].GetPositionX(), instancePositions[1].GetPositionY());
if (_encounterProgress == ENCOUNTER_PROGRESS_NONE)
{
Map::PlayerList const& players = instance->GetPlayers();
if (!players.isEmpty())
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
if (Player* player = itr->GetSource())
player->KilledMonsterCredit(NPC_LODGE_QUEST_TRIGGER, 0);
}
for (std::set<uint64>::const_iterator itr = _finalFlamesSet.begin(); itr != _finalFlamesSet.end(); ++itr)
if (GameObject* gobject = instance->GetGameObject(*itr))
{
gobject->SetRespawnTime(0);
gobject->UpdateObjectVisibility(true);
}
for (std::set<uint64>::const_iterator itr = _prisonersSet.begin(); itr != _prisonersSet.end(); ++itr)
if (Creature* orc = instance->GetCreature(*itr))
if (roll_chance_i(25))
orc->HandleEmoteCommand(EMOTE_ONESHOT_CHEER);
SetData(DATA_ESCORT_PROGRESS, ENCOUNTER_PROGRESS_BARRELS);
DoUpdateWorldState(WORLD_STATE_BARRELS_PLANTED, 0);
break;
}
case EVENT_SUMMON_LIEUTENANT:
{
instance->LoadGrid(instancePositions[2].GetPositionX(), instancePositions[2].GetPositionY());
if (Creature* drake = instance->SummonCreature(NPC_LIEUTENANT_DRAKE, instancePositions[2]))
drake->AI()->Talk(0);
}
case EVENT_THRALL_REPOSITION:
{
if (Creature* thrall = instance->GetCreature(_thrallGUID))
{
if (!thrall->IsAlive())
{
++_attemptsCount;
EnsureGridLoaded();
thrall->SetVisible(false);
Reposition(thrall);
thrall->setDeathState(DEAD);
thrall->Respawn();
thrall->SetVisible(true);
SaveToDB();
}
else
thrall->AI()->Reset();
}
break;
}
}
}
void Reposition(Creature* thrall)
{
switch (uint32 data = GetData(DATA_ESCORT_PROGRESS))
{
case ENCOUNTER_PROGRESS_THRALL_ARMORED:
case ENCOUNTER_PROGRESS_AMBUSHES_1:
case ENCOUNTER_PROGRESS_SKARLOC_KILLED:
case ENCOUNTER_PROGRESS_TARREN_MILL:
case ENCOUNTER_PROGRESS_TARETHA_MEET:
thrall->UpdatePosition(thrallPositions[data - ENCOUNTER_PROGRESS_THRALL_ARMORED], true);
thrall->SetHomePosition(thrallPositions[data - ENCOUNTER_PROGRESS_THRALL_ARMORED]);
thrall->SetFacingTo(thrallPositions[data - ENCOUNTER_PROGRESS_THRALL_ARMORED].GetOrientation());
break;
}
}
void EnsureGridLoaded()
{
for (uint8 i = 0; i < THRALL_POSITIONS_COUNT; ++i)
instance->LoadGrid(thrallPositions[i].GetPositionX(), thrallPositions[i].GetPositionY());
}
std::string GetSaveData()
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
saveStream << "O H " << _encounterProgress << ' ' << _attemptsCount;
OUT_SAVE_INST_DATA_COMPLETE;
return saveStream.str();
}
void Load(const char* in)
{
if (!in)
{
OUT_LOAD_INST_DATA_FAIL;
return;
}
OUT_LOAD_INST_DATA(in);
char dataHead1, dataHead2;
uint32 data0, data1;
std::istringstream loadStream(in);
loadStream >> dataHead1 >> dataHead2 >> data0 >> data1;
if (dataHead1 == 'O' && dataHead2 == 'H')
{
_encounterProgress = data0;
_attemptsCount = data1;
}
else
OUT_LOAD_INST_DATA_FAIL;
OUT_LOAD_INST_DATA_COMPLETE;
}
private:
uint32 _encounterProgress;
uint32 _barrelCount;
uint32 _attemptsCount;
uint64 _thrallGUID;
uint64 _tarethaGUID;
std::set<uint64> _initalFlamesSet;
std::set<uint64> _finalFlamesSet;
std::set<uint64> _prisonersSet;
EventMap _events;
};
};
void AddSC_instance_old_hillsbrad()
{
new instance_old_hillsbrad();
}

View File

@@ -1,907 +0,0 @@
/*
REWRITTEN BY XINEF
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
#include "ScriptedEscortAI.h"
#include "old_hillsbrad.h"
#include "Player.h"
/*enum Erozion
{
QUEST_ENTRY_HILLSBRAD = 10282,
QUEST_ENTRY_DIVERSION = 10283,
QUEST_ENTRY_ESCAPE = 10284,
QUEST_ENTRY_RETURN = 10285,
ITEM_ENTRY_BOMBS = 25853
};
*/
enum Says
{
SAY_START_EVENT_PART1 = 0,
SAY_ARMORY = 1,
SAY_SKARLOC_MEET = 2,
SAY_SKARLOC_TAUNT = 3,
SAY_START_EVENT_PART2 = 4,
SAY_MOUNTS_UP = 5,
SAY_CHURCH_END = 6,
SAY_MEET_TARETHA = 7,
SAY_EPOCH_WONDER = 8,
SAY_EPOCH_KILL_TARETHA = 9,
SAY_EVENT_COMPLETE = 10,
SAY_RANDOM_LOW_HP = 11,
SAY_RANDOM_DIE = 12,
SAY_RANDOM_AGGRO = 13,
SAY_RANDOM_KILL = 14,
SAY_LEAVE_COMBAT = 15,
SAY_KILL_ARMORER = 16,
SAY_GO_ARMORED = 17,
SAY_ENTER_CHURCH = 18,
SAY_GREET_TARETHA = 19,
SAY_CHAT_TARETHA1 = 20,
SAY_TARETHA_FREE = 0,
SAY_TARETHA_ESCAPED = 1,
SAY_TARETHA_TALK1 = 2,
SAY_TARETHA_TALK2 = 3,
SAY_ARMORER_THRALL = 0,
SAY_LOOKOUT_SAW = 0,
SAY_LOOKOUT_GO = 1,
SAY_LOOKOUT_CHURCH = 2,
SAY_LOOKOUT_INN = 3,
SAY_EPOCH_ENTER1 = 0,
SAY_EPOCH_ENTER2 = 1,
SAY_EPOCH_ENTER3 = 2,
SAY_EROZION_1 = 0,
SAY_EROZION_2 = 1,
SAY_EROZION_3 = 2,
};
enum Spells
{
SPELL_STRIKE = 14516,
SPELL_SHIELD_BLOCK = 12169,
SPELL_SUMMON_EROZION_IMAGE = 33954,
SPELL_SHADOW_PRISON = 33071,
SPELL_SHADOW_SPIKE = 33125,
SPELL_TELEPORT = 34776,
SPELL_MEMORY_WIPE = 33336,
SPELL_MEMORY_WIPE_RESUME = 33337
};
enum Npcs
{
NPC_TM_GUARDSMAN = 18092,
NPC_TM_PROTECTOR = 18093,
NPC_TM_LOOKOUT = 18094,
NPC_EPOCH_GUARDSMAN = 23175,
NPC_EPOCH_PROTECTOR = 23179,
NPC_EPOCH_LOOKOUT = 23177,
NPC_INFINITE_DEFILER = 18171,
NPC_INFINITE_SABOTEUR = 18172,
NPC_INFINITE_SLAYER = 18170
};
enum Misc
{
THRALL_WEAPON_ITEM = 927,
THRALL_SHIELD_ITEM = 2129,
THRALL_MODEL_UNEQUIPPED = 17292,
THRALL_MODEL_EQUIPPED = 18165,
ACTION_SET_IMMUNE_FLAG = 1,
ACTION_REMOVE_IMMUNE_FLAG = 2,
ACTION_TRANSFORM = 3,
ACTION_MOVE = 4,
ACTION_START_COMBAT = 5
};
#define SPEED_RUNNING 1.0f
#define SPEED_MOUNTED 1.6f
enum Events
{
// Combat
EVENT_CHECK_HEALTH = 1,
EVENT_SPELL_STRIKE = 2,
EVENT_SPELL_SHIELD_BLOCK = 3,
EVENT_OPEN_DOORS = 6,
EVENT_START_WP = 7,
EVENT_SET_FACING = 9,
EVENT_KILL_ARMORER = 10,
EVENT_TALK_KILL_ARMORER = 11,
EVENT_DRESSING_KNEEL = 20,
EVENT_DRESSING_ARMOR = 21,
EVENT_DRESSING_STAND = 22,
EVENT_DRESSING_AXE = 23,
EVENT_DRESSING_SHIELD = 24,
EVENT_DRESSING_TALK = 25,
EVENT_ENTER_MOUNT = 30,
EVENT_TALK_START_RIDE = 31,
EVENT_LOOK_1 = 40,
EVENT_MOVE_AROUND = 41,
EVENT_LOOK_2 = 42,
EVENT_LOOK_3 = 43,
EVENT_SUMMON_GUARDS = 44,
EVENT_SUMMON_TALK1 = 45,
EVENT_SUMMON_TALK2 = 46,
EVENT_LOOK_4 = 50,
EVENT_SUMMON_GUARDS_2 = 51,
EVENT_SUMMON_TALK3 = 52,
EVENT_THRALL_TALK = 60,
EVENT_SUMMON_CHRONO = 61,
EVENT_THRALL_TALK_2 = 62,
EVENT_TARETHA_FALL = 63,
EVENT_THRALL_TALK_3 = 64,
EVENT_THRALL_MOVE_DOWN = 65,
EVENT_EPOCH_INTRO = 70,
EVENT_SUMMON_INFINITES = 71,
EVENT_TRANSFORM = 72,
EVENT_START_WAVE_1 = 73,
EVENT_CHECK_WAVE_1 = 74,
EVENT_CHECK_WAVE_2 = 75,
EVENT_CHECK_WAVE_3 = 76,
EVENT_CALL_EPOCH = 77,
EVENT_THRALL_FACE_TARETHA = 80,
EVENT_THRALL_TALK_4 = 81,
EVENT_TARETHA_TALK_1 = 82,
EVENT_THRALL_TALK_5 = 83,
EVENT_SUMMON_EROZION = 84,
EVENT_EROZION_TALK_1 = 85,
EVENT_EROZION_ACTION_1 = 86,
EVENT_EROZION_TALK_2 = 87,
EVENT_EROZION_ACTION_2 = 88,
EVENT_EROZION_TALK_3 = 89,
EVENT_THRALL_TALK_6 = 90,
EVENT_THRALL_RUN_AWAY = 91,
EVENT_TARETHA_TALK_2 = 92
};
class npc_thrall_old_hillsbrad : public CreatureScript
{
public:
npc_thrall_old_hillsbrad() : CreatureScript("npc_thrall_old_hillsbrad") { }
CreatureAI* GetAI(Creature* creature) const
{
return GetInstanceAI<npc_thrall_old_hillsbradAI>(creature);
}
bool OnGossipHello(Player* player, Creature* creature)
{
InstanceScript* instance = creature->GetInstanceScript();
if (!instance)
return true;
uint32 menuId = creature->GetCreatureTemplate()->GossipMenuId;
if (instance->GetData(DATA_ESCORT_PROGRESS) == ENCOUNTER_PROGRESS_SKARLOC_KILLED)
menuId = 7830;
else if (instance->GetData(DATA_ESCORT_PROGRESS) == ENCOUNTER_PROGRESS_TARREN_MILL)
menuId = 7840;
else if (instance->GetData(DATA_ESCORT_PROGRESS) == ENCOUNTER_PROGRESS_TARETHA_MEET)
menuId = 7853;
player->PrepareGossipMenu(creature, menuId, true);
player->SendPreparedGossip(creature);
return true;
}
bool OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action)
{
GossipMenuItemData const* gossipMenuItemData = player->PlayerTalkClass->GetGossipMenu().GetItemData(0);
InstanceScript* instance = creature->GetInstanceScript();
if (!instance || (gossipMenuItemData && gossipMenuItemData->GossipActionMenuId != 0))
return false;
player->PlayerTalkClass->ClearMenus();
player->CLOSE_GOSSIP_MENU();
creature->AI()->DoAction(instance->GetData(DATA_ESCORT_PROGRESS));
creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP|UNIT_NPC_FLAG_QUESTGIVER);
return true;
}
struct npc_thrall_old_hillsbradAI : public npc_escortAI
{
npc_thrall_old_hillsbradAI(Creature* creature) : npc_escortAI(creature), summons(me)
{
instance = creature->GetInstanceScript();
}
void DoAction(int32 param)
{
switch (param)
{
case ENCOUNTER_PROGRESS_DRAKE_KILLED:
events.ScheduleEvent(EVENT_OPEN_DOORS, 0);
events.ScheduleEvent(EVENT_START_WP, 3000);
break;
case ENCOUNTER_PROGRESS_THRALL_ARMORED:
case ENCOUNTER_PROGRESS_AMBUSHES_1:
case ENCOUNTER_PROGRESS_SKARLOC_KILLED:
case ENCOUNTER_PROGRESS_TARREN_MILL:
SetEscortPaused(false);
break;
case ENCOUNTER_PROGRESS_TARETHA_MEET:
events.ScheduleEvent(EVENT_SUMMON_CHRONO, 0);
events.ScheduleEvent(EVENT_THRALL_TALK_2, 6000);
events.ScheduleEvent(EVENT_TARETHA_FALL, 11000);
events.ScheduleEvent(EVENT_THRALL_TALK_3, 14000);
events.ScheduleEvent(EVENT_THRALL_MOVE_DOWN, 17000);
break;
case NPC_TARETHA:
events.ScheduleEvent(EVENT_THRALL_FACE_TARETHA, 0);
events.ScheduleEvent(EVENT_THRALL_TALK_4, 4000);
events.ScheduleEvent(EVENT_TARETHA_TALK_1, 13000);
events.ScheduleEvent(EVENT_THRALL_TALK_5, 17000);
events.ScheduleEvent(EVENT_SUMMON_EROZION, 17500);
events.ScheduleEvent(EVENT_EROZION_TALK_1, 18000);
events.ScheduleEvent(EVENT_EROZION_ACTION_1, 26000);
events.ScheduleEvent(EVENT_EROZION_TALK_2, 29000);
events.ScheduleEvent(EVENT_EROZION_TALK_3, 42000);
events.ScheduleEvent(EVENT_EROZION_ACTION_2, 47000);
events.ScheduleEvent(EVENT_THRALL_TALK_6, 48000);
events.ScheduleEvent(EVENT_THRALL_RUN_AWAY, 51000);
events.ScheduleEvent(EVENT_TARETHA_TALK_2, 53000);
break;
}
}
void WaypointStart(uint32 waypointId)
{
switch (waypointId)
{
case 30:
Talk(SAY_START_EVENT_PART2);
break;
}
}
void WaypointReached(uint32 waypointId)
{
switch (waypointId)
{
case 0:
Talk(SAY_START_EVENT_PART1);
break;
case 8:
events.ScheduleEvent(EVENT_SET_FACING, 500);
break;
case 9:
SetRun(false);
events.ScheduleEvent(EVENT_KILL_ARMORER, 500);
events.ScheduleEvent(EVENT_TALK_KILL_ARMORER, 4000);
break;
case 10:
SetRun(true);
events.ScheduleEvent(EVENT_DRESSING_KNEEL, 500);
events.ScheduleEvent(EVENT_DRESSING_ARMOR, 3000);
events.ScheduleEvent(EVENT_DRESSING_STAND, 4000);
events.ScheduleEvent(EVENT_DRESSING_AXE, 7000);
events.ScheduleEvent(EVENT_DRESSING_SHIELD, 9000);
events.ScheduleEvent(EVENT_DRESSING_TALK, 12000);
break;
case 13:
me->SummonCreature(NPC_DURNHOLDE_SENTRY, 2200.28f, 137.37f, 87.93f, 5.07f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_DURNHOLDE_SENTRY, 2197.44f, 131.83f, 87.93f, 0.78f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_DURNHOLDE_MAGE, 2203.62f, 135.40f, 87.93f, 3.70f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_DURNHOLDE_VETERAN, 2200.75f, 130.13f, 87.93f, 1.48f, TEMPSUMMON_MANUAL_DESPAWN);
break;
case 16:
me->SummonCreature(NPC_DURNHOLDE_SENTRY, 2147.43f, 122.194f, 76.422f, 0.67f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_DURNHOLDE_SENTRY, 2146.27f, 126.13f, 76.241f, 0.60f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_DURNHOLDE_MAGE, 2142.62f, 120.38f, 75.862f, 0.48f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_DURNHOLDE_VETERAN, 2141.74f, 123.95f, 75.732f, 0.24f, TEMPSUMMON_MANUAL_DESPAWN);
break;
case 18:
me->SummonCreature(NPC_DURNHOLDE_SENTRY, 2138.37f, 167.98f, 66.23f, 2.59f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_DURNHOLDE_WARDEN, 2142.76f, 173.62f, 66.23f, 2.59f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_DURNHOLDE_MAGE, 2140.96f, 168.64f, 66.23f, 2.59f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_DURNHOLDE_VETERAN, 2142.53f, 171.03f, 66.23f, 2.59f, TEMPSUMMON_MANUAL_DESPAWN);
break;
case 22:
me->SummonCreature(NPC_DURNHOLDE_SENTRY, 2108.73f, 190.43f, 66.23f, 5.56f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_DURNHOLDE_MAGE, 2109.74f, 195.29f, 66.23f, 5.56f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_DURNHOLDE_MAGE, 2107.74f, 192.59f, 66.23f, 5.56f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_DURNHOLDE_SENTRY, 2112.26f, 195.13f, 66.23f, 5.56f, TEMPSUMMON_MANUAL_DESPAWN);
break;
case 27:
instance->SetData(DATA_ESCORT_PROGRESS, ENCOUNTER_PROGRESS_AMBUSHES_1);
break;
case 28:
me->SummonCreature(NPC_CAPTAIN_SKARLOC, 1995.78f, 277.46f, 66.64f, 0.74f, TEMPSUMMON_MANUAL_DESPAWN);
break;
case 29:
SetEscortPaused(true);
Talk(SAY_SKARLOC_MEET);
break;
case 30:
events.ScheduleEvent(EVENT_ENTER_MOUNT, 3000);
events.ScheduleEvent(EVENT_TALK_START_RIDE, 7000);
break;
case 59:
instance->SetData(DATA_ESCORT_PROGRESS, ENCOUNTER_PROGRESS_TARREN_MILL);
me->SummonCreature(NPC_SKARLOC_MOUNT, 2488.64f, 625.77f, 58.26f, 4.71f, TEMPSUMMON_TIMED_DESPAWN, 7000);
UnMountSelf();
_mounted = false;
SetRun(false);
break;
case 60:
me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION);
if (Creature* horse = me->FindNearestCreature(NPC_SKARLOC_MOUNT, 10.0f))
horse->GetMotionMaster()->MovePoint(0, 2501.15f, 572.14f, 54.13f);
SetEscortPaused(true);
SetRun(true);
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
break;
case 64:
SetRun(false);
break;
case 67:
events.ScheduleEvent(EVENT_LOOK_1, 500);
events.ScheduleEvent(EVENT_MOVE_AROUND, 3500);
events.ScheduleEvent(EVENT_LOOK_2, 5000);
events.ScheduleEvent(EVENT_LOOK_3, 6700);
events.ScheduleEvent(EVENT_SUMMON_GUARDS, 6000);
events.ScheduleEvent(EVENT_SUMMON_TALK1, 6500);
events.ScheduleEvent(EVENT_SUMMON_TALK2, 12000);
break;
case 82:
events.ScheduleEvent(EVENT_LOOK_4, 500);
events.ScheduleEvent(EVENT_SUMMON_GUARDS_2, 1000);
events.ScheduleEvent(EVENT_SUMMON_TALK3, 1500);
break;
case 91:
me->SummonCreature(NPC_TM_PROTECTOR, 2652.71f, 660.31f, 61.93f, 1.67f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_TM_LOOKOUT, 2648.96f, 662.59f, 61.93f, 0.79f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_TM_GUARDSMAN, 2657.36f, 662.34f, 61.93f, 2.68f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_TM_GUARDSMAN, 2656.39f, 659.77f, 61.93f, 2.61f, TEMPSUMMON_MANUAL_DESPAWN);
if (Creature* summon = summons.GetCreatureWithEntry(NPC_TM_LOOKOUT))
summon->AI()->Talk(SAY_LOOKOUT_INN);
break;
case 92:
SetRun(false);
break;
case 94:
summons.DespawnAll();
SetEscortPaused(true);
SetRun(true);
instance->SetData(DATA_ESCORT_PROGRESS, ENCOUNTER_PROGRESS_TARETHA_MEET);
if (Creature* Taretha = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_TARETHA_GUID)))
Taretha->AI()->Talk(SAY_TARETHA_ESCAPED);
events.ScheduleEvent(EVENT_THRALL_TALK, 2000);
break;
case 101:
SetEscortPaused(true);
events.ScheduleEvent(EVENT_EPOCH_INTRO, 500);
events.ScheduleEvent(EVENT_SUMMON_INFINITES, 1500);
events.ScheduleEvent(EVENT_TRANSFORM, 8000);
events.ScheduleEvent(EVENT_START_WAVE_1, 25000);
break;
case 103:
if (Creature* erozion = summons.GetCreatureWithEntry(NPC_EROZION))
erozion->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
instance->SetData(DATA_ESCORT_PROGRESS, ENCOUNTER_PROGRESS_FINISHED);
me->SetVisible(false);
break;
}
}
void MountSelf()
{
me->Mount(SKARLOC_MOUNT_MODEL);
me->SetSpeed(MOVE_RUN, SPEED_MOUNTED);
}
void UnMountSelf()
{
me->Dismount();
me->SetSpeed(MOVE_RUN, SPEED_RUNNING);
}
void MovementInform(uint32 type, uint32 point)
{
npc_escortAI::MovementInform(type, point);
if (type == POINT_MOTION_TYPE && point == 0xFFFFFF /*POINT_LAST_POINT*/)
{
if (roll_chance_i(30))
Talk(SAY_LEAVE_COMBAT);
if (_mounted)
MountSelf();
}
}
void EnterCombat(Unit*)
{
combatEvents.Reset();
combatEvents.ScheduleEvent(EVENT_CHECK_HEALTH, 500);
combatEvents.ScheduleEvent(EVENT_SPELL_SHIELD_BLOCK, 8000);
combatEvents.ScheduleEvent(EVENT_SPELL_STRIKE, 2000);
if (roll_chance_i(50))
Talk(SAY_RANDOM_AGGRO);
if (me->IsMounted())
{
_mounted = true;
UnMountSelf();
}
}
void Reset()
{
_mounted = false;
events.Reset();
combatEvents.Reset();
summons.DespawnAll();
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP|UNIT_NPC_FLAG_QUESTGIVER);
instance->SetData(DATA_THRALL_REPOSITION, 1);
uint32 data = instance->GetData(DATA_ESCORT_PROGRESS);
if (data >= ENCOUNTER_PROGRESS_THRALL_ARMORED)
ReorderInstance(data);
}
void KilledUnit(Unit*)
{
Talk(SAY_RANDOM_KILL);
}
void JustSummoned(Creature* summon)
{
if (summon->GetEntry() == NPC_INFINITE_SLAYER || summon->GetEntry() == NPC_INFINITE_SABOTEUR || summon->GetEntry() == NPC_INFINITE_DEFILER)
summon->GetMotionMaster()->MovePoint(10, 2634.25f, 672.01f, 54.445f);
summons.Summon(summon);
}
void SummonedCreatureDespawn(Creature* summon) { summons.Despawn(summon); }
void SummonedCreatureDies(Creature* summon, Unit*) { summons.Despawn(summon); }
void JustDied(Unit* killer)
{
if (killer == me)
return;
summons.DespawnAll();
Talk(SAY_RANDOM_DIE);
RemoveEscortState(STATE_ESCORT_ESCORTING);
instance->SetData(DATA_THRALL_REPOSITION, 3);
if (instance->GetData(DATA_ATTEMPTS_COUNT) < 20)
me->CastSpell(me, SPELL_SUMMON_EROZION_IMAGE, true);
else
me->SetRespawnTime(DAY);
}
void UpdateAI(uint32 diff)
{
npc_escortAI::UpdateAI(diff);
events.Update(diff);
switch (events.ExecuteEvent())
{
case EVENT_OPEN_DOORS:
if (GameObject* doors = me->FindNearestGameObject(GO_PRISON_DOOR, 10.0f))
doors->SetGoState(GO_STATE_ACTIVE);
break;
case EVENT_START_WP:
Start(true, true);
SetDespawnAtEnd(false);
break;
case EVENT_SET_FACING:
if (Creature* armorer = me->FindNearestCreature(NPC_DURNHOLDE_ARMORER, 30.0f))
{
armorer->AI()->Talk(SAY_ARMORER_THRALL);
armorer->SetFacingToObject(me);
me->SetFacingToObject(armorer);
}
break;
case EVENT_KILL_ARMORER:
me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACK_UNARMED);
if (Creature* armorer = me->FindNearestCreature(NPC_DURNHOLDE_ARMORER, 30.0f))
armorer->SetStandState(UNIT_STAND_STATE_DEAD);
break;
case EVENT_TALK_KILL_ARMORER:
Talk(SAY_KILL_ARMORER);
break;
case EVENT_DRESSING_KNEEL:
me->SetFacingTo(2.61f);
Talk(SAY_ARMORY);
me->SetStandState(UNIT_STAND_STATE_KNEEL);
break;
case EVENT_DRESSING_ARMOR:
me->SetDisplayId(THRALL_MODEL_EQUIPPED);
break;
case EVENT_DRESSING_STAND:
me->SetStandState(UNIT_STAND_STATE_STAND);
break;
case EVENT_DRESSING_AXE:
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, THRALL_WEAPON_ITEM);
break;
case EVENT_DRESSING_SHIELD:
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, THRALL_SHIELD_ITEM);
break;
case EVENT_DRESSING_TALK:
instance->SetData(DATA_ESCORT_PROGRESS, ENCOUNTER_PROGRESS_THRALL_ARMORED);
Talk(SAY_GO_ARMORED);
break;
case EVENT_ENTER_MOUNT:
MountSelf();
if (Creature* mount = me->FindNearestCreature(NPC_SKARLOC_MOUNT, 10.0f))
{
me->SetFacingTo(mount->GetOrientation());
mount->DespawnOrUnsummon();
}
break;
case EVENT_TALK_START_RIDE:
Talk(SAY_MOUNTS_UP);
break;
case EVENT_LOOK_1:
me->SetFacingTo(5.058f);
break;
case EVENT_MOVE_AROUND:
me->GetMotionMaster()->MovePoint(0, 2477.146f, 695.041f, 55.801f);
break;
case EVENT_LOOK_2:
me->SetFacingTo(2.297f);
break;
case EVENT_LOOK_3:
me->SetFacingTo(0.64f);
break;
case EVENT_SUMMON_GUARDS:
SetRun(true);
me->SummonCreature(NPC_TM_PROTECTOR, 2501.34f, 700.80f, 55.573f, 3.92f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_TM_LOOKOUT, 2503.02f, 699.11f, 55.57f, 3.92f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_TM_GUARDSMAN, 2503.04f, 702.495f, 50.63f, 3.92f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_TM_GUARDSMAN, 2504.72f, 700.806f, 55.62f, 3.92f, TEMPSUMMON_MANUAL_DESPAWN);
summons.DoAction(ACTION_SET_IMMUNE_FLAG);
break;
case EVENT_SUMMON_TALK1:
if (Creature* summon = summons.GetCreatureWithEntry(NPC_TM_LOOKOUT))
summon->AI()->Talk(SAY_LOOKOUT_SAW);
break;
case EVENT_SUMMON_TALK2:
if (Creature* summon = summons.GetCreatureWithEntry(NPC_TM_LOOKOUT))
summon->AI()->Talk(SAY_LOOKOUT_GO);
summons.DoAction(ACTION_REMOVE_IMMUNE_FLAG);
break;
case EVENT_LOOK_4:
me->SetFacingTo(0.41f);
Talk(SAY_ENTER_CHURCH);
break;
case EVENT_SUMMON_GUARDS_2:
me->SummonCreature(NPC_TM_PROTECTOR, 2630.75f, 664.80f, 54.28f, 4.37f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_TM_LOOKOUT, 2632.20f, 661.98f, 54.30f, 4.37f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_TM_GUARDSMAN, 2630.02f, 662.75f, 54.28f, 4.37f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_TM_GUARDSMAN, 2632.86f, 664.05f, 54.31f, 4.37f, TEMPSUMMON_MANUAL_DESPAWN);
break;
case EVENT_SUMMON_TALK3:
if (Creature* summon = summons.GetCreatureWithEntry(NPC_TM_LOOKOUT))
summon->AI()->Talk(SAY_LOOKOUT_CHURCH);
break;
case EVENT_THRALL_TALK:
Talk(SAY_MEET_TARETHA);
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
break;
case EVENT_SUMMON_CHRONO:
if (Creature* epoch = me->SummonCreature(NPC_EPOCH_HUNTER, 2640.49f, 696.15f, 64.31f, 4.51f, TEMPSUMMON_MANUAL_DESPAWN))
{
epoch->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
epoch->AI()->Talk(SAY_EPOCH_ENTER1);
}
break;
case EVENT_THRALL_TALK_2:
me->SetFacingTo(2.67f);
Talk(SAY_EPOCH_WONDER);
break;
case EVENT_TARETHA_FALL:
if (Creature* epoch = summons.GetCreatureWithEntry(NPC_EPOCH_HUNTER))
epoch->AI()->Talk(SAY_EPOCH_ENTER2);
if (Creature* Taretha = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_TARETHA_GUID)))
{
Taretha->CastSpell(Taretha, SPELL_SHADOW_SPIKE);
Taretha->SetStandState(UNIT_STAND_STATE_DEAD);
}
break;
case EVENT_THRALL_TALK_3:
me->SetFacingTo(5.78f);
Talk(SAY_EPOCH_KILL_TARETHA);
break;
case EVENT_THRALL_MOVE_DOWN:
SetEscortPaused(false);
break;
case EVENT_EPOCH_INTRO:
me->SetFacingTo(1.33f);
if (Creature* epoch = summons.GetCreatureWithEntry(NPC_EPOCH_HUNTER))
epoch->AI()->Talk(SAY_EPOCH_ENTER3);
break;
case EVENT_SUMMON_INFINITES:
me->SummonCreature(NPC_EPOCH_LOOKOUT, 2647.57f, 701.17f, 56.215f, 4.3f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_EPOCH_GUARDSMAN, 2629.46f, 704.76f, 56.286f, 4.98f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_EPOCH_PROTECTOR, 2640.14f, 709.44f, 56.135f, 4.70f, TEMPSUMMON_MANUAL_DESPAWN);
summons.DoAction(ACTION_SET_IMMUNE_FLAG);
summons.DoAction(ACTION_MOVE);
break;
case EVENT_TRANSFORM:
summons.DoAction(ACTION_TRANSFORM);
summons.DoAction(ACTION_SET_IMMUNE_FLAG);
break;
case EVENT_START_WAVE_1:
events.ScheduleEvent(EVENT_CHECK_WAVE_1, 500);
summons.DoAction(ACTION_REMOVE_IMMUNE_FLAG);
summons.DoAction(ACTION_START_COMBAT);
break;
case EVENT_CHECK_WAVE_1:
if (summons.size() == 1)
{
me->SummonCreature(NPC_INFINITE_SABOTEUR, 2599.57f, 683.72f, 55.975f, 0.05f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_INFINITE_SLAYER, 2599.57f, 677.0f, 55.975f, 0.05f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_INFINITE_DEFILER, 2592.57f, 680.0f, 55.975f, 0.05f, TEMPSUMMON_MANUAL_DESPAWN);
summons.DoAction(ACTION_START_COMBAT);
events.ScheduleEvent(EVENT_CHECK_WAVE_2, 500);
break;
}
events.ScheduleEvent(EVENT_CHECK_WAVE_1, 500);
break;
case EVENT_CHECK_WAVE_2:
if (summons.size() == 1)
{
me->SummonCreature(NPC_INFINITE_SLAYER, 2642.62f, 701.43f, 55.965f, 4.46f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_INFINITE_SLAYER, 2638.62f, 701.43f, 55.965f, 4.46f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_INFINITE_SABOTEUR, 2638.62f, 705.43f, 55.965f, 4.46f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_INFINITE_DEFILER, 2642.62f, 705.43f, 55.965f, 4.46f, TEMPSUMMON_MANUAL_DESPAWN);
summons.DoAction(ACTION_START_COMBAT);
events.ScheduleEvent(EVENT_CHECK_WAVE_3, 500);
break;
}
events.ScheduleEvent(EVENT_CHECK_WAVE_2, 500);
break;
case EVENT_CHECK_WAVE_3:
if (summons.size() == 1)
{
me->SetHomePosition(2634.79f, 672.964f, 54.8577f, 1.33f);
me->GetMotionMaster()->MoveTargetedHome();
events.ScheduleEvent(EVENT_CALL_EPOCH, 8000);
break;
}
events.ScheduleEvent(EVENT_CHECK_WAVE_3, 500);
break;
case EVENT_CALL_EPOCH:
if (Creature* epoch = summons.GetCreatureWithEntry(NPC_EPOCH_HUNTER))
{
epoch->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
epoch->GetMotionMaster()->MovePoint(0, *me, false, true);
}
break;
case EVENT_THRALL_FACE_TARETHA:
{
Map::PlayerList const& players = me->GetMap()->GetPlayers();
if (!players.isEmpty())
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
if (Player* player = itr->GetSource())
player->KilledMonsterCredit(20156, 0);
me->SetFacingTo(5.76f);
break;
}
case EVENT_THRALL_TALK_4:
Talk(SAY_GREET_TARETHA);
break;
case EVENT_TARETHA_TALK_1:
if (Creature* Taretha = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_TARETHA_GUID)))
Taretha->AI()->Talk(SAY_TARETHA_TALK1);
break;
case EVENT_THRALL_TALK_5:
Talk(SAY_CHAT_TARETHA1);
break;
case EVENT_SUMMON_EROZION:
if (Creature* erozion = me->SummonCreature(NPC_EROZION, 2646.31f, 680.01f, 55.36f, 3.76f, TEMPSUMMON_MANUAL_DESPAWN))
erozion->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
break;
case EVENT_EROZION_TALK_1:
if (Creature* erozion = summons.GetCreatureWithEntry(NPC_EROZION))
{
erozion->CastSpell(erozion, SPELL_TELEPORT, true);
erozion->AI()->Talk(SAY_EROZION_1);
}
break;
case EVENT_EROZION_ACTION_1:
if (Creature* erozion = summons.GetCreatureWithEntry(NPC_EROZION))
erozion->CastSpell(erozion, SPELL_MEMORY_WIPE, false);
break;
case EVENT_EROZION_TALK_2:
if (Creature* erozion = summons.GetCreatureWithEntry(NPC_EROZION))
erozion->AI()->Talk(SAY_EROZION_2);
break;
case EVENT_EROZION_TALK_3:
if (Creature* erozion = summons.GetCreatureWithEntry(NPC_EROZION))
erozion->AI()->Talk(SAY_EROZION_3);
break;
case EVENT_EROZION_ACTION_2:
if (Creature* erozion = summons.GetCreatureWithEntry(NPC_EROZION))
erozion->CastSpell(erozion, SPELL_MEMORY_WIPE_RESUME, false);
break;
case EVENT_THRALL_TALK_6:
Talk(SAY_EVENT_COMPLETE);
break;
case EVENT_THRALL_RUN_AWAY:
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
me->SetReactState(REACT_PASSIVE);
SetEscortPaused(false);
break;
case EVENT_TARETHA_TALK_2:
if (Creature* Taretha = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_TARETHA_GUID)))
{
Taretha->SetFacingTo(4.233f);
Taretha->AI()->Talk(SAY_TARETHA_TALK2);
}
break;
}
}
void UpdateEscortAI(uint32 diff)
{
if (!UpdateVictim())
return;
combatEvents.Update(diff);
switch (combatEvents.ExecuteEvent())
{
case EVENT_CHECK_HEALTH:
if (me->HealthBelowPct(20))
{
Talk(SAY_RANDOM_LOW_HP);
break;
}
events.ScheduleEvent(EVENT_CHECK_HEALTH, 500);
break;
case EVENT_SPELL_STRIKE:
me->CastSpell(me->GetVictim(), SPELL_STRIKE, false);
events.ScheduleEvent(EVENT_SPELL_STRIKE, 6000);
break;
case EVENT_SPELL_SHIELD_BLOCK:
me->CastSpell(me, SPELL_SHIELD_BLOCK, false);
events.ScheduleEvent(EVENT_SPELL_SHIELD_BLOCK, 6000);
break;
}
DoMeleeAttackIfReady();
}
void ReorderInstance(uint32 data)
{
Start(true, true);
SetEscortPaused(true);
SetDespawnAtEnd(false);
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP|UNIT_NPC_FLAG_QUESTGIVER);
if (data < ENCOUNTER_PROGRESS_THRALL_ARMORED)
{
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0);
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0);
me->SetDisplayId(THRALL_MODEL_UNEQUIPPED);
}
else
{
me->SetDisplayId(THRALL_MODEL_EQUIPPED);
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, THRALL_WEAPON_ITEM);
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, THRALL_SHIELD_ITEM);
}
switch (data)
{
case ENCOUNTER_PROGRESS_THRALL_ARMORED:
SetNextWaypoint(11, false);
break;
case ENCOUNTER_PROGRESS_AMBUSHES_1:
SetNextWaypoint(27, false);
break;
case ENCOUNTER_PROGRESS_SKARLOC_KILLED:
me->SummonCreature(NPC_SKARLOC_MOUNT, 2049.12f, 252.31f, 62.855f, me->GetOrientation(), TEMPSUMMON_MANUAL_DESPAWN);
SetNextWaypoint(30, false);
break;
case ENCOUNTER_PROGRESS_TARREN_MILL:
SetNextWaypoint(61, false);
break;
case ENCOUNTER_PROGRESS_TARETHA_MEET:
SetNextWaypoint(95, false);
if (Creature* Taretha = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_TARETHA_GUID)))
Taretha->SetStandState(UNIT_STAND_STATE_STAND);
break;
}
}
private:
InstanceScript* instance;
EventMap events;
EventMap combatEvents;
SummonList summons;
bool _mounted;
};
};
class npc_taretha : public CreatureScript
{
public:
npc_taretha() : CreatureScript("npc_taretha") { }
CreatureAI* GetAI(Creature* creature) const
{
return GetInstanceAI<npc_tarethaAI>(creature);
}
bool OnGossipHello(Player* player, Creature* creature)
{
return true;
}
struct npc_tarethaAI : public npc_escortAI
{
npc_tarethaAI(Creature* creature) : npc_escortAI(creature)
{
instance = creature->GetInstanceScript();
}
InstanceScript* instance;
void DoAction(int32 param)
{
me->SetStandState(UNIT_STAND_STATE_STAND);
me->RemoveAllAuras();
Start(false, true);
}
void WaypointReached(uint32 waypointId)
{
if (waypointId == 7)
{
SetRun(false);
Talk(SAY_TARETHA_FREE);
me->HandleEmoteCommand(EMOTE_ONESHOT_CHEER);
if (Creature* thrall = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_THRALL_GUID)))
thrall->AI()->DoAction(me->GetEntry());
}
else if (waypointId == 9)
me->SetVisible(false);
}
void Reset()
{
me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
me->CastSpell(me, SPELL_SHADOW_PRISON, true);
}
void AttackStart(Unit*) { }
void MoveInLineOfSight(Unit*) { }
};
};
void AddSC_old_hillsbrad()
{
new npc_thrall_old_hillsbrad();
new npc_taretha();
}

View File

@@ -1,79 +0,0 @@
/*
REWRITTEN BY XINEF
*/
#ifndef DEF_OLD_HILLSBRAD_H
#define DEF_OLD_HILLSBRAD_H
enum DataIds
{
DATA_ESCORT_PROGRESS = 0,
DATA_BOMBS_PLACED = 10,
DATA_THRALL_REPOSITION = 11,
DATA_THRALL_ADD_FLAG = 12,
DATA_THRALL_GUID = 13,
DATA_TARETHA_GUID = 14,
DATA_ATTEMPTS_COUNT = 15
};
enum NpcIds
{
NPC_EROZION = 18723,
NPC_THRALL = 17876,
NPC_TARETHA = 18887,
NPC_EPOCH_HUNTER = 18096,
NPC_LIEUTENANT_DRAKE = 17848,
NPC_LODGE_QUEST_TRIGGER = 20155,
NPC_ORC_PRISONER = 18598,
NPC_DURNHOLDE_ARMORER = 18764,
NPC_DURNHOLDE_WARDEN = 17833,
NPC_DURNHOLDE_VETERAN = 17860,
NPC_DURNHOLDE_MAGE = 17860,
NPC_DURNHOLDE_SENTRY = 17860,
NPC_CAPTAIN_SKARLOC = 17862,
NPC_SKARLOC_MOUNT = 18798,
NPC_LORDAERON_SENTRY = 17815,
NPC_LORDAERON_WATCHMAN = 17814,
};
enum GobjectIds
{
GO_BARREL = 182589,
GO_ROARING_FLAME = 182592,
GO_PRISON_DOOR = 184393
};
enum MiscIds
{
QUEST_DIVERSION = 10283,
WORLD_STATE_BARRELS_PLANTED = 2436,
SKARLOC_MOUNT_MODEL = 18223,
ENCOUNTER_PROGRESS_NONE = 0,
ENCOUNTER_PROGRESS_BARRELS = 1,
ENCOUNTER_PROGRESS_DRAKE_KILLED = 2,
ENCOUNTER_PROGRESS_THRALL_ARMORED = 3,
ENCOUNTER_PROGRESS_AMBUSHES_1 = 4,
ENCOUNTER_PROGRESS_SKARLOC_KILLED = 5,
ENCOUNTER_PROGRESS_TARREN_MILL = 6,
ENCOUNTER_PROGRESS_TARETHA_MEET = 7,
ENCOUNTER_PROGRESS_EPOCH_KILLED = 8,
ENCOUNTER_PROGRESS_FINISHED = 9,
EVENT_INITIAL_BARRELS_FLAME = 1,
EVENT_FINAL_BARRELS_FLAME = 2,
EVENT_SUMMON_LIEUTENANT = 3,
EVENT_THRALL_REPOSITION = 4,
INSTANCE_POSITIONS_COUNT = 3,
THRALL_POSITIONS_COUNT = 5
};
#endif

View File

@@ -1,153 +0,0 @@
/*
REWRITTEN BY XINEF
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "the_black_morass.h"
enum Enums
{
SAY_ENTER = 0,
SAY_AGGRO = 1,
SAY_BANISH = 2,
SAY_SLAY = 3,
SAY_DEATH = 4,
EMOTE_FRENZY = 5,
SPELL_CLEAVE = 40504,
SPELL_TIME_STOP = 31422,
SPELL_ENRAGE = 37605,
SPELL_SAND_BREATH = 31473,
SPELL_CORRUPT_MEDIVH = 37853,
SPELL_BANISH_DRAGON_HELPER = 31550
};
enum Events
{
EVENT_SANDBREATH = 1,
EVENT_TIMESTOP = 2,
EVENT_FRENZY = 3,
EVENT_CLEAVE = 4
};
class boss_aeonus : public CreatureScript
{
public:
boss_aeonus() : CreatureScript("boss_aeonus") { }
struct boss_aeonusAI : public ScriptedAI
{
boss_aeonusAI(Creature* creature) : ScriptedAI(creature)
{
instance = creature->GetInstanceScript();
}
EventMap events;
InstanceScript* instance;
void Reset()
{
events.Reset();
}
void JustReachedHome()
{
if (Unit* medivh = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_MEDIVH)))
if (me->GetDistance2d(medivh) < 20.0f)
me->CastSpell(me, SPELL_CORRUPT_MEDIVH, false);
}
void InitializeAI()
{
Talk(SAY_ENTER);
ScriptedAI::InitializeAI();
if (Unit* medivh = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_MEDIVH)))
{
me->SetHomePosition(medivh->GetPositionX() + 14.0f*cos(medivh->GetAngle(me)), medivh->GetPositionY() + 14.0f*sin(medivh->GetAngle(me)), medivh->GetPositionZ(), me->GetAngle(medivh));
me->GetMotionMaster()->MoveTargetedHome();
}
}
void EnterCombat(Unit* /*who*/)
{
events.ScheduleEvent(EVENT_CLEAVE, 5000);
events.ScheduleEvent(EVENT_SANDBREATH, 20000);
events.ScheduleEvent(EVENT_TIMESTOP, 15000);
events.ScheduleEvent(EVENT_FRENZY, 30000);
Talk(SAY_AGGRO);
}
void MoveInLineOfSight(Unit* who)
{
if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_TIME_KEEPER)
{
if (me->IsWithinDistInMap(who, 20.0f))
{
Talk(SAY_BANISH);
me->CastSpell(me, SPELL_BANISH_DRAGON_HELPER, true);
return;
}
}
ScriptedAI::MoveInLineOfSight(who);
}
void JustDied(Unit* /*killer*/)
{
Talk(SAY_DEATH);
instance->SetData(TYPE_AEONUS, DONE);
}
void KilledUnit(Unit* victim)
{
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
}
void UpdateAI(uint32 diff)
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_CLEAVE:
me->CastSpell(me->GetVictim(), SPELL_CLEAVE, false);
events.ScheduleEvent(EVENT_CLEAVE, 10000);
break;
case EVENT_SANDBREATH:
me->CastSpell(me->GetVictim(), SPELL_SAND_BREATH, false);
events.ScheduleEvent(EVENT_SANDBREATH, 20000);
break;
case EVENT_TIMESTOP:
me->CastSpell(me, SPELL_TIME_STOP, false);
events.ScheduleEvent(EVENT_TIMESTOP, 25000);
break;
case EVENT_FRENZY:
Talk(EMOTE_FRENZY);
me->CastSpell(me, SPELL_ENRAGE, false);
events.ScheduleEvent(EVENT_FRENZY, 30000);
break;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const
{
return new boss_aeonusAI(creature);
}
};
void AddSC_boss_aeonus()
{
new boss_aeonus();
}

View File

@@ -1,142 +0,0 @@
/*
REWRITTEN BY XINEF
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "the_black_morass.h"
enum Enums
{
SAY_ENTER = 0,
SAY_AGGRO = 1,
SAY_BANISH = 2,
SAY_SLAY = 3,
SAY_DEATH = 4,
SPELL_ARCANE_BLAST = 31457,
SPELL_ARCANE_DISCHARGE = 31472,
SPELL_TIME_LAPSE = 31467,
SPELL_ATTRACTION = 38540,
SPELL_BANISH_DRAGON_HELPER = 31550,
};
enum Events
{
EVENT_ARCANE_BLAST = 1,
EVENT_TIME_LAPSE = 2,
EVENT_ARCANE_DISCHARGE = 3,
EVENT_ATTRACTION = 4
};
class boss_chrono_lord_deja : public CreatureScript
{
public:
boss_chrono_lord_deja() : CreatureScript("boss_chrono_lord_deja") { }
struct boss_chrono_lord_dejaAI : public ScriptedAI
{
boss_chrono_lord_dejaAI(Creature* creature) : ScriptedAI(creature) { }
EventMap events;
void Reset()
{
events.Reset();
}
void OwnTalk(uint32 id)
{
if (me->GetEntry() == NPC_CHRONO_LORD_DEJA)
Talk(id);
}
void InitializeAI()
{
OwnTalk(SAY_ENTER);
ScriptedAI::InitializeAI();
}
void EnterCombat(Unit* /*who*/)
{
events.ScheduleEvent(EVENT_ARCANE_BLAST, 10000);
events.ScheduleEvent(EVENT_TIME_LAPSE, 15000);
events.ScheduleEvent(EVENT_ARCANE_DISCHARGE, 25000);
if (IsHeroic())
events.ScheduleEvent(EVENT_ATTRACTION, 20000);
OwnTalk(SAY_AGGRO);
}
void MoveInLineOfSight(Unit* who)
{
if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_TIME_KEEPER)
{
if (me->IsWithinDistInMap(who, 20.0f))
{
OwnTalk(SAY_BANISH);
me->CastSpell(me, SPELL_BANISH_DRAGON_HELPER, true);
return;
}
}
ScriptedAI::MoveInLineOfSight(who);
}
void KilledUnit(Unit* victim)
{
if (victim->GetTypeId() == TYPEID_PLAYER)
OwnTalk(SAY_SLAY);
}
void JustDied(Unit* /*killer*/)
{
OwnTalk(SAY_DEATH);
if (InstanceScript* instance = me->GetInstanceScript())
instance->SetData(TYPE_CHRONO_LORD_DEJA, DONE);
}
void UpdateAI(uint32 diff)
{
if (!UpdateVictim())
return;
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
events.Update(diff);
switch (events.ExecuteEvent())
{
case EVENT_ARCANE_BLAST:
me->CastSpell(me->GetVictim(), SPELL_ARCANE_BLAST, false);
events.ScheduleEvent(EVENT_ARCANE_BLAST, 20000);
break;
case EVENT_TIME_LAPSE:
me->CastSpell(me, SPELL_TIME_LAPSE, false);
events.ScheduleEvent(EVENT_TIME_LAPSE, 20000);
break;
case EVENT_ARCANE_DISCHARGE:
me->CastSpell(me, SPELL_ARCANE_DISCHARGE, false);
events.ScheduleEvent(EVENT_ARCANE_DISCHARGE, 25000);
break;
case EVENT_ATTRACTION:
me->CastSpell(me, SPELL_ATTRACTION, false);
events.ScheduleEvent(EVENT_ATTRACTION, 30000);
break;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const
{
return new boss_chrono_lord_dejaAI(creature);
}
};
void AddSC_boss_chrono_lord_deja()
{
new boss_chrono_lord_deja();
}

View File

@@ -1,141 +0,0 @@
/*
REWRITTEN BY XINEF
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "the_black_morass.h"
enum Enums
{
SAY_ENTER = 0,
SAY_AGGRO = 1,
SAY_BANISH = 2,
SAY_SLAY = 3,
SAY_DEATH = 4,
SPELL_HASTEN = 31458,
SPELL_MORTAL_WOUND = 31464,
SPELL_WING_BUFFET = 31475,
SPELL_REFLECT = 38592,
SPELL_BANISH_DRAGON_HELPER = 31550
};
enum Events
{
EVENT_HASTEN = 1,
EVENT_MORTAL_WOUND = 2,
EVENT_WING_BUFFET = 3,
EVENT_SPELL_REFLECTION = 4
};
class boss_temporus : public CreatureScript
{
public:
boss_temporus() : CreatureScript("boss_temporus") { }
struct boss_temporusAI : public ScriptedAI
{
boss_temporusAI(Creature* creature) : ScriptedAI(creature) { }
EventMap events;
void OwnTalk(uint32 id)
{
if (me->GetEntry() == NPC_TEMPORUS)
Talk(id);
}
void Reset()
{
events.Reset();
}
void InitializeAI()
{
OwnTalk(SAY_ENTER);
ScriptedAI::InitializeAI();
}
void EnterCombat(Unit* /*who*/)
{
events.ScheduleEvent(EVENT_HASTEN, 12000);
events.ScheduleEvent(EVENT_MORTAL_WOUND, 5000);
events.ScheduleEvent(EVENT_WING_BUFFET, 20000);
if (IsHeroic())
events.ScheduleEvent(EVENT_SPELL_REFLECTION, 28000);
OwnTalk(SAY_AGGRO);
}
void KilledUnit(Unit* victim)
{
if (victim->GetTypeId() == TYPEID_PLAYER)
OwnTalk(SAY_SLAY);
}
void JustDied(Unit* /*killer*/)
{
OwnTalk(SAY_DEATH);
if (InstanceScript* instance = me->GetInstanceScript())
instance->SetData(TYPE_TEMPORUS, DONE);
}
void MoveInLineOfSight(Unit* who)
{
if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_TIME_KEEPER)
{
if (me->IsWithinDistInMap(who, 20.0f))
{
OwnTalk(SAY_BANISH);
me->CastSpell(me, SPELL_BANISH_DRAGON_HELPER, true);
return;
}
}
ScriptedAI::MoveInLineOfSight(who);
}
void UpdateAI(uint32 diff)
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_HASTEN:
me->CastSpell(me, SPELL_HASTEN, false);
events.ScheduleEvent(EVENT_HASTEN, 20000);
break;
case EVENT_MORTAL_WOUND:
me->CastSpell(me->GetVictim(), SPELL_MORTAL_WOUND, false);
events.ScheduleEvent(EVENT_MORTAL_WOUND, 10000);
break;
case EVENT_WING_BUFFET:
me->CastSpell(me, SPELL_WING_BUFFET, false);
events.ScheduleEvent(EVENT_WING_BUFFET, 20000);
break;
case EVENT_SPELL_REFLECTION:
me->CastSpell(me, SPELL_REFLECT, false);
events.ScheduleEvent(EVENT_SPELL_REFLECTION, 30000);
break;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const
{
return new boss_temporusAI(creature);
}
};
void AddSC_boss_temporus()
{
new boss_temporus();
}

View File

@@ -1,341 +0,0 @@
/*
REWRITTEN BY XINEF
*/
#include "ScriptMgr.h"
#include "InstanceScript.h"
#include "the_black_morass.h"
#include "Player.h"
#include "TemporarySummon.h"
#include "SpellInfo.h"
#include "ScriptedCreature.h"
const Position PortalLocation[4]=
{
{-2041.06f, 7042.08f, 29.99f, 1.30f},
{-1968.18f, 7042.11f, 21.93f, 2.12f},
{-1885.82f, 7107.36f, 22.32f, 3.07f},
{-1928.11f, 7175.95f, 22.11f, 3.44f}
};
class instance_the_black_morass : public InstanceMapScript
{
public:
instance_the_black_morass() : InstanceMapScript("instance_the_black_morass", 269) { }
InstanceScript* GetInstanceScript(InstanceMap* map) const
{
return new instance_the_black_morass_InstanceMapScript(map);
}
struct instance_the_black_morass_InstanceMapScript : public InstanceScript
{
instance_the_black_morass_InstanceMapScript(Map* map) : InstanceScript(map) { }
std::set<uint64> encounterNPCs;
uint32 encounters[MAX_ENCOUNTER];
uint64 _medivhGUID;
uint8 _currentRift;
uint8 _shieldPercent;
void Initialize()
{
memset(&encounters, 0, sizeof(encounters));
_medivhGUID = 0;
_currentRift = 0;
_shieldPercent = 100;
encounterNPCs.clear();
}
void CleanupInstance()
{
Events.Reset();
_currentRift = 0;
_shieldPercent = 100;
instance->LoadGrid(-2023.0f, 7121.0f);
if (Creature* medivh = instance->GetCreature(_medivhGUID))
{
medivh->DespawnOrUnsummon();
medivh->SetRespawnTime(3);
}
std::set<uint64> eCopy = encounterNPCs;
for (std::set<uint64>::const_iterator itr = eCopy.begin(); itr != eCopy.end(); ++itr)
if (Creature* creature = instance->GetCreature(*itr))
creature->DespawnOrUnsummon();
}
bool IsEncounterInProgress() const
{
return false;
}
void OnPlayerEnter(Player* player)
{
if (instance->GetPlayersCountExceptGMs() <= 1 && GetData(TYPE_AEONUS) != DONE)
CleanupInstance();
player->SendUpdateWorldState(WORLD_STATE_BM, _currentRift > 0 ? 1 : 0);
player->SendUpdateWorldState(WORLD_STATE_BM_SHIELD, _shieldPercent);
player->SendUpdateWorldState(WORLD_STATE_BM_RIFT, _currentRift);
}
void OnCreatureCreate(Creature* creature)
{
switch (creature->GetEntry())
{
case NPC_MEDIVH:
_medivhGUID = creature->GetGUID();
break;
case NPC_TIME_RIFT:
case NPC_CHRONO_LORD_DEJA:
case NPC_INFINITE_CHRONO_LORD:
case NPC_TEMPORUS:
case NPC_INFINITE_TIMEREAVER:
case NPC_AEONUS:
case NPC_RIFT_KEEPER_WARLOCK:
case NPC_RIFT_KEEPER_MAGE:
case NPC_RIFT_LORD:
case NPC_RIFT_LORD_2:
case NPC_INFINITE_ASSASIN:
case NPC_INFINITE_WHELP:
case NPC_INFINITE_CRONOMANCER:
case NPC_INFINITE_EXECUTIONER:
case NPC_INFINITE_VANQUISHER:
encounterNPCs.insert(creature->GetGUID());
break;
}
}
void OnCreatureRemove(Creature* creature)
{
switch (creature->GetEntry())
{
case NPC_TIME_RIFT:
case NPC_CHRONO_LORD_DEJA:
case NPC_INFINITE_CHRONO_LORD:
case NPC_TEMPORUS:
case NPC_INFINITE_TIMEREAVER:
case NPC_AEONUS:
case NPC_RIFT_KEEPER_WARLOCK:
case NPC_RIFT_KEEPER_MAGE:
case NPC_RIFT_LORD:
case NPC_RIFT_LORD_2:
case NPC_INFINITE_ASSASIN:
case NPC_INFINITE_WHELP:
case NPC_INFINITE_CRONOMANCER:
case NPC_INFINITE_EXECUTIONER:
case NPC_INFINITE_VANQUISHER:
encounterNPCs.erase(creature->GetGUID());
break;
}
}
void SetData(uint32 type, uint32 data)
{
switch (type)
{
case TYPE_AEONUS:
{
encounters[type] = DONE;
SaveToDB();
if (Creature* medivh = instance->GetCreature(_medivhGUID))
medivh->AI()->DoAction(ACTION_OUTRO);
Map::PlayerList const& players = instance->GetPlayers();
if (!players.isEmpty())
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
if (Player* player = itr->GetSource())
{
if (player->GetQuestStatus(QUEST_OPENING_PORTAL) == QUEST_STATUS_INCOMPLETE)
player->AreaExploredOrEventHappens(QUEST_OPENING_PORTAL);
if (player->GetQuestStatus(QUEST_MASTER_TOUCH) == QUEST_STATUS_INCOMPLETE)
player->AreaExploredOrEventHappens(QUEST_MASTER_TOUCH);
}
break;
}
case TYPE_CHRONO_LORD_DEJA:
case TYPE_TEMPORUS:
encounters[type] = DONE;
Events.RescheduleEvent(EVENT_NEXT_PORTAL, 60000);
Events.SetPhase(1);
SaveToDB();
break;
case DATA_RIFT_KILLED:
if (!Events.IsInPhase(1))
Events.RescheduleEvent(EVENT_NEXT_PORTAL, 4000);
break;
case DATA_MEDIVH:
DoUpdateWorldState(WORLD_STATE_BM, 1);
DoUpdateWorldState(WORLD_STATE_BM_SHIELD, _shieldPercent);
DoUpdateWorldState(WORLD_STATE_BM_RIFT, _currentRift);
Events.RescheduleEvent(EVENT_NEXT_PORTAL, 3000);
break;
case DATA_DAMAGE_SHIELD:
--_shieldPercent;
DoUpdateWorldState(WORLD_STATE_BM_SHIELD, _shieldPercent);
if (!_shieldPercent)
if (Creature* medivh = instance->GetCreature(_medivhGUID))
if (medivh->IsAlive())
{
Unit::Kill(medivh, medivh);
// Xinef: delete all spawns
std::set<uint64> eCopy = encounterNPCs;
for (std::set<uint64>::iterator itr = eCopy.begin(); itr != eCopy.end(); ++itr)
if (Creature* creature = instance->GetCreature(*itr))
creature->DespawnOrUnsummon();
}
break;
}
}
uint32 GetData(uint32 type) const
{
switch (type)
{
case TYPE_CHRONO_LORD_DEJA:
case TYPE_TEMPORUS:
case TYPE_AEONUS:
return encounters[type];
case DATA_SHIELD_PERCENT:
return _shieldPercent;
case DATA_RIFT_NUMBER:
return _currentRift;
}
return 0;
}
void SetData64(uint32 type, uint64 data)
{
if (type == DATA_SUMMONED_NPC)
encounterNPCs.insert(data);
else if (type == DATA_DELETED_NPC)
encounterNPCs.erase(data);
}
uint64 GetData64(uint32 data) const
{
if (data == DATA_MEDIVH)
return _medivhGUID;
return 0;
}
void SummonPortalKeeper()
{
Creature* rift = NULL;
for (std::set<uint64>::const_iterator itr = encounterNPCs.begin(); itr != encounterNPCs.end(); ++itr)
if (Creature* summon = instance->GetCreature(*itr))
if (summon->GetEntry() == NPC_TIME_RIFT)
{
rift = summon;
break;
}
if (!rift)
return;
int32 entry = 0;
switch (_currentRift)
{
case 6: entry = GetData(TYPE_CHRONO_LORD_DEJA) == DONE ? (instance->IsHeroic() ? NPC_INFINITE_CHRONO_LORD : -NPC_CHRONO_LORD_DEJA) : NPC_CHRONO_LORD_DEJA; break;
case 12: entry = GetData(TYPE_TEMPORUS) == DONE ? (instance->IsHeroic() ? NPC_INFINITE_TIMEREAVER : -NPC_TEMPORUS) : NPC_TEMPORUS; break;
case 18: entry = NPC_AEONUS; break;
default: entry = RAND(NPC_RIFT_KEEPER_WARLOCK, NPC_RIFT_KEEPER_MAGE, NPC_RIFT_LORD, NPC_RIFT_LORD_2); break;
}
Position pos;
rift->GetNearPosition(pos, 10.0f, 2*M_PI*rand_norm());
if (TempSummon* summon = instance->SummonCreature(abs(entry), pos))
{
summon->SetTempSummonType(TEMPSUMMON_CORPSE_TIMED_DESPAWN);
summon->SetTimer(3*MINUTE*IN_MILLISECONDS);
if (entry < 0)
summon->SetLootMode(0);
if (summon->GetEntry() != NPC_AEONUS)
{
rift->AI()->SetGUID(summon->GetGUID());
rift->CastSpell(summon, SPELL_RIFT_CHANNEL, false);
}
else
summon->SetReactState(REACT_DEFENSIVE);
}
}
void Update(uint32 diff)
{
Events.Update(diff);
switch (Events.ExecuteEvent())
{
case EVENT_NEXT_PORTAL:
++_currentRift;
DoUpdateWorldState(WORLD_STATE_BM_RIFT, _currentRift);
Events.ScheduleEvent(EVENT_SUMMON_KEEPER, 6000);
Events.SetPhase(0);
if (Creature* medivh = instance->GetCreature(_medivhGUID))
{
uint8 position = (_currentRift-1)%4;
instance->SummonCreature(NPC_TIME_RIFT, PortalLocation[position]);
}
break;
case EVENT_SUMMON_KEEPER:
SummonPortalKeeper();
break;
}
}
std::string GetSaveData()
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
saveStream << "B M " << encounters[0] << ' ' << encounters[1] << ' ' << encounters[2];
OUT_SAVE_INST_DATA_COMPLETE;
return saveStream.str();
}
void Load(const char* in)
{
if (!in)
{
OUT_LOAD_INST_DATA_FAIL;
return;
}
OUT_LOAD_INST_DATA(in);
char dataHead1, dataHead2;
std::istringstream loadStream(in);
loadStream >> dataHead1 >> dataHead2;
if (dataHead1 == 'B' && dataHead2 == 'M')
{
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
loadStream >> encounters[i];
}
else
OUT_LOAD_INST_DATA_FAIL;
OUT_LOAD_INST_DATA_COMPLETE;
}
protected:
EventMap Events;
};
};
void AddSC_instance_the_black_morass()
{
new instance_the_black_morass();
}

View File

@@ -1,402 +0,0 @@
/*
REWRITTEN BY XINEF
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
#include "the_black_morass.h"
#include "MoveSplineInit.h"
enum medivhSays
{
SAY_WEAK75 = 0,
SAY_WEAK50 = 1,
SAY_WEAK25 = 2,
SAY_ENTER = 3,
SAY_INTRO = 4,
SAY_DEATH = 5,
SAY_WIN = 6,
SAY_ORCS_ENTER = 7,
SAY_ORCS_ANSWER = 0
};
enum medivhSpells
{
SPELL_MANA_SHIELD = 31635,
SPELL_MEDIVH_CHANNEL = 31556,
SPELL_BLACK_CRYSTAL = 32563,
SPELL_PORTAL_CRYSTALS = 32564,
SPELL_BANISH_PURPLE = 32566,
SPELL_BANISH_GREEN = 32567,
SPELL_CORRUPT = 31326,
SPELL_CORRUPT_AEONUS = 37853,
};
enum medivhMisc
{
NPC_DP_EMITTER_STALKER = 18582,
NPC_DP_CRYSTAL_STALKER = 18553,
NPC_SHADOW_COUNCIL_ENFORCER = 17023,
GO_DARK_PORTAL = 185103,
EVENT_CHECK_HEALTH_25 = 1,
EVENT_CHECK_HEALTH_50 = 2,
EVENT_CHECK_HEALTH_75 = 3,
EVENT_SUMMON_CRYSTAL = 4,
EVENT_SUMMON_FLYING_CRYSTAL = 5,
EVENT_OUTRO_1 = 10,
EVENT_OUTRO_2 = 11,
EVENT_OUTRO_3 = 12,
EVENT_OUTRO_4 = 13,
EVENT_OUTRO_5 = 14,
EVENT_OUTRO_6 = 15,
EVENT_OUTRO_7 = 16,
EVENT_OUTRO_8 = 17
};
class NpcRunToHome : public BasicEvent
{
public:
NpcRunToHome(Creature& owner) : _owner(owner) { }
bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/)
{
_owner.GetMotionMaster()->MoveTargetedHome();
return true;
}
private:
Creature& _owner;
};
class npc_medivh_bm : public CreatureScript
{
public:
npc_medivh_bm() : CreatureScript("npc_medivh_bm") { }
CreatureAI* GetAI(Creature* creature) const
{
return new npc_medivh_bmAI(creature);
}
struct npc_medivh_bmAI : public ScriptedAI
{
npc_medivh_bmAI(Creature* creature) : ScriptedAI(creature)
{
instance = creature->GetInstanceScript();
groundArray.clear();
airArray.clear();
groundArray.push_back(G3D::Vector3(creature->GetPositionX() + 8.0f, creature->GetPositionY(), creature->GetPositionZ()));
airArray.push_back(G3D::Vector3(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ()));
for (uint8 i = 0; i < 10; ++i)
groundArray.push_back(G3D::Vector3(creature->GetPositionX() + 8.0f*cos(2.0f*M_PI*i/10.0f), creature->GetPositionY() + 8.0f*sin(2.0f*M_PI*i/10.0f), creature->GetPositionZ()));
for (uint8 i = 0; i < 40; ++i)
airArray.push_back(G3D::Vector3(creature->GetPositionX() + i*0.25f*cos(2.0f*M_PI*i/10.0f), creature->GetPositionY() + i*0.25f*sin(2.0f*M_PI*i/10.0f), creature->GetPositionZ() + i/4.0f));
for (uint8 i = 40; i < 80; ++i)
airArray.push_back(G3D::Vector3(creature->GetPositionX() + 10.0f*cos(2.0f*M_PI*i/10.0f), creature->GetPositionY() + 10.0f*sin(2.0f*M_PI*i/10.0f), creature->GetPositionZ() + i/4.0f));
}
InstanceScript* instance;
EventMap events;
Movement::PointsArray groundArray;
Movement::PointsArray airArray;
void Reset()
{
events.Reset();
me->CastSpell(me, SPELL_MANA_SHIELD, true);
if (instance->GetData(TYPE_AEONUS) != DONE)
me->CastSpell(me, SPELL_MEDIVH_CHANNEL, false);
}
void JustSummoned(Creature* summon)
{
instance->SetData64(DATA_SUMMONED_NPC, summon->GetGUID());
if (summon->GetEntry() == NPC_DP_CRYSTAL_STALKER)
{
summon->DespawnOrUnsummon(25000);
summon->CastSpell(summon, RAND(SPELL_BANISH_PURPLE, SPELL_BANISH_GREEN), true);
summon->GetMotionMaster()->MoveSplinePath(&airArray);
}
else if (summon->GetEntry() == NPC_DP_EMITTER_STALKER)
{
summon->CastSpell(summon, SPELL_BLACK_CRYSTAL, true);
Movement::MoveSplineInit init(summon);
init.MovebyPath(groundArray);
init.SetCyclic();
init.Launch();
}
}
void SummonedCreatureDespawn(Creature* summon)
{
instance->SetData64(DATA_DELETED_NPC, summon->GetGUID());
}
void MoveInLineOfSight(Unit* who)
{
if (!events.Empty() || instance->GetData(TYPE_AEONUS) == DONE)
return;
if (who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 20.0f))
{
Talk(SAY_ENTER);
instance->SetData(DATA_MEDIVH, 1);
me->CastSpell(me, SPELL_MEDIVH_CHANNEL, false);
events.ScheduleEvent(EVENT_CHECK_HEALTH_75, 500);
events.ScheduleEvent(EVENT_CHECK_HEALTH_50, 500);
events.ScheduleEvent(EVENT_CHECK_HEALTH_25, 500);
events.ScheduleEvent(EVENT_SUMMON_CRYSTAL, 2000);
events.ScheduleEvent(EVENT_SUMMON_CRYSTAL, 4000);
events.ScheduleEvent(EVENT_SUMMON_CRYSTAL, 6000);
events.ScheduleEvent(EVENT_SUMMON_FLYING_CRYSTAL, 8000);
}
}
void AttackStart(Unit* ) { }
void DoAction(int32 param)
{
if (param == ACTION_OUTRO)
{
events.Reset();
events.ScheduleEvent(EVENT_OUTRO_1, 4000);
me->InterruptNonMeleeSpells(true);
me->SummonGameObject(GO_DARK_PORTAL, -2086.0f, 7125.6215f, 30.5f, 6.148f, 0.0f, 0.0f, 0.0f, 0.0f, 0);
}
}
void JustDied(Unit* )
{
me->SetRespawnTime(DAY);
events.Reset();
Talk(SAY_DEATH);
}
void UpdateAI(uint32 diff)
{
events.Update(diff);
switch (uint32 eventId = events.ExecuteEvent())
{
case EVENT_CHECK_HEALTH_25:
case EVENT_CHECK_HEALTH_50:
case EVENT_CHECK_HEALTH_75:
if (instance->GetData(DATA_SHIELD_PERCENT) <= eventId*25)
{
Talk(eventId-1);
break;
}
events.ScheduleEvent(eventId, 500);
break;
case EVENT_SUMMON_CRYSTAL:
me->SummonCreature(NPC_DP_EMITTER_STALKER, me->GetPositionX() + 8.0f, me->GetPositionY(), me->GetPositionZ());
break;
case EVENT_SUMMON_FLYING_CRYSTAL:
me->CastSpell(me, SPELL_PORTAL_CRYSTALS, true);
events.ScheduleEvent(EVENT_SUMMON_FLYING_CRYSTAL, 1000);
break;
case EVENT_OUTRO_1:
me->SetFacingTo(6.21f);
Talk(SAY_WIN);
events.ScheduleEvent(EVENT_OUTRO_2, 17000);
break;
case EVENT_OUTRO_2:
me->SetFacingTo(3.07f);
events.ScheduleEvent(EVENT_OUTRO_3, 2000);
break;
case EVENT_OUTRO_3:
SummonOrcs(-2046.158f, -3.0f, 37000, 30000, true);
events.ScheduleEvent(EVENT_OUTRO_4, 2000);
break;
case EVENT_OUTRO_4:
SummonOrcs(-2055.97f, -2.0f, 33000, 28000, false);
events.ScheduleEvent(EVENT_OUTRO_5, 2000);
break;
case EVENT_OUTRO_5:
SummonOrcs(-2064.0f, -1.5f, 29000, 26000, false);
events.ScheduleEvent(EVENT_OUTRO_6, 2000);
break;
case EVENT_OUTRO_6:
SummonOrcs(-2074.35f, -0.1f, 26000, 24000, false);
events.ScheduleEvent(EVENT_OUTRO_7, 7000);
break;
case EVENT_OUTRO_7:
Talk(SAY_ORCS_ENTER);
events.ScheduleEvent(EVENT_OUTRO_8, 7000);
break;
case EVENT_OUTRO_8:
if (Creature* cr = me->FindNearestCreature(NPC_SHADOW_COUNCIL_ENFORCER, 20.0f))
{
cr->SetFacingTo(3.07f);
cr->AI()->Talk(SAY_ORCS_ANSWER);
}
break;
}
}
void SummonOrcs(float x, float y, uint32 duration, uint32 homeTime, bool first)
{
for (uint8 i = 0; i < 6; ++i)
{
if (Creature* cr = me->SummonCreature(NPC_SHADOW_COUNCIL_ENFORCER, -2091.731f, 7133.083f - 3.0f*i, 34.589f, 0.0f))
{
cr->GetMotionMaster()->MovePoint(0, (first && i == 3) ? x+2.0f : x, cr->GetPositionY()+y, cr->GetMap()->GetHeight(x, cr->GetPositionY()+y, MAX_HEIGHT, true));
cr->m_Events.AddEvent(new NpcRunToHome(*cr), cr->m_Events.CalculateTime(homeTime+urand(0, 2000)));
cr->DespawnOrUnsummon(duration+urand(0, 2000));
}
}
}
};
};
enum timeRift
{
EVENT_SUMMON_AT_RIFT = 1,
EVENT_CHECK_DEATH = 2
};
class npc_time_rift : public CreatureScript
{
public:
npc_time_rift() : CreatureScript("npc_time_rift") { }
CreatureAI* GetAI(Creature* creature) const
{
return new npc_time_riftAI(creature);
}
struct npc_time_riftAI : public NullCreatureAI
{
npc_time_riftAI(Creature* creature) : NullCreatureAI(creature)
{
instance = creature->GetInstanceScript();
riftKeeperGUID = 0;
}
EventMap events;
InstanceScript* instance;
uint64 riftKeeperGUID;
void Reset()
{
if (instance->GetData(DATA_RIFT_NUMBER) >= 18)
{
me->DespawnOrUnsummon(30000);
return;
}
events.ScheduleEvent(EVENT_SUMMON_AT_RIFT, 16000);
events.ScheduleEvent(EVENT_CHECK_DEATH, 8000);
}
void SetGUID(uint64 guid, int32)
{
riftKeeperGUID = guid;
}
void DoSummonAtRift(uint32 entry)
{
Position pos;
me->GetNearPosition(pos, 10.0f, 2*M_PI*rand_norm());
if (Creature* summon = me->SummonCreature(entry, pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000))
if (Unit* medivh = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_MEDIVH)))
{
float o = medivh->GetAngle(summon)+frand(-1.0f, 1.0f);
summon->SetHomePosition(medivh->GetPositionX() + 14.0f*cos(o), medivh->GetPositionY() + 14.0f*sin(o), medivh->GetPositionZ(), summon->GetAngle(medivh));
summon->GetMotionMaster()->MoveTargetedHome();
summon->SetReactState(REACT_DEFENSIVE);
}
}
void DoSelectSummon()
{
uint32 entry = RAND(NPC_INFINITE_ASSASIN, NPC_INFINITE_WHELP, NPC_INFINITE_CRONOMANCER, NPC_INFINITE_EXECUTIONER, NPC_INFINITE_VANQUISHER);
if (entry == NPC_INFINITE_WHELP)
{
DoSummonAtRift(entry);
DoSummonAtRift(entry);
DoSummonAtRift(entry);
}
else
DoSummonAtRift(entry);
}
void UpdateAI(uint32 diff)
{
events.Update(diff);
switch (events.ExecuteEvent())
{
case EVENT_SUMMON_AT_RIFT:
DoSelectSummon();
events.ScheduleEvent(EVENT_SUMMON_AT_RIFT, 15000);
break;
case EVENT_CHECK_DEATH:
if (!me->HasUnitState(UNIT_STATE_CASTING))
{
Creature* riftKeeper = ObjectAccessor::GetCreature(*me, riftKeeperGUID);
if (!riftKeeper || !riftKeeper->IsAlive())
{
instance->SetData(DATA_RIFT_KILLED, 1);
me->DespawnOrUnsummon(0);
break;
}
else
me->CastSpell(riftKeeper, SPELL_RIFT_CHANNEL, false);
}
events.ScheduleEvent(EVENT_CHECK_DEATH, 500);
break;
}
}
};
};
class spell_black_morass_corrupt_medivh : public SpellScriptLoader
{
public:
spell_black_morass_corrupt_medivh() : SpellScriptLoader("spell_black_morass_corrupt_medivh") { }
class spell_black_morass_corrupt_medivh_AuraScript : public AuraScript
{
PrepareAuraScript(spell_black_morass_corrupt_medivh_AuraScript);
void PeriodicTick(AuraEffect const* /*aurEff*/)
{
if (InstanceScript* instance = GetUnitOwner()->GetInstanceScript())
instance->SetData(DATA_DAMAGE_SHIELD, 1);
}
void Register()
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_black_morass_corrupt_medivh_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
InstanceScript* _instance;
};
AuraScript* GetAuraScript() const
{
return new spell_black_morass_corrupt_medivh_AuraScript();
}
};
void AddSC_the_black_morass()
{
new npc_medivh_bm();
new npc_time_rift();
new spell_black_morass_corrupt_medivh();
}

View File

@@ -1,72 +0,0 @@
/*
REWRITTEN BY XINEF
*/
#ifndef DEF_THEBLACKMORASS_H
#define DEF_THEBLACKMORASS_H
enum DataTypes
{
TYPE_CHRONO_LORD_DEJA = 0,
TYPE_TEMPORUS = 1,
TYPE_AEONUS = 2,
MAX_ENCOUNTER = 3,
DATA_MEDIVH = 10,
DATA_RIFT_KILLED = 11,
DATA_DAMAGE_SHIELD = 12,
DATA_SHIELD_PERCENT = 13,
DATA_RIFT_NUMBER = 14,
DATA_SUMMONED_NPC = 20,
DATA_DELETED_NPC = 21,
};
enum WorldStateIds
{
WORLD_STATE_BM = 2541,
WORLD_STATE_BM_SHIELD = 2540,
WORLD_STATE_BM_RIFT = 2784
};
enum QuestIds
{
QUEST_OPENING_PORTAL = 10297,
QUEST_MASTER_TOUCH = 9836
};
enum CreatureIds
{
NPC_MEDIVH = 15608,
NPC_TIME_RIFT = 17838,
NPC_TIME_KEEPER = 17918,
NPC_RIFT_KEEPER_WARLOCK = 21104,
NPC_RIFT_KEEPER_MAGE = 21148,
NPC_RIFT_LORD = 17839,
NPC_RIFT_LORD_2 = 21140,
NPC_CHRONO_LORD_DEJA = 17879,
NPC_INFINITE_CHRONO_LORD = 21697,
NPC_TEMPORUS = 17880,
NPC_INFINITE_TIMEREAVER = 21698,
NPC_AEONUS = 17881,
NPC_INFINITE_ASSASIN = 17835,
NPC_INFINITE_WHELP = 21818,
NPC_INFINITE_CRONOMANCER = 17892,
NPC_INFINITE_EXECUTIONER = 18994,
NPC_INFINITE_VANQUISHER = 18995
};
enum Misc
{
SPELL_RIFT_CHANNEL = 31387,
EVENT_NEXT_PORTAL = 1,
EVENT_SUMMON_KEEPER = 2,
ACTION_OUTRO = 1
};
#endif