diff options
Diffstat (limited to 'src/server/scripts')
34 files changed, 4319 insertions, 673 deletions
diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt index 9726cc1a937..cf4618022b3 100644 --- a/src/server/scripts/CMakeLists.txt +++ b/src/server/scripts/CMakeLists.txt @@ -45,6 +45,8 @@ message("") include_directories( ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast ${CMAKE_SOURCE_DIR}/dep/g3dlite/include ${CMAKE_SOURCE_DIR}/dep/SFMT ${CMAKE_SOURCE_DIR}/dep/zlib diff --git a/src/server/scripts/Commands/CMakeLists.txt b/src/server/scripts/Commands/CMakeLists.txt index 97e9b35e6cd..7b9e2444952 100644 --- a/src/server/scripts/Commands/CMakeLists.txt +++ b/src/server/scripts/Commands/CMakeLists.txt @@ -42,6 +42,7 @@ set(scripts_STAT_SRCS Commands/cs_server.cpp Commands/cs_titles.cpp Commands/cs_wp.cpp + Commands/cs_mmaps.cpp # Commands/cs_pdump.cpp # Commands/cs_channel.cpp # Commands/cs_pet.cpp diff --git a/src/server/scripts/Commands/cs_disable.cpp b/src/server/scripts/Commands/cs_disable.cpp index 37e282cac8e..34738777c85 100644 --- a/src/server/scripts/Commands/cs_disable.cpp +++ b/src/server/scripts/Commands/cs_disable.cpp @@ -48,6 +48,7 @@ public: { "achievement_criteria", SEC_ADMINISTRATOR, true, &HandleRemoveDisableAchievementCriteriaCommand, "", NULL }, { "outdoorpvp", SEC_ADMINISTRATOR, true, &HandleRemoveDisableOutdoorPvPCommand, "", NULL }, { "vmap", SEC_ADMINISTRATOR, true, &HandleRemoveDisableVmapCommand, "", NULL }, + { "mmap", SEC_ADMINISTRATOR, true, &HandleRemoveDisableMMapCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; static ChatCommand addDisableCommandTable[] = @@ -59,6 +60,7 @@ public: { "achievement_criteria", SEC_ADMINISTRATOR, true, &HandleAddDisableAchievementCriteriaCommand, "", NULL }, { "outdoorpvp", SEC_ADMINISTRATOR, true, &HandleAddDisableOutdoorPvPCommand, "", NULL }, { "vmap", SEC_ADMINISTRATOR, true, &HandleAddDisableVmapCommand, "", NULL }, + { "mmap", SEC_ADMINISTRATOR, true, &HandleAddDisableMMapCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; static ChatCommand disableCommandTable[] = @@ -172,6 +174,17 @@ public: disableTypeStr = "vmap"; break; } + case DISABLE_TYPE_MMAP: + { + if (!sMapStore.LookupEntry(entry)) + { + handler->PSendSysMessage(LANG_COMMAND_NOMAPFOUND); + handler->SetSentErrorMessage(true); + return false; + } + disableTypeStr = "mmap"; + break; + } default: break; } @@ -256,6 +269,14 @@ public: return HandleAddDisables(handler, args, DISABLE_TYPE_VMAP); } + static bool HandleAddDisableMMapCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + return HandleAddDisables(handler, args, DISABLE_TYPE_MMAP); + } + static bool HandleRemoveDisables(ChatHandler* handler, char const* args, uint8 disableType) { char* entryStr = strtok((char*)args, " "); @@ -289,6 +310,9 @@ public: case DISABLE_TYPE_VMAP: disableTypeStr = "vmap"; break; + case DISABLE_TYPE_MMAP: + disableTypeStr = "mmap"; + break; } PreparedStatement* stmt = NULL; @@ -367,6 +391,14 @@ public: return HandleRemoveDisables(handler, args, DISABLE_TYPE_VMAP); } + + static bool HandleRemoveDisableMMapCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + return HandleRemoveDisables(handler, args, DISABLE_TYPE_MMAP); + } }; void AddSC_disable_commandscript() diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 54fe41a8a4d..e2b5ac9487d 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -46,6 +46,7 @@ public: { "leader", SEC_ADMINISTRATOR, false, &HandleGroupLeaderCommand, "", NULL }, { "disband", SEC_ADMINISTRATOR, false, &HandleGroupDisbandCommand, "", NULL }, { "remove", SEC_ADMINISTRATOR, false, &HandleGroupRemoveCommand, "", NULL }, + { "join", SEC_ADMINISTRATOR, false, &HandleGroupJoinCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; static ChatCommand petCommandTable[] = @@ -2725,6 +2726,61 @@ public: return true; } + static bool HandleGroupJoinCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + Player* playerSource = NULL; + Player* playerTarget = NULL; + Group* groupSource = NULL; + Group* groupTarget = NULL; + uint64 guidSource = 0; + uint64 guidTarget = 0; + char* nameplgrStr = strtok((char*)args, " "); + char* nameplStr = strtok(NULL, " "); + + if (handler->GetPlayerGroupAndGUIDByName(nameplgrStr, playerSource, groupSource, guidSource, true)) + { + if (groupSource) + { + if (handler->GetPlayerGroupAndGUIDByName(nameplStr, playerTarget, groupTarget, guidTarget, true)) + { + if (!groupTarget && playerTarget->GetGroup() != groupSource) + { + if (!groupSource->IsFull()) + { + groupSource->AddMember(playerTarget); + groupSource->BroadcastGroupUpdate(); + handler->PSendSysMessage(LANG_GROUP_PLAYER_JOINED, playerTarget->GetName().c_str(), playerSource->GetName().c_str()); + return true; + } + else + { + // group is full + handler->PSendSysMessage(LANG_GROUP_FULL); + return true; + } + } + else + { + // group is full or target player already in a group + handler->PSendSysMessage(LANG_GROUP_ALREADY_IN_GROUP, playerTarget->GetName().c_str()); + return true; + } + } + } + else + { + // specified source player is not in a group + handler->PSendSysMessage(LANG_GROUP_NOT_IN_GROUP, playerSource->GetName().c_str()); + return true; + } + } + + return true; + } + static bool HandlePlayAllCommand(ChatHandler* handler, char const* args) { if (!*args) diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp new file mode 100644 index 00000000000..97861133983 --- /dev/null +++ b/src/server/scripts/Commands/cs_mmaps.cpp @@ -0,0 +1,294 @@ +/* + * Copyright (C) 2008-2013 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/>. + */ + +/** +* @file cs_mmaps.cpp +* @brief .mmap related commands +* +* This file contains the CommandScripts for all +* mmap sub-commands +*/ + +#include "ScriptMgr.h" +#include "Chat.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "PointMovementGenerator.h" +#include "PathGenerator.h" +#include "MMapFactory.h" +#include "Map.h" +#include "TargetedMovementGenerator.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "CellImpl.h" + +class mmaps_commandscript : public CommandScript +{ +public: + mmaps_commandscript() : CommandScript("mmaps_commandscript") { } + + ChatCommand* GetCommands() const + { + static ChatCommand mmapCommandTable[] = + { + { "path", SEC_ADMINISTRATOR, false, &HandleMmapPathCommand, "", NULL }, + { "loc", SEC_ADMINISTRATOR, false, &HandleMmapLocCommand, "", NULL }, + { "loadedtiles", SEC_ADMINISTRATOR, false, &HandleMmapLoadedTilesCommand, "", NULL }, + { "stats", SEC_ADMINISTRATOR, false, &HandleMmapStatsCommand, "", NULL }, + { "testarea", SEC_ADMINISTRATOR, false, &HandleMmapTestArea, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand commandTable[] = + { + { "mmap", SEC_ADMINISTRATOR, true, NULL, "", mmapCommandTable }, + { NULL, 0, false, NULL, "", NULL } + }; + return commandTable; + } + + static bool HandleMmapPathCommand(ChatHandler* handler, char const* args) + { + if (!MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId())) + { + handler->PSendSysMessage("NavMesh not loaded for current map."); + return true; + } + + handler->PSendSysMessage("mmap path:"); + + // units + Player* player = handler->GetSession()->GetPlayer(); + Unit* target = handler->getSelectedUnit(); + if (!player || !target) + { + handler->PSendSysMessage("Invalid target/source selection."); + return true; + } + + char* para = strtok((char*)args, " "); + + bool useStraightPath = false; + if (para && strcmp(para, "true") == 0) + useStraightPath = true; + + // unit locations + float x, y, z; + player->GetPosition(x, y, z); + + // path + PathGenerator path(target); + path.SetUseStraightPath(useStraightPath); + bool result = path.CalculatePath(x, y, z); + + PointsArray pointPath = path.GetPath(); + handler->PSendSysMessage("%s's path to %s:", target->GetName().c_str(), player->GetName().c_str()); + handler->PSendSysMessage("Building: %s", useStraightPath ? "StraightPath" : "SmoothPath"); + handler->PSendSysMessage("Result: %s - Length: "SIZEFMTD" - Type: %u", (result ? "true" : "false"), pointPath.size(), path.GetPathType()); + + Vector3 start = path.GetStartPosition(); + Vector3 end = path.GetEndPosition(); + Vector3 actualEnd = path.GetActualEndPosition(); + + handler->PSendSysMessage("StartPosition (%.3f, %.3f, %.3f)", start.x, start.y, start.z); + handler->PSendSysMessage("EndPosition (%.3f, %.3f, %.3f)", end.x, end.y, end.z); + handler->PSendSysMessage("ActualEndPosition (%.3f, %.3f, %.3f)", actualEnd.x, actualEnd.y, actualEnd.z); + + if (!player->isGameMaster()) + handler->PSendSysMessage("Enable GM mode to see the path points."); + + for (uint32 i = 0; i < pointPath.size(); ++i) + player->SummonCreature(VISUAL_WAYPOINT, pointPath[i].x, pointPath[i].y, pointPath[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 9000); + + return true; + } + + static bool HandleMmapLocCommand(ChatHandler* handler, char const* /*args*/) + { + handler->PSendSysMessage("mmap tileloc:"); + + // grid tile location + Player* player = handler->GetSession()->GetPlayer(); + + int32 gx = 32 - player->GetPositionX() / SIZE_OF_GRIDS; + int32 gy = 32 - player->GetPositionY() / SIZE_OF_GRIDS; + + handler->PSendSysMessage("%03u%02i%02i.mmtile", player->GetMapId(), gy, gx); + handler->PSendSysMessage("gridloc [%i,%i]", gx, gy); + + // calculate navmesh tile location + dtNavMesh const* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId()); + dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(handler->GetSession()->GetPlayer()->GetMapId(), player->GetInstanceId()); + if (!navmesh || !navmeshquery) + { + handler->PSendSysMessage("NavMesh not loaded for current map."); + return true; + } + + float const* min = navmesh->getParams()->orig; + float x, y, z; + player->GetPosition(x, y, z); + float location[VERTEX_SIZE] = {y, z, x}; + float extents[VERTEX_SIZE] = {3.0f, 5.0f, 3.0f}; + + int32 tilex = int32((y - min[0]) / SIZE_OF_GRIDS); + int32 tiley = int32((x - min[2]) / SIZE_OF_GRIDS); + + handler->PSendSysMessage("Calc [%02i,%02i]", tilex, tiley); + + // navmesh poly -> navmesh tile location + dtQueryFilter filter = dtQueryFilter(); + dtPolyRef polyRef = INVALID_POLYREF; + navmeshquery->findNearestPoly(location, extents, &filter, &polyRef, NULL); + + if (polyRef == INVALID_POLYREF) + handler->PSendSysMessage("Dt [??,??] (invalid poly, probably no tile loaded)"); + else + { + dtMeshTile const* tile; + dtPoly const* poly; + navmesh->getTileAndPolyByRef(polyRef, &tile, &poly); + if (tile) + handler->PSendSysMessage("Dt [%02i,%02i]", tile->header->x, tile->header->y); + else + handler->PSendSysMessage("Dt [??,??] (no tile loaded)"); + } + + return true; + } + + static bool HandleMmapLoadedTilesCommand(ChatHandler* handler, char const* /*args*/) + { + uint32 mapid = handler->GetSession()->GetPlayer()->GetMapId(); + dtNavMesh const* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(mapid); + dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(mapid, handler->GetSession()->GetPlayer()->GetInstanceId()); + if (!navmesh || !navmeshquery) + { + handler->PSendSysMessage("NavMesh not loaded for current map."); + return true; + } + + handler->PSendSysMessage("mmap loadedtiles:"); + + for (int32 i = 0; i < navmesh->getMaxTiles(); ++i) + { + dtMeshTile const* tile = navmesh->getTile(i); + if (!tile || !tile->header) + continue; + + handler->PSendSysMessage("[%02i,%02i]", tile->header->x, tile->header->y); + } + + return true; + } + + static bool HandleMmapStatsCommand(ChatHandler* handler, char const* /*args*/) + { + uint32 mapId = handler->GetSession()->GetPlayer()->GetMapId(); + handler->PSendSysMessage("mmap stats:"); + handler->PSendSysMessage(" global mmap pathfinding is %sabled", MMAP::MMapFactory::IsPathfindingEnabled(mapId) ? "en" : "dis"); + + MMAP::MMapManager* manager = MMAP::MMapFactory::createOrGetMMapManager(); + handler->PSendSysMessage(" %u maps loaded with %u tiles overall", manager->getLoadedMapsCount(), manager->getLoadedTilesCount()); + + dtNavMesh const* navmesh = manager->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId()); + if (!navmesh) + { + handler->PSendSysMessage("NavMesh not loaded for current map."); + return true; + } + + uint32 tileCount = 0; + uint32 nodeCount = 0; + uint32 polyCount = 0; + uint32 vertCount = 0; + uint32 triCount = 0; + uint32 triVertCount = 0; + uint32 dataSize = 0; + for (int32 i = 0; i < navmesh->getMaxTiles(); ++i) + { + dtMeshTile const* tile = navmesh->getTile(i); + if (!tile || !tile->header) + continue; + + tileCount++; + nodeCount += tile->header->bvNodeCount; + polyCount += tile->header->polyCount; + vertCount += tile->header->vertCount; + triCount += tile->header->detailTriCount; + triVertCount += tile->header->detailVertCount; + dataSize += tile->dataSize; + } + + handler->PSendSysMessage("Navmesh stats:"); + handler->PSendSysMessage(" %u tiles loaded", tileCount); + handler->PSendSysMessage(" %u BVTree nodes", nodeCount); + handler->PSendSysMessage(" %u polygons (%u vertices)", polyCount, vertCount); + handler->PSendSysMessage(" %u triangles (%u vertices)", triCount, triVertCount); + handler->PSendSysMessage(" %.2f MB of data (not including pointers)", ((float)dataSize / sizeof(unsigned char)) / 1048576); + + return true; + } + + static bool HandleMmapTestArea(ChatHandler* handler, char const* /*args*/) + { + float radius = 40.0f; + WorldObject* object = handler->GetSession()->GetPlayer(); + + CellCoord pair(Trinity::ComputeCellCoord(object->GetPositionX(), object->GetPositionY())); + Cell cell(pair); + cell.SetNoCreate(); + + std::list<Creature*> creatureList; + + Trinity::AnyUnitInObjectRangeCheck go_check(object, radius); + Trinity::CreatureListSearcher<Trinity::AnyUnitInObjectRangeCheck> go_search(object, creatureList, go_check); + TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AnyUnitInObjectRangeCheck>, GridTypeMapContainer> go_visit(go_search); + + // Get Creatures + cell.Visit(pair, go_visit, *(object->GetMap()), *object, radius); + + if (!creatureList.empty()) + { + handler->PSendSysMessage("Found "SIZEFMTD" Creatures.", creatureList.size()); + + uint32 paths = 0; + uint32 uStartTime = getMSTime(); + + float gx, gy, gz; + object->GetPosition(gx, gy, gz); + for (std::list<Creature*>::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr) + { + PathGenerator path(*itr); + path.CalculatePath(gx, gy, gz); + ++paths; + } + + uint32 uPathLoadTime = getMSTimeDiff(uStartTime, getMSTime()); + handler->PSendSysMessage("Generated %i paths in %i ms", paths, uPathLoadTime); + } + else + handler->PSendSysMessage("No creatures in %f yard range.", radius); + + return true; + } +}; + +void AddSC_mmaps_commandscript() +{ + new mmaps_commandscript(); +} diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index 8679e288282..7ccd5ed1177 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -33,6 +33,42 @@ EndScriptData */ #include "Player.h" #include "Pet.h" +struct NpcFlagText +{ + uint32 flag; + int32 text; +}; + +#define NPCFLAG_COUNT 24 + +const NpcFlagText npcFlagTexts[NPCFLAG_COUNT] = +{ + { UNIT_NPC_FLAG_AUCTIONEER, LANG_NPCINFO_AUCTIONEER }, + { UNIT_NPC_FLAG_BANKER, LANG_NPCINFO_BANKER }, + { UNIT_NPC_FLAG_BATTLEMASTER, LANG_NPCINFO_BATTLEMASTER }, + { UNIT_NPC_FLAG_FLIGHTMASTER, LANG_NPCINFO_FLIGHTMASTER }, + { UNIT_NPC_FLAG_GOSSIP, LANG_NPCINFO_GOSSIP }, + { UNIT_NPC_FLAG_GUILD_BANKER, LANG_NPCINFO_GUILD_BANKER }, + { UNIT_NPC_FLAG_INNKEEPER, LANG_NPCINFO_INNKEEPER }, + { UNIT_NPC_FLAG_PETITIONER, LANG_NPCINFO_PETITIONER }, + { UNIT_NPC_FLAG_PLAYER_VEHICLE, LANG_NPCINFO_PLAYER_VEHICLE }, + { UNIT_NPC_FLAG_QUESTGIVER, LANG_NPCINFO_QUESTGIVER }, + { UNIT_NPC_FLAG_REPAIR, LANG_NPCINFO_REPAIR }, + { UNIT_NPC_FLAG_SPELLCLICK, LANG_NPCINFO_SPELLCLICK }, + { UNIT_NPC_FLAG_SPIRITGUIDE, LANG_NPCINFO_SPIRITGUIDE }, + { UNIT_NPC_FLAG_SPIRITHEALER, LANG_NPCINFO_SPIRITHEALER }, + { UNIT_NPC_FLAG_STABLEMASTER, LANG_NPCINFO_STABLEMASTER }, + { UNIT_NPC_FLAG_TABARDDESIGNER, LANG_NPCINFO_TABARDDESIGNER }, + { UNIT_NPC_FLAG_TRAINER, LANG_NPCINFO_TRAINER }, + { UNIT_NPC_FLAG_TRAINER_CLASS, LANG_NPCINFO_TRAINER_CLASS }, + { UNIT_NPC_FLAG_TRAINER_PROFESSION, LANG_NPCINFO_TRAINER_PROFESSION }, + { UNIT_NPC_FLAG_VENDOR, LANG_NPCINFO_VENDOR }, + { UNIT_NPC_FLAG_VENDOR_AMMO, LANG_NPCINFO_VENDOR_AMMO }, + { UNIT_NPC_FLAG_VENDOR_FOOD, LANG_NPCINFO_VENDOR_FOOD }, + { UNIT_NPC_FLAG_VENDOR_POISON, LANG_NPCINFO_VENDOR_POISON }, + { UNIT_NPC_FLAG_VENDOR_REAGENT, LANG_NPCINFO_VENDOR_REAGENT } +}; + class npc_commandscript : public CommandScript { public: @@ -619,11 +655,9 @@ public: handler->PSendSysMessage(LANG_NPCINFO_POSITION, float(target->GetPositionX()), float(target->GetPositionY()), float(target->GetPositionZ())); handler->PSendSysMessage(LANG_NPCINFO_AIINFO, target->GetAIName().c_str(), target->GetScriptName().c_str()); - if (npcflags & UNIT_NPC_FLAG_VENDOR) - handler->SendSysMessage(LANG_NPCINFO_VENDOR); - - if (npcflags & UNIT_NPC_FLAG_TRAINER) - handler->SendSysMessage(LANG_NPCINFO_TRAINER); + for (uint8 i = 0; i < NPCFLAG_COUNT; i++) + if (npcflags & npcFlagTexts[i].flag) + handler->PSendSysMessage(npcFlagTexts[i].text, npcFlagTexts[i].flag); return true; } diff --git a/src/server/scripts/EasternKingdoms/Scholomance/boss_kirtonos_the_herald.cpp b/src/server/scripts/EasternKingdoms/Scholomance/boss_kirtonos_the_herald.cpp index b0a2d48d053..19660cec4af 100644 --- a/src/server/scripts/EasternKingdoms/Scholomance/boss_kirtonos_the_herald.cpp +++ b/src/server/scripts/EasternKingdoms/Scholomance/boss_kirtonos_the_herald.cpp @@ -64,6 +64,12 @@ enum eMisc KIRTONOS_PATH = 105061 }; +Position const PosMove[2] = +{ + { 299.4884f, 92.76137f, 105.6335f, 0.0f }, + { 314.8673f, 90.30210f, 101.6459f, 0.0f } +}; + class boss_kirtonos_the_herald : public CreatureScript { public: boss_kirtonos_the_herald() : CreatureScript("boss_kirtonos_the_herald") { } @@ -74,15 +80,11 @@ class boss_kirtonos_the_herald : public CreatureScript void Reset() { - _introEvent = 0; - _introTimer = 0; _Reset(); } void EnterCombat(Unit* /*who*/) { - _introTimer = 0; - _introEvent = 0; events.ScheduleEvent(EVENT_SWOOP, urand(8000, 8000)); events.ScheduleEvent(EVENT_WING_FLAP, urand(15000, 15000)); events.ScheduleEvent(EVENT_PIERCE_ARMOR, urand(18000, 18000)); @@ -120,12 +122,10 @@ class boss_kirtonos_the_herald : public CreatureScript void IsSummonedBy(Unit* /*summoner*/) { + events.ScheduleEvent(INTRO_1, 500); me->SetDisableGravity(true); me->SetReactState(REACT_PASSIVE); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - _introEvent = INTRO_1; - _introTimer = 1; - _currentPoint = 0; Talk(EMOTE_SUMMONED); } @@ -138,68 +138,58 @@ class boss_kirtonos_the_herald : public CreatureScript { if (type == WAYPOINT_MOTION_TYPE && id == POINT_KIRTONOS_LAND) { - _introTimer = 1500; - _introEvent = INTRO_2; + events.ScheduleEvent(INTRO_2, 1500); } } void UpdateAI(uint32 const diff) { - if (_introEvent) + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent() && !UpdateVictim()) { - if (_introTimer <= diff) + switch (eventId) { - switch (_introEvent) - { - case INTRO_1: - me->GetMotionMaster()->MovePath(KIRTONOS_PATH, false); - _introEvent = 0; - break; - case INTRO_2: - me->GetMotionMaster()->MovePoint(0, 299.4884f, 92.76137f, 105.6335f); - _introTimer = 1000; - _introEvent = INTRO_3; - break; - case INTRO_3: - if (GameObject* gate = me->GetMap()->GetGameObject(instance->GetData64(GO_GATE_KIRTONOS))) - gate->SetGoState(GO_STATE_READY); - me->SetFacingTo(0.01745329f); - _introTimer = 3000; - _introEvent = INTRO_4; - break; - case INTRO_4: - if (GameObject* brazier = me->GetMap()->GetGameObject(instance->GetData64(GO_BRAZIER_OF_THE_HERALD))) - brazier->SetGoState(GO_STATE_READY); - me->SetWalk(true); - me->SetDisableGravity(false); - DoCast(me, SPELL_KIRTONOS_TRANSFORM); - me->SetCanFly(false); - _introTimer = 1000; - _introEvent = INTRO_5; - break; - case INTRO_5: - me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_KIRTONOS_STAFF)); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - me->SetReactState(REACT_AGGRESSIVE); - _introTimer = 5000; - _introEvent = INTRO_6; - case INTRO_6: - me->GetMotionMaster()->MovePoint(0, 314.8673f, 90.3021f, 101.6459f); - _introTimer = 0; - _introEvent = 0; + case INTRO_1: + me->GetMotionMaster()->MovePath(KIRTONOS_PATH, false); + break; + case INTRO_2: + me->GetMotionMaster()->MovePoint(0, PosMove[0]); + events.ScheduleEvent(INTRO_3, 1000); + break; + case INTRO_3: + if (GameObject* gate = me->GetMap()->GetGameObject(instance->GetData64(GO_GATE_KIRTONOS))) + gate->SetGoState(GO_STATE_READY); + me->SetFacingTo(0.01745329f); + events.ScheduleEvent(INTRO_4, 3000); + break; + case INTRO_4: + if (GameObject* brazier = me->GetMap()->GetGameObject(instance->GetData64(GO_BRAZIER_OF_THE_HERALD))) + brazier->SetGoState(GO_STATE_READY); + me->SetWalk(true); + me->SetDisableGravity(false); + DoCast(me, SPELL_KIRTONOS_TRANSFORM); + me->SetCanFly(false); + events.ScheduleEvent(INTRO_5, 1000); + break; + case INTRO_5: + me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_KIRTONOS_STAFF)); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_AGGRESSIVE); + events.ScheduleEvent(INTRO_6, 5000); + break; + case INTRO_6: + me->GetMotionMaster()->MovePoint(0, PosMove[1]); + break; + default: break; - } } - else - _introTimer -= diff; } if (!UpdateVictim()) return; - events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) return; @@ -257,11 +247,6 @@ class boss_kirtonos_the_herald : public CreatureScript DoMeleeAttackIfReady(); } - - private: - uint8 _introEvent; - uint32 _introTimer; - uint32 _currentPoint; }; CreatureAI* GetAI(Creature* creature) const @@ -280,6 +265,11 @@ enum Brazier_Of_The_Herald SOUND_SCREECH = 557 }; +Position const PosSummon[1] = +{ + { 315.028f, 70.53845f, 102.1496f, 0.3859715f } +}; + class go_brazier_of_the_herald : public GameObjectScript { public: @@ -289,7 +279,7 @@ class go_brazier_of_the_herald : public GameObjectScript { go->UseDoorOrButton(); go->PlayDirectSound(SOUND_SCREECH, 0); - player->SummonCreature(NPC_KIRTONOS, 315.028f, 70.53845f, 102.1496f, 0.3859715f, TEMPSUMMON_DEAD_DESPAWN, 900000); + player->SummonCreature(NPC_KIRTONOS, PosSummon[0], TEMPSUMMON_DEAD_DESPAWN, 900000); return true; } }; diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp index 1334d587464..c2806c395f4 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2013 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 @@ -17,60 +16,74 @@ */ /* ScriptData -SDName: Boss_Arlokk -SD%Complete: 95 -SDComment: Wrong cleave and red aura is missing. -SDCategory: Zul'Gurub +TCName: Boss_Arlokk +TC%Complete: 95 +TCComment: Wrong cleave and red aura is missing not yet added. +TCComment: Prowlers moving through wall hopefully mmaps will fix. +TCComment: Can't test LOS until mmaps. +TCCategory: Zul'Gurub EndScriptData */ #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "SpellInfo.h" #include "zulgurub.h" enum Says { SAY_AGGRO = 0, - SAY_FEAST_PANTHER = 1, + SAY_FEAST_PROWLER = 1, SAY_DEATH = 2 }; enum Spells { - SPELL_SHADOW_WORD_PAIN = 23952, - SPELL_GOUGE = 24698, - SPELL_MARK = 24210, - SPELL_CLEAVE = 26350, // Perhaps not right. Not a red aura... - SPELL_PANTHER_TRANSFORM = 24190 + SPELL_SHADOW_WORD_PAIN = 24212, // Corrected + SPELL_GOUGE = 12540, // Corrected + SPELL_MARK_OF_ARLOKK = 24210, // triggered spell 24211 Added to spell_dbc + SPELL_RAVAGE = 24213, // Corrected + SPELL_CLEAVE = 25174, // Searching for right spell + SPELL_PANTHER_TRANSFORM = 24190, // Transform to panther now used + SPELL_SUMMON_PROWLER = 24246, // Added to Spell_dbc + SPELL_VANISH_VISUAL = 24222, // Added + SPELL_VANISH = 24223, // Added + SPELL_SUPER_INVIS = 24235 // Added to Spell_dbc }; enum Events { - EVENT_SHADOW_WORD_PAIN = 0, - EVENT_GOUGE = 1, - EVENT_MARK = 2, - EVENT_CLEAVE = 3, - EVENT_VANISH = 4, - EVENT_VISIBLE = 5, - EVENT_SUMMON = 6 + EVENT_SHADOW_WORD_PAIN = 1, + EVENT_GOUGE = 2, + EVENT_MARK_OF_ARLOKK = 3, + EVENT_RAVAGE = 4, + EVENT_TRANSFORM = 5, + EVENT_VANISH = 6, + EVENT_VANISH_2 = 7, + EVENT_TRANSFORM_BACK = 8, + EVENT_VISIBLE = 9, + EVENT_SUMMON_PROWLERS = 10 }; enum Phases { - PHASE_ONE = 1, - PHASE_TWO = 2 + PHASE_ALL = 0, + PHASE_ONE = 1, + PHASE_TWO = 2 }; -enum ModelIds +enum Weapon { - MODEL_ID_NORMAL = 15218, - MODEL_ID_PANTHER = 15215, - MODEL_ID_BLANK = 11686 + WEAPON_DAGGER = 10616 }; -Position const PosSummonProwlers[2] = +enum Misc { - { -11532.7998f, -1649.6734f, 41.4800f, 0.0f }, - { -11532.9970f, -1606.4840f, 41.2979f, 0.0f } + MAX_PROWLERS_PER_SIDE = 15 +}; + +Position const PosMoveOnSpawn[1] = +{ + { -11561.9f, -1627.868f, 41.29941f, 0.0f } }; class boss_arlokk : public CreatureScript @@ -79,58 +92,92 @@ class boss_arlokk : public CreatureScript struct boss_arlokkAI : public BossAI { - boss_arlokkAI(Creature* creature) : BossAI(creature, DATA_ARLOKK) {} - - uint32 summonCount; - // Unit* markedTarget; - uint64 markedTargetGUID; + boss_arlokkAI(Creature* creature) : BossAI(creature, DATA_ARLOKK) { } void Reset() { - summonCount = 0; - markedTargetGUID = 0; - me->SetDisplayId(MODEL_ID_NORMAL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + _summonCountA = 0; + _summonCountB = 0; + me->RemoveAllAuras(); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_DAGGER)); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(WEAPON_DAGGER)); + if (instance) + { + if (GameObject* gate = me->GetMap()->GetGameObject(instance->GetData64(GO_FORCEFIELD))) + gate->SetGoState(GO_STATE_READY); + me->SetWalk(false); + me->GetMotionMaster()->MovePoint(0, PosMoveOnSpawn[0]); + } } void JustDied(Unit* /*killer*/) { - _JustDied(); Talk(SAY_DEATH); - me->SetDisplayId(MODEL_ID_NORMAL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveAllAuras(); + if (instance) + { + if (GameObject* gate = me->GetMap()->GetGameObject(instance->GetData64(GO_FORCEFIELD))) + gate->SetGoState(GO_STATE_ACTIVE); + instance->SetBossState(DATA_ARLOKK, DONE); + } } void EnterCombat(Unit* /*who*/) { _EnterCombat(); - events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 8000, 0, PHASE_ONE); - events.ScheduleEvent(EVENT_MARK, 35000, 0, PHASE_ONE); - events.ScheduleEvent(EVENT_SUMMON, 5000); - events.ScheduleEvent(EVENT_VANISH, 60000); + events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(7000, 9000), 0, PHASE_ONE); + events.ScheduleEvent(EVENT_GOUGE, urand(12000, 15000), 0, PHASE_ONE); + if (instance) + events.ScheduleEvent(EVENT_SUMMON_PROWLERS, 6000, 0, PHASE_ALL); + events.ScheduleEvent(EVENT_MARK_OF_ARLOKK, urand(9000, 11000), 0, PHASE_ALL); + events.ScheduleEvent(EVENT_TRANSFORM, urand(15000, 20000), 0, PHASE_ONE); Talk(SAY_AGGRO); - } - void JustReachedHome() - { - if (instance) - instance->SetData(DATA_ARLOKK, NOT_STARTED); - me->DespawnOrUnsummon(); + // Sets up list of Panther spawners to cast on + std::list<Creature*> triggerList; + GetCreatureListWithEntryInGrid(triggerList, me, NPC_PANTHER_TRIGGER, 100.0f); + if (!triggerList.empty()) + { + uint8 sideA = 0; + uint8 sideB = 0; + for (std::list<Creature*>::const_iterator itr = triggerList.begin(); itr != triggerList.end(); ++itr) + { + if (Creature* trigger = *itr) + { + if (trigger->GetPositionY() < -1625.0f) + { + _triggersSideAGUID[sideA] = trigger->GetGUID(); + ++sideA; + } + else + { + _triggersSideBGUID[sideB] = trigger->GetGUID(); + ++sideB; + } + } + } + } } - void DoSummonPhanters() + void EnterEvadeMode() { - if (markedTargetGUID) - Talk(SAY_FEAST_PANTHER, markedTargetGUID); - me->SummonCreature(NPC_ZULIAN_PROWLER, PosSummonProwlers[0], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - me->SummonCreature(NPC_ZULIAN_PROWLER, PosSummonProwlers[1], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (instance) + { + if (GameObject* object = me->GetMap()->GetGameObject(instance->GetData64(GO_FORCEFIELD))) + object->SetGoState(GO_STATE_ACTIVE); + if (GameObject* object = me->GetMap()->GetGameObject(instance->GetData64(GO_GONG_OF_BETHEKK))) + object->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + instance->SetBossState(DATA_ARLOKK, NOT_STARTED); + } + me->DespawnOrUnsummon(4000); } - void JustSummoned(Creature* summoned) + void SetData(uint32 id, uint32 /*value*/) { - if (Unit* markedTarget = Unit::GetUnit(*me, markedTargetGUID)) - summoned->AI()->AttackStart(markedTarget); - ++summonCount; + if (id == 1) + --_summonCountA; + else if (id == 2) + --_summonCountB; } void UpdateAI(uint32 const diff) @@ -149,48 +196,104 @@ class boss_arlokk : public CreatureScript { case EVENT_SHADOW_WORD_PAIN: DoCastVictim(SPELL_SHADOW_WORD_PAIN, true); - events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 15000, 0, PHASE_ONE); - break; - case EVENT_MARK: - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_MARK); - events.ScheduleEvent(EVENT_MARK, 15000, 0, PHASE_ONE); - break; - case EVENT_CLEAVE: - DoCastVictim(SPELL_SHADOW_WORD_PAIN, true); - events.ScheduleEvent(EVENT_CLEAVE, 16000, 0, PHASE_TWO); + events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(5000, 7000), 0, PHASE_ONE); break; case EVENT_GOUGE: - DoCastVictim(SPELL_SHADOW_WORD_PAIN, true); - events.ScheduleEvent(EVENT_GOUGE, urand(17000, 27000), 0, PHASE_TWO); + DoCastVictim(SPELL_GOUGE, true); break; - case EVENT_SUMMON: - if (summonCount <= 30) - DoSummonPhanters(); - events.ScheduleEvent(EVENT_SUMMON, 5000); + case EVENT_SUMMON_PROWLERS: + if (_summonCountA < MAX_PROWLERS_PER_SIDE) + { + if (Unit* trigger = me->GetUnit(*me, _triggersSideAGUID[urand(0, 4)])) + { + trigger->CastSpell(trigger, SPELL_SUMMON_PROWLER); + ++_summonCountA; + } + } + if (_summonCountB < MAX_PROWLERS_PER_SIDE) + { + if (Unit* trigger = me->GetUnit(*me, _triggersSideBGUID[urand(0, 4)])) + { + trigger->CastSpell(trigger, SPELL_SUMMON_PROWLER); + ++_summonCountB; + } + } + events.ScheduleEvent(EVENT_SUMMON_PROWLERS, 6000, 0, PHASE_ALL); break; - case EVENT_VANISH: - me->SetDisplayId(MODEL_ID_BLANK); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + case EVENT_MARK_OF_ARLOKK: + { + Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, urand(1,3), 0.0f, false, -SPELL_MARK_OF_ARLOKK); + if (!target) + target = me->getVictim(); + if (target) + { + DoCast(target, SPELL_MARK_OF_ARLOKK, true); + Talk(SAY_FEAST_PROWLER, target->GetGUID()); + } + events.ScheduleEvent(EVENT_MARK_OF_ARLOKK, urand(120000, 130000)); + break; + } + case EVENT_TRANSFORM: + { + DoCast(me, SPELL_PANTHER_TRANSFORM); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(EQUIP_UNEQUIP)); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(EQUIP_UNEQUIP)); + const CreatureTemplate* cinfo = me->GetCreatureTemplate(); + me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35))); + me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35))); + me->UpdateDamagePhysical(BASE_ATTACK); me->AttackStop(); DoResetThreat(); - events.ScheduleEvent(EVENT_VISIBLE, 6000); + me->SetReactState(REACT_PASSIVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + DoCast(me, SPELL_VANISH_VISUAL); + DoCast(me, SPELL_VANISH); + events.ScheduleEvent(EVENT_VANISH, 1000, 0, PHASE_ONE); + break; + } + case EVENT_VANISH: + DoCast(me, SPELL_SUPER_INVIS); + me->SetWalk(false); + if (instance) + me->GetMotionMaster()->MovePoint(0, frand(-11551.0f, -11508.0f), frand(-1638.0f, -1617.0f), me->GetPositionZ()); + events.ScheduleEvent(EVENT_VANISH_2, 9000, 0, PHASE_ONE); + break; + case EVENT_VANISH_2: + DoCast(me, SPELL_VANISH); + DoCast(me, SPELL_SUPER_INVIS); + events.ScheduleEvent(EVENT_VISIBLE, urand(7000, 10000), 0, PHASE_ONE); break; case EVENT_VISIBLE: - { - me->SetDisplayId(MODEL_ID_PANTHER); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - const CreatureTemplate* cinfo = me->GetCreatureTemplate(); - me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35))); - me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35))); - me->UpdateDamagePhysical(BASE_ATTACK); - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - AttackStart(target); - events.ScheduleEvent(EVENT_VANISH, 39000); - events.ScheduleEvent(EVENT_CLEAVE, 0, PHASE_TWO); - events.ScheduleEvent(EVENT_GOUGE, 14000, 0, PHASE_TWO); - events.SetPhase(PHASE_TWO); - break; - } + me->SetReactState(REACT_AGGRESSIVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + AttackStart(target); + me->RemoveAura(SPELL_SUPER_INVIS); + me->RemoveAura(SPELL_VANISH); + events.ScheduleEvent(EVENT_RAVAGE, urand(10000, 14000), 0, PHASE_TWO); + events.ScheduleEvent(EVENT_TRANSFORM_BACK, urand(15000, 18000), 0, PHASE_TWO); + events.SetPhase(PHASE_TWO); + break; + case EVENT_RAVAGE: + DoCastVictim(SPELL_RAVAGE, true); + events.ScheduleEvent(EVENT_RAVAGE, urand(10000, 14000), 0, PHASE_TWO); + break; + case EVENT_TRANSFORM_BACK: + { + me->RemoveAura(SPELL_PANTHER_TRANSFORM); + DoCast(me, SPELL_VANISH_VISUAL); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_DAGGER)); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(WEAPON_DAGGER)); + const CreatureTemplate* cinfo = me->GetCreatureTemplate(); + me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg)); + me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg)); + me->UpdateDamagePhysical(BASE_ATTACK); + events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(4000, 7000), 0, PHASE_ONE); + events.ScheduleEvent(EVENT_GOUGE, urand(12000, 15000), 0, PHASE_ONE); + events.ScheduleEvent(EVENT_TRANSFORM, urand(16000, 20000), 0, PHASE_ONE); + events.SetPhase(PHASE_ONE); + break; + } default: break; } @@ -198,28 +301,148 @@ class boss_arlokk : public CreatureScript DoMeleeAttackIfReady(); } + + private: + uint8 _summonCountA; + uint8 _summonCountB; + uint64 _triggersSideAGUID[5]; + uint64 _triggersSideBGUID[5]; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetZulGurubAI<boss_arlokkAI>(creature); + } +}; + +/*###### +## npc_zulian_prowler +######*/ + +enum ZulianProwlerSpells +{ + SPELL_SNEAK_RANK_1_1 = 22766, + SPELL_SNEAK_RANK_1_2 = 7939, // Added to Spell_dbc + SPELL_MARK_OF_ARLOKK_TRIGGER = 24211 // Added to Spell_dbc +}; + +enum ZulianProwlerEvents +{ + EVENT_ATTACK = 1 +}; + +Position const PosProwlerCenter[1] = +{ + { -11556.7f, -1631.344f, 41.2994f, 0.0f } +}; + +class npc_zulian_prowler : public CreatureScript +{ + public: npc_zulian_prowler() : CreatureScript("npc_zulian_prowler") {} + + struct npc_zulian_prowlerAI : public ScriptedAI + { + npc_zulian_prowlerAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } + + void Reset() + { + if (me->GetPositionY() < -1625.0f) + _sideData = 1; + else + _sideData = 2; + + DoCast(me, SPELL_SNEAK_RANK_1_1); + DoCast(me, SPELL_SNEAK_RANK_1_2); + + if (_instance) + if (Unit* arlokk = me->GetUnit(*me, _instance->GetData64(NPC_ARLOKK))) + me->GetMotionMaster()->MovePoint(0, arlokk->GetPositionX(), arlokk->GetPositionY(), arlokk->GetPositionZ()); + _events.ScheduleEvent(EVENT_ATTACK, 6000); + } + + void EnterCombat(Unit* /*who*/) + { + me->GetMotionMaster()->Clear(false); + me->RemoveAura(SPELL_SNEAK_RANK_1_1); + me->RemoveAura(SPELL_SNEAK_RANK_1_2); + } + + void SpellHit(Unit* caster, SpellInfo const* spell) + { + if (spell->Id == SPELL_MARK_OF_ARLOKK_TRIGGER) // Should only hit if line of sight + me->Attack(caster, true); + } + + void JustDied(Unit* /*killer*/) + { + if (_instance) + { + if (Unit* arlokk = me->GetUnit(*me, _instance->GetData64(NPC_ARLOKK))) + { + if (arlokk->isAlive()) + arlokk->GetAI()->SetData(_sideData, 0); + } + } + me->DespawnOrUnsummon(4000); + } + + void UpdateAI(const uint32 diff) + { + if (UpdateVictim()) + { + DoMeleeAttackIfReady(); + return; + } + + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_ATTACK: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0.0f, 100, false)) + me->Attack(target, true); + break; + default: + break; + } + } + } + + private: + int32 _sideData; + EventMap _events; + InstanceScript* _instance; }; CreatureAI* GetAI(Creature* creature) const { - return new boss_arlokkAI(creature); + return GetZulGurubAI<npc_zulian_prowlerAI>(creature); } }; +/*###### +## go_gong_of_bethekk +######*/ + +Position const PosSummonArlokk[1] = +{ + { -11507.22f, -1628.062f, 41.38264f, 3.159046f } +}; + class go_gong_of_bethekk : public GameObjectScript { public: go_gong_of_bethekk() : GameObjectScript("go_gong_of_bethekk") {} bool OnGossipHello(Player* /*player*/, GameObject* go) { - if (InstanceScript* instance = go->GetInstanceScript()) + if (go->GetInstanceScript()) { - if (instance->GetData(DATA_ARLOKK) == DONE || instance->GetData(DATA_ARLOKK) == IN_PROGRESS) - return true; - instance->SetData(DATA_ARLOKK, IN_PROGRESS); - return true; + go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + go->SendCustomAnim(0); + go->SummonCreature(NPC_ARLOKK, PosSummonArlokk[0], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 600000); } - return true; } }; @@ -227,6 +450,6 @@ class go_gong_of_bethekk : public GameObjectScript void AddSC_boss_arlokk() { new boss_arlokk(); + new npc_zulian_prowler(); new go_gong_of_bethekk(); } - diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_gahzranka.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_gahzranka.cpp index 70399b6934c..f3f12bc35c5 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_gahzranka.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_gahzranka.cpp @@ -112,4 +112,3 @@ void AddSC_boss_gahzranka() { new boss_gahzranka(); } - diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp index 8003f4a1ed7..68aac7547df 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp @@ -90,15 +90,15 @@ class boss_hakkar : public CreatureScript events.ScheduleEvent(EVENT_CAUSE_INSANITY, 17000); events.ScheduleEvent(EVENT_WILL_OF_HAKKAR, 17000); events.ScheduleEvent(EVENT_ENRAGE, 600000); - if (instance->GetData(DATA_JEKLIK) != DONE) + if (instance->GetBossState(DATA_JEKLIK) != DONE) events.ScheduleEvent(EVENT_ASPECT_OF_JEKLIK, 4000); - if (instance->GetData(DATA_VENOXIS) != DONE) + if (instance->GetBossState(DATA_VENOXIS) != DONE) events.ScheduleEvent(EVENT_ASPECT_OF_VENOXIS, 7000); - if (instance->GetData(DATA_MARLI) != DONE) + if (instance->GetBossState(DATA_MARLI) != DONE) events.ScheduleEvent(EVENT_ASPECT_OF_MARLI, 12000); - if (instance->GetData(DATA_THEKAL) != DONE) + if (instance->GetBossState(DATA_THEKAL) != DONE) events.ScheduleEvent(EVENT_ASPECT_OF_THEKAL, 8000); - if (instance->GetData(DATA_ARLOKK) != DONE) + if (instance->GetBossState(DATA_ARLOKK) != DONE) events.ScheduleEvent(EVENT_ASPECT_OF_ARLOKK, 18000); Talk(SAY_AGGRO); } diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_hazzarah.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_hazzarah.cpp index 15228815d69..809403bb325 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_hazzarah.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_hazzarah.cpp @@ -121,4 +121,3 @@ void AddSC_boss_hazzarah() { new boss_hazzarah(); } - diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp index 7f19962e719..dc02c895327 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp @@ -271,7 +271,7 @@ class mob_batrider : public CreatureScript { if (instance) { - if (instance->GetData(DATA_JEKLIK) == DONE) + if (instance->GetBossState(DATA_JEKLIK) == DONE) { me->setDeathState(JUST_DIED); me->RemoveCorpse(); diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp index 258dda26c11..e402480609b 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp @@ -25,6 +25,9 @@ EndScriptData */ #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "Spell.h" +#include "SpellAuras.h" +#include "SpellScript.h" #include "zulgurub.h" enum Says @@ -32,23 +35,73 @@ enum Says SAY_AGGRO = 0, SAY_DING_KILL = 1, SAY_WATCH = 2, - SAY_WATCH_WHISPER = 3, // is this text for real? easter egg? + SAY_WATCH_WHISPER = 3, + SAY_OHGAN_DEAD = 4, SAY_GRATS_JINDO = 0, }; enum Spells { - SPELL_CHARGE = 24408, - SPELL_CLEAVE = 7160, + SPELL_CHARGE = 24408, // seen + SPELL_OVERPOWER = 24407, // Seen SPELL_FEAR = 29321, - SPELL_WHIRLWIND = 15589, - SPELL_MORTAL_STRIKE = 16856, - SPELL_ENRAGE = 24318, - SPELL_WATCH = 24314, - SPELL_LEVEL_UP = 24312, - SPELL_SWIFT_ORANGE_RAPTOR = 23243, - // Ohgans Spell - SPELL_SUNDERARMOR = 24317 + SPELL_WHIRLWIND = 13736, // Triggers 15589 + SPELL_MORTAL_STRIKE = 16856, // Seen + SPELL_FRENZY = 24318, // seen + SPELL_WATCH = 24314, // seen 24315, 24316 + SPELL_WATCH_CHARGE = 24315, // Triggers 24316 + SPELL_LEVEL_UP = 24312 // +}; + +enum Events +{ + EVENT_CHECK_SPEAKER = 1, + EVENT_CHECK_START = 2, + EVENT_STARTED = 3, + EVENT_OVERPOWER = 4, + EVENT_MORTAL_STRIKE = 5, + EVENT_WHIRLWIND = 6, + EVENT_CHECK_OHGAN = 7, + EVENT_WATCH_PLAYER = 8, + EVENT_CHARGE_PLAYER = 9 +}; + +enum Misc +{ + MODEL_OHGAN_MOUNT = 15271, + PATH_MANDOKIR = 492861, + POINT_MANDOKIR_END = 24, + CHAINED_SPIRT_COUNT = 20 +}; + +Position const PosSummonChainedSpirits[CHAINED_SPIRT_COUNT] = +{ + { -12167.17f, -1979.330f, 133.0992f, 2.268928f }, + { -12262.74f, -1953.394f, 133.5496f, 0.593412f }, + { -12176.89f, -1983.068f, 133.7841f, 2.129302f }, + { -12226.45f, -1977.933f, 132.7982f, 1.466077f }, + { -12204.74f, -1890.431f, 135.7569f, 4.415683f }, + { -12216.70f, -1891.806f, 136.3496f, 4.677482f }, + { -12236.19f, -1892.034f, 134.1041f, 5.044002f }, + { -12248.24f, -1893.424f, 134.1182f, 5.270895f }, + { -12257.36f, -1897.663f, 133.1484f, 5.462881f }, + { -12265.84f, -1903.077f, 133.1649f, 5.654867f }, + { -12158.69f, -1972.707f, 133.8751f, 2.408554f }, + { -12178.82f, -1891.974f, 134.1786f, 3.944444f }, + { -12193.36f, -1890.039f, 135.1441f, 4.188790f }, + { -12275.59f, -1932.845f, 134.9017f, 0.174533f }, + { -12273.51f, -1941.539f, 136.1262f, 0.314159f }, + { -12247.02f, -1963.497f, 133.9476f, 0.872665f }, + { -12238.68f, -1969.574f, 133.6273f, 1.134464f }, + { -12192.78f, -1982.116f, 132.6966f, 1.919862f }, + { -12210.81f, -1979.316f, 133.8700f, 1.797689f }, + { -12283.51f, -1924.839f, 133.5170f, 0.069813f } +}; + +Position const PosMandokir[2] = +{ + { -12167.8f, -1927.25f, 153.73f, 3.76991f }, + { -12197.86f, -1949.392f, 130.2745f, 0.0f } }; class boss_mandokir : public CreatureScript @@ -57,298 +110,319 @@ class boss_mandokir : public CreatureScript struct boss_mandokirAI : public BossAI { - boss_mandokirAI(Creature* creature) : BossAI(creature, DATA_MANDOKIR) {} - - uint32 KillCount; - uint32 Watch_Timer; - uint32 TargetInRange; - uint32 Cleave_Timer; - uint32 Whirlwind_Timer; - uint32 Fear_Timer; - uint32 MortalStrike_Timer; - uint32 Check_Timer; - float targetX; - float targetY; - float targetZ; - - InstanceScript* instance; - - bool endWatch; - bool someWatched; - bool RaptorDead; - bool CombatStart; - bool SpeakerDead; - - uint64 WatchTarget; + boss_mandokirAI(Creature* creature) : BossAI(creature, DATA_MANDOKIR) { } void Reset() { - KillCount = 0; - Watch_Timer = 33000; - Cleave_Timer = 7000; - Whirlwind_Timer = 20000; - Fear_Timer = 1000; - MortalStrike_Timer = 1000; - Check_Timer = 1000; - - targetX = 0.0f; - targetY = 0.0f; - targetZ = 0.0f; - TargetInRange = 0; - - WatchTarget = 0; - - someWatched = false; - endWatch = false; - RaptorDead = false; - CombatStart = false; - SpeakerDead = false; - - DoCast(me, 23243); + if (me->GetPositionZ() > 140.0f) + { + _Reset(); + killCount = 0; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC); + events.ScheduleEvent(EVENT_CHECK_START, 1000); + if (Creature* speaker = Creature::GetCreature(*me, instance->GetData64(NPC_VILEBRANCH_SPEAKER))) + if (!speaker->isAlive()) + speaker->Respawn(true); + } + summons.DespawnAll(); + me->Mount(MODEL_OHGAN_MOUNT); } void JustDied(Unit* /*killer*/) { - _JustDied(); + // Do not want to unsummon Ohgan + for (int i = 0; i < CHAINED_SPIRT_COUNT; ++i) + if (Creature* unsummon = Creature::GetCreature(*me, chainedSpirtGUIDs[i])) + unsummon->DespawnOrUnsummon(); + instance->SetBossState(DATA_MANDOKIR, DONE); + instance->SaveToDB(); } - void KilledUnit(Unit* victim) + void EnterCombat(Unit* /*who*/) { - if (victim->GetTypeId() == TYPEID_PLAYER) + _EnterCombat(); + events.ScheduleEvent(EVENT_OVERPOWER, urand(7000, 9000)); + events.ScheduleEvent(EVENT_MORTAL_STRIKE, urand(12000, 18000)); + events.ScheduleEvent(EVENT_WHIRLWIND, urand(24000, 30000)); + events.ScheduleEvent(EVENT_CHECK_OHGAN, 1000); + events.ScheduleEvent(EVENT_WATCH_PLAYER, urand(13000, 15000)); + events.ScheduleEvent(EVENT_CHARGE_PLAYER, urand(33000, 38000)); + me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation()); + Talk(SAY_AGGRO); + me->Dismount(); + // Summon Ohgan (Spell missing) TEMP HACK + me->SummonCreature(NPC_OHGAN, me->GetPositionX()-3, me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 35000); + // Summon Chained Spirits + for (int i = 0; i < CHAINED_SPIRT_COUNT; ++i) { - ++KillCount; - - if (KillCount == 3) - { - Talk(SAY_DING_KILL); - - if (instance) - { - uint64 JindoGUID = instance->GetData64(DATA_JINDO); - if (JindoGUID) - { - if (Creature* jTemp = Creature::GetCreature(*me, JindoGUID)) - { - if (jTemp->isAlive()) - jTemp->AI()->Talk(SAY_GRATS_JINDO); - } - } - } - DoCast(me, SPELL_LEVEL_UP, true); - KillCount = 0; - } + Creature* chainedSpirt = me->SummonCreature(NPC_CHAINED_SPIRT, PosSummonChainedSpirits[i], TEMPSUMMON_CORPSE_DESPAWN); + chainedSpirtGUIDs[i] = chainedSpirt->GetGUID(); } + DoZoneInCombat(); } - void EnterCombat(Unit* /*who*/) + void KilledUnit(Unit* victim) { - _EnterCombat(); - Talk(SAY_AGGRO); + if (victim->GetTypeId() != TYPEID_PLAYER) + return; + + if (++killCount == 3) + { + Talk(SAY_DING_KILL); + if (Creature* jindo = Creature::GetCreature(*me, instance->GetData64(DATA_JINDO))) + if (jindo->isAlive()) + jindo->AI()->Talk(SAY_GRATS_JINDO); + DoCast(me, SPELL_LEVEL_UP, true); + killCount = 0; + } } - void UpdateAI(const uint32 diff) + void MovementInform(uint32 type, uint32 id) { - if (!SpeakerDead) + if (type == WAYPOINT_MOTION_TYPE) { - if (!me->FindNearestCreature(NPC_SPEAKER, 100.0f, true)) + me->SetWalk(false); + if (id == POINT_MANDOKIR_END) { - me->GetMotionMaster()->MovePoint(0, -12196.3f, -1948.37f, 130.36f); - SpeakerDead = true; + me->SetHomePosition(PosMandokir[0]); + instance->SetBossState(DATA_MANDOKIR, NOT_STARTED); + me->DespawnOrUnsummon(6000); // No idea how to respawn on wipe. } } + } - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != POINT_MOTION_TYPE && SpeakerDead) - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + void UpdateAI(uint32 const diff) + { + events.Update(diff); if (!UpdateVictim()) - return; - - if (me->getVictim() && me->isAlive()) { - if (!CombatStart) + if (instance->GetBossState(DATA_MANDOKIR) == NOT_STARTED || instance->GetBossState(DATA_MANDOKIR) == SPECIAL) { - //At combat Start Mandokir is mounted so we must unmount it first - me->Dismount(); - - //And summon his raptor - me->SummonCreature(14988, me->getVictim()->GetPositionX(), me->getVictim()->GetPositionY(), me->getVictim()->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 35000); - CombatStart = true; - } - - if (Watch_Timer <= diff) //Every 20 Sec Mandokir will check this - { - if (WatchTarget) //If someone is watched and If the Position of the watched target is different from the one stored, or are attacking, mandokir will charge him + while (uint32 eventId = events.ExecuteEvent()) { - Unit* unit = Unit::GetUnit(*me, WatchTarget); - - if (unit && ( - targetX != unit->GetPositionX() || - targetY != unit->GetPositionY() || - targetZ != unit->GetPositionZ() || - unit->isInCombat())) + switch (eventId) { - if (me->IsWithinMeleeRange(unit)) - { - DoCast(unit, 24316); - } - else - { - DoCast(unit, SPELL_CHARGE); - //me->SendMonsterMove(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), 0, true, 1); - AttackStart(unit); - } + case EVENT_CHECK_START: + if (instance->GetBossState(DATA_MANDOKIR) == SPECIAL) + { + me->GetMotionMaster()->MovePoint(0, PosMandokir[1].m_positionX, PosMandokir[1].m_positionY, PosMandokir[1].m_positionZ); + events.ScheduleEvent(EVENT_STARTED, 6000); + } + else + events.ScheduleEvent(EVENT_CHECK_START, 1000); + break; + case EVENT_STARTED: + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC); + me->GetMotionMaster()->MovePath(PATH_MANDOKIR, false); + break; + default: + break; } } - someWatched = false; - Watch_Timer = 20000; - } else Watch_Timer -= diff; - - if ((Watch_Timer < 8000) && !someWatched) //8 sec(cast time + expire time) before the check for the watch effect mandokir will cast watch debuff on a random target - { - if (Unit* p = SelectTarget(SELECT_TARGET_RANDOM, 0)) - { - Talk(SAY_WATCH, p->GetGUID()); - DoCast(p, SPELL_WATCH); - WatchTarget = p->GetGUID(); - someWatched = true; - endWatch = true; - } } + return; + } - if ((Watch_Timer < 1000) && endWatch) //1 sec before the debuf expire, store the target position - { - Unit* unit = Unit::GetUnit(*me, WatchTarget); - if (unit) - { - targetX = unit->GetPositionX(); - targetY = unit->GetPositionY(); - targetZ = unit->GetPositionZ(); - } - endWatch = false; - } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - if (!someWatched) + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) { - //Cleave - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 7000; - } else Cleave_Timer -= diff; - - //Whirlwind - if (Whirlwind_Timer <= diff) - { + case EVENT_OVERPOWER: + DoCastVictim(SPELL_OVERPOWER, true); + events.ScheduleEvent(EVENT_OVERPOWER, urand(6000, 12000)); + break; + case EVENT_MORTAL_STRIKE: + if (me->getVictim() && me->getVictim()->HealthBelowPct(50)) + DoCastVictim(SPELL_MORTAL_STRIKE, true); + events.ScheduleEvent(EVENT_MORTAL_STRIKE, urand(12000, 18000)); + break; + case EVENT_WHIRLWIND: DoCast(me, SPELL_WHIRLWIND); - Whirlwind_Timer = 18000; - } else Whirlwind_Timer -= diff; - - //If more then 3 targets in melee range mandokir will cast fear - if (Fear_Timer <= diff) - { - TargetInRange = 0; - - std::list<HostileReference*>::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (; i != me->getThreatManager().getThreatList().end(); ++i) + events.ScheduleEvent(EVENT_WHIRLWIND, urand(22000, 26000)); + break; + case EVENT_CHECK_OHGAN: + if (instance->GetBossState(DATA_OHGAN) == DONE) { - Unit* unit = Unit::GetUnit(*me, (*i)->getUnitGuid()); - if (unit && me->IsWithinMeleeRange(unit)) - ++TargetInRange; + DoCast(me, SPELL_FRENZY); + Talk(SAY_OHGAN_DEAD); } - - if (TargetInRange > 3) - DoCast(me->getVictim(), SPELL_FEAR); - - Fear_Timer = 4000; - } else Fear_Timer -=diff; - - //Mortal Strike if target below 50% hp - if (me->getVictim() && me->getVictim()->HealthBelowPct(50)) - { - if (MortalStrike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); - MortalStrike_Timer = 15000; - } else MortalStrike_Timer -= diff; - } - } - //Checking if Ohgan is dead. If yes Mandokir will enrage. - if (Check_Timer <= diff) - { - if (instance) - { - if (instance->GetData(DATA_OHGAN) == DONE) + else + events.ScheduleEvent(EVENT_CHECK_OHGAN, 1000); + break; + case EVENT_WATCH_PLAYER: + if (Unit* player = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) { - if (!RaptorDead) - { - DoCast(me, SPELL_ENRAGE); - RaptorDead = true; - } + DoCast(player, SPELL_WATCH); + Talk(SAY_WATCH, player->GetGUID()); } - } - - Check_Timer = 1000; - } else Check_Timer -= diff; - - DoMeleeAttackIfReady(); + events.ScheduleEvent(EVENT_WATCH_PLAYER, urand(12000, 15000)); + break; + case EVENT_CHARGE_PLAYER: + DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 40, true), SPELL_CHARGE); + events.ScheduleEvent(EVENT_CHARGE_PLAYER, urand(22000, 30000)); + break; + default: + break; + } } + + DoMeleeAttackIfReady(); } + + private: + uint8 killCount; + uint64 chainedSpirtGUIDs[CHAINED_SPIRT_COUNT]; }; CreatureAI* GetAI(Creature* creature) const { - return new boss_mandokirAI(creature); + return GetZulGurubAI<boss_mandokirAI>(creature); } }; // Ohgan + +enum OhganSpells +{ + SPELL_SUNDERARMOR = 24317 +}; + class mob_ohgan : public CreatureScript { public: mob_ohgan() : CreatureScript("mob_ohgan") {} struct mob_ohganAI : public ScriptedAI { - mob_ohganAI(Creature* creature) : ScriptedAI(creature) + mob_ohganAI(Creature* creature) : ScriptedAI(creature), instance(creature->GetInstanceScript()) { } + + void Reset() { - instance = creature->GetInstanceScript(); + SunderArmor_Timer = 5000; } + void EnterCombat(Unit* /*who*/) {} + + void JustDied(Unit* /*killer*/) + { + instance->SetBossState(DATA_OHGAN, DONE); + } + + void UpdateAI(const uint32 diff) + { + // Return since we have no target + if (!UpdateVictim()) + return; + + if (SunderArmor_Timer <= diff) + { + DoCastVictim(SPELL_SUNDERARMOR, true); + SunderArmor_Timer = urand(10000, 15000); + } else SunderArmor_Timer -= diff; + + DoMeleeAttackIfReady(); + } + + private: uint32 SunderArmor_Timer; InstanceScript* instance; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetZulGurubAI<mob_ohganAI>(creature); + } +}; + +enum VilebranchSpells +{ + SPELL_DEMORALIZING_SHOUT = 13730, + SPELL_CLEAVE = 15284 +}; + +class mob_vilebranch_speaker : public CreatureScript +{ + public: mob_vilebranch_speaker() : CreatureScript("mob_vilebranch_speaker") {} + + struct mob_vilebranch_speakerAI : public ScriptedAI + { + mob_vilebranch_speakerAI(Creature* creature) : ScriptedAI(creature), instance(creature->GetInstanceScript()) { } void Reset() { - SunderArmor_Timer = 5000; + demoralizing_Shout_Timer = urand (2000, 4000); + cleave_Timer = urand (5000, 8000); } void EnterCombat(Unit* /*who*/) {} void JustDied(Unit* /*killer*/) { - if (instance) - instance->SetData(DATA_OHGAN, DONE); + instance->SetBossState(DATA_MANDOKIR, SPECIAL); } - void UpdateAI (const uint32 diff) + void UpdateAI(const uint32 diff) { - //Return since we have no target + // Return since we have no target if (!UpdateVictim()) return; - //SunderArmor_Timer - if (SunderArmor_Timer <= diff) + if (demoralizing_Shout_Timer <= diff) { - DoCast(me->getVictim(), SPELL_SUNDERARMOR); - SunderArmor_Timer = urand(10000, 15000); - } else SunderArmor_Timer -= diff; + DoCast(me, SPELL_DEMORALIZING_SHOUT); + demoralizing_Shout_Timer = urand(22000, 30000); + } else demoralizing_Shout_Timer -= diff; + + if (cleave_Timer <= diff) + { + DoCastVictim(SPELL_CLEAVE, true); + cleave_Timer = urand(6000, 9000); + } else cleave_Timer -= diff; DoMeleeAttackIfReady(); } + + private: + uint32 demoralizing_Shout_Timer; + uint32 cleave_Timer; + InstanceScript* instance; }; CreatureAI* GetAI(Creature* creature) const { - return new mob_ohganAI(creature); + return new mob_vilebranch_speakerAI(creature); + } +}; + +class spell_threatening_gaze : public SpellScriptLoader +{ + public: + spell_threatening_gaze() : SpellScriptLoader("spell_threatening_gaze") { } + + class spell_threatening_gaze_AuraScript : public AuraScript + { + PrepareAuraScript(spell_threatening_gaze_AuraScript); + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + if(Unit* target = GetTarget()) + if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE && GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_DEATH) + caster->CastSpell(target, SPELL_WATCH_CHARGE); + } + + void Register() + { + OnEffectRemove += AuraEffectRemoveFn(spell_threatening_gaze_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_threatening_gaze_AuraScript(); } }; @@ -356,5 +430,6 @@ void AddSC_boss_mandokir() { new boss_mandokir(); new mob_ohgan(); + new mob_vilebranch_speaker(); + new spell_threatening_gaze(); } - diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp index ab45162fc35..61eb695719a 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp @@ -113,7 +113,7 @@ class boss_thekal : public CreatureScript void JustReachedHome() { if (instance) - instance->SetData(DATA_THEKAL, NOT_STARTED); + instance->SetBossState(DATA_THEKAL, NOT_STARTED); } void UpdateAI(uint32 const diff) @@ -167,7 +167,7 @@ class boss_thekal : public CreatureScript { if (instance) { - if (instance->GetData(DATA_LORKHAN) == SPECIAL) + if (instance->GetBossState(DATA_LORKHAN) == SPECIAL) { //Resurrect LorKhan if (Unit* pLorKhan = Unit::GetUnit(*me, instance->GetData64(DATA_LORKHAN))) @@ -180,7 +180,7 @@ class boss_thekal : public CreatureScript } } - if (instance->GetData(DATA_ZATH) == SPECIAL) + if (instance->GetBossState(DATA_ZATH) == SPECIAL) { //Resurrect Zath if (Unit* pZath = Unit::GetUnit(*me, instance->GetData64(DATA_ZATH))) @@ -189,7 +189,7 @@ class boss_thekal : public CreatureScript pZath->setFaction(14); pZath->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); pZath->SetFullHealth(); - instance->SetData(DATA_ZATH, DONE); + instance->SetBossState(DATA_ZATH, DONE); } } } @@ -241,7 +241,7 @@ class boss_thekal : public CreatureScript me->SetStandState(UNIT_STAND_STATE_SLEEP); me->AttackStop(); if (instance) - instance->SetData(DATA_THEKAL, SPECIAL); + instance->SetBossState(DATA_THEKAL, SPECIAL); WasDead=true; } } @@ -288,7 +288,7 @@ class mob_zealot_lorkhan : public CreatureScript FakeDeath = false; if (instance) - instance->SetData(DATA_LORKHAN, NOT_STARTED); + instance->SetBossState(DATA_LORKHAN, NOT_STARTED); me->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); @@ -356,7 +356,7 @@ class mob_zealot_lorkhan : public CreatureScript { if (instance) { - if (instance->GetData(DATA_THEKAL) == SPECIAL) + if (instance->GetBossState(DATA_THEKAL) == SPECIAL) { //Resurrect Thekal if (Unit* pThekal = Unit::GetUnit(*me, instance->GetData64(DATA_THEKAL))) @@ -368,7 +368,7 @@ class mob_zealot_lorkhan : public CreatureScript } } - if (instance->GetData(DATA_ZATH) == SPECIAL) + if (instance->GetBossState(DATA_ZATH) == SPECIAL) { //Resurrect Zath if (Unit* pZath = Unit::GetUnit(*me, instance->GetData64(DATA_ZATH))) @@ -395,7 +395,7 @@ class mob_zealot_lorkhan : public CreatureScript me->AttackStop(); if (instance) - instance->SetData(DATA_LORKHAN, SPECIAL); + instance->SetBossState(DATA_LORKHAN, SPECIAL); FakeDeath = true; } @@ -450,7 +450,7 @@ class mob_zealot_zath : public CreatureScript FakeDeath = false; if (instance) - instance->SetData(DATA_ZATH, NOT_STARTED); + instance->SetBossState(DATA_ZATH, NOT_STARTED); me->SetStandState(UNIT_STAND_STATE_STAND); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); @@ -509,7 +509,7 @@ class mob_zealot_zath : public CreatureScript { if (instance) { - if (instance->GetData(DATA_LORKHAN) == SPECIAL) + if (instance->GetBossState(DATA_LORKHAN) == SPECIAL) { //Resurrect LorKhan if (Unit* pLorKhan = Unit::GetUnit(*me, instance->GetData64(DATA_LORKHAN))) @@ -521,7 +521,7 @@ class mob_zealot_zath : public CreatureScript } } - if (instance->GetData(DATA_THEKAL) == SPECIAL) + if (instance->GetBossState(DATA_THEKAL) == SPECIAL) { //Resurrect Thekal if (Unit* pThekal = Unit::GetUnit(*me, instance->GetData64(DATA_THEKAL))) @@ -548,7 +548,7 @@ class mob_zealot_zath : public CreatureScript me->AttackStop(); if (instance) - instance->SetData(DATA_ZATH, SPECIAL); + instance->SetBossState(DATA_ZATH, SPECIAL); FakeDeath = true; } diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp index b997d277c95..01c5ef998f5 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp @@ -29,7 +29,7 @@ EndScriptData */ class instance_zulgurub : public InstanceMapScript { - public: instance_zulgurub(): InstanceMapScript("instance_zulgurub", 309) {} + public: instance_zulgurub(): InstanceMapScript(ZGScriptName, 309) {} struct instance_zulgurub_InstanceMapScript : public InstanceScript { @@ -38,24 +38,21 @@ class instance_zulgurub : public InstanceMapScript SetBossNumber(EncounterCount); } - //If all High Priest bosses were killed. Lorkhan, Zath and Ohgan are added too. - //Storing Lorkhan, Zath and Thekal because we need to cast on them later. Jindo is needed for healfunction too. - uint64 LorKhanGUID; - uint64 ZathGUID; - uint64 ThekalGUID; - uint64 JindoGUID; - void Initialize() { - LorKhanGUID = 0; - ZathGUID = 0; - ThekalGUID = 0; - JindoGUID = 0; + _zealotLorkhanGUID = 0; + _zealotZathGUID = 0; + _highPriestTekalGUID = 0; + _jindoTheHexxerGUID = 0; + _vilebranchSpeakerGUID = 0; + _arlokkGUID = 0; + _goForcefieldGUID = 0; + _goGongOfBethekkGUID = 0; } bool IsEncounterInProgress() const { - //not active in Zul'Gurub + // not active in Zul'Gurub return false; } @@ -63,78 +60,71 @@ class instance_zulgurub : public InstanceMapScript { switch (creature->GetEntry()) { - case NPC_ZEALOT_LORKHAN: LorKhanGUID = creature->GetGUID(); break; - case NPC_ZEALOT_ZATH: ZathGUID = creature->GetGUID(); break; - case NPC_HIGH_PRIEST_THEKAL: ThekalGUID = creature->GetGUID(); break; - case NPC_JINDO_THE_HEXXER: JindoGUID = creature->GetGUID(); break; - } - } - - bool SetBossState(uint32 type, EncounterState state) - { - if (!InstanceScript::SetBossState(type, state)) - return false; - - switch (type) - { - case DATA_JEKLIK: - case DATA_VENOXIS: - case DATA_MARLI: - case DATA_ARLOKK: - case DATA_HAKKAR: - case DATA_MANDOKIR: - case DATA_JINDO: - case DATA_GAHZRANKA: - case DATA_EDGE_OF_MADNESS: - case DATA_THEKAL: - case DATA_LORKHAN: - case DATA_ZATH: - case DATA_OHGAN: + case NPC_ZEALOT_LORKHAN: + _zealotLorkhanGUID = creature->GetGUID(); break; - default: + case NPC_ZEALOT_ZATH: + _zealotZathGUID = creature->GetGUID(); + break; + case NPC_HIGH_PRIEST_THEKAL: + _highPriestTekalGUID = creature->GetGUID(); + break; + case NPC_JINDO_THE_HEXXER: + _jindoTheHexxerGUID = creature->GetGUID(); + break; + case NPC_VILEBRANCH_SPEAKER: + _vilebranchSpeakerGUID = creature->GetGUID(); + break; + case NPC_ARLOKK: + _arlokkGUID = creature->GetGUID(); break; } - - return true; } - uint32 GetData(uint32 type) const - { - switch (type) + void OnGameObjectCreate(GameObject* go) { - case DATA_JEKLIK: return GetBossState(DATA_JEKLIK); - case DATA_VENOXIS: return GetBossState(DATA_VENOXIS); - case DATA_MARLI: return GetBossState(DATA_MARLI); - case DATA_ARLOKK: return GetBossState(DATA_ARLOKK); - case DATA_HAKKAR: return GetBossState(DATA_HAKKAR); - case DATA_MANDOKIR: return GetBossState(DATA_MANDOKIR); - case DATA_JINDO: return GetBossState(DATA_JINDO); - case DATA_GAHZRANKA: return GetBossState(DATA_GAHZRANKA); - case DATA_EDGE_OF_MADNESS: return GetBossState(DATA_EDGE_OF_MADNESS); - case DATA_THEKAL: return GetBossState(DATA_THEKAL); - case DATA_LORKHAN: return GetBossState(DATA_LORKHAN); - case DATA_ZATH: return GetBossState(DATA_ZATH); - case DATA_OHGAN: return GetBossState(DATA_OHGAN); + switch (go->GetEntry()) + { + case GO_FORCEFIELD: + _goForcefieldGUID = go->GetGUID(); + break; + case GO_GONG_OF_BETHEKK: + _goGongOfBethekkGUID = go->GetGUID(); + if (GetBossState(DATA_ARLOKK) == DONE) + go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + else + go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); break; default: break; + } } - return 0; - } - uint64 GetData64(uint32 uiData) const { switch (uiData) { case DATA_LORKHAN: - return LorKhanGUID; + return _zealotLorkhanGUID; + break; case DATA_ZATH: - return ZathGUID; + return _zealotZathGUID; + break; case DATA_THEKAL: - return ThekalGUID; + return _highPriestTekalGUID; + break; case DATA_JINDO: - return JindoGUID; + return _jindoTheHexxerGUID; + break; + case NPC_ARLOKK: + return _arlokkGUID; + break; + case GO_FORCEFIELD: + return _goForcefieldGUID; + break; + case GO_GONG_OF_BETHEKK: + return _goGongOfBethekkGUID; + break; } return 0; } @@ -181,6 +171,18 @@ class instance_zulgurub : public InstanceMapScript OUT_LOAD_INST_DATA_COMPLETE; } + private: + //If all High Priest bosses were killed. Lorkhan, Zath and Ohgan are added too. + //Storing Lorkhan, Zath and Thekal because we need to cast on them later. Jindo is needed for healfunction too. + + uint64 _zealotLorkhanGUID; + uint64 _zealotZathGUID; + uint64 _highPriestTekalGUID; + uint64 _jindoTheHexxerGUID; + uint64 _vilebranchSpeakerGUID; + uint64 _arlokkGUID; + uint64 _goForcefieldGUID; + uint64 _goGongOfBethekkGUID; }; InstanceScript* GetInstanceScript(InstanceMap* map) const diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h b/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h index 2544e4f4d5f..77767153a96 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h +++ b/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h @@ -20,6 +20,8 @@ uint32 const EncounterCount = 13; +#define ZGScriptName "instance_zulgurub" + enum DataTypes { DATA_JEKLIK = 0, // Main boss @@ -34,20 +36,43 @@ enum DataTypes DATA_EDGE_OF_MADNESS = 9, // Optional Event Edge of Madness - one of: Gri'lek, Renataki, Hazza'rah, or Wushoolay DATA_LORKHAN = 10, // Zealot Lor'Khan add to High priest Thekal! DATA_ZATH = 11, // Zealot Zath add to High priest Thekal! - DATA_OHGAN = 12 // Bloodlord Mandokir's raptor mount + DATA_OHGAN = 12, // Bloodlord Mandokir's raptor mount + TYPE_EDGE_OF_MADNESS = 13 // Boss storage }; enum CreatureIds { + NPC_ARLOKK = 14515, // Arlokk Event + NPC_PANTHER_TRIGGER = 15091, // Arlokk Event + NPC_ZULIAN_PROWLER = 15101, // Arlokk Event NPC_ZEALOT_LORKHAN = 11347, NPC_ZEALOT_ZATH = 11348, NPC_HIGH_PRIEST_THEKAL = 14509, NPC_JINDO_THE_HEXXER = 11380, NPC_NIGHTMARE_ILLUSION = 15163, - NPC_ZULIAN_PROWLER = 15101, - NPC_SPEAKER = 11391, NPC_SHADE_OF_JINDO = 14986, - NPC_SACRIFICED_TROLL = 14826 + NPC_SACRIFICED_TROLL = 14826, + NPC_MANDOKIR = 11382, // Mandokir Event + NPC_OHGAN = 14988, // Mandokir Event + NPC_VILEBRANCH_SPEAKER = 11391, // Mandokir Event + NPC_CHAINED_SPIRT = 15117 // Mandokir Event + }; +enum GameobjectIds +{ + GO_FORCEFIELD = 180497, // Arlokk Event + GO_GONG_OF_BETHEKK = 180526 // Arlokk Event +}; + +template<class AI> +CreatureAI* GetZulGurubAI(Creature* creature) +{ + if (InstanceMap* instance = creature->GetMap()->ToInstanceMap()) + if (instance->GetInstanceScript()) + if (instance->GetScriptId() == sObjectMgr->GetScriptId(ZGScriptName)) + return new AI(creature); + return NULL; +} + #endif diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp index 7f8108e5e71..6039e01b901 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp @@ -359,7 +359,7 @@ class boss_halion : public CreatureScript if (Creature* twilightHalion = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_TWILIGHT_HALION))) if (twilightHalion->isAlive()) twilightHalion->Kill(twilightHalion); - + if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_HALION_CONTROLLER))) if (controller->isAlive()) controller->Kill(controller); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp index c8caa3976e4..ab0c44aa6d0 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp @@ -46,6 +46,7 @@ enum Spells SPELL_FRENZIED_BLOODTHIRST_VISUAL = 71949, SPELL_VAMPIRIC_BITE = 71726, SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_PLR = 70879, + SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_HEAL = 70872, SPELL_FRENZIED_BLOODTHIRST = 70877, SPELL_UNCONTROLLABLE_FRENZY = 70923, SPELL_PRESENCE_OF_THE_DARKFALLEN = 71952, @@ -698,6 +699,42 @@ class spell_blood_queen_bloodbolt : public SpellScriptLoader } }; +// 70871 - Essence of the Blood Queen +class spell_blood_queen_essence_of_the_blood_queen : public SpellScriptLoader +{ + public: + spell_blood_queen_essence_of_the_blood_queen() : SpellScriptLoader("spell_blood_queen_essence_of_the_blood_queen") { } + + class spell_blood_queen_essence_of_the_blood_queen_AuraScript : public AuraScript + { + PrepareAuraScript(spell_blood_queen_essence_of_the_blood_queen_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_HEAL)) + return false; + return true; + } + + void OnProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + int32 heal = CalculatePct(int32(eventInfo.GetDamageInfo()->GetDamage()), aurEff->GetAmount()); + GetTarget()->CastCustomSpell(SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_HEAL, SPELLVALUE_BASE_POINT0, heal, GetTarget(), TRIGGERED_FULL_MASK, NULL, aurEff); + } + + void Register() + { + OnEffectProc += AuraEffectProcFn(spell_blood_queen_essence_of_the_blood_queen_AuraScript::OnProc, EFFECT_1, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_blood_queen_essence_of_the_blood_queen_AuraScript(); + } +}; + class spell_blood_queen_pact_of_the_darkfallen : public SpellScriptLoader { public: @@ -849,6 +886,7 @@ void AddSC_boss_blood_queen_lana_thel() new spell_blood_queen_vampiric_bite(); new spell_blood_queen_frenzied_bloodthirst(); new spell_blood_queen_bloodbolt(); + new spell_blood_queen_essence_of_the_blood_queen(); new spell_blood_queen_pact_of_the_darkfallen(); new spell_blood_queen_pact_of_the_darkfallen_dmg(); new spell_blood_queen_pact_of_the_darkfallen_dmg_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 452d09cf65f..3bd313fa148 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -145,6 +145,7 @@ enum Spells SPELL_RESTORE_SOUL = 72595, SPELL_RESTORE_SOULS = 73650, // Heroic SPELL_DARK_HUNGER = 69383, // Passive proc healing + SPELL_DARK_HUNGER_HEAL = 69384, SPELL_DESTROY_SOUL = 74086, // Used when Terenas Menethil dies SPELL_SOUL_RIP = 69397, // Deals increasing damage SPELL_SOUL_RIP_DAMAGE = 69398, @@ -3008,6 +3009,41 @@ class spell_the_lich_king_restore_soul : public SpellScriptLoader } }; +class spell_the_lich_king_dark_hunger : public SpellScriptLoader +{ + public: + spell_the_lich_king_dark_hunger() : SpellScriptLoader("spell_the_lich_king_dark_hunger") { } + + class spell_the_lich_king_dark_hunger_AuraScript : public AuraScript + { + PrepareAuraScript(spell_the_lich_king_dark_hunger_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_DARK_HUNGER_HEAL)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + int32 heal = int32(eventInfo.GetDamageInfo()->GetDamage() / 2); + GetTarget()->CastCustomSpell(SPELL_DARK_HUNGER_HEAL, SPELLVALUE_BASE_POINT0, heal, GetTarget(), true, NULL, aurEff); + } + + void Register() + { + OnEffectProc += AuraEffectProcFn(spell_the_lich_king_dark_hunger_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_the_lich_king_dark_hunger_AuraScript(); + } +}; + class spell_the_lich_king_in_frostmourne_room : public SpellScriptLoader { public: @@ -3253,6 +3289,7 @@ void AddSC_boss_the_lich_king() new spell_the_lich_king_lights_favor(); new spell_the_lich_king_soul_rip(); new spell_the_lich_king_restore_soul(); + new spell_the_lich_king_dark_hunger(); new spell_the_lich_king_in_frostmourne_room(); new spell_the_lich_king_summon_spirit_bomb(); new spell_the_lich_king_trigger_vile_spirit(); 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 1f96848fa0a..13a4fe23690 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 @@ -343,7 +343,7 @@ class boss_algalon_the_observer : public CreatureScript DoCast(me, SPELL_RIDE_THE_LIGHTNING, true); me->GetMotionMaster()->MovePoint(POINT_ALGALON_LAND, AlgalonLandPos); me->SetHomePosition(AlgalonLandPos); - Movement::MoveSplineInit init(*me); + Movement::MoveSplineInit init(me); init.MoveTo(AlgalonLandPos.GetPositionX(), AlgalonLandPos.GetPositionY(), AlgalonLandPos.GetPositionZ()); init.SetOrientationFixed(true); init.Launch(); diff --git a/src/server/scripts/Northrend/zone_sholazar_basin.cpp b/src/server/scripts/Northrend/zone_sholazar_basin.cpp index f3afc03e68a..7db2ae4707b 100644 --- a/src/server/scripts/Northrend/zone_sholazar_basin.cpp +++ b/src/server/scripts/Northrend/zone_sholazar_basin.cpp @@ -1033,6 +1033,102 @@ public: } }; +/*###### +## Quest: Reconnaissance Flight (12671) +######*/ +enum ReconnaissanceFlight +{ + NPC_PLANE = 28710, // Vic's Flying Machine + NPC_PILOT = 28646, + + VIC_SAY_0 = 0, + VIC_SAY_1 = 1, + VIC_SAY_2 = 2, + VIC_SAY_3 = 3, + VIC_SAY_4 = 4, + VIC_SAY_5 = 5, + VIC_SAY_6 = 6, + PLANE_EMOTE = 0, + + AURA_ENGINE = 52255, // Engine on Fire + + SPELL_LAND = 52226, // Land Flying Machine + SPELL_CREDIT = 53328 // Land Flying Machine Credit +}; + +class npc_vics_flying_machine : public CreatureScript +{ +public: + npc_vics_flying_machine() : CreatureScript("npc_vics_flying_machine") { } + + struct npc_vics_flying_machineAI : public VehicleAI + { + npc_vics_flying_machineAI(Creature* creature) : VehicleAI(creature) {} + + void PassengerBoarded(Unit* passenger, int8 /*seatId*/, bool apply) + { + if (apply && passenger->GetTypeId() == TYPEID_PLAYER) + me->GetMotionMaster()->MovePath(NPC_PLANE, false); + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != WAYPOINT_MOTION_TYPE) + return; + + if (Creature* pilot = GetClosestCreatureWithEntry(me, NPC_PILOT, 10)) + switch (id) + { + case 5: + pilot->AI()->Talk(VIC_SAY_0); + break; + case 11: + pilot->AI()->Talk(VIC_SAY_1); + break; + case 12: + pilot->AI()->Talk(VIC_SAY_2); + break; + case 14: + pilot->AI()->Talk(VIC_SAY_3); + break; + case 15: + pilot->AI()->Talk(VIC_SAY_4); + break; + case 17: + pilot->AI()->Talk(VIC_SAY_5); + break; + case 21: + pilot->AI()->Talk(VIC_SAY_6); + break; + case 25: + me->AI()->Talk(PLANE_EMOTE); + me->AI()->DoCast(AURA_ENGINE); + break; + } + } + + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) + { + if (spell->Id == SPELL_LAND) + { + Unit* passenger = me->GetVehicleKit()->GetPassenger(1); // player should be on seat 1 + if (passenger && passenger->GetTypeId() == TYPEID_PLAYER) + { + passenger->CastSpell(passenger, SPELL_CREDIT, true); + passenger->ExitVehicle(); + } + } + } + + void UpdateAI(const uint32 /*diff*/) {} + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_vics_flying_machineAI(creature); + } +}; + void AddSC_sholazar_basin() { new npc_injured_rainspeaker_oracle(); @@ -1045,4 +1141,5 @@ void AddSC_sholazar_basin() new spell_q12620_the_lifewarden_wrath(); new spell_q12589_shoot_rjr(); new npc_haiphoon(); + new npc_vics_flying_machine(); } diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index 060db02d53c..73c34d42538 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -31,12 +31,14 @@ enum DeathKnightSpells SPELL_DK_ANTI_MAGIC_SHELL_TALENT = 51052, SPELL_DK_BLACK_ICE_R1 = 49140, SPELL_DK_BLOOD_BOIL_TRIGGERED = 65658, + SPELL_DK_BLOOD_GORGED_HEAL = 50454, SPELL_DK_CORPSE_EXPLOSION_TRIGGERED = 43999, SPELL_DK_CORPSE_EXPLOSION_VISUAL = 51270, SPELL_DK_DEATH_COIL_DAMAGE = 47632, SPELL_DK_DEATH_COIL_HEAL = 47633, SPELL_DK_DEATH_STRIKE_HEAL = 45470, SPELL_DK_GHOUL_EXPLODE = 47496, + SPELL_DK_GLYPH_OF_ICEBOUND_FORTITUDE = 58625, SPELL_DK_RUNIC_POWER_ENERGIZE = 49088, SPELL_DK_SCOURGE_STRIKE_TRIGGERED = 70890, SPELL_DK_WILL_OF_THE_NECROPOLIS_TALENT_R1 = 49189, @@ -251,6 +253,58 @@ class spell_dk_blood_boil : public SpellScriptLoader } }; +// 50453 - Bloodworms Health Leech +class spell_dk_blood_gorged : public SpellScriptLoader +{ + public: + spell_dk_blood_gorged() : SpellScriptLoader("spell_dk_blood_gorged") { } + + class spell_dk_blood_gorged_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dk_blood_gorged_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_DK_BLOOD_GORGED_HEAL)) + return false; + return true; + } + + bool Load() + { + _procTarget = NULL; + return true; + } + + bool CheckProc(ProcEventInfo& /*eventInfo*/) + { + _procTarget = GetTarget()->GetOwner(); + return _procTarget; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + int32 bp = int32(eventInfo.GetDamageInfo()->GetDamage() * 1.5f); + GetTarget()->CastCustomSpell(SPELL_DK_BLOOD_GORGED_HEAL, SPELLVALUE_BASE_POINT0, bp, _procTarget, true, NULL, aurEff); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_dk_blood_gorged_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_dk_blood_gorged_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + + private: + Unit* _procTarget; + }; + + AuraScript* GetAuraScript() const + { + return new spell_dk_blood_gorged_AuraScript(); + } +}; + // 49158 - Corpse Explosion (51325, 51326, 51327, 51328) class spell_dk_corpse_explosion : public SpellScriptLoader { @@ -584,6 +638,55 @@ class spell_dk_ghoul_explode : public SpellScriptLoader } }; +// 48792 - Icebound Fortitude +class spell_dk_icebound_fortitude : public SpellScriptLoader +{ + public: + spell_dk_icebound_fortitude() : SpellScriptLoader("spell_dk_icebound_fortitude") { } + + class spell_dk_icebound_fortitude_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dk_icebound_fortitude_AuraScript); + + bool Load() + { + Unit* caster = GetCaster(); + return caster && caster->GetTypeId() == TYPEID_PLAYER; + } + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* caster = GetCaster()) + { + int32 value = amount; + uint32 defValue = uint32(caster->ToPlayer()->GetSkillValue(SKILL_DEFENSE) + caster->ToPlayer()->GetRatingBonusValue(CR_DEFENSE_SKILL)); + + if (defValue > 400) + value -= int32((defValue - 400) * 0.15); + + // Glyph of Icebound Fortitude + if (AuraEffect const* aurEff = caster->GetAuraEffect(SPELL_DK_GLYPH_OF_ICEBOUND_FORTITUDE, EFFECT_0)) + { + int32 valMax = -aurEff->GetAmount(); + if (value > valMax) + value = valMax; + } + amount = value; + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_icebound_fortitude_AuraScript::CalculateAmount, EFFECT_2, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dk_icebound_fortitude_AuraScript(); + } +}; + // 50365, 50371 - Improved Blood Presence class spell_dk_improved_blood_presence : public SpellScriptLoader { @@ -677,6 +780,33 @@ class spell_dk_improved_unholy_presence : public SpellScriptLoader } }; +// 59754 Rune Tap - Party +class spell_dk_rune_tap_party : public SpellScriptLoader +{ + public: + spell_dk_rune_tap_party() : SpellScriptLoader("spell_dk_rune_tap_party") { } + + class spell_dk_rune_tap_party_SpellScript : public SpellScript + { + PrepareSpellScript(spell_dk_rune_tap_party_SpellScript); + + void CheckTargets(std::list<WorldObject*>& targets) + { + targets.remove(GetCaster()); + } + + void Register() + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dk_rune_tap_party_SpellScript::CheckTargets, EFFECT_0, TARGET_UNIT_CASTER_AREA_PARTY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_dk_rune_tap_party_SpellScript(); + } +}; + // 55090 - Scourge Strike (55265, 55270, 55271) class spell_dk_scourge_strike : public SpellScriptLoader { @@ -784,6 +914,33 @@ class spell_dk_spell_deflection : public SpellScriptLoader } }; +// 55233 - Vampiric Blood +class spell_dk_vampiric_blood : public SpellScriptLoader +{ + public: + spell_dk_vampiric_blood() : SpellScriptLoader("spell_dk_vampiric_blood") { } + + class spell_dk_vampiric_blood_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dk_vampiric_blood_AuraScript); + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + amount = GetUnitOwner()->CountPctFromMaxHealth(amount); + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_vampiric_blood_AuraScript::CalculateAmount, EFFECT_1, SPELL_AURA_MOD_INCREASE_HEALTH); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dk_vampiric_blood_AuraScript(); + } +}; + // 52284 - Will of the Necropolis class spell_dk_will_of_the_necropolis : public SpellScriptLoader { @@ -854,6 +1011,7 @@ void AddSC_deathknight_spell_scripts() new spell_dk_anti_magic_shell_self(); new spell_dk_anti_magic_zone(); new spell_dk_blood_boil(); + new spell_dk_blood_gorged(); new spell_dk_corpse_explosion(); new spell_dk_death_coil(); new spell_dk_death_gate(); @@ -861,9 +1019,12 @@ void AddSC_deathknight_spell_scripts() new spell_dk_death_pact(); new spell_dk_death_strike(); new spell_dk_ghoul_explode(); + new spell_dk_icebound_fortitude(); new spell_dk_improved_blood_presence(); new spell_dk_improved_unholy_presence(); + new spell_dk_rune_tap_party(); new spell_dk_scourge_strike(); new spell_dk_spell_deflection(); + new spell_dk_vampiric_blood(); new spell_dk_will_of_the_necropolis(); } diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp index 6dd453597de..160f14ff670 100644 --- a/src/server/scripts/Spells/spell_druid.cpp +++ b/src/server/scripts/Spells/spell_druid.cpp @@ -30,10 +30,15 @@ enum DruidSpells { SPELL_DRUID_ENRAGE_MOD_DAMAGE = 51185, + SPELL_DRUID_GLYPH_OF_TYPHOON = 62135, + SPELL_DRUID_IDOL_OF_FERAL_SHADOWS = 34241, + SPELL_DRUID_IDOL_OF_WORSHIP = 60774, SPELL_DRUID_INCREASED_MOONFIRE_DURATION = 38414, SPELL_DRUID_KING_OF_THE_JUNGLE = 48492, SPELL_DRUID_LIFEBLOOM_ENERGIZE = 64372, SPELL_DRUID_LIFEBLOOM_FINAL_HEAL = 33778, + SPELL_DRUID_LIVING_SEED_HEAL = 48503, + SPELL_DRUID_LIVING_SEED_PROC = 48504, SPELL_DRUID_NATURES_SPLENDOR = 57865, SPELL_DRUID_SURVIVAL_INSTINCTS = 50322, SPELL_DRUID_SAVAGE_ROAR = 62071, @@ -41,6 +46,35 @@ enum DruidSpells SPELL_DRUID_ITEM_T8_BALANCE_RELIC = 64950, }; +// -1850 - Dash +class spell_dru_dash : public SpellScriptLoader +{ + public: + spell_dru_dash() : SpellScriptLoader("spell_dru_dash") { } + + class spell_dru_dash_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_dash_AuraScript); + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + // do not set speed if not in cat form + if (GetUnitOwner()->GetShapeshiftForm() != FORM_CAT) + amount = 0; + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dru_dash_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_MOD_INCREASE_SPEED); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dru_dash_AuraScript(); + } +}; + // -5229 - Enrage class spell_dru_enrage : public SpellScriptLoader { @@ -121,6 +155,69 @@ class spell_dru_glyph_of_starfire : public SpellScriptLoader } }; +// 34246 - Idol of the Emerald Queen +// 60779 - Idol of Lush Moss +class spell_dru_idol_lifebloom : public SpellScriptLoader +{ + public: + spell_dru_idol_lifebloom() : SpellScriptLoader("spell_dru_idol_lifebloom") { } + + class spell_dru_idol_lifebloom_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_idol_lifebloom_AuraScript); + + void HandleEffectCalcSpellMod(AuraEffect const* aurEff, SpellModifier*& spellMod) + { + if (!spellMod) + { + spellMod = new SpellModifier(GetAura()); + spellMod->op = SPELLMOD_DOT; + spellMod->type = SPELLMOD_FLAT; + spellMod->spellId = GetId(); + spellMod->mask = GetSpellInfo()->Effects[aurEff->GetEffIndex()].SpellClassMask; + } + spellMod->value = aurEff->GetAmount() / 7; + } + + void Register() + { + DoEffectCalcSpellMod += AuraEffectCalcSpellModFn(spell_dru_idol_lifebloom_AuraScript::HandleEffectCalcSpellMod, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dru_idol_lifebloom_AuraScript(); + } +}; + +// 29166 - Innervate +class spell_dru_innervate : public SpellScriptLoader +{ + public: + spell_dru_innervate() : SpellScriptLoader("spell_dru_innervate") { } + + class spell_dru_innervate_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_innervate_AuraScript); + + void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + amount = CalculatePct(int32(GetUnitOwner()->GetCreatePowers(POWER_MANA) / aurEff->GetTotalTicks()), amount); + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dru_innervate_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_ENERGIZE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dru_innervate_AuraScript(); + } +}; + // -5570 - Insect Swarm class spell_dru_insect_swarm : public SpellScriptLoader { @@ -232,6 +329,77 @@ class spell_dru_lifebloom : public SpellScriptLoader } }; +// -48496 - Living Seed +class spell_dru_living_seed : public SpellScriptLoader +{ + public: + spell_dru_living_seed() : SpellScriptLoader("spell_dru_living_seed") { } + + class spell_dru_living_seed_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_living_seed_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_DRUID_LIVING_SEED_PROC)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + int32 amount = CalculatePct(eventInfo.GetHealInfo()->GetHeal(), aurEff->GetAmount()); + GetTarget()->CastCustomSpell(SPELL_DRUID_LIVING_SEED_PROC, SPELLVALUE_BASE_POINT0, amount, eventInfo.GetProcTarget(), true, NULL, aurEff); + } + + void Register() + { + OnEffectProc += AuraEffectProcFn(spell_dru_living_seed_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dru_living_seed_AuraScript(); + } +}; + +// 48504 - Living Seed (Proc) +class spell_dru_living_seed_proc : public SpellScriptLoader +{ + public: + spell_dru_living_seed_proc() : SpellScriptLoader("spell_dru_living_seed_proc") { } + + class spell_dru_living_seed_proc_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_living_seed_proc_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_DRUID_LIVING_SEED_HEAL)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + GetTarget()->CastCustomSpell(SPELL_DRUID_LIVING_SEED_HEAL, SPELLVALUE_BASE_POINT0, aurEff->GetAmount(), GetTarget(), true, NULL, aurEff); + } + + void Register() + { + OnEffectProc += AuraEffectProcFn(spell_dru_living_seed_proc_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dru_living_seed_proc_AuraScript(); + } +}; + // 69366 - Moonkin Form passive class spell_dru_moonkin_form_passive : public SpellScriptLoader { @@ -276,6 +444,33 @@ class spell_dru_moonkin_form_passive : public SpellScriptLoader } }; +// 48391 - Owlkin Frenzy +class spell_dru_owlkin_frenzy : public SpellScriptLoader +{ + public: + spell_dru_owlkin_frenzy() : SpellScriptLoader("spell_dru_owlkin_frenzy") { } + + class spell_dru_owlkin_frenzy_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_owlkin_frenzy_AuraScript); + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + amount = CalculatePct(GetUnitOwner()->GetCreatePowers(POWER_MANA), amount); + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dru_owlkin_frenzy_AuraScript::CalculateAmount, EFFECT_2, SPELL_AURA_PERIODIC_ENERGIZE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dru_owlkin_frenzy_AuraScript(); + } +}; + // -16972 - Predatory Strikes class spell_dru_predatory_strikes : public SpellScriptLoader { @@ -349,6 +544,54 @@ class spell_dru_primal_tenacity : public SpellScriptLoader } }; +// -1079 - Rip +class spell_dru_rip : public SpellScriptLoader +{ + public: + spell_dru_rip() : SpellScriptLoader("spell_dru_rip") { } + + class spell_dru_rip_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_rip_AuraScript); + + bool Load() + { + Unit* caster = GetCaster(); + return caster && caster->GetTypeId() == TYPEID_PLAYER; + } + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated) + { + canBeRecalculated = false; + + if (Unit* caster = GetCaster()) + { + // 0.01 * $AP * cp + uint8 cp = caster->ToPlayer()->GetComboPoints(); + + // Idol of Feral Shadows. Can't be handled as SpellMod due its dependency from CPs + if (AuraEffect const* idol = caster->GetAuraEffect(SPELL_DRUID_IDOL_OF_FERAL_SHADOWS, EFFECT_0)) + amount += cp * idol->GetAmount(); + // Idol of Worship. Can't be handled as SpellMod due its dependency from CPs + else if (AuraEffect const* idol = caster->GetAuraEffect(SPELL_DRUID_IDOL_OF_WORSHIP, EFFECT_0)) + amount += cp * idol->GetAmount(); + + amount += int32(CalculatePct(caster->GetTotalAttackPowerValue(BASE_ATTACK), cp)); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dru_rip_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dru_rip_AuraScript(); + } +}; + // 62606 - Savage Defense class spell_dru_savage_defense : public SpellScriptLoader { @@ -658,6 +901,35 @@ class spell_dru_tiger_s_fury : public SpellScriptLoader } }; +// -61391 - Typhoon +class spell_dru_typhoon : public SpellScriptLoader +{ + public: + spell_dru_typhoon() : SpellScriptLoader("spell_dru_typhoon") { } + + class spell_dru_typhoon_SpellScript : public SpellScript + { + PrepareSpellScript(spell_dru_typhoon_SpellScript); + + void HandleKnockBack(SpellEffIndex effIndex) + { + // Glyph of Typhoon + if (GetCaster()->HasAura(SPELL_DRUID_GLYPH_OF_TYPHOON)) + PreventHitDefaultEffect(effIndex); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_dru_typhoon_SpellScript::HandleKnockBack, EFFECT_0, SPELL_EFFECT_KNOCK_BACK); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_dru_typhoon_SpellScript(); + } +}; + // 70691 - Item T10 Restoration 4P Bonus class spell_dru_t10_restoration_4p_bonus : public SpellScriptLoader { @@ -715,13 +987,20 @@ class spell_dru_t10_restoration_4p_bonus : public SpellScriptLoader void AddSC_druid_spell_scripts() { + new spell_dru_dash(); new spell_dru_enrage(); new spell_dru_glyph_of_starfire(); + new spell_dru_idol_lifebloom(); + new spell_dru_innervate(); new spell_dru_insect_swarm(); new spell_dru_lifebloom(); + new spell_dru_living_seed(); + new spell_dru_living_seed_proc(); new spell_dru_moonkin_form_passive(); + new spell_dru_owlkin_frenzy(); new spell_dru_predatory_strikes(); new spell_dru_primal_tenacity(); + new spell_dru_rip(); new spell_dru_savage_defense(); new spell_dru_savage_roar(); new spell_dru_starfall_aoe(); @@ -729,5 +1008,6 @@ void AddSC_druid_spell_scripts() new spell_dru_survival_instincts(); new spell_dru_swift_flight_passive(); new spell_dru_tiger_s_fury(); + new spell_dru_typhoon(); new spell_dru_t10_restoration_4p_bonus(); } diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index b5f4312bae5..05fad623114 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -72,6 +72,97 @@ class spell_gen_absorb0_hitlimit1 : public SpellScriptLoader } }; +// 28764 - Adaptive Warding (Frostfire Regalia Set) +enum AdaptiveWarding +{ + SPELL_GEN_ADAPTIVE_WARDING_FIRE = 28765, + SPELL_GEN_ADAPTIVE_WARDING_NATURE = 28768, + SPELL_GEN_ADAPTIVE_WARDING_FROST = 28766, + SPELL_GEN_ADAPTIVE_WARDING_SHADOW = 28769, + SPELL_GEN_ADAPTIVE_WARDING_ARCANE = 28770 +}; + +class spell_gen_adaptive_warding : public SpellScriptLoader +{ + public: + spell_gen_adaptive_warding() : SpellScriptLoader("spell_gen_adaptive_warding") { } + + class spell_gen_adaptive_warding_AuraScript : public AuraScript + { + PrepareAuraScript(spell_gen_adaptive_warding_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_GEN_ADAPTIVE_WARDING_FIRE) || + !sSpellMgr->GetSpellInfo(SPELL_GEN_ADAPTIVE_WARDING_NATURE) || + !sSpellMgr->GetSpellInfo(SPELL_GEN_ADAPTIVE_WARDING_FROST) || + !sSpellMgr->GetSpellInfo(SPELL_GEN_ADAPTIVE_WARDING_SHADOW) || + !sSpellMgr->GetSpellInfo(SPELL_GEN_ADAPTIVE_WARDING_ARCANE)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (eventInfo.GetDamageInfo()->GetSpellInfo()) // eventInfo.GetSpellInfo() + return false; + + // find Mage Armor + if (!GetTarget()->GetAuraEffect(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT, SPELLFAMILY_MAGE, 0x10000000, 0x0, 0x0)) + return false; + + switch (GetFirstSchoolInMask(eventInfo.GetSchoolMask())) + { + case SPELL_SCHOOL_NORMAL: + case SPELL_SCHOOL_HOLY: + return false; + default: + break; + } + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + uint32 spellId = 0; + switch (GetFirstSchoolInMask(eventInfo.GetSchoolMask())) + { + case SPELL_SCHOOL_FIRE: + spellId = SPELL_GEN_ADAPTIVE_WARDING_FIRE; + break; + case SPELL_SCHOOL_NATURE: + spellId = SPELL_GEN_ADAPTIVE_WARDING_NATURE; + break; + case SPELL_SCHOOL_FROST: + spellId = SPELL_GEN_ADAPTIVE_WARDING_FROST; + break; + case SPELL_SCHOOL_SHADOW: + spellId = SPELL_GEN_ADAPTIVE_WARDING_SHADOW; + break; + case SPELL_SCHOOL_ARCANE: + spellId = SPELL_GEN_ADAPTIVE_WARDING_ARCANE; + break; + default: + return; + } + GetTarget()->CastSpell(GetTarget(), spellId, true, NULL, aurEff); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_gen_adaptive_warding_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_gen_adaptive_warding_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_gen_adaptive_warding_AuraScript(); + } +}; + // 41337 Aura of Anger class spell_gen_aura_of_anger : public SpellScriptLoader { @@ -226,6 +317,245 @@ class spell_gen_cannibalize : public SpellScriptLoader } }; +// 63845 - Create Lance +enum CreateLanceSpells +{ + SPELL_CREATE_LANCE_ALLIANCE = 63914, + SPELL_CREATE_LANCE_HORDE = 63919 +}; + +class spell_gen_create_lance : public SpellScriptLoader +{ + public: + spell_gen_create_lance() : SpellScriptLoader("spell_gen_create_lance") { } + + class spell_gen_create_lance_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gen_create_lance_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_CREATE_LANCE_ALLIANCE) || !sSpellMgr->GetSpellInfo(SPELL_CREATE_LANCE_HORDE)) + return false; + return true; + } + + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + + if (Player* target = GetHitPlayer()) + { + if (target->GetTeam() == ALLIANCE) + GetCaster()->CastSpell(target, SPELL_CREATE_LANCE_ALLIANCE, true); + else + GetCaster()->CastSpell(target, SPELL_CREATE_LANCE_HORDE, true); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_gen_create_lance_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_gen_create_lance_SpellScript(); + } +}; + +// 28702 - Netherbloom +enum Netherbloom +{ + SPELL_NETHERBLOOM_POLLEN_1 = 28703 +}; + +class spell_gen_netherbloom : public SpellScriptLoader +{ + public: + spell_gen_netherbloom() : SpellScriptLoader("spell_gen_netherbloom") { } + + class spell_gen_netherbloom_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gen_netherbloom_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + for (uint8 i = 0; i < 5; ++i) + if (!sSpellMgr->GetSpellInfo(SPELL_NETHERBLOOM_POLLEN_1 + i)) + return false; + return true; + } + + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + + if (Unit* target = GetHitUnit()) + { + // 25% chance of casting a random buff + if (roll_chance_i(75)) + return; + + // triggered spells are 28703 to 28707 + // Note: some sources say, that there was the possibility of + // receiving a debuff. However, this seems to be removed by a patch. + + // don't overwrite an existing aura + for (uint8 i = 0; i < 5; ++i) + if (target->HasAura(SPELL_NETHERBLOOM_POLLEN_1 + i)) + return; + + target->CastSpell(target, SPELL_NETHERBLOOM_POLLEN_1 + urand(0, 4), true); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_gen_netherbloom_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_gen_netherbloom_SpellScript(); + } +}; + +// 28720 - Nightmare Vine +enum NightmareVine +{ + SPELL_NIGHTMARE_POLLEN = 28721 +}; + +class spell_gen_nightmare_vine : public SpellScriptLoader +{ + public: + spell_gen_nightmare_vine() : SpellScriptLoader("spell_gen_nightmare_vine") { } + + class spell_gen_nightmare_vine_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gen_nightmare_vine_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_NIGHTMARE_POLLEN)) + return false; + return true; + } + + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + + if (Unit* target = GetHitUnit()) + { + // 25% chance of casting Nightmare Pollen + if (roll_chance_i(25)) + target->CastSpell(target, SPELL_NIGHTMARE_POLLEN, true); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_gen_nightmare_vine_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_gen_nightmare_vine_SpellScript(); + } +}; + +// 27539 - Obsidian Armor +enum ObsidianArmor +{ + SPELL_GEN_OBSIDIAN_ARMOR_HOLY = 27536, + SPELL_GEN_OBSIDIAN_ARMOR_FIRE = 27533, + SPELL_GEN_OBSIDIAN_ARMOR_NATURE = 27538, + SPELL_GEN_OBSIDIAN_ARMOR_FROST = 27534, + SPELL_GEN_OBSIDIAN_ARMOR_SHADOW = 27535, + SPELL_GEN_OBSIDIAN_ARMOR_ARCANE = 27540 +}; + +class spell_gen_obsidian_armor : public SpellScriptLoader +{ + public: + spell_gen_obsidian_armor() : SpellScriptLoader("spell_gen_obsidian_armor") { } + + class spell_gen_obsidian_armor_AuraScript : public AuraScript + { + PrepareAuraScript(spell_gen_obsidian_armor_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_GEN_OBSIDIAN_ARMOR_HOLY) || + !sSpellMgr->GetSpellInfo(SPELL_GEN_OBSIDIAN_ARMOR_FIRE) || + !sSpellMgr->GetSpellInfo(SPELL_GEN_OBSIDIAN_ARMOR_NATURE) || + !sSpellMgr->GetSpellInfo(SPELL_GEN_OBSIDIAN_ARMOR_FROST) || + !sSpellMgr->GetSpellInfo(SPELL_GEN_OBSIDIAN_ARMOR_SHADOW) || + !sSpellMgr->GetSpellInfo(SPELL_GEN_OBSIDIAN_ARMOR_ARCANE)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (eventInfo.GetDamageInfo()->GetSpellInfo()) // eventInfo.GetSpellInfo() + return false; + + if (GetFirstSchoolInMask(eventInfo.GetSchoolMask()) == SPELL_SCHOOL_NORMAL) + return false; + + return true; + } + + void OnProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + uint32 spellId = 0; + switch (GetFirstSchoolInMask(eventInfo.GetSchoolMask())) + { + case SPELL_SCHOOL_HOLY: + spellId = SPELL_GEN_OBSIDIAN_ARMOR_HOLY; + break; + case SPELL_SCHOOL_FIRE: + spellId = SPELL_GEN_OBSIDIAN_ARMOR_FIRE; + break; + case SPELL_SCHOOL_NATURE: + spellId = SPELL_GEN_OBSIDIAN_ARMOR_NATURE; + break; + case SPELL_SCHOOL_FROST: + spellId = SPELL_GEN_OBSIDIAN_ARMOR_FROST; + break; + case SPELL_SCHOOL_SHADOW: + spellId = SPELL_GEN_OBSIDIAN_ARMOR_SHADOW; + break; + case SPELL_SCHOOL_ARCANE: + spellId = SPELL_GEN_OBSIDIAN_ARMOR_ARCANE; + break; + default: + return; + } + GetTarget()->CastSpell(GetTarget(), spellId, true, NULL, aurEff); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_gen_obsidian_armor_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_gen_obsidian_armor_AuraScript::OnProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_gen_obsidian_armor_AuraScript(); + } +}; + // 45472 Parachute enum ParachuteSpells { @@ -3191,10 +3521,15 @@ class spell_gen_replenishment : public SpellScriptLoader void AddSC_generic_spell_scripts() { new spell_gen_absorb0_hitlimit1(); + new spell_gen_adaptive_warding(); new spell_gen_aura_of_anger(); new spell_gen_av_drekthar_presence(); new spell_gen_burn_brutallus(); new spell_gen_cannibalize(); + new spell_gen_create_lance(); + new spell_gen_netherbloom(); + new spell_gen_nightmare_vine(); + new spell_gen_obsidian_armor(); new spell_gen_parachute(); new spell_gen_pet_summoned(); new spell_gen_remove_flight_auras(); diff --git a/src/server/scripts/Spells/spell_holiday.cpp b/src/server/scripts/Spells/spell_holiday.cpp index d883b4d7da7..dbfc2b44501 100644 --- a/src/server/scripts/Spells/spell_holiday.cpp +++ b/src/server/scripts/Spells/spell_holiday.cpp @@ -303,27 +303,10 @@ class spell_winter_veil_mistletoe : public SpellScriptLoader void HandleScript(SpellEffIndex /*effIndex*/) { - Unit* caster = GetCaster(); - if (Player* target = GetHitPlayer()) { - uint32 spellId = 0; - switch (urand(0, 2)) - { - case 0: - spellId = SPELL_CREATE_MISTLETOE; - break; - case 1: - spellId = SPELL_CREATE_HOLLY; - break; - case 2: - spellId = SPELL_CREATE_SNOWFLAKES; - break; - default: - return; - } - - caster->CastSpell(target, spellId, true); + uint32 spellId = RAND(SPELL_CREATE_HOLLY, SPELL_CREATE_MISTLETOE, SPELL_CREATE_SNOWFLAKES); + GetCaster()->CastSpell(target, spellId, true); } } @@ -339,6 +322,71 @@ class spell_winter_veil_mistletoe : public SpellScriptLoader } }; +// 26275 - PX-238 Winter Wondervolt TRAP +enum PX238WinterWondervolt +{ + SPELL_PX_238_WINTER_WONDERVOLT_TRANSFORM_1 = 26157, + SPELL_PX_238_WINTER_WONDERVOLT_TRANSFORM_2 = 26272, + SPELL_PX_238_WINTER_WONDERVOLT_TRANSFORM_3 = 26273, + SPELL_PX_238_WINTER_WONDERVOLT_TRANSFORM_4 = 26274 +}; + +class spell_winter_veil_px_238_winter_wondervolt : public SpellScriptLoader +{ + public: + spell_winter_veil_px_238_winter_wondervolt() : SpellScriptLoader("spell_winter_veil_px_238_winter_wondervolt") { } + + class spell_winter_veil_px_238_winter_wondervolt_SpellScript : public SpellScript + { + PrepareSpellScript(spell_winter_veil_px_238_winter_wondervolt_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_PX_238_WINTER_WONDERVOLT_TRANSFORM_1) || + !sSpellMgr->GetSpellInfo(SPELL_PX_238_WINTER_WONDERVOLT_TRANSFORM_2) || + !sSpellMgr->GetSpellInfo(SPELL_PX_238_WINTER_WONDERVOLT_TRANSFORM_3) || + !sSpellMgr->GetSpellInfo(SPELL_PX_238_WINTER_WONDERVOLT_TRANSFORM_4)) + return false; + return true; + } + + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + + uint32 const spells[4] = + { + SPELL_PX_238_WINTER_WONDERVOLT_TRANSFORM_1, + SPELL_PX_238_WINTER_WONDERVOLT_TRANSFORM_2, + SPELL_PX_238_WINTER_WONDERVOLT_TRANSFORM_3, + SPELL_PX_238_WINTER_WONDERVOLT_TRANSFORM_4 + }; + + if (Unit* target = GetHitUnit()) + { + for (uint8 i = 0; i < 4; ++i) + if (target->HasAura(spells[i])) + return; + + GetCaster()->CastSpell(target, spells[urand(0, 3)], true); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_winter_veil_px_238_winter_wondervolt_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + + private: + + }; + + SpellScript* GetSpellScript() const + { + return new spell_winter_veil_px_238_winter_wondervolt_SpellScript(); + } +}; + void AddSC_holiday_spell_scripts() { // Love is in the Air @@ -349,4 +397,5 @@ void AddSC_holiday_spell_scripts() new spell_hallow_end_tricky_treat(); // Winter Veil new spell_winter_veil_mistletoe(); + new spell_winter_veil_px_238_winter_wondervolt(); } diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp index a9b21807899..877248cf1a8 100644 --- a/src/server/scripts/Spells/spell_hunter.cpp +++ b/src/server/scripts/Spells/spell_hunter.cpp @@ -33,12 +33,15 @@ enum HunterSpells { SPELL_HUNTER_ASPECT_OF_THE_BEAST_PET = 61669, + SPELL_HUNTER_ASPECT_OF_THE_VIPER_ENERGIZE = 34075, SPELL_HUNTER_BESTIAL_WRATH = 19574, SPELL_HUNTER_CHIMERA_SHOT_SERPENT = 53353, SPELL_HUNTER_CHIMERA_SHOT_VIPER = 53358, SPELL_HUNTER_CHIMERA_SHOT_SCORPID = 53359, + SPELL_HUNTER_GLYPHE_OF_ASPECT_OF_THE_VIPER = 56851, SPELL_HUNTER_INVIGORATION_TRIGGERED = 53398, SPELL_HUNTER_MASTERS_CALL_TRIGGERED = 62305, + SPELL_HUNTER_MISDIRECTION_PROC = 35079, SPELL_HUNTER_PET_LAST_STAND_TRIGGERED = 53479, SPELL_HUNTER_PET_HEART_OF_THE_PHOENIX = 55709, SPELL_HUNTER_PET_HEART_OF_THE_PHOENIX_TRIGGERED = 54114, @@ -99,6 +102,50 @@ class spell_hun_aspect_of_the_beast : public SpellScriptLoader } }; +// 34074 - Aspect of the Viper +class spell_hun_ascpect_of_the_viper : public SpellScriptLoader +{ + public: + spell_hun_ascpect_of_the_viper() : SpellScriptLoader("spell_hun_ascpect_of_the_viper") { } + + class spell_hun_ascpect_of_the_viper_AuraScript : public AuraScript + { + PrepareAuraScript(spell_hun_ascpect_of_the_viper_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_HUNTER_ASPECT_OF_THE_VIPER_ENERGIZE)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_HUNTER_GLYPHE_OF_ASPECT_OF_THE_VIPER)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + + uint32 maxMana = GetTarget()->GetMaxPower(POWER_MANA); + int32 mana = CalculatePct(maxMana, GetTarget()->GetAttackTime(RANGED_ATTACK) / 1000.0f); + + if (AuraEffect const* glyphe = GetTarget()->GetAuraEffect(SPELL_HUNTER_GLYPHE_OF_ASPECT_OF_THE_VIPER, EFFECT_0)) + AddPct(mana, glyphe->GetAmount()); + + GetTarget()->CastCustomSpell(SPELL_HUNTER_ASPECT_OF_THE_VIPER_ENERGIZE, SPELLVALUE_BASE_POINT0, mana, GetTarget(), true, NULL, aurEff); + } + + void Register() + { + OnEffectProc += AuraEffectProcFn(spell_hun_ascpect_of_the_viper_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_OBS_MOD_POWER); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_hun_ascpect_of_the_viper_AuraScript(); + } +}; + // 53209 - Chimera Shot class spell_hun_chimera_shot : public SpellScriptLoader { @@ -358,16 +405,35 @@ class spell_hun_misdirection : public SpellScriptLoader { PrepareAuraScript(spell_hun_misdirection_AuraScript); + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_HUNTER_MISDIRECTION_PROC)) + return false; + return true; + } + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - if (Unit* caster = GetCaster()) - if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_DEFAULT) - caster->SetReducedThreatPercent(0, 0); + if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_DEFAULT) + GetTarget()->ResetRedirectThreat(); + } + + bool CheckProc(ProcEventInfo& /*eventInfo*/) + { + return GetTarget()->GetRedirectThreatTarget(); + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + GetTarget()->CastSpell(GetTarget(), SPELL_HUNTER_MISDIRECTION_PROC, true, NULL, aurEff); } void Register() { AfterEffectRemove += AuraEffectRemoveFn(spell_hun_misdirection_AuraScript::OnRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + DoCheckProc += AuraCheckProcFn(spell_hun_misdirection_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_hun_misdirection_AuraScript::HandleProc, EFFECT_1, SPELL_AURA_DUMMY); } }; @@ -377,7 +443,7 @@ class spell_hun_misdirection : public SpellScriptLoader } }; -// 35079 - Misdirection proc +// 35079 - Misdirection (Proc) class spell_hun_misdirection_proc : public SpellScriptLoader { public: @@ -389,8 +455,7 @@ class spell_hun_misdirection_proc : public SpellScriptLoader void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - if (GetCaster()) - GetCaster()->SetReducedThreatPercent(0, 0); + GetTarget()->ResetRedirectThreat(); } void Register() @@ -740,6 +805,7 @@ class spell_hun_target_only_pet_and_owner : public SpellScriptLoader void AddSC_hunter_spell_scripts() { new spell_hun_aspect_of_the_beast(); + new spell_hun_ascpect_of_the_viper(); new spell_hun_chimera_shot(); new spell_hun_disengage(); new spell_hun_invigoration(); diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp index b4e06cb6b48..b8e17f4ecca 100644 --- a/src/server/scripts/Spells/spell_item.cpp +++ b/src/server/scripts/Spells/spell_item.cpp @@ -73,6 +73,150 @@ class spell_item_trigger_spell : public SpellScriptLoader } }; +// 26400 - Arcane Shroud +class spell_item_arcane_shroud : public SpellScriptLoader +{ + public: + spell_item_arcane_shroud() : SpellScriptLoader("spell_item_arcane_shroud") { } + + class spell_item_arcane_shroud_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_arcane_shroud_AuraScript); + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + int32 diff = GetUnitOwner()->getLevel() - 60; + if (diff > 0) + amount += 2 * diff; + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_item_arcane_shroud_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_MOD_THREAT); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_item_arcane_shroud_AuraScript(); + } +}; + +// 64411 - Blessing of Ancient Kings (Val'anyr, Hammer of Ancient Kings) +enum BlessingOfAncientKings +{ + SPELL_PROTECTION_OF_ANCIENT_KINGS = 64413 +}; + +class spell_item_blessing_of_ancient_kings : public SpellScriptLoader +{ + public: + spell_item_blessing_of_ancient_kings() : SpellScriptLoader("spell_item_blessing_of_ancient_kings") { } + + class spell_item_blessing_of_ancient_kings_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_blessing_of_ancient_kings_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_PROTECTION_OF_ANCIENT_KINGS)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + return eventInfo.GetProcTarget(); + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + int32 absorb = int32(CalculatePct(eventInfo.GetHealInfo()->GetHeal(), 15.0f)); + if (AuraEffect* protEff = eventInfo.GetProcTarget()->GetAuraEffect(SPELL_PROTECTION_OF_ANCIENT_KINGS, 0, eventInfo.GetActor()->GetGUID())) + { + // The shield can grow to a maximum size of 20,000 damage absorbtion + protEff->SetAmount(std::min<int32>(protEff->GetAmount() + absorb, 20000)); + + // Refresh and return to prevent replacing the aura + aurEff->GetBase()->RefreshDuration(); + } + else + GetTarget()->CastCustomSpell(SPELL_PROTECTION_OF_ANCIENT_KINGS, SPELLVALUE_BASE_POINT0, absorb, eventInfo.GetProcTarget(), true, NULL, aurEff); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_item_blessing_of_ancient_kings_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_item_blessing_of_ancient_kings_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_item_blessing_of_ancient_kings_AuraScript(); + } +}; + +// 8342 - Defibrillate (Goblin Jumper Cables) have 33% chance on success +// 22999 - Defibrillate (Goblin Jumper Cables XL) have 50% chance on success +// 54732 - Defibrillate (Gnomish Army Knife) have 67% chance on success +enum Defibrillate +{ + SPELL_GOBLIN_JUMPER_CABLES_FAIL = 8338, + SPELL_GOBLIN_JUMPER_CABLES_XL_FAIL = 23055 +}; + +class spell_item_defibrillate : public SpellScriptLoader +{ + public: + spell_item_defibrillate(char const* name, uint8 chance, uint32 failSpell = 0) : SpellScriptLoader(name), _chance(chance), _failSpell(failSpell) { } + + class spell_item_defibrillate_SpellScript : public SpellScript + { + PrepareSpellScript(spell_item_defibrillate_SpellScript); + + public: + spell_item_defibrillate_SpellScript(uint8 chance, uint32 failSpell) : SpellScript(), _chance(chance), _failSpell(failSpell) { } + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (_failSpell && !sSpellMgr->GetSpellInfo(_failSpell)) + return false; + return true; + } + + void HandleScript(SpellEffIndex effIndex) + { + if (roll_chance_i(_chance)) + { + PreventHitDefaultEffect(effIndex); + if (_failSpell) + GetCaster()->CastSpell(GetCaster(), _failSpell, true, GetCastItem()); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_item_defibrillate_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_RESURRECT); + } + + private: + uint8 _chance; + uint32 _failSpell; + }; + + SpellScript* GetSpellScript() const + { + return new spell_item_defibrillate_SpellScript(_chance, _failSpell); + } + + private: + uint8 _chance; + uint32 _failSpell; +}; + // http://www.wowhead.com/item=6522 Deviate Fish // 8063 Deviate Fish enum DeviateFishSpells @@ -357,6 +501,47 @@ class spell_item_mingos_fortune_generator : public SpellScriptLoader } }; +// 71875, 71877 - Item - Black Bruise: Necrotic Touch Proc +enum NecroticTouch +{ + SPELL_ITEM_NECROTIC_TOUCH_PROC = 71879 +}; + +class spell_item_necrotic_touch : public SpellScriptLoader +{ + public: + spell_item_necrotic_touch() : SpellScriptLoader("spell_item_necrotic_touch") { } + + class spell_item_necrotic_touch_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_necrotic_touch_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_ITEM_NECROTIC_TOUCH_PROC)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + int32 bp = CalculatePct(int32(eventInfo.GetDamageInfo()->GetDamage()), aurEff->GetAmount()); + GetTarget()->CastCustomSpell(SPELL_ITEM_NECROTIC_TOUCH_PROC, SPELLVALUE_BASE_POINT0, bp, GetTarget(), true, NULL, aurEff); + } + + void Register() + { + OnEffectProc += AuraEffectProcFn(spell_item_necrotic_touch_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_item_necrotic_touch_AuraScript(); + } +}; + // http://www.wowhead.com/item=10720 Gnomish Net-o-Matic Projector // 13120 Net-o-Matic enum NetOMaticSpells @@ -464,6 +649,35 @@ class spell_item_noggenfogger_elixir : public SpellScriptLoader } }; +// 17512 - Piccolo of the Flaming Fire +class spell_item_piccolo_of_the_flaming_fire : public SpellScriptLoader +{ + public: + spell_item_piccolo_of_the_flaming_fire() : SpellScriptLoader("spell_item_piccolo_of_the_flaming_fire") { } + + class spell_item_piccolo_of_the_flaming_fire_SpellScript : public SpellScript + { + PrepareSpellScript(spell_item_piccolo_of_the_flaming_fire_SpellScript); + + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + if (Player* target = GetHitPlayer()) + target->HandleEmoteCommand(EMOTE_STATE_DANCE); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_item_piccolo_of_the_flaming_fire_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_item_piccolo_of_the_flaming_fire_SpellScript(); + } +}; + // http://www.wowhead.com/item=6657 Savory Deviate Delight // 8213 Savory Deviate Delight enum SavoryDeviateDelight @@ -522,6 +736,262 @@ class spell_item_savory_deviate_delight : public SpellScriptLoader } }; +// 48129 - Scroll of Recall +// 60320 - Scroll of Recall II +// 60321 - Scroll of Recall III +enum ScrollOfRecall +{ + SPELL_SCROLL_OF_RECALL_I = 48129, + SPELL_SCROLL_OF_RECALL_II = 60320, + SPELL_SCROLL_OF_RECALL_III = 60321, + SPELL_LOST = 60444, + SPELL_SCROLL_OF_RECALL_FAIL_ALLIANCE_1 = 60323, + SPELL_SCROLL_OF_RECALL_FAIL_HORDE_1 = 60328, +}; + +class spell_item_scroll_of_recall : public SpellScriptLoader +{ + public: + spell_item_scroll_of_recall() : SpellScriptLoader("spell_item_scroll_of_recall") { } + + class spell_item_scroll_of_recall_SpellScript : public SpellScript + { + PrepareSpellScript(spell_item_scroll_of_recall_SpellScript); + + bool Load() + { + return GetCaster()->GetTypeId() == TYPEID_PLAYER; + } + + void HandleScript(SpellEffIndex effIndex) + { + Unit* caster = GetCaster(); + uint8 maxSafeLevel = 0; + switch (GetSpellInfo()->Id) + { + case SPELL_SCROLL_OF_RECALL_I: // Scroll of Recall + maxSafeLevel = 40; + break; + case SPELL_SCROLL_OF_RECALL_II: // Scroll of Recall II + maxSafeLevel = 70; + break; + case SPELL_SCROLL_OF_RECALL_III: // Scroll of Recal III + maxSafeLevel = 80; + break; + default: + break; + } + + if (caster->getLevel() > maxSafeLevel) + { + caster->CastSpell(caster, SPELL_LOST, true); + + // ALLIANCE from 60323 to 60330 - HORDE from 60328 to 60335 + uint32 spellId = SPELL_SCROLL_OF_RECALL_FAIL_ALLIANCE_1; + if (GetCaster()->ToPlayer()->GetTeam() == HORDE) + spellId = SPELL_SCROLL_OF_RECALL_FAIL_HORDE_1; + + GetCaster()->CastSpell(GetCaster(), spellId + urand(0, 7), true); + + PreventHitDefaultEffect(effIndex); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_item_scroll_of_recall_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_TELEPORT_UNITS); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_item_scroll_of_recall_SpellScript(); + } +}; + +// 71169 - Shadow's Fate (Shadowmourne questline) +enum ShadowsFate +{ + SPELL_SOUL_FEAST = 71203, + QUEST_A_FEAST_OF_SOULS = 24547 +}; + +class spell_item_shadows_fate : public SpellScriptLoader +{ + public: + spell_item_shadows_fate() : SpellScriptLoader("spell_item_shadows_fate") { } + + class spell_item_shadows_fate_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_shadows_fate_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_SOUL_FEAST)) + return false; + if (!sObjectMgr->GetQuestTemplate(QUEST_A_FEAST_OF_SOULS)) + return false; + return true; + } + + bool Load() + { + _procTarget = NULL; + return true; + } + + bool CheckProc(ProcEventInfo& /*eventInfo*/) + { + _procTarget = GetCaster(); + return _procTarget && _procTarget->GetTypeId() == TYPEID_PLAYER && _procTarget->ToPlayer()->GetQuestStatus(QUEST_A_FEAST_OF_SOULS) == QUEST_STATUS_INCOMPLETE; + } + + void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + GetTarget()->CastSpell(_procTarget, SPELL_SOUL_FEAST, true); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_item_shadows_fate_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_item_shadows_fate_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + + private: + Unit* _procTarget; + }; + + AuraScript* GetAuraScript() const + { + return new spell_item_shadows_fate_AuraScript(); + } +}; + +enum Shadowmourne +{ + SPELL_SHADOWMOURNE_CHAOS_BANE_DAMAGE = 71904, + SPELL_SHADOWMOURNE_SOUL_FRAGMENT = 71905, + SPELL_SHADOWMOURNE_VISUAL_LOW = 72521, + SPELL_SHADOWMOURNE_VISUAL_HIGH = 72523, + SPELL_SHADOWMOURNE_CHAOS_BANE_BUFF = 73422, +}; + +// 71903 - Item - Shadowmourne Legendary +class spell_item_shadowmourne : public SpellScriptLoader +{ + public: + spell_item_shadowmourne() : SpellScriptLoader("spell_item_shadowmourne") { } + + class spell_item_shadowmourne_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_shadowmourne_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_SHADOWMOURNE_CHAOS_BANE_DAMAGE)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_SHADOWMOURNE_SOUL_FRAGMENT)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_SHADOWMOURNE_CHAOS_BANE_BUFF)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (GetTarget()->HasAura(SPELL_SHADOWMOURNE_CHAOS_BANE_BUFF)) // cant collect shards while under effect of Chaos Bane buff + return false; + return eventInfo.GetProcTarget() && eventInfo.GetProcTarget()->isAlive(); + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + GetTarget()->CastSpell(GetTarget(), SPELL_SHADOWMOURNE_SOUL_FRAGMENT, true, NULL, aurEff); + + // this can't be handled in AuraScript of SoulFragments because we need to know victim + if (Aura* soulFragments = GetTarget()->GetAura(SPELL_SHADOWMOURNE_SOUL_FRAGMENT)) + { + if (soulFragments->GetStackAmount() >= 10) + { + GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_SHADOWMOURNE_CHAOS_BANE_DAMAGE, true, NULL, aurEff); + soulFragments->Remove(); + } + } + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_item_shadowmourne_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_item_shadowmourne_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_item_shadowmourne_AuraScript(); + } +}; + +// 71905 - Soul Fragment +class spell_item_shadowmourne_soul_fragment : public SpellScriptLoader +{ + public: + spell_item_shadowmourne_soul_fragment() : SpellScriptLoader("spell_item_shadowmourne_soul_fragment") { } + + class spell_item_shadowmourne_soul_fragment_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_shadowmourne_soul_fragment_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_SHADOWMOURNE_VISUAL_LOW) || !sSpellMgr->GetSpellInfo(SPELL_SHADOWMOURNE_VISUAL_HIGH) || !sSpellMgr->GetSpellInfo(SPELL_SHADOWMOURNE_CHAOS_BANE_BUFF)) + return false; + return true; + } + + void OnStackChange(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Unit* target = GetTarget(); + switch (GetStackAmount()) + { + case 1: + target->CastSpell(target, SPELL_SHADOWMOURNE_VISUAL_LOW, true); + break; + case 6: + target->RemoveAurasDueToSpell(SPELL_SHADOWMOURNE_VISUAL_LOW); + target->CastSpell(target, SPELL_SHADOWMOURNE_VISUAL_HIGH, true); + break; + case 10: + target->RemoveAurasDueToSpell(SPELL_SHADOWMOURNE_VISUAL_HIGH); + target->CastSpell(target, SPELL_SHADOWMOURNE_CHAOS_BANE_BUFF, true); + break; + default: + break; + } + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Unit* target = GetTarget(); + target->RemoveAurasDueToSpell(SPELL_SHADOWMOURNE_VISUAL_LOW); + target->RemoveAurasDueToSpell(SPELL_SHADOWMOURNE_VISUAL_HIGH); + } + + void Register() + { + AfterEffectApply += AuraEffectApplyFn(spell_item_shadowmourne_soul_fragment_AuraScript::OnStackChange, EFFECT_0, SPELL_AURA_MOD_STAT, AuraEffectHandleModes(AURA_EFFECT_HANDLE_REAL | AURA_EFFECT_HANDLE_REAPPLY)); + AfterEffectRemove += AuraEffectRemoveFn(spell_item_shadowmourne_soul_fragment_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_MOD_STAT, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_item_shadowmourne_soul_fragment_AuraScript(); + } +}; + // http://www.wowhead.com/item=7734 Six Demon Bag // 14537 Six Demon Bag enum SixDemonBagSpells @@ -593,6 +1063,35 @@ class spell_item_six_demon_bag : public SpellScriptLoader } }; +// 28862 - The Eye of Diminution +class spell_item_the_eye_of_diminution : public SpellScriptLoader +{ + public: + spell_item_the_eye_of_diminution() : SpellScriptLoader("spell_item_the_eye_of_diminution") { } + + class spell_item_the_eye_of_diminution_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_the_eye_of_diminution_AuraScript); + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + int32 diff = GetUnitOwner()->getLevel() - 60; + if (diff > 0) + amount += diff; + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_item_the_eye_of_diminution_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_MOD_THREAT); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_item_the_eye_of_diminution_AuraScript(); + } +}; + // http://www.wowhead.com/item=44012 Underbelly Elixir // 59640 Underbelly Elixir enum UnderbellyElixirSpells @@ -646,70 +1145,6 @@ class spell_item_underbelly_elixir : public SpellScriptLoader } }; -enum eShadowmourneVisuals -{ - SPELL_SHADOWMOURNE_VISUAL_LOW = 72521, - SPELL_SHADOWMOURNE_VISUAL_HIGH = 72523, - SPELL_SHADOWMOURNE_CHAOS_BANE_BUFF = 73422, -}; - -class spell_item_shadowmourne : public SpellScriptLoader -{ -public: - spell_item_shadowmourne() : SpellScriptLoader("spell_item_shadowmourne") { } - - class spell_item_shadowmourne_AuraScript : public AuraScript - { - PrepareAuraScript(spell_item_shadowmourne_AuraScript); - - bool Validate(SpellInfo const* /*spellEntry*/) - { - if (!sSpellMgr->GetSpellInfo(SPELL_SHADOWMOURNE_VISUAL_LOW) || !sSpellMgr->GetSpellInfo(SPELL_SHADOWMOURNE_VISUAL_HIGH) || !sSpellMgr->GetSpellInfo(SPELL_SHADOWMOURNE_CHAOS_BANE_BUFF)) - return false; - return true; - } - - void OnStackChange(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - Unit* target = GetTarget(); - switch (GetStackAmount()) - { - case 1: - target->CastSpell(target, SPELL_SHADOWMOURNE_VISUAL_LOW, true); - break; - case 6: - target->RemoveAurasDueToSpell(SPELL_SHADOWMOURNE_VISUAL_LOW); - target->CastSpell(target, SPELL_SHADOWMOURNE_VISUAL_HIGH, true); - break; - case 10: - target->RemoveAurasDueToSpell(SPELL_SHADOWMOURNE_VISUAL_HIGH); - target->CastSpell(target, SPELL_SHADOWMOURNE_CHAOS_BANE_BUFF, true); - break; - default: - break; - } - } - - void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - Unit* target = GetTarget(); - target->RemoveAurasDueToSpell(SPELL_SHADOWMOURNE_VISUAL_LOW); - target->RemoveAurasDueToSpell(SPELL_SHADOWMOURNE_VISUAL_HIGH); - } - - void Register() - { - AfterEffectApply += AuraEffectApplyFn(spell_item_shadowmourne_AuraScript::OnStackChange, EFFECT_0, SPELL_AURA_MOD_STAT, AuraEffectHandleModes(AURA_EFFECT_HANDLE_REAL | AURA_EFFECT_HANDLE_REAPPLY)); - AfterEffectRemove += AuraEffectRemoveFn(spell_item_shadowmourne_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_MOD_STAT, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const - { - return new spell_item_shadowmourne_AuraScript(); - } -}; - enum AirRifleSpells { SPELL_AIR_RIFLE_HOLD_VISUAL = 65582, @@ -2030,17 +2465,28 @@ void AddSC_item_spell_scripts() // 23075 Mithril Mechanical Dragonling new spell_item_trigger_spell("spell_item_mithril_mechanical_dragonling", SPELL_MITHRIL_MECHANICAL_DRAGONLING); + new spell_item_arcane_shroud(); + new spell_item_blessing_of_ancient_kings(); + new spell_item_defibrillate("spell_item_goblin_jumper_cables", 67, SPELL_GOBLIN_JUMPER_CABLES_FAIL); + new spell_item_defibrillate("spell_item_goblin_jumper_cables_xl", 50, SPELL_GOBLIN_JUMPER_CABLES_XL_FAIL); + new spell_item_defibrillate("spell_item_gnomish_army_knife", 33); new spell_item_deviate_fish(); new spell_item_flask_of_the_north(); new spell_item_gnomish_death_ray(); new spell_item_make_a_wish(); new spell_item_mingos_fortune_generator(); + new spell_item_necrotic_touch(); new spell_item_net_o_matic(); new spell_item_noggenfogger_elixir(); + new spell_item_piccolo_of_the_flaming_fire(); new spell_item_savory_deviate_delight(); + new spell_item_scroll_of_recall(); + new spell_item_shadows_fate(); + new spell_item_shadowmourne(); + new spell_item_shadowmourne_soul_fragment(); new spell_item_six_demon_bag(); + new spell_item_the_eye_of_diminution(); new spell_item_underbelly_elixir(); - new spell_item_shadowmourne(); new spell_item_red_rider_air_rifle(); new spell_item_create_heart_candy(); diff --git a/src/server/scripts/Spells/spell_mage.cpp b/src/server/scripts/Spells/spell_mage.cpp index 61f0579190f..ca835c61a3a 100644 --- a/src/server/scripts/Spells/spell_mage.cpp +++ b/src/server/scripts/Spells/spell_mage.cpp @@ -28,11 +28,15 @@ enum MageSpells { + SPELL_MAGE_BURNOUT = 29077, SPELL_MAGE_COLD_SNAP = 11958, - SPELL_MAGE_FROST_WARDING_R1 = 28332, + SPELL_MAGE_FOCUS_MAGIC_PROC = 54648, + SPELL_MAGE_FROST_WARDING_R1 = 11189, SPELL_MAGE_FROST_WARDING_TRIGGERED = 57776, SPELL_MAGE_INCANTERS_ABSORBTION_R1 = 44394, SPELL_MAGE_INCANTERS_ABSORBTION_TRIGGERED = 44413, + SPELL_MAGE_IGNITE = 12654, + SPELL_MAGE_MASTER_OF_ELEMENTS_ENERGIZE = 29077, SPELL_MAGE_SQUIRREL_FORM = 32813, SPELL_MAGE_GIRAFFE_FORM = 32816, SPELL_MAGE_SERPENT_FORM = 32817, @@ -45,6 +49,31 @@ enum MageSpells SPELL_MAGE_GLYPH_OF_BLAST_WAVE = 62126, }; +// Incanter's Absorbtion +class spell_mage_incanters_absorbtion_base_AuraScript : public AuraScript +{ + public: + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_INCANTERS_ABSORBTION_TRIGGERED)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_INCANTERS_ABSORBTION_R1)) + return false; + return true; + } + + void Trigger(AuraEffect* aurEff, DamageInfo& /*dmgInfo*/, uint32& absorbAmount) + { + Unit* target = GetTarget(); + + if (AuraEffect* talentAurEff = target->GetAuraEffectOfRankedSpell(SPELL_MAGE_INCANTERS_ABSORBTION_R1, EFFECT_0)) + { + int32 bp = CalculatePct(absorbAmount, talentAurEff->GetAmount()); + target->CastCustomSpell(target, SPELL_MAGE_INCANTERS_ABSORBTION_TRIGGERED, &bp, NULL, NULL, true, NULL, aurEff); + } + } +}; + // -11113 - Blast Wave class spell_mage_blast_wave : public SpellScriptLoader { @@ -80,6 +109,51 @@ class spell_mage_blast_wave : public SpellScriptLoader } }; +// -44449 - Burnout +class spell_mage_burnout : public SpellScriptLoader +{ + public: + spell_mage_burnout() : SpellScriptLoader("spell_mage_burnout") { } + + class spell_mage_burnout_AuraScript : public AuraScript + { + PrepareAuraScript(spell_mage_burnout_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_BURNOUT)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + return eventInfo.GetDamageInfo()->GetSpellInfo(); // eventInfo.GetSpellInfo() + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + int32 mana = int32(eventInfo.GetDamageInfo()->GetSpellInfo()->CalcPowerCost(GetTarget(), eventInfo.GetDamageInfo()->GetSchoolMask())); + mana = CalculatePct(mana, aurEff->GetAmount()); + + GetTarget()->CastCustomSpell(SPELL_MAGE_BURNOUT, SPELLVALUE_BASE_POINT0, mana, GetTarget(), true, NULL, aurEff); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_mage_burnout_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_mage_burnout_AuraScript::HandleProc, EFFECT_1, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_mage_burnout_AuraScript(); + } +}; + // 11958 - Cold Snap class spell_mage_cold_snap : public SpellScriptLoader { @@ -127,29 +201,47 @@ class spell_mage_cold_snap : public SpellScriptLoader } }; -// -543, -6143 - Frost Warding -class spell_mage_frost_warding_trigger : public SpellScriptLoader +// -543 - Fire Ward +// -6143 - Frost Ward +class spell_mage_fire_frost_ward : public SpellScriptLoader { public: - spell_mage_frost_warding_trigger() : SpellScriptLoader("spell_mage_frost_warding_trigger") { } + spell_mage_fire_frost_ward() : SpellScriptLoader("spell_mage_fire_frost_ward") { } - class spell_mage_frost_warding_trigger_AuraScript : public AuraScript + class spell_mage_fire_frost_ward_AuraScript : public spell_mage_incanters_absorbtion_base_AuraScript { - PrepareAuraScript(spell_mage_frost_warding_trigger_AuraScript); + PrepareAuraScript(spell_mage_fire_frost_ward_AuraScript); bool Validate(SpellInfo const* /*spellInfo*/) { - if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_FROST_WARDING_TRIGGERED) || !sSpellMgr->GetSpellInfo(SPELL_MAGE_FROST_WARDING_R1)) + if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_FROST_WARDING_TRIGGERED)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_FROST_WARDING_R1)) return false; return true; } - void Absorb(AuraEffect* aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount) + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated) + { + canBeRecalculated = false; + if (Unit* caster = GetCaster()) + { + // +80.68% from sp bonus + float bonus = 0.8068f; + + bonus *= caster->SpellBaseHealingBonusDone(GetSpellInfo()->GetSchoolMask()); + bonus *= caster->CalculateLevelPenalty(GetSpellInfo()); + + amount += int32(bonus); + } + } + + void Absorb(AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount) { Unit* target = GetTarget(); if (AuraEffect* talentAurEff = target->GetAuraEffectOfRankedSpell(SPELL_MAGE_FROST_WARDING_R1, EFFECT_0)) { - int32 chance = talentAurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue(); + int32 chance = talentAurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue(); // SPELL_EFFECT_DUMMY with NO_TARGET if (roll_chance_i(chance)) { @@ -164,79 +256,156 @@ class spell_mage_frost_warding_trigger : public SpellScriptLoader void Register() { - OnEffectAbsorb += AuraEffectAbsorbFn(spell_mage_frost_warding_trigger_AuraScript::Absorb, EFFECT_0); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_mage_fire_frost_ward_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB); + OnEffectAbsorb += AuraEffectAbsorbFn(spell_mage_fire_frost_ward_AuraScript::Absorb, EFFECT_0); + AfterEffectAbsorb += AuraEffectAbsorbFn(spell_mage_fire_frost_ward_AuraScript::Trigger, EFFECT_0); } }; AuraScript* GetAuraScript() const { - return new spell_mage_frost_warding_trigger_AuraScript(); + return new spell_mage_fire_frost_ward_AuraScript(); } }; -class spell_mage_incanters_absorbtion_base_AuraScript : public AuraScript +// 54646 - Focus Magic +class spell_mage_focus_magic : public SpellScriptLoader { public: + spell_mage_focus_magic() : SpellScriptLoader("spell_mage_focus_magic") { } - bool Validate(SpellInfo const* /*spellInfo*/) + class spell_mage_focus_magic_AuraScript : public AuraScript { - return sSpellMgr->GetSpellInfo(SPELL_MAGE_INCANTERS_ABSORBTION_TRIGGERED) - && sSpellMgr->GetSpellInfo(SPELL_MAGE_INCANTERS_ABSORBTION_R1); - } + PrepareAuraScript(spell_mage_focus_magic_AuraScript); - void Trigger(AuraEffect* aurEff, DamageInfo & /*dmgInfo*/, uint32 & absorbAmount) - { - Unit* target = GetTarget(); + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_FOCUS_MAGIC_PROC)) + return false; + return true; + } - if (AuraEffect* talentAurEff = target->GetAuraEffectOfRankedSpell(SPELL_MAGE_INCANTERS_ABSORBTION_R1, EFFECT_0)) + bool Load() { - int32 bp = CalculatePct(absorbAmount, talentAurEff->GetAmount()); - target->CastCustomSpell(target, SPELL_MAGE_INCANTERS_ABSORBTION_TRIGGERED, &bp, NULL, NULL, true, NULL, aurEff); + _procTarget = NULL; + return true; + } + + bool CheckProc(ProcEventInfo& /*eventInfo*/) + { + _procTarget = GetCaster(); + return _procTarget && _procTarget->isAlive(); + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + GetTarget()->CastSpell(_procTarget, SPELL_MAGE_FOCUS_MAGIC_PROC, true, NULL, aurEff); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_mage_focus_magic_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_mage_focus_magic_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_MOD_SPELL_CRIT_CHANCE); } + + private: + Unit* _procTarget; + }; + + AuraScript* GetAuraScript() const + { + return new spell_mage_focus_magic_AuraScript(); } }; -// -543, -6143, -11426 - Incanter's Absorption -class spell_mage_incanters_absorbtion_absorb : public SpellScriptLoader +// -11426 - Ice Barrier +class spell_mage_ice_barrier : public SpellScriptLoader { public: - spell_mage_incanters_absorbtion_absorb() : SpellScriptLoader("spell_mage_incanters_absorbtion_absorb") { } + spell_mage_ice_barrier() : SpellScriptLoader("spell_mage_ice_barrier") { } - class spell_mage_incanters_absorbtion_absorb_AuraScript : public spell_mage_incanters_absorbtion_base_AuraScript + class spell_mage_ice_barrier_AuraScript : public spell_mage_incanters_absorbtion_base_AuraScript { - PrepareAuraScript(spell_mage_incanters_absorbtion_absorb_AuraScript); + PrepareAuraScript(spell_mage_ice_barrier_AuraScript); + + void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& canBeRecalculated) + { + canBeRecalculated = false; + if (Unit* caster = GetCaster()) + { + // +80.68% from sp bonus + float bonus = 0.8068f; + + bonus *= caster->SpellBaseHealingBonusDone(GetSpellInfo()->GetSchoolMask()); + + // Glyph of Ice Barrier: its weird having a SPELLMOD_ALL_EFFECTS here but its blizzards doing :) + // Glyph of Ice Barrier is only applied at the spell damage bonus because it was already applied to the base value in CalculateSpellDamage + bonus = caster->ApplyEffectModifiers(GetSpellInfo(), aurEff->GetEffIndex(), bonus); + + bonus *= caster->CalculateLevelPenalty(GetSpellInfo()); + + amount += int32(bonus); + } + } void Register() { - AfterEffectAbsorb += AuraEffectAbsorbFn(spell_mage_incanters_absorbtion_absorb_AuraScript::Trigger, EFFECT_0); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_mage_ice_barrier_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB); + AfterEffectAbsorb += AuraEffectAbsorbFn(spell_mage_ice_barrier_AuraScript::Trigger, EFFECT_0); } }; AuraScript* GetAuraScript() const { - return new spell_mage_incanters_absorbtion_absorb_AuraScript(); + return new spell_mage_ice_barrier_AuraScript(); } }; -// -1463 - Incanter's Absorption -class spell_mage_incanters_absorbtion_manashield : public SpellScriptLoader +// -11119 - Ignite +class spell_mage_ignite : public SpellScriptLoader { public: - spell_mage_incanters_absorbtion_manashield() : SpellScriptLoader("spell_mage_incanters_absorbtion_manashield") { } + spell_mage_ignite() : SpellScriptLoader("spell_mage_ignite") { } - class spell_mage_incanters_absorbtion_manashield_AuraScript : public spell_mage_incanters_absorbtion_base_AuraScript + class spell_mage_ignite_AuraScript : public AuraScript { - PrepareAuraScript(spell_mage_incanters_absorbtion_manashield_AuraScript); + PrepareAuraScript(spell_mage_ignite_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_IGNITE)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + return eventInfo.GetProcTarget(); + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + SpellInfo const* igniteDot = sSpellMgr->GetSpellInfo(SPELL_MAGE_IGNITE); + int32 pct = 8 * GetSpellInfo()->GetRank(); + + int32 amount = int32(CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), pct) / igniteDot->GetMaxTicks()); + amount += eventInfo.GetProcTarget()->GetRemainingPeriodicAmount(eventInfo.GetActor()->GetGUID(), SPELL_MAGE_IGNITE, SPELL_AURA_PERIODIC_DAMAGE); + GetTarget()->CastCustomSpell(SPELL_MAGE_IGNITE, SPELLVALUE_BASE_POINT0, amount, eventInfo.GetProcTarget(), true, NULL, aurEff); + } void Register() { - AfterEffectManaShield += AuraEffectManaShieldFn(spell_mage_incanters_absorbtion_manashield_AuraScript::Trigger, EFFECT_0); + DoCheckProc += AuraCheckProcFn(spell_mage_ignite_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_mage_ignite_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); } }; AuraScript* GetAuraScript() const { - return new spell_mage_incanters_absorbtion_manashield_AuraScript(); + return new spell_mage_ignite_AuraScript(); } }; @@ -279,6 +448,90 @@ class spell_mage_living_bomb : public SpellScriptLoader } }; +// -1463 - Mana Shield +class spell_mage_mana_shield : public SpellScriptLoader +{ + public: + spell_mage_mana_shield() : SpellScriptLoader("spell_mage_mana_shield") { } + + class spell_mage_mana_shield_AuraScript : public spell_mage_incanters_absorbtion_base_AuraScript + { + PrepareAuraScript(spell_mage_mana_shield_AuraScript); + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated) + { + canBeRecalculated = false; + if (Unit* caster = GetCaster()) + { + // +80.53% from sp bonus + float bonus = 0.8053f; + + bonus *= caster->SpellBaseHealingBonusDone(GetSpellInfo()->GetSchoolMask()); + bonus *= caster->CalculateLevelPenalty(GetSpellInfo()); + + amount += int32(bonus); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_mage_mana_shield_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_MANA_SHIELD); + AfterEffectManaShield += AuraEffectManaShieldFn(spell_mage_mana_shield_AuraScript::Trigger, EFFECT_0); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_mage_mana_shield_AuraScript(); + } +}; + +// -29074 - Master of Elements +class spell_mage_master_of_elements : public SpellScriptLoader +{ + public: + spell_mage_master_of_elements() : SpellScriptLoader("spell_mage_master_of_elements") { } + + class spell_mage_master_of_elements_AuraScript : public AuraScript + { + PrepareAuraScript(spell_mage_master_of_elements_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_MASTER_OF_ELEMENTS_ENERGIZE)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + return eventInfo.GetDamageInfo()->GetSpellInfo(); // eventInfo.GetSpellInfo() + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + int32 mana = int32(eventInfo.GetDamageInfo()->GetSpellInfo()->CalcPowerCost(GetTarget(), eventInfo.GetDamageInfo()->GetSchoolMask())); + mana = CalculatePct(mana, aurEff->GetAmount()); + + if (mana > 0) + GetTarget()->CastCustomSpell(SPELL_MAGE_MASTER_OF_ELEMENTS_ENERGIZE, SPELLVALUE_BASE_POINT0, mana, GetTarget(), true, NULL, aurEff); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_mage_master_of_elements_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_mage_master_of_elements_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_mage_master_of_elements_AuraScript(); + } +}; + enum SilvermoonPolymorph { NPC_AUROSALIA = 18744, @@ -377,11 +630,15 @@ class spell_mage_summon_water_elemental : public SpellScriptLoader void AddSC_mage_spell_scripts() { new spell_mage_blast_wave(); + new spell_mage_burnout(); new spell_mage_cold_snap(); - new spell_mage_frost_warding_trigger(); - new spell_mage_incanters_absorbtion_absorb(); - new spell_mage_incanters_absorbtion_manashield(); + new spell_mage_fire_frost_ward(); + new spell_mage_focus_magic(); + new spell_mage_ice_barrier(); + new spell_mage_ignite(); new spell_mage_living_bomb(); + new spell_mage_mana_shield(); + new spell_mage_master_of_elements(); new spell_mage_polymorph_cast_visual(); new spell_mage_summon_water_elemental(); } diff --git a/src/server/scripts/Spells/spell_paladin.cpp b/src/server/scripts/Spells/spell_paladin.cpp index d3fc86302e1..6be2453affb 100644 --- a/src/server/scripts/Spells/spell_paladin.cpp +++ b/src/server/scripts/Spells/spell_paladin.cpp @@ -31,6 +31,7 @@ enum PaladinSpells { SPELL_PALADIN_DIVINE_PLEA = 54428, SPELL_PALADIN_BLESSING_OF_SANCTUARY_BUFF = 67480, + SPELL_PALADIN_BLESSING_OF_SANCTUARY_ENERGIZE = 57319, SPELL_PALADIN_HOLY_SHOCK_R1 = 20473, SPELL_PALADIN_HOLY_SHOCK_R1_DAMAGE = 25912, @@ -45,12 +46,23 @@ enum PaladinSpells SPELL_PALADIN_DIVINE_STORM_DUMMY = 54171, SPELL_PALADIN_DIVINE_STORM_HEAL = 54172, + SPELL_PALADIN_EYE_FOR_AN_EYE_DAMAGE = 25997, + SPELL_PALADIN_FORBEARANCE = 25771, SPELL_PALADIN_AVENGING_WRATH_MARKER = 61987, SPELL_PALADIN_IMMUNE_SHIELD_MARKER = 61988, SPELL_PALADIN_HAND_OF_SACRIFICE = 6940, SPELL_PALADIN_DIVINE_SACRIFICE = 64205, + + SPELL_PALADIN_GLYPH_OF_SALVATION = 63225, + + SPELL_PALADIN_RIGHTEOUS_DEFENSE_TAUNT = 31790, + + SPELL_PALADIN_SEAL_OF_RIGHTEOUSNESS = 25742, + + SPELL_GENERIC_ARENA_DAMPENING = 74410, + SPELL_GENERIC_BATTLEGROUND_DAMPENING = 74411 }; // 31850 - Ardent Defender @@ -185,8 +197,8 @@ class spell_pal_blessing_of_faith : public SpellScriptLoader } }; -// 20911 Blessing of Sanctuary -// 25899 Greater Blessing of Sanctuary +// 20911 - Blessing of Sanctuary +// 25899 - Greater Blessing of Sanctuary class spell_pal_blessing_of_sanctuary : public SpellScriptLoader { public: @@ -200,6 +212,8 @@ class spell_pal_blessing_of_sanctuary : public SpellScriptLoader { if (!sSpellMgr->GetSpellInfo(SPELL_PALADIN_BLESSING_OF_SANCTUARY_BUFF)) return false; + if (!sSpellMgr->GetSpellInfo(SPELL_PALADIN_BLESSING_OF_SANCTUARY_ENERGIZE)) + return false; return true; } @@ -216,10 +230,23 @@ class spell_pal_blessing_of_sanctuary : public SpellScriptLoader target->RemoveAura(SPELL_PALADIN_BLESSING_OF_SANCTUARY_BUFF, GetCasterGUID()); } + bool CheckProc(ProcEventInfo& /*eventInfo*/) + { + return GetTarget()->getPowerType() == POWER_MANA; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + GetTarget()->CastSpell(GetTarget(), SPELL_PALADIN_BLESSING_OF_SANCTUARY_ENERGIZE, true, NULL, aurEff); + } + void Register() { AfterEffectApply += AuraEffectApplyFn(spell_pal_blessing_of_sanctuary_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); AfterEffectRemove += AuraEffectRemoveFn(spell_pal_blessing_of_sanctuary_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + DoCheckProc += AuraCheckProcFn(spell_pal_blessing_of_sanctuary_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_pal_blessing_of_sanctuary_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); } }; @@ -410,6 +437,43 @@ class spell_pal_exorcism_and_holy_wrath_damage : public SpellScriptLoader } }; +// -9799 - Eye for an Eye +class spell_pal_eye_for_an_eye : public SpellScriptLoader +{ + public: + spell_pal_eye_for_an_eye() : SpellScriptLoader("spell_pal_eye_for_an_eye") { } + + class spell_pal_eye_for_an_eye_AuraScript : public AuraScript + { + PrepareAuraScript(spell_pal_eye_for_an_eye_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_PALADIN_EYE_FOR_AN_EYE_DAMAGE)) + return false; + return true; + } + + void OnProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + // return damage % to attacker but < 50% own total health + int32 damage = int32(std::min(CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), aurEff->GetAmount()), GetTarget()->GetMaxHealth() / 2)); + GetTarget()->CastCustomSpell(SPELL_PALADIN_EYE_FOR_AN_EYE_DAMAGE, SPELLVALUE_BASE_POINT0, damage, eventInfo.GetProcTarget(), true, NULL, aurEff); + } + + void Register() + { + OnEffectProc += AuraEffectProcFn(spell_pal_eye_for_an_eye_AuraScript::OnProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_pal_eye_for_an_eye_AuraScript(); + } +}; + // 63521 - Guarded by The Light class spell_pal_guarded_by_the_light : public SpellScriptLoader { @@ -490,6 +554,39 @@ class spell_pal_hand_of_sacrifice : public SpellScriptLoader } }; +// 1038 - Hand of Salvation +class spell_pal_hand_of_salvation : public SpellScriptLoader +{ + public: + spell_pal_hand_of_salvation() : SpellScriptLoader("spell_pal_hand_of_salvation") { } + + class spell_pal_hand_of_salvation_AuraScript : public AuraScript + { + PrepareAuraScript(spell_pal_hand_of_salvation_AuraScript); + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* caster = GetCaster()) + { + // Glyph of Salvation + if (caster->GetGUID() == GetUnitOwner()->GetGUID()) + if (AuraEffect const* aurEff = caster->GetAuraEffect(SPELL_PALADIN_GLYPH_OF_SALVATION, EFFECT_0)) + amount -= aurEff->GetAmount(); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_pal_hand_of_salvation_AuraScript::CalculateAmount, EFFECT_1, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_pal_hand_of_salvation_AuraScript(); + } +}; + // -20473 - Holy Shock class spell_pal_holy_shock : public SpellScriptLoader { @@ -656,6 +753,13 @@ class spell_pal_righteous_defense : public SpellScriptLoader { PrepareSpellScript(spell_pal_righteous_defense_SpellScript); + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_PALADIN_RIGHTEOUS_DEFENSE_TAUNT)) + return false; + return true; + } + SpellCastResult CheckCast() { Unit* caster = GetCaster(); @@ -673,9 +777,27 @@ class spell_pal_righteous_defense : public SpellScriptLoader return SPELL_CAST_OK; } + void HandleTriggerSpellLaunch(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + } + + void HandleTriggerSpellHit(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + if (Unit* target = GetHitUnit()) + GetCaster()->CastSpell(target, SPELL_PALADIN_RIGHTEOUS_DEFENSE_TAUNT, true); + } + void Register() { OnCheckCast += SpellCheckCastFn(spell_pal_righteous_defense_SpellScript::CheckCast); + //! WORKAROUND + //! target select will be executed in hitphase of effect 0 + //! so we must handle trigger spell also in hit phase (default execution in launch phase) + //! see issue #3718 + OnEffectLaunchTarget += SpellEffectFn(spell_pal_righteous_defense_SpellScript::HandleTriggerSpellLaunch, EFFECT_1, SPELL_EFFECT_TRIGGER_SPELL); + OnEffectHitTarget += SpellEffectFn(spell_pal_righteous_defense_SpellScript::HandleTriggerSpellHit, EFFECT_1, SPELL_EFFECT_TRIGGER_SPELL); } }; @@ -685,6 +807,96 @@ class spell_pal_righteous_defense : public SpellScriptLoader } }; +// 58597 - Sacred Shield +class spell_pal_sacred_shield : public SpellScriptLoader +{ + public: + spell_pal_sacred_shield() : SpellScriptLoader("spell_pal_sacred_shield") { } + + class spell_pal_sacred_shield_AuraScript : public AuraScript + { + PrepareAuraScript(spell_pal_sacred_shield_AuraScript); + + void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* caster = GetCaster()) + { + // +75.00% from sp bonus + float bonus = CalculatePct(caster->SpellBaseHealingBonusDone(GetSpellInfo()->GetSchoolMask()), 75.0f); + + // Divine Guardian is only applied at the spell healing bonus because it was already applied to the base value in CalculateSpellDamage + bonus = caster->ApplyEffectModifiers(GetSpellInfo(), aurEff->GetEffIndex(), bonus); + bonus *= caster->CalculateLevelPenalty(GetSpellInfo()); + + amount += int32(bonus); + + // Arena - Dampening + if (AuraEffect const* dampening = caster->GetAuraEffect(SPELL_GENERIC_ARENA_DAMPENING, EFFECT_0)) + AddPct(amount, dampening->GetAmount()); + // Battleground - Dampening + else if (AuraEffect const* dampening = caster->GetAuraEffect(SPELL_GENERIC_BATTLEGROUND_DAMPENING, EFFECT_0)) + AddPct(amount, dampening->GetAmount()); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_pal_sacred_shield_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_pal_sacred_shield_AuraScript(); + } +}; + +// 20154, 21084 - Seal of Righteousness - melee proc dummy (addition ${$MWS*(0.022*$AP+0.044*$SPH)} damage) +class spell_pal_seal_of_righteousness : public SpellScriptLoader +{ + public: + spell_pal_seal_of_righteousness() : SpellScriptLoader("spell_pal_seal_of_righteousness") { } + + class spell_pal_seal_of_righteousness_AuraScript : public AuraScript + { + PrepareAuraScript(spell_pal_seal_of_righteousness_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_PALADIN_SEAL_OF_RIGHTEOUSNESS)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + return eventInfo.GetProcTarget(); + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + float ap = GetTarget()->GetTotalAttackPowerValue(BASE_ATTACK); + int32 holy = GetTarget()->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_HOLY); + holy += eventInfo.GetProcTarget()->SpellBaseDamageBonusTaken(SPELL_SCHOOL_MASK_HOLY); + int32 bp = int32((ap * 0.022f + 0.044f * holy) * GetTarget()->GetAttackTime(BASE_ATTACK) / 1000); + GetTarget()->CastCustomSpell(SPELL_PALADIN_SEAL_OF_RIGHTEOUSNESS, SPELLVALUE_BASE_POINT0, bp, eventInfo.GetProcTarget(), true, NULL, aurEff); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_pal_seal_of_righteousness_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_pal_seal_of_righteousness_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_pal_seal_of_righteousness_AuraScript(); + } +}; + void AddSC_paladin_spell_scripts() { new spell_pal_ardent_defender(); @@ -694,10 +906,14 @@ void AddSC_paladin_spell_scripts() new spell_pal_divine_storm(); new spell_pal_divine_storm_dummy(); new spell_pal_exorcism_and_holy_wrath_damage(); + new spell_pal_eye_for_an_eye(); new spell_pal_guarded_by_the_light(); new spell_pal_hand_of_sacrifice(); + new spell_pal_hand_of_salvation(); new spell_pal_holy_shock(); new spell_pal_judgement_of_command(); new spell_pal_lay_on_hands(); new spell_pal_righteous_defense(); + new spell_pal_sacred_shield(); + new spell_pal_seal_of_righteousness(); } diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp index 1c416a0d28a..e19110d0f62 100644 --- a/src/server/scripts/Spells/spell_priest.cpp +++ b/src/server/scripts/Spells/spell_priest.cpp @@ -29,22 +29,115 @@ enum PriestSpells { - SPELL_PRIEST_EMPOWERED_RENEW = 63544, - SPELL_PRIEST_GUARDIAN_SPIRIT_HEAL = 48153, - SPELL_PRIEST_PENANCE_R1 = 47540, - SPELL_PRIEST_PENANCE_R1_DAMAGE = 47758, - SPELL_PRIEST_PENANCE_R1_HEAL = 47757, - SPELL_PRIEST_REFLECTIVE_SHIELD_TRIGGERED = 33619, - SPELL_PRIEST_REFLECTIVE_SHIELD_R1 = 33201, - SPELL_PRIEST_SHADOW_WORD_DEATH = 32409, - SPELL_PRIEST_T9_HEALING_2P = 67201, - SPELL_PRIEST_VAMPIRIC_TOUCH_DISPEL = 64085, + SPELL_PRIEST_DIVINE_AEGIS = 47753, + SPELL_PRIEST_EMPOWERED_RENEW = 63544, + SPELL_PRIEST_GLYPHE_OF_LIGHTWELL = 55673, + SPELL_PRIEST_GLYPHE_OF_PRAYER_OF_HEALING_HEAL = 56161, + SPELL_PRIEST_GUARDIAN_SPIRIT_HEAL = 48153, + SPELL_PRIEST_MANA_LEECH_PROC = 34650, + SPELL_PRIEST_PENANCE_R1 = 47540, + SPELL_PRIEST_PENANCE_R1_DAMAGE = 47758, + SPELL_PRIEST_PENANCE_R1_HEAL = 47757, + SPELL_PRIEST_REFLECTIVE_SHIELD_TRIGGERED = 33619, + SPELL_PRIEST_REFLECTIVE_SHIELD_R1 = 33201, + SPELL_PRIEST_SHADOW_WORD_DEATH = 32409, + SPELL_PRIEST_T9_HEALING_2P = 67201, + SPELL_PRIEST_VAMPIRIC_TOUCH_DISPEL = 64085, }; enum PriestSpellIcons { - PRIEST_ICON_ID_EMPOWERED_RENEW_TALENT = 3021, - PRIEST_ICON_ID_PAIN_AND_SUFFERING = 2874, + PRIEST_ICON_ID_BORROWED_TIME = 2899, + PRIEST_ICON_ID_EMPOWERED_RENEW_TALENT = 3021, + PRIEST_ICON_ID_PAIN_AND_SUFFERING = 2874, +}; + +// -47509 - Divine Aegis +class spell_pri_divine_aegis : public SpellScriptLoader +{ + public: + spell_pri_divine_aegis() : SpellScriptLoader("spell_pri_divine_aegis") { } + + class spell_pri_divine_aegis_AuraScript : public AuraScript + { + PrepareAuraScript(spell_pri_divine_aegis_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_PRIEST_DIVINE_AEGIS)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + return eventInfo.GetProcTarget(); + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + int32 absorb = CalculatePct(int32(eventInfo.GetHealInfo()->GetHeal()), aurEff->GetAmount()); + + // Multiple effects stack, so let's try to find this aura. + if (AuraEffect const* aegis = eventInfo.GetProcTarget()->GetAuraEffect(SPELL_PRIEST_DIVINE_AEGIS, EFFECT_0)) + absorb += aegis->GetAmount(); + + absorb = std::min(absorb, eventInfo.GetProcTarget()->getLevel() * 125); + + GetTarget()->CastCustomSpell(SPELL_PRIEST_DIVINE_AEGIS, SPELLVALUE_BASE_POINT0, absorb, eventInfo.GetProcTarget(), true, NULL, aurEff); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_pri_divine_aegis_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_pri_divine_aegis_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_pri_divine_aegis_AuraScript(); + } +}; + +// 55680 - Glyph of Prayer of Healing +class spell_pri_glyph_of_prayer_of_healing : public SpellScriptLoader +{ + public: + spell_pri_glyph_of_prayer_of_healing() : SpellScriptLoader("spell_pri_glyph_of_prayer_of_healing") { } + + class spell_pri_glyph_of_prayer_of_healing_AuraScript : public AuraScript + { + PrepareAuraScript(spell_pri_glyph_of_prayer_of_healing_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_PRIEST_GLYPHE_OF_PRAYER_OF_HEALING_HEAL)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(SPELL_PRIEST_GLYPHE_OF_PRAYER_OF_HEALING_HEAL); + int32 heal = int32(CalculatePct(int32(eventInfo.GetHealInfo()->GetHeal()), aurEff->GetAmount()) / triggeredSpellInfo->GetMaxTicks()); + GetTarget()->CastCustomSpell(SPELL_PRIEST_GLYPHE_OF_PRAYER_OF_HEALING_HEAL, SPELLVALUE_BASE_POINT0, heal, eventInfo.GetProcTarget(), true, NULL, aurEff); + } + + void Register() + { + OnEffectProc += AuraEffectProcFn(spell_pri_glyph_of_prayer_of_healing_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_pri_glyph_of_prayer_of_healing_AuraScript(); + } }; // -47788 - Guardian Spirit @@ -104,6 +197,38 @@ class spell_pri_guardian_spirit : public SpellScriptLoader } }; +// -7001 - Lightwell Renew +class spell_pri_lightwell_renew : public SpellScriptLoader +{ + public: + spell_pri_lightwell_renew() : SpellScriptLoader("spell_pri_lightwell_renew") { } + + class spell_pri_lightwell_renew_AuraScript : public AuraScript + { + PrepareAuraScript(spell_pri_lightwell_renew_AuraScript); + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* caster = GetCaster()) + { + // Bonus from Glyph of Lightwell + if (AuraEffect* modHealing = caster->GetAuraEffect(SPELL_PRIEST_GLYPHE_OF_LIGHTWELL, EFFECT_0)) + AddPct(amount, modHealing->GetAmount()); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_pri_lightwell_renew_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_HEAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_pri_lightwell_renew_AuraScript(); + } +}; + // -8129 - Mana Burn class spell_pri_mana_burn : public SpellScriptLoader { @@ -132,6 +257,57 @@ class spell_pri_mana_burn : public SpellScriptLoader } }; +// 28305 - Mana Leech (Passive) (Priest Pet Aura) +class spell_pri_mana_leech : public SpellScriptLoader +{ + public: + spell_pri_mana_leech() : SpellScriptLoader("spell_pri_mana_leech") { } + + class spell_pri_mana_leech_AuraScript : public AuraScript + { + PrepareAuraScript(spell_pri_mana_leech_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_PRIEST_MANA_LEECH_PROC)) + return false; + return true; + } + + bool Load() + { + _procTarget = NULL; + return true; + } + + bool CheckProc(ProcEventInfo& /*eventInfo*/) + { + _procTarget = GetTarget()->GetOwner(); + return _procTarget; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + GetTarget()->CastSpell(_procTarget, SPELL_PRIEST_MANA_LEECH_PROC, true, NULL, aurEff); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_pri_mana_leech_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_pri_mana_leech_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + + private: + Unit* _procTarget; + }; + + AuraScript* GetAuraScript() const + { + return new spell_pri_mana_leech_AuraScript(); + } +}; + // -49821 - Mind Sear class spell_pri_mind_sear : public SpellScriptLoader { @@ -260,81 +436,114 @@ class spell_pri_penance : public SpellScriptLoader } }; -// 33110 - Prayer of Mending Heal -class spell_pri_prayer_of_mending_heal : public SpellScriptLoader +// -17 - Power Word: Shield +class spell_pri_power_word_shield : public SpellScriptLoader { public: - spell_pri_prayer_of_mending_heal() : SpellScriptLoader("spell_pri_prayer_of_mending_heal") { } + spell_pri_power_word_shield() : SpellScriptLoader("spell_pri_power_word_shield") { } - class spell_pri_prayer_of_mending_heal_SpellScript : public SpellScript + class spell_pri_power_word_shield_AuraScript : public AuraScript { - PrepareSpellScript(spell_pri_prayer_of_mending_heal_SpellScript); + PrepareAuraScript(spell_pri_power_word_shield_AuraScript); - void HandleHeal(SpellEffIndex /*effIndex*/) + bool Validate(SpellInfo const* /*spellInfo*/) { - if (Unit* caster = GetOriginalCaster()) + if (!sSpellMgr->GetSpellInfo(SPELL_PRIEST_REFLECTIVE_SHIELD_TRIGGERED)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_PRIEST_REFLECTIVE_SHIELD_R1)) + return false; + return true; + } + + void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& canBeRecalculated) + { + canBeRecalculated = false; + if (Unit* caster = GetCaster()) { - if (AuraEffect* aurEff = caster->GetAuraEffect(SPELL_PRIEST_T9_HEALING_2P, EFFECT_0)) + // +80.68% from sp bonus + float bonus = 0.8068f; + + // Borrowed Time + if (AuraEffect const* borrowedTime = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, PRIEST_ICON_ID_BORROWED_TIME, EFFECT_1)) + bonus += CalculatePct(1.0f, borrowedTime->GetAmount()); + + bonus *= caster->SpellBaseHealingBonusDone(GetSpellInfo()->GetSchoolMask()); + + // Improved PW: Shield: its weird having a SPELLMOD_ALL_EFFECTS here but its blizzards doing :) + // Improved PW: Shield is only applied at the spell healing bonus because it was already applied to the base value in CalculateSpellDamage + bonus = caster->ApplyEffectModifiers(GetSpellInfo(), aurEff->GetEffIndex(), bonus); + bonus *= caster->CalculateLevelPenalty(GetSpellInfo()); + + amount += int32(bonus); + + // Twin Disciplines + if (AuraEffect const* twinDisciplines = caster->GetAuraEffect(SPELL_AURA_ADD_PCT_MODIFIER, SPELLFAMILY_PRIEST, 0x400000, 0, 0, GetCasterGUID())) + AddPct(amount, twinDisciplines->GetAmount()); + + // Focused Power + amount *= caster->GetTotalAuraMultiplier(SPELL_AURA_MOD_HEALING_DONE_PERCENT); + } + } + + void ReflectDamage(AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount) + { + Unit* target = GetTarget(); + if (dmgInfo.GetAttacker() == target) + return; + + if (Unit* caster = GetCaster()) + if (AuraEffect* talentAurEff = caster->GetAuraEffectOfRankedSpell(SPELL_PRIEST_REFLECTIVE_SHIELD_R1, EFFECT_0)) { - int32 heal = GetHitHeal(); - AddPct(heal, aurEff->GetAmount()); - SetHitHeal(heal); + int32 bp = CalculatePct(absorbAmount, talentAurEff->GetAmount()); + target->CastCustomSpell(dmgInfo.GetAttacker(), SPELL_PRIEST_REFLECTIVE_SHIELD_TRIGGERED, &bp, NULL, NULL, true, NULL, aurEff); } - } } void Register() { - OnEffectHitTarget += SpellEffectFn(spell_pri_prayer_of_mending_heal_SpellScript::HandleHeal, EFFECT_0, SPELL_EFFECT_HEAL); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_pri_power_word_shield_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB); + AfterEffectAbsorb += AuraEffectAbsorbFn(spell_pri_power_word_shield_AuraScript::ReflectDamage, EFFECT_0); } }; - SpellScript* GetSpellScript() const + AuraScript* GetAuraScript() const { - return new spell_pri_prayer_of_mending_heal_SpellScript(); + return new spell_pri_power_word_shield_AuraScript(); } }; -// -17 - Reflective Shield -class spell_pri_reflective_shield_trigger : public SpellScriptLoader +// 33110 - Prayer of Mending Heal +class spell_pri_prayer_of_mending_heal : public SpellScriptLoader { public: - spell_pri_reflective_shield_trigger() : SpellScriptLoader("spell_pri_reflective_shield_trigger") { } + spell_pri_prayer_of_mending_heal() : SpellScriptLoader("spell_pri_prayer_of_mending_heal") { } - class spell_pri_reflective_shield_trigger_AuraScript : public AuraScript + class spell_pri_prayer_of_mending_heal_SpellScript : public SpellScript { - PrepareAuraScript(spell_pri_reflective_shield_trigger_AuraScript); - - bool Validate(SpellInfo const* /*spellInfo*/) - { - if (!sSpellMgr->GetSpellInfo(SPELL_PRIEST_REFLECTIVE_SHIELD_TRIGGERED) || !sSpellMgr->GetSpellInfo(SPELL_PRIEST_REFLECTIVE_SHIELD_R1)) - return false; - return true; - } + PrepareSpellScript(spell_pri_prayer_of_mending_heal_SpellScript); - void Trigger(AuraEffect* aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount) + void HandleHeal(SpellEffIndex /*effIndex*/) { - Unit* target = GetTarget(); - if (dmgInfo.GetAttacker() == target) - return; - - if (GetCaster()) - if (AuraEffect* talentAurEff = target->GetAuraEffectOfRankedSpell(SPELL_PRIEST_REFLECTIVE_SHIELD_R1, EFFECT_0)) + if (Unit* caster = GetOriginalCaster()) + { + if (AuraEffect* aurEff = caster->GetAuraEffect(SPELL_PRIEST_T9_HEALING_2P, EFFECT_0)) { - int32 bp = CalculatePct(absorbAmount, talentAurEff->GetAmount()); - target->CastCustomSpell(dmgInfo.GetAttacker(), SPELL_PRIEST_REFLECTIVE_SHIELD_TRIGGERED, &bp, NULL, NULL, true, NULL, aurEff); + int32 heal = GetHitHeal(); + AddPct(heal, aurEff->GetAmount()); + SetHitHeal(heal); } + } } void Register() { - AfterEffectAbsorb += AuraEffectAbsorbFn(spell_pri_reflective_shield_trigger_AuraScript::Trigger, EFFECT_0); + OnEffectHitTarget += SpellEffectFn(spell_pri_prayer_of_mending_heal_SpellScript::HandleHeal, EFFECT_0, SPELL_EFFECT_HEAL); } }; - AuraScript* GetAuraScript() const + SpellScript* GetSpellScript() const { - return new spell_pri_reflective_shield_trigger_AuraScript(); + return new spell_pri_prayer_of_mending_heal_SpellScript(); } }; @@ -457,13 +666,17 @@ class spell_pri_vampiric_touch : public SpellScriptLoader void AddSC_priest_spell_scripts() { + new spell_pri_divine_aegis(); + new spell_pri_glyph_of_prayer_of_healing(); new spell_pri_guardian_spirit(); + new spell_pri_lightwell_renew(); new spell_pri_mana_burn(); + new spell_pri_mana_leech(); new spell_pri_mind_sear(); new spell_pri_pain_and_suffering_proc(); new spell_pri_penance(); + new spell_pri_power_word_shield(); new spell_pri_prayer_of_mending_heal(); - new spell_pri_reflective_shield_trigger(); new spell_pri_renew(); new spell_pri_shadow_word_death(); new spell_pri_vampiric_touch(); diff --git a/src/server/scripts/Spells/spell_rogue.cpp b/src/server/scripts/Spells/spell_rogue.cpp index 70b677f5aaa..f6391c80d63 100644 --- a/src/server/scripts/Spells/spell_rogue.cpp +++ b/src/server/scripts/Spells/spell_rogue.cpp @@ -28,10 +28,68 @@ enum RogueSpells { + SPELL_ROGUE_BLADE_FLURRY_EXTRA_ATTACK = 22482, SPELL_ROGUE_CHEAT_DEATH_COOLDOWN = 31231, SPELL_ROGUE_GLYPH_OF_PREPARATION = 56819, SPELL_ROGUE_PREY_ON_THE_WEAK = 58670, SPELL_ROGUE_SHIV_TRIGGERED = 5940, + SPELL_ROGUE_TRICKS_OF_THE_TRADE_DMG_BOOST = 57933, + SPELL_ROGUE_TRICKS_OF_THE_TRADE_PROC = 59628, +}; + +// 13877, 33735, (check 51211, 65956) - Blade Flurry +class spell_rog_blade_flurry : public SpellScriptLoader +{ + public: + spell_rog_blade_flurry() : SpellScriptLoader("spell_rog_blade_flurry") { } + + class spell_rog_blade_flurry_AuraScript : public AuraScript + { + PrepareAuraScript(spell_rog_blade_flurry_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_ROGUE_BLADE_FLURRY_EXTRA_ATTACK)) + return false; + return true; + } + + bool Load() + { + _procTarget = NULL; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + _procTarget = eventInfo.GetActor()->SelectNearbyTarget(eventInfo.GetProcTarget()); + return _procTarget; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + if (eventInfo.GetDamageInfo()) + { + int32 damage = eventInfo.GetDamageInfo()->GetDamage(); + GetTarget()->CastCustomSpell(SPELL_ROGUE_BLADE_FLURRY_EXTRA_ATTACK, SPELLVALUE_BASE_POINT0, damage, _procTarget, true, NULL, aurEff); + } + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_rog_blade_flurry_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_rog_blade_flurry_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_MOD_MELEE_HASTE); + } + + private: + Unit* _procTarget; + }; + + AuraScript* GetAuraScript() const + { + return new spell_rog_blade_flurry_AuraScript(); + } }; // -31228 - Cheat Death @@ -347,6 +405,58 @@ class spell_rog_prey_on_the_weak : public SpellScriptLoader } }; +// -1943 - Rupture +class spell_rog_rupture : public SpellScriptLoader +{ + public: + spell_rog_rupture() : SpellScriptLoader("spell_rog_rupture") { } + + class spell_rog_rupture_AuraScript : public AuraScript + { + PrepareAuraScript(spell_rog_rupture_AuraScript); + + bool Load() + { + Unit* caster = GetCaster(); + return caster && caster->GetTypeId() == TYPEID_PLAYER; + } + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated) + { + if (Unit* caster = GetCaster()) + { + canBeRecalculated = false; + + float const attackpowerPerCombo[6] = + { + 0.0f, + 0.015f, // 1 point: ${($m1 + $b1*1 + 0.015 * $AP) * 4} damage over 8 secs + 0.024f, // 2 points: ${($m1 + $b1*2 + 0.024 * $AP) * 5} damage over 10 secs + 0.03f, // 3 points: ${($m1 + $b1*3 + 0.03 * $AP) * 6} damage over 12 secs + 0.03428571f, // 4 points: ${($m1 + $b1*4 + 0.03428571 * $AP) * 7} damage over 14 secs + 0.0375f // 5 points: ${($m1 + $b1*5 + 0.0375 * $AP) * 8} damage over 16 secs + }; + + uint8 cp = caster->ToPlayer()->GetComboPoints(); + if (cp > 5) + cp = 5; + + amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * attackpowerPerCombo[cp]); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_rog_rupture_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_rog_rupture_AuraScript(); + } +}; + // 5938 - Shiv class spell_rog_shiv : public SpellScriptLoader { @@ -388,12 +498,107 @@ class spell_rog_shiv : public SpellScriptLoader } }; +// 57934 - Tricks of the Trade +class spell_rog_tricks_of_the_trade : public SpellScriptLoader +{ + public: + spell_rog_tricks_of_the_trade() : SpellScriptLoader("spell_rog_tricks_of_the_trade") { } + + class spell_rog_tricks_of_the_trade_AuraScript : public AuraScript + { + PrepareAuraScript(spell_rog_tricks_of_the_trade_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_ROGUE_TRICKS_OF_THE_TRADE_DMG_BOOST)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_ROGUE_TRICKS_OF_THE_TRADE_PROC)) + return false; + return true; + } + + bool Load() + { + _redirectTarget = NULL; + return true; + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_DEFAULT) + GetTarget()->ResetRedirectThreat(); + } + + bool CheckProc(ProcEventInfo& /*eventInfo*/) + { + _redirectTarget = GetTarget()->GetRedirectThreatTarget(); + return _redirectTarget; + } + + void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + + Unit* target = GetTarget(); + target->CastSpell(_redirectTarget, SPELL_ROGUE_TRICKS_OF_THE_TRADE_DMG_BOOST, true); + target->CastSpell(target, SPELL_ROGUE_TRICKS_OF_THE_TRADE_PROC, true); + Remove(AURA_REMOVE_BY_DEFAULT); // maybe handle by proc charges + } + + void Register() + { + AfterEffectRemove += AuraEffectRemoveFn(spell_rog_tricks_of_the_trade_AuraScript::OnRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + DoCheckProc += AuraCheckProcFn(spell_rog_tricks_of_the_trade_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_rog_tricks_of_the_trade_AuraScript::HandleProc, EFFECT_1, SPELL_AURA_DUMMY); + } + + private: + Unit* _redirectTarget; + }; + + AuraScript* GetAuraScript() const + { + return new spell_rog_tricks_of_the_trade_AuraScript(); + } +}; + +// 59628 - Tricks of the Trade (Proc) +class spell_rog_tricks_of_the_trade_proc : public SpellScriptLoader +{ + public: + spell_rog_tricks_of_the_trade_proc() : SpellScriptLoader("spell_rog_tricks_of_the_trade_proc") { } + + class spell_rog_tricks_of_the_trade_proc_AuraScript : public AuraScript + { + PrepareAuraScript(spell_rog_tricks_of_the_trade_proc_AuraScript); + + void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->ResetRedirectThreat(); + } + + void Register() + { + AfterEffectRemove += AuraEffectRemoveFn(spell_rog_tricks_of_the_trade_proc_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_rog_tricks_of_the_trade_proc_AuraScript(); + } +}; + void AddSC_rogue_spell_scripts() { + new spell_rog_blade_flurry(); new spell_rog_cheat_death(); new spell_rog_deadly_poison(); new spell_rog_nerves_of_steel(); new spell_rog_preparation(); new spell_rog_prey_on_the_weak(); + new spell_rog_rupture(); new spell_rog_shiv(); + new spell_rog_tricks_of_the_trade(); + new spell_rog_tricks_of_the_trade_proc(); } diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp index 0d249953421..b69295150c2 100644 --- a/src/server/scripts/Spells/spell_shaman.cpp +++ b/src/server/scripts/Spells/spell_shaman.cpp @@ -33,11 +33,14 @@ enum ShamanSpells SPELL_SHAMAN_ANCESTRAL_AWAKENING_PROC = 52752, SPELL_SHAMAN_BIND_SIGHT = 6277, SPELL_SHAMAN_CLEANSING_TOTEM_EFFECT = 52025, + SPELL_SHAMAN_EARTH_SHIELD_HEAL = 379, SPELL_SHAMAN_EXHAUSTION = 57723, SPELL_SHAMAN_FIRE_NOVA_R1 = 1535, SPELL_SHAMAN_FIRE_NOVA_TRIGGERED_R1 = 8349, + SPELL_SHAMAN_GLYPH_OF_EARTH_SHIELD = 63279, SPELL_SHAMAN_GLYPH_OF_HEALING_STREAM_TOTEM = 55456, SPELL_SHAMAN_GLYPH_OF_MANA_TIDE = 55441, + SPELL_SHAMAN_GLYPH_OF_THUNDERSTORM = 62132, SPELL_SHAMAN_LAVA_FLOWS_R1 = 51480, SPELL_SHAMAN_LAVA_FLOWS_TRIGGERED_R1 = 64694, SPELL_SHAMAN_MANA_SPRING_TOTEM_ENERGIZE = 52032, @@ -265,6 +268,68 @@ class spell_sha_cleansing_totem_pulse : public SpellScriptLoader } }; +// -974 - Earth Shield +class spell_sha_earth_shield : public SpellScriptLoader +{ + public: + spell_sha_earth_shield() : SpellScriptLoader("spell_sha_earth_shield") { } + + class spell_sha_earth_shield_AuraScript : public AuraScript + { + PrepareAuraScript(spell_sha_earth_shield_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_EARTH_SHIELD_HEAL)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_GLYPH_OF_EARTH_SHIELD)) + return false; + return true; + } + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool & /*canBeRecalculated*/) + { + if (Unit* caster = GetCaster()) + { + amount = caster->SpellHealingBonusDone(GetUnitOwner(), GetSpellInfo(), amount, HEAL); + amount = GetUnitOwner()->SpellHealingBonusTaken(caster, GetSpellInfo(), amount, HEAL); + + // Glyph of Earth Shield + //! WORKAROUND + //! this glyphe is a proc + if (AuraEffect* glyphe = caster->GetAuraEffect(SPELL_SHAMAN_GLYPH_OF_EARTH_SHIELD, EFFECT_0)) + AddPct(amount, glyphe->GetAmount()); + } + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + + //! HACK due to currenct proc system implementation + if (Player* player = GetTarget()->ToPlayer()) + if (player->HasSpellCooldown(SPELL_SHAMAN_EARTH_SHIELD_HEAL)) + return; + + GetTarget()->CastCustomSpell(SPELL_SHAMAN_EARTH_SHIELD_HEAL, SPELLVALUE_BASE_POINT0, aurEff->GetAmount(), GetTarget(), true, NULL, aurEff, GetCasterGUID()); + + if (Player* player = GetTarget()->ToPlayer()) + player->AddSpellCooldown(SPELL_SHAMAN_EARTH_SHIELD_HEAL, 0, time(NULL) + 3); + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_sha_earth_shield_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_DUMMY); + OnEffectProc += AuraEffectProcFn(spell_sha_earth_shield_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_sha_earth_shield_AuraScript(); + } +}; + // 6474 - Earthbind Totem - Fix Talent: Earthen Power class spell_sha_earthbind_totem : public SpellScriptLoader { @@ -743,6 +808,35 @@ class spell_sha_sentry_totem : public SpellScriptLoader } }; +// -51490 - Thunderstorm +class spell_sha_thunderstorm : public SpellScriptLoader +{ + public: + spell_sha_thunderstorm() : SpellScriptLoader("spell_sha_thunderstorm") { } + + class spell_sha_thunderstorm_SpellScript : public SpellScript + { + PrepareSpellScript(spell_sha_thunderstorm_SpellScript); + + void HandleKnockBack(SpellEffIndex effIndex) + { + // Glyph of Thunderstorm + if (GetCaster()->HasAura(SPELL_SHAMAN_GLYPH_OF_THUNDERSTORM)) + PreventHitDefaultEffect(effIndex); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_sha_thunderstorm_SpellScript::HandleKnockBack, EFFECT_2, SPELL_EFFECT_KNOCK_BACK); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_sha_thunderstorm_SpellScript(); + } +}; + void AddSC_shaman_spell_scripts() { new spell_sha_ancestral_awakening_proc(); @@ -750,6 +844,7 @@ void AddSC_shaman_spell_scripts() new spell_sha_bloodlust(); new spell_sha_chain_heal(); new spell_sha_cleansing_totem_pulse(); + new spell_sha_earth_shield(); new spell_sha_earthbind_totem(); new spell_sha_earthen_power(); new spell_sha_fire_nova(); @@ -760,4 +855,5 @@ void AddSC_shaman_spell_scripts() new spell_sha_mana_spring_totem(); new spell_sha_mana_tide_totem(); new spell_sha_sentry_totem(); + new spell_sha_thunderstorm(); } diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp index 89c69733daf..78bfcbab6a0 100644 --- a/src/server/scripts/Spells/spell_warlock.cpp +++ b/src/server/scripts/Spells/spell_warlock.cpp @@ -37,6 +37,8 @@ enum WarlockSpells SPELL_WARLOCK_DEMONIC_EMPOWERMENT_FELGUARD = 54508, SPELL_WARLOCK_DEMONIC_EMPOWERMENT_FELHUNTER = 54509, SPELL_WARLOCK_DEMONIC_EMPOWERMENT_IMP = 54444, + SPELL_WARLOCK_FEL_SYNERGY_HEAL = 54181, + SPELL_WARLOCK_GLYPHE_OF_SIPHON_LIFE = 63106, SPELL_WARLOCK_IMPROVED_HEALTHSTONE_R1 = 18692, SPELL_WARLOCK_IMPROVED_HEALTHSTONE_R2 = 18693, SPELL_WARLOCK_IMPROVED_HEALTH_FUNNEL_R1 = 18703, @@ -48,6 +50,7 @@ enum WarlockSpells SPELL_WARLOCK_LIFE_TAP_ENERGIZE = 31818, SPELL_WARLOCK_LIFE_TAP_ENERGIZE_2 = 32553, SPELL_WARLOCK_SOULSHATTER = 32835, + SPELL_WARLOCK_SIPHON_LIFE_HEAL = 63106, SPELL_WARLOCK_UNSTABLE_AFFLICTION_DISPEL = 31117 }; @@ -418,6 +421,49 @@ class spell_warl_everlasting_affliction : public SpellScriptLoader } }; +// -47230 - Fel Synergy +class spell_warl_fel_synergy : public SpellScriptLoader +{ + public: + spell_warl_fel_synergy() : SpellScriptLoader("spell_warl_fel_synergy") { } + + class spell_warl_fel_synergy_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_fel_synergy_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_WARLOCK_FEL_SYNERGY_HEAL)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + return GetTarget()->GetGuardianPet() && eventInfo.GetDamageInfo()->GetDamage(); + } + + void OnProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + int32 heal = CalculatePct(int32(eventInfo.GetDamageInfo()->GetDamage()), aurEff->GetAmount()); + GetTarget()->CastCustomSpell(SPELL_WARLOCK_FEL_SYNERGY_HEAL, SPELLVALUE_BASE_POINT0, heal, (Unit*)NULL, true, NULL, aurEff); // TARGET_UNIT_PET + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_warl_fel_synergy_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_warl_fel_synergy_AuraScript::OnProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_warl_fel_synergy_AuraScript(); + } +}; + // -48181 - Haunt class spell_warl_haunt : public SpellScriptLoader { @@ -649,6 +695,92 @@ class spell_warl_seed_of_corruption : public SpellScriptLoader } }; +// -7235 - Shadow Ward +class spell_warl_shadow_ward : public SpellScriptLoader +{ + public: + spell_warl_shadow_ward() : SpellScriptLoader("spell_warl_shadow_ward") { } + + class spell_warl_shadow_ward_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_shadow_ward_AuraScript); + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated) + { + canBeRecalculated = false; + if (Unit* caster = GetCaster()) + { + // +80.68% from sp bonus + float bonus = 0.8068f; + + bonus *= caster->SpellBaseHealingBonusDone(GetSpellInfo()->GetSchoolMask()); + bonus *= caster->CalculateLevelPenalty(GetSpellInfo()); + + amount += int32(bonus); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_shadow_ward_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_warl_shadow_ward_AuraScript(); + } +}; + +// 63108 - Siphon Life +class spell_warl_siphon_life : public SpellScriptLoader +{ + public: + spell_warl_siphon_life() : SpellScriptLoader("spell_warl_siphon_life") { } + + class spell_warl_siphon_life_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_siphon_life_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_WARLOCK_SIPHON_LIFE_HEAL)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_WARLOCK_GLYPHE_OF_SIPHON_LIFE)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + return eventInfo.GetDamageInfo()->GetDamage(); + } + + void OnProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + int32 amount = int32(CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), aurEff->GetAmount())); + // Glyph of Siphon Life + if (AuraEffect const* glyphe = GetTarget()->GetAuraEffect(SPELL_WARLOCK_GLYPHE_OF_SIPHON_LIFE, EFFECT_0)) + AddPct(amount, glyphe->GetAmount()); + + GetTarget()->CastCustomSpell(SPELL_WARLOCK_SIPHON_LIFE_HEAL, SPELLVALUE_BASE_POINT0, amount, GetTarget(), true, NULL, aurEff); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_warl_siphon_life_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_warl_siphon_life_AuraScript::OnProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_warl_siphon_life_AuraScript(); + } +}; + // 29858 - Soulshatter class spell_warl_soulshatter : public SpellScriptLoader { @@ -737,11 +869,14 @@ void AddSC_warlock_spell_scripts() new spell_warl_demonic_circle_teleport(); new spell_warl_demonic_empowerment(); new spell_warl_everlasting_affliction(); + new spell_warl_fel_synergy(); new spell_warl_haunt(); new spell_warl_health_funnel(); new spell_warl_life_tap(); new spell_warl_ritual_of_doom_effect(); new spell_warl_seed_of_corruption(); + new spell_warl_shadow_ward(); + new spell_warl_siphon_life(); new spell_warl_soulshatter(); new spell_warl_unstable_affliction(); } diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp index f84265b89de..7136f046873 100644 --- a/src/server/scripts/Spells/spell_warrior.cpp +++ b/src/server/scripts/Spells/spell_warrior.cpp @@ -31,20 +31,26 @@ enum WarriorSpells SPELL_WARRIOR_BLOODTHIRST = 23885, SPELL_WARRIOR_BLOODTHIRST_DAMAGE = 23881, SPELL_WARRIOR_CHARGE = 34846, + SPELL_WARRIOR_DAMAGE_SHIELD_DAMAGE = 59653, SPELL_WARRIOR_DEEP_WOUNDS_RANK_1 = 12162, SPELL_WARRIOR_DEEP_WOUNDS_RANK_2 = 12850, SPELL_WARRIOR_DEEP_WOUNDS_RANK_3 = 12868, SPELL_WARRIOR_DEEP_WOUNDS_RANK_PERIODIC = 12721, SPELL_WARRIOR_EXECUTE = 20647, SPELL_WARRIOR_GLYPH_OF_EXECUTION = 58367, + SPELL_WARRIOR_GLYPH_OF_VIGILANCE = 63326, SPELL_WARRIOR_JUGGERNAUT_CRIT_BONUS_BUFF = 65156, SPELL_WARRIOR_JUGGERNAUT_CRIT_BONUS_TALENT = 64976, SPELL_WARRIOR_LAST_STAND_TRIGGERED = 12976, SPELL_WARRIOR_SLAM = 50783, + SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK = 26654, + SPELL_WARRIOR_TAUNT = 355, SPELL_WARRIOR_UNRELENTING_ASSAULT_RANK_1 = 46859, SPELL_WARRIOR_UNRELENTING_ASSAULT_RANK_2 = 46860, SPELL_WARRIOR_UNRELENTING_ASSAULT_TRIGGER_1 = 64849, SPELL_WARRIOR_UNRELENTING_ASSAULT_TRIGGER_2 = 64850, + SPELL_WARRIOR_VIGILANCE_PROC = 50725, + SPELL_WARRIOR_VIGILANCE_REDIRECT_THREAT = 59665, SPELL_PALADIN_BLESSING_OF_SANCTUARY = 20911, SPELL_PALADIN_GREATER_BLESSING_OF_SANCTUARY = 25899, @@ -194,6 +200,44 @@ class spell_warr_concussion_blow : public SpellScriptLoader } }; +// -58872 - Damage Shield +class spell_warr_damage_shield : public SpellScriptLoader +{ + public: + spell_warr_damage_shield() : SpellScriptLoader("spell_warr_damage_shield") { } + + class spell_warr_damage_shield_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warr_damage_shield_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_WARRIOR_DAMAGE_SHIELD_DAMAGE)) + return false; + return true; + } + + void OnProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + // % of amount blocked + int32 damage = CalculatePct(int32(GetTarget()->GetShieldBlockValue()), aurEff->GetAmount()); + GetTarget()->CastCustomSpell(SPELL_WARRIOR_DAMAGE_SHIELD_DAMAGE, SPELLVALUE_BASE_POINT0, damage, eventInfo.GetProcTarget(), true, NULL, aurEff); + } + + void Register() + { + OnEffectProc += AuraEffectProcFn(spell_warr_damage_shield_AuraScript::OnProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_warr_damage_shield_AuraScript(); + } +}; + // -12162 - Deep Wounds class spell_warr_deep_wounds : public SpellScriptLoader { @@ -333,6 +377,34 @@ class spell_warr_improved_spell_reflection : public SpellScriptLoader } }; +// 5246 - Intimidating Shout +class spell_warr_intimidating_shout : public SpellScriptLoader +{ + public: + spell_warr_intimidating_shout() : SpellScriptLoader("spell_warr_intimidating_shout") { } + + class spell_warr_intimidating_shout_SpellScript : public SpellScript + { + PrepareSpellScript(spell_warr_intimidating_shout_SpellScript); + + void FilterTargets(std::list<WorldObject*>& unitList) + { + unitList.remove(GetExplTargetWorldObject()); + } + + void Register() + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_warr_intimidating_shout_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_warr_intimidating_shout_SpellScript::FilterTargets, EFFECT_2, TARGET_UNIT_SRC_AREA_ENEMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_warr_intimidating_shout_SpellScript(); + } +}; + // 12975 - Last Stand class spell_warr_last_stand : public SpellScriptLoader { @@ -409,6 +481,83 @@ class spell_warr_overpower : public SpellScriptLoader } }; +// -772 - Rend +class spell_warr_rend : public SpellScriptLoader +{ + public: + spell_warr_rend() : SpellScriptLoader("spell_warr_rend") { } + + class spell_warr_rend_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warr_rend_AuraScript); + + void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& canBeRecalculated) + { + if (Unit* caster = GetCaster()) + { + canBeRecalculated = false; + + // $0.2 * (($MWB + $mwb) / 2 + $AP / 14 * $MWS) bonus per tick + float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK); + int32 mws = caster->GetAttackTime(BASE_ATTACK); + float mwbMin = caster->GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE); + float mwbMax = caster->GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE); + float mwb = ((mwbMin + mwbMax) / 2 + ap * mws / 14000) * 0.2f; + amount += int32(caster->ApplyEffectModifiers(GetSpellInfo(), aurEff->GetEffIndex(), mwb)); + + // "If used while your target is above 75% health, Rend does 35% more damage." + // as for 3.1.3 only ranks above 9 (wrong tooltip?) + if (GetSpellInfo()->GetRank() >= 9) + { + if (GetUnitOwner()->HasAuraState(AURA_STATE_HEALTH_ABOVE_75_PERCENT, GetSpellInfo(), caster)) + AddPct(amount, GetSpellInfo()->Effects[EFFECT_2].CalcValue(caster)); + } + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warr_rend_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_warr_rend_AuraScript(); + } +}; + +// 64380, 65941 - Shattering Throw +class spell_warr_shattering_throw : public SpellScriptLoader +{ + public: + spell_warr_shattering_throw() : SpellScriptLoader("spell_warr_shattering_throw") { } + + class spell_warr_shattering_throw_SpellScript : public SpellScript + { + PrepareSpellScript(spell_warr_shattering_throw_SpellScript); + + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + + // remove shields, will still display immune to damage part + if (Unit* target = GetHitUnit()) + target->RemoveAurasWithMechanic(1 << MECHANIC_IMMUNE_SHIELD, AURA_REMOVE_BY_ENEMY_SPELL); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_warr_shattering_throw_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_warr_shattering_throw_SpellScript(); + } +}; + // -1464 - Slam class spell_warr_slam : public SpellScriptLoader { @@ -445,6 +594,57 @@ class spell_warr_slam : public SpellScriptLoader } }; +// 12328, 18765, 35429 - Sweeping Strikes +class spell_warr_sweeping_strikes : public SpellScriptLoader +{ + public: + spell_warr_sweeping_strikes() : SpellScriptLoader("spell_warr_sweeping_strikes") { } + + class spell_warr_sweeping_strikes_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warr_sweeping_strikes_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK)) + return false; + return true; + } + + bool Load() + { + _procTarget = NULL; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + _procTarget = eventInfo.GetActor()->SelectNearbyTarget(eventInfo.GetProcTarget()); + return _procTarget; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + GetTarget()->CastSpell(_procTarget, SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK, true, NULL, aurEff); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_warr_sweeping_strikes_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_warr_sweeping_strikes_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + + private: + Unit* _procTarget; + }; + + AuraScript* GetAuraScript() const + { + return new spell_warr_sweeping_strikes_AuraScript(); + } +}; + // 50720 - Vigilance class spell_warr_vigilance : public SpellScriptLoader { @@ -457,34 +657,80 @@ class spell_warr_vigilance : public SpellScriptLoader bool Validate(SpellInfo const* /*spellInfo*/) { + if (!sSpellMgr->GetSpellInfo(SPELL_WARRIOR_GLYPH_OF_VIGILANCE)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_WARRIOR_VIGILANCE_PROC)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_WARRIOR_VIGILANCE_REDIRECT_THREAT)) + return false; if (!sSpellMgr->GetSpellInfo(SPELL_GEN_DAMAGE_REDUCTION_AURA)) return false; return true; } - void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + bool Load() + { + _procTarget = NULL; + return true; + } + + void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Unit* target = GetTarget(); + target->CastSpell(target, SPELL_GEN_DAMAGE_REDUCTION_AURA, true); + + if (Unit* caster = GetCaster()) + target->CastSpell(caster, SPELL_WARRIOR_VIGILANCE_REDIRECT_THREAT, true); + } + + void HandleAfterApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - if (Unit* target = GetTarget()) - target->CastSpell(target, SPELL_GEN_DAMAGE_REDUCTION_AURA, true); + //! WORKAROUND + //! this glyph is a proc + if (Unit* caster = GetCaster()) + { + if (AuraEffect const* glyph = caster->GetAuraEffect(SPELL_WARRIOR_GLYPH_OF_VIGILANCE, EFFECT_0)) + GetTarget()->ModifyRedirectThreat(glyph->GetAmount()); + } } - void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - if (Unit* target = GetTarget()) + Unit* target = GetTarget(); + if (target->HasAura(SPELL_GEN_DAMAGE_REDUCTION_AURA) && + !(target->HasAura(SPELL_PALADIN_BLESSING_OF_SANCTUARY) || + target->HasAura(SPELL_PALADIN_GREATER_BLESSING_OF_SANCTUARY) || + target->HasAura(SPELL_PRIEST_RENEWED_HOPE))) { - if (target->HasAura(SPELL_GEN_DAMAGE_REDUCTION_AURA) && !(target->HasAura(SPELL_PALADIN_BLESSING_OF_SANCTUARY) || - target->HasAura(SPELL_PALADIN_GREATER_BLESSING_OF_SANCTUARY) || - target->HasAura(SPELL_PRIEST_RENEWED_HOPE))) - target->RemoveAurasDueToSpell(SPELL_GEN_DAMAGE_REDUCTION_AURA); + target->RemoveAurasDueToSpell(SPELL_GEN_DAMAGE_REDUCTION_AURA); } + + target->ResetRedirectThreat(); + } + + bool CheckProc(ProcEventInfo& /*eventInfo*/) + { + _procTarget = GetCaster(); + return _procTarget; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + GetTarget()->CastSpell(_procTarget, SPELL_WARRIOR_VIGILANCE_PROC, true, NULL, aurEff); } void Register() { - OnEffectApply += AuraEffectApplyFn(spell_warr_vigilance_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); - OnEffectRemove += AuraEffectRemoveFn(spell_warr_vigilance_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + OnEffectApply += AuraEffectApplyFn(spell_warr_vigilance_AuraScript::HandleApply, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + AfterEffectApply += AuraEffectApplyFn(spell_warr_vigilance_AuraScript::HandleAfterApply, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + OnEffectRemove += AuraEffectRemoveFn(spell_warr_vigilance_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + DoCheckProc += AuraCheckProcFn(spell_warr_vigilance_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_warr_vigilance_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); } + private: + Unit* _procTarget; }; AuraScript* GetAuraScript() const @@ -493,17 +739,54 @@ class spell_warr_vigilance : public SpellScriptLoader } }; +// 50725 Vigilance +class spell_warr_vigilance_trigger : public SpellScriptLoader +{ + public: + spell_warr_vigilance_trigger() : SpellScriptLoader("spell_warr_vigilance_trigger") { } + + class spell_warr_vigilance_trigger_SpellScript : public SpellScript + { + PrepareSpellScript(spell_warr_vigilance_trigger_SpellScript); + + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + + // Remove Taunt cooldown + if (Player* target = GetHitPlayer()) + target->RemoveSpellCooldown(SPELL_WARRIOR_TAUNT, true); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_warr_vigilance_trigger_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_warr_vigilance_trigger_SpellScript(); + } +}; + void AddSC_warrior_spell_scripts() { new spell_warr_bloodthirst(); new spell_warr_bloodthirst_heal(); new spell_warr_charge(); new spell_warr_concussion_blow(); + new spell_warr_damage_shield(); new spell_warr_deep_wounds(); new spell_warr_execute(); new spell_warr_improved_spell_reflection(); + new spell_warr_intimidating_shout(); new spell_warr_last_stand(); new spell_warr_overpower(); + new spell_warr_rend(); + new spell_warr_shattering_throw(); new spell_warr_slam(); + new spell_warr_sweeping_strikes(); new spell_warr_vigilance(); + new spell_warr_vigilance_trigger(); } |
