Merge commit '32d9a71a4219ea353950979a2491e7879b7fa79a' into 4.3.4

Conflicts:
	README.md
	sql/base/auth_database.sql
	sql/updates/world/2014_12_27_01_world_335.sql
	src/server/game/Conditions/ConditionMgr.cpp
	src/server/game/Globals/ObjectMgr.cpp
	src/server/game/Server/WorldSession.cpp
	src/server/scripts/Commands/cs_misc.cpp
	src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp
	src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp
	src/server/scripts/Spells/spell_hunter.cpp
This commit is contained in:
Carbenium committed 2015-07-21 20:05:44 +02:00
commit 79eb80dcba
71 files changed
+1652 -1862

No files matched your search

+2 -2
View File
@@ -489,7 +489,7 @@ public:
static bool HandleDebugSendQuestPartyMsgCommand(ChatHandler* handler, char const* args)
{
uint32 msg = atol((char*)args);
uint32 msg = atoul(args);
handler->GetSession()->GetPlayer()->SendPushToPartyResponse(handler->GetSession()->GetPlayer(), msg);
return true;
}
@@ -508,7 +508,7 @@ public:
static bool HandleDebugSendQuestInvalidMsgCommand(ChatHandler* handler, char const* args)
{
QuestFailedReason msg = static_cast<QuestFailedReason>(atol((char*)args));
QuestFailedReason msg = static_cast<QuestFailedReason>(atoul(args));
handler->GetSession()->GetPlayer()->SendCanTakeQuestResponse(msg);
return true;
}
+2 -2
View File
@@ -118,7 +118,7 @@ public:
if (!id)
return false;
uint32 objectId = atol(id);
uint32 objectId = atoul(id);
if (!objectId)
return false;
@@ -240,7 +240,7 @@ public:
if (!id)
return false;
uint32 objectId = atol(id);
uint32 objectId = atoul(id);
if (objectId)
result = WorldDatabase.PQuery("SELECT guid, id, position_x, position_y, position_z, orientation, map, phaseMask, (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ FROM gameobject WHERE map = '%i' AND id = '%u' ORDER BY order_ ASC LIMIT 1",
+1 -1
View File
@@ -269,7 +269,7 @@ public:
const char* onlineState = "";
// Parse the guid to uint32...
ObjectGuid parseGUID(HIGHGUID_PLAYER, uint32(atol((char*)args)));
ObjectGuid parseGUID(HIGHGUID_PLAYER, uint32(atoul(args)));
// ... and try to extract a player out of it.
if (sObjectMgr->GetPlayerNameByGUID(parseGUID, nameTarget))
+8 -8
View File
@@ -65,7 +65,7 @@ public:
if (!id)
return false;
uint32 creatureId = atol(id);
uint32 creatureId = atoul(id);
if (!creatureId)
{
handler->PSendSysMessage(LANG_COMMAND_INVALIDCREATUREID, creatureId);
@@ -82,7 +82,7 @@ public:
}
char* countStr = strtok(NULL, " ");
uint32 count = countStr ? atol(countStr) : 10;
uint32 count = countStr ? atoul(countStr) : 10;
if (count == 0)
return false;
@@ -133,11 +133,11 @@ public:
if (!*args)
return false;
char* id = handler->extractKeyFromLink((char*)args, "Hitem");
char const* id = handler->extractKeyFromLink((char*)args, "Hitem");
if (!id)
return false;
uint32 itemId = atol(id);
uint32 itemId = atoul(id);
if (!itemId)
{
handler->PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, itemId);
@@ -154,7 +154,7 @@ public:
}
char* countStr = strtok(NULL, " ");
uint32 count = countStr ? atol(countStr) : 10;
uint32 count = countStr ? atoul(countStr) : 10;
if (count == 0)
return false;
@@ -354,7 +354,7 @@ public:
if (!id)
return false;
uint32 gameObjectId = atol(id);
uint32 gameObjectId = atoul(id);
if (!gameObjectId)
{
handler->PSendSysMessage(LANG_COMMAND_LISTOBJINVALIDID, gameObjectId);
@@ -371,7 +371,7 @@ public:
}
char* countStr = strtok(NULL, " ");
uint32 count = countStr ? atol(countStr) : 10;
uint32 count = countStr ? atoul(countStr) : 10;
if (count == 0)
return false;
@@ -476,7 +476,7 @@ public:
if (!*args)
return false;
ObjectGuid parseGUID(HIGHGUID_PLAYER, uint32(atol((char*)args)));
ObjectGuid parseGUID(HIGHGUID_PLAYER, uint32(atoul(args)));
if (sObjectMgr->GetPlayerNameByGUID(parseGUID, targetName))
{
+7 -7
View File
@@ -1149,7 +1149,7 @@ public:
char const* id = handler->extractKeyFromLink((char*)args, "Hitem");
if (!id)
return false;
itemId = uint32(atol(id));
itemId = atoul(id);
}
char const* ccount = strtok(NULL, " ");
@@ -1231,7 +1231,7 @@ public:
if (!id)
return false;
uint32 itemSetId = atol(id);
uint32 itemSetId = atoul(id);
// prevent generation all items with itemset field value '0'
if (itemSetId == 0)
@@ -1372,7 +1372,7 @@ public:
return false;
}
int32 level = uint32(atol(levelStr));
int32 level = atol(levelStr);
Player* target = handler->getSelectedPlayer();
if (!target)
@@ -1394,7 +1394,7 @@ public:
// If our target does not yet have the skill they are trying to add to them, the chosen level also becomes
// the max level of the new profession.
uint16 max = maxPureSkill ? atol(maxPureSkill) : targetHasSkill ? target->GetPureMaxSkillValue(skill) : uint16(level);
uint16 max = maxPureSkill ? atoul(maxPureSkill) : targetHasSkill ? target->GetPureMaxSkillValue(skill) : uint16(level);
if (level <= 0 || level > max || max <= 0)
return false;
@@ -1434,7 +1434,7 @@ public:
PreparedStatement* stmt = NULL;
// To make sure we get a target, we convert our guid to an omniversal...
ObjectGuid parseGUID(HIGHGUID_PLAYER, uint32(atol((char*)args)));
ObjectGuid parseGUID(HIGHGUID_PLAYER, uint32(atoul(args)));
// ... and make sure we get a target, somehow.
if (sObjectMgr->GetPlayerNameByGUID(parseGUID, targetName))
@@ -1795,7 +1795,7 @@ public:
uint32 totalmail = uint32(fields[1].GetUInt64());
// ... we have to convert it from Char to int. We can use totalmail as it is
rmailint = atol(readmail.c_str());
rmailint = atoul(readmail.c_str());
// Output XXI. LANG_INFO_CHR_MAILS if at least one mail is given
if (totalmail >= 1)
@@ -1993,7 +1993,7 @@ public:
static bool HandleMuteInfoHelper(uint32 accountId, char const* accountName, ChatHandler *handler)
{
PreparedStatement *stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_MUTE_INFO);
stmt->setUInt16(0, accountId);
stmt->setUInt32(0, accountId);
PreparedQueryResult result = LoginDatabase.Query(stmt);
if (!result)
+5 -5
View File
@@ -334,15 +334,15 @@ public:
char* fmaxcount = strtok(NULL, " "); //add maxcount, default: 0
uint32 maxcount = 0;
if (fmaxcount)
maxcount = atol(fmaxcount);
maxcount = atoul(fmaxcount);
char* fincrtime = strtok(NULL, " "); //add incrtime, default: 0
uint32 incrtime = 0;
if (fincrtime)
incrtime = atol(fincrtime);
incrtime = atoul(fincrtime);
char* fextendedcost = strtok(NULL, " "); //add ExtendedCost, default: 0
uint32 extendedcost = fextendedcost ? atol(fextendedcost) : 0;
uint32 extendedcost = fextendedcost ? atoul(fextendedcost) : 0;
Creature* vendor = handler->getSelectedCreature();
if (!vendor)
{
@@ -572,7 +572,7 @@ public:
handler->SetSentErrorMessage(true);
return false;
}
uint32 itemId = atol(pitem);
uint32 itemId = atoul(pitem);
const uint8 type = 1; // FIXME: make type (1 item, 2 currency) an argument
@@ -1356,7 +1356,7 @@ public:
return false;
}
ObjectGuid receiver_guid(HIGHGUID_PLAYER, uint32(atol(receiver_str)));
ObjectGuid receiver_guid(HIGHGUID_PLAYER, uint32(atoul(receiver_str)));
// check online security
Player* receiver = ObjectAccessor::FindPlayer(receiver_guid);
+4 -4
View File
@@ -67,7 +67,7 @@ public:
if (!cId)
return false;
uint32 entry = atol(cId);
uint32 entry = atoul(cId);
Quest const* quest = sObjectMgr->GetQuestTemplate(entry);
@@ -112,7 +112,7 @@ public:
if (!cId)
return false;
uint32 entry = atol(cId);
uint32 entry = atoul(cId);
Quest const* quest = sObjectMgr->GetQuestTemplate(entry);
@@ -165,7 +165,7 @@ public:
if (!cId)
return false;
uint32 entry = atol(cId);
uint32 entry = atoul(cId);
Quest const* quest = sObjectMgr->GetQuestTemplate(entry);
@@ -269,7 +269,7 @@ public:
if (!cId)
return false;
uint32 entry = atol(cId);
uint32 entry = atoul(cId);
Quest const* quest = sObjectMgr->GetQuestTemplate(entry);
@@ -225,7 +225,7 @@ class boss_ragnaros : public CreatureScript
events.ScheduleEvent(EVENT_ELEMENTAL_FIRE, urand(10000, 14000));
break;
case EVENT_MAGMA_BLAST:
if (me->IsWithinMeleeRange(me->GetVictim()))
if (!me->IsWithinMeleeRange(me->GetVictim()))
{
DoCastVictim(SPELL_MAGMA_BLAST);
if (!_hasYelledMagmaBurst)
@@ -25,10 +25,9 @@ EndScriptData */
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "hyjal.h"
#include "SpellAuras.h"
#include "hyjal_trash.h"
#include "SpellScript.h"
#include "Player.h"
#include "hyjal.h"
enum Texts
{
@@ -39,42 +38,59 @@ enum Texts
SAY_ENRAGE = 5,
SAY_DEATH = 6,
SAY_SOUL_CHARGE = 7,
// YELL_ARCHIMONDE_INTRO = 8
};
enum Spells
{
SPELL_DENOUEMENT_WISP = 32124,
SPELL_ANCIENT_SPARK = 39349,
SPELL_PROTECTION_OF_ELUNE = 38528,
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_DRAIN_WORLD_TREE = 39140,
SPELL_DRAIN_WORLD_TREE_TRIGGERED = 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,
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 Events
{
EVENT_HAND_OF_DEATH = 1, // Raid wiper
EVENT_UNLEASH_SOUL_CHARGE,
EVENT_FINGER_OF_DEATH,
EVENT_GRIP_OF_THE_LEGION,
EVENT_FEAR,
EVENT_AIR_BURST,
EVENT_DOOMFIRE,
EVENT_DISTANCE_CHECK, // 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
EVENT_SUMMON_WHISP
};
enum Summons
{
CREATURE_DOOMFIRE = 18095,
CREATURE_DOOMFIRE_SPIRIT = 18104,
CREATURE_ANCIENT_WISP = 17946,
CREATURE_CHANNEL_TARGET = 22418,
NPC_DOOMFIRE = 18095,
NPC_DOOMFIRE_SPIRIT = 18104,
NPC_ANCIENT_WISP = 17946
};
Position const NordrassilLoc = {5503.713f, -3523.436f, 1608.781f, 0.0f};
enum Actions
{
ACTION_ENRAGE,
ACTION_CHANNEL_WORLD_TREE
};
class npc_ancient_wisp : public CreatureScript
{
@@ -200,7 +216,6 @@ public:
}
void MoveInLineOfSight(Unit* who) override
{
//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
@@ -249,409 +264,309 @@ class boss_archimonde : public CreatureScript
public:
boss_archimonde() : CreatureScript("boss_archimonde") { }
CreatureAI* GetAI(Creature* creature) const override
struct boss_archimondeAI : public BossAI
{
return GetInstanceAI<boss_archimondeAI>(creature);
}
struct boss_archimondeAI : public hyjal_trashAI
{
boss_archimondeAI(Creature* creature) : hyjal_trashAI(creature)
boss_archimondeAI(Creature* creature) : BossAI(creature, DATA_ARCHIMONDE)
{
Initialize();
instance = creature->GetInstanceScript();
}
void Initialize()
{
DoomfireSpiritGUID.Clear();
damageTaken = 0;
WorldTreeGUID.Clear();
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;
_unleashSpell = 0;
_chargeSpell = 0;
Enraged = false;
BelowTenPercent = false;
HasProtected = false;
IsChanneling = false;
}
InstanceScript* instance;
ObjectGuid DoomfireSpiritGUID;
ObjectGuid 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 InitializeAI() override
{
BossAI::InitializeAI();
DoAction(ACTION_CHANNEL_WORLD_TREE);
}
void Reset() override
{
instance->SetData(DATA_ARCHIMONDEEVENT, NOT_STARTED);
Initialize();
_Reset();
me->RemoveAllAuras(); // Reset Soul Charge auras.
}
void EnterCombat(Unit* /*who*/) override
{
me->InterruptSpell(CURRENT_CHANNELED_SPELL);
Talk(SAY_AGGRO);
DoZoneInCombat();
_EnterCombat();
events.ScheduleEvent(EVENT_FEAR, 42000);
events.ScheduleEvent(EVENT_AIR_BURST, 30000);
events.ScheduleEvent(EVENT_GRIP_OF_THE_LEGION, urand(5000, 25000));
events.ScheduleEvent(EVENT_DOOMFIRE, 20000);
events.ScheduleEvent(EVENT_UNLEASH_SOUL_CHARGE, urand(2000, 30000));
events.ScheduleEvent(EVENT_FINGER_OF_DEATH, 15000);
events.ScheduleEvent(EVENT_HAND_OF_DEATH, 600000);
events.ScheduleEvent(EVENT_DISTANCE_CHECK, 30000);
}
instance->SetData(DATA_ARCHIMONDEEVENT, IN_PROGRESS);
void ExecuteEvent(uint32 eventId) override
{
switch (eventId)
{
case EVENT_HAND_OF_DEATH:
DoCastAOE(SPELL_HAND_OF_DEATH);
events.ScheduleEvent(EVENT_HAND_OF_DEATH, 2000);
break;
case EVENT_UNLEASH_SOUL_CHARGE:
_chargeSpell = 0;
_unleashSpell = 0;
me->InterruptNonMeleeSpells(false);
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);
SoulChargeCount--;
events.ScheduleEvent(EVENT_UNLEASH_SOUL_CHARGE, urand(2000, 30000));
}
break;
case EVENT_FINGER_OF_DEATH:
if (!SelectTarget(SELECT_TARGET_RANDOM, 0, 5.0f)) // Checks if there are no targets in melee range
{
DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), SPELL_FINGER_OF_DEATH);
events.ScheduleEvent(EVENT_FINGER_OF_DEATH, 1000);
}
else
events.ScheduleEvent(EVENT_FINGER_OF_DEATH, 5000);
break;
case EVENT_GRIP_OF_THE_LEGION:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
DoCast(target, SPELL_GRIP_OF_THE_LEGION);
events.ScheduleEvent(EVENT_GRIP_OF_THE_LEGION, urand(5000, 25000));
break;
case EVENT_AIR_BURST:
Talk(SAY_AIR_BURST);
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1))
DoCast(target, SPELL_AIR_BURST); //not on tank
events.ScheduleEvent(EVENT_AIR_BURST, urand(25000, 40000));
break;
case EVENT_FEAR:
DoCastAOE(SPELL_FEAR);
events.ScheduleEvent(EVENT_FEAR, 42000);
break;
case EVENT_DOOMFIRE:
Talk(SAY_DOOMFIRE);
if (Unit* temp = SelectTarget(SELECT_TARGET_RANDOM, 1))
SummonDoomfire(temp);
else
SummonDoomfire(me->GetVictim());
events.ScheduleEvent(EVENT_DOOMFIRE, 20000);
break;
case EVENT_DISTANCE_CHECK:
if (Creature* channelTrigger = instance->GetCreature(DATA_CHANNEL_TARGET))
if (me->IsWithinDistInMap(channelTrigger, 75.0f))
DoAction(ACTION_ENRAGE);
events.ScheduleEvent(EVENT_DISTANCE_CHECK, 5000);
break;
case EVENT_SUMMON_WHISP:
DoSpawnCreature(NPC_ANCIENT_WISP, float(rand32() % 40), float(rand32() % 40), 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
++WispCount;
if (WispCount >= 30)
me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
events.ScheduleEvent(EVENT_SUMMON_WHISP, 1500);
break;
default:
break;
}
}
void DamageTaken(Unit* /*attacker*/, uint32 &damage) override
{
if (me->HealthBelowPctDamaged(10, damage))
{
if (!Enraged)
DoAction(ACTION_ENRAGE);
if (!HasProtected)
{
me->GetMotionMaster()->Clear(false);
me->GetMotionMaster()->MoveIdle();
// All members of raid must get this buff
DoCastAOE(SPELL_PROTECTION_OF_ELUNE, true);
HasProtected = true;
events.ScheduleEvent(EVENT_SUMMON_WHISP, 1500);
}
}
}
void KilledUnit(Unit* victim) override
{
Talk(SAY_SLAY);
if (victim && victim->GetTypeId() == TYPEID_PLAYER)
GainSoulCharge(victim->ToPlayer());
}
void GainSoulCharge(Player* victim)
{
switch (victim->getClass())
if (victim->GetTypeId() == TYPEID_PLAYER)
{
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;
}
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;
events.ScheduleEvent(EVENT_UNLEASH_SOUL_CHARGE, urand(2000, 30000));
++SoulChargeCount;
}
}
void JustDied(Unit* killer) override
void JustReachedHome() override
{
DoAction(ACTION_CHANNEL_WORLD_TREE);
}
void JustDied(Unit* /*killer*/) override
{
hyjal_trashAI::JustDied(killer);
Talk(SAY_DEATH);
instance->SetData(DATA_ARCHIMONDEEVENT, DONE);
}
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->GetAttackDistance(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->GetAttackDistance(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;
_JustDied();
// @todo: remove this when instance script gets updated, kept for compatibility only
instance->SetData(DATA_ARCHIMONDE, DONE);
}
void JustSummoned(Creature* summoned) override
{
if (summoned->GetEntry() == CREATURE_ANCIENT_WISP)
summoned->AI()->AttackStart(me);
else
switch (summoned->GetEntry())
{
summoned->setFaction(me->getFaction());
summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
case NPC_ANCIENT_WISP:
summoned->AI()->AttackStart(me);
break;
case NPC_DOOMFIRE_SPIRIT:
DoomfireSpiritGUID = summoned->GetGUID();
break;
case NPC_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.Clear();
}
break;
default:
break;
}
}
if (summoned->GetEntry() == CREATURE_DOOMFIRE_SPIRIT)
void DoAction(int32 actionId) override
{
switch (actionId)
{
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.Clear();
}
case ACTION_ENRAGE:
me->GetMotionMaster()->Clear(false);
me->GetMotionMaster()->MoveIdle();
Enraged = true;
Talk(SAY_ENRAGE);
break;
case ACTION_CHANNEL_WORLD_TREE:
DoCastAOE(SPELL_DRAIN_WORLD_TREE, true);
break;
default:
break;
}
}
//this is code doing close to what the summoning spell would do (spell 31903)
void SummonDoomfire(Unit* target)
{
me->SummonCreature(CREATURE_DOOMFIRE_SPIRIT,
if (!target)
return;
me->SummonCreature(NPC_DOOMFIRE_SPIRIT,
target->GetPositionX()+15.0f, target->GetPositionY()+15.0f, target->GetPositionZ(), 0,
TEMPSUMMON_TIMED_DESPAWN, 27000);
me->SummonCreature(CREATURE_DOOMFIRE,
me->SummonCreature(NPC_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) override
{
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(rand32() % 40), float(rand32() % 40), 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
SummonWispTimer = 1500;
++WispCount;
} else SummonWispTimer -= diff;
if (WispCount >= 30)
me->DealDamage(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*/) override { }
private:
ObjectGuid DoomfireSpiritGUID;
uint8 SoulChargeCount;
uint8 WispCount;
uint32 _chargeSpell;
uint32 _unleashSpell;
bool Enraged;
bool HasProtected;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetInstanceAI<boss_archimondeAI>(creature);
}
};
// 39142 - Drain World Tree Dummy
class spell_archimonde_drain_world_tree_dummy : public SpellScriptLoader
{
public:
spell_archimonde_drain_world_tree_dummy() : SpellScriptLoader("spell_archimonde_drain_world_tree_dummy") { }
class spell_archimonde_drain_world_tree_dummy_SpellScript : public SpellScript
{
PrepareSpellScript(spell_archimonde_drain_world_tree_dummy_SpellScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
if (!sSpellMgr->GetSpellInfo(SPELL_DRAIN_WORLD_TREE_TRIGGERED))
return false;
return true;
}
void HandleScript(SpellEffIndex /*effIndex*/)
{
if (Unit* target = GetHitUnit())
target->CastSpell(GetCaster(), SPELL_DRAIN_WORLD_TREE_TRIGGERED, true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_archimonde_drain_world_tree_dummy_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_archimonde_drain_world_tree_dummy_SpellScript();
}
};
void AddSC_boss_archimonde()
@@ -660,4 +575,5 @@ void AddSC_boss_archimonde()
new npc_doomfire();
new npc_doomfire_targetting();
new npc_ancient_wisp();
new spell_archimonde_drain_world_tree_dummy();
}
@@ -44,7 +44,8 @@ enum DataTypes
DATA_HORDE_RETREAT = 17,
DATA_RAIDDAMAGE = 18,
DATA_RESET_RAIDDAMAGE = 19,
TYPE_RETREAT = 20
TYPE_RETREAT = 20,
DATA_CHANNEL_TARGET = 21
};
enum WorldStateIds
@@ -77,7 +78,8 @@ enum CreaturesIds
KAZROGAL = 17888,
AZGALOR = 17842,
ARCHIMONDE = 17968,
NPC_WORLD_TRIGGER_TINY = 21987
NPC_WORLD_TRIGGER_TINY = 21987,
NPC_CHANNEL_TARGET = 22418
};
enum GameobjectIds
@@ -89,5 +91,6 @@ enum GameobjectIds
GO_ROARING_FLAME = 182592
};
#endif
#define MINRAIDDAMAGE 700000 // minimal damage before trash can drop loot and reputation, resets if faction leader dies
#endif
@@ -26,7 +26,6 @@ enum Spells
SPELL_METEOR = 33814, //infernal visual
SPELL_IMMOLATION = 37059,
SPELL_FLAME_BUFFET = 31724,
NPC_TRIGGER = 21987, //World Trigger (Tiny)
MODEL_INVIS = 11686, //invisible model
SPELL_DISEASE_CLOUD = 31607,
SPELL_KNOCKDOWN = 31610,
@@ -465,10 +464,7 @@ public:
}
if (!meteor)
{
float x, y, z;
me->GetPosition(x, y, z);
Creature* trigger = me->SummonCreature(NPC_TRIGGER, x + 8, y + 8, z + 25 + rand32() % 10, me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN, 1000);
if (trigger)
if (Creature* trigger = me->SummonCreature(NPC_WORLD_TRIGGER_TINY, me->GetPositionWithOffset({ 8.0f, 8.0f, frand(25.0f, 35.0f), 0.0f }), TEMPSUMMON_TIMED_DESPAWN, 1000))
{
trigger->SetVisible(false);
trigger->setFaction(me->getFaction());
@@ -21,8 +21,6 @@
#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);
@@ -40,8 +40,16 @@ EndScriptData */
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"
enum Yells
{
YELL_ARCHIMONDE_INTRO = 8
};
ObjectData const creatureData[] =
{
{ NPC_CHANNEL_TARGET, DATA_CHANNEL_TARGET },
{ 0, 0 } // END
};
class instance_hyjal : public InstanceMapScript
{
@@ -58,6 +66,7 @@ public:
instance_mount_hyjal_InstanceMapScript(Map* map) : InstanceScript(map)
{
SetHeaders(DataHeader);
LoadObjectData(creatureData, nullptr);
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
RaidDamage = 0;
@@ -105,15 +114,35 @@ public:
{
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;
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();
if (GetData(DATA_AZGALOREVENT) != DONE)
creature->SetVisible(false);
break;
case JAINA:
JainaProudmoore = creature->GetGUID();
break;
case THRALL:
Thrall = creature->GetGUID();
break;
case TYRANDE:
TyrandeWhisperwind = creature->GetGUID();
break;
}
InstanceScript::OnCreatureCreate(creature);
}
ObjectGuid GetGuidData(uint32 identifier) const override
@@ -147,40 +176,19 @@ public:
m_auiEncounter[2] = data;
break;
case DATA_AZGALOREVENT:
m_auiEncounter[3] = data;
if (data == DONE)
{
m_auiEncounter[3] = data;
if (data == DONE)
instance->LoadGrid(5581.49f, -3445.63f);
if (Creature* archimonde = instance->GetCreature(Archimonde))
{
if (ArchiYell)
break;
archimonde->SetVisible(true);
ArchiYell = true;
Creature* creature = instance->GetCreature(Azgalor);
if (creature)
if (!ArchiYell)
{
Creature* unit = creature->SummonCreature(NPC_WORLD_TRIGGER_TINY, creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 10000);
ArchiYell = true;
archimonde->AI()->Talk(YELL_ARCHIMONDE_INTRO);
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 (Player* player = i->GetSource())
{
WorldPacket packet;
ChatHandler::BuildChatPacket(packet, CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, unit, player, YELL_EFFORTS);
player->SendDirectMessage(&packet);
player->PlayDirectSound(10986, player);
}
}
}
}
}
}
@@ -292,6 +292,7 @@ public:
break;
}
player->CLOSE_GOSSIP_MENU();
ai->SetDespawnAtFar(false);
creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
return true;
}
@@ -19,13 +19,15 @@
/* ScriptData
SDName: Dustwallow_Marsh
SD%Complete: 95
SDComment: Quest support: 1270, 1222, 27245
SDComment: Quest support: 558, 11126, 11142, 11174, Vendor Nat Pagle
SDCategory: Dustwallow Marsh
EndScriptData */
/* ContentData
npc_stinky
go_blackhoof_cage
npc_lady_jaina_proudmoore
npc_nat_pagle
npc_private_hendel
npc_cassa_crimsonwing - handled by npc_taxi
EndContentData */
#include "ScriptMgr.h"
@@ -36,99 +38,6 @@ EndContentData */
#include "Player.h"
#include "WorldSession.h"
/*######
## npc_risen_husk_spirit
######*/
enum HauntingWitchHill
{
// Quest
QUEST_WHATS_HAUNTING_WITCH_HILL = 11180,
// General spells
SPELL_SUMMON_RESTLESS_APPARITION = 42511,
SPELL_WITCH_HILL_INFORMATION_CREDIT = 42512,
// Risen Husk specific
SPELL_CONSUME_FLESH = 37933,
NPC_RISEN_HUSK = 23555,
// Risen Spirit specific
SPELL_INTANGIBLE_PRESENCE = 43127,
NPC_RISEN_SPIRIT = 23554,
// Events
EVENT_CONSUME_FLESH = 1,
EVENT_INTANGIBLE_PRESENCE = 2,
};
class npc_risen_husk_spirit : public CreatureScript
{
public:
npc_risen_husk_spirit() : CreatureScript("npc_risen_husk_spirit") { }
struct npc_risen_husk_spiritAI : public ScriptedAI
{
npc_risen_husk_spiritAI(Creature* creature) : ScriptedAI(creature) { }
void Reset() override
{
events.Reset();
if (me->GetEntry() == NPC_RISEN_HUSK)
events.ScheduleEvent(EVENT_CONSUME_FLESH, 5000);
else if (me->GetEntry() == NPC_RISEN_SPIRIT)
events.ScheduleEvent(EVENT_INTANGIBLE_PRESENCE, 5000);
}
void JustDied(Unit* killer) override
{
if (killer->GetTypeId() == TYPEID_PLAYER)
{
if (killer->ToPlayer()->GetQuestStatus(QUEST_WHATS_HAUNTING_WITCH_HILL) == QUEST_STATUS_INCOMPLETE)
{
DoCast(me, SPELL_SUMMON_RESTLESS_APPARITION, true);
DoCast(killer, SPELL_WITCH_HILL_INFORMATION_CREDIT, true);
}
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_CONSUME_FLESH:
DoCastVictim(SPELL_CONSUME_FLESH);
events.ScheduleEvent(EVENT_CONSUME_FLESH, 15000);
break;
case EVENT_INTANGIBLE_PRESENCE:
DoCastVictim(SPELL_INTANGIBLE_PRESENCE);
events.ScheduleEvent(EVENT_INTANGIBLE_PRESENCE, 15000);
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
private:
EventMap events;
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_risen_husk_spiritAI(creature);
}
};
/*######
## npc_lady_jaina_proudmoore
######*/
@@ -366,131 +275,6 @@ public:
};
/*######
## npc_stinky
######*/
enum Stinky
{
QUEST_STINKYS_ESCAPE_H = 1270,
QUEST_STINKYS_ESCAPE_A = 1222,
SAY_QUEST_ACCEPTED = 0,
SAY_STAY_1 = 1,
SAY_STAY_2 = 2,
SAY_STAY_3 = 3,
SAY_STAY_4 = 4,
SAY_STAY_5 = 5,
SAY_STAY_6 = 6,
SAY_QUEST_COMPLETE = 7,
SAY_ATTACKED_1 = 8,
EMOTE_DISAPPEAR = 9
};
class npc_stinky : public CreatureScript
{
public:
npc_stinky() : CreatureScript("npc_stinky") { }
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_stinkyAI(creature);
}
bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest) override
{
if (quest->GetQuestId() == QUEST_STINKYS_ESCAPE_H || quest->GetQuestId() == QUEST_STINKYS_ESCAPE_A)
{
if (npc_stinkyAI* pEscortAI = CAST_AI(npc_stinky::npc_stinkyAI, creature->AI()))
{
creature->setFaction(FACTION_ESCORT_N_NEUTRAL_ACTIVE);
creature->SetStandState(UNIT_STAND_STATE_STAND);
creature->AI()->Talk(SAY_QUEST_ACCEPTED);
pEscortAI->Start(false, false, player->GetGUID());
}
}
return true;
}
struct npc_stinkyAI : public npc_escortAI
{
npc_stinkyAI(Creature* creature) : npc_escortAI(creature) { }
void WaypointReached(uint32 waypointId) override
{
Player* player = GetPlayerForEscort();
if (!player)
return;
switch (waypointId)
{
case 7:
Talk(SAY_STAY_1, player);
break;
case 11:
Talk(SAY_STAY_2, player);
break;
case 25:
Talk(SAY_STAY_3, player);
break;
case 26:
Talk(SAY_STAY_4, player);
break;
case 27:
Talk(SAY_STAY_5, player);
break;
case 28:
Talk(SAY_STAY_6, player);
me->SetStandState(UNIT_STAND_STATE_KNEEL);
break;
case 29:
me->SetStandState(UNIT_STAND_STATE_STAND);
break;
case 37:
Talk(SAY_QUEST_COMPLETE, player);
me->SetSpeed(MOVE_RUN, 1.2f, true);
me->SetWalk(false);
if (player->GetQuestStatus(QUEST_STINKYS_ESCAPE_H))
player->GroupEventHappens(QUEST_STINKYS_ESCAPE_H, me);
if (player->GetQuestStatus(QUEST_STINKYS_ESCAPE_A))
player->GroupEventHappens(QUEST_STINKYS_ESCAPE_A, me);
break;
case 39:
Talk(EMOTE_DISAPPEAR);
break;
}
}
void EnterCombat(Unit* who) override
{
Talk(SAY_ATTACKED_1, who);
}
void Reset() override { }
void JustDied(Unit* /*killer*/) override
{
Player* player = GetPlayerForEscort();
if (player && HasEscortState(STATE_ESCORT_ESCORTING))
{
if (player->GetQuestStatus(QUEST_STINKYS_ESCAPE_H))
player->FailQuest(QUEST_STINKYS_ESCAPE_H);
if (player->GetQuestStatus(QUEST_STINKYS_ESCAPE_A))
player->FailQuest(QUEST_STINKYS_ESCAPE_A);
}
}
void UpdateAI(uint32 uiDiff) override
{
npc_escortAI::UpdateAI(uiDiff);
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
};
};
enum SpellScripts
{
@@ -631,41 +415,13 @@ class spell_energize_aoe : public SpellScriptLoader
}
};
/*######
## go_blackhoof_cage
######*/
enum PrisonersOfTheGrimTotems
{
NPC_THERAMORE_PRISONER = 23720,
SAY_FREE = 0,
};
class go_blackhoof_cage : public GameObjectScript
{
public:
go_blackhoof_cage() : GameObjectScript("go_blackhoof_cage") { }
bool OnGossipHello(Player* player, GameObject* go) override
{
go->UseDoorOrButton();
if (Creature* prisoner = go->FindNearestCreature(NPC_THERAMORE_PRISONER, 1.0f))
{
if (player)
player->KilledMonsterCredit(NPC_THERAMORE_PRISONER);
prisoner->AI()->Talk(SAY_FREE); // We also emote cry here (handled in creature_text.emote)
prisoner->DespawnOrUnsummon(6000);
}
return true;
}
};
void AddSC_dustwallow_marsh()
{
new npc_stinky();
new npc_lady_jaina_proudmoore();
new npc_nat_pagle();
new npc_private_hendel();
new npc_zelfrax();
new spell_ooze_zap();
new spell_ooze_zap_channel_end();
new spell_energize_aoe();
new go_blackhoof_cage();
}
@@ -362,7 +362,7 @@ class NecroticPlagueTargetCheck : public std::unary_function<Unit*, bool>
bool operator()(Unit* unit) const
{
if (!unit || unit == _sourceObj || !unit->isTargetableForAttack() || unit->IsTotem() || unit->HasAura(SPELL_PLAGUE_AVOIDANCE))
if (!unit || unit == _sourceObj || !unit->isTargetableForAttack() || unit->GetTypeId() != TYPEID_PLAYER || unit->HasAura(SPELL_PLAGUE_AVOIDANCE))
return false;
if ((_notAura1 && unit->HasAura(_notAura1)) || (_notAura2 && unit->HasAura(_notAura2)))
return false;
@@ -30,26 +30,23 @@ EndScriptData */
#include "naxxramas.h"
#include "Player.h"
enum Yells
enum Texts
{
//when shappiron dies. dialog between kel and lich king (in this order)
SAY_SAPP_DIALOG1 = 0, //not used
SAY_SAPP_DIALOG2_LICH = 1, //not used
SAY_SAPP_DIALOG3 = 2, //not used
SAY_SAPP_DIALOG4_LICH = 3, //not used
SAY_SAPP_DIALOG5 = 4, //not used
SAY_CAT_DIED = 5, //when cat dies, not used
//when each of the 4 wing bosses dies
SAY_TAUNT = 6,
SAY_AGGRO = 7,
SAY_SLAY = 8,
SAY_DEATH = 9,
SAY_CHAIN = 10,
SAY_FROST_BLAST = 11,
SAY_REQUEST_AID = 12, //start of phase 3
SAY_ANSWER_REQUEST = 13, //lich king answer
EMOTE_PHASE_TWO = 13,
SAY_SUMMON_MINIONS = 14, //start of phase 1
SAY_SPECIAL = 15
SAY_SPECIAL = 15,
// The Lich King
SAY_ANSWER_REQUEST = 3,
// Old World Trigger
SAY_GUARDIAN_SPAWNED = 0
};
enum Events
@@ -70,7 +67,10 @@ enum Events
EVENT_TRIGGER,
EVENT_PHASE,
EVENT_MORTAL_WOUND
EVENT_MORTAL_WOUND,
EVENT_ANSWER_REQUEST,
EVENT_SUMMON_GUARDIANS
};
enum Spells
@@ -123,6 +123,13 @@ enum Spells
SPELL_MORTAL_WOUND = 28467
};
enum Phases
{
PHASE_ONE = 1, // Players move in the circle and Kel'Thuzad spawns his minions.
PHASE_TWO = 2, // Starts on a timer.
PHASE_THREE = 3 // At 45% health.
};
enum Creatures
{
NPC_WASTE = 16427, // Soldiers of the Frozen Wastes
@@ -270,15 +277,11 @@ public:
void Initialize()
{
nGuardiansOfIcecrownCount = 0;
uiGuardiansOfIcecrownTimer = 5000; // 5 seconds for summoning each Guardian of Icecrown in phase 3
Phase = 0;
nAbomination = 0;
nWeaver = 0;
}
uint32 Phase;
uint32 uiGuardiansOfIcecrownTimer;
uint32 uiFaction;
uint8 nGuardiansOfIcecrownCount;
@@ -345,7 +348,6 @@ public:
void EnterCombat(Unit* /*who*/) override
{
me->setFaction(uiFaction);
_EnterCombat();
for (uint8 i = 0; i <= 3; ++i)
{
@@ -354,10 +356,10 @@ public:
}
DoCast(me, SPELL_KELTHUZAD_CHANNEL, false);
Talk(SAY_SUMMON_MINIONS);
Phase = 1;
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE);
me->SetFloatValue(UNIT_FIELD_COMBATREACH, 4);
me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 4);
events.SetPhase(PHASE_ONE);
events.ScheduleEvent(EVENT_TRIGGER, 5000);
events.ScheduleEvent(EVENT_WASTE, 15000);
events.ScheduleEvent(EVENT_ABOMIN, 30000);
@@ -365,6 +367,23 @@ public:
events.ScheduleEvent(EVENT_PHASE, 228000);
}
void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
if (events.IsInPhase(PHASE_TWO) && me->HealthBelowPctDamaged(45, damage))
{
Talk(SAY_REQUEST_AID);
events.SetPhase(PHASE_THREE);
events.ScheduleEvent(EVENT_ANSWER_REQUEST, 4000);
for (uint8 i = 0; i <= 3; ++i)
{
if (GameObject* portal = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_KELTHUZAD_PORTAL01 + i)))
if (portal->getLootState() == GO_READY)
portal->UseDoorOrButton();
}
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
@@ -372,7 +391,7 @@ public:
events.Update(diff);
if (Phase == 1)
if (events.IsInPhase(PHASE_ONE))
{
while (uint32 eventId = events.ExecuteEvent())
{
@@ -405,6 +424,7 @@ public:
case EVENT_PHASE:
events.Reset();
Talk(SAY_AGGRO);
Talk(EMOTE_PHASE_TWO);
spawns.DespawnAll();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE);
me->CastStop();
@@ -417,7 +437,7 @@ public:
events.ScheduleEvent(EVENT_BLAST, urand(60000, 120000));
if (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)
events.ScheduleEvent(EVENT_CHAIN, urand(30000, 60000));
Phase = 2;
events.SetPhase(PHASE_TWO);
break;
default:
break;
@@ -426,38 +446,6 @@ public:
}
else
{
//start phase 3 when we are 45% health
if (Phase != 3)
{
if (HealthBelowPct(45))
{
Phase = 3;
Talk(SAY_REQUEST_AID);
//here Lich King should respond to KelThuzad but I don't know which Creature to make talk
//so for now just make Kelthuzad says it.
Talk(SAY_ANSWER_REQUEST);
for (uint8 i = 0; i <= 3; ++i)
{
if (GameObject* portal = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_KELTHUZAD_PORTAL01 + i)))
if (portal->getLootState() == GO_READY)
portal->UseDoorOrButton();
}
}
}
else if (nGuardiansOfIcecrownCount < RAID_MODE(2, 4))
{
if (uiGuardiansOfIcecrownTimer <= diff)
{
/// @todo Add missing text
if (Creature* guardian = DoSummon(NPC_ICECROWN, Pos[RAND(2, 5, 8, 11)]))
guardian->SetFloatValue(UNIT_FIELD_COMBATREACH, 2);
++nGuardiansOfIcecrownCount;
uiGuardiansOfIcecrownTimer = 5000;
}
else uiGuardiansOfIcecrownTimer -= diff;
}
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
@@ -609,6 +597,18 @@ public:
Talk(SAY_FROST_BLAST);
events.Repeat(30000, 90000);
break;
case EVENT_ANSWER_REQUEST:
if (Creature* lichKing = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_LICH_KING)))
lichKing->AI()->Talk(SAY_ANSWER_REQUEST);
events.ScheduleEvent(EVENT_SUMMON_GUARDIANS, 5000);
break;
case EVENT_SUMMON_GUARDIANS:
if (Creature* guardian = DoSummon(NPC_ICECROWN, Pos[RAND(2, 5, 8, 11)]))
guardian->SetFloatValue(UNIT_FIELD_COMBATREACH, 2);
++nGuardiansOfIcecrownCount;
if (nGuardiansOfIcecrownCount < RAID_MODE(2, 4))
events.ScheduleEvent(EVENT_SUMMON_GUARDIANS, 5000);
break;
default:
break;
}
@@ -69,6 +69,15 @@ MinionData const minionData[] =
{ 0, 0, }
};
ObjectData const objectData[] =
{
{ GO_NAXX_PORTAL_ARACHNID, DATA_NAXX_PORTAL_ARACHNID },
{ GO_NAXX_PORTAL_CONSTRUCT, DATA_NAXX_PORTAL_CONSTRUCT },
{ GO_NAXX_PORTAL_PLAGUE, DATA_NAXX_PORTAL_PLAGUE },
{ GO_NAXX_PORTAL_MILITARY, DATA_NAXX_PORTAL_MILITARY },
{ 0, 0, }
};
float const HeiganPos[2] = { 2796.0f, -3707.0f };
float const HeiganEruptionSlope[3] =
{
@@ -111,10 +120,12 @@ class instance_naxxramas : public InstanceMapScript
SetBossNumber(EncounterCount);
LoadDoorData(doorData);
LoadMinionData(minionData);
LoadObjectData(nullptr, objectData);
minHorsemenDiedTime = 0;
maxHorsemenDiedTime = 0;
AbominationCount = 0;
CurrentWingTaunt = SAY_KELTHUZAD_FIRST_WING_TAUNT;
playerDied = 0;
}
@@ -156,6 +167,9 @@ class instance_naxxramas : public InstanceMapScript
case NPC_KEL_THUZAD:
KelthuzadGUID = creature->GetGUID();
break;
case NPC_LICH_KING:
LichKingGUID = creature->GetGUID();
break;
default:
break;
}
@@ -201,11 +215,30 @@ class instance_naxxramas : public InstanceMapScript
case GO_KELTHUZAD_TRIGGER:
KelthuzadTriggerGUID = go->GetGUID();
break;
case GO_ROOM_KELTHUZAD:
KelthuzadDoorGUID = go->GetGUID();
break;
case GO_NAXX_PORTAL_ARACHNID:
if (GetBossState(BOSS_MAEXXNA) == DONE)
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
break;
case GO_NAXX_PORTAL_CONSTRUCT:
if (GetBossState(BOSS_THADDIUS) == DONE)
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
break;
case GO_NAXX_PORTAL_PLAGUE:
if (GetBossState(BOSS_LOATHEB) == DONE)
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
break;
case GO_NAXX_PORTAL_MILITARY:
if (GetBossState(BOSS_HORSEMEN) == DONE)
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
break;
default:
break;
}
AddDoor(go, true);
InstanceScript::OnGameObjectCreate(go);
}
void OnGameObjectRemove(GameObject* go) override
@@ -232,7 +265,7 @@ class instance_naxxramas : public InstanceMapScript
break;
}
AddDoor(go, false);
InstanceScript::OnGameObjectRemove(go);
}
void OnUnitDeath(Unit* unit) override
@@ -242,6 +275,15 @@ class instance_naxxramas : public InstanceMapScript
playerDied = 1;
SaveToDB();
}
if (Creature* creature = unit->ToCreature())
if (creature->GetEntry() == NPC_BIGGLESWORTH)
{
// Loads Kel'Thuzad's grid. We need this as he must be active in order for his texts to work.
instance->LoadGrid(3749.67f, -5114.06f);
if (Creature* kelthuzad = instance->GetCreature(KelthuzadGUID))
kelthuzad->AI()->Talk(SAY_KELTHUZAD_CAT_DIED);
}
}
void SetData(uint32 id, uint32 value) override
@@ -327,6 +369,8 @@ class instance_naxxramas : public InstanceMapScript
return PortalsGUID[3];
case DATA_KELTHUZAD_TRIGGER:
return KelthuzadTriggerGUID;
case DATA_LICH_KING:
return LichKingGUID;
}
return ObjectGuid::Empty;
@@ -337,18 +381,156 @@ class instance_naxxramas : public InstanceMapScript
if (!InstanceScript::SetBossState(id, state))
return false;
if (id == BOSS_HORSEMEN && state == DONE)
switch (id)
{
if (GameObject* horsemenChest = instance->GetGameObject(HorsemenChestGUID))
{
horsemenChest->SetRespawnTime(horsemenChest->GetRespawnDelay());
horsemenChest->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
}
case BOSS_MAEXXNA:
if (state == DONE)
{
if (GameObject* teleporter = GetGameObject(DATA_NAXX_PORTAL_ARACHNID))
teleporter->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000);
}
break;
case BOSS_LOATHEB:
if (state == DONE)
{
if (GameObject* teleporter = GetGameObject(DATA_NAXX_PORTAL_PLAGUE))
teleporter->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000);
}
break;
case BOSS_THADDIUS:
if (state == DONE)
{
if (GameObject* teleporter = GetGameObject(DATA_NAXX_PORTAL_CONSTRUCT))
teleporter->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000);
}
break;
case BOSS_GOTHIK:
if (state == DONE)
events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_KORTHAZZ, 10000);
break;
case BOSS_HORSEMEN:
if (state == DONE)
{
if (GameObject* horsemenChest = instance->GetGameObject(HorsemenChestGUID))
{
horsemenChest->SetRespawnTime(horsemenChest->GetRespawnDelay());
horsemenChest->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
}
if (GameObject* teleporter = GetGameObject(DATA_NAXX_PORTAL_MILITARY))
teleporter->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000);
}
break;
case BOSS_SAPPHIRON:
if (state == DONE)
events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD, 6000);
break;
default:
break;
}
return true;
}
void Update(uint32 diff) override
{
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_DIALOGUE_GOTHIK_KORTHAZZ:
if (Creature* korthazz = instance->GetCreature(ThaneGUID))
korthazz->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN);
events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_ZELIEK, 5000);
break;
case EVENT_DIALOGUE_GOTHIK_ZELIEK:
if (Creature* zeliek = instance->GetCreature(SirGUID))
zeliek->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN);
events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_BLAUMEUX, 6000);
break;
case EVENT_DIALOGUE_GOTHIK_BLAUMEUX:
if (Creature* blaumeux = instance->GetCreature(LadyGUID))
blaumeux->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN);
events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_RIVENDARE, 6000);
break;
case EVENT_DIALOGUE_GOTHIK_RIVENDARE:
if (Creature* rivendare = instance->GetCreature(BaronGUID))
rivendare->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN);
events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_BLAUMEUX2, 6000);
break;
case EVENT_DIALOGUE_GOTHIK_BLAUMEUX2:
if (Creature* blaumeux = instance->GetCreature(LadyGUID))
blaumeux->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN2);
events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_ZELIEK2, 6000);
break;
case EVENT_DIALOGUE_GOTHIK_ZELIEK2:
if (Creature* zeliek = instance->GetCreature(SirGUID))
zeliek->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN2);
events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_KORTHAZZ2, 6000);
break;
case EVENT_DIALOGUE_GOTHIK_KORTHAZZ2:
if (Creature* korthazz = instance->GetCreature(ThaneGUID))
korthazz->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN2);
events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_RIVENDARE2, 6000);
break;
case EVENT_DIALOGUE_GOTHIK_RIVENDARE2:
if (Creature* rivendare = instance->GetCreature(BaronGUID))
rivendare->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN2);
break;
case EVENT_KELTHUZAD_WING_TAUNT:
// Loads Kel'Thuzad's grid. We need this as he must be active in order for his texts to work.
instance->LoadGrid(3749.67f, -5114.06f);
if (Creature* kelthuzad = instance->GetCreature(KelthuzadGUID))
kelthuzad->AI()->Talk(CurrentWingTaunt);
++CurrentWingTaunt;
break;
case EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD:
if (Creature* kelthuzad = instance->GetCreature(KelthuzadGUID))
kelthuzad->AI()->Talk(SAY_DIALOGUE_SAPPHIRON_KELTHUZAD);
HandleGameObject(KelthuzadDoorGUID, false);
events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_LICHKING, 6000);
break;
case EVENT_DIALOGUE_SAPPHIRON_LICHKING:
if (Creature* lichKing = instance->GetCreature(LichKingGUID))
lichKing->AI()->Talk(SAY_DIALOGUE_SAPPHIRON_LICH_KING);
events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD2, 16000);
break;
case EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD2:
if (Creature* kelthuzad = instance->GetCreature(KelthuzadGUID))
kelthuzad->AI()->Talk(SAY_DIALOGUE_SAPPHIRON_KELTHUZAD2);
events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_LICHKING2, 9000);
break;
case EVENT_DIALOGUE_SAPPHIRON_LICHKING2:
if (Creature* lichKing = instance->GetCreature(LichKingGUID))
lichKing->AI()->Talk(SAY_DIALOGUE_SAPPHIRON_LICH_KING2);
events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD3, 12000);
break;
case EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD3:
if (Creature* kelthuzad = instance->GetCreature(KelthuzadGUID))
kelthuzad->AI()->Talk(SAY_DIALOGUE_SAPPHIRON_KELTHUZAD3);
events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD4, 6000);
break;
case EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD4:
if (Creature* kelthuzad = instance->GetCreature(KelthuzadGUID))
kelthuzad->AI()->Talk(SAY_DIALOGUE_SAPPHIRON_KELTHUZAD4);
HandleGameObject(KelthuzadDoorGUID, true);
break;
default:
break;
}
}
}
void HeiganErupt(uint32 section)
{
for (uint32 i = 0; i < 4; ++i)
@@ -450,10 +632,15 @@ class instance_naxxramas : public InstanceMapScript
ObjectGuid KelthuzadGUID;
ObjectGuid KelthuzadTriggerGUID;
ObjectGuid PortalsGUID[4];
ObjectGuid KelthuzadDoorGUID;
ObjectGuid LichKingGUID;
uint8 AbominationCount;
uint8 CurrentWingTaunt;
/* The Immortal / The Undying */
uint32 playerDied;
EventMap events;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
@@ -52,6 +52,11 @@ enum Data
DATA_HORSEMEN2,
DATA_HORSEMEN3,
DATA_ABOMINATION_KILLED,
DATA_NAXX_PORTAL_ARACHNID,
DATA_NAXX_PORTAL_CONSTRUCT,
DATA_NAXX_PORTAL_PLAGUE,
DATA_NAXX_PORTAL_MILITARY
};
enum Data64
@@ -71,6 +76,7 @@ enum Data64
DATA_KELTHUZAD_PORTAL03,
DATA_KELTHUZAD_PORTAL04,
DATA_KELTHUZAD_TRIGGER,
DATA_LICH_KING
};
enum CreaturesIds
@@ -89,7 +95,10 @@ enum CreaturesIds
NPC_CRYPT_GUARD = 16573,
NPC_NAXXRAMAS_FOLLOWER = 16505,
NPC_FOLLOWER_WORSHIPPER = 16506,
NPC_DK_UNDERSTUDY = 16803
NPC_DK_UNDERSTUDY = 16803,
NPC_BIGGLESWORTH = 16998,
NPC_LICH_KING = 16980,
NPC_OLD_WORLD_TRIGGER = 15384
};
enum GameObjectsIds
@@ -133,7 +142,13 @@ enum GameObjectsIds
GO_CONS_EYE_RAMP_BOSS = 181232,
GO_CONS_NOX_TESLA_FEUGEN = 181477,
GO_CONS_NOX_TESLA_STALAGG = 181478,
GO_BIRTH = 181356
GO_BIRTH = 181356,
// Teleporting pads spawned by the end of every quarter.
GO_NAXX_PORTAL_ARACHNID = 181575,
GO_NAXX_PORTAL_CONSTRUCT = 181576,
GO_NAXX_PORTAL_PLAGUE = 181577,
GO_NAXX_PORTAL_MILITARY = 181578
};
enum SpellIds
@@ -142,6 +157,50 @@ enum SpellIds
SPELL_SLIME = 28801
};
enum InstanceEvents
{
// Dialogue that happens after Gothik's death.
EVENT_DIALOGUE_GOTHIK_KORTHAZZ = 1,
EVENT_DIALOGUE_GOTHIK_ZELIEK,
EVENT_DIALOGUE_GOTHIK_BLAUMEUX,
EVENT_DIALOGUE_GOTHIK_RIVENDARE,
EVENT_DIALOGUE_GOTHIK_BLAUMEUX2,
EVENT_DIALOGUE_GOTHIK_ZELIEK2,
EVENT_DIALOGUE_GOTHIK_KORTHAZZ2,
EVENT_DIALOGUE_GOTHIK_RIVENDARE2,
// Dialogue that happens after each wing.
EVENT_KELTHUZAD_WING_TAUNT,
// Dialogue that happens after Sapphiron's death.
EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD,
EVENT_DIALOGUE_SAPPHIRON_LICHKING,
EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD2,
EVENT_DIALOGUE_SAPPHIRON_LICHKING2,
EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD3,
EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD4
};
enum InstanceTexts
{
// The Four Horsemen
SAY_DIALOGUE_GOTHIK_HORSEMAN = 5,
SAY_DIALOGUE_GOTHIK_HORSEMAN2 = 6,
// Kel'Thuzad
SAY_DIALOGUE_SAPPHIRON_KELTHUZAD = 0,
SAY_DIALOGUE_SAPPHIRON_KELTHUZAD2 = 2,
SAY_DIALOGUE_SAPPHIRON_KELTHUZAD3 = 4,
SAY_DIALOGUE_SAPPHIRON_KELTHUZAD4 = 20,
SAY_KELTHUZAD_CAT_DIED = 5,
SAY_KELTHUZAD_FIRST_WING_TAUNT = 16,
// Lich King
SAY_DIALOGUE_SAPPHIRON_LICH_KING = 1,
SAY_DIALOGUE_SAPPHIRON_LICH_KING2 = 2
};
/*
template<class AI>
CreatureAI* GetNaxxramasAI(Creature* creature)
@@ -100,21 +100,21 @@ class boss_anomalus : public CreatureScript
{
Initialize();
instance->SetData(DATA_ANOMALUS_EVENT, NOT_STARTED);
instance->SetBossState(DATA_ANOMALUS, NOT_STARTED);
}
void EnterCombat(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
instance->SetData(DATA_ANOMALUS_EVENT, IN_PROGRESS);
instance->SetBossState(DATA_ANOMALUS, IN_PROGRESS);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
instance->SetData(DATA_ANOMALUS_EVENT, DONE);
instance->SetBossState(DATA_ANOMALUS, DONE);
}
uint32 GetData(uint32 type) const override
@@ -101,7 +101,7 @@ public:
RemovePrison(CheckContainmentSpheres());
instance->SetData(DATA_KERISTRASZA_EVENT, NOT_STARTED);
instance->SetBossState(DATA_KERISTRASZA, NOT_STARTED);
}
void EnterCombat(Unit* /*who*/) override
@@ -109,14 +109,14 @@ public:
Talk(SAY_AGGRO);
DoCastAOE(SPELL_INTENSE_COLD);
instance->SetData(DATA_KERISTRASZA_EVENT, IN_PROGRESS);
instance->SetBossState(DATA_KERISTRASZA, IN_PROGRESS);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
instance->SetData(DATA_KERISTRASZA_EVENT, DONE);
instance->SetBossState(DATA_KERISTRASZA, DONE);
}
void KilledUnit(Unit* who) override
@@ -31,7 +31,9 @@ enum Spells
SPELL_FIRE_MAGUS_VISUAL = 47705,
SPELL_FROST_MAGUS_VISUAL = 47706,
SPELL_ARCANE_MAGUS_VISUAL = 47704
SPELL_ARCANE_MAGUS_VISUAL = 47704,
SPELL_WEAR_CHRISTMAS_HAT = 61400
};
enum Creatures
@@ -53,7 +55,9 @@ enum Yells
enum Misc
{
ACTION_MAGUS_DEAD = 1,
DATA_SPLIT_PERSONALITY = 2
DATA_SPLIT_PERSONALITY = 2,
GAME_EVENT_WINTER_VEIL = 2,
};
const Position CenterOfRoom = {504.80f, 89.07f, -16.12f, 6.27f};
@@ -128,21 +132,24 @@ public:
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
me->SetVisible(true);
instance->SetData(DATA_MAGUS_TELESTRA_EVENT, NOT_STARTED);
instance->SetBossState(DATA_MAGUS_TELESTRA, NOT_STARTED);
if (IsHeroic() && sGameEventMgr->IsActiveEvent(GAME_EVENT_WINTER_VEIL) && !me->HasAura(SPELL_WEAR_CHRISTMAS_HAT))
me->AddAura(SPELL_WEAR_CHRISTMAS_HAT, me);
}
void EnterCombat(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
instance->SetData(DATA_MAGUS_TELESTRA_EVENT, IN_PROGRESS);
instance->SetBossState(DATA_MAGUS_TELESTRA, IN_PROGRESS);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
instance->SetData(DATA_MAGUS_TELESTRA_EVENT, DONE);
instance->SetBossState(DATA_MAGUS_TELESTRA, DONE);
}
void KilledUnit(Unit* who) override
@@ -68,7 +68,7 @@ public:
struct boss_ormorokAI : public BossAI
{
boss_ormorokAI(Creature* creature) : BossAI(creature, DATA_ORMOROK_EVENT)
boss_ormorokAI(Creature* creature) : BossAI(creature, DATA_ORMOROK)
{
Initialize();
}
@@ -95,8 +95,6 @@ public:
events.ScheduleEvent(EVENT_CRYSTALLINE_TANGLER, 17000);
Talk(SAY_AGGRO);
instance->SetData(DATA_ORMOROK_EVENT, IN_PROGRESS);
}
void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) override
@@ -112,10 +110,7 @@ public:
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(SAY_DEATH);
instance->SetData(DATA_ORMOROK_EVENT, DONE);
}
void KilledUnit(Unit* who) override
@@ -138,27 +133,27 @@ public:
{
switch (eventId)
{
case EVENT_TRAMPLE:
DoCast(me, SPELL_TRAMPLE);
events.ScheduleEvent(EVENT_TRAMPLE, 10000);
break;
case EVENT_SPELL_REFLECTION:
Talk(SAY_REFLECT);
DoCast(me, SPELL_SPELL_REFLECTION);
events.ScheduleEvent(EVENT_SPELL_REFLECTION, 30000);
break;
case EVENT_CRYSTAL_SPIKES:
Talk(SAY_CRYSTAL_SPIKES);
DoCast(SPELL_CRYSTAL_SPIKES);
events.ScheduleEvent(EVENT_CRYSTAL_SPIKES, 12000);
break;
case EVENT_CRYSTALLINE_TANGLER:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, OrmorokTanglerPredicate(me)))
DoCast(target, SPELL_SUMMON_CRYSTALLINE_TANGLER);
events.ScheduleEvent(EVENT_CRYSTALLINE_TANGLER, 17000);
break;
default:
break;
case EVENT_TRAMPLE:
DoCast(me, SPELL_TRAMPLE);
events.ScheduleEvent(EVENT_TRAMPLE, 10000);
break;
case EVENT_SPELL_REFLECTION:
Talk(SAY_REFLECT);
DoCast(me, SPELL_SPELL_REFLECTION);
events.ScheduleEvent(EVENT_SPELL_REFLECTION, 30000);
break;
case EVENT_CRYSTAL_SPIKES:
Talk(SAY_CRYSTAL_SPIKES);
DoCast(SPELL_CRYSTAL_SPIKES);
events.ScheduleEvent(EVENT_CRYSTAL_SPIKES, 12000);
break;
case EVENT_CRYSTALLINE_TANGLER:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, OrmorokTanglerPredicate(me)))
DoCast(target, SPELL_SUMMON_CRYSTALLINE_TANGLER);
events.ScheduleEvent(EVENT_CRYSTALLINE_TANGLER, 17000);
break;
default:
break;
}
}
@@ -18,10 +18,8 @@
#include "ScriptMgr.h"
#include "InstanceScript.h"
#include "nexus.h"
#include "Player.h"
#define NUMBER_OF_ENCOUNTERS 4
#include "nexus.h"
enum Factions
{
@@ -30,229 +28,163 @@ enum Factions
class instance_nexus : public InstanceMapScript
{
public:
instance_nexus() : InstanceMapScript("instance_nexus", 576) { }
public:
instance_nexus() : InstanceMapScript(NexusScriptName, 576) { }
InstanceScript* GetInstanceScript(InstanceMap* map) const override
{
return new instance_nexus_InstanceMapScript(map);
}
struct instance_nexus_InstanceMapScript : public InstanceScript
{
instance_nexus_InstanceMapScript(Map* map) : InstanceScript(map)
struct instance_nexus_InstanceMapScript : public InstanceScript
{
SetHeaders(DataHeader);
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
}
uint32 m_auiEncounter[NUMBER_OF_ENCOUNTERS];
ObjectGuid Anomalus;
ObjectGuid Keristrasza;
ObjectGuid AnomalusContainmentSphere;
ObjectGuid OrmoroksContainmentSphere;
ObjectGuid TelestrasContainmentSphere;
std::string strInstData;
void OnCreatureCreate(Creature* creature) override
{
Map::PlayerList const &players = instance->GetPlayers();
uint32 TeamInInstance = 0;
if (!players.isEmpty())
instance_nexus_InstanceMapScript(Map* map) : InstanceScript(map)
{
if (Player* player = players.begin()->GetSource())
TeamInInstance = player->GetTeam();
}
switch (creature->GetEntry())
{
case 26763:
Anomalus = creature->GetGUID();
break;
case 26723:
Keristrasza = creature->GetGUID();
break;
// Alliance npcs are spawned by default, if you are alliance, you will fight against horde npcs.
case 26800:
{
if (ServerAllowsTwoSideGroups())
creature->setFaction(FACTION_HOSTILE_FOR_ALL);
if (TeamInInstance == ALLIANCE)
creature->UpdateEntry(26799);
break;
}
case 26802:
{
if (ServerAllowsTwoSideGroups())
creature->setFaction(FACTION_HOSTILE_FOR_ALL);
if (TeamInInstance == ALLIANCE)
creature->UpdateEntry(26801);
break;
}
case 26805:
{
if (ServerAllowsTwoSideGroups())
creature->setFaction(FACTION_HOSTILE_FOR_ALL);
if (TeamInInstance == ALLIANCE)
creature->UpdateEntry(26803);
break;
}
case 27949:
{
if (ServerAllowsTwoSideGroups())
creature->setFaction(FACTION_HOSTILE_FOR_ALL);
if (TeamInInstance == ALLIANCE)
creature->UpdateEntry(27947);
break;
}
case 26796:
{
if (ServerAllowsTwoSideGroups())
creature->setFaction(FACTION_HOSTILE_FOR_ALL);
if (TeamInInstance == ALLIANCE)
creature->UpdateEntry(26798);
break;
}
}
}
void OnGameObjectCreate(GameObject* go) override
{
switch (go->GetEntry())
{
case 188527:
{
AnomalusContainmentSphere = go->GetGUID();
if (m_auiEncounter[1] == DONE)
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
break;
}
case 188528:
{
OrmoroksContainmentSphere = go->GetGUID();
if (m_auiEncounter[2] == DONE)
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
break;
}
case 188526:
{
TelestrasContainmentSphere = go->GetGUID();
if (m_auiEncounter[0] == DONE)
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
break;
}
}
}
uint32 GetData(uint32 identifier) const override
{
switch (identifier)
{
case DATA_MAGUS_TELESTRA_EVENT: return m_auiEncounter[0];
case DATA_ANOMALUS_EVENT: return m_auiEncounter[1];
case DATA_ORMOROK_EVENT: return m_auiEncounter[2];
case DATA_KERISTRASZA_EVENT: return m_auiEncounter[3];
}
return 0;
}
void SetData(uint32 identifier, uint32 data) override
{
switch (identifier)
{
case DATA_MAGUS_TELESTRA_EVENT:
{
if (data == DONE)
{
GameObject* Sphere = instance->GetGameObject(TelestrasContainmentSphere);
if (Sphere)
Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
}
m_auiEncounter[0] = data;
break;
}
case DATA_ANOMALUS_EVENT:
{
if (data == DONE)
{
if (GameObject* Sphere = instance->GetGameObject(AnomalusContainmentSphere))
Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
}
m_auiEncounter[1] = data;
break;
}
case DATA_ORMOROK_EVENT:
{
if (data == DONE)
{
if (GameObject* Sphere = instance->GetGameObject(OrmoroksContainmentSphere))
Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
}
m_auiEncounter[2] = data;
break;
}
case DATA_KERISTRASZA_EVENT:
m_auiEncounter[3] = data;
break;
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
_teamInInstance = 0;
}
if (data == DONE)
void OnPlayerEnter(Player* player) override
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
saveStream << m_auiEncounter[0] << ' ' << m_auiEncounter[1] << ' ' << m_auiEncounter[2] << ' '
<< m_auiEncounter[3];
strInstData = saveStream.str();
SaveToDB();
OUT_SAVE_INST_DATA_COMPLETE;
}
}
ObjectGuid GetGuidData(uint32 uiIdentifier) const override
{
switch (uiIdentifier)
{
case DATA_ANOMALUS: return Anomalus;
case DATA_KERISTRASZA: return Keristrasza;
case ANOMALUS_CONTAINMET_SPHERE: return AnomalusContainmentSphere;
case ORMOROKS_CONTAINMET_SPHERE: return OrmoroksContainmentSphere;
case TELESTRAS_CONTAINMET_SPHERE: return TelestrasContainmentSphere;
}
return ObjectGuid::Empty;
}
std::string GetSaveData() override
{
return strInstData;
}
void Load(const char *chrIn)
{
if (!chrIn)
{
OUT_LOAD_INST_DATA_FAIL;
return;
if (!_teamInInstance)
_teamInInstance = player->GetTeam();
}
OUT_LOAD_INST_DATA(chrIn);
void OnCreatureCreate(Creature* creature) override
{
switch (creature->GetEntry())
{
case NPC_ANOMALUS:
AnomalusGUID = creature->GetGUID();
break;
case NPC_KERISTRASZA:
KeristraszaGUID = creature->GetGUID();
break;
// Alliance npcs are spawned by default, if you are alliance, you will fight against horde npcs.
case NPC_ALLIANCE_BERSERKER:
if (ServerAllowsTwoSideGroups())
creature->setFaction(FACTION_HOSTILE_FOR_ALL);
if (_teamInInstance == ALLIANCE)
creature->UpdateEntry(NPC_HORDE_BERSERKER);
break;
case NPC_ALLIANCE_RANGER:
if (ServerAllowsTwoSideGroups())
creature->setFaction(FACTION_HOSTILE_FOR_ALL);
if (_teamInInstance == ALLIANCE)
creature->UpdateEntry(NPC_HORDE_RANGER);
break;
case NPC_ALLIANCE_CLERIC:
if (ServerAllowsTwoSideGroups())
creature->setFaction(FACTION_HOSTILE_FOR_ALL);
if (_teamInInstance == ALLIANCE)
creature->UpdateEntry(NPC_HORDE_CLERIC);
break;
case NPC_ALLIANCE_COMMANDER:
if (ServerAllowsTwoSideGroups())
creature->setFaction(FACTION_HOSTILE_FOR_ALL);
if (_teamInInstance == ALLIANCE)
creature->UpdateEntry(NPC_HORDE_COMMANDER);
break;
case NPC_COMMANDER_STOUTBEARD:
if (ServerAllowsTwoSideGroups())
creature->setFaction(FACTION_HOSTILE_FOR_ALL);
if (_teamInInstance == ALLIANCE)
creature->UpdateEntry(NPC_COMMANDER_KOLURG);
break;
default:
break;
}
}
std::istringstream loadStream(chrIn);
loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3];
void OnGameObjectCreate(GameObject* go) override
{
switch (go->GetEntry())
{
case GO_ANOMALUS_CONTAINMET_SPHERE:
AnomalusContainmentSphere = go->GetGUID();
if (GetBossState(DATA_ANOMALUS) == DONE)
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
break;
case GO_ORMOROKS_CONTAINMET_SPHERE:
OrmoroksContainmentSphere = go->GetGUID();
if (GetBossState(DATA_ORMOROK) == DONE)
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
break;
case GO_TELESTRAS_CONTAINMET_SPHERE:
TelestrasContainmentSphere = go->GetGUID();
if (GetBossState(DATA_MAGUS_TELESTRA) == DONE)
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
break;
default:
break;
}
}
for (uint8 i = 0; i < NUMBER_OF_ENCOUNTERS; ++i)
if (m_auiEncounter[i] == IN_PROGRESS)
m_auiEncounter[i] = NOT_STARTED;
bool SetBossState(uint32 type, EncounterState state) override
{
if (!InstanceScript::SetBossState(type, state))
return false;
OUT_LOAD_INST_DATA_COMPLETE;
switch (type)
{
case DATA_MAGUS_TELESTRA:
if (state == DONE)
{
if (GameObject* sphere = instance->GetGameObject(TelestrasContainmentSphere))
sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
}
break;
case DATA_ANOMALUS:
if (state == DONE)
{
if (GameObject* sphere = instance->GetGameObject(AnomalusContainmentSphere))
sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
}
break;
case DATA_ORMOROK:
if (state == DONE)
{
if (GameObject* sphere = instance->GetGameObject(OrmoroksContainmentSphere))
sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
}
break;
default:
break;
}
return true;
}
ObjectGuid GetGuidData(uint32 type) const override
{
switch (type)
{
case DATA_ANOMALUS:
return AnomalusGUID;
case DATA_KERISTRASZA:
return KeristraszaGUID;
case ANOMALUS_CONTAINMET_SPHERE:
return AnomalusContainmentSphere;
case ORMOROKS_CONTAINMET_SPHERE:
return OrmoroksContainmentSphere;
case TELESTRAS_CONTAINMET_SPHERE:
return TelestrasContainmentSphere;
default:
break;
}
return ObjectGuid::Empty;
}
private:
ObjectGuid AnomalusGUID;
ObjectGuid KeristraszaGUID;
ObjectGuid AnomalusContainmentSphere;
ObjectGuid OrmoroksContainmentSphere;
ObjectGuid TelestrasContainmentSphere;
uint32 _teamInInstance;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
{
return new instance_nexus_InstanceMapScript(map);
}
};
};
void AddSC_instance_nexus()
@@ -18,21 +18,48 @@
#ifndef DEF_NEXUS_H
#define DEF_NEXUS_H
#define NexusScriptName "instance_nexus"
#define DataHeader "NEX"
uint32 const EncounterCount = 4;
enum DataTypes
{
DATA_MAGUS_TELESTRA_EVENT,
DATA_ANOMALUS_EVENT,
DATA_ORMOROK_EVENT,
DATA_KERISTRASZA_EVENT,
DATA_MAGUS_TELESTRA = 0,
DATA_ANOMALUS = 1,
DATA_ORMOROK = 2,
DATA_KERISTRASZA = 3,
DATA_ANOMALUS,
DATA_KERISTRASZA,
ANOMALUS_CONTAINMET_SPHERE = 4,
ORMOROKS_CONTAINMET_SPHERE = 5,
TELESTRAS_CONTAINMET_SPHERE = 6
};
ANOMALUS_CONTAINMET_SPHERE,
ORMOROKS_CONTAINMET_SPHERE,
TELESTRAS_CONTAINMET_SPHERE
enum CreatureIds
{
NPC_ANOMALUS = 26763,
NPC_KERISTRASZA = 26723,
// Alliance
NPC_ALLIANCE_BERSERKER = 26800,
NPC_ALLIANCE_RANGER = 26802,
NPC_ALLIANCE_CLERIC = 26805,
NPC_ALLIANCE_COMMANDER = 27949,
NPC_COMMANDER_STOUTBEARD = 26796,
// Horde
NPC_HORDE_BERSERKER = 26799,
NPC_HORDE_RANGER = 26801,
NPC_HORDE_CLERIC = 26803,
NPC_HORDE_COMMANDER = 27947,
NPC_COMMANDER_KOLURG = 26798
};
enum GameObjectIds
{
GO_ANOMALUS_CONTAINMET_SPHERE = 188527,
GO_ORMOROKS_CONTAINMET_SPHERE = 188528,
GO_TELESTRAS_CONTAINMET_SPHERE = 188526
};
#endif
@@ -192,6 +192,7 @@ class instance_oculus : public InstanceMapScript
FreeDragons();
if (Creature* varos = instance->GetCreature(VarosGUID))
varos->SetPhaseMask(1, true);
events.ScheduleEvent(EVENT_VAROS_INTRO, 15000);
}
break;
case DATA_VAROS:
@@ -209,6 +210,7 @@ class instance_oculus : public InstanceMapScript
{
eregos->SetPhaseMask(1, true);
GreaterWhelps();
events.ScheduleEvent(EVENT_EREGOS_INTRO, 5000);
}
}
break;
@@ -267,6 +269,28 @@ class instance_oculus : public InstanceMapScript
}
}
void Update(uint32 diff) override
{
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_VAROS_INTRO:
if (Creature* varos = instance->GetCreature(VarosGUID))
varos->AI()->Talk(SAY_VAROS_INTRO_TEXT);
break;
case EVENT_EREGOS_INTRO:
if (Creature* eregos = instance->GetCreature(EregosGUID))
eregos->AI()->Talk(SAY_EREGOS_INTRO_TEXT);
break;
default:
break;
}
}
}
void GreaterWhelps()
{
for (ObjectGuid guid : GreaterWhelpList)
@@ -289,6 +313,8 @@ class instance_oculus : public InstanceMapScript
ObjectGuid EregosCacheGUID;
GuidList GreaterWhelpList;
EventMap events;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
@@ -79,6 +79,18 @@ enum OculusSpells
SPELL_DEATH_SPELL = 50415
};
enum InstanceTexts
{
SAY_EREGOS_INTRO_TEXT = 0,
SAY_VAROS_INTRO_TEXT = 4
};
enum InstanceEvents
{
EVENT_VAROS_INTRO = 1,
EVENT_EREGOS_INTRO
};
enum Misc
{
POINT_MOVE_OUT = 1
@@ -28,7 +28,7 @@ EndScriptData */
#include "SpellScript.h"
#include "halls_of_lightning.h"
enum Yells
enum Texts
{
SAY_INTRO_1 = 0,
SAY_INTRO_2 = 1,
@@ -51,6 +51,21 @@ enum Spells
SPELL_PULSING_SHOCKWAVE_AURA = 59414
};
enum Events
{
EVENT_ARC_LIGHTNING = 1,
EVENT_LIGHTNING_NOVA,
EVENT_RESUME_PULSING_SHOCKWAVE,
EVENT_INTRO_DIALOGUE
};
enum Phases
{
// Phases are used to allow executing the intro event while UpdateVictim() returns false and convenience.
PHASE_INTRO = 1,
PHASE_NORMAL
};
enum Misc
{
ACHIEV_TIMELY_DEATH_START_EVENT = 20384
@@ -65,57 +80,41 @@ class boss_loken : public CreatureScript
public:
boss_loken() : CreatureScript("boss_loken") { }
CreatureAI* GetAI(Creature* creature) const override
struct boss_lokenAI : public BossAI
{
return GetInstanceAI<boss_lokenAI>(creature);
}
struct boss_lokenAI : public ScriptedAI
{
boss_lokenAI(Creature* creature) : ScriptedAI(creature)
boss_lokenAI(Creature* creature) : BossAI(creature, DATA_LOKEN)
{
Initialize();
instance = creature->GetInstanceScript();
_isIntroDone = false;
}
void Initialize()
{
m_uiArcLightning_Timer = 15000;
m_uiLightningNova_Timer = 20000;
m_uiResumePulsingShockwave_Timer = 1000;
m_uiHealthAmountModifier = 1;
_healthAmountModifier = 1;
}
InstanceScript* instance;
uint32 m_uiArcLightning_Timer;
uint32 m_uiLightningNova_Timer;
uint32 m_uiResumePulsingShockwave_Timer;
uint32 m_uiHealthAmountModifier;
void Reset() override
{
Initialize();
instance->SetBossState(DATA_LOKEN, NOT_STARTED);
_Reset();
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT);
}
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
Talk(SAY_AGGRO);
instance->SetBossState(DATA_LOKEN, IN_PROGRESS);
events.SetPhase(PHASE_NORMAL);
events.ScheduleEvent(EVENT_ARC_LIGHTNING, 15000);
events.ScheduleEvent(EVENT_LIGHTNING_NOVA, 20000);
events.ScheduleEvent(EVENT_RESUME_PULSING_SHOCKWAVE, 1000);
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
instance->SetBossState(DATA_LOKEN, DONE);
_JustDied();
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_PULSING_SHOCKWAVE_AURA);
}
@@ -125,66 +124,89 @@ public:
Talk(SAY_SLAY);
}
void UpdateAI(uint32 uiDiff) override
void MoveInLineOfSight(Unit* who) override
{
//Return since we have no target
if (!UpdateVictim())
if (!_isIntroDone && me->IsValidAttackTarget(who) && me->IsWithinDistInMap(who, 40.0f))
{
_isIntroDone = true;
Talk(SAY_INTRO_1);
events.ScheduleEvent(EVENT_INTRO_DIALOGUE, 20000, 0, PHASE_INTRO);
}
BossAI::MoveInLineOfSight(who);
}
void UpdateAI(uint32 diff) override
{
if (events.IsInPhase(PHASE_NORMAL) && !UpdateVictim())
return;
if (m_uiResumePulsingShockwave_Timer)
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
if (m_uiResumePulsingShockwave_Timer <= uiDiff)
switch (eventId)
{
DoCast(me, SPELL_PULSING_SHOCKWAVE_AURA, true);
me->ClearUnitState(UNIT_STATE_CASTING); // this flag breaks movement
DoCast(me, SPELL_PULSING_SHOCKWAVE, true);
m_uiResumePulsingShockwave_Timer = 0;
case EVENT_ARC_LIGHTNING:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
DoCast(target, SPELL_ARC_LIGHTNING);
events.ScheduleEvent(EVENT_ARC_LIGHTNING, urand(15000, 16000));
break;
case EVENT_LIGHTNING_NOVA:
Talk(SAY_NOVA);
Talk(EMOTE_NOVA);
DoCastAOE(SPELL_LIGHTNING_NOVA);
me->RemoveAurasDueToSpell(sSpellMgr->GetSpellIdForDifficulty(SPELL_PULSING_SHOCKWAVE, me));
events.ScheduleEvent(EVENT_RESUME_PULSING_SHOCKWAVE, DUNGEON_MODE(5000, 4000)); // Pause Pulsing Shockwave aura
events.ScheduleEvent(EVENT_LIGHTNING_NOVA, urand(20000, 21000));
break;
case EVENT_RESUME_PULSING_SHOCKWAVE:
DoCast(me, SPELL_PULSING_SHOCKWAVE_AURA, true);
me->ClearUnitState(UNIT_STATE_CASTING); // This flag breaks movement.
DoCast(me, SPELL_PULSING_SHOCKWAVE, true);
break;
case EVENT_INTRO_DIALOGUE:
Talk(SAY_INTRO_2);
events.SetPhase(PHASE_NORMAL);
break;
default:
break;
}
else
m_uiResumePulsingShockwave_Timer -= uiDiff;
}
if (m_uiArcLightning_Timer <= uiDiff)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
DoCast(target, SPELL_ARC_LIGHTNING);
m_uiArcLightning_Timer = urand(15000, 16000);
}
else
m_uiArcLightning_Timer -= uiDiff;
if (m_uiLightningNova_Timer <= uiDiff)
{
Talk(SAY_NOVA);
Talk(EMOTE_NOVA);
DoCast(me, SPELL_LIGHTNING_NOVA);
me->RemoveAurasDueToSpell(sSpellMgr->GetSpellIdForDifficulty(SPELL_PULSING_SHOCKWAVE, me));
m_uiResumePulsingShockwave_Timer = DUNGEON_MODE(5000, 4000); // Pause Pulsing Shockwave aura
m_uiLightningNova_Timer = urand(20000, 21000);
}
else
m_uiLightningNova_Timer -= uiDiff;
// Health check
if (HealthBelowPct(100 - 25 * m_uiHealthAmountModifier))
{
switch (m_uiHealthAmountModifier)
{
case 1: Talk(SAY_75HEALTH); break;
case 2: Talk(SAY_50HEALTH); break;
case 3: Talk(SAY_25HEALTH); break;
}
++m_uiHealthAmountModifier;
}
DoMeleeAttackIfReady();
}
void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
if (me->HealthBelowPctDamaged(100 - 25 * _healthAmountModifier, damage))
{
switch (_healthAmountModifier)
{
case 1:
Talk(SAY_75HEALTH);
break;
case 2:
Talk(SAY_50HEALTH);
break;
case 3:
Talk(SAY_25HEALTH);
break;
default:
break;
}
++_healthAmountModifier;
}
}
private:
uint32 _healthAmountModifier;
bool _isIntroDone;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetInstanceAI<boss_lokenAI>(creature);
}
};
class spell_loken_pulsing_shockwave : public SpellScriptLoader
@@ -366,48 +366,6 @@ class npc_commander_eligor_dawnbringer : public CreatureScript
}
};
enum AlexstraszaWrGate
{
// Quest
QUEST_RETURN_TO_AG_A = 12499,
QUEST_RETURN_TO_AG_H = 12500,
// Movie
MOVIE_ID_GATES = 14
};
#define GOSSIP_ITEM_WHAT_HAPPENED "Alexstrasza, can you show me what happened here?"
class npc_alexstrasza_wr_gate : public CreatureScript
{
public:
npc_alexstrasza_wr_gate() : CreatureScript("npc_alexstrasza_wr_gate") { }
bool OnGossipHello(Player* player, Creature* creature) override
{
if (creature->IsQuestGiver())
player->PrepareQuestMenu(creature->GetGUID());
if (player->GetQuestRewardStatus(QUEST_RETURN_TO_AG_A) || player->GetQuestRewardStatus(QUEST_RETURN_TO_AG_H))
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_WHAT_HAPPENED, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
return true;
}
bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action) override
{
player->PlayerTalkClass->ClearMenus();
if (action == GOSSIP_ACTION_INFO_DEF+1)
{
player->CLOSE_GOSSIP_MENU();
player->SendMovieStart(MOVIE_ID_GATES);
}
return true;
}
};
/*######
## Quest Strengthen the Ancients (12096|12092)
######*/
@@ -746,7 +704,6 @@ class npc_torturer_lecraft : public CreatureScript
void AddSC_dragonblight()
{
new npc_commander_eligor_dawnbringer();
new npc_alexstrasza_wr_gate();
new spell_q12096_q12092_dummy();
new spell_q12096_q12092_bark();
new npc_wyrmrest_defender();
@@ -209,52 +209,6 @@ public:
}
};
/*######
## npc_vereth_the_cunning
######*/
enum VerethTheCunning
{
NPC_GEIST_RETURN_BUNNY_KC = 31049,
NPC_LITHE_STALKER = 30894,
SPELL_SUBDUED_LITHE_STALKER = 58151,
};
class npc_vereth_the_cunning : public CreatureScript
{
public:
npc_vereth_the_cunning() : CreatureScript("npc_vereth_the_cunning") { }
struct npc_vereth_the_cunningAI : public ScriptedAI
{
npc_vereth_the_cunningAI(Creature* creature) : ScriptedAI(creature) { }
void MoveInLineOfSight(Unit* who) override
{
ScriptedAI::MoveInLineOfSight(who);
if (who->GetEntry() == NPC_LITHE_STALKER && me->IsWithinDistInMap(who, 10.0f))
{
if (Unit* owner = who->GetCharmer())
{
if (who->HasAura(SPELL_SUBDUED_LITHE_STALKER))
{
owner->ToPlayer()->KilledMonsterCredit(NPC_GEIST_RETURN_BUNNY_KC);
who->ToCreature()->DisappearAndDie();
}
}
}
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_vereth_the_cunningAI(creature);
}
};
/*######
* npc_tournament_training_dummy
######*/
@@ -881,207 +835,12 @@ class npc_frostbrood_skytalon : public CreatureScript
}
};
/*######
## The Flesh Giant Champion - Id: 13235
######*/
enum FleshGiant
{
QUEST_FLESH_GIANT_CHAMPION = 13235,
NPC_MORBIDUS = 30698,
NPC_LICH_KING = 31301,
NPC_OLAKIN = 31428,
NPC_DHAKAR = 31306,
FACTION_HOSTILE = 14,
FACTION_BASIC = 2102,
EVENT_INTRO = 1,
EVENT_LK_SAY_1 = 2,
EVENT_LK_SAY_2 = 3,
EVENT_LK_SAY_3 = 4,
EVENT_LK_SAY_4 = 5,
EVENT_LK_SAY_5 = 6,
EVENT_OUTRO = 7,
EVENT_START = 8,
SPELL_SIMPLE_TELEPORT = 64195,
SAY_DHAKAR_START = 0,
SAY_LK_1 = 0,
SAY_LK_2 = 1,
SAY_LK_3 = 2,
SAY_LK_4 = 3,
SAY_LK_5 = 4,
SAY_OLAKIN_PAY = 0
};
class npc_margrave_dhakar : public CreatureScript
{
public:
npc_margrave_dhakar() : CreatureScript("npc_margrave_dhakar") { }
struct npc_margrave_dhakarAI : public ScriptedAI
{
npc_margrave_dhakarAI(Creature* creature) : ScriptedAI(creature) , _summons(me) { }
void Reset() override
{
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE);
_events.Reset();
_summons.DespawnAll();
}
void sGossipSelect(Player* player, uint32 sender, uint32 action) override
{
if (player->GetQuestStatus(QUEST_FLESH_GIANT_CHAMPION) == QUEST_STATUS_INCOMPLETE && !player->IsInCombat())
{
if (me->GetCreatureTemplate()->GossipMenuId == sender && !action)
{
_events.ScheduleEvent(EVENT_INTRO, 1000);
me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
}
}
}
void UpdateAI(uint32 diff) override
{
_events.Update(diff);
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_INTRO:
{
Talk(SAY_DHAKAR_START);
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H);
if (Creature* morbidus = me->FindNearestCreature(NPC_MORBIDUS, 50.0f, true))
{
if (Creature* lichKing = me->SummonCreature(NPC_LICH_KING, morbidus->GetPositionX() + 10.0f, morbidus->GetPositionY(), morbidus->GetPositionZ()))
{
_lichKingGuid = lichKing->GetGUID();
lichKing->SetFacingTo(morbidus->GetOrientation());
lichKing->CastSpell(lichKing, SPELL_SIMPLE_TELEPORT, true);
}
}
_events.ScheduleEvent(EVENT_LK_SAY_1, 5000);
break;
}
case EVENT_LK_SAY_1:
{
if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _lichKingGuid))
lichKing->AI()->Talk(SAY_LK_1);
_events.ScheduleEvent(EVENT_LK_SAY_2, 5000);
break;
}
case EVENT_LK_SAY_2:
{
if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _lichKingGuid))
lichKing->AI()->Talk(SAY_LK_2);
_events.ScheduleEvent(EVENT_LK_SAY_3, 5000);
break;
}
case EVENT_LK_SAY_3:
{
if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _lichKingGuid))
lichKing->AI()->Talk(SAY_LK_3);
_events.ScheduleEvent(EVENT_LK_SAY_4, 5000);
break;
}
case EVENT_LK_SAY_4:
{
if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _lichKingGuid))
lichKing->AI()->Talk(SAY_LK_4);
_events.ScheduleEvent(EVENT_OUTRO, 12000);
break;
}
case EVENT_LK_SAY_5:
{
if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _lichKingGuid))
lichKing->AI()->Talk(SAY_LK_5);
_events.ScheduleEvent(EVENT_OUTRO, 8000);
break;
}
case EVENT_OUTRO:
{
if (Creature* olakin = me->FindNearestCreature(NPC_OLAKIN, 50.0f, true))
olakin->AI()->Talk(SAY_OLAKIN_PAY);
if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _lichKingGuid))
lichKing->DespawnOrUnsummon(0);
_events.ScheduleEvent(EVENT_START, 5000);
break;
}
case EVENT_START:
{
if (Creature* morbidus = me->FindNearestCreature(NPC_MORBIDUS, 50.0f, true))
{
morbidus->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1 | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_DISABLE_MOVE);
morbidus->setFaction(FACTION_HOSTILE);
}
break;
}
}
}
DoMeleeAttackIfReady();
}
private:
EventMap _events;
SummonList _summons;
ObjectGuid _lichKingGuid;
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_margrave_dhakarAI(creature);
}
};
class npc_morbidus : public CreatureScript
{
public:
npc_morbidus() : CreatureScript("npc_morbidus") { }
struct npc_morbidusAI : public ScriptedAI
{
npc_morbidusAI(Creature* creature) : ScriptedAI(creature) { }
void Reset() override
{
if (Creature* dhakar = me->FindNearestCreature(NPC_DHAKAR, 50.0f, true))
dhakar->AI()->Reset();
// this will prevent the event to start without morbidus being alive
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->SetReactState(REACT_PASSIVE);
me->setFaction(FACTION_BASIC);
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_morbidusAI(creature);
}
};
void AddSC_icecrown()
{
new npc_squire_david;
new npc_argent_valiant;
new npc_guardian_pavilion;
new npc_vereth_the_cunning;
new npc_tournament_training_dummy;
new npc_blessed_banner();
new npc_frostbrood_skytalon();
new npc_margrave_dhakar();
new npc_morbidus();
}
@@ -21,8 +21,14 @@
DoorData const doorData[] =
{
{ GO_IKISS_DOOR, DATA_TALON_KING_IKISS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END
{ GO_IKISS_DOOR, DATA_TALON_KING_IKISS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END
};
ObjectData const gameObjectData[] =
{
{ GO_TALON_KING_COFFER, DATA_TALON_KING_COFFER },
{ 0, 0 } // END
};
class instance_sethekk_halls : public InstanceMapScript
@@ -37,6 +43,7 @@ class instance_sethekk_halls : public InstanceMapScript
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
LoadDoorData(doorData);
LoadObjectData(nullptr, gameObjectData);
}
void OnCreatureCreate(Creature* creature) override
@@ -50,16 +57,27 @@ class instance_sethekk_halls : public InstanceMapScript
}
}
void OnGameObjectCreate(GameObject* go) override
bool SetBossState(uint32 type, EncounterState state) override
{
if (go->GetEntry() == GO_IKISS_DOOR)
AddDoor(go, true);
}
if (!InstanceScript::SetBossState(type, state))
return false;
void OnGameObjectRemove(GameObject* go) override
{
if (go->GetEntry() == GO_IKISS_DOOR)
AddDoor(go, false);
switch (type)
{
case DATA_TALON_KING_IKISS:
if (state == DONE)
{
/// @workaround: GO_FLAG_INTERACT_COND remains on the gob, but it is not handled correctly in this case
/// gameobject should have GO_DYNFLAG_LO_ACTIVATE too, which makes gobs interactable with GO_FLAG_INTERACT_COND
/// so just removed GO_FLAG_INTERACT_COND
if (GameObject* coffer = GetGameObject(DATA_TALON_KING_COFFER))
coffer->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND | GO_FLAG_NOT_SELECTABLE);
}
break;
default:
break;
}
return true;
}
};
@@ -28,7 +28,10 @@ enum DataTypes
// Encounter States/Boss GUIDs
DATA_DARKWEAVER_SYTH = 0,
DATA_TALON_KING_IKISS = 1,
DATA_ANZU = 2
DATA_ANZU = 2,
// Additional Data
DATA_TALON_KING_COFFER = 3
};
enum CreatureIds
@@ -39,7 +42,8 @@ enum CreatureIds
enum GameObjectIds
{
GO_IKISS_DOOR = 177203
GO_IKISS_DOOR = 177203,
GO_TALON_KING_COFFER = 187372
};
template<class AI>
@@ -31,21 +31,25 @@ class go_main_chambers_access_panel : public GameObjectScript
return false;
if (go->GetEntry() == GO_ACCESS_PANEL_HYDRO && (instance->GetBossState(DATA_HYDROMANCER_THESPIA) == DONE || instance->GetBossState(DATA_HYDROMANCER_THESPIA) == SPECIAL))
{
instance->SetBossState(DATA_HYDROMANCER_THESPIA, SPECIAL);
go->SetGoState(GO_STATE_ACTIVE);
}
if (go->GetEntry() == GO_ACCESS_PANEL_MEK && (instance->GetBossState(DATA_MEKGINEER_STEAMRIGGER) == DONE || instance->GetBossState(DATA_MEKGINEER_STEAMRIGGER) == SPECIAL))
{
instance->SetBossState(DATA_MEKGINEER_STEAMRIGGER, SPECIAL);
go->SetGoState(GO_STATE_ACTIVE);
}
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
go->SetGoState(GO_STATE_ACTIVE);
return true;
}
};
ObjectData const gameObjectData[] =
{
{ GO_ACCESS_PANEL_HYDRO, DATA_ACCESS_PANEL_HYDRO },
{ GO_ACCESS_PANEL_MEK, DATA_ACCESS_PANEL_MEK },
{ 0, 0 } // END
};
class instance_steam_vault : public InstanceMapScript
{
public:
@@ -57,6 +61,7 @@ class instance_steam_vault : public InstanceMapScript
{
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
LoadObjectData(nullptr, gameObjectData);
DistillerState = 0;
}
@@ -89,6 +94,8 @@ class instance_steam_vault : public InstanceMapScript
default:
break;
}
InstanceScript::OnGameObjectCreate(go);
}
ObjectGuid GetGuidData(uint32 type) const override
@@ -128,6 +135,9 @@ class instance_steam_vault : public InstanceMapScript
switch (type)
{
case DATA_HYDROMANCER_THESPIA:
if (state == DONE)
if (GameObject* panel = GetGameObject(DATA_ACCESS_PANEL_HYDRO))
panel->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
if (state == SPECIAL)
{
if (GetBossState(DATA_MEKGINEER_STEAMRIGGER) == SPECIAL)
@@ -137,6 +147,9 @@ class instance_steam_vault : public InstanceMapScript
}
break;
case DATA_MEKGINEER_STEAMRIGGER:
if (state == DONE)
if (GameObject* panel = GetGameObject(DATA_ACCESS_PANEL_MEK))
panel->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
if (state == SPECIAL)
{
if (GetBossState(DATA_HYDROMANCER_THESPIA) == SPECIAL)
@@ -28,7 +28,11 @@ enum DataTypes
DATA_HYDROMANCER_THESPIA = 0,
DATA_MEKGINEER_STEAMRIGGER = 1,
DATA_WARLORD_KALITHRESH = 2,
DATA_DISTILLER = 3
DATA_DISTILLER = 3,
// Additional Data
DATA_ACCESS_PANEL_HYDRO = 4,
DATA_ACCESS_PANEL_MEK = 5
};
enum CreatureIds
-67
View File
@@ -40,8 +40,6 @@ go_dragonflayer_cage
go_tadpole_cage
go_amberpine_outhouse
go_hive_pod
go_gjalerbron_cage
go_large_gjalerbron_cage
go_veil_skith_cage
EndContentData */
@@ -1040,69 +1038,6 @@ class go_massive_seaforium_charge : public GameObjectScript
};
/*######
## go_gjalerbron_cage
######*/
enum OfKeysAndCages
{
QUEST_ALLIANCE_OF_KEYS_AND_CAGES = 11231,
QUEST_HORDE_OF_KEYS_AND_CAGES = 11265,
NPC_GJALERBRON_PRISONER = 24035,
SAY_FREE = 0,
};
class go_gjalerbron_cage : public GameObjectScript
{
public:
go_gjalerbron_cage() : GameObjectScript("go_gjalerbron_cage") { }
bool OnGossipHello(Player* player, GameObject* go) override
{
go->UseDoorOrButton();
if ((player->GetTeamId() == TEAM_ALLIANCE && player->GetQuestStatus(QUEST_ALLIANCE_OF_KEYS_AND_CAGES) == QUEST_STATUS_INCOMPLETE) ||
(player->GetTeamId() == TEAM_HORDE && player->GetQuestStatus(QUEST_HORDE_OF_KEYS_AND_CAGES) == QUEST_STATUS_INCOMPLETE))
{
if (Creature* prisoner = go->FindNearestCreature(NPC_GJALERBRON_PRISONER, 5.0f))
{
player->KilledMonsterCredit(NPC_GJALERBRON_PRISONER);
prisoner->AI()->Talk(SAY_FREE);
prisoner->DespawnOrUnsummon(6000);
}
}
return true;
}
};
/*########
## go_large_gjalerbron_cage
#####*/
class go_large_gjalerbron_cage : public GameObjectScript
{
public:
go_large_gjalerbron_cage() : GameObjectScript("go_large_gjalerbron_cage") { }
bool OnGossipHello(Player* player, GameObject* go) override
{
go->UseDoorOrButton();
if ((player->GetTeamId() == TEAM_ALLIANCE && player->GetQuestStatus(QUEST_ALLIANCE_OF_KEYS_AND_CAGES) == QUEST_STATUS_INCOMPLETE) ||
(player->GetTeamId() == TEAM_HORDE && player->GetQuestStatus(QUEST_HORDE_OF_KEYS_AND_CAGES) == QUEST_STATUS_INCOMPLETE))
{
std::list<Creature*> prisonerList;
GetCreatureListWithEntryInGrid(prisonerList, go, NPC_GJALERBRON_PRISONER, INTERACTION_DISTANCE);
for (std::list<Creature*>::const_iterator itr = prisonerList.begin(); itr != prisonerList.end(); ++itr)
{
player->KilledMonsterCredit(NPC_GJALERBRON_PRISONER, (*itr)->GetGUID());
(*itr)->DespawnOrUnsummon(6000);
(*itr)->AI()->Talk(SAY_FREE);
}
}
return false;
}
};
/*########
#### go_veil_skith_cage
#####*/
@@ -1222,8 +1157,6 @@ void AddSC_go_scripts()
new go_amberpine_outhouse();
new go_hive_pod();
new go_massive_seaforium_charge();
new go_gjalerbron_cage();
new go_large_gjalerbron_cage();
new go_veil_skith_cage();
new go_frostblade_shrine();
new go_midsummer_bonfire();