/* Copyright (C) 2006,2007 ScriptDev2 * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "../../../sc_defines.h" #include "../../../../../../game/Player.h" #include "../../../../../../game/Group.h" #include "../../../../../../game/GossipDef.h" #define GOSSIP_ITEM_BEGIN "We are ready to defend the Alliance base." #define GOSSIP_ITEM_ANETHERON "The defenses are holding up; we can continue." #define GOSSIP_ITEM_RETREAT "We can't keep this up. It's time to retreat." // Trash Mobs summoned in waves #define NECROMANCER 17899 #define ABOMINATION 17898 #define GHOUL 17895 #define BANSHEE 17905 #define CRYPT_FIEND 17897 #define GARGOYLE 17906 #define FROST_WYRM 17907 #define GIANT_INFERNAL 17908 #define FEL_STALKER 17916 // Bosses summoned after every 8 waves #define RAGE_WINTERCHILL 17767 #define ANETHERON 17808 #define KAZROGAL 17888 #define AZGALOR 17842 #define ARCHIMONDE 17968 #define HORDEBASE_X 5464.5522 #define HORDEBASE_Y -2731.5644 #define HORDEBASE_Z 1485.7075 #define SPELL_TELEPORT_VISUAL 41232 struct Wave { uint32 Mob1, Mob2, Mob3, Mob4, Mob5, Mob6, Mob7, Mob8, Mob9, Mob10, Mob11, Mob12, Mob13, Mob14, Mob15, Mob16, Mob17, Mob18; uint32 WaveTimer; bool IsBoss; }; static Wave AllianceWaves[]= { {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, 0, 0, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 1 {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 2 {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 3 {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 4 {GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 5 {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 120000, false}, // Wave 6 {GHOUL, GHOUL, GHOUL, GHOUL, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 7 {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 120000, false}, // Wave 8 {RAGE_WINTERCHILL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true}, // All 8 Waves are summoned, summon Rage Winterchill, next few waves are for Anetheron {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, 0, 0, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 1 {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 2 {GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 3 {GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 4 {CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, BANSHEE, BANSHEE, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 5 {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 6 {CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, BANSHEE, BANSHEE, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false}, // Wave 7 {GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, // Wave 8 {ANETHERON, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true} // All 8 Waves are summoned, summon Anatheron }; struct Location { float x, y, z; }; static Location AllianceBase[]= { {4979.010, -1709.134, 1339.674}, {4969.123, -1705.904, 1341.363}, {4970.260, -1698.546, 1341.200}, {4975.262, -1698.239, 1341.427} }; struct MANGOS_DLL_DECL npc_jaina_proudmooreAI : public ScriptedAI { npc_jaina_proudmooreAI(Creature *c) : ScriptedAI(c) { pInstance = ((ScriptedInstance*)c->GetInstanceData()); SetVariables(); } ScriptedInstance* pInstance; uint64 PlayerGUID; uint64 WinterchillGUID; uint64 AnetheronGUID; uint32 NextWaveTimer; uint32 WaveCount; uint32 CheckTimer; bool EventBegun; bool AllianceOverrun; bool InCombat; bool RageWinterchillDead; bool AnetheronDead; void SetVariables() { PlayerGUID = 0; WinterchillGUID = 0; AnetheronGUID = 0; NextWaveTimer = 30000; WaveCount = 0; CheckTimer = 0; EventBegun = false; AllianceOverrun = false; InCombat = false; RageWinterchillDead = false; AnetheronDead = false; } void EnterEvadeMode() { SetVariables(); m_creature->RemoveAllAuras(); m_creature->DeleteThreatList(); m_creature->CombatStop(); DoGoHome(); } void AttackStart(Unit *who) { if(!who) return; if(who->isTargetableForAttack() && who!= m_creature) { DoStartMeleeAttack(who); if(!InCombat) { InCombat = true; } } } void MoveInLineOfSight(Unit *who) { if(who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) { float attackRadius = m_creature->GetAttackDistance(who); if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) { if(who->HasStealthAura()) who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); if(who && who->isAlive()) m_creature->AddThreat(who, 1.0f); if(!InCombat) { InCombat = true; } } } } void SummonCreature(uint32 entry, bool IsBoss = true) { uint32 random = rand()%4; float X = AllianceBase[random].x; float Y = AllianceBase[random].y; float Z = AllianceBase[random].z; Creature* pCreature = m_creature->SummonCreature(entry, X, Y, Z, 0, TEMPSUMMON_DEAD_DESPAWN, 0); if(pCreature) { if(PlayerGUID) { Unit* pUnit = Unit::GetUnit((*m_creature), PlayerGUID); if(pUnit) pCreature->AddThreat(pUnit, 1.0f); else pCreature->AddThreat(m_creature, 1.0f); }else pCreature->AddThreat(m_creature, 1.0f); if(IsBoss) { if(!RageWinterchillDead) WinterchillGUID = pCreature->GetGUID(); else AnetheronGUID = pCreature->GetGUID(); } } } void SummonNextWave(uint32 Wave) { if(AllianceWaves[Wave].IsBoss) SummonCreature(AllianceWaves[Wave].Mob1, true); if(AllianceWaves[Wave].Mob1 && (!AllianceWaves[Wave].IsBoss)) SummonCreature(AllianceWaves[Wave].Mob1); if(AllianceWaves[Wave].Mob2) SummonCreature(AllianceWaves[Wave].Mob2); if(AllianceWaves[Wave].Mob3) SummonCreature(AllianceWaves[Wave].Mob3); if(AllianceWaves[Wave].Mob4) SummonCreature(AllianceWaves[Wave].Mob4); if(AllianceWaves[Wave].Mob5) SummonCreature(AllianceWaves[Wave].Mob5); if(AllianceWaves[Wave].Mob6) SummonCreature(AllianceWaves[Wave].Mob6); if(AllianceWaves[Wave].Mob7) SummonCreature(AllianceWaves[Wave].Mob7); if(AllianceWaves[Wave].Mob8) SummonCreature(AllianceWaves[Wave].Mob8); if(AllianceWaves[Wave].Mob9) SummonCreature(AllianceWaves[Wave].Mob9); if(AllianceWaves[Wave].Mob10) SummonCreature(AllianceWaves[Wave].Mob10); if(AllianceWaves[Wave].Mob11) SummonCreature(AllianceWaves[Wave].Mob11); if(AllianceWaves[Wave].Mob12) SummonCreature(AllianceWaves[Wave].Mob12); if(AllianceWaves[Wave].Mob13) SummonCreature(AllianceWaves[Wave].Mob13); if(AllianceWaves[Wave].Mob14) SummonCreature(AllianceWaves[Wave].Mob14); if(AllianceWaves[Wave].Mob15) SummonCreature(AllianceWaves[Wave].Mob15); if(AllianceWaves[Wave].Mob16) SummonCreature(AllianceWaves[Wave].Mob16); if(AllianceWaves[Wave].Mob17) SummonCreature(AllianceWaves[Wave].Mob17); if(AllianceWaves[Wave].Mob18) SummonCreature(AllianceWaves[Wave].Mob18); if(!AllianceWaves[Wave].IsBoss) NextWaveTimer = AllianceWaves[Wave].WaveTimer; else NextWaveTimer = 0; } void TeleportRaid(Player* player) { if(!player) { if(PlayerGUID) { player = ((Player*)Unit::GetUnit((*m_creature), PlayerGUID)); if(!player) return; }else return; } Group* Raid = player->GetGroup(); if(Raid) { const Group::MemberSlotList list = Raid->GetMemberSlots(); Group::member_citerator itr = list.begin(); for( ; itr != list.end(); itr++) { Player* member = ((Player*)Unit::GetUnit((*m_creature), itr->guid)); if(member && member->isAlive()) { member->CastSpell(member, SPELL_TELEPORT_VISUAL, true); member->TeleportTo(m_creature->GetMapId(), HORDEBASE_X, HORDEBASE_Y, HORDEBASE_Z, member->GetOrientation()); } } } } void StartEvent(Player* player) { if(player) { EventBegun = true; PlayerGUID = player->GetGUID(); m_creature->SetUInt32Value(UNIT_NPC_FLAGS, 0); } } void StartAnetheronPhase(Player* player) { if(player) { EventBegun = true; PlayerGUID = player->GetGUID(); m_creature->SetUInt32Value(UNIT_NPC_FLAGS, 0); } } void UpdateAI(const uint32 diff) { if(!EventBegun) return; if(NextWaveTimer) { if(NextWaveTimer < diff) { SummonNextWave(WaveCount); WaveCount++; }else NextWaveTimer -= diff; } if(CheckTimer < diff) { if(PlayerGUID) { Player* target = ((Player*)Unit::GetUnit((*m_creature), PlayerGUID)); if(target) { if(!target->isAlive()) { Group* Raid = target->GetGroup(); if(Raid) { const Group::MemberSlotList list = Raid->GetMemberSlots(); Group::member_citerator itr = list.begin(); uint32 DeathCount = 0; uint32 RaidCount = Raid->GetMembersCount(); for( ; itr != list.end(); itr++) { Player* member = ((Player*)Unit::GetUnit((*m_creature), itr->guid)); if(member && member->isAlive()) break; else DeathCount++; } if(DeathCount == RaidCount) { EventBegun = false; SetVariables(); EnterEvadeMode(); } } } } } if(WinterchillGUID) { Unit* pUnit = Unit::GetUnit((*m_creature), WinterchillGUID); if(pUnit && (!pUnit->isAlive())) { RageWinterchillDead = true; m_creature->SetUInt32Value(UNIT_NPC_FLAGS, 1); WinterchillGUID = 0; } } if(AnetheronGUID) { Unit* pUnit = Unit::GetUnit((*m_creature), AnetheronGUID); if(pUnit && (!pUnit->isAlive())) { AnetheronDead = true; m_creature->SetUInt32Value(UNIT_NPC_FLAGS, 1); AnetheronDead = 0; } } CheckTimer = 15000; }else CheckTimer -= diff; } }; bool GossipSelect_npc_jaina_proudmoore(Player *player, Creature *_Creature, uint32 sender, uint32 action ) { switch(action) { case GOSSIP_ACTION_INFO_DEF + 1: player->PlayerTalkClass->CloseGossip(); ((npc_jaina_proudmooreAI*)_Creature->AI())->StartEvent(player); break; case GOSSIP_ACTION_INFO_DEF + 2: player->PlayerTalkClass->CloseGossip(); ((npc_jaina_proudmooreAI*)_Creature->AI())->StartAnetheronPhase(player); break; case GOSSIP_ACTION_INFO_DEF + 3: player->PlayerTalkClass->CloseGossip(); ((npc_jaina_proudmooreAI*)_Creature->AI())->TeleportRaid(player); break; } return true; } bool GossipHello_npc_jaina_proudmoore(Player *player, Creature *_Creature) { if(player->isAlive()) { if(!((npc_jaina_proudmooreAI*)_Creature->AI())->EventBegun) { if(((npc_jaina_proudmooreAI*)_Creature->AI())->RageWinterchillDead) { player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_ANETHERON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); player->PlayerTalkClass->SendGossipMenu(907, _Creature->GetGUID()); } else { player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_BEGIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); player->PlayerTalkClass->SendGossipMenu(907, _Creature->GetGUID()); } } else { if(((npc_jaina_proudmooreAI*)_Creature->AI())->AnetheronDead) { player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM_RETREAT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); player->PlayerTalkClass->SendGossipMenu(907, _Creature->GetGUID()); } } } return true; } CreatureAI* GetAI_npc_jaina_proudmoore(Creature* _Creature) { return new npc_jaina_proudmooreAI(_Creature); } void AddSC_npc_jaina_proudmoore() { Script *newscript; newscript = new Script; newscript->Name="npc_jaina_proudmoore"; newscript->GetAI = GetAI_npc_jaina_proudmoore; newscript->pGossipHello = &GossipHello_npc_jaina_proudmoore; newscript->pGossipSelect = &GossipSelect_npc_jaina_proudmoore; m_scripts[nrscripts++] = newscript; }