Merge remote-tracking branch 'origin/master' into mmaps

This commit is contained in:
Nay
2012-09-23 22:17:52 +01:00
16 changed files with 548 additions and 158 deletions

View File

@@ -133,7 +133,7 @@ public:
struct boss_eregosAI : public BossAI
{
boss_eregosAI(Creature* creature) : BossAI(creature, DATA_EREGOS_EVENT) { }
void Reset()
{
_Reset();
@@ -160,7 +160,7 @@ public:
_emeraldVoid = false;
if (me->FindNearestCreature(NPC_AMBER_DRAKE_VEHICLE, 500.0f, true))
_amberVoid = false;
}
}
uint32 GetData(uint32 type)
{

View File

@@ -56,13 +56,16 @@ enum Events
EVENT_DARK_SMASH,
EVENT_DREADFUL_ROAR,
EVENT_WOE_STRIKE,
EVENT_SHADOW_AXE
EVENT_SHADOW_AXE,
EVENT_JUST_TRANSFORMED,
EVENT_SUMMON_BANSHEE
};
enum Phases
{
PHASE_HUMAN = 1,
PHASE_UNDEAD,
PHASE_EVENT
};
enum Spells
@@ -83,7 +86,7 @@ enum Spells
SPELL_WOE_STRIKE = 42730,
ENTRY_THROW_TARGET = 23996,
SPELL_SHADOW_AXE_SUMMON = 42749
SPELL_SHADOW_AXE_SUMMON = 42748
};
class boss_ingvar_the_plunderer : public CreatureScript
@@ -107,9 +110,6 @@ public:
InstanceScript* instance;
bool bIsUndead;
bool bEventInProgress;
uint32 uiSpawnResTimer;
void Reset()
{
@@ -117,7 +117,6 @@ public:
me->UpdateEntry(MOB_INGVAR_HUMAN);
bIsUndead = false;
bEventInProgress = false;
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
me->SetStandState(UNIT_STAND_STATE_STAND);
@@ -130,13 +129,6 @@ public:
events.ScheduleEvent(EVENT_ENRAGE, urand(7,14)*IN_MILLISECONDS, 0, PHASE_HUMAN);
events.ScheduleEvent(EVENT_SMASH, urand(12,17)*IN_MILLISECONDS, 0, PHASE_HUMAN);
events.ScheduleEvent(EVENT_DARK_SMASH, urand(14,22)*IN_MILLISECONDS, 0, PHASE_UNDEAD);
events.ScheduleEvent(EVENT_DREADFUL_ROAR, urand(18,21)*IN_MILLISECONDS, 0, PHASE_UNDEAD);
events.ScheduleEvent(EVENT_WOE_STRIKE, urand(10,14)*IN_MILLISECONDS, 0, PHASE_UNDEAD);
events.ScheduleEvent(EVENT_SHADOW_AXE, 30*IN_MILLISECONDS, 0, PHASE_UNDEAD);
uiSpawnResTimer = 3000;
if (instance)
instance->SetData(DATA_INGVAR_EVENT, NOT_STARTED);
}
@@ -156,37 +148,34 @@ public:
me->SetStandState(UNIT_STAND_STATE_DEAD);
// visuel hack end
bEventInProgress = true;
bIsUndead = true;
events.SetPhase(PHASE_UNDEAD);
events.SetPhase(PHASE_EVENT);
events.ScheduleEvent(EVENT_SUMMON_BANSHEE, 3 * IN_MILLISECONDS, 0, PHASE_EVENT);
DoScriptText(YELL_DEAD_1, me);
}
if (bEventInProgress)
{
if (events.GetPhaseMask() & (1 << PHASE_EVENT))
damage = 0;
}
}
void StartZombiePhase()
{
bIsUndead = true;
bEventInProgress = false;
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->UpdateEntry(MOB_INGVAR_UNDEAD);
me->SetInCombatWith(me->getVictim());
me->GetMotionMaster()->MoveChase(me->getVictim());
events.ScheduleEvent(EVENT_JUST_TRANSFORMED, 2 * IN_MILLISECONDS, 0, PHASE_EVENT);
DoScriptText(YELL_AGGRO_2, me);
}
void EnterCombat(Unit* /*who*/)
{
DoScriptText(YELL_AGGRO_1, me);
if (!bIsUndead)
DoScriptText(YELL_AGGRO_1, me);
if (instance)
instance->SetData(DATA_INGVAR_EVENT, IN_PROGRESS);
me->SetInCombatWithZone();
}
void JustDied(Unit* /*killer*/)
@@ -201,6 +190,15 @@ public:
}
}
void ScheduleSecondPhase()
{
events.SetPhase(PHASE_UNDEAD);
events.ScheduleEvent(EVENT_DARK_SMASH, urand(14,18)*IN_MILLISECONDS, 0, PHASE_UNDEAD);
events.ScheduleEvent(EVENT_DREADFUL_ROAR, urand(18,22)*IN_MILLISECONDS, 0, PHASE_UNDEAD);
events.ScheduleEvent(EVENT_WOE_STRIKE, urand(10,14)*IN_MILLISECONDS, 0, PHASE_UNDEAD);
events.ScheduleEvent(EVENT_SHADOW_AXE, 30*IN_MILLISECONDS, 0, PHASE_UNDEAD);
}
void KilledUnit(Unit* /*victim*/)
{
if (bIsUndead)
@@ -211,24 +209,9 @@ public:
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim())
if (!UpdateVictim() && !(events.GetPhaseMask() & (1 << PHASE_EVENT)))
return;
if (bEventInProgress)
{
if (uiSpawnResTimer)
{
if (uiSpawnResTimer <= diff)
{
DoCast(me, SPELL_SUMMON_BANSHEE); // Summons directly on caster position
// DoCast(me, SPELL_SCOURG_RESURRECTION, true); // Not needed ?
uiSpawnResTimer = 0;
} else uiSpawnResTimer -= diff;
}
return;
}
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
@@ -245,24 +228,33 @@ public:
break;
case EVENT_STAGGERING_ROAR:
DoCast(me, SPELL_STAGGERING_ROAR);
events.ScheduleEvent(EVENT_STAGGERING_ROAR, urand(18,21)*IN_MILLISECONDS, 0, PHASE_HUMAN);
events.ScheduleEvent(EVENT_STAGGERING_ROAR, urand(18,22)*IN_MILLISECONDS, 0, PHASE_HUMAN);
break;
case EVENT_ENRAGE:
DoCast(me, SPELL_ENRAGE);
events.ScheduleEvent(EVENT_ENRAGE, urand(7,14)*IN_MILLISECONDS, 0, PHASE_HUMAN);
break;
case EVENT_SMASH:
DoCastVictim(SPELL_SMASH);
events.ScheduleEvent(EVENT_SMASH, urand(12,17)*IN_MILLISECONDS, 0, PHASE_HUMAN);
DoCastAOE(SPELL_SMASH);
events.ScheduleEvent(EVENT_SMASH, urand(12,16)*IN_MILLISECONDS, 0, PHASE_HUMAN);
break;
case EVENT_JUST_TRANSFORMED:
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->SetInCombatWithZone();
me->GetMotionMaster()->MoveChase(me->getVictim());
ScheduleSecondPhase();
return;
case EVENT_SUMMON_BANSHEE:
DoCast(me, SPELL_SUMMON_BANSHEE);
return;
// PHASE TWO
case EVENT_DARK_SMASH:
DoCastVictim(SPELL_DARK_SMASH);
events.ScheduleEvent(EVENT_DARK_SMASH, urand(14,22)*IN_MILLISECONDS, 0, PHASE_UNDEAD);
events.ScheduleEvent(EVENT_DARK_SMASH, urand(12,16)*IN_MILLISECONDS, 0, PHASE_UNDEAD);
break;
case EVENT_DREADFUL_ROAR:
DoCast(me, SPELL_DREADFUL_ROAR);
events.ScheduleEvent(EVENT_DREADFUL_ROAR, urand(18,21)*IN_MILLISECONDS, 0, PHASE_UNDEAD);
events.ScheduleEvent(EVENT_DREADFUL_ROAR, urand(18,22)*IN_MILLISECONDS, 0, PHASE_UNDEAD);
break;
case EVENT_WOE_STRIKE:
DoCastVictim(SPELL_WOE_STRIKE);
@@ -271,8 +263,7 @@ public:
case EVENT_SHADOW_AXE:
if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1))
{
me->SummonCreature(ENTRY_THROW_TARGET, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 2000);
DoCast(me, SPELL_SHADOW_AXE_SUMMON);
DoCast(target, SPELL_SHADOW_AXE_SUMMON);
}
events.ScheduleEvent(EVENT_SHADOW_AXE, 30*IN_MILLISECONDS, 0, PHASE_UNDEAD);
break;
@@ -411,7 +402,8 @@ public:
enum eShadowAxe
{
SPELL_SHADOW_AXE_DAMAGE = 42750,
H_SPELL_SHADOW_AXE_DAMAGE = 59719
H_SPELL_SHADOW_AXE_DAMAGE = 59719,
POINT_TARGET = 28
};
class mob_ingvar_throw_dummy : public CreatureScript
@@ -430,32 +422,34 @@ public:
{
}
uint32 uiDespawnTimer;
void Reset()
{
Unit* target = me->FindNearestCreature(ENTRY_THROW_TARGET, 50);
if (target)
if (Creature* target = me->FindNearestCreature(ENTRY_THROW_TARGET, 50.0f))
{
DoCast(me, SPELL_SHADOW_AXE_DAMAGE);
float x, y, z;
target->GetPosition(x, y, z);
me->GetMotionMaster()->MovePoint(0, x, y, z);
me->GetMotionMaster()->MoveCharge(x, y, z, 42.0f, POINT_TARGET);
target->DisappearAndDie();
}
uiDespawnTimer = 7000;
}
void AttackStart(Unit* /*who*/) {}
void MoveInLineOfSight(Unit* /*who*/) {}
void EnterCombat(Unit* /*who*/) {}
void UpdateAI(const uint32 diff)
{
if (uiDespawnTimer <= diff)
else
{
me->DealDamage(me, me->GetHealth());
me->RemoveCorpse();
uiDespawnTimer = 0;
} else uiDespawnTimer -= diff;
me->DisappearAndDie();
}
}
void MovementInform(uint32 type, uint32 id)
{
if (type == EFFECT_MOTION_TYPE && id == POINT_TARGET)
{
DoCast(me, SPELL_SHADOW_AXE_DAMAGE);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
if (TempSummon* summon = me->ToTempSummon())
{
summon->UnSummon(10000);
}
else
me->DisappearAndDie();
}
}
};
};

View File

@@ -43,6 +43,9 @@ enum KelsethEncounter
NPC_FROSTTOMB = 23965,
NPC_SKELETON = 23970,
NPC_RUNEMAGE = 23960,
NPC_STRATEGIST = 23956,
SAY_START_COMBAT = 1,
SAY_SUMMON_SKELETONS,
SAY_FROST_TOMB,
@@ -118,10 +121,7 @@ public:
struct boss_kelesethAI : public BossAI
{
boss_kelesethAI(Creature* creature) : BossAI(creature, DATA_PRINCEKELESETH_EVENT)
{
creature->SetReactState(REACT_DEFENSIVE);
}
boss_kelesethAI(Creature* creature) : BossAI(creature, DATA_PRINCEKELESETH_EVENT){}
void Reset()
{
@@ -138,12 +138,37 @@ public:
onTheRocks = true;
}
void EnterCombat(Unit* /*who*/)
void EnterCombat(Unit* who)
{
me->SetInCombatWithZone();
if (instance)
instance->SetData(DATA_PRINCEKELESETH_EVENT, IN_PROGRESS);
Talk(SAY_START_COMBAT);
if (!who)
return;
std::list<Creature*> runemages;
me->GetCreatureListWithEntryInGrid(runemages, NPC_RUNEMAGE, 60.0f);
if (!runemages.empty())
{
for (std::list<Creature*>::iterator itr = runemages.begin(); itr != runemages.end(); ++itr)
{
if ((*itr)->isAlive() && (*itr)->IsWithinLOSInMap(me))
(*itr)->AI()->AttackStart(who);
}
}
std::list<Creature*> strategists;
me->GetCreatureListWithEntryInGrid(strategists, NPC_STRATEGIST, 60.0f);
if (!strategists.empty())
{
for (std::list<Creature*>::iterator itr = strategists.begin(); itr != strategists.end(); ++itr)
{
if ((*itr)->isAlive() && (*itr)->IsWithinLOSInMap(me))
(*itr)->AI()->AttackStart(who);
}
}
}
void JustDied(Unit* /*killer*/)
@@ -168,10 +193,20 @@ public:
return 0;
}
void ExecuteEvent(uint32 const eventId)
void UpdateAI(uint32 const diff)
{
switch (eventId)
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_SUMMON_SKELETONS:
Talk(SAY_SUMMON_SKELETONS);
SummonSkeletons();
@@ -192,7 +227,10 @@ public:
}
events.ScheduleEvent(EVENT_FROST_TOMB, urand(14,19)*IN_MILLISECONDS);
break;
}
}
DoMeleeAttackIfReady();
}
void SummonSkeletons()
@@ -225,7 +263,6 @@ public:
events.Reset();
events.ScheduleEvent(EVENT_DECREPIFY, urand(4,6)*IN_MILLISECONDS);
DoCast(SPELL_BONE_ARMOR);
}
void DamageTaken(Unit* /*done_by*/, uint32 &damage)
@@ -278,6 +315,13 @@ public:
break;
case EVENT_SHADOW_FISSURE:
DoCast(me, SPELL_SHADOW_FISSURE, true);
if (TempSummon* temp = me->ToTempSummon())
{
if (Unit* summoner = temp->GetSummoner())
{
DoCast(summoner, SPELL_BONE_ARMOR);
}
}
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
me->RemoveFlag(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD);
me->GetMotionMaster()->MoveChase(me->getVictim());

View File

@@ -47,6 +47,7 @@ enum eEnums
SPELL_CHARGE = 43651,
SPELL_STONE_STRIKE = 48583,
SPELL_SUMMON_SKARVALD_GHOST = 48613,
SPELL_ENRAGE = 48193,
MOB_SKARVALD_GHOST = 27390,
//Spells of Dalronn and his Ghost
MOB_DALRONN_THE_CONTROLLER = 24201,
@@ -58,6 +59,20 @@ enum eEnums
MOB_DALRONN_GHOST = 27389
};
class SkarvaldChargePredicate
{
public:
SkarvaldChargePredicate(Unit* unit) : me(unit) {}
bool operator() (WorldObject* object) const
{
return object->GetDistance2d(me) >= 5.0f && object->GetDistance2d(me) <= 30.0f;
}
private:
Unit* me;
};
class boss_skarvald_the_constructor : public CreatureScript
{
public:
@@ -83,6 +98,7 @@ public:
uint32 Response_Timer;
uint32 Check_Timer;
bool Dalronn_isDead;
bool Enraged;
void Reset()
{
@@ -90,6 +106,7 @@ public:
StoneStrike_Timer = 10000;
Dalronn_isDead = false;
Check_Timer = 5000;
Enraged = false;
ghost = (me->GetEntry() == MOB_SKARVALD_GHOST);
if (!ghost && instance)
@@ -116,6 +133,15 @@ public:
}
}
void DamageTaken(Unit* /*attacker*/, uint32& damage)
{
if (!Enraged && !ghost && me->HealthBelowPctDamaged(15, damage))
{
Enraged = true;
DoCast(me, SPELL_ENRAGE);
}
}
void JustDied(Unit* killer)
{
if (!ghost && instance)
@@ -194,7 +220,7 @@ public:
if (Charge_Timer <= diff)
{
DoCast(SelectTarget(SELECT_TARGET_RANDOM, 1), SPELL_CHARGE);
DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, SkarvaldChargePredicate(me)), SPELL_CHARGE);
Charge_Timer = 5000+rand()%5000;
} else Charge_Timer -= diff;
@@ -204,7 +230,8 @@ public:
StoneStrike_Timer = 5000+rand()%5000;
} else StoneStrike_Timer -= diff;
DoMeleeAttackIfReady();
if (!me->HasUnitState(UNIT_STATE_CASTING))
DoMeleeAttackIfReady();
}
};

View File

@@ -18,6 +18,8 @@
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "utgarde_keep.h"
#include "SpellScript.h"
#include "SpellAuraEffects.h"
uint32 entry_search[3] =
{
@@ -164,7 +166,82 @@ public:
};
};
enum TickingTimeBomb
{
SPELL_TICKING_TIME_BOMB_EXPLODE = 59687
};
class spell_ticking_time_bomb : public SpellScriptLoader
{
public:
spell_ticking_time_bomb() : SpellScriptLoader("spell_ticking_time_bomb") { }
class spell_ticking_time_bomb_AuraScript : public AuraScript
{
PrepareAuraScript(spell_ticking_time_bomb_AuraScript);
bool Validate(SpellInfo const* /*spellEntry*/)
{
return (bool) sSpellMgr->GetSpellInfo(SPELL_TICKING_TIME_BOMB_EXPLODE);
}
void HandleOnEffectRemove(AuraEffect const* /* aurEff */, AuraEffectHandleModes /* mode */)
{
if (GetCaster() == GetTarget())
{
GetTarget()->CastSpell(GetTarget(), SPELL_TICKING_TIME_BOMB_EXPLODE, true);
}
}
void Register()
{
OnEffectRemove += AuraEffectRemoveFn(spell_ticking_time_bomb_AuraScript::HandleOnEffectRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const
{
return new spell_ticking_time_bomb_AuraScript();
}
};
enum Fixate
{
SPELL_FIXATE_TRIGGER = 40415
};
class spell_fixate : public SpellScriptLoader
{
public:
spell_fixate() : SpellScriptLoader("spell_fixate") { }
class spell_fixate_SpellScript : public SpellScript
{
PrepareSpellScript(spell_fixate_SpellScript);
bool Validate(SpellInfo const* /*spellEntry*/)
{
return (bool) sSpellMgr->GetSpellInfo(SPELL_FIXATE_TRIGGER);
}
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
{
// The unit has to cast the taunt on hisself, but we need the original caster for SPELL_AURA_MOD_TAUNT
GetCaster()->CastSpell(GetCaster(), SPELL_FIXATE_TRIGGER, true, 0, 0, GetHitUnit()->GetGUID());
}
void Register()
{
OnEffectHitTarget += SpellEffectFn(spell_fixate_SpellScript::HandleScriptEffect, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
SpellScript* GetSpellScript() const
{
return new spell_fixate_SpellScript();
}
};
void AddSC_utgarde_keep()
{
new npc_dragonflayer_forge_master();
new spell_ticking_time_bomb();
new spell_fixate();
}

View File

@@ -1667,7 +1667,6 @@ public:
/*######
## npc_imprisoned_beryl_sorcerer
######*/
enum eImprisionedBerylSorcerer
{
SPELL_NEURAL_NEEDLE = 45634,
@@ -1692,103 +1691,79 @@ public:
{
npc_imprisoned_beryl_sorcererAI(Creature* creature) : ScriptedAI(creature) {}
uint64 CasterGUID;
uint32 uiStep;
uint32 uiPhase;
uint32 rebuff;
void Reset()
{
uiStep = 1;
uiPhase = 0;
CasterGUID = 0;
if (me->GetReactState() != REACT_PASSIVE)
me->SetReactState(REACT_PASSIVE);
rebuff = 0;
}
void UpdateAI(const uint32 diff)
{
UpdateVictim();
if (rebuff <= diff)
{
if (!me->HasAura(SPELL_COSMETIC_ENSLAVE_CHAINS_SELF))
{
DoCast(me, SPELL_COSMETIC_ENSLAVE_CHAINS_SELF);
}
rebuff = 180000;
}
else
rebuff -= diff;
DoMeleeAttackIfReady();
}
void EnterCombat(Unit* /*who*/)
{
}
void SpellHit(Unit* unit, const SpellInfo* pSpell)
void SpellHit(Unit* unit, const SpellInfo* spell)
{
if (pSpell->Id == SPELL_NEURAL_NEEDLE && unit->GetTypeId() == TYPEID_PLAYER)
if (spell->Id == SPELL_NEURAL_NEEDLE && unit->GetTypeId() == TYPEID_PLAYER)
{
++uiPhase;
CasterGUID = unit->GetGUID();
if (Player* player = unit->ToPlayer())
{
GotStinged(player->GetGUID());
}
}
}
void UpdateAI(const uint32 uiDiff)
void GotStinged(uint64 casterGUID)
{
ScriptedAI::UpdateAI(uiDiff);
if (!me->HasAura(SPELL_COSMETIC_ENSLAVE_CHAINS_SELF))
DoCast(me, SPELL_COSMETIC_ENSLAVE_CHAINS_SELF);
if (me->GetReactState() != REACT_PASSIVE)
me->SetReactState(REACT_PASSIVE);
switch (uiPhase)
if (Player* caster = Player::GetPlayer(*me, casterGUID))
{
case 1:
if (uiStep == 1)
{
uint32 step = caster->GetAuraCount(SPELL_NEURAL_NEEDLE) + 1;
switch (step)
{
case 1:
DoScriptText(SAY_IMPRISIONED_BERYL_1, me);
uiStep = 2;
}
break;
case 2:
if (uiStep == 2)
{
DoScriptText(SAY_IMPRISIONED_BERYL_2, me);
uiStep = 3;
}
break;
case 3:
if (uiStep == 3)
{
break;
case 2:
DoScriptText(SAY_IMPRISIONED_BERYL_2, me, caster);
break;
case 3:
DoScriptText(SAY_IMPRISIONED_BERYL_3, me);
uiStep = 4;
}
break;
case 4:
if (uiStep == 4)
{
break;
case 4:
DoScriptText(SAY_IMPRISIONED_BERYL_4, me);
uiStep = 5;
}
break;
case 5:
if (uiStep == 5)
{
if (Player* pCaster = Unit::GetPlayer(*me, CasterGUID))
{
DoScriptText(SAY_IMPRISIONED_BERYL_5, me);
pCaster->KilledMonsterCredit(25478, 0);
uiStep = 6;
}
}
break;
case 6:
if (uiStep == 6)
{
DoScriptText(SAY_IMPRISIONED_BERYL_6, me);
uiStep = 7;
}
break;
case 7:
if (uiStep == 7)
{
break;
case 5:
DoScriptText(SAY_IMPRISIONED_BERYL_5, me);
break;
case 6:
DoScriptText(SAY_IMPRISIONED_BERYL_6, me, caster);
break;
case 7:
DoScriptText(SAY_IMPRISIONED_BERYL_7, me);
uiStep = 1;
uiPhase = 0;
}
break;
caster->KilledMonsterCredit(NPC_IMPRISONED_BERYL_SORCERER, 0);
break;
}
}
}
};

View File

@@ -1899,6 +1899,96 @@ class spell_unlocking_zuluheds_chains : public SpellScriptLoader
}
};
enum ShadowMoonTuberEnum
{
SPELL_WHISTLE = 36652,
SPELL_SHADOWMOON_TUBER = 36462,
NPC_BOAR_ENTRY = 21195,
GO_SHADOWMOON_TUBER_MOUND = 184701,
POINT_TUBER = 1,
TYPE_BOAR = 1,
DATA_BOAR = 1
};
class npc_shadowmoon_tuber_node : public CreatureScript
{
public:
npc_shadowmoon_tuber_node() : CreatureScript("npc_shadowmoon_tuber_node") {}
struct npc_shadowmoon_tuber_nodeAI : public ScriptedAI
{
npc_shadowmoon_tuber_nodeAI(Creature* creature) : ScriptedAI(creature) {}
void Reset()
{
tapped = false;
tuberGUID = 0;
resetTimer = 60000;
}
void SetData(uint32 id, uint32 data)
{
if (id == TYPE_BOAR && data == DATA_BOAR)
{
// Spawn chest GO
DoCast(SPELL_SHADOWMOON_TUBER);
// Despawn the tuber
if (GameObject* tuber = me->FindNearestGameObject(GO_SHADOWMOON_TUBER_MOUND, 5.0f))
{
tuberGUID = tuber->GetGUID();
// @Workaround: find how to properly despawn the GO
tuber->SetPhaseMask(2, true);
}
}
}
void SpellHit(Unit* /*caster*/, const SpellInfo* spell)
{
if (!tapped && spell->Id == SPELL_WHISTLE)
{
if (Creature* boar = me->FindNearestCreature(NPC_BOAR_ENTRY, 30.0f))
{
// Disable trigger and force nearest boar to walk to him
tapped = true;
boar->SetWalk(false);
boar->GetMotionMaster()->MovePoint(POINT_TUBER, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ());
}
}
}
void UpdateAI(const uint32 diff)
{
if (tapped)
{
if (resetTimer <= diff)
{
// Respawn the tuber
if (tuberGUID)
if (GameObject* tuber = GameObject::GetGameObject(*me, tuberGUID))
// @Workaround: find how to properly respawn the GO
tuber->SetPhaseMask(1, true);
Reset();
}
else
resetTimer -= diff;
}
}
private:
bool tapped;
uint64 tuberGUID;
uint32 resetTimer;
};
CreatureAI* GetAI(Creature* creature) const
{
return new npc_shadowmoon_tuber_nodeAI(creature);
}
};
void AddSC_shadowmoon_valley()
{
new mob_mature_netherwing_drake();
@@ -1917,4 +2007,5 @@ void AddSC_shadowmoon_valley()
new mob_torloth_the_magnificent();
new npc_enraged_spirit();
new spell_unlocking_zuluheds_chains();
new npc_shadowmoon_tuber_node();
}