diff options
Diffstat (limited to 'src/server/scripts')
48 files changed, 1011 insertions, 869 deletions
diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt index c1a9435de52..938520209a0 100644 --- a/src/server/scripts/CMakeLists.txt +++ b/src/server/scripts/CMakeLists.txt @@ -47,7 +47,9 @@ message("") include_directories( ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast/Include ${CMAKE_SOURCE_DIR}/dep/g3dlite/include ${CMAKE_SOURCE_DIR}/dep/SFMT ${CMAKE_SOURCE_DIR}/dep/zlib diff --git a/src/server/scripts/Commands/cs_account.cpp b/src/server/scripts/Commands/cs_account.cpp index 3c9714ca55a..1121e4d0a2f 100644 --- a/src/server/scripts/Commands/cs_account.cpp +++ b/src/server/scripts/Commands/cs_account.cpp @@ -377,6 +377,7 @@ public: if (!AccountMgr::CheckEmail(handler->GetSession()->GetAccountId(), std::string(oldEmail))) { handler->SendSysMessage(LANG_COMMAND_WRONGEMAIL); + sScriptMgr->OnFailedEmailChange(handler->GetSession()->GetAccountId()); handler->SetSentErrorMessage(true); TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s) Character:[%s] (GUID: %u) Tried to change email, but the provided email [%s] is not equal to registration email [%s].", handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(), @@ -388,6 +389,7 @@ public: if (!AccountMgr::CheckPassword(handler->GetSession()->GetAccountId(), std::string(password))) { handler->SendSysMessage(LANG_COMMAND_WRONGOLDPASSWORD); + sScriptMgr->OnFailedEmailChange(handler->GetSession()->GetAccountId()); handler->SetSentErrorMessage(true); TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s) Character:[%s] (GUID: %u) Tried to change email, but the provided password is wrong.", handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(), @@ -398,6 +400,7 @@ public: if (strcmp(email, oldEmail) == 0) { handler->SendSysMessage(LANG_OLD_EMAIL_IS_NEW_EMAIL); + sScriptMgr->OnFailedEmailChange(handler->GetSession()->GetAccountId()); handler->SetSentErrorMessage(true); return false; } @@ -405,6 +408,7 @@ public: if (strcmp(email, emailConfirmation) != 0) { handler->SendSysMessage(LANG_NEW_EMAILS_NOT_MATCH); + sScriptMgr->OnFailedEmailChange(handler->GetSession()->GetAccountId()); handler->SetSentErrorMessage(true); TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s) Character:[%s] (GUID: %u) Tried to change email, but the provided password is wrong.", handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(), @@ -418,6 +422,7 @@ public: { case AOR_OK: handler->SendSysMessage(LANG_COMMAND_EMAIL); + sScriptMgr->OnEmailChange(handler->GetSession()->GetAccountId()); TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s) Character:[%s] (GUID: %u) Changed Email from [%s] to [%s].", handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(), handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow(), @@ -425,6 +430,7 @@ public: break; case AOR_EMAIL_TOO_LONG: handler->SendSysMessage(LANG_EMAIL_TOO_LONG); + sScriptMgr->OnFailedEmailChange(handler->GetSession()->GetAccountId()); handler->SetSentErrorMessage(true); return false; default: @@ -469,6 +475,7 @@ public: if (!AccountMgr::CheckPassword(handler->GetSession()->GetAccountId(), std::string(oldPassword))) { handler->SendSysMessage(LANG_COMMAND_WRONGOLDPASSWORD); + sScriptMgr->OnFailedPasswordChange(handler->GetSession()->GetAccountId()); handler->SetSentErrorMessage(true); TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s) Character:[%s] (GUID: %u) Tried to change password, but the provided old password is wrong.", handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(), @@ -481,6 +488,7 @@ public: && !AccountMgr::CheckEmail(handler->GetSession()->GetAccountId(), std::string(emailConfirmation))) // ... and returns false if the comparison fails. { handler->SendSysMessage(LANG_COMMAND_WRONGEMAIL); + sScriptMgr->OnFailedPasswordChange(handler->GetSession()->GetAccountId()); handler->SetSentErrorMessage(true); TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s) Character:[%s] (GUID: %u) Tried to change password, but the entered email [%s] is wrong.", handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(), @@ -493,6 +501,7 @@ public: if (strcmp(newPassword, passwordConfirmation) != 0) { handler->SendSysMessage(LANG_NEW_PASSWORDS_NOT_MATCH); + sScriptMgr->OnFailedPasswordChange(handler->GetSession()->GetAccountId()); handler->SetSentErrorMessage(true); return false; } @@ -503,12 +512,14 @@ public: { case AOR_OK: handler->SendSysMessage(LANG_COMMAND_PASSWORD); + sScriptMgr->OnPasswordChange(handler->GetSession()->GetAccountId()); TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s) Character:[%s] (GUID: %u) Changed Password.", handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(), handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow()); break; case AOR_PASS_TOO_LONG: handler->SendSysMessage(LANG_PASSWORD_TOO_LONG); + sScriptMgr->OnFailedPasswordChange(handler->GetSession()->GetAccountId()); handler->SetSentErrorMessage(true); return false; default: diff --git a/src/server/scripts/Commands/cs_go.cpp b/src/server/scripts/Commands/cs_go.cpp index 3c1fa973cd8..44ebb1ea4e0 100644 --- a/src/server/scripts/Commands/cs_go.cpp +++ b/src/server/scripts/Commands/cs_go.cpp @@ -29,6 +29,7 @@ EndScriptData */ #include "Chat.h" #include "Language.h" #include "Player.h" +#include "Transport.h" class go_commandscript : public CommandScript { @@ -132,21 +133,24 @@ public: float x = fields[0].GetFloat(); float y = fields[1].GetFloat(); float z = fields[2].GetFloat(); - float ort = fields[3].GetFloat(); - int mapId = fields[4].GetUInt16(); + float o = fields[3].GetFloat(); + uint32 mapId = fields[4].GetUInt16(); uint32 guid = fields[5].GetUInt32(); uint32 id = fields[6].GetUInt32(); - // if creature is in same map with caster go at its current location - if (Creature* creature = sObjectAccessor->GetCreature(*player, MAKE_NEW_GUID(guid, id, HIGHGUID_UNIT))) + Transport* transport = NULL; + + if (Creature* creature = ObjectAccessor::GetObjectInWorld(MAKE_NEW_GUID(guid, id, HIGHGUID_UNIT), (Creature*)NULL)) { x = creature->GetPositionX(); y = creature->GetPositionY(); z = creature->GetPositionZ(); - ort = creature->GetOrientation(); + o = creature->GetOrientation(); + mapId = creature->GetMapId(); + transport = creature->GetTransport(); } - if (!MapManager::IsValidMapCoord(mapId, x, y, z, ort)) + if (!MapManager::IsValidMapCoord(mapId, x, y, z, o) || sObjectMgr->IsTransportMap(mapId)) { handler->PSendSysMessage(LANG_INVALID_TARGET_COORD, x, y, mapId); handler->SetSentErrorMessage(true); @@ -163,7 +167,11 @@ public: else player->SaveRecallPosition(); - player->TeleportTo(mapId, x, y, z, ort); + if (player->TeleportTo(mapId, x, y, z, o)) + { + if (transport) + transport->AddPassenger(player); + } return true; } @@ -274,8 +282,8 @@ public: if (!guid) return false; - float x, y, z, ort; - int mapId; + float x, y, z, o; + uint32 mapId; // by DB guid if (GameObjectData const* goData = sObjectMgr->GetGOData(guid)) @@ -283,7 +291,7 @@ public: x = goData->posX; y = goData->posY; z = goData->posZ; - ort = goData->orientation; + o = goData->orientation; mapId = goData->mapid; } else @@ -293,7 +301,7 @@ public: return false; } - if (!MapManager::IsValidMapCoord(mapId, x, y, z, ort)) + if (!MapManager::IsValidMapCoord(mapId, x, y, z, o) || sObjectMgr->IsTransportMap(mapId)) { handler->PSendSysMessage(LANG_INVALID_TARGET_COORD, x, y, mapId); handler->SetSentErrorMessage(true); @@ -310,7 +318,7 @@ public: else player->SaveRecallPosition(); - player->TeleportTo(mapId, x, y, z, ort); + player->TeleportTo(mapId, x, y, z, o); return true; } diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index 28d49fe11aa..9cf8c041883 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -43,6 +43,7 @@ struct EnumName #define CREATE_NAMED_ENUM(VALUE) { VALUE, STRINGIZE(VALUE) } #define NPCFLAG_COUNT 24 +#define FLAGS_EXTRA_COUNT 16 EnumName<NPCFlags, int32> const npcFlagTexts[NPCFLAG_COUNT] = { @@ -144,6 +145,26 @@ EnumName<UnitFlags> const unitFlags[MAX_UNIT_FLAGS] = CREATE_NAMED_ENUM(UNIT_FLAG_UNK_31) }; +EnumName<CreatureFlagsExtra> const flagsExtra[FLAGS_EXTRA_COUNT] = +{ + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_INSTANCE_BIND), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_CIVILIAN), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_NO_PARRY), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_NO_PARRY_HASTEN), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_NO_BLOCK), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_NO_CRUSH), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_NO_XP_AT_KILL), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_TRIGGER), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_NO_TAUNT), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_WORLDEVENT), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_GUARD), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_NO_CRIT), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_NO_SKILLGAIN), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_TAUNT_DIMINISH), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_ALL_DIMINISH), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_DUNGEON_BOSS) +}; + class npc_commandscript : public CommandScript { public: @@ -730,6 +751,10 @@ public: handler->PSendSysMessage(LANG_NPCINFO_ARMOR, target->GetArmor()); handler->PSendSysMessage(LANG_NPCINFO_POSITION, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ()); handler->PSendSysMessage(LANG_NPCINFO_AIINFO, target->GetAIName().c_str(), target->GetScriptName().c_str()); + handler->PSendSysMessage(LANG_NPCINFO_FLAGS_EXTRA, cInfo->flags_extra); + for (uint8 i = 0; i < FLAGS_EXTRA_COUNT; ++i) + if (cInfo->flags_extra & flagsExtra[i].Value) + handler->PSendSysMessage("%s (0x%X)", flagsExtra[i].Name, flagsExtra[i].Value); for (uint8 i = 0; i < NPCFLAG_COUNT; i++) if (npcflags & npcFlagTexts[i].Value) diff --git a/src/server/scripts/Custom/CMakeLists.txt b/src/server/scripts/Custom/CMakeLists.txt index 78db719ae6e..80ebe36b555 100644 --- a/src/server/scripts/Custom/CMakeLists.txt +++ b/src/server/scripts/Custom/CMakeLists.txt @@ -8,8 +8,11 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# file(GLOB_RECURSE sources_Custom Custom/*.cpp Custom/*.h) + set(scripts_STAT_SRCS ${scripts_STAT_SRCS} +# ${sources_Custom} ) message(" -> Prepared: Custom") diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_golemagg.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_golemagg.cpp index 2a473754ce6..f9757997731 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_golemagg.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_golemagg.cpp @@ -144,7 +144,7 @@ class npc_core_rager : public CreatureScript if (HealthAbovePct(50) || !instance) return; - if (Creature* pGolemagg = instance->instance->GetCreature(instance->GetData64(BOSS_GOLEMAGG_THE_INCINERATOR))) + if (Creature* pGolemagg = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_GOLEMAGG_THE_INCINERATOR))) { if (pGolemagg->IsAlive()) { diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp index 3c4b372808b..7944011c7a0 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp @@ -150,14 +150,14 @@ public: Phase = 0; - instance->SetData(DATA_KAELTHAS_EVENT, NOT_STARTED); + instance->SetBossState(DATA_KAELTHAS, NOT_STARTED); } void JustDied(Unit* /*killer*/) override { Talk(SAY_DEATH); - instance->SetData(DATA_KAELTHAS_EVENT, DONE); + instance->SetBossState(DATA_KAELTHAS, DONE); // Enable the Translocation Orb Exit if (GameObject* escapeOrb = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_ESCAPE_ORB))) @@ -172,7 +172,7 @@ public: void EnterCombat(Unit* /*who*/) override { - instance->SetData(DATA_KAELTHAS_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_KAELTHAS, IN_PROGRESS); } void MoveInLineOfSight(Unit* who) override @@ -515,7 +515,7 @@ public: return; } //Don't really die in all phases of Kael'Thas - if (instance->GetData(DATA_KAELTHAS_EVENT) == 0) + if (instance->GetBossState(DATA_KAELTHAS) == 0) { //prevent death damage = 0; diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp index 8dc8ff799ba..2af9d9b1567 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp @@ -153,7 +153,7 @@ public: //this mean she at some point evaded void JustReachedHome() override { - instance->SetData(DATA_DELRISSA_EVENT, FAIL); + instance->SetBossState(DATA_DELRISSA, FAIL); } void EnterCombat(Unit* who) override @@ -172,7 +172,7 @@ public: } } - instance->SetData(DATA_DELRISSA_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_DELRISSA, IN_PROGRESS); } void InitializeLackeys() @@ -240,7 +240,7 @@ public: Talk(SAY_DEATH); if (instance->GetData(DATA_DELRISSA_DEATH_COUNT) == MAX_ACTIVE_LACKEY) - instance->SetData(DATA_DELRISSA_EVENT, DONE); + instance->SetBossState(DATA_DELRISSA, DONE); else { if (me->HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE)) @@ -434,7 +434,7 @@ struct boss_priestess_lackey_commonAI : public ScriptedAI if (!pDelrissa->HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE)) pDelrissa->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - instance->SetData(DATA_DELRISSA_EVENT, DONE); + instance->SetBossState(DATA_DELRISSA, DONE); } } } diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp index d77f5db9cea..d6c0f95f967 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp @@ -119,7 +119,7 @@ public: } // Set Inst data for encounter - instance->SetData(DATA_SELIN_EVENT, NOT_STARTED); + instance->SetBossState(DATA_SELIN, NOT_STARTED); DrainLifeTimer = urand(3000, 7000); DrainManaTimer = DrainLifeTimer + 5000; @@ -194,7 +194,7 @@ public: void EnterCombat(Unit* /*who*/) override { Talk(SAY_AGGRO); - instance->SetData(DATA_SELIN_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_SELIN, IN_PROGRESS); } void KilledUnit(Unit* /*victim*/) override @@ -228,7 +228,7 @@ public: { Talk(SAY_DEATH); - instance->SetData(DATA_SELIN_EVENT, DONE); // Encounter complete! + instance->SetBossState(DATA_SELIN, DONE); // Encounter complete! ShatterRemainingCrystals(); } @@ -351,7 +351,7 @@ public: } } } - } else TC_LOG_ERROR("scripts", ERROR_INST_DATA); + } } }; }; diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp index 58b9ef12095..b9930820303 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * * 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 @@ -16,13 +15,6 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Boss_Vexallus -SD%Complete: 90 -SDComment: Heroic and Normal support. Needs further testing. -SDCategory: Magister's Terrace -EndScriptData */ - #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "magisters_terrace.h" @@ -41,26 +33,22 @@ enum Yells enum Spells { - // Pure energy spell info - SPELL_ENERGY_BOLT = 46156, - SPELL_ENERGY_FEEDBACK = 44335, - - // Vexallus spell info SPELL_CHAIN_LIGHTNING = 44318, - SPELL_H_CHAIN_LIGHTNING = 46380, // heroic spell SPELL_OVERLOAD = 44353, SPELL_ARCANE_SHOCK = 44319, - SPELL_H_ARCANE_SHOCK = 46381, // heroic spell SPELL_SUMMON_PURE_ENERGY = 44322, // mod scale -10 H_SPELL_SUMMON_PURE_ENERGY1 = 46154, // mod scale -5 H_SPELL_SUMMON_PURE_ENERGY2 = 46159 // mod scale -5 - }; -enum Creatures +enum Events { - NPC_PURE_ENERGY = 24745, + EVENT_ENERGY_BOLT = 1, + EVENT_ENERGY_FEEDBACK, + EVENT_CHAIN_LIGHTNING, + EVENT_OVERLOAD, + EVENT_ARCANE_SHOCK }; enum Misc @@ -71,170 +59,160 @@ enum Misc class boss_vexallus : public CreatureScript { -public: - boss_vexallus() : CreatureScript("boss_vexallus") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<boss_vexallusAI>(creature); - }; - - struct boss_vexallusAI : public BossAI - { - boss_vexallusAI(Creature* creature) : BossAI(creature, DATA_VEXALLUS_EVENT) - { - instance = creature->GetInstanceScript(); - } - - InstanceScript* instance; + public: + boss_vexallus() : CreatureScript("boss_vexallus") { } - uint32 ChainLightningTimer; - uint32 ArcaneShockTimer; - uint32 OverloadTimer; - uint32 IntervalHealthAmount; - bool Enraged; - - void Reset() override + struct boss_vexallusAI : public BossAI { - summons.DespawnAll(); - ChainLightningTimer = 8000; - ArcaneShockTimer = 5000; - OverloadTimer = 1200; - IntervalHealthAmount = 1; - Enraged = false; - - instance->SetData(DATA_VEXALLUS_EVENT, NOT_STARTED); - } + boss_vexallusAI(Creature* creature) : BossAI(creature, DATA_VEXALLUS) + { + _intervalHealthAmount = 1; + _enraged = false; + } - void KilledUnit(Unit* /*victim*/) override - { - Talk(SAY_KILL); - } + void Reset() override + { + _Reset(); + _intervalHealthAmount = 1; + _enraged = false; + } - void JustDied(Unit* /*killer*/) override - { - summons.DespawnAll(); - instance->SetData(DATA_VEXALLUS_EVENT, DONE); - } + void KilledUnit(Unit* /*victim*/) override + { + Talk(SAY_KILL); + } - void EnterCombat(Unit* /*who*/) override - { - Talk(SAY_AGGRO); + void JustDied(Unit* /*killer*/) override + { + _JustDied(); + } - instance->SetData(DATA_VEXALLUS_EVENT, IN_PROGRESS); - } + void EnterCombat(Unit* /*who*/) override + { + Talk(SAY_AGGRO); + _EnterCombat(); - void JustSummoned(Creature* summoned) override - { - if (Unit* temp = SelectTarget(SELECT_TARGET_RANDOM, 0)) - summoned->GetMotionMaster()->MoveFollow(temp, 0, 0); + events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 8000); + events.ScheduleEvent(EVENT_ARCANE_SHOCK, 5000); + } - //spells are SUMMON_TYPE_GUARDIAN, so using setOwner should be ok - summoned->CastSpell(summoned, SPELL_ENERGY_BOLT, false, 0, 0, me->GetGUID()); - } + void JustSummoned(Creature* summoned) override + { + if (Unit* temp = SelectTarget(SELECT_TARGET_RANDOM, 0)) + summoned->GetMotionMaster()->MoveFollow(temp, 0, 0); - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; + summons.Summon(summoned); + } - if (!Enraged) + void DamageTaken(Unit* /*who*/, uint32& /*damage*/) override { - //used for check, when Vexallus cast adds 85%, 70%, 55%, 40%, 25% - if (!HealthAbovePct(100 - INTERVAL_MODIFIER * IntervalHealthAmount)) + if (_enraged) + return; + + // 85%, 70%, 55%, 40%, 25% + if (!HealthAbovePct(100 - INTERVAL_MODIFIER * _intervalHealthAmount)) { - //increase amount, unless we're at 10%, then we switch and return - if (IntervalHealthAmount == INTERVAL_SWITCH) + // increase amount, unless we're at 10%, then we switch and return + if (_intervalHealthAmount == INTERVAL_SWITCH) { - Enraged = true; + _enraged = true; + events.Reset(); + events.ScheduleEvent(EVENT_OVERLOAD, 1200); return; } else - ++IntervalHealthAmount; + ++_intervalHealthAmount; Talk(SAY_ENERGY); Talk(EMOTE_DISCHARGE_ENERGY); if (IsHeroic()) { - DoCast(me, H_SPELL_SUMMON_PURE_ENERGY1, false); - DoCast(me, H_SPELL_SUMMON_PURE_ENERGY2, false); + DoCast(me, H_SPELL_SUMMON_PURE_ENERGY1); + DoCast(me, H_SPELL_SUMMON_PURE_ENERGY2); } else - DoCast(me, SPELL_SUMMON_PURE_ENERGY, false); - - //below are workaround summons, remove when summoning spells w/implicitTarget 73 implemented in the core - me->SummonCreature(NPC_PURE_ENERGY, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0); - - if (IsHeroic()) - me->SummonCreature(NPC_PURE_ENERGY, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoCast(me, SPELL_SUMMON_PURE_ENERGY); } + } - if (ChainLightningTimer <= diff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(target, SPELL_CHAIN_LIGHTNING); + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - ChainLightningTimer = 8000; - } else ChainLightningTimer -= diff; + events.Update(diff); - if (ArcaneShockTimer <= diff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - if (target) - DoCast(target, SPELL_ARCANE_SHOCK); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - ArcaneShockTimer = 8000; - } else ArcaneShockTimer -= diff; - } - else - { - if (OverloadTimer <= diff) + while (uint32 eventId = events.ExecuteEvent()) { - DoCastVictim(SPELL_OVERLOAD); + switch (eventId) + { + case EVENT_CHAIN_LIGHTNING: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) + DoCast(target, SPELL_CHAIN_LIGHTNING); + events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 8000); + break; + case EVENT_ARCANE_SHOCK: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 20.0f, true)) + DoCast(target, SPELL_ARCANE_SHOCK); + events.ScheduleEvent(EVENT_ARCANE_SHOCK, 8000); + break; + case EVENT_OVERLOAD: + DoCastVictim(SPELL_OVERLOAD); + events.ScheduleEvent(EVENT_OVERLOAD, 2000); + break; + default: + break; + } + } - OverloadTimer = 2000; - } else OverloadTimer -= diff; + DoMeleeAttackIfReady(); } - DoMeleeAttackIfReady(); - } - }; + private: + uint32 _intervalHealthAmount; + bool _enraged; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<boss_vexallusAI>(creature); + }; }; -class npc_pure_energy : public CreatureScript +enum NpcPureEnergy { -public: - npc_pure_energy() : CreatureScript("npc_pure_energy") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_pure_energyAI(creature); - }; - - struct npc_pure_energyAI : public ScriptedAI - { - npc_pure_energyAI(Creature* creature) : ScriptedAI(creature) - { - me->SetDisplayId(me->GetCreatureTemplate()->Modelid2); - } + SPELL_ENERGY_BOLT = 46156, + SPELL_ENERGY_FEEDBACK = 44335, + SPELL_PURE_ENERGY_PASSIVE = 44326 +}; - void Reset() override { } +class npc_pure_energy : public CreatureScript +{ + public: + npc_pure_energy() : CreatureScript("npc_pure_energy") { } - void JustDied(Unit* slayer) override + struct npc_pure_energyAI : public ScriptedAI { - if (Unit* temp = me->GetOwner()) + npc_pure_energyAI(Creature* creature) : ScriptedAI(creature) { - if (temp && temp->IsAlive()) - slayer->CastSpell(slayer, SPELL_ENERGY_FEEDBACK, true, 0, 0, temp->GetGUID()); + me->SetDisplayId(me->GetCreatureTemplate()->Modelid2); } - } - void EnterCombat(Unit* /*who*/) override { } - void MoveInLineOfSight(Unit* /*who*/) override { } + void JustDied(Unit* killer) override + { + killer->CastSpell(killer, SPELL_ENERGY_FEEDBACK, true); + me->RemoveAurasDueToSpell(SPELL_PURE_ENERGY_PASSIVE); + } + }; - void AttackStart(Unit* /*who*/) override { } - }; + CreatureAI* GetAI(Creature* creature) const override + { + return new npc_pure_energyAI(creature); + }; }; void AddSC_boss_vexallus() diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp index daea647609d..e0050420a08 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * * 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 @@ -16,19 +15,10 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Instance_Magisters_Terrace -SD%Complete: 60 -SDComment: Designed only for Selin Fireheart -SDCategory: Magister's Terrace -EndScriptData */ - #include "ScriptMgr.h" #include "InstanceScript.h" #include "magisters_terrace.h" -#define MAX_ENCOUNTER 4 - /* 0 - Selin Fireheart 1 - Vexallus @@ -36,281 +26,239 @@ EndScriptData */ 3 - Kael'thas Sunstrider */ -enum Creatures +DoorData const doorData[] = { - NPC_SELIN = 24723, - NPC_DELRISSA = 24560, - NPC_FELCRYSTALS = 24722 -}; - -enum GameObjects -{ - GO_VEXALLUS_DOOR = 187896, - GO_SELIN_DOOR = 187979, - GO_SELIN_ENCOUNTER_DOOR = 188065, - GO_DELRISSA_DOOR = 187770, - GO_KAEL_DOOR = 188064, - GO_KAEL_STATUE_1 = 188165, - GO_KAEL_STATUE_2 = 188166, - GO_ESCAPE_ORB = 188173 + { GO_SELIN_DOOR, DATA_SELIN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_SELIN_ENCOUNTER_DOOR, DATA_SELIN, DOOR_TYPE_ROOM, BOUNDARY_NONE }, + { GO_VEXALLUS_DOOR, DATA_VEXALLUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_DELRISSA_DOOR, DATA_DELRISSA, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_KAEL_DOOR, DATA_KAELTHAS, DOOR_TYPE_ROOM, BOUNDARY_NONE }, + { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END }; class instance_magisters_terrace : public InstanceMapScript { -public: - instance_magisters_terrace() : InstanceMapScript("instance_magisters_terrace", 585) { } - - struct instance_magisters_terrace_InstanceMapScript : public InstanceScript - { - instance_magisters_terrace_InstanceMapScript(Map* map) : InstanceScript(map) { } - - uint32 Encounter[MAX_ENCOUNTER]; - uint32 DelrissaDeathCount; + public: + instance_magisters_terrace() : InstanceMapScript("instance_magisters_terrace", 585) { } - std::vector<uint64> FelCrystals; - - uint64 SelinGUID; - uint64 DelrissaGUID; - uint64 VexallusDoorGUID; - uint64 SelinDoorGUID; - uint64 SelinEncounterDoorGUID; - uint64 DelrissaDoorGUID; - uint64 KaelDoorGUID; - uint64 KaelStatue[2]; - uint64 EscapeOrbGUID; - uint32 StatuesState; - uint8 felCristalIndex; - - void Initialize() override + struct instance_magisters_terrace_InstanceMapScript : public InstanceScript { - memset(&Encounter, 0, sizeof(Encounter)); - - FelCrystals.clear(); + instance_magisters_terrace_InstanceMapScript(Map* map) : InstanceScript(map) + { + SetBossNumber(EncounterCount); + LoadDoorData(doorData); - DelrissaDeathCount = 0; + FelCrystals.clear(); + DelrissaDeathCount = 0; - SelinGUID = 0; - DelrissaGUID = 0; - VexallusDoorGUID = 0; - SelinDoorGUID = 0; - SelinEncounterDoorGUID = 0; - DelrissaDoorGUID = 0; - KaelDoorGUID = 0; - KaelStatue[0] = 0; - KaelStatue[1] = 0; - EscapeOrbGUID = 0; - StatuesState = 0; - felCristalIndex = 0; - } + SelinGUID = 0; + DelrissaGUID = 0; + EscapeOrbGUID = 0; + FelCristalIndex = 0; - bool IsEncounterInProgress() const override - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (Encounter[i] == IN_PROGRESS) - return true; - return false; - } + memset(KaelStatue, 0, 2 * sizeof(uint64)); + } - uint32 GetData(uint32 identifier) const - { - switch (identifier) + uint32 GetData(uint32 type) const override { - case DATA_SELIN_EVENT: - return Encounter[0]; - case DATA_VEXALLUS_EVENT: - return Encounter[1]; - case DATA_DELRISSA_EVENT: - return Encounter[2]; - case DATA_KAELTHAS_EVENT: - return Encounter[3]; - case DATA_DELRISSA_DEATH_COUNT: - return DelrissaDeathCount; - case DATA_FEL_CRYSTAL_SIZE: - return FelCrystals.size(); + switch (type) + { + case DATA_DELRISSA_DEATH_COUNT: + return DelrissaDeathCount; + case DATA_FEL_CRYSTAL_SIZE: + return uint32(FelCrystals.size()); + default: + break; + } + return 0; } - return 0; - } - void SetData(uint32 identifier, uint32 data) - { - switch (identifier) + void SetData(uint32 type, uint32 data) override { - case DATA_SELIN_EVENT: - if (data == DONE) - { - HandleGameObject(SelinEncounterDoorGUID, true); - HandleGameObject(SelinDoorGUID, true); - } - else if (data == IN_PROGRESS) - HandleGameObject(SelinEncounterDoorGUID, false); - else if (data == NOT_STARTED) - HandleGameObject(SelinEncounterDoorGUID, true); - - Encounter[0] = data; - break; - case DATA_VEXALLUS_EVENT: - if (data == DONE) - HandleGameObject(VexallusDoorGUID, true); - Encounter[1] = data; - break; - case DATA_DELRISSA_EVENT: - if (data == DONE) - HandleGameObject(DelrissaDoorGUID, true); - if (data == IN_PROGRESS) - DelrissaDeathCount = 0; - Encounter[2] = data; - break; - case DATA_KAELTHAS_EVENT: - if (data == NOT_STARTED || data == DONE) - HandleGameObject(KaelDoorGUID, true); - else if (data == IN_PROGRESS) - HandleGameObject(KaelDoorGUID, false); - Encounter[3] = data; - break; - case DATA_DELRISSA_DEATH_COUNT: - if (data == SPECIAL) - ++DelrissaDeathCount; - else - DelrissaDeathCount = 0; - break; - case DATA_KAELTHAS_STATUES: - HandleGameObject(KaelStatue[0], data); - HandleGameObject(KaelStatue[1], data); - StatuesState = data; - break; + switch (type) + { + case DATA_DELRISSA_DEATH_COUNT: + if (data == SPECIAL) + ++DelrissaDeathCount; + else + DelrissaDeathCount = 0; + break; + case DATA_KAELTHAS_STATUES: + HandleGameObject(KaelStatue[0], data); + HandleGameObject(KaelStatue[1], data); + break; + default: + break; + } } - SaveToDB(); - } - - void OnCreatureCreate(Creature* creature) override - { - switch (creature->GetEntry()) + void OnCreatureCreate(Creature* creature) override { - case NPC_SELIN: - SelinGUID = creature->GetGUID(); - break; - case NPC_DELRISSA: - DelrissaGUID = creature->GetGUID(); - break; - case NPC_FELCRYSTALS: - FelCrystals.push_back(creature->GetGUID()); - break; + switch (creature->GetEntry()) + { + case NPC_SELIN: + SelinGUID = creature->GetGUID(); + break; + case NPC_DELRISSA: + DelrissaGUID = creature->GetGUID(); + break; + case NPC_FELCRYSTALS: + FelCrystals.push_back(creature->GetGUID()); + break; + default: + break; + } } - } - void OnGameObjectCreate(GameObject* go) override - { - switch (go->GetEntry()) + void OnGameObjectCreate(GameObject* go) override { - case GO_VEXALLUS_DOOR: - VexallusDoorGUID = go->GetGUID(); - break; - case GO_SELIN_DOOR: - SelinDoorGUID = go->GetGUID(); - break; - case GO_SELIN_ENCOUNTER_DOOR: - SelinEncounterDoorGUID = go->GetGUID(); - break; - case GO_DELRISSA_DOOR: - DelrissaDoorGUID = go->GetGUID(); - break; - case GO_KAEL_DOOR: - KaelDoorGUID = go->GetGUID(); - break; - case GO_KAEL_STATUE_1: - KaelStatue[0] = go->GetGUID(); - break; - case GO_KAEL_STATUE_2: - KaelStatue[1] = go->GetGUID(); - break; - case GO_ESCAPE_ORB: - EscapeOrbGUID = go->GetGUID(); - break; + switch (go->GetEntry()) + { + case GO_VEXALLUS_DOOR: + case GO_SELIN_DOOR: + case GO_SELIN_ENCOUNTER_DOOR: + case GO_DELRISSA_DOOR: + case GO_KAEL_DOOR: + AddDoor(go, true); + break; + case GO_KAEL_STATUE_1: + KaelStatue[0] = go->GetGUID(); + break; + case GO_KAEL_STATUE_2: + KaelStatue[1] = go->GetGUID(); + break; + case GO_ESCAPE_ORB: + EscapeOrbGUID = go->GetGUID(); + break; + default: + break; + } } - } - - std::string GetSaveData() override - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << Encounter[0] << ' ' << Encounter[1] << ' ' << Encounter[2] << ' ' << Encounter[3] << ' ' << StatuesState; - OUT_SAVE_INST_DATA_COMPLETE; - return saveStream.str(); - } + void OnGameObjectRemove(GameObject* go) override + { + switch (go->GetEntry()) + { + case GO_VEXALLUS_DOOR: + case GO_SELIN_DOOR: + case GO_SELIN_ENCOUNTER_DOOR: + case GO_DELRISSA_DOOR: + case GO_KAEL_DOOR: + AddDoor(go, false); + break; + default: + break; + } + } - void Load(const char* str) override - { - if (!str) + bool SetBossState(uint32 type, EncounterState state) override { - OUT_LOAD_INST_DATA_FAIL; - return; + if (!InstanceScript::SetBossState(type, state)) + return false; + + switch (type) + { + case DATA_DELRISSA: + if (type == IN_PROGRESS) + DelrissaDeathCount = 0; + break; + default: + break; + } + return true; } - OUT_LOAD_INST_DATA(str); + std::string GetSaveData() override + { + OUT_SAVE_INST_DATA; - std::istringstream loadStream(str); + std::ostringstream saveStream; + saveStream << "M T " << GetBossSaveData(); - for (uint32 i = 0; i < MAX_ENCOUNTER; ++i) - { - uint32 tmpState; - loadStream >> tmpState; - if (tmpState == IN_PROGRESS || tmpState > SPECIAL) - tmpState = NOT_STARTED; - SetData(i, tmpState); + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); } - loadStream >> StatuesState; - SetData(DATA_KAELTHAS_STATUES, StatuesState); + void Load(const char* str) override + { + if (!str) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } - OUT_LOAD_INST_DATA_COMPLETE; - } + OUT_LOAD_INST_DATA(str); - uint64 GetData64(uint32 identifier) const - { - switch (identifier) - { - case DATA_SELIN: - return SelinGUID; - case DATA_DELRISSA: - return DelrissaGUID; - case DATA_VEXALLUS_DOOR: - return VexallusDoorGUID; - case DATA_DELRISSA_DOOR: - return DelrissaDoorGUID; - case DATA_KAEL_DOOR: - return KaelDoorGUID; - case DATA_KAEL_STATUE_LEFT: - return KaelStatue[0]; - case DATA_KAEL_STATUE_RIGHT: - return KaelStatue[1]; - case DATA_ESCAPE_ORB: - return EscapeOrbGUID; - case DATA_FEL_CRYSTAL: - if (FelCrystals.size() < felCristalIndex) + char dataHead1, dataHead2; + + std::istringstream loadStream(str); + loadStream >> dataHead1 >> dataHead2; + if (dataHead1 == 'M' && dataHead2 == 'T') + { + for (uint32 i = 0; i < EncounterCount; ++i) { - TC_LOG_ERROR("scripts", "Magisters Terrace: No Fel Crystals loaded in Inst Data"); - return 0; + uint32 tmpState; + loadStream >> tmpState; + if (tmpState == IN_PROGRESS || tmpState > SPECIAL) + tmpState = NOT_STARTED; + SetBossState(i, EncounterState(tmpState)); } + } + else + OUT_LOAD_INST_DATA_FAIL; - return FelCrystals.at(felCristalIndex); + OUT_LOAD_INST_DATA_COMPLETE; + } + + uint64 GetData64(uint32 type) const override + { + switch (type) + { + case DATA_SELIN: + return SelinGUID; + case DATA_DELRISSA: + return DelrissaGUID; + case DATA_KAEL_STATUE_LEFT: + return KaelStatue[0]; + case DATA_KAEL_STATUE_RIGHT: + return KaelStatue[1]; + case DATA_ESCAPE_ORB: + return EscapeOrbGUID; + case DATA_FEL_CRYSTAL: + if (FelCrystals.size() < FelCristalIndex) + { + TC_LOG_ERROR("scripts", "Magisters Terrace: No Fel Crystals loaded in Inst Data"); + return 0; + } + + return FelCrystals.at(FelCristalIndex); + default: + break; + } + return 0; } - return 0; - } - void SetData64(uint32 identifier, uint64 value) + void SetData64(uint32 type, uint64 value) override + { + if (type == DATA_FEL_CRYSTAL) + FelCristalIndex = value; + } + + protected: + std::vector<uint64> FelCrystals; + + uint64 SelinGUID; + uint64 DelrissaGUID; + uint64 KaelStatue[2]; + uint64 EscapeOrbGUID; + uint32 DelrissaDeathCount; + uint8 FelCristalIndex; + }; + + InstanceScript* GetInstanceScript(InstanceMap* map) const override { - if (identifier == DATA_FEL_CRYSTAL) - felCristalIndex = value; + return new instance_magisters_terrace_InstanceMapScript(map); } - }; - - InstanceScript* GetInstanceScript(InstanceMap* map) const override - { - return new instance_magisters_terrace_InstanceMapScript(map); - } }; void AddSC_instance_magisters_terrace() diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h index ddfaa91bc98..d3517dfccf6 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h @@ -19,24 +19,17 @@ #ifndef DEF_MAGISTERS_TERRACE_H #define DEF_MAGISTERS_TERRACE_H -#define ERROR_INST_DATA "TSCR Error: Instance Data not set properly for Magister's Terrace instance (map 585). Encounters will be buggy." +uint32 const EncounterCount = 4; -enum Data +enum DataTypes { - DATA_SELIN_EVENT, - DATA_VEXALLUS_EVENT, - DATA_DELRISSA_EVENT, - DATA_KAELTHAS_EVENT, - DATA_SELIN, - DATA_FEL_CRYSTAL, - DATA_FEL_CRYSTAL_SIZE, - - DATA_VEXALLUS_DOOR, + DATA_VEXALLUS, DATA_DELRISSA, - DATA_DELRISSA_DOOR, + DATA_KAELTHAS, - DATA_KAEL_DOOR, + DATA_FEL_CRYSTAL, + DATA_FEL_CRYSTAL_SIZE, DATA_KAEL_STATUE_LEFT, DATA_KAEL_STATUE_RIGHT, @@ -45,4 +38,23 @@ enum Data DATA_ESCAPE_ORB }; +enum CreatureIds +{ + NPC_SELIN = 24723, + NPC_DELRISSA = 24560, + NPC_FELCRYSTALS = 24722 +}; + +enum GameObjectIds +{ + GO_VEXALLUS_DOOR = 187896, + GO_SELIN_DOOR = 187979, + GO_SELIN_ENCOUNTER_DOOR = 188065, + GO_DELRISSA_DOOR = 187770, + GO_KAEL_DOOR = 188064, + GO_KAEL_STATUE_1 = 188165, + GO_KAEL_STATUE_2 = 188166, + GO_ESCAPE_ORB = 188173 +}; + #endif diff --git a/src/server/scripts/EasternKingdoms/zone_eversong_woods.cpp b/src/server/scripts/EasternKingdoms/zone_eversong_woods.cpp index 8c612a11621..bc4fff4da7b 100644 --- a/src/server/scripts/EasternKingdoms/zone_eversong_woods.cpp +++ b/src/server/scripts/EasternKingdoms/zone_eversong_woods.cpp @@ -190,6 +190,9 @@ enum InfusedCrystal // Quest QUEST_POWERING_OUR_DEFENSES = 8490, + // Quest Credit + QUEST_POD_CREDIT = 16364, + // Says EMOTE = 0, @@ -266,24 +269,17 @@ public: summoned->AI()->AttackStart(me); } - void JustDied(Unit* /*killer*/) override - { - if (PlayerGUID && !Completed) - if (Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID)) - player->FailQuest(QUEST_POWERING_OUR_DEFENSES); - } - void UpdateAI(uint32 diff) override { if (EndTimer < diff && Progress) { - Talk(EMOTE); Completed = true; if (PlayerGUID) if (Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID)) - player->CompleteQuest(QUEST_POWERING_OUR_DEFENSES); - - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + { + Talk(EMOTE, player); + player->KilledMonsterCredit(QUEST_POD_CREDIT); + } me->RemoveCorpse(); } else EndTimer -= diff; diff --git a/src/server/scripts/Events/CMakeLists.txt b/src/server/scripts/Events/CMakeLists.txt index e45bc585007..3bdb6e6eac2 100644 --- a/src/server/scripts/Events/CMakeLists.txt +++ b/src/server/scripts/Events/CMakeLists.txt @@ -8,9 +8,11 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +file(GLOB_RECURSE sources_Events Events/*.cpp Events/*.h) + set(scripts_STAT_SRCS ${scripts_STAT_SRCS} - Events/childrens_week.cpp + ${sources_Events} ) message(" -> Prepared: Events") diff --git a/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp b/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp index aa9774bfd62..ee244e51b09 100644 --- a/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp +++ b/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp @@ -133,106 +133,6 @@ class npc_risen_husk_spirit : public CreatureScript }; /*###### -## npc_theramor_guard -######*/ - -enum TheramoreGuard -{ - QUEST_DISCREDITING_THE_DESERTERS = 11133, - - NPC_THERAMORE_GUARD = 4979, - - SPELL_DOCTORED_LEAFLET = 42725, - SPELL_PROPAGANDIZED = 42246, - - SAY_QUEST1 = 0, - SAY_QUEST2 = 1, - SAY_QUEST3 = 2 -}; - -#define GOSSIP_ITEM_THERAMORE_GUARD "You look like an intelligent person. Why don't you read one of these leaflets and give it some thought?" - -class npc_theramore_guard : public CreatureScript -{ -public: - npc_theramore_guard() : CreatureScript("npc_theramore_guard") { } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (player->GetQuestStatus(QUEST_DISCREDITING_THE_DESERTERS) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_THERAMORE_GUARD, GOSSIP_SENDER_MAIN, GOSSIP_SENDER_INFO); - - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - - return true; - } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - - if (action == GOSSIP_SENDER_INFO) - { - player->CLOSE_GOSSIP_MENU(); - player->KilledMonsterCredit(NPC_THERAMORE_GUARD, 0); - creature->AI()->Talk(SAY_QUEST1); - creature->CastSpell(creature, SPELL_DOCTORED_LEAFLET, false); - creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - CAST_AI(npc_theramore_guard::npc_theramore_guardAI, creature->AI())->YellTimer = 4000; - CAST_AI(npc_theramore_guard::npc_theramore_guardAI, creature->AI())->bYellTimer = true; - } - - return true; - } - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_theramore_guardAI(creature); - } - - struct npc_theramore_guardAI : public ScriptedAI - { - npc_theramore_guardAI(Creature* creature) : ScriptedAI(creature) { } - - uint32 YellTimer; - uint32 Step; - bool bYellTimer; - - void Reset() override - { - bYellTimer = false; - Step = 0; - } - - void UpdateAI(uint32 Diff) override - { - if (!me->HasAura(SPELL_PROPAGANDIZED)) - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - - if (bYellTimer && YellTimer <= Diff) - { - switch (Step) - { - case 0: - Talk(SAY_QUEST2); - YellTimer = 3000; - ++Step; - break; - case 1: - Talk(SAY_QUEST3); - me->HandleEmoteCommand(EMOTE_ONESHOT_LAUGH); - Step = 0; - bYellTimer = false; - break; - } - } - else - YellTimer -= Diff; - } - }; -}; - -/*###### ## npc_lady_jaina_proudmoore ######*/ @@ -772,7 +672,6 @@ void AddSC_dustwallow_marsh() new npc_private_hendel(); new npc_zelfrax(); new npc_stinky(); - new npc_theramore_guard(); new spell_ooze_zap(); new spell_ooze_zap_channel_end(); new spell_energize_aoe(); diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp index 4aa59e72556..bf7b4355ea6 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp @@ -141,9 +141,9 @@ class instance_ahnkahet : public InstanceMapScript SwitchTrigger = data; break; case DATA_JEDOGA_RESET_INITIANDS: - for (std::set<uint64>::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) + for (uint64 guid : InitiandGUIDs) { - if (Creature* creature = instance->GetCreature(*itr)) + if (Creature* creature = instance->GetCreature(guid)) { creature->Respawn(); if (!creature->IsInEvadeMode()) @@ -164,9 +164,9 @@ class instance_ahnkahet : public InstanceMapScript case DATA_SPHERE_2: return SpheresState[type - DATA_SPHERE_1]; case DATA_ALL_INITIAND_DEAD: - for (std::set<uint64>::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) + for (uint64 guid : InitiandGUIDs) { - Creature* cr = instance->GetCreature(*itr); + Creature* cr = instance->GetCreature(guid); if (!cr || cr->IsAlive()) return 0; } @@ -214,11 +214,11 @@ class instance_ahnkahet : public InstanceMapScript { std::vector<uint64> vInitiands; vInitiands.clear(); - for (std::set<uint64>::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) + for (uint64 guid : InitiandGUIDs) { - Creature* cr = instance->GetCreature(*itr); + Creature* cr = instance->GetCreature(guid); if (cr && cr->IsAlive()) - vInitiands.push_back(*itr); + vInitiands.push_back(guid); } if (vInitiands.empty()) return 0; @@ -245,9 +245,9 @@ class instance_ahnkahet : public InstanceMapScript case DATA_JEDOGA_SHADOWSEEKER: if (state == DONE) { - for (std::set<uint64>::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) + for (uint64 guid : InitiandGUIDs) { - if (Creature* cr = instance->GetCreature(*itr)) + if (Creature* cr = instance->GetCreature(guid)) cr->DespawnOrUnsummon(); } } diff --git a/src/server/scripts/Northrend/CMakeLists.txt b/src/server/scripts/Northrend/CMakeLists.txt index aff3c0a9528..8401ea4b9a5 100644 --- a/src/server/scripts/Northrend/CMakeLists.txt +++ b/src/server/scripts/Northrend/CMakeLists.txt @@ -20,7 +20,6 @@ set(scripts_STAT_SRCS Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp Northrend/Ulduar/HallsOfLightning/boss_loken.cpp Northrend/Ulduar/Ulduar/boss_general_vezax.cpp - Northrend/Ulduar/Ulduar/ulduar_teleporter.cpp Northrend/Ulduar/Ulduar/boss_thorim.cpp Northrend/Ulduar/Ulduar/boss_ignis.cpp Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp index f352b4faace..43c295d5f64 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp @@ -855,7 +855,6 @@ class npc_halion_controller : public CreatureScript { if (Creature* halion = ObjectAccessor::GetCreature(*me, _instance->GetData64(itr))) { - RemoveCorporeality(halion, itr == DATA_TWILIGHT_HALION); halion->CastSpell(halion, GetSpell(_materialCorporealityValue, itr == DATA_TWILIGHT_HALION), true); if (itr == DATA_TWILIGHT_HALION) @@ -866,19 +865,6 @@ class npc_halion_controller : public CreatureScript } } - void RemoveCorporeality(Creature* who, bool isTwilight = false) - { - for (uint8 i = 0; i < MAX_CORPOREALITY_STATE; i++) - { - uint32 spellID = (isTwilight ? _corporealityReference[i].twilightRealmSpell : _corporealityReference[i].materialRealmSpell); - if (who->HasAura(spellID)) - { - who->RemoveAurasDueToSpell(spellID); - break; - } - } - } - uint32 GetSpell(uint8 pctValue, bool isTwilight = false) const { CorporealityEntry entry = _corporealityReference[pctValue]; diff --git a/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp b/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp index 63b1359a406..4e9462a447f 100644 --- a/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp +++ b/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp @@ -208,7 +208,7 @@ public: { for (uint8 i = 0; i < 4; i++) if (uint64 guid = instance->GetData64(summoners[i].data)) - if (Creature* crystalChannelTarget = instance->instance->GetCreature(guid)) + if (Creature* crystalChannelTarget = ObjectAccessor::GetCreature(*me, guid)) { if (active) crystalChannelTarget->AI()->SetData(summoners[i].spell, summoners[i].timer); @@ -221,7 +221,7 @@ public: { for (uint8 i = 0; i < 4; i++) if (uint64 guid = instance->GetData64(DATA_NOVOS_CRYSTAL_1 + i)) - if (GameObject* crystal = instance->instance->GetGameObject(guid)) + if (GameObject* crystal = ObjectAccessor::GetGameObject(*me, guid)) SetCrystalStatus(crystal, active); } @@ -241,7 +241,7 @@ public: { for (uint8 i = 0; i < 4; i++) if (uint64 guid = instance->GetData64(DATA_NOVOS_CRYSTAL_1 + i)) - if (GameObject* crystal = instance->instance->GetGameObject(guid)) + if (GameObject* crystal = ObjectAccessor::GetGameObject(*me, guid)) if (crystal->GetGoState() == GO_STATE_ACTIVE) { SetCrystalStatus(crystal, false); @@ -258,7 +258,7 @@ public: events.ScheduleEvent(EVENT_SUMMON_MINIONS, 15000); } else if (uint64 guid = instance->GetData64(DATA_NOVOS_SUMMONER_4)) - if (Creature* crystalChannelTarget = instance->instance->GetCreature(guid)) + if (Creature* crystalChannelTarget = ObjectAccessor::GetCreature(*me, guid)) crystalChannelTarget->AI()->SetData(SPELL_SUMMON_CRYSTAL_HANDLER, 15000); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp index 16d1531e890..e1658e564ec 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp @@ -1227,9 +1227,9 @@ class spell_deathbringer_blood_nova_targeting : public SpellScriptLoader if (targets.empty()) return; - // select one random target, with preference of ranged targets + // select one random target, preferring ranged targets uint32 targetsAtRange = 0; - uint32 const minTargets = uint32(GetCaster()->GetMap()->GetSpawnMode() & 1 ? 10 : 4); + uint32 const minTargets = uint32(GetCaster()->GetMap()->Is25ManRaid() ? 10 : 4); targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster(), false)); // get target count at range @@ -1237,18 +1237,12 @@ class spell_deathbringer_blood_nova_targeting : public SpellScriptLoader if ((*itr)->GetDistance(GetCaster()) < 12.0f) break; - // set the upper cap + // If not enough ranged targets are present just select anyone if (targetsAtRange < minTargets) - targetsAtRange = std::min<uint32>(targets.size() - 1, minTargets); - - if (!targetsAtRange) - { - targets.clear(); - return; - } + targetsAtRange = uint32(targets.size()); std::list<WorldObject*>::const_iterator itr = targets.begin(); - std::advance(itr, urand(0, targetsAtRange)); + std::advance(itr, urand(0, targetsAtRange - 1)); target = *itr; targets.clear(); targets.push_back(target); 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 223f3731032..b72b953efb4 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -559,6 +559,11 @@ class boss_the_lich_king : public CreatureScript Trinity::GameObjectWorker<FrozenThroneResetWorker> worker(me, reset); me->VisitNearbyGridObject(333.0f, worker); + // Restore Tirion's gossip only after The Lich King fully resets to prevent + // restarting the encounter while LK still runs back to spawn point + if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_HIGHLORD_TIRION_FORDRING))) + tirion->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + // Reset any light override me->GetMap()->SetZoneOverrideLight(AREA_THE_FROZEN_THRONE, 0, 5000); } @@ -1201,11 +1206,6 @@ class npc_tirion_fordring_tft : public CreatureScript void JustReachedHome() override { me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - - if (_instance->GetBossState(DATA_THE_LICH_KING) == DONE) - return; - - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); } void UpdateAI(uint32 diff) override diff --git a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp index d3b4a285af6..d4f00414b7d 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp @@ -120,7 +120,6 @@ public: } void MoveInLineOfSight(Unit* who) override - { if (!hasTaunted && me->IsWithinDistInMap(who, 60.0f) && who->GetTypeId() == TYPEID_PLAYER) { diff --git a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp index 02bafa8d10d..3d42827c0a8 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp @@ -84,7 +84,6 @@ class boss_faerlina : public CreatureScript } void MoveInLineOfSight(Unit* who) override - { if (!_introDone && who->GetTypeId() == TYPEID_PLAYER) { diff --git a/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp b/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp index 3a0e3ce7c73..381be8d5cd1 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp @@ -70,7 +70,6 @@ public: } void MoveInLineOfSight(Unit* who) override - { if (who->GetEntry() == NPC_ZOMBIE && me->IsWithinDistInMap(who, 7)) { diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp index 1331c25de17..e8ed181da5a 100644 --- a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp +++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp @@ -368,9 +368,9 @@ class instance_naxxramas : public InstanceMapScript if (i == section) continue; - for (std::set<uint64>::const_iterator itr = HeiganEruptionGUID[i].begin(); itr != HeiganEruptionGUID[i].end(); ++itr) + for (uint64 guid : HeiganEruptionGUID[i]) { - if (GameObject* heiganEruption = instance->GetGameObject(*itr)) + if (GameObject* heiganEruption = instance->GetGameObject(guid)) { heiganEruption->SendCustomAnim(heiganEruption->GetGoAnimProgress()); heiganEruption->CastSpell(NULL, SPELL_ERUPTION); diff --git a/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp b/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp index bf84a267a27..2b15ddf32c4 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp @@ -281,8 +281,8 @@ class instance_oculus : public InstanceMapScript void GreaterWhelps() { - for (std::list<uint64>::const_iterator itr = GreaterWhelpList.begin(); itr != GreaterWhelpList.end(); ++itr) - if (Creature* gwhelp = instance->GetCreature(*itr)) + for (uint64 guid : GreaterWhelpList) + if (Creature* gwhelp = instance->GetCreature(guid)) gwhelp->SetPhaseMask(1, true); } diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp index 24d145f097f..13ea815febc 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp @@ -164,11 +164,9 @@ public: for (uint8 i = 0; i < 2; ++i) { - if (Creature* pStormforgedLieutenant = (ObjectAccessor::GetCreature((*me), m_auiStormforgedLieutenantGUID[i]))) - { + if (Creature* pStormforgedLieutenant = ObjectAccessor::GetCreature(*me, m_auiStormforgedLieutenantGUID[i])) if (!pStormforgedLieutenant->IsAlive()) pStormforgedLieutenant->Respawn(); - } } if (m_uiStance != STANCE_DEFENSIVE) @@ -411,7 +409,7 @@ public: void EnterCombat(Unit* who) override { - if (Creature* pBjarngrim = instance->instance->GetCreature(instance->GetData64(DATA_BJARNGRIM))) + if (Creature* pBjarngrim = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_BJARNGRIM))) { if (pBjarngrim->IsAlive() && !pBjarngrim->GetVictim()) pBjarngrim->AI()->AttackStart(who); @@ -434,7 +432,7 @@ public: if (m_uiRenewSteel_Timer <= uiDiff) { - if (Creature* pBjarngrim = instance->instance->GetCreature(instance->GetData64(DATA_BJARNGRIM))) + if (Creature* pBjarngrim = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_BJARNGRIM))) { if (pBjarngrim->IsAlive()) DoCast(pBjarngrim, SPELL_RENEW_STEEL_N); diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp index aac315cda0d..83082b18d73 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp @@ -165,9 +165,9 @@ public: Position pos = me->GetPosition(); - for (std::list<uint64>::const_iterator itr = lSparkList.begin(); itr != lSparkList.end(); ++itr) + for (uint64 guid : lSparkList) { - if (Creature* pSpark = ObjectAccessor::GetCreature(*me, *itr)) + if (Creature* pSpark = ObjectAccessor::GetCreature(*me, guid)) { if (pSpark->IsAlive()) { diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp index d0b8f75e711..b424ce01b06 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp @@ -162,13 +162,11 @@ public: if (m_lGolemGUIDList.empty()) return; - for (std::list<uint64>::const_iterator itr = m_lGolemGUIDList.begin(); itr != m_lGolemGUIDList.end(); ++itr) + for (uint64 guid : m_lGolemGUIDList) { - if (Creature* temp = ObjectAccessor::GetCreature(*me, *itr)) - { + if (Creature* temp = ObjectAccessor::GetCreature(*me, guid)) if (temp->IsAlive()) temp->DespawnOrUnsummon(); - } } m_lGolemGUIDList.clear(); @@ -179,9 +177,9 @@ public: if (m_lGolemGUIDList.empty()) return; - for (std::list<uint64>::const_iterator itr = m_lGolemGUIDList.begin(); itr != m_lGolemGUIDList.end(); ++itr) + for (uint64 guid : m_lGolemGUIDList) { - if (Creature* temp = ObjectAccessor::GetCreature(*me, *itr)) + if (Creature* temp = ObjectAccessor::GetCreature(*me, guid)) { // Only shatter brittle golems if (temp->IsAlive() && temp->GetEntry() == NPC_BRITTLE_GOLEM) diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp index eec08c3c429..796299cc952 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp @@ -37,7 +37,7 @@ enum Spells enum Events { - EVENT_PARTING_SORROW = 1, + EVENT_PARTING_SORROW = 1, EVENT_STORM_OF_GRIEF, EVENT_SHOCK_OF_SORROW, EVENT_PILLAR_OF_WOE diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp index 67500382758..595dcecd554 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp @@ -334,7 +334,7 @@ class boss_algalon_the_observer : public CreatureScript { case ACTION_START_INTRO: { - me->SetFlag(UNIT_FIELD_FLAGS_2, 0x20); + me->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_INSTANTLY_APPEAR_MODEL); me->SetDisableGravity(true); DoCast(me, SPELL_ARRIVAL, true); DoCast(me, SPELL_RIDE_THE_LIGHTNING, true); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp index 4dfa38abae5..257518d998b 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp @@ -18,9 +18,10 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "InstanceScript.h" -#include "ulduar.h" #include "Player.h" #include "WorldPacket.h" +#include "SpellScript.h" +#include "ulduar.h" static DoorData const doorData[] = { @@ -1161,7 +1162,43 @@ class instance_ulduar : public InstanceMapScript } }; +class spell_ulduar_teleporter : public SpellScriptLoader +{ + public: + spell_ulduar_teleporter() : SpellScriptLoader("spell_ulduar_teleporter") { } + + class spell_ulduar_teleporter_SpellScript : public SpellScript + { + PrepareSpellScript(spell_ulduar_teleporter_SpellScript); + + SpellCastResult CheckRequirement() + { + if (GetExplTargetUnit()->GetTypeId() != TYPEID_PLAYER) + return SPELL_FAILED_DONT_REPORT; + + if (GetExplTargetUnit()->IsInCombat()) + { + Spell::SendCastResult(GetExplTargetUnit()->ToPlayer(), GetSpellInfo(), 0, SPELL_FAILED_AFFECTING_COMBAT); + return SPELL_FAILED_AFFECTING_COMBAT; + } + + return SPELL_CAST_OK; + } + + void Register() override + { + OnCheckCast += SpellCheckCastFn(spell_ulduar_teleporter_SpellScript::CheckRequirement); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_ulduar_teleporter_SpellScript(); + } +}; + void AddSC_instance_ulduar() { new instance_ulduar(); + new spell_ulduar_teleporter(); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar_teleporter.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar_teleporter.cpp deleted file mode 100644 index 9fc0e4056fa..00000000000 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar_teleporter.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> - * - * 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/>. - */ - -#include "ScriptMgr.h" -#include "ScriptedGossip.h" -#include "InstanceScript.h" -#include "Player.h" -#include "ulduar.h" - -/* -The teleporter appears to be active and stable. - -- Expedition Base Camp -- Formation Grounds -- Colossal Forge -- Scrapyard -- Antechamber of Ulduar -- Shattered Walkway -- Conservatory of Life -*/ - -enum UlduarTeleporter -{ - BASE_CAMP = 200, - GROUNDS = 201, - FORGE = 202, - SCRAPYARD = 203, - ANTECHAMBER = 204, - WALKWAY = 205, - CONSERVATORY = 206, -}; - -class ulduar_teleporter : public GameObjectScript -{ - public: - ulduar_teleporter() : GameObjectScript("ulduar_teleporter") { } - - bool OnGossipSelect(Player* player, GameObject* /*gameObject*/, uint32 sender, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - if (sender != GOSSIP_SENDER_MAIN) - return false; - if (!player->getAttackers().empty()) - return false; - - switch (action) - { - case BASE_CAMP: - player->TeleportTo(603, -706.122f, -92.6024f, 429.876f, 0.0f); - player->CLOSE_GOSSIP_MENU(); - break; - case GROUNDS: - player->TeleportTo(603, 131.248f, -35.3802f, 409.804f, 0.0f); - player->CLOSE_GOSSIP_MENU(); - break; - case FORGE: - player->TeleportTo(603, 553.233f, -12.3247f, 409.679f, 0.0f); - player->CLOSE_GOSSIP_MENU(); - break; - case SCRAPYARD: - player->TeleportTo(603, 926.292f, -11.4635f, 418.595f, 0.0f); - player->CLOSE_GOSSIP_MENU(); - break; - case ANTECHAMBER: - player->TeleportTo(603, 1498.09f, -24.246f, 420.967f, 0.0f); - player->CLOSE_GOSSIP_MENU(); - break; - case WALKWAY: - player->TeleportTo(603, 1859.45f, -24.1f, 448.9f, 0.0f); - player->CLOSE_GOSSIP_MENU(); - break; - case CONSERVATORY: - player->TeleportTo(603, 2086.27f, -24.3134f, 421.239f, 0.0f); - player->CLOSE_GOSSIP_MENU(); - break; - } - - return true; - } - - bool OnGossipHello(Player* player, GameObject* gameObject) override - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Teleport to the Expedition Base Camp", GOSSIP_SENDER_MAIN, BASE_CAMP); - if (InstanceScript* instance = gameObject->GetInstanceScript()) - { - if (instance->GetData(DATA_COLOSSUS) == 2) //count of 2 collossus death - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Teleport to the Formation Grounds", GOSSIP_SENDER_MAIN, GROUNDS); - if (instance->GetBossState(BOSS_LEVIATHAN) == DONE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Teleport to the Colossal Forge", GOSSIP_SENDER_MAIN, FORGE); - if (instance->GetBossState(BOSS_XT002) == DONE) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Teleport to the Scrapyard", GOSSIP_SENDER_MAIN, SCRAPYARD); - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Teleport to the Antechamber of Ulduar", GOSSIP_SENDER_MAIN, ANTECHAMBER); - } - if (instance->GetBossState(BOSS_KOLOGARN) == DONE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Teleport to the Shattered Walkway", GOSSIP_SENDER_MAIN, WALKWAY); - if (instance->GetBossState(BOSS_AURIAYA) == DONE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Teleport to the Conservatory of Life", GOSSIP_SENDER_MAIN, CONSERVATORY); - } - - player->SEND_GOSSIP_MENU(gameObject->GetGOInfo()->GetGossipMenuId(), gameObject->GetGUID()); - return true; - } -}; - -void AddSC_ulduar_teleporter() -{ - new ulduar_teleporter(); -} diff --git a/src/server/scripts/Northrend/zone_crystalsong_forest.cpp b/src/server/scripts/Northrend/zone_crystalsong_forest.cpp index e4bd9c469fb..7d680ecd071 100644 --- a/src/server/scripts/Northrend/zone_crystalsong_forest.cpp +++ b/src/server/scripts/Northrend/zone_crystalsong_forest.cpp @@ -76,20 +76,18 @@ public: GetCreatureListWithEntryInGrid(orbList, me, NPC_TRANSITUS_SHIELD_DUMMY, 32.0f); if (!orbList.empty()) { - for (std::list<Creature*>::const_iterator itr = orbList.begin(); itr != orbList.end(); ++itr) + for (Creature* orb : orbList) { - if (Creature* pOrb = *itr) + if (orb->GetPositionY() < 1000) { - if (pOrb->GetPositionY() < 1000) - { - targetGUID = pOrb->GetGUID(); - break; - } + targetGUID = orb->GetGUID(); + break; } } } } - }else + } + else { if (!targetGUID) if (Creature* pOrb = GetClosestCreatureWithEntry(me, NPC_TRANSITUS_SHIELD_DUMMY, 32.0f)) diff --git a/src/server/scripts/Northrend/zone_dalaran.cpp b/src/server/scripts/Northrend/zone_dalaran.cpp index 21fc93578ae..1e8da70bbbf 100644 --- a/src/server/scripts/Northrend/zone_dalaran.cpp +++ b/src/server/scripts/Northrend/zone_dalaran.cpp @@ -73,7 +73,6 @@ public: void AttackStart(Unit* /*who*/) override { } void MoveInLineOfSight(Unit* who) override - { if (!who || !who->IsInWorld() || who->GetZoneId() != 4395) return; diff --git a/src/server/scripts/Northrend/zone_dragonblight.cpp b/src/server/scripts/Northrend/zone_dragonblight.cpp index bda6d953d9f..59c9b21a220 100644 --- a/src/server/scripts/Northrend/zone_dragonblight.cpp +++ b/src/server/scripts/Northrend/zone_dragonblight.cpp @@ -246,13 +246,10 @@ class npc_commander_eligor_dawnbringer : public CreatureScript { std::list<Creature*> creatureList; GetCreatureListWithEntryInGrid(creatureList, me, AudienceMobs[ii], 15.0f); - for (std::list<Creature*>::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr) + for (Creature* creature : creatureList) { - if (Creature* creatureList = *itr) - { - audienceList[creaturecount] = creatureList->GetGUID(); - ++creaturecount; - } + audienceList[creaturecount] = creature->GetGUID(); + ++creaturecount; } } diff --git a/src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp b/src/server/scripts/Outland/BlackTemple/boss_gurtogg_bloodboil.cpp index 0004df68016..f03caa37cb2 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_gurtogg_bloodboil.cpp @@ -17,14 +17,14 @@ */ /* ScriptData -SDName: Boss_Bloodboil -SD%Complete: 80 -SDComment: Bloodboil not working correctly, missing enrage -SDCategory: Black Temple +Name: Boss_Bloodboil +Complete: 80 +Category: Black Temple EndScriptData */ #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "SpellScript.h" #include "black_temple.h" enum Bloodboil @@ -54,9 +54,6 @@ enum Bloodboil SPELL_BERSERK = 45078 }; - -//This is used to sort the players by distance in preparation for the Bloodboil cast. - class boss_gurtogg_bloodboil : public CreatureScript { public: @@ -137,51 +134,6 @@ public: Talk(SAY_DEATH); } - // Note: This seems like a very complicated fix. The fix needs to be handled by the core, as implementation of limited-target AoE spells are still not limited. - void CastBloodboil() - { - // Get the Threat List - std::list<HostileReference*> m_threatlist = me->getThreatManager().getThreatList(); - - if (m_threatlist.empty()) // He doesn't have anyone in his threatlist, useless to continue - return; - - std::list<Unit*> targets; - std::list<HostileReference*>::const_iterator itr = m_threatlist.begin(); - for (; itr!= m_threatlist.end(); ++itr) //store the threat list in a different container - { - Unit* target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()); - //only on alive players - if (target && target->IsAlive() && target->GetTypeId() == TYPEID_PLAYER) - targets.push_back(target); - } - - //Sort the list of players - targets.sort(Trinity::ObjectDistanceOrderPred(me, false)); - //Resize so we only get top 5 - targets.resize(5); - - //Aura each player in the targets list with Bloodboil. Aura code copied+pasted from Aura command in Level3.cpp - /*SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_BLOODBOIL); - if (spellInfo) - { - for (std::list<Unit*>::const_iterator itr = targets.begin(); itr != targets.end(); ++itr) - { - Unit* target = *itr; - if (!target) return; - for (uint32 i = 0; i<3; ++i) - { - uint8 eff = spellInfo->Effect[i]; - if (eff >= TOTAL_SPELL_EFFECTS) - continue; - - Aura* Aur = new Aura(spellInfo, i, target, target, target); - target->AddAura(Aur); - } - } - }*/ - } - void RevertThreatOnTarget(uint64 guid) { if (Unit* unit = ObjectAccessor::GetUnit(*me, guid)) @@ -247,8 +199,7 @@ public: { if (BloodboilCount < 5) // Only cast it five times. { - //CastBloodboil(); // Causes issues on windows, so is commented out. - DoCastVictim(SPELL_BLOODBOIL); + DoCastAOE(SPELL_BLOODBOIL); ++BloodboilCount; BloodboilTimer = 10000*BloodboilCount; } @@ -274,7 +225,7 @@ public: { if (Phase1) { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) { Phase1 = false; @@ -327,7 +278,41 @@ public: }; +// 42005 - Bloodboil +class spell_gurtogg_bloodboil_bloodboil : public SpellScriptLoader +{ + public: + spell_gurtogg_bloodboil_bloodboil() : SpellScriptLoader("spell_gurtogg_bloodboil_bloodboil") { } + + class spell_gurtogg_bloodboil_bloodboil_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gurtogg_bloodboil_bloodboil_SpellScript); + + void FilterTargets(std::list<WorldObject*>& targets) + { + if (targets.size() <= 5) + return; + + // Sort the list of players + targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster(), false)); + // Resize so we only get top 5 + targets.resize(5); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_gurtogg_bloodboil_bloodboil_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_gurtogg_bloodboil_bloodboil_SpellScript(); + } +}; + void AddSC_boss_gurtogg_bloodboil() { new boss_gurtogg_bloodboil(); + new spell_gurtogg_bloodboil_bloodboil(); } diff --git a/src/server/scripts/Outland/CMakeLists.txt b/src/server/scripts/Outland/CMakeLists.txt index 414a3bce14a..0c69a236ef8 100644 --- a/src/server/scripts/Outland/CMakeLists.txt +++ b/src/server/scripts/Outland/CMakeLists.txt @@ -112,7 +112,7 @@ set(scripts_STAT_SRCS Outland/BlackTemple/instance_black_temple.cpp Outland/BlackTemple/boss_reliquary_of_souls.cpp Outland/BlackTemple/boss_warlord_najentus.cpp - Outland/BlackTemple/boss_bloodboil.cpp + Outland/BlackTemple/boss_gurtogg_bloodboil.cpp Outland/BlackTemple/boss_illidan.cpp Outland/zone_shadowmoon_valley.cpp Outland/zone_blades_edge_mountains.cpp diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index 5ae0e1601c5..245ec7e88cf 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -39,9 +39,11 @@ enum DeathKnightSpells SPELL_DK_DEATH_COIL_DAMAGE = 47632, SPELL_DK_DEATH_COIL_HEAL = 47633, SPELL_DK_DEATH_STRIKE_HEAL = 45470, + SPELL_DK_FROST_FEVER = 55095, SPELL_DK_FROST_PRESENCE = 48263, SPELL_DK_FROST_PRESENCE_TRIGGERED = 61261, SPELL_DK_GHOUL_EXPLODE = 47496, + SPELL_DK_GLYPH_OF_DISEASE = 63334, SPELL_DK_GLYPH_OF_ICEBOUND_FORTITUDE = 58625, SPELL_DK_IMPROVED_BLOOD_PRESENCE_R1 = 50365, SPELL_DK_IMPROVED_FROST_PRESENCE_R1 = 50384, @@ -51,6 +53,7 @@ enum DeathKnightSpells SPELL_DK_ITEM_SIGIL_VENGEFUL_HEART = 64962, SPELL_DK_ITEM_T8_MELEE_4P_BONUS = 64736, SPELL_DK_MASTER_OF_GHOULS = 52143, + SPELL_DK_BLOOD_PLAGUE = 55078, SPELL_DK_RAISE_DEAD_USE_REAGENT = 48289, SPELL_DK_RUNIC_POWER_ENERGIZE = 49088, SPELL_DK_SCENT_OF_BLOOD = 50422, @@ -933,6 +936,91 @@ class spell_dk_improved_unholy_presence : public SpellScriptLoader } }; +// ID - 50842 Pestilence +class spell_dk_pestilence : public SpellScriptLoader +{ + public: + spell_dk_pestilence() : SpellScriptLoader("spell_dk_pestilence") { } + + class spell_dk_pestilence_SpellScript : public SpellScript + { + PrepareSpellScript(spell_dk_pestilence_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_DK_GLYPH_OF_DISEASE) + || !sSpellMgr->GetSpellInfo(SPELL_DK_BLOOD_PLAGUE) + || !sSpellMgr->GetSpellInfo(SPELL_DK_FROST_FEVER)) + return false; + return true; + } + + void OnHit(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + Unit* hitUnit = GetHitUnit(); + Unit* victim = GetExplTargetUnit(); + + if (!victim) + return; + + if (victim != hitUnit || caster->HasAura(SPELL_DK_GLYPH_OF_DISEASE)) + { + if (Aura* aurOld = victim->GetAura(SPELL_DK_BLOOD_PLAGUE, caster->GetGUID())) // Check Blood Plague application on victim. + { + if (AuraEffect* aurEffOld = aurOld->GetEffect(EFFECT_0)) + { + float donePct = aurEffOld->GetDonePct(); + float critChance = aurEffOld->GetCritChance(); + + caster->CastSpell(hitUnit, SPELL_DK_BLOOD_PLAGUE, true); // Spread the disease to hitUnit. + + if (Aura* aurNew = hitUnit->GetAura(SPELL_DK_BLOOD_PLAGUE, caster->GetGUID())) // Check Blood Plague application on hitUnit. + { + if (AuraEffect* aurEffNew = aurNew->GetEffect(EFFECT_0)) + { + aurEffNew->SetCritChance(critChance); // Blood Plague can crit if caster has T9. + aurEffNew->SetDonePct(donePct); + aurEffNew->SetDamage(caster->SpellDamageBonusDone(hitUnit, aurEffNew->GetSpellInfo(), std::max(aurEffNew->GetAmount(), 0), DOT) * donePct); + } + } + } + } + + if (Aura* aurOld = victim->GetAura(SPELL_DK_FROST_FEVER, caster->GetGUID())) // Check Frost Fever application on victim. + { + if (AuraEffect* aurEffOld = aurOld->GetEffect(EFFECT_0)) + { + float donePct = aurEffOld->GetDonePct(); + + caster->CastSpell(hitUnit, SPELL_DK_FROST_FEVER, true); // Spread the disease to hitUnit. + + if (Aura* aurNew = hitUnit->GetAura(SPELL_DK_FROST_FEVER, caster->GetGUID())) // Check Frost Fever application on hitUnit. + { + if (AuraEffect* aurEffNew = aurNew->GetEffect(EFFECT_0)) + { + aurEffNew->SetDonePct(donePct); + aurEffNew->SetDamage(caster->SpellDamageBonusDone(hitUnit, aurEffNew->GetSpellInfo(), std::max(aurEffNew->GetAmount(), 0), DOT) * donePct); + } + } + } + } + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_dk_pestilence_SpellScript::OnHit, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_dk_pestilence_SpellScript(); + } +}; + + // 48266 - Blood Presence // 48263 - Frost Presence // 48265 - Unholy Presence @@ -1467,6 +1555,7 @@ void AddSC_deathknight_spell_scripts() new spell_dk_improved_blood_presence(); new spell_dk_improved_frost_presence(); new spell_dk_improved_unholy_presence(); + new spell_dk_pestilence(); new spell_dk_presence(); new spell_dk_raise_dead(); new spell_dk_rune_tap_party(); diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp index 3f935077b22..4571798506e 100644 --- a/src/server/scripts/Spells/spell_warlock.cpp +++ b/src/server/scripts/Spells/spell_warlock.cpp @@ -518,7 +518,7 @@ class spell_warl_haunt : public SpellScriptLoader { PrepareSpellScript(spell_warl_haunt_SpellScript); - void HandleOnHit() + void HandleAfterHit() { if (Aura* aura = GetHitAura()) if (AuraEffect* aurEff = aura->GetEffect(EFFECT_1)) @@ -527,7 +527,7 @@ class spell_warl_haunt : public SpellScriptLoader void Register() override { - OnHit += SpellHitFn(spell_warl_haunt_SpellScript::HandleOnHit); + AfterHit += SpellHitFn(spell_warl_haunt_SpellScript::HandleAfterHit); } }; diff --git a/src/server/scripts/World/CMakeLists.txt b/src/server/scripts/World/CMakeLists.txt index 7d1b46732cf..56a0a1eb4c7 100644 --- a/src/server/scripts/World/CMakeLists.txt +++ b/src/server/scripts/World/CMakeLists.txt @@ -8,20 +8,11 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +file(GLOB_RECURSE sources_World World/*.cpp World/*.h) + set(scripts_STAT_SRCS ${scripts_STAT_SRCS} - World/achievement_scripts.cpp - World/areatrigger_scripts.cpp - World/boss_emerald_dragons.cpp - World/chat_log.cpp - World/go_scripts.cpp - World/guards.cpp - World/item_scripts.cpp - World/mob_generic_creature.cpp - World/npc_innkeeper.cpp - World/npc_professions.cpp - World/npc_taxi.cpp - World/npcs_special.cpp + ${sources_World} ) message(" -> Prepared: World") diff --git a/src/server/scripts/World/action_ip_logger.cpp b/src/server/scripts/World/action_ip_logger.cpp new file mode 100644 index 00000000000..057f3d6ee36 --- /dev/null +++ b/src/server/scripts/World/action_ip_logger.cpp @@ -0,0 +1,315 @@ +/* + * Copyright (C) 2008-2014 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/>. + */ + +#include "ScriptMgr.h" +#include "Channel.h" +#include "Guild.h" +#include "Group.h" + +enum IPLoggingTypes +{ + + // AccountActionIpLogger(); + ACCOUNT_LOGIN = 0, + ACCOUNT_FAIL_LOGIN = 1, + ACCOUNT_CHANGE_PW = 2, + ACCOUNT_CHANGE_PW_FAIL = 3, // Only two types of account changes exist... + ACCOUNT_CHANGE_EMAIL = 4, + ACCOUNT_CHANGE_EMAIL_FAIL = 5, // ...so we log them individually + // OBSOLETE - ACCOUNT_LOGOUT = 6, /* Can not be logged. We still keep the type however */ + // CharacterActionIpLogger(); + CHARACTER_CREATE = 7, + CHARACTER_LOGIN = 8, + CHARACTER_LOGOUT = 9, + // CharacterDeleteActionIpLogger(); + CHARACTER_DELETE = 10, + CHARACTER_FAILED_DELETE = 11, + // AccountActionIpLogger(), CharacterActionIpLogger(), CharacterActionIpLogger(); + UNKNOWN_ACTION = 12 +}; + +class AccountActionIpLogger : public AccountScript +{ + public: + AccountActionIpLogger() : AccountScript("AccountActionIpLogger") { } + + // We log last_ip instead of last_attempt_ip, as login was successful + // ACCOUNT_LOGIN = 0 + void OnAccountLogin(uint32 accountId) override + { + AccountIPLogAction(accountId, ACCOUNT_LOGIN); + } + + // We log last_attempt_ip instead of last_ip, as failed login doesn't necessarily mean approperiate user + // ACCOUNT_FAIL_LOGIN = 1 + void OnFailedAccountLogin(uint32 accountId) override + { + AccountIPLogAction(accountId, ACCOUNT_FAIL_LOGIN); + } + + // ACCOUNT_CHANGE_PW = 2 + void OnPasswordChange(uint32 accountId) override + { + AccountIPLogAction(accountId, ACCOUNT_CHANGE_PW); + } + + // ACCOUNT_CHANGE_PW_FAIL = 3 + void OnFailedPasswordChange(uint32 accountId) override + { + AccountIPLogAction(accountId, ACCOUNT_CHANGE_PW_FAIL); + } + + // Registration Email can NOT be changed apart from GM level users. Thus, we do not require to log them... + // ACCOUNT_CHANGE_EMAIL = 4 + void OnEmailChange(uint32 accountId) override + { + AccountIPLogAction(accountId, ACCOUNT_CHANGE_EMAIL); // ... they get logged by gm command logger anyway + } + + // ACCOUNT_CHANGE_EMAIL_FAIL = 5 + void OnFailedEmailChange(uint32 accountId) override + { + AccountIPLogAction(accountId, ACCOUNT_CHANGE_EMAIL_FAIL); + } + + /* It's impossible to log the account logout process out of character selection - shouldn't matter anyway, + * as ip doesn't change through playing (obviously).*/ + // ACCOUNT_LOGOUT = 6 + void AccountIPLogAction(uint32 accountId, IPLoggingTypes aType) + { + // Action IP Logger is only intialized if config is set up + // Else, this script isn't loaded in the first place: We require no config check. + + // We declare all the required variables + uint32 playerGuid = accountId; + uint32 characterGuid = 0; + std::string systemNote = "ERROR"; // "ERROR" is a placeholder here. We change it later. + + // With this switch, we change systemNote so that we have a more accurate phrasing of what type it is. + // Avoids Magicnumbers in SQL table + switch (aType) + { + case ACCOUNT_LOGIN: + systemNote = "Logged on Successful AccountLogin"; + break; + case ACCOUNT_FAIL_LOGIN: + systemNote = "Logged on Failed AccountLogin"; + break; + case ACCOUNT_CHANGE_PW: + systemNote = "Logged on Successful Account Password Change"; + break; + case ACCOUNT_CHANGE_PW_FAIL: + systemNote = "Logged on Failed Account Password Change"; + break; + case ACCOUNT_CHANGE_EMAIL: + systemNote = "Logged on Successful Account Email Change"; + break; + case ACCOUNT_CHANGE_EMAIL_FAIL: + systemNote = "Logged on Failed Account Email Change"; + break; + /*case ACCOUNT_LOGOUT: + systemNote = "Logged on AccountLogout"; //Can not be logged + break;*/ + // Neither should happen. Ever. Period. If it does, call Ghostbusters and all your local software defences to investigate. + case UNKNOWN_ACTION: + default: + systemNote = "ERROR! Unknown action!"; + break; + } + + // Once we have done everything, we can insert the new log. + // Seeing as the time differences should be minimal, we do not get unixtime and the timestamp right now; + // Rather, we let it be added with the SQL query. + if (aType != ACCOUNT_FAIL_LOGIN) + { + // As we can assume most account actions are NOT failed login, so this is the more accurate check. + // For those, we need last_ip... + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ALDL_IP_LOGGING); + + stmt->setUInt32(0, playerGuid); + stmt->setUInt32(1, characterGuid); + stmt->setUInt8(2, aType); + stmt->setUInt32(3, playerGuid); + stmt->setString(4, systemNote.c_str()); + LoginDatabase.Execute(stmt); + } + else // ... but for failed login, we query last_attempt_ip from account table. Which we do with an unique query + { + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_FACL_IP_LOGGING); + + stmt->setUInt32(0, playerGuid); + stmt->setUInt32(1, characterGuid); + stmt->setUInt8(2, aType); + stmt->setUInt32(3, playerGuid); + stmt->setString(4, systemNote.c_str()); + LoginDatabase.Execute(stmt); + } + return; + } +}; + +class CharacterActionIpLogger : public PlayerScript +{ + public: + CharacterActionIpLogger() : PlayerScript("CharacterActionIpLogger") { } + + // CHARACTER_CREATE = 7 + void OnCreate(Player* player) override + { + CharacterIPLogAction(player, CHARACTER_CREATE); + } + + // CHARACTER_LOGIN = 8 + void OnLogin(Player* player, bool /*firstLogin*/) override + { + CharacterIPLogAction(player, CHARACTER_LOGIN); + } + + // CHARACTER_LOGOUT = 9 + void OnLogout(Player* player) override + { + CharacterIPLogAction(player, CHARACTER_LOGOUT); + } + + // CHARACTER_DELETE = 10 + // CHARACTER_FAILED_DELETE = 11 + // We don't log either here - they require a guid + + // UNKNOWN_ACTION = 12 + // There is no real hook we could use for that. + // Shouldn't happen anyway, should it ? Nothing to see here. + + /// Logs a number of actions done by players with an IP + void CharacterIPLogAction(Player* player, IPLoggingTypes aType) + { + // Action IP Logger is only intialized if config is set up + // Else, this script isn't loaded in the first place: We require no config check. + + // We declare all the required variables + uint32 playerGuid = player->GetSession()->GetAccountId(); + uint32 characterGuid = player->GetGUIDLow(); + const std::string currentIp = player->GetSession()->GetRemoteAddress(); + std::string systemNote = "ERROR"; // "ERROR" is a placeholder here. We change it... + + // ... with this switch, so that we have a more accurate phrasing of what type it is + switch (aType) + { + case CHARACTER_CREATE: + systemNote = "Logged on CharacterCreate"; + break; + case CHARACTER_LOGIN: + systemNote = "Logged on CharacterLogin"; + break; + case CHARACTER_LOGOUT: + systemNote = "Logged on CharacterLogout"; + break; + case CHARACTER_DELETE: + systemNote = "Logged on CharacterDelete"; + break; + case CHARACTER_FAILED_DELETE: + systemNote = "Logged on Failed CharacterDelete"; + break; + // Neither should happen. Ever. Period. If it does, call Mythbusters. + case UNKNOWN_ACTION: + default: + systemNote = "ERROR! Unknown action!"; + break; + } + + // Once we have done everything, we can insert the new log. + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_CHAR_IP_LOGGING); + + stmt->setUInt32(0, playerGuid); + stmt->setUInt32(1, characterGuid); + stmt->setUInt8(2, aType); + stmt->setString(3, currentIp.c_str()); // We query the ip here. + stmt->setString(4, systemNote.c_str()); + // Seeing as the time differences should be minimal, we do not get unixtime and the timestamp right now; + // Rather, we let it be added with the SQL query. + + LoginDatabase.Execute(stmt); + return; + } +}; + +class CharacterDeleteActionIpLogger : public PlayerScript +{ +public: + CharacterDeleteActionIpLogger() : PlayerScript("CharacterDeleteActionIpLogger") { } + + // CHARACTER_DELETE = 10 + void OnDelete(uint64 guid, uint32 accountId) override + { + DeleteIPLogAction(guid, accountId, CHARACTER_DELETE); + } + + // CHARACTER_FAILED_DELETE = 11 + void OnFailedDelete(uint64 guid, uint32 accountId) override + { + DeleteIPLogAction(guid, accountId, CHARACTER_FAILED_DELETE); + } + + void DeleteIPLogAction(uint64 guid, uint32 playerGuid, IPLoggingTypes aType) + { + // Action IP Logger is only intialized if config is set up + // Else, this script isn't loaded in the first place: We require no config check. + + // We declare all the required variables + uint32 characterGuid = GUID_LOPART(guid); // We have no access to any member function of Player* or WorldSession*. So use old-fashioned way. + // Query playerGuid/accountId, as we only have characterGuid + std::string systemNote = "ERROR"; // "ERROR" is a placeholder here. We change it later. + + // With this switch, we change systemNote so that we have a more accurate phrasing of what type it is. + // Avoids Magicnumbers in SQL table + switch (aType) + { + case CHARACTER_DELETE: + systemNote = "Logged on CharacterDelete"; + break; + case CHARACTER_FAILED_DELETE: + systemNote = "Logged on Failed CharacterDelete"; + break; + // Neither should happen. Ever. Period. If it does, call to whatever god you have for mercy and guidance. + case UNKNOWN_ACTION: + default: + systemNote = "ERROR! Unknown action!"; + break; + } + + // Once we have done everything, we can insert the new log. + PreparedStatement* stmt2 = LoginDatabase.GetPreparedStatement(LOGIN_INS_ALDL_IP_LOGGING); + + stmt2->setUInt32(0, playerGuid); + stmt2->setUInt32(1, characterGuid); + stmt2->setUInt8(2, aType); + stmt2->setUInt32(3, playerGuid); + stmt2->setString(4, systemNote.c_str()); + // Seeing as the time differences should be minimal, we do not get unixtime and the timestamp right now; + // Rather, we let it be added with the SQL query. + + LoginDatabase.Execute(stmt2); + return; + } +}; + + +void AddSC_action_ip_logger() +{ + new AccountActionIpLogger(); + new CharacterActionIpLogger(); + new CharacterDeleteActionIpLogger(); +} diff --git a/src/server/scripts/World/areatrigger_scripts.cpp b/src/server/scripts/World/areatrigger_scripts.cpp index fb438c38efb..4393f72eb1b 100644 --- a/src/server/scripts/World/areatrigger_scripts.cpp +++ b/src/server/scripts/World/areatrigger_scripts.cpp @@ -51,11 +51,7 @@ enum CoilfangGOs class AreaTrigger_at_coilfang_waterfall : public AreaTriggerScript { public: - - AreaTrigger_at_coilfang_waterfall() - : AreaTriggerScript("at_coilfang_waterfall") - { - } + AreaTrigger_at_coilfang_waterfall() : AreaTriggerScript("at_coilfang_waterfall") { } bool OnTrigger(Player* player, AreaTriggerEntry const* /*trigger*/) override { @@ -83,11 +79,7 @@ enum LegionTeleporter class AreaTrigger_at_legion_teleporter : public AreaTriggerScript { public: - - AreaTrigger_at_legion_teleporter() - : AreaTriggerScript("at_legion_teleporter") - { - } + AreaTrigger_at_legion_teleporter() : AreaTriggerScript("at_legion_teleporter") { } bool OnTrigger(Player* player, AreaTriggerEntry const* /*trigger*/) override { @@ -125,11 +117,7 @@ enum StormwrightShelf class AreaTrigger_at_stormwright_shelf : public AreaTriggerScript { public: - - AreaTrigger_at_stormwright_shelf() - : AreaTriggerScript("at_stormwright_shelf") - { - } + AreaTrigger_at_stormwright_shelf() : AreaTriggerScript("at_stormwright_shelf") { } bool OnTrigger(Player* player, AreaTriggerEntry const* /*trigger*/) override { @@ -153,11 +141,7 @@ enum ScentLarkorwi class AreaTrigger_at_scent_larkorwi : public AreaTriggerScript { public: - - AreaTrigger_at_scent_larkorwi() - : AreaTriggerScript("at_scent_larkorwi") - { - } + AreaTrigger_at_scent_larkorwi() : AreaTriggerScript("at_scent_larkorwi") { } bool OnTrigger(Player* player, AreaTriggerEntry const* /*trigger*/) override { @@ -184,11 +168,7 @@ enum AtLastRites class AreaTrigger_at_last_rites : public AreaTriggerScript { public: - - AreaTrigger_at_last_rites() - : AreaTriggerScript("at_last_rites") - { - } + AreaTrigger_at_last_rites() : AreaTriggerScript("at_last_rites") { } bool OnTrigger(Player* player, AreaTriggerEntry const* trigger) override { @@ -246,7 +226,6 @@ enum Waygate class AreaTrigger_at_sholazar_waygate : public AreaTriggerScript { public: - AreaTrigger_at_sholazar_waygate() : AreaTriggerScript("at_sholazar_waygate") { } bool OnTrigger(Player* player, AreaTriggerEntry const* trigger) override diff --git a/src/server/scripts/World/go_scripts.cpp b/src/server/scripts/World/go_scripts.cpp index ca00b0fc352..4bb88a560bb 100644 --- a/src/server/scripts/World/go_scripts.cpp +++ b/src/server/scripts/World/go_scripts.cpp @@ -118,7 +118,8 @@ public: enum GildedBrazier { - NPC_STILLBLADE = 17716, + NPC_STILLBLADE = 17716, + QUEST_THE_FIRST_TRIAL = 9678 }; class go_gilded_brazier : public GameObjectScript @@ -130,7 +131,7 @@ public: { if (go->GetGoType() == GAMEOBJECT_TYPE_GOOBER) { - if (player->GetQuestStatus(9678) == QUEST_STATUS_INCOMPLETE) + if (player->GetQuestStatus(QUEST_THE_FIRST_TRIAL) == QUEST_STATUS_INCOMPLETE) { if (Creature* Stillblade = player->SummonCreature(NPC_STILLBLADE, 8106.11f, -7542.06f, 151.775f, 3.02598f, TEMPSUMMON_DEAD_DESPAWN, 60000)) Stillblade->AI()->AttackStart(player); diff --git a/src/server/scripts/World/guards.cpp b/src/server/scripts/World/guards.cpp index 21a81d37868..a156a41fcef 100644 --- a/src/server/scripts/World/guards.cpp +++ b/src/server/scripts/World/guards.cpp @@ -387,7 +387,7 @@ public: void AddSC_guards() { - new guard_generic; - new guard_shattrath_aldor; - new guard_shattrath_scryer; + new guard_generic(); + new guard_shattrath_aldor(); + new guard_shattrath_scryer(); } diff --git a/src/server/scripts/World/mob_generic_creature.cpp b/src/server/scripts/World/mob_generic_creature.cpp index 30666d5d2ea..2eb91b7b8fe 100644 --- a/src/server/scripts/World/mob_generic_creature.cpp +++ b/src/server/scripts/World/mob_generic_creature.cpp @@ -229,6 +229,6 @@ public: void AddSC_generic_creature() { //new generic_creature; - new trigger_periodic; + new trigger_periodic(); //new trigger_death; } diff --git a/src/server/scripts/World/npc_innkeeper.cpp b/src/server/scripts/World/npc_innkeeper.cpp index b647cccf8ea..be56e57cc9d 100644 --- a/src/server/scripts/World/npc_innkeeper.cpp +++ b/src/server/scripts/World/npc_innkeeper.cpp @@ -134,6 +134,6 @@ public: void AddSC_npc_innkeeper() { - new npc_innkeeper; + new npc_innkeeper(); } diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index c32edff09bc..e67823a2939 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -185,7 +185,6 @@ public: } void MoveInLineOfSight(Unit* who) override - { if (!SpawnAssoc) return; @@ -1520,7 +1519,10 @@ class npc_brewfest_reveler : public CreatureScript enum TrainingDummy { NPC_ADVANCED_TARGET_DUMMY = 2674, - NPC_TARGET_DUMMY = 2673 + NPC_TARGET_DUMMY = 2673, + + EVENT_TD_CHECK_COMBAT = 1, + EVENT_TD_DESPAWN = 2 }; class npc_training_dummy : public CreatureScript @@ -1533,20 +1535,22 @@ public: npc_training_dummyAI(Creature* creature) : ScriptedAI(creature) { SetCombatMovement(false); - entry = creature->GetEntry(); } - uint32 entry; - uint32 resetTimer; - uint32 despawnTimer; + EventMap _events; + std::unordered_map<uint64, time_t> _damageTimes; void Reset() override { me->SetControlled(true, UNIT_STATE_STUNNED);//disable rotate me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true);//imune to knock aways like blast wave - resetTimer = 5000; - despawnTimer = 15000; + _events.Reset(); + _damageTimes.clear(); + if (me->GetEntry() != NPC_ADVANCED_TARGET_DUMMY && me->GetEntry() != NPC_TARGET_DUMMY) + _events.ScheduleEvent(EVENT_TD_CHECK_COMBAT, 1000); + else + _events.ScheduleEvent(EVENT_TD_DESPAWN, 15000); } void EnterEvadeMode() override @@ -1557,37 +1561,52 @@ public: Reset(); } - void DamageTaken(Unit* /*doneBy*/, uint32& damage) override + void DamageTaken(Unit* doneBy, uint32& damage) override { - resetTimer = 5000; + me->AddThreat(doneBy, float(damage)); // just to create threat reference + _damageTimes[doneBy->GetGUID()] = time(NULL); damage = 0; } void UpdateAI(uint32 diff) override { - if (!UpdateVictim()) + if (!me->IsInCombat()) return; if (!me->HasUnitState(UNIT_STATE_STUNNED)) me->SetControlled(true, UNIT_STATE_STUNNED);//disable rotate - if (entry != NPC_ADVANCED_TARGET_DUMMY && entry != NPC_TARGET_DUMMY) + _events.Update(diff); + + if (uint32 eventId = _events.ExecuteEvent()) { - if (resetTimer <= diff) + switch (eventId) { - EnterEvadeMode(); - resetTimer = 5000; + case EVENT_TD_CHECK_COMBAT: + { + time_t now = time(NULL); + for (std::unordered_map<uint64, time_t>::iterator itr = _damageTimes.begin(); itr != _damageTimes.end();) + { + // If unit has not dealt damage to training dummy for 5 seconds, remove him from combat + if (itr->second < now - 5) + { + if (Unit* unit = ObjectAccessor::GetUnit(*me, itr->first)) + unit->getHostileRefManager().deleteReference(me); + + itr = _damageTimes.erase(itr); + } + else + ++itr; + } + _events.ScheduleEvent(EVENT_TD_CHECK_COMBAT, 1000); + break; + } + case EVENT_TD_DESPAWN: + me->DespawnOrUnsummon(1); + break; + default: + break; } - else - resetTimer -= diff; - return; - } - else - { - if (despawnTimer <= diff) - me->DespawnOrUnsummon(); - else - despawnTimer -= diff; } } |