diff options
Diffstat (limited to 'src')
33 files changed, 1071 insertions, 635 deletions
diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp index 953bbf7521a..e3518cb6921 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> +/* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/> * * Thanks to the original authors: ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * diff --git a/src/server/game/AI/ScriptedAI/ScriptedGossip.h b/src/server/game/AI/ScriptedAI/ScriptedGossip.h index 5d376be888e..34300ff406c 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedGossip.h +++ b/src/server/game/AI/ScriptedAI/ScriptedGossip.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> +/* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/> * * Thanks to the original authors: ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * diff --git a/src/server/game/Chat/Commands/Level2.cpp b/src/server/game/Chat/Commands/Level2.cpp index 2f04ebcf6bc..31942d9e2fa 100755 --- a/src/server/game/Chat/Commands/Level2.cpp +++ b/src/server/game/Chat/Commands/Level2.cpp @@ -712,19 +712,20 @@ bool ChatHandler::HandleLookupPlayerIpCommand(const char* args) char* limit_str; Player *chr = getSelectedPlayer(); - if (chr == NULL) + if (!*args) { - if (!*args) + // NULL only if used from console + if (!chr || chr == GetSession()->GetPlayer()) return false; - ip = strtok ((char*)args, " "); - limit_str = strtok (NULL, " "); - limit = limit_str ? atoi (limit_str) : -1; + ip = chr->GetSession()->GetRemoteAddress(); + limit = -1; } else { - ip = chr->GetSession()->GetRemoteAddress(); - limit = -1; + ip = strtok ((char*)args, " "); + limit_str = strtok (NULL, " "); + limit = limit_str ? atoi (limit_str) : -1; } LoginDatabase.EscapeString(ip); diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 3e06f9e73db..ff627f78ea0 100755 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -715,7 +715,7 @@ void Creature::Motion_Initialize() i_motionMaster.Initialize(); } else if (m_formation->isFormed()) - i_motionMaster.MoveIdle(MOTION_SLOT_IDLE); //wait the order of leader + i_motionMaster.MoveIdle(); //wait the order of leader else i_motionMaster.Initialize(); } diff --git a/src/server/game/Entities/Creature/CreatureGroups.cpp b/src/server/game/Entities/Creature/CreatureGroups.cpp index 3a63c32fc1e..abf82dc5919 100755 --- a/src/server/game/Entities/Creature/CreatureGroups.cpp +++ b/src/server/game/Entities/Creature/CreatureGroups.cpp @@ -203,7 +203,7 @@ void CreatureGroup::FormationReset(bool dismiss) if (dismiss) itr->first->GetMotionMaster()->Initialize(); else - itr->first->GetMotionMaster()->MoveIdle(MOTION_SLOT_IDLE); + itr->first->GetMotionMaster()->MoveIdle(); sLog->outDebug(LOG_FILTER_UNITS, "Set %s movement for member GUID: %u", dismiss ? "default" : "idle", itr->first->GetGUIDLow()); } } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 6854a68ac1d..7f7facfaff1 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -13997,6 +13997,10 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool PrepareQuestMenu(source->GetGUID()); } + if (source->GetTypeId() == TYPEID_GAMEOBJECT) + if (source->ToGameObject()->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) + PrepareQuestMenu(source->GetGUID()); + for (GossipMenuItemsMap::const_iterator itr = menuItemBounds.first; itr != menuItemBounds.second; ++itr) { bool canTalk = true; @@ -14082,11 +14086,6 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool switch (itr->second.OptionType) { - case GOSSIP_OPTION_QUESTGIVER: - if (go->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) - PrepareQuestMenu(source->GetGUID()); - canTalk = false; - break; case GOSSIP_OPTION_GOSSIP: if (go->GetGoType() != GAMEOBJECT_TYPE_QUESTGIVER && go->GetGoType() != GAMEOBJECT_TYPE_GOOBER) canTalk = false; @@ -16657,6 +16656,7 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) _LoadInstanceTimeRestrictions(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADINSTANCELOCKTIMES)); _LoadBGData(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADBGDATA)); + GetSession()->SetPlayer(this); MapEntry const* mapEntry = sMapStore.LookupEntry(mapId); if (!mapEntry || !IsPositionValid()) { diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index fdc6eef8407..2d6e8f1b724 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -8938,18 +8938,17 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg // Maelstrom Weapon case 53817: { - // Item - Shaman T10 Enhancement 4P Bonus - if (AuraEffect const* aurEff = GetAuraEffect(70832, 0)) - if (Aura const* maelstrom = GetAura(53817)) - if ((maelstrom->GetStackAmount() == maelstrom->GetSpellInfo()->StackAmount) && roll_chance_i(aurEff->GetAmount())) - CastSpell(this, 70831, true, castItem, triggeredByAura); - // has rank dependant proc chance, ignore too often cases // PPM = 2.5 * (rank of talent), uint32 rank = auraSpellInfo->GetRank(); // 5 rank -> 100% 4 rank -> 80% and etc from full rate if (!roll_chance_i(20*rank)) return false; + // Item - Shaman T10 Enhancement 4P Bonus + if (AuraEffect const* aurEff = GetAuraEffect(70832, 0)) + if (Aura const* maelstrom = GetAura(53817)) + if ((maelstrom->GetStackAmount() == maelstrom->GetSpellInfo()->StackAmount - 1) && roll_chance_i(aurEff->GetAmount())) + CastSpell(this, 70831, true, castItem, triggeredByAura); break; } // Astral Shift @@ -16262,7 +16261,7 @@ void Unit::GetRaidMember(std::list<Unit*> &nearMembers, float radius) if (owner->isAlive() && (owner == this || IsWithinDistInMap(owner, radius))) nearMembers.push_back(owner); if (Guardian* pet = owner->GetGuardianPet()) - if (pet->isAlive() && (pet == this && IsWithinDistInMap(pet, radius))) + if (pet->isAlive() && (pet == this || IsWithinDistInMap(pet, radius))) nearMembers.push_back(pet); } } @@ -16299,7 +16298,7 @@ void Unit::GetPartyMemberInDist(std::list<Unit*> &TagUnitMap, float radius) if (owner->isAlive() && (owner == this || IsWithinDistInMap(owner, radius))) TagUnitMap.push_back(owner); if (Guardian* pet = owner->GetGuardianPet()) - if (pet->isAlive() && (pet == this && IsWithinDistInMap(pet, radius))) + if (pet->isAlive() && (pet == this || IsWithinDistInMap(pet, radius))) TagUnitMap.push_back(pet); } } diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp index fa8c0fb39e4..90fb8ffb9f0 100755 --- a/src/server/game/Instances/InstanceScript.cpp +++ b/src/server/game/Instances/InstanceScript.cpp @@ -302,21 +302,21 @@ void InstanceScript::DoUpdateWorldState(uint32 uiStateId, uint32 uiStateData) } // Send Notify to all players in instance -void InstanceScript::DoSendNotifyToInstance(const char *format, ...) +void InstanceScript::DoSendNotifyToInstance(char const* format, ...) { - InstanceMap::PlayerList const &PlayerList = instance->GetPlayers(); + InstanceMap::PlayerList const& players = instance->GetPlayers(); - if (!PlayerList.isEmpty()) + if (!players.isEmpty()) { va_list ap; va_start(ap, format); - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (Player* player = i->getSource()) - if (WorldSession* pSession = player->GetSession()) - pSession->SendNotification(format, ap); - } + char buff[1024]; + vsnprintf(buff, 1024, format, ap); va_end(ap); + for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + if (Player* player = i->getSource()) + if (WorldSession* session = player->GetSession()) + session->SendNotification(buff); } } diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index 51725c118ce..6660da146f0 100755 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -175,12 +175,11 @@ void MotionMaster::DelayedExpire() --i_top; } -void MotionMaster::MoveIdle(MovementSlot slot) +void MotionMaster::MoveIdle() { - //if (empty() || !isStatic(top())) - // push(&si_idleMovement); - if (!isStatic(Impl[slot])) - Mutate(&si_idleMovement, slot); + //! Should be preceded by MovementExpired or Clear if there's an overlying movementgenerator active + if (empty() || !isStatic(top())) + Mutate(&si_idleMovement, MOTION_SLOT_IDLE); } void MotionMaster::MoveRandom(float spawndist) diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index 64026ea7b80..a972c3b06ce 100755 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -142,7 +142,7 @@ class MotionMaster //: private std::stack<MovementGenerator *> DirectExpire(reset); } - void MoveIdle(MovementSlot slot = MOTION_SLOT_ACTIVE); + void MoveIdle(); void MoveTargetedHome(); void MoveRandom(float spawndist = 0.0f); void MoveFollow(Unit* target, float dist, float angle, MovementSlot slot = MOTION_SLOT_ACTIVE); diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp index 6322151e792..c46721db6cd 100755 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/game/Scripting/ScriptLoader.cpp @@ -570,6 +570,7 @@ void AddSC_the_eye(); void AddSC_boss_gatewatcher_iron_hand(); //TK The Mechanar void AddSC_boss_nethermancer_sepethrea(); void AddSC_boss_pathaleon_the_calculator(); +void AddSC_boss_mechano_lord_capacitus(); void AddSC_instance_mechanar(); void AddSC_blades_edge_mountains(); @@ -1030,6 +1031,7 @@ void AddOutlandScripts() AddSC_boss_gatewatcher_iron_hand(); //TK The Mechanar AddSC_boss_nethermancer_sepethrea(); AddSC_boss_pathaleon_the_calculator(); + AddSC_boss_mechano_lord_capacitus(); AddSC_instance_mechanar(); AddSC_blades_edge_mountains(); diff --git a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp index fd649175f76..35276bb1d0a 100644 --- a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp @@ -776,6 +776,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) // "GetAccountId() == db stored account id" checked in LoadFromDB (prevent login not own character using cheating tools) if (!pCurrChar->LoadFromDB(GUID_LOPART(playerGuid), holder)) { + SetPlayer(NULL); KickPlayer(); // disconnect client, player no set to session and it will not deleted or saved at kick delete pCurrChar; // delete it manually delete holder; // delete all unprocessed queries @@ -784,9 +785,6 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) } pCurrChar->GetMotionMaster()->Initialize(); - - SetPlayer(pCurrChar); - pCurrChar->SendDungeonDifficulty(false); WorldPacket data(SMSG_LOGIN_VERIFY_WORLD, 20); diff --git a/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp b/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp index d5d205279f7..d1227c9b7d7 100755 --- a/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp @@ -160,7 +160,8 @@ void WorldSession::HandleGossipSelectOptionOpcode(WorldPacket & recv_data) else { go->AI()->GossipSelect(_player, menuId, gossipListId); - sScriptMgr->OnGossipSelect(_player, go, _player->PlayerTalkClass->GetGossipOptionSender(gossipListId), _player->PlayerTalkClass->GetGossipOptionAction(gossipListId)); + if (!sScriptMgr->OnGossipSelect(_player, go, _player->PlayerTalkClass->GetGossipOptionSender(gossipListId), _player->PlayerTalkClass->GetGossipOptionAction(gossipListId))) + _player->OnGossipSelect(go, gossipListId, menuId); } } } diff --git a/src/server/game/Server/Protocol/Handlers/PetHandler.cpp b/src/server/game/Server/Protocol/Handlers/PetHandler.cpp index fc13ef802fd..68ce3153450 100755 --- a/src/server/game/Server/Protocol/Handlers/PetHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/PetHandler.cpp @@ -155,6 +155,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid case COMMAND_STAY: //flat=1792 //STAY pet->AttackStop(); pet->InterruptNonMeleeSpells(false); + pet->GetMotionMaster()->Clear(false); pet->GetMotionMaster()->MoveIdle(); charmInfo->SetCommandState(COMMAND_STAY); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 40b3101cfd5..2c33488f76c 100755 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -333,38 +333,6 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex) switch (m_spellInfo->Id) // better way to check unknown { - // Positive/Negative Charge - case 28062: - case 28085: - case 39090: - case 39093: - if (!m_triggeredByAuraSpell) - break; - if (unitTarget == m_caster) - { - uint8 count = 0; - for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) - if (ihit->targetGUID != m_caster->GetGUID()) - if (Player* target = ObjectAccessor::GetPlayer(*m_caster, ihit->targetGUID)) - if (target->HasAura(m_triggeredByAuraSpell->Id)) - ++count; - if (count) - { - uint32 spellId = 0; - switch (m_spellInfo->Id) - { - case 28062: spellId = 29659; break; - case 28085: spellId = 29660; break; - case 39090: spellId = 39089; break; - case 39093: spellId = 39092; break; - } - m_caster->SetAuraStack(spellId, m_caster, count); - } - } - - if (unitTarget->HasAura(m_triggeredByAuraSpell->Id)) - damage = 0; - break; // Consumption case 28865: damage = (((InstanceMap*)m_caster->GetMap())->GetDifficulty() == REGULAR_DIFFICULTY ? 2750 : 4250); diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index e57cbf4a390..f3d5697c672 100755 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3041,6 +3041,7 @@ void SpellMgr::LoadDbcDataCorrections() case 42611: // Shoot case 61588: // Blazing Harpoon case 52479: // Gift of the Harvester + case 48246: // Ball of Flame spellInfo->MaxAffectedTargets = 1; break; case 41376: // Spite @@ -3383,6 +3384,7 @@ void SpellMgr::LoadDbcDataCorrections() spellInfo->AreaGroupId = 0; // originally, these require area 4522, which is... outside of Icecrown Citadel break; case 70602: // Corruption + case 48278: // Paralyze spellInfo->AttributesEx3 |= SPELL_ATTR3_STACK_FOR_DIFF_CASTERS; break; case 70715: // Column of Frost (visual marker) diff --git a/src/server/scripts/Commands/cs_account.cpp b/src/server/scripts/Commands/cs_account.cpp index ac265acbf71..7372c92c4dd 100644 --- a/src/server/scripts/Commands/cs_account.cpp +++ b/src/server/scripts/Commands/cs_account.cpp @@ -510,7 +510,7 @@ public: stmt->setUInt32(0, targetAccountId); stmt->setUInt8(1, uint8(gm)); - stmt->setUInt32(2, gmRealmID); + stmt->setInt32(2, gmRealmID); LoginDatabase.Execute(stmt); } diff --git a/src/server/scripts/EasternKingdoms/silverpine_forest.cpp b/src/server/scripts/EasternKingdoms/silverpine_forest.cpp index e166013a4b2..4d897c4f3b8 100644 --- a/src/server/scripts/EasternKingdoms/silverpine_forest.cpp +++ b/src/server/scripts/EasternKingdoms/silverpine_forest.cpp @@ -19,12 +19,11 @@ /* ScriptData SDName: Silverpine_Forest SD%Complete: 100 -SDComment: Quest support: 1886, 435, 452 +SDComment: Quest support: 435, 452 SDCategory: Silverpine Forest EndScriptData */ /* ContentData -npc_astor_hadren npc_deathstalker_erland pyrewood_ambush EndContentData */ @@ -33,73 +32,6 @@ EndContentData */ #include "ScriptedEscortAI.h" /*###### -## npc_astor_hadren -######*/ - -#define GOSSIP_HAH "You're Astor Hadren, right?" -#define GOSSIP_SAH "You've got something I need, Astor. And I'll be taking it now." - -class npc_astor_hadren : public CreatureScript -{ -public: - npc_astor_hadren() : CreatureScript("npc_astor_hadren") { } - - CreatureAI* GetAI(Creature* creature) const - { - return new npc_astor_hadrenAI(creature); - } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*uiSender*/, uint32 uiAction) - { - player->PlayerTalkClass->ClearMenus(); - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF + 1: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SAH, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - player->SEND_GOSSIP_MENU(624, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - player->CLOSE_GOSSIP_MENU(); - creature->setFaction(21); - if (player) - CAST_AI(npc_astor_hadren::npc_astor_hadrenAI, creature->AI())->AttackStart(player); - break; - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) - { - if (player->GetQuestStatus(1886) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HAH, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - - player->SEND_GOSSIP_MENU(623, creature->GetGUID()); - - return true; - } - - struct npc_astor_hadrenAI : public ScriptedAI - { - npc_astor_hadrenAI(Creature* c) : ScriptedAI(c) {} - - void Reset() - { - me->setFaction(68); - } - - void EnterCombat(Unit* /*who*/) - { - } - - void JustDied(Unit* /*who*/) - { - me->setFaction(68); - } - }; - -}; - -/*###### ## npc_deathstalker_erland ######*/ @@ -386,7 +318,6 @@ public: void AddSC_silverpine_forest() { - new npc_astor_hadren(); new npc_deathstalker_erland(); new pyrewood_ambush(); } diff --git a/src/server/scripts/Kalimdor/ashenvale.cpp b/src/server/scripts/Kalimdor/ashenvale.cpp index e27d7287179..5d26653a1a8 100644 --- a/src/server/scripts/Kalimdor/ashenvale.cpp +++ b/src/server/scripts/Kalimdor/ashenvale.cpp @@ -35,34 +35,42 @@ EndContentData */ # npc_torek ####*/ -#define SAY_READY -1000106 -#define SAY_MOVE -1000107 -#define SAY_PREPARE -1000108 -#define SAY_WIN -1000109 -#define SAY_END -1000110 +enum TorekSays +{ + SAY_READY = 0, + SAY_MOVE = 1, + SAY_PREPARE = 2, + SAY_WIN = 3, + SAY_END = 4, +}; -#define SPELL_REND 11977 -#define SPELL_THUNDERCLAP 8078 +enum TorekSpells +{ + SPELL_REND = 11977, + SPELL_THUNDERCLAP = 8078, +}; -#define QUEST_TOREK_ASSULT 6544 +enum TorekMisc +{ + QUEST_TOREK_ASSULT = 6544, -#define ENTRY_SPLINTERTREE_RAIDER 12859 -#define ENTRY_DURIEL 12860 -#define ENTRY_SILVERWING_SENTINEL 12896 -#define ENTRY_SILVERWING_WARRIOR 12897 + ENTRY_SPLINTERTREE_RAIDER = 12859, + ENTRY_DURIEL = 12860, + ENTRY_SILVERWING_SENTINEL = 12896, + ENTRY_SILVERWING_WARRIOR = 12897, +}; class npc_torek : public CreatureScript { public: - npc_torek() - : CreatureScript("npc_torek") + npc_torek() : CreatureScript("npc_torek") { } struct npc_torekAI : public npc_escortAI { - npc_torekAI(Creature* c) : npc_escortAI(c) {} + npc_torekAI(Creature* creature) : npc_escortAI(creature) {} uint32 Rend_Timer; uint32 Thunderclap_Timer; @@ -78,10 +86,10 @@ class npc_torek : public CreatureScript switch (i) { case 1: - DoScriptText(SAY_MOVE, me, player); + Talk(SAY_MOVE, player->GetGUID()); break; case 8: - DoScriptText(SAY_PREPARE, me, player); + Talk(SAY_PREPARE, player->GetGUID()); break; case 19: //TODO: verify location and creatures amount. @@ -96,7 +104,7 @@ class npc_torek : public CreatureScript player->GroupEventHappens(QUEST_TOREK_ASSULT, me); break; case 21: - DoScriptText(SAY_END, me, player); + Talk(SAY_END, player->GetGUID()); break; } } @@ -148,7 +156,7 @@ class npc_torek : public CreatureScript if (quest->GetQuestId() == QUEST_TOREK_ASSULT) { //TODO: find companions, make them follow Torek, at any time (possibly done by core/database in future?) - DoScriptText(SAY_READY, creature, player); + creature->AI()->Talk(SAY_READY, player->GetGUID()); creature->setFaction(113); if (npc_escortAI* pEscortAI = CAST_AI(npc_torekAI, creature->AI())) diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp index e6678be3a2b..bc6145252d2 100755 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp @@ -568,12 +568,11 @@ public: } bool m_bFall; - uint32 m_uiPermafrostTimer; + float x, y, z; void Reset() { m_bFall = false; - m_uiPermafrostTimer = 0; me->SetReactState(REACT_PASSIVE); me->SetFlying(true); me->SetDisplayId(25144); @@ -590,11 +589,13 @@ public: if (!m_bFall) { m_bFall = true; - me->SetFlying(false); me->GetMotionMaster()->MoveIdle(); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); //At hit the ground - me->GetMotionMaster()->MoveFall(142.2f, 0); + me->GetPosition(x, y, z); + z = me->GetMap()->GetHeight(x, y, z, true, 50); + me->HandleEmoteCommand(EMOTE_ONESHOT_FLYDEATH); + me->GetMotionMaster()->MoveFall(z, 0); //me->FallGround(); //need correct vmap use (i believe it isn't working properly right now) } } @@ -607,24 +608,13 @@ public: switch (uiId) { case 0: - m_uiPermafrostTimer = IN_MILLISECONDS; - break; - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (m_uiPermafrostTimer) - { - if (m_uiPermafrostTimer <= uiDiff) - { - m_uiPermafrostTimer = 0; me->RemoveAurasDueToSpell(SPELL_FROST_SPHERE); me->SetDisplayId(11686); - me->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.0f); + me->Relocate(x, y, z, me->GetOrientation()); DoCast(SPELL_PERMAFROST_VISUAL); DoCast(SPELL_PERMAFROST); - } else m_uiPermafrostTimer -= uiDiff; + me->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.0f); + break; } } }; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp index 25610341a2f..46c1cf425ed 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp @@ -638,7 +638,7 @@ class npc_spinestalker : public CreatureScript float moveTime = me->GetExactDist(&SpinestalkerFlyPos) / (me->GetSpeed(MOVE_FLIGHT) * 0.001f); me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, SpinestalkerLandPos), me->m_Events.CalculateTime(uint64(moveTime) + 250)); me->SetDefaultMovementType(IDLE_MOTION_TYPE); - me->GetMotionMaster()->MoveIdle(MOTION_SLOT_IDLE); + me->GetMotionMaster()->MoveIdle(); me->StopMoving(); me->GetMotionMaster()->MovePoint(POINT_FROSTWYRM_FLY_IN, SpinestalkerFlyPos); } @@ -753,7 +753,7 @@ class npc_rimefang : public CreatureScript float moveTime = me->GetExactDist(&RimefangFlyPos) / (me->GetSpeed(MOVE_FLIGHT) * 0.001f); me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, RimefangLandPos), me->m_Events.CalculateTime(uint64(moveTime) + 250)); me->SetDefaultMovementType(IDLE_MOTION_TYPE); - me->GetMotionMaster()->MoveIdle(MOTION_SLOT_IDLE); + me->GetMotionMaster()->MoveIdle(); me->StopMoving(); me->GetMotionMaster()->MovePoint(POINT_FROSTWYRM_FLY_IN, RimefangFlyPos); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp index 1fbdb7f4677..f2657e5b2ef 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -1656,7 +1656,8 @@ class npc_strangulate_vehicle : public CreatureScript switch (eventId) { case EVENT_TELEPORT: - me->GetMotionMaster()->MoveIdle(MOTION_SLOT_ACTIVE); + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveIdle(); if (TempSummon* summ = me->ToTempSummon()) { if (Unit* summoner = summ->GetSummoner()) diff --git a/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp b/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp index 4c2348d30c9..58d3a4240b2 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp @@ -20,79 +20,185 @@ enum Spells { - SPELL_NECROTIC_AURA = 55593, - SPELL_SUMMON_SPORE = 29234, - SPELL_DEATHBLOOM = 29865, - H_SPELL_DEATHBLOOM = 55053, - SPELL_INEVITABLE_DOOM = 29204, - H_SPELL_INEVITABLE_DOOM = 55052 + SPELL_NECROTIC_AURA = 55593, + SPELL_WARN_NECROTIC_AURA = 59481, + SPELL_SUMMON_SPORE = 29234, + SPELL_DEATHBLOOM = 29865, + H_SPELL_DEATHBLOOM = 55053, + SPELL_INEVITABLE_DOOM = 29204, + H_SPELL_INEVITABLE_DOOM = 55052 +}; + +enum Texts +{ + SAY_NECROTIC_AURA_APPLIED = 0, + SAY_NECROTIC_AURA_REMOVED = 1, + SAY_NECROTIC_AURA_FADING = 2, }; enum Events { - EVENT_NONE, - EVENT_AURA, - EVENT_BLOOM, - EVENT_DOOM, + EVENT_NECROTIC_AURA = 1, + EVENT_DEATHBLOOM = 2, + EVENT_INEVITABLE_DOOM = 3, + EVENT_SPORE = 4, + EVENT_NECROTIC_AURA_FADING = 5, +}; + +enum Achievement +{ + DATA_ACHIEVEMENT_SPORE_LOSER = 21822183, }; class boss_loatheb : public CreatureScript { -public: - boss_loatheb() : CreatureScript("boss_loatheb") { } + public: + boss_loatheb() : CreatureScript("boss_loatheb") { } - CreatureAI* GetAI(Creature* creature) const - { - return new boss_loathebAI (creature); - } + struct boss_loathebAI : public BossAI + { + boss_loathebAI(Creature* creature) : BossAI(creature, BOSS_LOATHEB) + { + } - struct boss_loathebAI : public BossAI - { - boss_loathebAI(Creature* c) : BossAI(c, BOSS_LOATHEB) {} + void Reset() + { + _Reset(); + _doomCounter = 0; + _sporeLoserData = true; + } - void EnterCombat(Unit* /*who*/) - { - _EnterCombat(); - events.ScheduleEvent(EVENT_AURA, 10000); - events.ScheduleEvent(EVENT_BLOOM, 5000); - events.ScheduleEvent(EVENT_DOOM, 120000); - } + void EnterCombat(Unit* /*who*/) + { + _EnterCombat(); + events.ScheduleEvent(EVENT_NECROTIC_AURA, 17000); + events.ScheduleEvent(EVENT_DEATHBLOOM, 5000); + events.ScheduleEvent(EVENT_SPORE, IsHeroic() ? 18000 : 36000); + events.ScheduleEvent(EVENT_INEVITABLE_DOOM, 120000); + } - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; + void SummonedCreatureDies(Creature* /*summon*/, Unit* /*killer*/) + { + _sporeLoserData = false; + } - events.Update(diff); + uint32 GetData(uint32 id) + { + if (id != DATA_ACHIEVEMENT_SPORE_LOSER) + return 0; - while (uint32 eventId = events.ExecuteEvent()) + return uint32(_sporeLoserData); + } + + void UpdateAI(uint32 const diff) { - switch (eventId) + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) { - case EVENT_AURA: - DoCastAOE(SPELL_NECROTIC_AURA); - events.ScheduleEvent(EVENT_AURA, 20000); - break; - case EVENT_BLOOM: - // TODO : Add missing text - DoCastAOE(SPELL_SUMMON_SPORE, true); - DoCastAOE(RAID_MODE(SPELL_DEATHBLOOM, H_SPELL_DEATHBLOOM)); - events.ScheduleEvent(EVENT_BLOOM, 30000); - break; - case EVENT_DOOM: - DoCastAOE(RAID_MODE(SPELL_INEVITABLE_DOOM, H_SPELL_INEVITABLE_DOOM)); - events.ScheduleEvent(EVENT_DOOM, events.GetTimer() < 5*60000 ? 30000 : 15000); - break; + switch (eventId) + { + case EVENT_NECROTIC_AURA: + DoCastAOE(SPELL_NECROTIC_AURA); + DoCast(me, SPELL_WARN_NECROTIC_AURA); + events.ScheduleEvent(EVENT_NECROTIC_AURA, 20000); + events.ScheduleEvent(EVENT_NECROTIC_AURA_FADING, 14000); + break; + case EVENT_DEATHBLOOM: + DoCastAOE(RAID_MODE(SPELL_DEATHBLOOM, H_SPELL_DEATHBLOOM)); + events.ScheduleEvent(EVENT_DEATHBLOOM, 30000); + break; + case EVENT_INEVITABLE_DOOM: + _doomCounter++; + DoCastAOE(RAID_MODE(SPELL_INEVITABLE_DOOM, H_SPELL_INEVITABLE_DOOM)); + events.ScheduleEvent(EVENT_INEVITABLE_DOOM, std::max(120000 - _doomCounter * 15000, 15000)); // needs to be confirmed + break; + case EVENT_SPORE: + DoCast(me, SPELL_SUMMON_SPORE, false); + events.ScheduleEvent(EVENT_SPORE, IsHeroic() ? 18000 : 36000); + break; + case EVENT_NECROTIC_AURA_FADING: + Talk(SAY_NECROTIC_AURA_FADING); + break; + default: + break; + } } + + DoMeleeAttackIfReady(); } - DoMeleeAttackIfReady(); + private: + bool _sporeLoserData; + uint8 _doomCounter; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_loathebAI(creature); + } +}; + +class achievement_spore_loser : public AchievementCriteriaScript +{ + public: + achievement_spore_loser() : AchievementCriteriaScript("achievement_spore_loser") { } + + bool OnCheck(Player* /*source*/, Unit* target) + { + return target && target->GetAI()->GetData(DATA_ACHIEVEMENT_SPORE_LOSER); } - }; +}; + +typedef boss_loatheb::boss_loathebAI LoathebAI; + +class spell_loatheb_necrotic_aura_warning : public SpellScriptLoader +{ + public: + spell_loatheb_necrotic_aura_warning() : SpellScriptLoader("spell_loatheb_necrotic_aura_warning") { } + + class spell_loatheb_necrotic_aura_warning_AuraScript : public AuraScript + { + PrepareAuraScript(spell_loatheb_necrotic_aura_warning_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellStore.LookupEntry(SPELL_WARN_NECROTIC_AURA)) + return false; + return true; + } + void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (GetTarget()->IsAIEnabled) + CAST_AI(LoathebAI, GetTarget()->GetAI())->Talk(SAY_NECROTIC_AURA_APPLIED); + } + + void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (GetTarget()->IsAIEnabled) + CAST_AI(LoathebAI, GetTarget()->GetAI())->Talk(SAY_NECROTIC_AURA_REMOVED); + } + + void Register() + { + AfterEffectApply += AuraEffectApplyFn(spell_loatheb_necrotic_aura_warning_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_loatheb_necrotic_aura_warning_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_loatheb_necrotic_aura_warning_AuraScript(); + } }; void AddSC_boss_loatheb() { new boss_loatheb(); + new achievement_spore_loser(); + new spell_loatheb_necrotic_aura_warning(); } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp index b0138fb1a5e..be9168c6fd4 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp @@ -83,7 +83,11 @@ enum ThaddiusSpells SPELL_BALL_LIGHTNING = 28299, SPELL_CHAIN_LIGHTNING = 28167, H_SPELL_CHAIN_LIGHTNING = 54531, - SPELL_BERSERK = 27680 + SPELL_BERSERK = 27680, + SPELL_POSITIVE_CHARGE = 28062, + SPELL_POSITIVE_CHARGE_STACK = 29659, + SPELL_NEGATIVE_CHARGE = 28085, + SPELL_NEGATIVE_CHARGE_STACK = 29660 }; enum Events @@ -94,6 +98,11 @@ enum Events EVENT_BERSERK, }; +enum Achievement +{ + DATA_POLARITY_SWITCH = 76047605, +}; + class boss_thaddius : public CreatureScript { public: @@ -135,6 +144,7 @@ public: bool checkStalaggAlive; bool checkFeugenAlive; + bool polaritySwitch; uint32 uiAddsTimer; void KilledUnit(Unit* /*victim*/) @@ -194,6 +204,20 @@ public: me->SetReactState(REACT_AGGRESSIVE); } + void SetData(uint32 id, uint32 data) + { + if (id == DATA_POLARITY_SWITCH) + polaritySwitch = data ? true : false; + } + + uint32 GetData(uint32 id) + { + if (id != DATA_POLARITY_SWITCH) + return 0; + + return uint32(polaritySwitch); + } + void UpdateAI(const uint32 diff) { if (checkFeugenAlive && checkStalaggAlive) @@ -400,9 +424,101 @@ public: }; +class spell_thaddius_pos_neg_charge : public SpellScriptLoader +{ + public: + spell_thaddius_pos_neg_charge() : SpellScriptLoader("spell_thaddius_pos_neg_charge") { } + + class spell_thaddius_pos_neg_charge_SpellScript : public SpellScript + { + PrepareSpellScript(spell_thaddius_pos_neg_charge_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_POSITIVE_CHARGE)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_POSITIVE_CHARGE_STACK)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_NEGATIVE_CHARGE)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_NEGATIVE_CHARGE_STACK)) + return false; + return true; + } + + bool Load() + { + return GetCaster()->GetTypeId() == TYPEID_UNIT; + } + + void HandleTargets(std::list<Unit*>& targetList) + { + uint8 count = 0; + for (std::list<Unit*>::iterator ihit = targetList.begin(); ihit != targetList.end(); ++ihit) + if ((*ihit)->GetGUID() != GetCaster()->GetGUID()) + if (Player* target = (*ihit)->ToPlayer()) + if (target->HasAura(GetTriggeringSpell()->Id)) + ++count; + + if (count) + { + uint32 spellId = 0; + + if (GetSpellInfo()->Id == SPELL_POSITIVE_CHARGE) + spellId = SPELL_POSITIVE_CHARGE_STACK; + else // if (GetSpellInfo()->Id == SPELL_NEGATIVE_CHARGE) + spellId = SPELL_NEGATIVE_CHARGE_STACK; + + GetCaster()->SetAuraStack(spellId, GetCaster(), count); + } + } + + void HandleDamage(SpellEffIndex /*effIndex*/) + { + if (!GetTriggeringSpell()) + return; + + Unit* target = GetHitUnit(); + Unit* caster = GetCaster(); + + if (target->HasAura(GetTriggeringSpell()->Id)) + SetHitDamage(0); + else + { + if (target->GetTypeId() == TYPEID_PLAYER && caster->IsAIEnabled) + caster->ToCreature()->AI()->SetData(DATA_POLARITY_SWITCH, 1); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_thaddius_pos_neg_charge_SpellScript::HandleDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + OnUnitTargetSelect += SpellUnitTargetFn(spell_thaddius_pos_neg_charge_SpellScript::HandleTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_thaddius_pos_neg_charge_SpellScript(); + } +}; + +class achievement_polarity_switch : public AchievementCriteriaScript +{ + public: + achievement_polarity_switch() : AchievementCriteriaScript("achievement_polarity_switch") { } + + bool OnCheck(Player* /*source*/, Unit* target) + { + return target && target->GetAI()->GetData(DATA_POLARITY_SWITCH); + } +}; + void AddSC_boss_thaddius() { new boss_thaddius(); new mob_stalagg(); new mob_feugen(); + new spell_thaddius_pos_neg_charge(); + new achievement_polarity_switch(); } diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp index 32cb279ce5f..c05d9a21850 100644 --- a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp +++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp @@ -166,8 +166,8 @@ public: kelthuzadGUID = 0; kelthuzadTriggerGUID = 0; - playerDied = 0; - gothikDoorState = GO_STATE_ACTIVE; + playerDied = 0; + gothikDoorState = GO_STATE_ACTIVE; memset(portalsGUID, 0, sizeof(portalsGUID)); } diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp index e96801f3ecb..c6f72890d1f 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp @@ -61,7 +61,7 @@ enum eEnums //OTHER SPELLS //SPELL_CHARGE_UP = 52098, // only used when starting walk from one platform to the other - //SPELL_TEMPORARY_ELECTRICAL_CHARGE = 52092, // triggered part of above + SPELL_TEMPORARY_ELECTRICAL_CHARGE = 52092, // triggered part of above NPC_STORMFORGED_LIEUTENANT = 29240, SPELL_ARC_WELD = 59085, @@ -98,11 +98,13 @@ public: m_instance = creature->GetInstanceScript(); m_uiStance = STANCE_DEFENSIVE; memset(&m_auiStormforgedLieutenantGUID, 0, sizeof(m_auiStormforgedLieutenantGUID)); + canBuff = true; } InstanceScript* m_instance; bool m_bIsChangingStance; + bool canBuff; uint8 m_uiChargingStatus; uint8 m_uiStance; @@ -126,6 +128,10 @@ public: void Reset() { + if (canBuff) + if (!me->HasAura(SPELL_TEMPORARY_ELECTRICAL_CHARGE)) + me->AddAura(SPELL_TEMPORARY_ELECTRICAL_CHARGE, me); + m_bIsChangingStance = false; m_uiChargingStatus = 0; @@ -167,6 +173,16 @@ public: m_instance->SetData(TYPE_BJARNGRIM, NOT_STARTED); } + void EnterEvadeMode() + { + if (me->HasAura(SPELL_TEMPORARY_ELECTRICAL_CHARGE)) + canBuff = true; + else + canBuff = false; + + ScriptedAI::EnterEvadeMode(); + } + void EnterCombat(Unit* /*who*/) { DoScriptText(SAY_AGGRO, me); @@ -211,7 +227,7 @@ public: void UpdateAI(const uint32 uiDiff) { //Return since we have no target - if (!UpdateVictim()) + if (!UpdateVictim()) return; // Change stance diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp index 01cd36266d0..9cab1de197c 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp @@ -20,69 +20,89 @@ enum Spells { - SPELL_CALL_FLAMES = 48258, - SPELL_RITUAL_OF_THE_SWORD = 48276, //Effect #1 Teleport, Effect #2 Dummy + SPELL_SVALA_TRANSFORMING1 = 54140, + SPELL_SVALA_TRANSFORMING2 = 54205, + SPELL_TRANSFORMING_CHANNEL = 54142, + + SPELL_CALL_FLAMES = 48258, // caster effect only, triggers event 17841 SPELL_SINSTER_STRIKE = 15667, H_SPELL_SINSTER_STRIKE = 59409, - SPELL_SVALA_TRANSFORMING1 = 54140, - SPELL_SVALA_TRANSFORMING2 = 54205 + + SPELL_RITUAL_PREPARATION = 48267, + SPELL_RITUAL_OF_THE_SWORD = 48276, + SPELL_RITUAL_STRIKE_TRIGGER = 48331, // triggers 48277 & 59930, needs NPC_RITUAL_TARGET as spell_script_target + SPELL_RITUAL_DISARM = 54159, + SPELL_RITUAL_STRIKE_EFF_1 = 48277, + SPELL_RITUAL_STRIKE_EFF_2 = 59930, + + SPELL_SUMMONED_VIS = 64446, + SPELL_RITUAL_CHANNELER_1 = 48271, + SPELL_RITUAL_CHANNELER_2 = 48274, + SPELL_RITUAL_CHANNELER_3 = 48275, + + // Ritual Channeler spells + SPELL_PARALYZE = 48278, + SPELL_SHADOWS_IN_THE_DARK = 59407, + + // Scourge Hulk spells + SPELL_MIGHTY_BLOW = 48697, + SPELL_VOLATILE_INFECTION = 56785, + H_SPELL_VOLATILE_INFECTION = 59228 }; -//not in db + enum Yells { - SAY_DIALOG_WITH_ARTHAS_1 = -1575015, - SAY_DIALOG_WITH_ARTHAS_2 = -1575016, - SAY_DIALOG_WITH_ARTHAS_3 = -1575017, - SAY_AGGRO = -1575018, - SAY_SLAY_1 = -1575019, - SAY_SLAY_2 = -1575020, - SAY_SLAY_3 = -1575021, - SAY_DEATH = -1575022, - SAY_SACRIFICE_PLAYER_1 = -1575023, - SAY_SACRIFICE_PLAYER_2 = -1575024, - SAY_SACRIFICE_PLAYER_3 = -1575025, - SAY_SACRIFICE_PLAYER_4 = -1575026, - SAY_SACRIFICE_PLAYER_5 = -1575027, - SAY_DIALOG_OF_ARTHAS_1 = -1575028, - SAY_DIALOG_OF_ARTHAS_2 = -1575029 + // Svala + SAY_SVALA_INTRO_0 = 0, + + // Svala Sorrowgrave + SAY_SVALA_INTRO_1 = 0, + SAY_SVALA_INTRO_2 = 1, + SAY_AGGRO = 2, + SAY_SLAY = 3, + SAY_DEATH = 4, + SAY_SACRIFICE_PLAYER = 5, + + // Image of Arthas + SAY_DIALOG_OF_ARTHAS_1 = 0, + SAY_DIALOG_OF_ARTHAS_2 = 1 }; + enum Creatures { CREATURE_ARTHAS = 29280, // Image of Arthas CREATURE_SVALA_SORROWGRAVE = 26668, // Svala after transformation CREATURE_SVALA = 29281, // Svala before transformation - CREATURE_RITUAL_CHANNELER = 27281 + CREATURE_RITUAL_CHANNELER = 27281, + CREATURE_SPECTATOR = 26667, + CREATURE_RITUAL_TARGET = 27327, + CREATURE_FLAME_BRAZIER = 27273, + CREATURE_SCOURGE_HULK = 26555 }; -enum ChannelerSpells -{ - //ritual channeler's spells - SPELL_PARALYZE = 48278, - SPELL_SHADOWS_IN_THE_DARK = 59407 -}; -enum Misc + +enum Objects { - DATA_SVALA_DISPLAY_ID = 25944 + OBJECT_UTGARDE_MIRROR = 191745 }; -enum IntroPhase + +enum SvalaPhase { IDLE, INTRO, - FINISHED -}; -enum CombatPhase -{ NORMAL, - SACRIFICING + SACRIFICING, + SVALADEAD }; -static Position RitualChannelerPos[]= +#define DATA_INCREDIBLE_HULK 2043 + +static const float spectatorWP[2][3] = { - {296.42f, -355.01f, 90.94f, 0.0f}, - {302.36f, -352.01f, 90.54f, 0.0f}, - {291.39f, -350.89f, 90.54f, 0.0f} + {296.95f,-312.76f,86.36f}, + {297.69f,-275.81f,86.36f} }; + static Position ArthasPos = { 295.81f, -366.16f, 92.57f, 1.58f }; -static Position SvalaPos = { 296.632f, -346.075f, 90.6307f, 1.58f }; class boss_svala : public CreatureScript { @@ -96,31 +116,96 @@ public: struct boss_svalaAI : public ScriptedAI { - boss_svalaAI(Creature* c) : ScriptedAI(c) + boss_svalaAI(Creature* creature) : ScriptedAI(creature), summons(creature) { - instance = c->GetInstanceScript(); + instance = creature->GetInstanceScript(); + Phase = IDLE; + + me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_RITUAL_STRIKE_EFF_1, true); + me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_RITUAL_STRIKE_EFF_2, true); } - uint32 uiIntroTimer; + InstanceScript* instance; + SummonList summons; + SvalaPhase Phase; + + Position pos; + float x, y, z; - uint8 uiIntroPhase; + uint32 introTimer; + uint8 introPhase; + uint8 sacrePhase; - IntroPhase Phase; + TempSummon* arthas; + uint64 arthasGUID; - TempSummon* pArthas; - uint64 uiArthasGUID; + uint32 sinsterStrikeTimer; + uint32 callFlamesTimer; + uint32 sacrificeTimer; - InstanceScript* instance; + bool sacrificed; void Reset() { - Phase = IDLE; - uiIntroTimer = 1 * IN_MILLISECONDS; - uiIntroPhase = 0; - uiArthasGUID = 0; + sacrificed = false; + SetCombatMovement(true); + + summons.DespawnAll(); + me->RemoveAllAuras(); + + if (Phase > INTRO) + { + me->SetFlying(true); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + } + + if (Phase > NORMAL) + Phase = NORMAL; + + introTimer = 1 * IN_MILLISECONDS; + introPhase = 0; + arthasGUID = 0; if (instance) + { instance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, NOT_STARTED); + instance->SetData64(DATA_SACRIFICED_PLAYER, 0); + } + } + + void JustReachedHome() + { + if (Phase > INTRO) + { + me->SetFlying(false); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->SetOrientation(1.58f); + me->SendMovementFlagUpdate(); + } + } + + void EnterCombat(Unit* /*who*/) + { + Talk(SAY_AGGRO); + + sinsterStrikeTimer = 7 * IN_MILLISECONDS; + callFlamesTimer = urand(10 * IN_MILLISECONDS, 20 * IN_MILLISECONDS); + + if (instance) + instance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, IN_PROGRESS); + } + + void JustSummoned(Creature* summon) + { + if (summon->GetEntry() == CREATURE_RITUAL_CHANNELER) + summon->CastSpell(summon, SPELL_SUMMONED_VIS, true); + + summons.Summon(summon); + } + + void SummonedCreatureDespawn(Creature* summon) + { + summons.Despawn(summon); } void MoveInLineOfSight(Unit* who) @@ -132,287 +217,500 @@ public: { Phase = INTRO; me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (GameObject* mirror = GetClosestGameObjectWithEntry(me, OBJECT_UTGARDE_MIRROR, 100.0f)) + mirror->SetGoState(GO_STATE_READY); + + if (Creature* arthas = me->SummonCreature(CREATURE_ARTHAS, ArthasPos, TEMPSUMMON_MANUAL_DESPAWN)) + { + arthas->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + arthasGUID = arthas->GetGUID(); + } + } + } + + void KilledUnit(Unit* victim) + { + if (victim != me) + Talk(SAY_SLAY); + } + + void DamageTaken(Unit* attacker, uint32 &damage) + { + if (Phase == SVALADEAD) + { + if (attacker != me) + damage = 0; + return; + } - if (Creature* pArthas = me->SummonCreature(CREATURE_ARTHAS, ArthasPos, TEMPSUMMON_MANUAL_DESPAWN)) + if (damage >= me->GetHealth()) + { + if (Phase == SACRIFICING) + SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + + me->GetPosition(x, y, z); + z = me->GetMap()->GetHeight(x, y, z, true, 50); + + if (me->GetPositionZ() > z) { - pArthas->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - uiArthasGUID = pArthas->GetGUID(); + damage = 0; + Phase = SVALADEAD; + me->InterruptNonMeleeSpells(true); + me->RemoveAllAuras(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetHealth(1); + + SetCombatMovement(false); + me->HandleEmoteCommand(EMOTE_ONESHOT_FLYDEATH); + me->GetMotionMaster()->MoveFall(z, 1); } } } - void AttackStart(Unit* /*who*/) {} + void MovementInform(uint32 motionType, uint32 pointId) + { + if (motionType != POINT_MOTION_TYPE) + return; + + if (pointId == 1) + { + me->Relocate(x, y, z, me->GetOrientation()); + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + + void JustDied(Unit* killer) + { + summons.DespawnAll(); + + if (instance) + instance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, DONE); + + Talk(SAY_DEATH); + } + + void SpellHitTarget(Unit* target, const SpellInfo* spell) + { + if (spell->Id == SPELL_RITUAL_STRIKE_EFF_1 && Phase != NORMAL && Phase != SVALADEAD) + { + Phase = NORMAL; + SetCombatMovement(true); + + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 300, true)) + me->GetMotionMaster()->MoveChase(target); + } + } void UpdateAI(const uint32 diff) { - if (Phase != INTRO) + if (Phase == IDLE) + return; + + if (Phase == INTRO) + { + if (introTimer <= diff) + { + Creature* arthas = Unit::GetCreature(*me, arthasGUID); + if (!arthas) + return; + + switch (introPhase) + { + case 0: + Talk(SAY_SVALA_INTRO_0); + ++introPhase; + introTimer = 8100; + break; + case 1: + arthas->AI()->Talk(SAY_DIALOG_OF_ARTHAS_1); + ++introPhase; + introTimer = 10000; + break; + case 2: + arthas->CastSpell(me, SPELL_TRANSFORMING_CHANNEL, false); + me->SetFlying(true); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + pos.Relocate(me); + pos.m_positionZ += 8.0f; + me->GetMotionMaster()->MoveTakeoff(0, pos, 3.30078125f); + // spectators flee event + if (instance) + { + std::list<Creature*> lspectatorList; + GetCreatureListWithEntryInGrid(lspectatorList, me, CREATURE_SPECTATOR, 100.0f); + for(std::list<Creature*>::iterator itr = lspectatorList.begin(); itr != lspectatorList.end(); ++itr) + { + if ((*itr)->isAlive()) + { + (*itr)->SetStandState(UNIT_STAND_STATE_STAND); + (*itr)->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); + (*itr)->GetMotionMaster()->MovePoint(1, spectatorWP[0][0], spectatorWP[0][1], spectatorWP[0][2]); + } + } + } + ++introPhase; + introTimer = 4200; + break; + case 3: + me->CastSpell(me, SPELL_SVALA_TRANSFORMING1, false); + ++introPhase; + introTimer = 6200; + break; + case 4: + me->CastSpell(me, SPELL_SVALA_TRANSFORMING2, false); + arthas->InterruptNonMeleeSpells(true); + me->RemoveAllAuras(); + me->UpdateEntry(CREATURE_SVALA_SORROWGRAVE); + me->SetFacingToObject(arthas); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + ++introPhase; + introTimer = 3200; + break; + case 5: + Talk(SAY_SVALA_INTRO_1); + ++introPhase; + introTimer = 10000; + break; + case 6: + arthas->AI()->Talk(SAY_DIALOG_OF_ARTHAS_2); + ++introPhase; + introTimer = 7200; + break; + case 7: + Talk(SAY_SVALA_INTRO_2); + me->SetOrientation(1.58f); + me->SendMovementFlagUpdate(); + arthas->SetVisible(false); + ++introPhase; + introTimer = 13800; + break; + case 8: + me->SetFlying(false); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->SendMovementFlagUpdate(); + pos.Relocate(me); + pos.m_positionX = me->GetHomePosition().GetPositionX(); + pos.m_positionY = me->GetHomePosition().GetPositionY(); + pos.m_positionZ = 90.6065f; + me->GetMotionMaster()->MoveLand(0, pos, 6.247422f); + ++introPhase; + introTimer = 3000; + break; + case 9: + if (GameObject* mirror = GetClosestGameObjectWithEntry(me, OBJECT_UTGARDE_MIRROR, 100.0f)) + mirror->SetGoState(GO_STATE_ACTIVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + arthas->DespawnOrUnsummon(); + arthasGUID = 0; + Phase = NORMAL; + break; + } + } else introTimer -= diff; + return; + } - if (uiIntroTimer <= diff) + if (Phase == NORMAL) { - Creature* pArthas = Unit::GetCreature(*me, uiArthasGUID); - if (!pArthas) + //Return since we have no target + if (!UpdateVictim()) return; - switch (uiIntroPhase) + if (me->IsWithinMeleeRange(me->getVictim()) && me->HasUnitMovementFlag(MOVEMENTFLAG_LEVITATING)) { - case 0: - DoScriptText(SAY_DIALOG_WITH_ARTHAS_1, me); - ++uiIntroPhase; - uiIntroTimer = 3500; - break; - case 1: - DoScriptText(SAY_DIALOG_OF_ARTHAS_1, pArthas); - ++uiIntroPhase; - uiIntroTimer = 3500; - break; - case 2: - DoScriptText(SAY_DIALOG_WITH_ARTHAS_2, me); - ++uiIntroPhase; - uiIntroTimer = 3500; - break; - case 3: - DoScriptText(SAY_DIALOG_OF_ARTHAS_2, pArthas); - ++uiIntroPhase; - uiIntroTimer = 3500; - break; - case 4: - DoScriptText(SAY_DIALOG_WITH_ARTHAS_3, me); - DoCast(me, SPELL_SVALA_TRANSFORMING1); - ++uiIntroPhase; - uiIntroTimer = 2800; - break; - case 5: - DoCast(me, SPELL_SVALA_TRANSFORMING2); - ++uiIntroPhase; - uiIntroTimer = 200; - break; - case 6: - if (me->SummonCreature(CREATURE_SVALA_SORROWGRAVE, SvalaPos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60*IN_MILLISECONDS)) + me->SetFlying(false); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->SendMovementFlagUpdate(); + } + + if (sinsterStrikeTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SINSTER_STRIKE); + sinsterStrikeTimer = urand(5 * IN_MILLISECONDS, 9 * IN_MILLISECONDS); + } else sinsterStrikeTimer -= diff; + + if (callFlamesTimer <= diff) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoCast(target, SPELL_CALL_FLAMES); + callFlamesTimer = urand(10 * IN_MILLISECONDS, 20 * IN_MILLISECONDS); + } + } else callFlamesTimer -= diff; + + if (!sacrificed) + { + if (HealthBelowPct(50)) + { + if (Unit* sacrificeTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 80, true)) { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - me->SetDisplayId(DATA_SVALA_DISPLAY_ID); - pArthas->DespawnOrUnsummon(); - uiArthasGUID = 0; - Phase = FINISHED; + if (instance) + instance->SetData64(DATA_SACRIFICED_PLAYER, sacrificeTarget->GetGUID()); + + Talk(SAY_SACRIFICE_PLAYER); + + DoCast(sacrificeTarget, SPELL_RITUAL_PREPARATION); + + SetCombatMovement(false); + me->SetFlying(true); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + + Phase = SACRIFICING; + sacrePhase = 0; + sacrificeTimer = 1 * IN_MILLISECONDS; + + DoCast(me, SPELL_RITUAL_OF_THE_SWORD); + sacrificed = true; } - else - Reset(); - break; + } } - } else uiIntroTimer -= diff; + + DoMeleeAttackIfReady(); + } + else //SACRIFICING + { + if (sacrificeTimer <= diff) + { + switch (sacrePhase) + { + case 0: + // spawn ritual channelers + if (instance) + { + DoCast(me, SPELL_RITUAL_CHANNELER_1, true); + DoCast(me, SPELL_RITUAL_CHANNELER_2, true); + DoCast(me, SPELL_RITUAL_CHANNELER_3, true); + } + ++sacrePhase; + sacrificeTimer = 2 * IN_MILLISECONDS; + break; + case 1: + me->StopMoving(); + me->GetMotionMaster()->MoveIdle(); + me->InterruptNonMeleeSpells(true); + DoCast(me, SPELL_RITUAL_STRIKE_TRIGGER, true); + ++sacrePhase; + sacrificeTimer = 200; + break; + case 2: + DoCast(me, SPELL_RITUAL_DISARM); + ++sacrePhase; + break; + case 3: + break; + } + } + else sacrificeTimer -= diff; + } } }; }; -class mob_ritual_channeler : public CreatureScript +class npc_ritual_channeler : public CreatureScript { public: - mob_ritual_channeler() : CreatureScript("mob_ritual_channeler") { } + npc_ritual_channeler() : CreatureScript("npc_ritual_channeler") { } CreatureAI* GetAI(Creature* creature) const { - return new mob_ritual_channelerAI(creature); + return new npc_ritual_channelerAI(creature); } - struct mob_ritual_channelerAI : public Scripted_NoMovementAI + struct npc_ritual_channelerAI : public Scripted_NoMovementAI { - mob_ritual_channelerAI(Creature* c) :Scripted_NoMovementAI(c) + npc_ritual_channelerAI(Creature* creature) :Scripted_NoMovementAI(creature) { - instance = c->GetInstanceScript(); + instance = creature->GetInstanceScript(); } InstanceScript* instance; + uint32 paralyzeTimer; void Reset() { - DoCast(me, SPELL_SHADOWS_IN_THE_DARK); - } - - // called by svala sorrowgrave to set guid of victim - void DoAction(const int32 /*action*/) - { + paralyzeTimer = 1600; if (instance) - if (Unit* victim = me->GetUnit(*me, instance->GetData64(DATA_SACRIFICED_PLAYER))) - DoCast(victim, SPELL_PARALYZE); + if (IsHeroic()) + DoCast(me, SPELL_SHADOWS_IN_THE_DARK); } - - void EnterCombat(Unit* /*who*/) + + void UpdateAI(const uint32 diff) { + if (me->HasUnitState(UNIT_STAT_CASTING)) + return; + + if (paralyzeTimer <= diff) + { + if (instance) + if (Unit* victim = me->GetUnit(*me, instance->GetData64(DATA_SACRIFICED_PLAYER))) + DoCast(victim, SPELL_PARALYZE, false); + + paralyzeTimer = 200; + } + else + paralyzeTimer -= diff; } }; - }; -class boss_svala_sorrowgrave : public CreatureScript +class npc_spectator : public CreatureScript { public: - boss_svala_sorrowgrave() : CreatureScript("boss_svala_sorrowgrave") { } + npc_spectator() : CreatureScript("npc_spectator") { } CreatureAI* GetAI(Creature* creature) const { - return new boss_svala_sorrowgraveAI(creature); + return new npc_spectatorAI(creature); } - struct boss_svala_sorrowgraveAI : public ScriptedAI + struct npc_spectatorAI : public ScriptedAI { - boss_svala_sorrowgraveAI(Creature* c) : ScriptedAI(c), summons(c) + npc_spectatorAI(Creature* creature) : ScriptedAI(creature) { } + + void Reset() { } + + void MovementInform(uint32 motionType, uint32 pointId) { - instance = c->GetInstanceScript(); + if (motionType == POINT_MOTION_TYPE) + { + if (pointId == 1) + me->GetMotionMaster()->MovePoint(2,spectatorWP[1][0],spectatorWP[1][1],spectatorWP[1][2]); + else if (pointId == 2) + me->DespawnOrUnsummon(1000); + } } + }; +}; - uint32 uiSinsterStrikeTimer; - uint32 uiCallFlamesTimer; - uint32 uiRitualOfSwordTimer; - uint32 uiSacrificeTimer; +class checkRitualTarget +{ + public: + explicit checkRitualTarget(Unit* _caster) : caster(_caster) { } - CombatPhase Phase; + bool operator() (Unit* unit) + { + if (InstanceScript* instance = caster->GetInstanceScript()) + if (instance->GetData64(DATA_SACRIFICED_PLAYER) == unit->GetGUID()) + return false; - SummonList summons; + return true; + } - bool bSacrificed; + private: + Unit* caster; +}; - InstanceScript* instance; +class spell_paralyze_pinnacle : public SpellScriptLoader +{ + public: + spell_paralyze_pinnacle() : SpellScriptLoader("spell_paralyze_pinnacle") { } - void Reset() + class spell_paralyze_pinnacle_SpellScript : public SpellScript { - uiSinsterStrikeTimer = 7 * IN_MILLISECONDS; - uiCallFlamesTimer = 10 * IN_MILLISECONDS; - uiRitualOfSwordTimer = 20 * IN_MILLISECONDS; - uiSacrificeTimer = 8 * IN_MILLISECONDS; + PrepareSpellScript(spell_paralyze_pinnacle_SpellScript); - bSacrificed = false; - - Phase = NORMAL; - - DoTeleportTo(296.632f, -346.075f, 90.6307f); - me->SetUnitMovementFlags(MOVEMENTFLAG_WALKING); - - summons.DespawnAll(); + void FilterTargets(std::list<Unit*>& unitList) + { + unitList.remove_if(checkRitualTarget(GetCaster())); + } - if (instance) + void Register() { - instance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, NOT_STARTED); - instance->SetData64(DATA_SACRIFICED_PLAYER, 0); + OnUnitTargetSelect += SpellUnitTargetFn(spell_paralyze_pinnacle_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } - } + }; - void EnterCombat(Unit* /*who*/) + SpellScript* GetSpellScript() const { - DoScriptText(SAY_AGGRO, me); - - if (instance) - instance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, IN_PROGRESS); + return new spell_paralyze_pinnacle_SpellScript(); } +}; - void JustSummoned(Creature* summon) - { - summons.Summon(summon); - } +class npc_scourge_hulk : public CreatureScript +{ + public: + npc_scourge_hulk() : CreatureScript("npc_scourge_hulk") { } - void SummonedCreatureDespawn(Creature* summon) + struct npc_scourge_hulkAI : public ScriptedAI { - summons.Despawn(summon); - } + npc_scourge_hulkAI(Creature* creature) : ScriptedAI(creature) { } - void UpdateAI(const uint32 diff) - { - if (Phase == NORMAL) + uint32 mightyBlow; + uint32 volatileInfection; + + void Reset() + { + mightyBlow = urand(4000, 9000); + volatileInfection = urand(10000, 14000); + killedByRitualStrike = false; + } + + uint32 GetData(uint32 type) + { + return type == DATA_INCREDIBLE_HULK ? killedByRitualStrike : 0; + } + + void DamageTaken(Unit* attacker, uint32 &damage) + { + if (damage >= me->GetHealth() && attacker->GetEntry() == CREATURE_SVALA_SORROWGRAVE) + killedByRitualStrike = true; + } + + void UpdateAI(uint32 const diff) { - //Return since we have no target if (!UpdateVictim()) return; - if (uiSinsterStrikeTimer <= diff) + if (mightyBlow <= diff) { - DoCast(me->getVictim(), SPELL_SINSTER_STRIKE); - uiSinsterStrikeTimer = urand(5 * IN_MILLISECONDS, 9 * IN_MILLISECONDS); - } else uiSinsterStrikeTimer -= diff; - - if (uiCallFlamesTimer <= diff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoCast(target, SPELL_CALL_FLAMES); - uiCallFlamesTimer = urand(8 * IN_MILLISECONDS, 12 * IN_MILLISECONDS); - } - } else uiCallFlamesTimer -= diff; + if (Unit* victim = me->getVictim()) + if (!victim->HasUnitState(UNIT_STAT_STUNNED)) // Prevent knocking back a ritual player + DoCast(victim, SPELL_MIGHTY_BLOW); + mightyBlow = urand(12000, 17000); + } + else + mightyBlow -= diff; - if (!bSacrificed) + if (volatileInfection <= diff) { - if (uiRitualOfSwordTimer <= diff) - { - if (Unit* pSacrificeTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoScriptText(RAND(SAY_SACRIFICE_PLAYER_1, SAY_SACRIFICE_PLAYER_2, SAY_SACRIFICE_PLAYER_3, SAY_SACRIFICE_PLAYER_4, SAY_SACRIFICE_PLAYER_5), me); - DoCast(pSacrificeTarget, SPELL_RITUAL_OF_THE_SWORD); - //Spell doesn't teleport - DoTeleportPlayer(pSacrificeTarget, 296.632f, -346.075f, 90.63f, 4.6f); - me->SetUnitMovementFlags(MOVEMENTFLAG_CAN_FLY); - DoTeleportTo(296.632f, -346.075f, 120.85f); - Phase = SACRIFICING; - if (instance) - { - instance->SetData64(DATA_SACRIFICED_PLAYER, pSacrificeTarget->GetGUID()); - - for (uint8 i = 0; i < 3; ++i) - if (Creature* summon = me->SummonCreature(CREATURE_RITUAL_CHANNELER, RitualChannelerPos[i], TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 360000)) - summon->AI()->DoAction(0); - } - - bSacrificed = true; - } - } else uiRitualOfSwordTimer -= diff; + DoCastVictim(SPELL_VOLATILE_INFECTION); + volatileInfection = urand(13000, 17000); } + else + volatileInfection -= diff; DoMeleeAttackIfReady(); } - else //SACRIFICING - { - if (uiSacrificeTimer <= diff) - { - Unit* pSacrificeTarget = instance ? Unit::GetUnit(*me, instance->GetData64(DATA_SACRIFICED_PLAYER)) : NULL; - if (instance && !summons.empty() && pSacrificeTarget && pSacrificeTarget->isAlive()) - me->Kill(pSacrificeTarget, false); // durability damage? - - //go down - Phase = NORMAL; - pSacrificeTarget = NULL; - me->SetUnitMovementFlags(MOVEMENTFLAG_WALKING); - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - me->GetMotionMaster()->MoveChase(target); - uiSacrificeTimer = 8 * IN_MILLISECONDS; - } - else uiSacrificeTimer -= diff; - } - } + private: + bool killedByRitualStrike; + }; - void KilledUnit(Unit* /*victim*/) + CreatureAI* GetAI(Creature* creature) const { - DoScriptText(RAND(SAY_SLAY_1, SAY_SLAY_2, SAY_SLAY_3), me); + return new npc_scourge_hulkAI(creature); } +}; - void JustDied(Unit* killer) - { - if (instance) - { - Creature* pSvala = Unit::GetCreature((*me), instance->GetData64(DATA_SVALA)); - if (pSvala && pSvala->isAlive()) - killer->Kill(pSvala); +class achievement_incredible_hulk : public AchievementCriteriaScript +{ + public: + achievement_incredible_hulk() : AchievementCriteriaScript("achievement_incredible_hulk") { } - instance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, DONE); - } - DoScriptText(SAY_DEATH, me); + bool OnCheck(Player* /*player*/, Unit* target) + { + return target && target->IsAIEnabled && target->GetAI()->GetData(DATA_INCREDIBLE_HULK); } - }; - }; void AddSC_boss_svala() { new boss_svala(); - new mob_ritual_channeler(); - new boss_svala_sorrowgrave(); + new npc_ritual_channeler(); + new npc_spectator(); + new spell_paralyze_pinnacle(); + new npc_scourge_hulk(); + new achievement_incredible_hulk(); } diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_pinnacle.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_pinnacle.cpp index c5bc235da1f..cb596f284c5 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_pinnacle.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_pinnacle.cpp @@ -170,8 +170,12 @@ public: void SetData64(uint32 type, uint64 data) { - if (type == DATA_SACRIFICED_PLAYER) - uiSacrificedPlayer = data; + switch (type) + { + case DATA_SACRIFICED_PLAYER: + uiSacrificedPlayer = data; + break; + } } uint32 GetData(uint32 type) @@ -201,6 +205,7 @@ public: case DATA_MOB_ORB: return uiPalehoofOrb; case DATA_SVALA: return uiSvala; case DATA_GORTOK_PALEHOOF_SPHERE: return uiGortokPalehoofSphere; + case DATA_SACRIFICED_PLAYER: return uiSacrificedPlayer; } return 0; diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/utgarde_pinnacle.h b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/utgarde_pinnacle.h index 7d10483ca1d..872314ee25e 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/utgarde_pinnacle.h +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/utgarde_pinnacle.h @@ -53,7 +53,7 @@ enum eCreatures MOB_MASSIVE_JORMUNGAR = 26685, MOB_FEROCIOUS_RHINO = 26686, MOB_SVALA = 29281, - MOB_PALEHOOF_ORB = 26688, + MOB_PALEHOOF_ORB = 26688 }; #endif diff --git a/src/server/scripts/Northrend/grizzly_hills.cpp b/src/server/scripts/Northrend/grizzly_hills.cpp index de0c6a909ad..9eb73463795 100644 --- a/src/server/scripts/Northrend/grizzly_hills.cpp +++ b/src/server/scripts/Northrend/grizzly_hills.cpp @@ -16,115 +16,9 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Grizzly_Hills -SD%Complete: 80 -SDComment: Quest support: 12231, 12247 -SDCategory: Grizzly Hills -EndScriptData */ - -/* ContentData -npc_orsonn_and_kodian -EndContentData */ - #include "ScriptPCH.h" #include "ScriptedEscortAI.h" -#define GOSSIP_ITEM1 "You're free to go Orsonn, but first tell me what's wrong with the furbolg." -#define GOSSIP_ITEM2 "What happened then?" -#define GOSSIP_ITEM3 "Thank you, Son of Ursoc. I'll see what can be done." -#define GOSSIP_ITEM4 "Who was this stranger?" -#define GOSSIP_ITEM5 "Thank you, Kodian. I'll do what I can." - -enum eEnums -{ - GOSSIP_TEXTID_ORSONN1 = 12793, - GOSSIP_TEXTID_ORSONN2 = 12794, - GOSSIP_TEXTID_ORSONN3 = 12796, - - GOSSIP_TEXTID_KODIAN1 = 12797, - GOSSIP_TEXTID_KODIAN2 = 12798, - - NPC_ORSONN = 27274, - NPC_KODIAN = 27275, - - //trigger creatures - NPC_ORSONN_CREDIT = 27322, - NPC_KODIAN_CREDIT = 27321, - - QUEST_CHILDREN_OF_URSOC = 12247, - QUEST_THE_BEAR_GODS_OFFSPRING = 12231 -}; - -class npc_orsonn_and_kodian : public CreatureScript -{ -public: - npc_orsonn_and_kodian() : CreatureScript("npc_orsonn_and_kodian") { } - - bool OnGossipHello(Player* player, Creature* creature) - { - if (creature->isQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (player->GetQuestStatus(QUEST_CHILDREN_OF_URSOC) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(QUEST_THE_BEAR_GODS_OFFSPRING) == QUEST_STATUS_INCOMPLETE) - { - switch (creature->GetEntry()) - { - case NPC_ORSONN: - if (!player->GetReqKillOrCastCurrentCount(QUEST_CHILDREN_OF_URSOC, NPC_ORSONN_CREDIT) || !player->GetReqKillOrCastCurrentCount(QUEST_THE_BEAR_GODS_OFFSPRING, NPC_ORSONN_CREDIT)) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ORSONN1, creature->GetGUID()); - return true; - } - break; - case NPC_KODIAN: - if (!player->GetReqKillOrCastCurrentCount(QUEST_CHILDREN_OF_URSOC, NPC_KODIAN_CREDIT) || !player->GetReqKillOrCastCurrentCount(QUEST_THE_BEAR_GODS_OFFSPRING, NPC_KODIAN_CREDIT)) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_KODIAN1, creature->GetGUID()); - return true; - } - break; - } - } - - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - return true; - } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*uiSender*/, uint32 uiAction) - { - player->PlayerTalkClass->ClearMenus(); - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ORSONN2, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ORSONN3, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - player->CLOSE_GOSSIP_MENU(); - player->TalkedToCreature(NPC_ORSONN_CREDIT, creature->GetGUID()); - break; - - case GOSSIP_ACTION_INFO_DEF+4: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); - player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_KODIAN2, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - player->CLOSE_GOSSIP_MENU(); - player->TalkedToCreature(NPC_KODIAN_CREDIT, creature->GetGUID()); - break; - } - - return true; - } -}; - /*###### ## Quest 12027: Mr. Floppy's Perilous Adventure ######*/ @@ -801,7 +695,6 @@ public: void AddSC_grizzly_hills() { - new npc_orsonn_and_kodian; new npc_emily; new npc_mrfloppy; new npc_outhouse_bunny; diff --git a/src/server/scripts/Outland/CMakeLists.txt b/src/server/scripts/Outland/CMakeLists.txt index ffd9332c8aa..229f7de72ec 100644 --- a/src/server/scripts/Outland/CMakeLists.txt +++ b/src/server/scripts/Outland/CMakeLists.txt @@ -45,6 +45,7 @@ set(scripts_STAT_SRCS Outland/CoilfangReservoir/underbog/boss_hungarfen.cpp Outland/CoilfangReservoir/underbog/boss_the_black_stalker.cpp Outland/shattrath_city.cpp + Outland/TempestKeep/Mechanar/boss_mechano_lord_capacitus.cpp Outland/TempestKeep/Mechanar/boss_pathaleon_the_calculator.cpp Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp Outland/TempestKeep/Mechanar/mechanar.h diff --git a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_mechano_lord_capacitus.cpp b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_mechano_lord_capacitus.cpp new file mode 100644 index 00000000000..070c107e61d --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_mechano_lord_capacitus.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +//! TODO - Boss not scripted, just ported required spellscript from core + +enum Spells +{ + SPELL_POSITIVE_CHARGE = 39090, + SPELL_POSITIVE_CHARGE_STACK = 39089, + SPELL_NEGATIVE_CHARGE = 39093, + SPELL_NEGATIVE_CHARGE_STACK = 39092 +}; + +class spell_capacitus_polarity_shift : public SpellScriptLoader +{ + public: + spell_capacitus_polarity_shift() : SpellScriptLoader("spell_capacitus_polarity_shift") { } + + class spell_capacitus_polarity_shift_SpellScript : public SpellScript + { + PrepareSpellScript(spell_capacitus_polarity_shift_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_POSITIVE_CHARGE)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_POSITIVE_CHARGE_STACK)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_NEGATIVE_CHARGE)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_NEGATIVE_CHARGE_STACK)) + return false; + return true; + } + + void HandleTargets(std::list<Unit*>& targetList) + { + uint8 count = 0; + for (std::list<Unit*>::iterator ihit = targetList.begin(); ihit != targetList.end(); ++ihit) + if ((*ihit)->GetGUID() != GetCaster()->GetGUID()) + if (Player* target = (*ihit)->ToPlayer()) + if (target->HasAura(GetTriggeringSpell()->Id)) + ++count; + + if (count) + { + uint32 spellId = 0; + + if (GetSpellInfo()->Id == SPELL_POSITIVE_CHARGE) + spellId = SPELL_POSITIVE_CHARGE_STACK; + else // if (GetSpellInfo()->Id == SPELL_NEGATIVE_CHARGE) + spellId = SPELL_NEGATIVE_CHARGE_STACK; + + GetCaster()->SetAuraStack(spellId, GetCaster(), count); + } + } + + void HandleDamage(SpellEffIndex /*effIndex*/) + { + if (!GetTriggeringSpell()) + return; + + Unit* target = GetHitUnit(); + + if (target->HasAura(GetTriggeringSpell()->Id)) + SetHitDamage(0); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_capacitus_polarity_shift_SpellScript::HandleDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + OnUnitTargetSelect += SpellUnitTargetFn(spell_capacitus_polarity_shift_SpellScript::HandleTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_capacitus_polarity_shift_SpellScript(); + } +}; + +void AddSC_boss_mechano_lord_capacitus() +{ + new spell_capacitus_polarity_shift(); +} diff --git a/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp b/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp index 78acd88c894..db95f60f556 100644 --- a/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp +++ b/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp @@ -38,19 +38,18 @@ EndContentData */ enum eMillhouseSays { - SAY_INTRO_1 = -1552010, - SAY_INTRO_2 = -1552011, - SAY_WATER = -1552012, - SAY_BUFFS = -1552013, - SAY_DRINK = -1552014, - SAY_READY = -1552015, - SAY_KILL_1 = -1552016, - SAY_KILL_2 = -1552017, - SAY_PYRO = -1552018, - SAY_ICEBLOCK = -1552019, - SAY_LOWHP = -1552020, - SAY_DEATH = -1552021, - SAY_COMPLETE = -1552022, + SAY_INTRO_1 = 0, + SAY_INTRO_2 = 1, + SAY_WATER = 2, + SAY_BUFFS = 3, + SAY_DRINK = 4, + SAY_READY = 5, + SAY_KILL = 6, + SAY_PYRO = 7, + SAY_ICEBLOCK = 8, + SAY_LOWHP = 9, + SAY_DEATH = 10, + SAY_COMPLETE = 11, }; enum eMillhouseSpells @@ -107,7 +106,7 @@ class npc_millhouse_manastorm : public CreatureScript Init = true; if (instance->GetData(TYPE_HARBINGERSKYRISS) == DONE) - DoScriptText(SAY_COMPLETE, me); + Talk(SAY_COMPLETE); } } @@ -126,12 +125,12 @@ class npc_millhouse_manastorm : public CreatureScript void KilledUnit(Unit* /*victim*/) { - DoScriptText(RAND(SAY_KILL_1, SAY_KILL_2), me); + Talk(SAY_KILL); } void JustDied(Unit* /*victim*/) { - DoScriptText(SAY_DEATH, me); + Talk(SAY_DEATH); /*for questId 10886 (heroic mode only) if (instance && instance->GetData(TYPE_HARBINGERSKYRISS) != DONE) @@ -149,30 +148,30 @@ class npc_millhouse_manastorm : public CreatureScript switch (Phase) { case 1: - DoScriptText(SAY_INTRO_1, me); + Talk(SAY_INTRO_1); EventProgress_Timer = 18000; break; case 2: - DoScriptText(SAY_INTRO_2, me); + Talk(SAY_INTRO_2); EventProgress_Timer = 18000; break; case 3: - DoScriptText(SAY_WATER, me); + Talk(SAY_WATER); DoCast(me, SPELL_CONJURE_WATER); EventProgress_Timer = 7000; break; case 4: - DoScriptText(SAY_BUFFS, me); + Talk(SAY_BUFFS); DoCast(me, SPELL_ICE_ARMOR); EventProgress_Timer = 7000; break; case 5: - DoScriptText(SAY_DRINK, me); + Talk(SAY_DRINK); DoCast(me, SPELL_ARCANE_INTELLECT); EventProgress_Timer = 7000; break; case 6: - DoScriptText(SAY_READY, me); + Talk(SAY_READY); EventProgress_Timer = 6000; break; case 7: @@ -192,7 +191,7 @@ class npc_millhouse_manastorm : public CreatureScript return; if (!LowHp && HealthBelowPct(20)) { - DoScriptText(SAY_LOWHP, me); + Talk(SAY_LOWHP); LowHp = true; } @@ -201,7 +200,7 @@ class npc_millhouse_manastorm : public CreatureScript if (me->IsNonMeleeSpellCasted(false)) return; - DoScriptText(SAY_PYRO, me); + Talk(SAY_PYRO); DoCast(me->getVictim(), SPELL_PYROBLAST); Pyroblast_Timer = 40000; @@ -232,14 +231,14 @@ class npc_millhouse_manastorm : public CreatureScript enum eWardenSays { - YELL_INTRO1 = -1552023, - YELL_INTRO2 = -1552024, - YELL_RELEASE1 = -1552025, - YELL_RELEASE2A = -1552026, - YELL_RELEASE2B = -1552027, - YELL_RELEASE3 = -1552028, - YELL_RELEASE4 = -1552029, - YELL_WELCOME = -1552030, + YELL_INTRO1 = 0, + YELL_INTRO2 = 1, + YELL_RELEASE1 = 2, + YELL_RELEASE2A = 3, + YELL_RELEASE2B = 4, + YELL_RELEASE3 = 5, + YELL_RELEASE4 = 6, + YELL_WELCOME = 7, }; enum eWardenUnits @@ -274,10 +273,10 @@ class npc_warden_mellichar : public CreatureScript { public: - npc_warden_mellichar() - : CreatureScript("npc_warden_mellichar") + npc_warden_mellichar() : CreatureScript("npc_warden_mellichar") { } + struct npc_warden_mellicharAI : public ScriptedAI { npc_warden_mellicharAI(Creature* creature) : ScriptedAI(creature) @@ -330,7 +329,7 @@ class npc_warden_mellichar : public CreatureScript void EnterCombat(Unit* /*who*/) { - DoScriptText(YELL_INTRO1, me); + Talk(YELL_INTRO1); DoCast(me, SPELL_BUBBLE_VISUAL); if (instance) @@ -437,7 +436,7 @@ class npc_warden_mellichar : public CreatureScript me->SummonCreature(ENTRY_MILLHOUSE, 413.292f, -148.378f, 42.56f, 6.27f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000); break; case 4: - DoScriptText(YELL_RELEASE2B, me); + Talk(YELL_RELEASE2B); break; case 5: switch (urand(0, 1)) @@ -463,7 +462,7 @@ class npc_warden_mellichar : public CreatureScript break; case 7: me->SummonCreature(ENTRY_SKYRISS, 445.763f, -191.639f, 44.64f, 1.60f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000); - DoScriptText(YELL_WELCOME, me); + Talk(YELL_WELCOME); break; } CanSpawn = false; @@ -474,17 +473,17 @@ class npc_warden_mellichar : public CreatureScript switch (Phase) { case 1: - DoScriptText(YELL_INTRO2, me); + Talk(YELL_INTRO2); EventProgress_Timer = 10000; ++Phase; break; case 2: - DoScriptText(YELL_RELEASE1, me); + Talk(YELL_RELEASE1); DoPrepareForPhase(); EventProgress_Timer = 7000; break; case 3: - DoScriptText(YELL_RELEASE2A, me); + Talk(YELL_RELEASE2A); DoPrepareForPhase(); EventProgress_Timer = 10000; break; @@ -493,12 +492,12 @@ class npc_warden_mellichar : public CreatureScript EventProgress_Timer = 15000; break; case 5: - DoScriptText(YELL_RELEASE3, me); + Talk(YELL_RELEASE3); DoPrepareForPhase(); EventProgress_Timer = 15000; break; case 6: - DoScriptText(YELL_RELEASE4, me); + Talk(YELL_RELEASE4); DoPrepareForPhase(); EventProgress_Timer = 15000; break; @@ -524,14 +523,16 @@ class npc_warden_mellichar : public CreatureScript # mob_zerekethvoidzone (this script probably not needed in future -> `creature_template_addon`.`auras`='36120 0') #####*/ -#define SPELL_VOID_ZONE_DAMAGE 36120 +enum ZerekethSpell +{ + SPELL_VOID_ZONE_DAMAGE = 36120, +}; class mob_zerekethvoidzone : public CreatureScript { public: - mob_zerekethvoidzone() - : CreatureScript("mob_zerekethvoidzone") + mob_zerekethvoidzone() : CreatureScript("mob_zerekethvoidzone") { } struct mob_zerekethvoidzoneAI : public ScriptedAI @@ -555,10 +556,10 @@ class mob_zerekethvoidzone : public CreatureScript return new mob_zerekethvoidzoneAI(creature); } }; + void AddSC_arcatraz() { new npc_millhouse_manastorm(); new npc_warden_mellichar(); new mob_zerekethvoidzone(); } - |