EverWrath/src/scripts/Outland/zone_shadowmoon_valley.cpp
2016-08-17 17:58:45 +02:00

1755 lines
54 KiB
C++

/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license: http://github.com/azerothcore/azerothcore-wotlk/LICENSE-GPL2
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*/
/* ScriptData
SDName: Shadowmoon_Valley
SD%Complete: 100
SDComment: Quest support: 10519, 10583, 10601, 10804, 10854, 10458, 10481, 10480, 10781, 10451. Vendor Drake Dealer Hurlunk.
SDCategory: Shadowmoon Valley
EndScriptData */
/* ContentData
npc_mature_netherwing_drake
npc_enslaved_netherwing_drake
npc_drake_dealer_hurlunk
npcs_flanis_swiftwing_and_kagrosh
npc_karynaku
npc_oronok_tornheart
npc_earthmender_wilda
npc_torloth_the_magnificent
npc_illidari_spawn
npc_lord_illidan_stormrage
go_crystal_prison
npc_enraged_spirit
EndContentData */
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
#include "ScriptedEscortAI.h"
#include "Group.h"
#include "SpellScript.h"
#include "Player.h"
#include "WorldSession.h"
// Ours
class spell_q10612_10613_the_fel_and_the_furious : public SpellScriptLoader
{
public:
spell_q10612_10613_the_fel_and_the_furious() : SpellScriptLoader("spell_q10612_10613_the_fel_and_the_furious") { }
class spell_q10612_10613_the_fel_and_the_furious_SpellScript : public SpellScript
{
PrepareSpellScript(spell_q10612_10613_the_fel_and_the_furious_SpellScript);
void HandleScriptEffect(SpellEffIndex effIndex)
{
Player* charmer = GetCaster()->GetCharmerOrOwnerPlayerOrPlayerItself();
if (!charmer)
return;
std::list<GameObject*> gList;
GetCaster()->GetGameObjectListWithEntryInGrid(gList, 184979, 30.0f);
uint8 counter = 0;
for (std::list<GameObject*>::const_iterator itr = gList.begin(); itr != gList.end(); ++itr, ++counter)
{
if (counter >= 10)
break;
GameObject* go = *itr;
if (!go->isSpawned())
continue;
Creature* cr2 = go->SummonTrigger(go->GetPositionX(), go->GetPositionY(), go->GetPositionZ()+2.0f, 0.0f, 100);
if (cr2)
{
cr2->setFaction(14);
cr2->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
GetCaster()->CastSpell(cr2, 38083, true);
}
go->SetLootState(GO_JUST_DEACTIVATED);
charmer->KilledMonsterCredit(21959, 0);
}
}
void Register()
{
OnEffectHitTarget += SpellEffectFn(spell_q10612_10613_the_fel_and_the_furious_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
SpellScript* GetSpellScript() const
{
return new spell_q10612_10613_the_fel_and_the_furious_SpellScript();
}
};
class spell_q10563_q10596_to_legion_hold : public SpellScriptLoader
{
public:
spell_q10563_q10596_to_legion_hold() : SpellScriptLoader("spell_q10563_q10596_to_legion_hold") { }
class spell_q10563_q10596_to_legion_hold_AuraScript : public AuraScript
{
PrepareAuraScript(spell_q10563_q10596_to_legion_hold_AuraScript)
void HandleEffectRemove(AuraEffect const * /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Player* player = GetTarget()->ToPlayer())
{
player->KilledMonsterCredit(21502, 0);
player->SetControlled(false, UNIT_STATE_STUNNED);
}
}
void HandleEffectApply(AuraEffect const * /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Player* player = GetTarget()->ToPlayer())
{
player->SetControlled(true, UNIT_STATE_STUNNED);
player->SummonCreature(21633, -3311.13f, 2946.15f, 171.1f, 4.86f, TEMPSUMMON_TIMED_DESPAWN, 64000);
}
}
void Register()
{
OnEffectApply += AuraEffectApplyFn(spell_q10563_q10596_to_legion_hold_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_TRANSFORM, AURA_EFFECT_HANDLE_REAL);
OnEffectRemove += AuraEffectRemoveFn(spell_q10563_q10596_to_legion_hold_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_TRANSFORM, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const
{
return new spell_q10563_q10596_to_legion_hold_AuraScript();
}
};
// Theirs
/*#####
# npc_invis_infernal_caster
#####*/
enum InvisInfernalCaster
{
EVENT_CAST_SUMMON_INFERNAL = 1,
NPC_INFERNAL_ATTACKER = 21419,
MODEL_INVISIBLE = 20577,
MODEL_INFERNAL = 17312,
SPELL_SUMMON_INFERNAL = 37277,
TYPE_INFERNAL = 1,
DATA_DIED = 1
};
class npc_invis_infernal_caster : public CreatureScript
{
public:
npc_invis_infernal_caster() : CreatureScript("npc_invis_infernal_caster") { }
struct npc_invis_infernal_casterAI : public ScriptedAI
{
npc_invis_infernal_casterAI(Creature* creature) : ScriptedAI(creature)
{
ground = 0.f;
}
void Reset()
{
ground = me->GetMap()->GetHeight(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ());
SummonInfernal();
events.ScheduleEvent(EVENT_CAST_SUMMON_INFERNAL, urand(1000, 3000));
}
void SetData(uint32 id, uint32 data)
{
if (id == TYPE_INFERNAL && data == DATA_DIED)
SummonInfernal();
}
void SummonInfernal()
{
Creature* infernal = me->SummonCreature(NPC_INFERNAL_ATTACKER, me->GetPositionX(), me->GetPositionY(), ground + 0.05f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000);
infernalGUID = infernal->GetGUID();
}
void UpdateAI(uint32 diff)
{
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_CAST_SUMMON_INFERNAL:
{
if (Unit* infernal = ObjectAccessor::GetUnit(*me, infernalGUID))
if (infernal->GetDisplayId() == MODEL_INVISIBLE)
me->CastSpell(infernal, SPELL_SUMMON_INFERNAL, true);
events.ScheduleEvent(EVENT_CAST_SUMMON_INFERNAL, 12000);
break;
}
default:
break;
}
}
}
private:
EventMap events;
uint64 infernalGUID;
float ground;
};
CreatureAI* GetAI(Creature* creature) const
{
return new npc_invis_infernal_casterAI(creature);
}
};
/*#####
# npc_infernal_attacker
#####*/
class npc_infernal_attacker : public CreatureScript
{
public:
npc_infernal_attacker() : CreatureScript("npc_infernal_attacker") { }
struct npc_infernal_attackerAI : public ScriptedAI
{
npc_infernal_attackerAI(Creature* creature) : ScriptedAI(creature) { }
void Reset()
{
me->SetDisplayId(MODEL_INVISIBLE);
me->GetMotionMaster()->MoveRandom(5.0f);
}
void IsSummonedBy(Unit* summoner)
{
if (!summoner)
return;
if (summoner->ToCreature())
casterGUID = summoner->ToCreature()->GetGUID();;
}
void JustDied(Unit* /*killer*/)
{
if (Creature* caster = ObjectAccessor::GetCreature(*me, casterGUID))
caster->AI()->SetData(TYPE_INFERNAL, DATA_DIED);
}
void SpellHit(Unit* /*caster*/, const SpellInfo* spell)
{
if (spell->Id == SPELL_SUMMON_INFERNAL)
{
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_PACIFIED | UNIT_FLAG_NOT_SELECTABLE);
me->SetDisplayId(MODEL_INFERNAL);
}
}
void UpdateAI(uint32 diff)
{
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
private:
uint64 casterGUID;
};
CreatureAI* GetAI(Creature* creature) const
{
return new npc_infernal_attackerAI(creature);
}
};
/*#####
# npc_mature_netherwing_drake
#####*/
enum MatureNetherwing
{
SAY_JUST_EATEN = 0,
SPELL_PLACE_CARCASS = 38439,
SPELL_JUST_EATEN = 38502,
SPELL_NETHER_BREATH = 38467,
POINT_ID = 1,
GO_CARCASS = 185155,
QUEST_KINDNESS = 10804,
NPC_EVENT_PINGER = 22131
};
class npc_mature_netherwing_drake : public CreatureScript
{
public:
npc_mature_netherwing_drake() : CreatureScript("npc_mature_netherwing_drake") { }
CreatureAI* GetAI(Creature* creature) const
{
return new npc_mature_netherwing_drakeAI(creature);
}
struct npc_mature_netherwing_drakeAI : public ScriptedAI
{
npc_mature_netherwing_drakeAI(Creature* creature) : ScriptedAI(creature) { }
uint64 uiPlayerGUID;
bool bCanEat;
bool bIsEating;
uint32 EatTimer;
uint32 CastTimer;
void Reset()
{
uiPlayerGUID = 0;
bCanEat = false;
bIsEating = false;
EatTimer = 5000;
CastTimer = 5000;
}
void SpellHit(Unit* pCaster, SpellInfo const* spell)
{
if (bCanEat || bIsEating)
return;
if (pCaster->GetTypeId() == TYPEID_PLAYER && spell->Id == SPELL_PLACE_CARCASS && !me->HasAura(SPELL_JUST_EATEN))
{
uiPlayerGUID = pCaster->GetGUID();
bCanEat = true;
}
}
void MovementInform(uint32 type, uint32 id)
{
if (type != POINT_MOTION_TYPE)
return;
if (id == POINT_ID)
{
bIsEating = true;
EatTimer = 7000;
me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACK_UNARMED);
}
}
void UpdateAI(uint32 diff)
{
if (bCanEat || bIsEating)
{
if (EatTimer <= diff)
{
if (bCanEat && !bIsEating)
{
if (Unit* unit = ObjectAccessor::GetUnit(*me, uiPlayerGUID))
{
if (GameObject* go = unit->FindNearestGameObject(GO_CARCASS, 10))
{
if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
me->GetMotionMaster()->MovementExpired();
me->GetMotionMaster()->MoveIdle();
me->StopMoving();
me->GetMotionMaster()->MovePoint(POINT_ID, go->GetPositionX(), go->GetPositionY(), go->GetPositionZ());
}
}
bCanEat = false;
}
else if (bIsEating)
{
DoCast(me, SPELL_JUST_EATEN);
Talk(SAY_JUST_EATEN);
if (Player* player = ObjectAccessor::GetPlayer(*me, uiPlayerGUID))
{
player->KilledMonsterCredit(NPC_EVENT_PINGER, 0);
if (GameObject* go = player->FindNearestGameObject(GO_CARCASS, 10))
go->Delete();
}
Reset();
me->GetMotionMaster()->Clear();
}
}
else
EatTimer -= diff;
return;
}
if (!UpdateVictim())
return;
if (CastTimer <= diff)
{
DoCastVictim(SPELL_NETHER_BREATH);
CastTimer = 5000;
} else CastTimer -= diff;
DoMeleeAttackIfReady();
}
};
};
/*###
# npc_enslaved_netherwing_drake
####*/
enum EnshlavedNetherwingDrake
{
// Factions
FACTION_DEFAULT = 62,
FACTION_FRIENDLY = 1840, // Not sure if this is correct, it was taken off of Mordenai.
// Spells
SPELL_HIT_FORCE_OF_NELTHARAKU = 38762,
SPELL_FORCE_OF_NELTHARAKU = 38775,
// Creatures
NPC_DRAGONMAW_SUBJUGATOR = 21718,
NPC_ESCAPE_DUMMY = 22317
};
class npc_enslaved_netherwing_drake : public CreatureScript
{
public:
npc_enslaved_netherwing_drake() : CreatureScript("npc_enslaved_netherwing_drake") { }
CreatureAI* GetAI(Creature* creature) const
{
return new npc_enslaved_netherwing_drakeAI(creature);
}
struct npc_enslaved_netherwing_drakeAI : public ScriptedAI
{
npc_enslaved_netherwing_drakeAI(Creature* creature) : ScriptedAI(creature)
{
PlayerGUID = 0;
Tapped = false;
Reset();
}
uint64 PlayerGUID;
uint32 FlyTimer;
bool Tapped;
void Reset()
{
if (!Tapped)
me->setFaction(FACTION_DEFAULT);
FlyTimer = 10000;
me->SetDisableGravity(false);
me->SetVisible(true);
}
void SpellHit(Unit* caster, const SpellInfo* spell)
{
if (!caster)
return;
if (caster->GetTypeId() == TYPEID_PLAYER && spell->Id == SPELL_HIT_FORCE_OF_NELTHARAKU && !Tapped)
{
Tapped = true;
PlayerGUID = caster->GetGUID();
me->setFaction(FACTION_FRIENDLY);
DoCast(caster, SPELL_FORCE_OF_NELTHARAKU, true);
Unit* Dragonmaw = me->FindNearestCreature(NPC_DRAGONMAW_SUBJUGATOR, 50);
if (Dragonmaw)
{
me->AddThreat(Dragonmaw, 100000.0f);
AttackStart(Dragonmaw);
}
HostileReference* ref = me->getThreatManager().getOnlineContainer().getReferenceByTarget(caster);
if (ref)
ref->removeReference();
}
}
void MovementInform(uint32 type, uint32 id)
{
if (type != POINT_MOTION_TYPE)
return;
if (id == 1)
{
if (PlayerGUID)
{
Unit* player = ObjectAccessor::GetUnit(*me, PlayerGUID);
if (player)
DoCast(player, SPELL_FORCE_OF_NELTHARAKU, true);
PlayerGUID = 0;
}
me->SetVisible(false);
me->SetDisableGravity(false);
Unit::DealDamage(me, me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
me->RemoveCorpse();
}
}
void UpdateAI(uint32 diff)
{
if (!UpdateVictim())
{
if (Tapped)
{
if (FlyTimer <= diff)
{
Tapped = false;
if (PlayerGUID)
{
Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID);
if (player && player->GetQuestStatus(10854) == QUEST_STATUS_INCOMPLETE)
{
DoCast(player, SPELL_FORCE_OF_NELTHARAKU, true);
/*
float x, y, z;
me->GetPosition(x, y, z);
float dx, dy, dz;
me->GetRandomPoint(x, y, z, 20, dx, dy, dz);
dz += 20; // so it's in the air, not ground*/
Position pos;
if (Unit* EscapeDummy = me->FindNearestCreature(NPC_ESCAPE_DUMMY, 30))
EscapeDummy->GetPosition(&pos);
else
{
me->GetRandomNearPosition(pos, 20);
pos.m_positionZ += 25;
}
me->SetDisableGravity(true);
me->GetMotionMaster()->MovePoint(1, pos);
}
}
} else FlyTimer -= diff;
}
return;
}
DoMeleeAttackIfReady();
}
};
};
/*#####
# npc_dragonmaw_peon
#####*/
class npc_dragonmaw_peon : public CreatureScript
{
public:
npc_dragonmaw_peon() : CreatureScript("npc_dragonmaw_peon") { }
CreatureAI* GetAI(Creature* creature) const
{
return new npc_dragonmaw_peonAI(creature);
}
struct npc_dragonmaw_peonAI : public ScriptedAI
{
npc_dragonmaw_peonAI(Creature* creature) : ScriptedAI(creature) { }
uint64 PlayerGUID;
bool Tapped;
uint32 PoisonTimer;
void Reset()
{
PlayerGUID = 0;
Tapped = false;
PoisonTimer = 0;
}
void SpellHit(Unit* caster, const SpellInfo* spell)
{
if (!caster)
return;
if (caster->GetTypeId() == TYPEID_PLAYER && spell->Id == 40468 && !Tapped)
{
PlayerGUID = caster->GetGUID();
Tapped = true;
float x, y, z;
caster->GetClosePoint(x, y, z, me->GetObjectSize());
me->SetWalk(false);
me->GetMotionMaster()->MovePoint(1, x, y, z);
}
}
void MovementInform(uint32 type, uint32 id)
{
if (type != POINT_MOTION_TYPE)
return;
if (id)
{
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_EAT);
PoisonTimer = 15000;
}
}
void UpdateAI(uint32 diff)
{
if (PoisonTimer)
{
if (PoisonTimer <= diff)
{
if (PlayerGUID)
{
Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID);
if (player && player->GetQuestStatus(11020) == QUEST_STATUS_INCOMPLETE)
player->KilledMonsterCredit(23209, 0);
}
PoisonTimer = 0;
Unit::DealDamage(me, me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
} else PoisonTimer -= diff;
}
}
};
};
/*######
## npc_drake_dealer_hurlunk
######*/
class npc_drake_dealer_hurlunk : public CreatureScript
{
public:
npc_drake_dealer_hurlunk() : CreatureScript("npc_drake_dealer_hurlunk") { }
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
{
player->PlayerTalkClass->ClearMenus();
if (action == GOSSIP_ACTION_TRADE)
player->GetSession()->SendListInventory(creature->GetGUID());
return true;
}
bool OnGossipHello(Player* player, Creature* creature)
{
if (creature->IsVendor() && player->GetReputationRank(1015) == REP_EXALTED)
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
return true;
}
};
/*######
## npc_flanis_swiftwing_and_kagrosh
######*/
#define GOSSIP_HSK1 "Take Flanis's Pack"
#define GOSSIP_HSK2 "Take Kagrosh's Pack"
class npcs_flanis_swiftwing_and_kagrosh : public CreatureScript
{
public:
npcs_flanis_swiftwing_and_kagrosh() : CreatureScript("npcs_flanis_swiftwing_and_kagrosh") { }
bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action)
{
player->PlayerTalkClass->ClearMenus();
if (action == GOSSIP_ACTION_INFO_DEF+1)
{
ItemPosCountVec dest;
uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 30658, 1, NULL);
if (msg == EQUIP_ERR_OK)
{
player->StoreNewItem(dest, 30658, 1, true);
player->PlayerTalkClass->ClearMenus();
}
}
if (action == GOSSIP_ACTION_INFO_DEF+2)
{
ItemPosCountVec dest;
uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 30659, 1, NULL);
if (msg == EQUIP_ERR_OK)
{
player->StoreNewItem(dest, 30659, 1, true);
player->PlayerTalkClass->ClearMenus();
}
}
return true;
}
bool OnGossipHello(Player* player, Creature* creature)
{
if (player->GetQuestStatus(10583) == QUEST_STATUS_INCOMPLETE && !player->HasItemCount(30658, 1, true))
player->ADD_GOSSIP_ITEM(0, GOSSIP_HSK1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
if (player->GetQuestStatus(10601) == QUEST_STATUS_INCOMPLETE && !player->HasItemCount(30659, 1, true))
player->ADD_GOSSIP_ITEM(0, GOSSIP_HSK2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
return true;
}
};
/*####
# npc_karynaku
####*/
enum Karynaku
{
QUEST_ALLY_OF_NETHER = 10870,
QUEST_ZUHULED_THE_WACK = 10866,
NPC_ZUHULED_THE_WACKED = 11980,
TAXI_PATH_ID = 649,
};
class npc_karynaku : public CreatureScript
{
public:
npc_karynaku() : CreatureScript("npc_karynaku") { }
bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest)
{
if (quest->GetQuestId() == QUEST_ALLY_OF_NETHER)
player->ActivateTaxiPathTo(TAXI_PATH_ID);
if (quest->GetQuestId() == QUEST_ZUHULED_THE_WACK)
creature->SummonCreature(NPC_ZUHULED_THE_WACKED, -4204.94f, 316.397f, 122.508f, 1.309f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 300000);
return true;
}
};
/*####
# npc_earthmender_wilda
####*/
enum Earthmender
{
SAY_WIL_START = 0,
SAY_WIL_AGGRO = 1,
SAY_WIL_PROGRESS1 = 2,
SAY_WIL_PROGRESS2 = 3,
SAY_WIL_FIND_EXIT = 4,
SAY_WIL_JUST_AHEAD = 5,
SAY_WIL_END = 6,
SPELL_CHAIN_LIGHTNING = 16006,
SPELL_EARTHBING_TOTEM = 15786,
SPELL_FROST_SHOCK = 12548,
SPELL_HEALING_WAVE = 12491,
QUEST_ESCAPE_COILSCAR = 10451,
NPC_COILSKAR_ASSASSIN = 21044,
FACTION_EARTHEN = 1726 //guessed
};
class npc_earthmender_wilda : public CreatureScript
{
public:
npc_earthmender_wilda() : CreatureScript("npc_earthmender_wilda") { }
bool OnQuestAccept(Player* player, Creature* creature, const Quest* quest)
{
if (quest->GetQuestId() == QUEST_ESCAPE_COILSCAR)
{
creature->AI()->Talk(SAY_WIL_START, player);
creature->setFaction(FACTION_EARTHEN);
if (npc_earthmender_wildaAI* pEscortAI = CAST_AI(npc_earthmender_wilda::npc_earthmender_wildaAI, creature->AI()))
pEscortAI->Start(false, false, player->GetGUID(), quest);
}
return true;
}
CreatureAI* GetAI(Creature* creature) const
{
return new npc_earthmender_wildaAI(creature);
}
struct npc_earthmender_wildaAI : public npc_escortAI
{
npc_earthmender_wildaAI(Creature* creature) : npc_escortAI(creature) { }
uint32 m_uiHealingTimer;
void Reset()
{
m_uiHealingTimer = 0;
}
void WaypointReached(uint32 waypointId)
{
Player* player = GetPlayerForEscort();
if (!player)
return;
switch (waypointId)
{
case 13:
Talk(SAY_WIL_PROGRESS1, player);
DoSpawnAssassin();
break;
case 14:
DoSpawnAssassin();
break;
case 15:
Talk(SAY_WIL_FIND_EXIT, player);
break;
case 19:
DoRandomSay();
break;
case 20:
DoSpawnAssassin();
break;
case 26:
DoRandomSay();
break;
case 27:
DoSpawnAssassin();
break;
case 33:
DoRandomSay();
break;
case 34:
DoSpawnAssassin();
break;
case 37:
DoRandomSay();
break;
case 38:
DoSpawnAssassin();
break;
case 39:
Talk(SAY_WIL_JUST_AHEAD, player);
break;
case 43:
DoRandomSay();
break;
case 44:
DoSpawnAssassin();
break;
case 50:
Talk(SAY_WIL_END, player);
player->GroupEventHappens(QUEST_ESCAPE_COILSCAR, me);
break;
}
}
void JustSummoned(Creature* summoned)
{
if (summoned->GetEntry() == NPC_COILSKAR_ASSASSIN)
summoned->AI()->AttackStart(me);
}
//this is very unclear, random say without no real relevance to script/event
void DoRandomSay()
{
Talk(SAY_WIL_PROGRESS2);
}
void DoSpawnAssassin()
{
//unknown where they actually appear
DoSummon(NPC_COILSKAR_ASSASSIN, me, 15.0f, 5000, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT);
}
void EnterCombat(Unit* who)
{
//don't always use
if (rand()%5)
return;
//only aggro text if not player
if (who->GetTypeId() != TYPEID_PLAYER)
{
//appears to be random
if (urand(0, 1))
Talk(SAY_WIL_AGGRO);
}
}
void UpdateAI(uint32 uiDiff)
{
npc_escortAI::UpdateAI(uiDiff);
if (!UpdateVictim())
return;
/// @todo add more abilities
if (!HealthAbovePct(30))
{
if (m_uiHealingTimer <= uiDiff)
{
DoCast(me, SPELL_HEALING_WAVE);
m_uiHealingTimer = 15000;
}
else
m_uiHealingTimer -= uiDiff;
}
}
};
};
/*#####
# Quest: Battle of the crimson watch
#####*/
/* ContentData
Battle of the crimson watch - creatures, gameobjects and defines
npc_illidari_spawn : Adds that are summoned in the Crimson Watch battle.
npc_torloth_the_magnificent : Final Creature that players have to face before quest is completed
npc_lord_illidan_stormrage : Creature that controls the event.
go_crystal_prison : GameObject that begins the event and hands out quest
EndContentData */
#define QUEST_BATTLE_OF_THE_CRIMSON_WATCH 10781
#define EVENT_AREA_RADIUS 65 //65yds
#define EVENT_COOLDOWN 30000 //in ms. appear after event completed or failed (should be = Adds despawn time)
struct TorlothCinematic
{
uint32 creature, Timer;
};
// Creature 0 - Torloth, 1 - Illidan
static TorlothCinematic TorlothAnim[]=
{
{0, 2000},
{1, 7000},
{0, 3000},
{0, 2000}, // Torloth stand
{0, 1000},
{0, 3000},
{0, 0}
};
struct Location
{
float x, y, z, o;
};
//Cordinates for Spawns
static Location SpawnLocation[]=
{
//Cords used for:
{-4615.8556f, 1342.2532f, 139.9f, 1.612f}, //Illidari Soldier
{-4598.9365f, 1377.3182f, 139.9f, 3.917f}, //Illidari Soldier
{-4598.4697f, 1360.8999f, 139.9f, 2.427f}, //Illidari Soldier
{-4589.3599f, 1369.1061f, 139.9f, 3.165f}, //Illidari Soldier
{-4608.3477f, 1386.0076f, 139.9f, 4.108f}, //Illidari Soldier
{-4633.1889f, 1359.8033f, 139.9f, 0.949f}, //Illidari Soldier
{-4623.5791f, 1351.4574f, 139.9f, 0.971f}, //Illidari Soldier
{-4607.2988f, 1351.6099f, 139.9f, 2.416f}, //Illidari Soldier
{-4633.7764f, 1376.0417f, 139.9f, 5.608f}, //Illidari Soldier
{-4600.2461f, 1369.1240f, 139.9f, 3.056f}, //Illidari Mind Breaker
{-4631.7808f, 1367.9459f, 139.9f, 0.020f}, //Illidari Mind Breaker
{-4600.2461f, 1369.1240f, 139.9f, 3.056f}, //Illidari Highlord
{-4631.7808f, 1367.9459f, 139.9f, 0.020f}, //Illidari Highlord
{-4615.5586f, 1353.0031f, 139.9f, 1.540f}, //Illidari Highlord
{-4616.4736f, 1384.2170f, 139.9f, 4.971f}, //Illidari Highlord
{-4627.1240f, 1378.8752f, 139.9f, 2.544f} //Torloth The Magnificent
};
struct WaveData
{
uint8 SpawnCount, UsedSpawnPoint;
uint32 CreatureId, SpawnTimer, YellTimer;
};
static WaveData WavesInfo[]=
{
{9, 0, 22075, 10000, 7000}, //Illidari Soldier
{2, 9, 22074, 10000, 7000}, //Illidari Mind Breaker
{4, 11, 19797, 10000, 7000}, //Illidari Highlord
{1, 15, 22076, 10000, 7000} //Torloth The Magnificent
};
struct SpawnSpells
{
uint32 Timer1, Timer2, SpellId;
};
static SpawnSpells SpawnCast[]=
{
{10000, 15000, 35871}, // Illidari Soldier Cast - Spellbreaker
{10000, 10000, 38985}, // Illidari Mind Breake Cast - Focused Bursts
{35000, 35000, 22884}, // Illidari Mind Breake Cast - Psychic Scream
{20000, 20000, 17194}, // Illidari Mind Breake Cast - Mind Blast
{8000, 15000, 38010}, // Illidari Highlord Cast - Curse of Flames
{12000, 20000, 16102}, // Illidari Highlord Cast - Flamestrike
{10000, 15000, 15284}, // Torloth the Magnificent Cast - Cleave
{18000, 20000, 39082}, // Torloth the Magnificent Cast - Shadowfury
{25000, 28000, 33961} // Torloth the Magnificent Cast - Spell Reflection
};
/*######
# npc_torloth_the_magnificent
#####*/
class npc_torloth_the_magnificent : public CreatureScript
{
public:
npc_torloth_the_magnificent() : CreatureScript("npc_torloth_the_magnificent") { }
CreatureAI* GetAI(Creature* c) const
{
return new npc_torloth_the_magnificentAI(c);
}
struct npc_torloth_the_magnificentAI : public ScriptedAI
{
npc_torloth_the_magnificentAI(Creature* creature) : ScriptedAI(creature) { }
uint32 AnimationTimer, SpellTimer1, SpellTimer2, SpellTimer3;
uint8 AnimationCount;
uint64 LordIllidanGUID;
uint64 AggroTargetGUID;
bool Timers;
void Reset()
{
AnimationTimer = 4000;
AnimationCount = 0;
LordIllidanGUID = 0;
AggroTargetGUID = 0;
Timers = false;
me->AddUnitState(UNIT_STATE_ROOT);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->SetTarget(0);
}
void EnterCombat(Unit* /*who*/) { }
void HandleAnimation()
{
Creature* creature = me;
if (TorlothAnim[AnimationCount].creature == 1)
{
creature = (ObjectAccessor::GetCreature(*me, LordIllidanGUID));
if (!creature)
return;
}
AnimationTimer = TorlothAnim[AnimationCount].Timer;
switch (AnimationCount)
{
case 0:
me->SetUInt32Value(UNIT_FIELD_BYTES_1, 8);
break;
case 3:
me->RemoveFlag(UNIT_FIELD_BYTES_1, 8);
break;
case 5:
if (Player* AggroTarget = ObjectAccessor::GetPlayer(*me, AggroTargetGUID))
{
me->SetTarget(AggroTarget->GetGUID());
me->AddThreat(AggroTarget, 1);
me->HandleEmoteCommand(EMOTE_ONESHOT_POINT);
}
break;
case 6:
if (Player* AggroTarget = ObjectAccessor::GetPlayer(*me, AggroTargetGUID))
{
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->ClearUnitState(UNIT_STATE_ROOT);
float x, y, z;
AggroTarget->GetPosition(x, y, z);
me->GetMotionMaster()->MovePoint(0, x, y, z);
}
break;
}
++AnimationCount;
}
void UpdateAI(uint32 diff)
{
if (AnimationTimer)
{
if (AnimationTimer <= diff)
{
HandleAnimation();
} else AnimationTimer -= diff;
}
if (AnimationCount < 6)
{
me->CombatStop();
} else if (!Timers)
{
SpellTimer1 = SpawnCast[6].Timer1;
SpellTimer2 = SpawnCast[7].Timer1;
SpellTimer3 = SpawnCast[8].Timer1;
Timers = true;
}
if (Timers)
{
if (SpellTimer1 <= diff)
{
DoCastVictim(SpawnCast[6].SpellId);//Cleave
SpellTimer1 = SpawnCast[6].Timer2 + (rand()%10 * 1000);
} else SpellTimer1 -= diff;
if (SpellTimer2 <= diff)
{
DoCastVictim(SpawnCast[7].SpellId);//Shadowfury
SpellTimer2 = SpawnCast[7].Timer2 + (rand()%5 * 1000);
} else SpellTimer2 -= diff;
if (SpellTimer3 <= diff)
{
DoCast(me, SpawnCast[8].SpellId);
SpellTimer3 = SpawnCast[8].Timer2 + (rand()%7 * 1000);//Spell Reflection
} else SpellTimer3 -= diff;
}
DoMeleeAttackIfReady();
}
void JustDied(Unit* killer)
{
switch (killer->GetTypeId())
{
case TYPEID_UNIT:
if (Unit* owner = killer->GetOwner())
if (Player* player = owner->ToPlayer())
player->GroupEventHappens(QUEST_BATTLE_OF_THE_CRIMSON_WATCH, me);
break;
case TYPEID_PLAYER:
if (Player* player = killer->ToPlayer())
player->GroupEventHappens(QUEST_BATTLE_OF_THE_CRIMSON_WATCH, me);
break;
default:
break;
}
if (Creature* LordIllidan = (ObjectAccessor::GetCreature(*me, LordIllidanGUID)))
LordIllidan->AI()->EnterEvadeMode();
}
};
};
/*#####
# npc_lord_illidan_stormrage
#####*/
class npc_lord_illidan_stormrage : public CreatureScript
{
public:
npc_lord_illidan_stormrage() : CreatureScript("npc_lord_illidan_stormrage") { }
CreatureAI* GetAI(Creature* c) const
{
return new npc_lord_illidan_stormrageAI(c);
}
struct npc_lord_illidan_stormrageAI : public ScriptedAI
{
npc_lord_illidan_stormrageAI(Creature* creature) : ScriptedAI(creature) { }
uint64 PlayerGUID;
uint32 WaveTimer;
uint32 AnnounceTimer;
int8 LiveCount;
uint8 WaveCount;
bool EventStarted;
bool Announced;
bool Failed;
void Reset()
{
PlayerGUID = 0;
WaveTimer = 10000;
AnnounceTimer = 7000;
LiveCount = 0;
WaveCount = 0;
EventStarted = false;
Announced = false;
Failed = false;
me->SetVisible(false);
}
void EnterCombat(Unit* /*who*/) { }
void MoveInLineOfSight(Unit* /*who*/) { }
void AttackStart(Unit* /*who*/) { }
void SummonNextWave();
void CheckEventFail()
{
Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID);
if (!player)
{
Failed = true;
return;
}
if (Group* EventGroup = player->GetGroup())
{
uint8 GroupMemberCount = 0;
uint8 DeadMemberCount = 0;
uint8 FailedMemberCount = 0;
Group::MemberSlotList const& members = EventGroup->GetMemberSlots();
for (Group::member_citerator itr = members.begin(); itr!= members.end(); ++itr)
{
Player* GroupMember = ObjectAccessor::GetPlayer(*me, itr->guid);
if (!GroupMember)
continue;
if (!GroupMember->IsWithinDistInMap(me, EVENT_AREA_RADIUS) && GroupMember->GetQuestStatus(QUEST_BATTLE_OF_THE_CRIMSON_WATCH) == QUEST_STATUS_INCOMPLETE)
{
GroupMember->FailQuest(QUEST_BATTLE_OF_THE_CRIMSON_WATCH);
++FailedMemberCount;
}
++GroupMemberCount;
if (GroupMember->isDead())
++DeadMemberCount;
}
if (GroupMemberCount == FailedMemberCount)
{
Failed = true;
}
if (GroupMemberCount == DeadMemberCount)
{
for (Group::member_citerator itr = members.begin(); itr!= members.end(); ++itr)
{
if (Player* groupMember = ObjectAccessor::GetPlayer(*me, itr->guid))
if (groupMember->GetQuestStatus(QUEST_BATTLE_OF_THE_CRIMSON_WATCH) == QUEST_STATUS_INCOMPLETE)
groupMember->FailQuest(QUEST_BATTLE_OF_THE_CRIMSON_WATCH);
}
Failed = true;
}
} else if (player->isDead() || !player->IsWithinDistInMap(me, EVENT_AREA_RADIUS))
{
player->FailQuest(QUEST_BATTLE_OF_THE_CRIMSON_WATCH);
Failed = true;
}
}
void LiveCounter()
{
--LiveCount;
if (!LiveCount)
Announced = false;
}
void UpdateAI(uint32 diff)
{
if (!PlayerGUID || !EventStarted)
return;
if (!LiveCount && WaveCount < 4)
{
if (!Announced && AnnounceTimer <= diff)
{
Announced = true;
}
else
AnnounceTimer -= diff;
if (WaveTimer <= diff)
{
SummonNextWave();
}
else
WaveTimer -= diff;
}
CheckEventFail();
if (Failed)
EnterEvadeMode();
}
};
};
/*######
# npc_illidari_spawn
######*/
class npc_illidari_spawn : public CreatureScript
{
public:
npc_illidari_spawn() : CreatureScript("npc_illidari_spawn") { }
CreatureAI* GetAI(Creature* c) const
{
return new npc_illidari_spawnAI(c);
}
struct npc_illidari_spawnAI : public ScriptedAI
{
npc_illidari_spawnAI(Creature* creature) : ScriptedAI(creature) { }
uint64 LordIllidanGUID;
uint32 SpellTimer1, SpellTimer2, SpellTimer3;
bool Timers;
void Reset()
{
LordIllidanGUID = 0;
Timers = false;
}
void EnterCombat(Unit* /*who*/) { }
void JustDied(Unit* /*killer*/)
{
me->RemoveCorpse();
if (Creature* LordIllidan = (ObjectAccessor::GetCreature(*me, LordIllidanGUID)))
if (LordIllidan)
CAST_AI(npc_lord_illidan_stormrage::npc_lord_illidan_stormrageAI, LordIllidan->AI())->LiveCounter();
}
void UpdateAI(uint32 diff)
{
if (!UpdateVictim())
return;
if (!Timers)
{
if (me->GetEntry() == 22075)//Illidari Soldier
{
SpellTimer1 = SpawnCast[0].Timer1 + (rand()%4 * 1000);
}
if (me->GetEntry() == 22074)//Illidari Mind Breaker
{
SpellTimer1 = SpawnCast[1].Timer1 + (rand()%10 * 1000);
SpellTimer2 = SpawnCast[2].Timer1 + (rand()%4 * 1000);
SpellTimer3 = SpawnCast[3].Timer1 + (rand()%4 * 1000);
}
if (me->GetEntry() == 19797)// Illidari Highlord
{
SpellTimer1 = SpawnCast[4].Timer1 + (rand()%4 * 1000);
SpellTimer2 = SpawnCast[5].Timer1 + (rand()%4 * 1000);
}
Timers = true;
}
//Illidari Soldier
if (me->GetEntry() == 22075)
{
if (SpellTimer1 <= diff)
{
DoCastVictim(SpawnCast[0].SpellId);//Spellbreaker
SpellTimer1 = SpawnCast[0].Timer2 + (rand()%5 * 1000);
} else SpellTimer1 -= diff;
}
//Illidari Mind Breaker
if (me->GetEntry() == 22074)
{
if (SpellTimer1 <= diff)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
if (target->GetTypeId() == TYPEID_PLAYER)
{
DoCast(target, SpawnCast[1].SpellId); //Focused Bursts
SpellTimer1 = SpawnCast[1].Timer2 + (rand()%5 * 1000);
} else SpellTimer1 = 2000;
}
} else SpellTimer1 -= diff;
if (SpellTimer2 <= diff)
{
DoCastVictim(SpawnCast[2].SpellId);//Psychic Scream
SpellTimer2 = SpawnCast[2].Timer2 + (rand()%13 * 1000);
} else SpellTimer2 -= diff;
if (SpellTimer3 <= diff)
{
DoCastVictim(SpawnCast[3].SpellId);//Mind Blast
SpellTimer3 = SpawnCast[3].Timer2 + (rand()%8 * 1000);
} else SpellTimer3 -= diff;
}
//Illidari Highlord
if (me->GetEntry() == 19797)
{
if (SpellTimer1 <= diff)
{
DoCastVictim(SpawnCast[4].SpellId);//Curse Of Flames
SpellTimer1 = SpawnCast[4].Timer2 + (rand()%10 * 1000);
} else SpellTimer1 -= diff;
if (SpellTimer2 <= diff)
{
DoCastVictim(SpawnCast[5].SpellId);//Flamestrike
SpellTimer2 = SpawnCast[5].Timer2 + (rand()%7 * 13000);
} else SpellTimer2 -= diff;
}
DoMeleeAttackIfReady();
}
};
};
void npc_lord_illidan_stormrage::npc_lord_illidan_stormrageAI::SummonNextWave()
{
uint8 count = WavesInfo[WaveCount].SpawnCount;
uint8 locIndex = WavesInfo[WaveCount].UsedSpawnPoint;
uint8 FelguardCount = 0;
uint8 DreadlordCount = 0;
for (uint8 i = 0; i < count; ++i)
{
Creature* Spawn = NULL;
float X = SpawnLocation[locIndex + i].x;
float Y = SpawnLocation[locIndex + i].y;
float Z = SpawnLocation[locIndex + i].z;
float O = SpawnLocation[locIndex + i].o;
Spawn = me->SummonCreature(WavesInfo[WaveCount].CreatureId, X, Y, Z, O, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000);
++LiveCount;
if (Spawn)
{
if (WaveCount == 0)//1 Wave
{
if (rand()%3 == 1 && FelguardCount<2)
{
Spawn->SetDisplayId(18654);
++FelguardCount;
}
else if (DreadlordCount < 3)
{
Spawn->SetDisplayId(19991);
++DreadlordCount;
}
else if (FelguardCount<2)
{
Spawn->SetDisplayId(18654);
++FelguardCount;
}
}
if (WaveCount < 3)//1-3 Wave
{
if (PlayerGUID)
{
if (Player* target = ObjectAccessor::GetPlayer(*me, PlayerGUID))
{
float x, y, z;
target->GetPosition(x, y, z);
Spawn->GetMotionMaster()->MovePoint(0, x, y, z);
}
}
CAST_AI(npc_illidari_spawn::npc_illidari_spawnAI, Spawn->AI())->LordIllidanGUID = me->GetGUID();
}
if (WavesInfo[WaveCount].CreatureId == 22076) // Torloth
{
CAST_AI(npc_torloth_the_magnificent::npc_torloth_the_magnificentAI, Spawn->AI())->LordIllidanGUID = me->GetGUID();
if (PlayerGUID)
CAST_AI(npc_torloth_the_magnificent::npc_torloth_the_magnificentAI, Spawn->AI())->AggroTargetGUID = PlayerGUID;
}
}
}
++WaveCount;
WaveTimer = WavesInfo[WaveCount].SpawnTimer;
AnnounceTimer = WavesInfo[WaveCount].YellTimer;
}
/*#####
# go_crystal_prison
######*/
class go_crystal_prison : public GameObjectScript
{
public:
go_crystal_prison() : GameObjectScript("go_crystal_prison") { }
bool OnQuestAccept(Player* player, GameObject* /*go*/, Quest const* quest)
{
if (quest->GetQuestId() == QUEST_BATTLE_OF_THE_CRIMSON_WATCH)
{
Creature* Illidan = player->FindNearestCreature(22083, 50);
if (Illidan && !CAST_AI(npc_lord_illidan_stormrage::npc_lord_illidan_stormrageAI, Illidan->AI())->EventStarted)
{
CAST_AI(npc_lord_illidan_stormrage::npc_lord_illidan_stormrageAI, Illidan->AI())->PlayerGUID = player->GetGUID();
CAST_AI(npc_lord_illidan_stormrage::npc_lord_illidan_stormrageAI, Illidan->AI())->LiveCount = 0;
CAST_AI(npc_lord_illidan_stormrage::npc_lord_illidan_stormrageAI, Illidan->AI())->EventStarted=true;
}
}
return true;
}
};
/*####
# npc_enraged_spirits
####*/
enum Enraged_Dpirits
{
// QUESTS
QUEST_ENRAGED_SPIRITS_FIRE_EARTH = 10458,
QUEST_ENRAGED_SPIRITS_AIR = 10481,
QUEST_ENRAGED_SPIRITS_WATER = 10480,
// Totem
ENTRY_TOTEM_OF_SPIRITS = 21071,
RADIUS_TOTEM_OF_SPIRITS = 15,
// SPIRITS
NPC_ENRAGED_EARTH_SPIRIT = 21050,
NPC_ENRAGED_FIRE_SPIRIT = 21061,
NPC_ENRAGED_AIR_SPIRIT = 21060,
NPC_ENRAGED_WATER_SPIRIT = 21059,
// SOULS
NPC_EARTHEN_SOUL = 21073,
NPC_FIERY_SOUL = 21097,
NPC_ENRAGED_AIRY_SOUL = 21116,
NPC_ENRAGED_WATERY_SOUL = 21109, // wrong model
// SPELL KILLCREDIT - not working!?! - using KilledMonsterCredit
SPELL_EARTHEN_SOUL_CAPTURED_CREDIT = 36108,
SPELL_FIERY_SOUL_CAPTURED_CREDIT = 36117,
SPELL_AIRY_SOUL_CAPTURED_CREDIT = 36182,
SPELL_WATERY_SOUL_CAPTURED_CREDIT = 36171,
// KilledMonsterCredit Workaround
NPC_CREDIT_FIRE = 21094,
NPC_CREDIT_WATER = 21095,
NPC_CREDIT_AIR = 21096,
NPC_CREDIT_EARTH = 21092,
// Captured Spell / Buff
SPELL_SOUL_CAPTURED = 36115,
// Factions
FACTION_ENRAGED_SOUL_FRIENDLY = 35,
FACTION_ENRAGED_SOUL_HOSTILE = 14
};
class npc_enraged_spirit : public CreatureScript
{
public:
npc_enraged_spirit() : CreatureScript("npc_enraged_spirit") { }
CreatureAI* GetAI(Creature* creature) const
{
return new npc_enraged_spiritAI(creature);
}
struct npc_enraged_spiritAI : public ScriptedAI
{
npc_enraged_spiritAI(Creature* creature) : ScriptedAI(creature) { }
void Reset() { }
void EnterCombat(Unit* /*who*/) { }
void JustDied(Unit* /*killer*/)
{
// always spawn spirit on death
// if totem around
// move spirit to totem and cast kill count
uint32 entry = 0;
uint32 credit = 0;
switch (me->GetEntry())
{
case NPC_ENRAGED_FIRE_SPIRIT:
entry = NPC_FIERY_SOUL;
//credit = SPELL_FIERY_SOUL_CAPTURED_CREDIT;
credit = NPC_CREDIT_FIRE;
break;
case NPC_ENRAGED_EARTH_SPIRIT:
entry = NPC_EARTHEN_SOUL;
//credit = SPELL_EARTHEN_SOUL_CAPTURED_CREDIT;
credit = NPC_CREDIT_EARTH;
break;
case NPC_ENRAGED_AIR_SPIRIT:
entry = NPC_ENRAGED_AIRY_SOUL;
//credit = SPELL_AIRY_SOUL_CAPTURED_CREDIT;
credit = NPC_CREDIT_AIR;
break;
case NPC_ENRAGED_WATER_SPIRIT:
entry = NPC_ENRAGED_WATERY_SOUL;
//credit = SPELL_WATERY_SOUL_CAPTURED_CREDIT;
credit = NPC_CREDIT_WATER;
break;
default:
break;
}
// Spawn Soul on Kill ALWAYS!
Creature* Summoned = NULL;
Unit* totemOspirits = NULL;
if (entry != 0)
Summoned = DoSpawnCreature(entry, 0, 0, 1, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 5000);
// FIND TOTEM, PROCESS QUEST
if (Summoned)
{
totemOspirits = me->FindNearestCreature(ENTRY_TOTEM_OF_SPIRITS, RADIUS_TOTEM_OF_SPIRITS);
if (totemOspirits)
{
Summoned->setFaction(FACTION_ENRAGED_SOUL_FRIENDLY);
Summoned->GetMotionMaster()->MovePoint(0, totemOspirits->GetPositionX(), totemOspirits->GetPositionY(), Summoned->GetPositionZ());
if (Unit* owner = totemOspirits->GetOwner())
if (Player* player = owner->ToPlayer())
player->KilledMonsterCredit(credit, 0);
DoCast(totemOspirits, SPELL_SOUL_CAPTURED);
}
}
}
};
};
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(uint32 diff)
{
if (tapped)
{
if (resetTimer <= diff)
{
// Respawn the tuber
if (tuberGUID)
if (GameObject* tuber = ObjectAccessor::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()
{
// Ours
new spell_q10612_10613_the_fel_and_the_furious();
new spell_q10563_q10596_to_legion_hold();
// Theirs
new npc_invis_infernal_caster();
new npc_infernal_attacker();
new npc_mature_netherwing_drake();
new npc_enslaved_netherwing_drake();
new npc_dragonmaw_peon();
new npc_drake_dealer_hurlunk();
new npcs_flanis_swiftwing_and_kagrosh();
new npc_karynaku();
new npc_earthmender_wilda();
new npc_lord_illidan_stormrage();
new go_crystal_prison();
new npc_illidari_spawn();
new npc_torloth_the_magnificent();
new npc_enraged_spirit();
new npc_shadowmoon_tuber_node();
}