diff options
Diffstat (limited to 'src/server/scripts')
35 files changed, 1979 insertions, 1330 deletions
diff --git a/src/server/scripts/Commands/cs_cheat.cpp b/src/server/scripts/Commands/cs_cheat.cpp index ade1b9fae02..4f503fdbb76 100644 --- a/src/server/scripts/Commands/cs_cheat.cpp +++ b/src/server/scripts/Commands/cs_cheat.cpp @@ -41,6 +41,7 @@ public: { "cooldown", SEC_GAMEMASTER, false, &HandleCoolDownCheatCommand, "", NULL }, { "power", SEC_GAMEMASTER, false, &HandlePowerCheatCommand, "", NULL }, { "waterwalk", SEC_GAMEMASTER, false, &HandleWaterWalkCheatCommand, "", NULL }, + { "status", SEC_GAMEMASTER, false, &HandleCheatStatusCommand, "", NULL }, { "taxi", SEC_GAMEMASTER, false, &HandleTaxiCheatCommand, "", NULL }, { "explore", SEC_GAMEMASTER, false, &HandleExploreCheatCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } @@ -159,6 +160,22 @@ public: return false; } + static bool HandleCheatStatusCommand(ChatHandler* handler, const char* /*args*/) + { + Player* player = handler->GetSession()->GetPlayer(); + + const char* enabled = "enabled"; + const char* disabled = "disabled"; + + handler->SendSysMessage(LANG_COMMAND_CHEAT_STATUS); + handler->PSendSysMessage(LANG_COMMAND_CHEAT_GOD, player->GetCommandStatus(CHEAT_GOD) ? enabled : disabled); + handler->PSendSysMessage(LANG_COMMAND_CHEAT_CD, player->GetCommandStatus(CHEAT_COOLDOWN) ? enabled : disabled); + handler->PSendSysMessage(LANG_COMMAND_CHEAT_CT, player->GetCommandStatus(CHEAT_CASTTIME) ? enabled : disabled); + handler->PSendSysMessage(LANG_COMMAND_CHEAT_POWER, player->GetCommandStatus(CHEAT_POWER) ? enabled : disabled); + handler->PSendSysMessage(LANG_COMMAND_CHEAT_WW, player->GetCommandStatus(CHEAT_WATERWALK) ? enabled : disabled); + return true; + } + static bool HandleWaterWalkCheatCommand(ChatHandler* handler, const char* args) { if (!handler->GetSession() && !handler->GetSession()->GetPlayer()) diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index fa4b0ce3957..2c9623b23a6 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. */ -
+ #include "Chat.h" #include "ScriptMgr.h" #include "AccountMgr.h" @@ -29,12 +29,12 @@ #include "TargetedMovementGenerator.h" #include "WeatherMgr.h" #include "ace/INET_Addr.h" -
+ class misc_commandscript : public CommandScript { public: misc_commandscript() : CommandScript("misc_commandscript") { } -
+ ChatCommand* GetCommands() const { static ChatCommand groupCommandTable[] = @@ -81,7 +81,7 @@ public: { "save", SEC_PLAYER, false, &HandleSaveCommand, "", NULL }, { "saveall", SEC_MODERATOR, true, &HandleSaveAllCommand, "", NULL }, { "kick", SEC_GAMEMASTER, true, &HandleKickPlayerCommand, "", NULL }, - { "start", SEC_PLAYER, false, &HandleStartCommand, "", NULL }, + { "unstuck", SEC_PLAYER, true, &HandleUnstuckCommand, "", NULL }, { "linkgrave", SEC_ADMINISTRATOR, false, &HandleLinkGraveCommand, "", NULL }, { "neargrave", SEC_ADMINISTRATOR, false, &HandleNearGraveCommand, "", NULL }, { "showarea", SEC_ADMINISTRATOR, false, &HandleShowAreaCommand, "", NULL }, @@ -117,7 +117,7 @@ public: }; return commandTable; } -
+ static bool HandleDevCommand(ChatHandler* handler, char const* args) { if (!*args) @@ -128,28 +128,28 @@ public: handler->GetSession()->SendNotification(LANG_DEV_OFF); return true; } -
+ std::string argstr = (char*)args; -
+ if (argstr == "on") { handler->GetSession()->GetPlayer()->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_DEVELOPER); handler->GetSession()->SendNotification(LANG_DEV_ON); return true; } -
+ if (argstr == "off") { handler->GetSession()->GetPlayer()->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_DEVELOPER); handler->GetSession()->SendNotification(LANG_DEV_OFF); return true; } -
+ handler->SendSysMessage(LANG_USE_BOL); handler->SetSentErrorMessage(true); return false; } -
+ static bool HandleGPSCommand(ChatHandler* handler, char const* args) { WorldObject* object = NULL; @@ -158,7 +158,7 @@ public: uint64 guid = handler->extractGuidFromLink((char*)args); if (guid) object = (WorldObject*)ObjectAccessor::GetObjectByTypeMask(*handler->GetSession()->GetPlayer(), guid, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT); -
+ if (!object) { handler->SendSysMessage(LANG_PLAYER_NOT_FOUND); @@ -169,7 +169,7 @@ public: else { object = handler->getSelectedUnit(); -
+ if (!object) { handler->SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); @@ -177,35 +177,35 @@ public: return false; } } -
+ CellCoord cellCoord = Trinity::ComputeCellCoord(object->GetPositionX(), object->GetPositionY()); Cell cell(cellCoord); -
+ uint32 zoneId, areaId; object->GetZoneAndAreaId(zoneId, areaId); -
+ MapEntry const* mapEntry = sMapStore.LookupEntry(object->GetMapId()); AreaTableEntry const* zoneEntry = GetAreaEntryByAreaID(zoneId); AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(areaId); -
+ float zoneX = object->GetPositionX(); float zoneY = object->GetPositionY(); -
+ Map2ZoneCoordinates(zoneX, zoneY, zoneId); -
+ Map const* map = object->GetMap(); float groundZ = map->GetHeight(object->GetPhaseMask(), object->GetPositionX(), object->GetPositionY(), MAX_HEIGHT); float floorZ = map->GetHeight(object->GetPhaseMask(), object->GetPositionX(), object->GetPositionY(), object->GetPositionZ()); -
+ GridCoord gridCoord = Trinity::ComputeGridCoord(object->GetPositionX(), object->GetPositionY()); -
+ // 63? WHY? int gridX = 63 - gridCoord.x_coord; int gridY = 63 - gridCoord.y_coord; -
+ uint32 haveMap = Map::ExistMap(object->GetMapId(), gridX, gridY) ? 1 : 0; uint32 haveVMap = Map::ExistVMap(object->GetMapId(), gridX, gridY) ? 1 : 0; -
+ if (haveVMap) { if (map->IsOutdoors(object->GetPositionX(), object->GetPositionY(), object->GetPositionZ())) @@ -215,7 +215,7 @@ public: } else handler->PSendSysMessage("no VMAP available for area info"); -
+ handler->PSendSysMessage(LANG_MAP_POSITION, object->GetMapId(), (mapEntry ? mapEntry->name[handler->GetSessionDbcLocale()] : "<unknown>"), zoneId, (zoneEntry ? zoneEntry->area_name[handler->GetSessionDbcLocale()] : "<unknown>"), @@ -224,16 +224,16 @@ public: object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), object->GetOrientation(), cell.GridX(), cell.GridY(), cell.CellX(), cell.CellY(), object->GetInstanceId(), zoneX, zoneY, groundZ, floorZ, haveMap, haveVMap); -
+ LiquidData liquidStatus; ZLiquidStatus status = map->getLiquidStatus(object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), MAP_ALL_LIQUIDS, &liquidStatus); -
+ if (status) handler->PSendSysMessage(LANG_LIQUID_STATUS, liquidStatus.level, liquidStatus.depth_level, liquidStatus.entry, liquidStatus.type_flags, status); -
+ return true; } -
+ static bool HandleAuraCommand(ChatHandler* handler, char const* args) { Unit* target = handler->getSelectedUnit(); @@ -243,16 +243,16 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form uint32 spellId = handler->extractSpellIdFromLink((char*)args); -
+ if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId)) Aura::TryRefreshStackOrCreate(spellInfo, MAX_EFFECT_MASK, target, target); -
+ return true; } -
+ static bool HandleUnAuraCommand(ChatHandler* handler, char const* args) { Unit* target = handler->getSelectedUnit(); @@ -262,21 +262,21 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ std::string argstr = args; if (argstr == "all") { target->RemoveAllAuras(); return true; } -
+ // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form uint32 spellId = handler->extractSpellIdFromLink((char*)args); if (!spellId) return false; -
+ target->RemoveAurasDueToSpell(spellId); -
+ return true; } // Teleport to Player @@ -287,7 +287,7 @@ public: std::string targetName; if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) return false; -
+ Player* _player = handler->GetSession()->GetPlayer(); if (target == _player || targetGuid == _player->GetGUID()) { @@ -295,15 +295,15 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ if (target) { // check online security if (handler->HasLowerSecurity(target, 0)) return false; -
+ std::string chrNameLink = handler->playerLink(targetName); -
+ Map* map = target->GetMap(); if (map->IsBattlegroundOrArena()) { @@ -317,7 +317,7 @@ public: // if both players are in different bgs else if (_player->GetBattlegroundId() && _player->GetBattlegroundId() != target->GetBattlegroundId()) _player->LeaveBattleground(false); // Note: should be changed so _player gets no Deserter debuff -
+ // all's well, set bg id // when porting out from the bg, it will be reset to 0 _player->SetBattlegroundId(target->GetBattlegroundId(), target->GetBattlegroundTypeId()); @@ -350,7 +350,7 @@ public: return false; } } -
+ // if the player or the player's group is bound to another instance // the player will not be bound to another one InstancePlayerBind* bind = _player->GetBoundInstance(target->GetMapId(), target->GetDifficulty(map->IsRaid())); @@ -363,15 +363,15 @@ public: if (InstanceSave* save = sInstanceSaveMgr->GetInstanceSave(target->GetInstanceId())) _player->BindToInstance(save, !save->CanReset()); } -
+ if (map->IsRaid()) _player->SetRaidDifficulty(target->GetRaidDifficulty()); else _player->SetDungeonDifficulty(target->GetDungeonDifficulty()); } -
+ handler->PSendSysMessage(LANG_APPEARING_AT, chrNameLink.c_str()); -
+ // stop flight if need if (_player->isInFlight()) { @@ -381,11 +381,11 @@ public: // save only in non-flight case else _player->SaveRecallPosition(); -
+ // to point to see at target with same orientation float x, y, z; target->GetContactPoint(_player, x, y, z); -
+ _player->TeleportTo(target->GetMapId(), x, y, z, _player->GetAngle(target), TELE_TO_GM_MODE); _player->SetPhaseMask(target->GetPhaseMask(), true); } @@ -394,18 +394,18 @@ public: // check offline security if (handler->HasLowerSecurity(NULL, targetGuid)) return false; -
+ std::string nameLink = handler->playerLink(targetName); -
+ handler->PSendSysMessage(LANG_APPEARING_AT, nameLink.c_str()); -
+ // to point where player stay (if loaded) float x, y, z, o; uint32 map; bool in_flight; if (!Player::LoadPositionFromDB(map, x, y, z, o, in_flight, targetGuid)) return false; -
+ // stop flight if need if (_player->isInFlight()) { @@ -415,10 +415,10 @@ public: // save only in non-flight case else _player->SaveRecallPosition(); -
+ _player->TeleportTo(map, x, y, z, _player->GetOrientation()); } -
+ return true; } // Summon Player @@ -429,7 +429,7 @@ public: std::string targetName; if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) return false; -
+ Player* _player = handler->GetSession()->GetPlayer(); if (target == _player || targetGuid == _player->GetGUID()) { @@ -437,23 +437,23 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ if (target) { std::string nameLink = handler->playerLink(targetName); // check online security if (handler->HasLowerSecurity(target, 0)) return false; -
+ if (target->IsBeingTeleported()) { handler->PSendSysMessage(LANG_IS_TELEPORTED, nameLink.c_str()); handler->SetSentErrorMessage(true); return false; } -
+ Map* map = handler->GetSession()->GetPlayer()->GetMap(); -
+ if (map->IsBattlegroundOrArena()) { // only allow if gm mode is on @@ -466,7 +466,7 @@ public: // if both players are in different bgs else if (target->GetBattlegroundId() && handler->GetSession()->GetPlayer()->GetBattlegroundId() != target->GetBattlegroundId()) target->LeaveBattleground(false); // Note: should be changed so target gets no Deserter debuff -
+ // all's well, set bg id // when porting out from the bg, it will be reset to 0 target->SetBattlegroundId(handler->GetSession()->GetPlayer()->GetBattlegroundId(), handler->GetSession()->GetPlayer()->GetBattlegroundTypeId()); @@ -477,10 +477,10 @@ public: else if (map->IsDungeon()) { Map* map = target->GetMap(); -
+ if (map->Instanceable() && map->GetInstanceId() != map->GetInstanceId()) target->UnbindInstance(map->GetInstanceId(), target->GetDungeonDifficulty(), true); -
+ // we are in instance, and can summon only player in our group with us as lead if (!handler->GetSession()->GetPlayer()->GetGroup() || !target->GetGroup() || (target->GetGroup()->GetLeaderGUID() != handler->GetSession()->GetPlayer()->GetGUID()) || @@ -492,11 +492,11 @@ public: return false; } } -
+ handler->PSendSysMessage(LANG_SUMMONING, nameLink.c_str(), ""); if (handler->needReportToTarget(target)) ChatHandler(target).PSendSysMessage(LANG_SUMMONED_BY, handler->playerLink(_player->GetName()).c_str()); -
+ // stop flight if need if (target->isInFlight()) { @@ -506,7 +506,7 @@ public: // save only in non-flight case else target->SaveRecallPosition(); -
+ // before GM float x, y, z; handler->GetSession()->GetPlayer()->GetClosePoint(x, y, z, target->GetObjectSize()); @@ -518,11 +518,11 @@ public: // check offline security if (handler->HasLowerSecurity(NULL, targetGuid)) return false; -
+ std::string nameLink = handler->playerLink(targetName); -
+ handler->PSendSysMessage(LANG_SUMMONING, nameLink.c_str(), handler->GetTrinityString(LANG_OFFLINE)); -
+ // in point where GM stay Player::SavePositionInDB(handler->GetSession()->GetPlayer()->GetMapId(), handler->GetSession()->GetPlayer()->GetPositionX(), @@ -532,7 +532,7 @@ public: handler->GetSession()->GetPlayer()->GetZoneId(), targetGuid); } -
+ return true; } // Summon group of player @@ -541,25 +541,25 @@ public: Player* target; if (!handler->extractPlayerTarget((char*)args, &target)) return false; -
+ // check online security if (handler->HasLowerSecurity(target, 0)) return false; -
+ Group* group = target->GetGroup(); -
+ std::string nameLink = handler->GetNameLink(target); -
+ if (!group) { handler->PSendSysMessage(LANG_NOT_IN_GROUP, nameLink.c_str()); handler->SetSentErrorMessage(true); return false; } -
+ Map* gmMap = handler->GetSession()->GetPlayer()->GetMap(); bool toInstance = gmMap->Instanceable(); -
+ // we are in instance, and can summon only player in our group with us as lead if (toInstance && ( !handler->GetSession()->GetPlayer()->GetGroup() || (group->GetLeaderGUID() != handler->GetSession()->GetPlayer()->GetGUID()) || @@ -570,31 +570,31 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* player = itr->getSource(); -
+ if (!player || player == handler->GetSession()->GetPlayer() || !player->GetSession()) continue; -
+ // check online security if (handler->HasLowerSecurity(player, 0)) return false; -
+ std::string plNameLink = handler->GetNameLink(player); -
+ if (player->IsBeingTeleported() == true) { handler->PSendSysMessage(LANG_IS_TELEPORTED, plNameLink.c_str()); handler->SetSentErrorMessage(true); return false; } -
+ if (toInstance) { Map* playerMap = player->GetMap(); -
+ if (playerMap->Instanceable() && playerMap->GetInstanceId() != gmMap->GetInstanceId()) { // cannot summon from instance to instance @@ -603,11 +603,11 @@ public: return false; } } -
+ handler->PSendSysMessage(LANG_SUMMONING, plNameLink.c_str(), ""); if (handler->needReportToTarget(player)) ChatHandler(player).PSendSysMessage(LANG_SUMMONED_BY, handler->GetNameLink().c_str()); -
+ // stop flight if need if (player->isInFlight()) { @@ -617,39 +617,39 @@ public: // save only in non-flight case else player->SaveRecallPosition(); -
+ // before GM float x, y, z; handler->GetSession()->GetPlayer()->GetClosePoint(x, y, z, player->GetObjectSize()); player->TeleportTo(handler->GetSession()->GetPlayer()->GetMapId(), x, y, z, player->GetOrientation()); } -
+ return true; } -
+ static bool HandleCommandsCommand(ChatHandler* handler, char const* /*args*/) { handler->ShowHelpForCommand(handler->getCommandTable(), ""); return true; } -
+ static bool HandleDieCommand(ChatHandler* handler, char const* /*args*/) { Unit* target = handler->getSelectedUnit(); -
+ if (!target || !handler->GetSession()->GetPlayer()->GetSelection()) { handler->SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); handler->SetSentErrorMessage(true); return false; } -
+ if (target->GetTypeId() == TYPEID_PLAYER) { if (handler->HasLowerSecurity((Player*)target, 0, false)) return false; } -
+ if (target->isAlive()) { if (sWorld->getBoolConfig(CONFIG_DIE_COMMAND_MODE)) @@ -657,17 +657,17 @@ public: else handler->GetSession()->GetPlayer()->DealDamage(target, target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); } -
+ return true; } -
+ static bool HandleReviveCommand(ChatHandler* handler, char const* args) { Player* target; uint64 targetGuid; if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid)) return false; -
+ if (target) { target->ResurrectPlayer(!AccountMgr::IsPlayerAccount(target->GetSession()->GetSecurity()) ? 1.0f : 0.5f); @@ -677,14 +677,14 @@ public: else // will resurrected at login without corpse sObjectAccessor->ConvertCorpseForPlayer(targetGuid); -
+ return true; } -
+ static bool HandleDismountCommand(ChatHandler* handler, char const* /*args*/) { Player* player = handler->GetSession()->GetPlayer(); -
+ // If player is not mounted, so go out :) if (!player->IsMounted()) { @@ -692,34 +692,34 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ if (player->isInFlight()) { handler->SendSysMessage(LANG_YOU_IN_FLIGHT); handler->SetSentErrorMessage(true); return false; } -
+ player->Dismount(); player->RemoveAurasByType(SPELL_AURA_MOUNTED); return true; } -
+ static bool HandleGUIDCommand(ChatHandler* handler, char const* /*args*/) { uint64 guid = handler->GetSession()->GetPlayer()->GetSelection(); -
+ if (guid == 0) { handler->SendSysMessage(LANG_NO_SELECTION); handler->SetSentErrorMessage(true); return false; } -
+ handler->PSendSysMessage(LANG_OBJECT_GUID, GUID_LOPART(guid), GUID_HIPART(guid)); return true; } -
+ static bool HandleHelpCommand(ChatHandler* handler, char const* args) { char const* cmd = strtok((char*)args, " "); @@ -733,7 +733,7 @@ public: if (!handler->ShowHelpForCommand(handler->getCommandTable(), cmd)) handler->SendSysMessage(LANG_NO_HELP_CMD); } -
+ return true; } // move item to other slot @@ -741,35 +741,35 @@ public: { if (!*args) return false; -
+ char const* param1 = strtok((char*)args, " "); if (!param1) return false; -
+ char const* param2 = strtok(NULL, " "); if (!param2) return false; -
+ uint8 srcSlot = uint8(atoi(param1)); uint8 dstSlot = uint8(atoi(param2)); -
+ if (srcSlot == dstSlot) return true; -
+ if (!handler->GetSession()->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0, srcSlot, true)) return false; -
+ if (!handler->GetSession()->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0, dstSlot, false)) return false; -
+ uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcSlot); uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstSlot); -
+ handler->GetSession()->GetPlayer()->SwapItem(src, dst); -
+ return true; } -
+ static bool HandleCooldownCommand(ChatHandler* handler, char const* args) { Player* target = handler->getSelectedPlayer(); @@ -779,9 +779,9 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ std::string nameLink = handler->GetNameLink(target); -
+ if (!*args) { target->RemoveAllSpellCooldown(); @@ -793,30 +793,30 @@ public: uint32 spellIid = handler->extractSpellIdFromLink((char*)args); if (!spellIid) return false; -
+ if (!sSpellMgr->GetSpellInfo(spellIid)) { handler->PSendSysMessage(LANG_UNKNOWN_SPELL, target == handler->GetSession()->GetPlayer() ? handler->GetTrinityString(LANG_YOU) : nameLink.c_str()); handler->SetSentErrorMessage(true); return false; } -
+ target->RemoveSpellCooldown(spellIid, true); handler->PSendSysMessage(LANG_REMOVE_COOLDOWN, spellIid, target == handler->GetSession()->GetPlayer() ? handler->GetTrinityString(LANG_YOU) : nameLink.c_str()); } return true; } -
+ static bool HandleGetDistanceCommand(ChatHandler* handler, char const* args) { WorldObject* obj = NULL; -
+ if (*args) { uint64 guid = handler->extractGuidFromLink((char*)args); if (guid) obj = (WorldObject*)ObjectAccessor::GetObjectByTypeMask(*handler->GetSession()->GetPlayer(), guid, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); -
+ if (!obj) { handler->SendSysMessage(LANG_PLAYER_NOT_FOUND); @@ -827,7 +827,7 @@ public: else { obj = handler->getSelectedUnit(); -
+ if (!obj) { handler->SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); @@ -835,7 +835,7 @@ public: return false; } } -
+ handler->PSendSysMessage(LANG_DISTANCE, handler->GetSession()->GetPlayer()->GetDistance(obj), handler->GetSession()->GetPlayer()->GetDistance2d(obj), handler->GetSession()->GetPlayer()->GetExactDist(obj), handler->GetSession()->GetPlayer()->GetExactDist2d(obj)); return true; } @@ -845,33 +845,33 @@ public: Player* target; if (!handler->extractPlayerTarget((char*)args, &target)) return false; -
+ // check online security if (handler->HasLowerSecurity(target, 0)) return false; -
+ if (target->IsBeingTeleported()) { handler->PSendSysMessage(LANG_IS_TELEPORTED, handler->GetNameLink(target).c_str()); handler->SetSentErrorMessage(true); return false; } -
+ // stop flight if need if (target->isInFlight()) { target->GetMotionMaster()->MovementExpired(); target->CleanupAfterTaxiFlight(); } -
+ target->TeleportTo(target->m_recallMap, target->m_recallX, target->m_recallY, target->m_recallZ, target->m_recallO); return true; } -
+ static bool HandleSaveCommand(ChatHandler* handler, char const* /*args*/) { Player* player = handler->GetSession()->GetPlayer(); -
+ // save GM account without delay and output message if (!AccountMgr::IsPlayerAccount(handler->GetSession()->GetSecurity())) { @@ -882,15 +882,15 @@ public: handler->SendSysMessage(LANG_PLAYER_SAVED); return true; } -
+ // save if the player has last been saved over 20 seconds ago uint32 saveInterval = sWorld->getIntConfig(CONFIG_INTERVAL_SAVE); if (saveInterval == 0 || (saveInterval > 20 * IN_MILLISECONDS && player->GetSaveTimer() <= saveInterval - 20 * IN_MILLISECONDS)) player->SaveToDB(); -
+ return true; } -
+ // Save all players in the world static bool HandleSaveAllCommand(ChatHandler* handler, char const* /*args*/) { @@ -898,7 +898,7 @@ public: handler->SendSysMessage(LANG_PLAYERS_SAVED); return true; } -
+ // kick player static bool HandleKickPlayerCommand(ChatHandler* handler, char const* args) { @@ -906,73 +906,106 @@ public: std::string playerName; if (!handler->extractPlayerTarget((char*)args, &target, NULL, &playerName)) return false; -
+ if (handler->GetSession() && target == handler->GetSession()->GetPlayer()) { handler->SendSysMessage(LANG_COMMAND_KICKSELF); handler->SetSentErrorMessage(true); return false; } -
+ // check online security if (handler->HasLowerSecurity(target, 0)) return false; -
+ if (sWorld->getBoolConfig(CONFIG_SHOW_KICK_IN_WORLD)) sWorld->SendWorldText(LANG_COMMAND_KICKMESSAGE, playerName.c_str()); else handler->PSendSysMessage(LANG_COMMAND_KICKMESSAGE, playerName.c_str()); -
+ target->GetSession()->KickPlayer(); -
+ return true; } -
- static bool HandleStartCommand(ChatHandler* handler, char const* /*args*/) + + static bool HandleUnstuckCommand(ChatHandler* handler, char const* args) { - Player* player = handler->GetSession()->GetPlayer(); -
- if (player->isInFlight()) + //No args required for players + if (handler->GetSession() && AccountMgr::IsPlayerAccount(handler->GetSession()->GetSecurity())) { - handler->SendSysMessage(LANG_YOU_IN_FLIGHT); - handler->SetSentErrorMessage(true); - return false; + Player* player = handler->GetSession()->GetPlayer(); + if (player->isInFlight() || player->isInCombat()) + { + handler->SendSysMessage(LANG_CANT_DO_NOW); + handler->SetSentErrorMessage(true); + return false; + } + + //7355: "Stuck" + player->CastSpell(player, 7355, false); + return true; } -
- if (player->isInCombat()) + + if (!*args) + return false; + + char* player_str = strtok((char*)args, " "); + if (!player_str) + return false; + + std::string location_str = "inn"; + if (char const* loc = strtok(NULL, " ")) + location_str = loc; + + Player* player = NULL; + if (!handler->extractPlayerTarget(player_str, &player)) + return false; + + if (player->isInFlight() || player->isInCombat()) { - handler->SendSysMessage(LANG_YOU_IN_COMBAT); + handler->SendSysMessage(LANG_CANT_DO_NOW); handler->SetSentErrorMessage(true); return false; } -
- if (player->isDead() || player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) + + if (location_str == "inn") + { + player->TeleportTo(player->m_homebindMapId, player->m_homebindX, player->m_homebindY, player->m_homebindZ, player->GetOrientation()); + return true; + } + + if (location_str == "graveyard") { - // if player is dead and stuck, send ghost to graveyard player->RepopAtGraveyard(); return true; } -
- // cast spell Stuck - player->CastSpell(player, 7355, false); - return true; + + if (location_str == "startzone") + { + player->TeleportTo(player->GetStartPosition()); + return true; + } + + //Not a supported argument + return false; + } -
+ static bool HandleLinkGraveCommand(ChatHandler* handler, char const* args) { if (!*args) return false; -
+ char* px = strtok((char*)args, " "); if (!px) return false; -
+ uint32 graveyardId = uint32(atoi(px)); -
+ uint32 team; -
+ char* px2 = strtok(NULL, " "); -
+ if (!px2) team = 0; else if (strncmp(px2, "horde", 6) == 0) @@ -981,20 +1014,20 @@ public: team = ALLIANCE; else return false; -
+ WorldSafeLocsEntry const* graveyard = sWorldSafeLocsStore.LookupEntry(graveyardId); -
+ if (!graveyard) { handler->PSendSysMessage(LANG_COMMAND_GRAVEYARDNOEXIST, graveyardId); handler->SetSentErrorMessage(true); return false; } -
+ Player* player = handler->GetSession()->GetPlayer(); -
+ uint32 zoneId = player->GetZoneId(); -
+ AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(zoneId); if (!areaEntry || areaEntry->zone !=0) { @@ -1002,21 +1035,21 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ if (sObjectMgr->AddGraveYardLink(graveyardId, zoneId, team)) handler->PSendSysMessage(LANG_COMMAND_GRAVEYARDLINKED, graveyardId, zoneId); else handler->PSendSysMessage(LANG_COMMAND_GRAVEYARDALRLINKED, graveyardId, zoneId); -
+ return true; } -
+ static bool HandleNearGraveCommand(ChatHandler* handler, char const* args) { uint32 team; -
+ size_t argStr = strlen(args); -
+ if (!*args) team = 0; else if (strncmp((char*)args, "horde", argStr) == 0) @@ -1025,17 +1058,17 @@ public: team = ALLIANCE; else return false; -
+ Player* player = handler->GetSession()->GetPlayer(); uint32 zone_id = player->GetZoneId(); -
+ WorldSafeLocsEntry const* graveyard = sObjectMgr->GetClosestGraveYard( player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetMapId(), team); -
+ if (graveyard) { uint32 graveyardId = graveyard->ID; -
+ GraveYardData const* data = sObjectMgr->FindGraveYardData(graveyardId, zone_id); if (!data) { @@ -1043,45 +1076,45 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ team = data->team; -
+ std::string team_name = handler->GetTrinityString(LANG_COMMAND_GRAVEYARD_NOTEAM); -
+ if (team == 0) team_name = handler->GetTrinityString(LANG_COMMAND_GRAVEYARD_ANY); else if (team == HORDE) team_name = handler->GetTrinityString(LANG_COMMAND_GRAVEYARD_HORDE); else if (team == ALLIANCE) team_name = handler->GetTrinityString(LANG_COMMAND_GRAVEYARD_ALLIANCE); -
+ handler->PSendSysMessage(LANG_COMMAND_GRAVEYARDNEAREST, graveyardId, team_name.c_str(), zone_id); } else { std::string team_name; -
+ if (team == 0) team_name = handler->GetTrinityString(LANG_COMMAND_GRAVEYARD_ANY); else if (team == HORDE) team_name = handler->GetTrinityString(LANG_COMMAND_GRAVEYARD_HORDE); else if (team == ALLIANCE) team_name = handler->GetTrinityString(LANG_COMMAND_GRAVEYARD_ALLIANCE); -
+ if (team == ~uint32(0)) handler->PSendSysMessage(LANG_COMMAND_ZONENOGRAVEYARDS, zone_id); else handler->PSendSysMessage(LANG_COMMAND_ZONENOGRAFACTION, zone_id, team_name.c_str()); } -
+ return true; } -
+ static bool HandleShowAreaCommand(ChatHandler* handler, char const* args) { if (!*args) return false; -
+ Player* playerTarget = handler->getSelectedPlayer(); if (!playerTarget) { @@ -1089,30 +1122,30 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ int32 area = GetAreaFlagByAreaID(atoi((char*)args)); int32 offset = area / 32; uint32 val = uint32((1 << (area % 32))); -
+ if (area<0 || offset >= PLAYER_EXPLORED_ZONES_SIZE) { handler->SendSysMessage(LANG_BAD_VALUE); handler->SetSentErrorMessage(true); return false; } -
+ uint32 currFields = playerTarget->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset); playerTarget->SetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset, uint32((currFields | val))); -
+ handler->SendSysMessage(LANG_EXPLORE_AREA); return true; } -
+ static bool HandleHideAreaCommand(ChatHandler* handler, char const* args) { if (!*args) return false; -
+ Player* playerTarget = handler->getSelectedPlayer(); if (!playerTarget) { @@ -1120,45 +1153,45 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ int32 area = GetAreaFlagByAreaID(atoi((char*)args)); int32 offset = area / 32; uint32 val = uint32((1 << (area % 32))); -
+ if (area < 0 || offset >= PLAYER_EXPLORED_ZONES_SIZE) { handler->SendSysMessage(LANG_BAD_VALUE); handler->SetSentErrorMessage(true); return false; } -
+ uint32 currFields = playerTarget->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset); playerTarget->SetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset, uint32((currFields ^ val))); -
+ handler->SendSysMessage(LANG_UNEXPLORE_AREA); return true; } -
+ static bool HandleAddItemCommand(ChatHandler* handler, char const* args) { if (!*args) return false; -
+ uint32 itemId = 0; -
+ if (args[0] == '[') // [name] manual form { char const* itemNameStr = strtok((char*)args, "]"); -
+ if (itemNameStr && itemNameStr[0]) { std::string itemName = itemNameStr+1; WorldDatabase.EscapeString(itemName); -
+ PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_ITEM_TEMPLATE_BY_NAME); stmt->setString(0, itemName); PreparedQueryResult result = WorldDatabase.Query(stmt); -
+ if (!result) { handler->PSendSysMessage(LANG_COMMAND_COULDNOTFIND, itemNameStr+1); @@ -1177,24 +1210,24 @@ public: return false; itemId = uint32(atol(id)); } -
+ char const* ccount = strtok(NULL, " "); -
+ int32 count = 1; -
+ if (ccount) count = strtol(ccount, NULL, 10); -
+ if (count == 0) count = 1; -
+ Player* player = handler->GetSession()->GetPlayer(); Player* playerTarget = handler->getSelectedPlayer(); if (!playerTarget) playerTarget = player; -
+ sLog->outDebug(LOG_FILTER_GENERAL, handler->GetTrinityString(LANG_ADDITEM), itemId, count); -
+ ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemId); if (!itemTemplate) { @@ -1202,7 +1235,7 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ // Subtract if (count < 0) { @@ -1210,55 +1243,55 @@ public: handler->PSendSysMessage(LANG_REMOVEITEM, itemId, -count, handler->GetNameLink(playerTarget).c_str()); return true; } -
+ // Adding items uint32 noSpaceForCount = 0; -
+ // check space and find places ItemPosCountVec dest; InventoryResult msg = playerTarget->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemId, count, &noSpaceForCount); if (msg != EQUIP_ERR_OK) // convert to possible store amount count -= noSpaceForCount; -
+ if (count == 0 || dest.empty()) // can't add any { handler->PSendSysMessage(LANG_ITEM_CANNOT_CREATE, itemId, noSpaceForCount); handler->SetSentErrorMessage(true); return false; } -
+ Item* item = playerTarget->StoreNewItem(dest, itemId, true, Item::GenerateItemRandomPropertyId(itemId)); -
+ // remove binding (let GM give it to another player later) if (player == playerTarget) for (ItemPosCountVec::const_iterator itr = dest.begin(); itr != dest.end(); ++itr) if (Item* item1 = player->GetItemByPos(itr->pos)) item1->SetBinding(false); -
+ if (count > 0 && item) { player->SendNewItem(item, count, false, true); if (player != playerTarget) playerTarget->SendNewItem(item, count, true, false); } -
+ if (noSpaceForCount > 0) handler->PSendSysMessage(LANG_ITEM_CANNOT_CREATE, itemId, noSpaceForCount); -
+ return true; } -
+ static bool HandleAddItemSetCommand(ChatHandler* handler, char const* args) { if (!*args) return false; -
+ char const* id = handler->extractKeyFromLink((char*)args, "Hitemset"); // number or [name] Shift-click form |color|Hitemset:itemset_id|h[name]|h|r if (!id) return false; -
+ uint32 itemSetId = atol(id); -
+ // prevent generation all items with itemset field value '0' if (itemSetId == 0) { @@ -1266,14 +1299,14 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ Player* player = handler->GetSession()->GetPlayer(); Player* playerTarget = handler->getSelectedPlayer(); if (!playerTarget) playerTarget = player; -
+ sLog->outDebug(LOG_FILTER_GENERAL, handler->GetTrinityString(LANG_ADDITEMSET), itemSetId); -
+ bool found = false; ItemTemplateContainer const* its = sObjectMgr->GetItemTemplateStore(); for (ItemTemplateContainer::const_iterator itr = its->begin(); itr != its->end(); ++itr) @@ -1286,11 +1319,11 @@ public: if (msg == EQUIP_ERR_OK) { Item* item = playerTarget->StoreNewItem(dest, itr->second.ItemId, true); -
+ // remove binding (let GM give it to another player later) if (player == playerTarget) item->SetBinding(false); -
+ player->SendNewItem(item, 1, false, true); if (player != playerTarget) playerTarget->SendNewItem(item, 1, true, false); @@ -1302,28 +1335,28 @@ public: } } } -
+ if (!found) { handler->PSendSysMessage(LANG_NO_ITEMS_FROM_ITEMSET_FOUND, itemSetId); handler->SetSentErrorMessage(true); return false; } -
+ return true; } -
+ static bool HandleBankCommand(ChatHandler* handler, char const* /*args*/) { handler->GetSession()->SendShowBank(handler->GetSession()->GetPlayer()->GetGUID()); return true; } -
+ static bool HandleChangeWeather(ChatHandler* handler, char const* args) { if (!*args) return false; -
+ // Weather is OFF if (!sWorld->getBoolConfig(CONFIG_WEATHER)) { @@ -1331,22 +1364,22 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ // *Change the weather of a cell char const* px = strtok((char*)args, " "); char const* py = strtok(NULL, " "); -
+ if (!px || !py) return false; -
+ uint32 type = uint32(atoi(px)); //0 to 3, 0: fine, 1: rain, 2: snow, 3: sand float grade = float(atof(py)); //0 to 1, sending -1 is instand good weather -
+ Player* player = handler->GetSession()->GetPlayer(); uint32 zoneid = player->GetZoneId(); -
+ Weather* weather = WeatherMgr::FindWeather(zoneid); -
+ if (!weather) weather = WeatherMgr::AddWeather(zoneid); if (!weather) @@ -1355,12 +1388,12 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ weather->SetWeather(WeatherType(type), grade); -
+ return true; } -
+ static bool HandleMaxSkillCommand(ChatHandler* handler, char const* /*args*/) { @@ -1371,25 +1404,25 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ // each skills that have max skill value dependent from level seted to current level max skill value SelectedPlayer->UpdateSkillsToMaxSkillsForLevel(); return true; } -
+ static bool HandleSetSkillCommand(ChatHandler* handler, char const* args) { // number or [name] Shift-click form |color|Hskill:skill_id|h[name]|h|r char const* skillStr = handler->extractKeyFromLink((char*)args, "Hskill"); if (!skillStr) return false; -
+ char const* levelStr = strtok(NULL, " "); if (!levelStr) return false; -
+ char const* maxPureSkill = strtok(NULL, " "); -
+ int32 skill = atoi(skillStr); if (skill <= 0) { @@ -1397,9 +1430,9 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ int32 level = uint32(atol(levelStr)); -
+ Player* target = handler->getSelectedPlayer(); if (!target) { @@ -1407,7 +1440,7 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ SkillLineEntry const* skillLine = sSkillLineStore.LookupEntry(skill); if (!skillLine) { @@ -1415,24 +1448,24 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ std::string tNameLink = handler->GetNameLink(target); -
+ if (!target->GetSkillValue(skill)) { handler->PSendSysMessage(LANG_SET_SKILL_ERROR, tNameLink.c_str(), skill, skillLine->name[handler->GetSessionDbcLocale()]); handler->SetSentErrorMessage(true); return false; } -
+ uint16 max = maxPureSkill ? atol (maxPureSkill) : target->GetPureMaxSkillValue(skill); -
+ if (level <= 0 || level > max || max <= 0) return false; -
+ target->SetSkill(skill, target->GetSkillStep(skill), level, max); handler->PSendSysMessage(LANG_SET_SKILL, skill, skillLine->name[handler->GetSessionDbcLocale()], tNameLink.c_str(), level, max); -
+ return true; } // show info of player @@ -1441,9 +1474,9 @@ public: Player* target; uint64 targetGuid; std::string targetName; -
+ uint32 parseGUID = MAKE_NEW_GUID(atol((char*)args), 0, HIGHGUID_PLAYER); -
+ if (sObjectMgr->GetPlayerNameByGUID(parseGUID, targetName)) { target = sObjectMgr->GetPlayerByLowGUID(parseGUID); @@ -1451,7 +1484,7 @@ public: } else if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) return false; -
+ uint32 accId = 0; uint32 money = 0; uint32 totalPlayerTime = 0; @@ -1464,14 +1497,14 @@ public: uint32 mapId; uint32 areaId; uint32 phase = 0; -
+ // get additional information from Player object if (target) { // check online security if (handler->HasLowerSecurity(target, 0)) return false; -
+ accId = target->GetSession()->GetAccountId(); money = target->GetMoney(); totalPlayerTime = target->GetTotalPlayedTime(); @@ -1490,14 +1523,14 @@ public: // check offline security if (handler->HasLowerSecurity(NULL, targetGuid)) return false; -
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_PINFO); stmt->setUInt32(0, GUID_LOPART(targetGuid)); PreparedQueryResult result = CharacterDatabase.Query(stmt); -
+ if (!result) return false; -
+ Field* fields = result->Fetch(); totalPlayerTime = fields[0].GetUInt32(); level = fields[1].GetUInt8(); @@ -1508,18 +1541,18 @@ public: mapId = fields[6].GetUInt16(); areaId = fields[7].GetUInt16(); } -
+ std::string userName = handler->GetTrinityString(LANG_ERROR); std::string eMail = handler->GetTrinityString(LANG_ERROR); std::string lastIp = handler->GetTrinityString(LANG_ERROR); uint32 security = 0; std::string lastLogin = handler->GetTrinityString(LANG_ERROR); -
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_PINFO); stmt->setInt32(0, int32(realmID)); stmt->setUInt32(1, accId); PreparedQueryResult result = LoginDatabase.Query(stmt); -
+ if (result) { Field* fields = result->Fetch(); @@ -1527,26 +1560,26 @@ public: security = fields[1].GetUInt8(); eMail = fields[2].GetString(); muteTime = fields[5].GetUInt64(); -
+ if (eMail.empty()) eMail = "-"; -
+ if (!handler->GetSession() || handler->GetSession()->GetSecurity() >= AccountTypes(security)) { lastIp = fields[3].GetString(); lastLogin = fields[4].GetString(); -
+ uint32 ip = inet_addr(lastIp.c_str()); #if TRINITY_ENDIAN == BIGENDIAN EndianConvertReverse(ip); #endif -
+ PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_IP2NATION_COUNTRY); -
+ stmt->setUInt32(0, ip); -
+ PreparedQueryResult result2 = WorldDatabase.Query(stmt); -
+ if (result2) { Field* fields2 = result2->Fetch(); @@ -1561,14 +1594,14 @@ public: lastLogin = "-"; } } -
+ std::string nameLink = handler->playerLink(targetName); -
+ handler->PSendSysMessage(LANG_PINFO_ACCOUNT, (target ? "" : handler->GetTrinityString(LANG_OFFLINE)), nameLink.c_str(), GUID_LOPART(targetGuid), userName.c_str(), accId, eMail.c_str(), security, lastIp.c_str(), lastLogin.c_str(), latency); -
+ std::string bannedby = "unknown"; std::string banreason = ""; -
+ stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_PINFO_BANS); stmt->setUInt32(0, accId); PreparedQueryResult result2 = LoginDatabase.Query(stmt); @@ -1578,7 +1611,7 @@ public: stmt->setUInt32(0, GUID_LOPART(targetGuid)); result2 = CharacterDatabase.Query(stmt); } -
+ if (result2) { Field* fields = result2->Fetch(); @@ -1586,13 +1619,13 @@ public: bannedby = fields[2].GetString(); banreason = fields[3].GetString(); } -
+ if (muteTime > 0) handler->PSendSysMessage(LANG_PINFO_MUTE, secsToTimeString(muteTime - time(NULL), true).c_str()); -
+ if (banTime >= 0) handler->PSendSysMessage(LANG_PINFO_BAN, banTime > 0 ? secsToTimeString(banTime - time(NULL), true).c_str() : "permanently", bannedby.c_str(), banreason.c_str()); -
+ std::string raceStr, ClassStr; switch (race) { @@ -1627,7 +1660,7 @@ public: raceStr = "Draenei"; break; } -
+ switch (Class) { case CLASS_WARRIOR: @@ -1661,30 +1694,30 @@ public: ClassStr = "Druid"; break; } -
+ std::string timeStr = secsToTimeString(totalPlayerTime, true, true); uint32 gold = money /GOLD; uint32 silv = (money % GOLD) / SILVER; uint32 copp = (money % GOLD) % SILVER; handler->PSendSysMessage(LANG_PINFO_LEVEL, raceStr.c_str(), ClassStr.c_str(), timeStr.c_str(), level, gold, silv, copp); -
+ // Add map, zone, subzone and phase to output int locale = handler->GetSessionDbcLocale(); std::string areaName = "<unknown>"; std::string zoneName = ""; -
+ MapEntry const* map = sMapStore.LookupEntry(mapId); -
+ AreaTableEntry const* area = GetAreaEntryByAreaID(areaId); if (area) { areaName = area->area_name[locale]; -
+ AreaTableEntry const* zone = GetAreaEntryByAreaID(area->zone); if (zone) zoneName = zone->area_name[locale]; } -
+ if (target) { if (!zoneName.empty()) @@ -1694,14 +1727,14 @@ public: } else handler->PSendSysMessage(LANG_PINFO_MAP_OFFLINE, map->name[locale], areaName.c_str()); -
+ return true; } -
+ static bool HandleRespawnCommand(ChatHandler* handler, char const* /*args*/) { Player* player = handler->GetSession()->GetPlayer(); -
+ // accept only explicitly selected target (not implicitly self targeting case) Unit* target = handler->getSelectedUnit(); if (player->GetSelection() && target) @@ -1712,22 +1745,22 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ if (target->isDead()) target->ToCreature()->Respawn(); return true; } -
+ CellCoord p(Trinity::ComputeCellCoord(player->GetPositionX(), player->GetPositionY())); Cell cell(p); cell.SetNoCreate(); -
+ Trinity::RespawnDo u_do; Trinity::WorldObjectWorker<Trinity::RespawnDo> worker(player, u_do); -
+ TypeContainerVisitor<Trinity::WorldObjectWorker<Trinity::RespawnDo>, GridTypeMapContainer > obj_worker(worker); cell.Visit(p, obj_worker, *player->GetMap(), *player, player->GetGridActivationRange()); -
+ return true; } // mute player for some times @@ -1738,33 +1771,33 @@ public: handler->extractOptFirstArg((char*)args, &nameStr, &delayStr); if (!delayStr) return false; -
+ char const* muteReason = strtok(NULL, "\r"); std::string muteReasonStr = "No reason"; if (muteReason != NULL) muteReasonStr = muteReason; -
+ Player* target; uint64 targetGuid; std::string targetName; if (!handler->extractPlayerTarget(nameStr, &target, &targetGuid, &targetName)) return false; -
+ uint32 accountId = target ? target->GetSession()->GetAccountId() : sObjectMgr->GetPlayerAccountIdByGUID(targetGuid); -
+ // find only player from same account if any if (!target) if (WorldSession* session = sWorld->FindSession(accountId)) target = session->GetPlayer(); -
+ uint32 notSpeakTime = uint32(atoi(delayStr)); -
+ // must have strong lesser security level if (handler->HasLowerSecurity (target, targetGuid, true)) return false; -
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_MUTE_TIME); -
+ if (target) { // Target is online, mute will be in effect right away. @@ -1779,16 +1812,16 @@ public: int32 muteTime = -int32(notSpeakTime * MINUTE); stmt->setInt64(0, muteTime); } -
+ stmt->setUInt32(1, accountId); LoginDatabase.Execute(stmt); std::string nameLink = handler->playerLink(targetName); -
+ handler->PSendSysMessage(target ? LANG_YOU_DISABLE_CHAT : LANG_COMMAND_DISABLE_CHAT_DELAYED, nameLink.c_str(), notSpeakTime, muteReasonStr.c_str()); -
+ return true; } -
+ // unmute player static bool HandleUnmuteCommand(ChatHandler* handler, char const* args) { @@ -1797,18 +1830,18 @@ public: std::string targetName; if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) return false; -
+ uint32 accountId = target ? target->GetSession()->GetAccountId() : sObjectMgr->GetPlayerAccountIdByGUID(targetGuid); -
+ // find only player from same account if any if (!target) if (WorldSession* session = sWorld->FindSession(accountId)) target = session->GetPlayer(); -
+ // must have strong lesser security level if (handler->HasLowerSecurity (target, targetGuid, true)) return false; -
+ if (target) { if (target->CanSpeak()) @@ -1817,25 +1850,25 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ target->GetSession()->m_muteTime = 0; } -
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_MUTE_TIME); stmt->setInt64(0, 0); stmt->setUInt32(1, accountId); LoginDatabase.Execute(stmt); -
+ if (target) ChatHandler(target).PSendSysMessage(LANG_YOUR_CHAT_ENABLED); -
+ std::string nameLink = handler->playerLink(targetName); -
+ handler->PSendSysMessage(LANG_YOU_ENABLE_CHAT, nameLink.c_str()); -
+ return true; } -
+ static bool HandleMovegensCommand(ChatHandler* handler, char const* /*args*/) { @@ -1846,13 +1879,13 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ handler->PSendSysMessage(LANG_MOVEGENS_LIST, (unit->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"), unit->GetGUIDLow()); -
+ MotionMaster* motionMaster = unit->GetMotionMaster(); float x, y, z; motionMaster->GetDestination(x, y, z); -
+ for (uint8 i = 0; i < MAX_MOTION_SLOT; ++i) { MovementGenerator* movementGenerator = motionMaster->GetMotionSlot(i); @@ -1861,7 +1894,7 @@ public: handler->SendSysMessage("Empty"); continue; } -
+ switch (movementGenerator->GetMovementGeneratorType()) { case IDLE_MOTION_TYPE: @@ -1886,7 +1919,7 @@ public: target = static_cast<ChaseMovementGenerator<Player> const*>(movementGenerator)->GetTarget(); else target = static_cast<ChaseMovementGenerator<Creature> const*>(movementGenerator)->GetTarget(); -
+ if (!target) handler->SendSysMessage(LANG_MOVEGENS_CHASE_NULL); else if (target->GetTypeId() == TYPEID_PLAYER) @@ -1902,7 +1935,7 @@ public: target = static_cast<FollowMovementGenerator<Player> const*>(movementGenerator)->GetTarget(); else target = static_cast<FollowMovementGenerator<Creature> const*>(movementGenerator)->GetTarget(); -
+ if (!target) handler->SendSysMessage(LANG_MOVEGENS_FOLLOW_NULL); else if (target->GetTypeId() == TYPEID_PLAYER) @@ -1953,7 +1986,7 @@ public: char const* newFlagStr = strtok((char*)args, " "); if (!newFlagStr) return false; -
+ Creature* caster = handler->getSelectedCreature(); if (!caster) { @@ -1961,19 +1994,19 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ Player* player = handler->GetSession()->GetPlayer(); -
+ caster->GetMotionMaster()->MovePoint(0, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()); -
+ return true; } -
+ static bool HandleDamageCommand(ChatHandler* handler, char const* args) { if (!*args) return false; -
+ Unit* target = handler->getSelectedUnit(); if (!target || !handler->GetSession()->GetPlayer()->GetSelection()) { @@ -1981,28 +2014,28 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ if (target->GetTypeId() == TYPEID_PLAYER) { if (handler->HasLowerSecurity((Player*)target, 0, false)) return false; } -
+ if (!target->isAlive()) return true; -
+ char* damageStr = strtok((char*)args, " "); if (!damageStr) return false; -
+ int32 damage_int = atoi((char*)damageStr); if (damage_int <= 0) return true; -
+ uint32 damage = damage_int; -
+ char* schoolStr = strtok((char*)NULL, " "); -
+ // flat melee damage without resistence/etc reduction if (!schoolStr) { @@ -2011,52 +2044,52 @@ public: handler->GetSession()->GetPlayer()->SendAttackStateUpdate (HITINFO_AFFECTS_VICTIM, target, 1, SPELL_SCHOOL_MASK_NORMAL, damage, 0, 0, VICTIMSTATE_HIT, 0); return true; } -
+ uint32 school = schoolStr ? atoi((char*)schoolStr) : SPELL_SCHOOL_NORMAL; if (school >= MAX_SPELL_SCHOOL) return false; -
+ SpellSchoolMask schoolmask = SpellSchoolMask(1 << school); -
+ if (Unit::IsDamageReducedByArmor(schoolmask)) damage = handler->GetSession()->GetPlayer()->CalcArmorReducedDamage(target, damage, NULL, BASE_ATTACK); -
+ char* spellStr = strtok((char*)NULL, " "); -
+ // melee damage by specific school if (!spellStr) { uint32 absorb = 0; uint32 resist = 0; -
+ handler->GetSession()->GetPlayer()->CalcAbsorbResist(target, schoolmask, SPELL_DIRECT_DAMAGE, damage, &absorb, &resist); -
+ if (damage <= absorb + resist) return true; -
+ damage -= absorb + resist; -
+ handler->GetSession()->GetPlayer()->DealDamageMods(target, damage, &absorb); handler->GetSession()->GetPlayer()->DealDamage(target, damage, NULL, DIRECT_DAMAGE, schoolmask, NULL, false); handler->GetSession()->GetPlayer()->SendAttackStateUpdate (HITINFO_AFFECTS_VICTIM, target, 1, schoolmask, damage, absorb, resist, VICTIMSTATE_HIT, 0); return true; } -
+ // non-melee damage -
+ // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form uint32 spellid = handler->extractSpellIdFromLink((char*)args); if (!spellid || !sSpellMgr->GetSpellInfo(spellid)) return false; -
+ handler->GetSession()->GetPlayer()->SpellNonMeleeDamageLog(target, spellid, damage); return true; } -
+ static bool HandleCombatStopCommand(ChatHandler* handler, char const* args) { Player* target = NULL; -
+ if (args && strlen(args) > 0) { target = sObjectAccessor->FindPlayerByName(args); @@ -2067,48 +2100,48 @@ public: return false; } } -
+ if (!target) { if (!handler->extractPlayerTarget((char*)args, &target)) return false; } -
+ // check online security if (handler->HasLowerSecurity(target, 0)) return false; -
+ target->CombatStop(); target->getHostileRefManager().deleteReferences(); return true; } -
+ static bool HandleFlushArenaPointsCommand(ChatHandler* /*handler*/, char const* /*args*/) { sArenaTeamMgr->DistributeArenaPoints(); return true; } -
+ static bool HandleRepairitemsCommand(ChatHandler* handler, char const* args) { Player* target; if (!handler->extractPlayerTarget((char*)args, &target)) return false; -
+ // check online security if (handler->HasLowerSecurity(target, 0)) return false; -
+ // Repair items target->DurabilityRepairAll(false, 0, false); -
+ handler->PSendSysMessage(LANG_YOU_REPAIR_ITEMS, handler->GetNameLink(target).c_str()); if (handler->needReportToTarget(target)) ChatHandler(target).PSendSysMessage(LANG_YOUR_ITEMS_REPAIRED, handler->GetNameLink().c_str()); -
+ return true; } -
+ // Send mail by command static bool HandleSendMailCommand(ChatHandler* handler, char const* args) { @@ -2118,37 +2151,37 @@ public: std::string targetName; if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) return false; -
+ char* tail1 = strtok(NULL, ""); if (!tail1) return false; -
+ char const* msgSubject = handler->extractQuotedArg(tail1); if (!msgSubject) return false; -
+ char* tail2 = strtok(NULL, ""); if (!tail2) return false; -
+ char const* msgText = handler->extractQuotedArg(tail2); if (!msgText) return false; -
+ // msgSubject, msgText isn't NUL after prev. check std::string subject = msgSubject; std::string text = msgText; -
+ // from console show not existed sender MailSender sender(MAIL_NORMAL, handler->GetSession() ? handler->GetSession()->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); -
+ //- TODO: Fix poor design SQLTransaction trans = CharacterDatabase.BeginTransaction(); MailDraft(subject, text) .SendMailTo(trans, MailReceiver(target, GUID_LOPART(targetGuid)), sender); -
+ CharacterDatabase.CommitTransaction(trans); -
+ std::string nameLink = handler->playerLink(targetName); handler->PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); return true; @@ -2162,49 +2195,49 @@ public: std::string receiverName; if (!handler->extractPlayerTarget((char*)args, &receiver, &receiverGuid, &receiverName)) return false; -
+ char* tail1 = strtok(NULL, ""); if (!tail1) return false; -
+ char const* msgSubject = handler->extractQuotedArg(tail1); if (!msgSubject) return false; -
+ char* tail2 = strtok(NULL, ""); if (!tail2) return false; -
+ char const* msgText = handler->extractQuotedArg(tail2); if (!msgText) return false; -
+ // msgSubject, msgText isn't NUL after prev. check std::string subject = msgSubject; std::string text = msgText; -
+ // extract items typedef std::pair<uint32, uint32> ItemPair; typedef std::list< ItemPair > ItemPairs; ItemPairs items; -
+ // get all tail string char* tail = strtok(NULL, ""); -
+ // get from tail next item str while (char* itemStr = strtok(tail, " ")) { // and get new tail tail = strtok(NULL, ""); -
+ // parse item str char const* itemIdStr = strtok(itemStr, ":"); char const* itemCountStr = strtok(NULL, " "); -
+ uint32 itemId = atoi(itemIdStr); if (!itemId) return false; -
+ ItemTemplate const* item_proto = sObjectMgr->GetItemTemplate(itemId); if (!item_proto) { @@ -2212,7 +2245,7 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ uint32 itemCount = itemCountStr ? atoi(itemCountStr) : 1; if (itemCount < 1 || (item_proto->MaxCount > 0 && itemCount > uint32(item_proto->MaxCount))) { @@ -2220,15 +2253,15 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ while (itemCount > item_proto->GetMaxStackSize()) { items.push_back(ItemPair(itemId, item_proto->GetMaxStackSize())); itemCount -= item_proto->GetMaxStackSize(); } -
+ items.push_back(ItemPair(itemId, itemCount)); -
+ if (items.size() > MAX_MAIL_ITEMS) { handler->PSendSysMessage(LANG_COMMAND_MAIL_ITEMS_LIMIT, MAX_MAIL_ITEMS); @@ -2236,15 +2269,15 @@ public: return false; } } -
+ // from console show not existed sender MailSender sender(MAIL_NORMAL, handler->GetSession() ? handler->GetSession()->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); -
+ // fill mail MailDraft draft(subject, text); -
+ SQLTransaction trans = CharacterDatabase.BeginTransaction(); -
+ for (ItemPairs::const_iterator itr = items.begin(); itr != items.end(); ++itr) { if (Item* item = Item::CreateItem(itr->first, itr->second, handler->GetSession() ? handler->GetSession()->GetPlayer() : 0)) @@ -2253,10 +2286,10 @@ public: draft.AddItem(item); } } -
+ draft.SendMailTo(trans, MailReceiver(receiver, GUID_LOPART(receiverGuid)), sender); CharacterDatabase.CommitTransaction(trans); -
+ std::string nameLink = handler->playerLink(receiverName); handler->PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); return true; @@ -2265,49 +2298,49 @@ public: static bool HandleSendMoneyCommand(ChatHandler* handler, char const* args) { /// format: name "subject text" "mail text" money -
+ Player* receiver; uint64 receiverGuid; std::string receiverName; if (!handler->extractPlayerTarget((char*)args, &receiver, &receiverGuid, &receiverName)) return false; -
+ char* tail1 = strtok(NULL, ""); if (!tail1) return false; -
+ char* msgSubject = handler->extractQuotedArg(tail1); if (!msgSubject) return false; -
+ char* tail2 = strtok(NULL, ""); if (!tail2) return false; -
+ char* msgText = handler->extractQuotedArg(tail2); if (!msgText) return false; -
+ char* moneyStr = strtok(NULL, ""); int32 money = moneyStr ? atoi(moneyStr) : 0; if (money <= 0) return false; -
+ // msgSubject, msgText isn't NUL after prev. check std::string subject = msgSubject; std::string text = msgText; -
+ // from console show not existed sender MailSender sender(MAIL_NORMAL, handler->GetSession() ? handler->GetSession()->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); -
+ SQLTransaction trans = CharacterDatabase.BeginTransaction(); -
+ MailDraft(subject, text) .AddMoney(money) .SendMailTo(trans, MailReceiver(receiver, GUID_LOPART(receiverGuid)), sender); -
+ CharacterDatabase.CommitTransaction(trans); -
+ std::string nameLink = handler->playerLink(receiverName); handler->PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); return true; @@ -2319,11 +2352,11 @@ public: Player* player; if (!handler->extractPlayerTarget((char*)args, &player)) return false; -
+ char* msgStr = strtok(NULL, ""); if (!msgStr) return false; -
+ ///- Check that he is not logging out. if (player->GetSession()->isLogingOut()) { @@ -2331,31 +2364,31 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ /// - Send the message // Use SendAreaTriggerMessage for fastest delivery. player->GetSession()->SendAreaTriggerMessage("%s", msgStr); player->GetSession()->SendAreaTriggerMessage("|cffff0000[Message from administrator]:|r"); -
+ // Confirmation message std::string nameLink = handler->GetNameLink(player); handler->PSendSysMessage(LANG_SENDMESSAGE, nameLink.c_str(), msgStr); -
+ return true; } -
+ static bool HandleCreatePetCommand(ChatHandler* handler, char const* /*args*/) { Player* player = handler->GetSession()->GetPlayer(); Creature* creatureTarget = handler->getSelectedCreature(); -
+ if (!creatureTarget || creatureTarget->isPet() || creatureTarget->GetTypeId() == TYPEID_PLAYER) { handler->PSendSysMessage(LANG_SELECT_CREATURE); handler->SetSentErrorMessage(true); return false; } -
+ CreatureTemplate const* creatrueTemplate = sObjectMgr->GetCreatureTemplate(creatureTarget->GetEntry()); // Creatures with family 0 crashes the server if (!creatrueTemplate->family) @@ -2364,14 +2397,14 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ if (player->GetPetGUID()) { handler->PSendSysMessage("You already have a pet"); handler->SetSentErrorMessage(true); return false; } -
+ // Everything looks OK, create new pet Pet* pet = new Pet(player, HUNTER_PET); if (!pet->CreateBaseAtCreature(creatureTarget)) @@ -2380,14 +2413,14 @@ public: handler->PSendSysMessage("Error 1"); return false; } -
+ creatureTarget->setDeathState(JUST_DIED); creatureTarget->RemoveCorpse(); creatureTarget->SetHealth(0); // just for nice GM-mode view -
+ pet->SetUInt64Value(UNIT_FIELD_CREATEDBY, player->GetGUID()); pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, player->getFaction()); -
+ if (!pet->InitStatsForLevel(creatureTarget->getLevel())) { sLog->outError(LOG_FILTER_GENERAL, "InitStatsForLevel() in EffectTameCreature failed! Pet deleted."); @@ -2395,47 +2428,47 @@ public: delete pet; return false; } -
+ // prepare visual effect for levelup pet->SetUInt32Value(UNIT_FIELD_LEVEL, creatureTarget->getLevel()-1); -
+ pet->GetCharmInfo()->SetPetNumber(sObjectMgr->GeneratePetNumber(), true); // this enables pet details window (Shift+P) pet->InitPetCreateSpells(); pet->SetFullHealth(); -
+ pet->GetMap()->AddToMap(pet->ToCreature()); -
+ // visual effect for levelup pet->SetUInt32Value(UNIT_FIELD_LEVEL, creatureTarget->getLevel()); -
+ player->SetMinion(pet, true); pet->SavePetToDB(PET_SAVE_AS_CURRENT); player->PetSpellInitialize(); -
+ return true; } -
+ static bool HandlePetLearnCommand(ChatHandler* handler, char const* args) { if (!*args) return false; -
+ Player* player = handler->GetSession()->GetPlayer(); Pet* pet = player->GetPet(); -
+ if (!pet) { handler->PSendSysMessage("You have no pet"); handler->SetSentErrorMessage(true); return false; } -
+ uint32 spellId = handler->extractSpellIdFromLink((char*)args); -
+ if (!spellId || !sSpellMgr->GetSpellInfo(spellId)) return false; -
+ // Check if pet already has it if (pet->HasSpell(spellId)) { @@ -2443,7 +2476,7 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ // Check if spell is valid SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo)) @@ -2452,18 +2485,18 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ pet->learnSpell(spellId); -
+ handler->PSendSysMessage("Pet has learned spell %u", spellId); return true; } -
+ static bool HandlePetUnlearnCommand(ChatHandler* handler, char const* args) { if (!*args) return false; -
+ Player* player = handler->GetSession()->GetPlayer(); Pet* pet = player->GetPet(); if (!pet) @@ -2472,17 +2505,17 @@ public: handler->SetSentErrorMessage(true); return false; } -
+ uint32 spellId = handler->extractSpellIdFromLink((char*)args); -
+ if (pet->HasSpell(spellId)) pet->removeSpell(spellId, false); else handler->PSendSysMessage("Pet doesn't have that spell"); -
+ return true; } -
+ static bool HandleFreezeCommand(ChatHandler* handler, char const* args) { std::string name; @@ -2503,31 +2536,31 @@ public: normalizePlayerName(name); player = sObjectAccessor->FindPlayerByName(name.c_str()); } -
+ if (!player) { handler->SendSysMessage(LANG_COMMAND_FREEZE_WRONG); return true; } -
+ if (player == handler->GetSession()->GetPlayer()) { handler->SendSysMessage(LANG_COMMAND_FREEZE_ERROR); return true; } -
+ // effect if (player && (player != handler->GetSession()->GetPlayer())) { handler->PSendSysMessage(LANG_COMMAND_FREEZE, name.c_str()); -
+ // stop combat + make player unattackable + duel stop + stop some spells player->setFaction(35); player->CombatStop(); if (player->IsNonMeleeSpellCasted(true)) player->InterruptNonMeleeSpells(true); player->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); -
+ // if player class = hunter || warlock remove pet if alive if ((player->getClass() == CLASS_HUNTER) || (player->getClass() == CLASS_WARLOCK)) { @@ -2539,23 +2572,23 @@ public: player->RemovePet(pet, PET_SAVE_NOT_IN_SLOT); } } -
+ if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(9454)) Aura::TryRefreshStackOrCreate(spellInfo, MAX_EFFECT_MASK, player, player); -
+ // save player player->SaveToDB(); } -
+ return true; } -
+ static bool HandleUnFreezeCommand(ChatHandler* handler, char const*args) { std::string name; Player* player; char* targetName = strtok((char*)args, " "); // Get entered name -
+ if (targetName) { name = targetName; @@ -2568,18 +2601,18 @@ public: if (player) name = player->GetName(); } -
+ if (player) { handler->PSendSysMessage(LANG_COMMAND_UNFREEZE, name.c_str()); -
+ // Reset player faction + allow combat + allow duels player->setFactionForRace(player->getRace()); player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); -
+ // Remove Freeze spell (allowing movement and spells) player->RemoveAurasDueToSpell(9454); -
+ // Save player player->SaveToDB(); } @@ -2591,21 +2624,21 @@ public: PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_GUID_BY_NAME); stmt->setString(0, name); PreparedQueryResult result = CharacterDatabase.Query(stmt); -
+ if (!result) { handler->SendSysMessage(LANG_COMMAND_FREEZE_WRONG); return true; } -
+ // If player found: delete his freeze aura Field* fields = result->Fetch(); uint32 lowGuid = fields[0].GetUInt32(); -
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_AURA_FROZEN); stmt->setUInt32(0, lowGuid); CharacterDatabase.Execute(stmt); -
+ handler->PSendSysMessage(LANG_COMMAND_UNFREEZE, name.c_str()); return true; } @@ -2615,10 +2648,10 @@ public: return true; } } -
+ return true; } -
+ static bool HandleListFreezeCommand(ChatHandler* handler, char const* /*args*/) { // Get names from DB @@ -2629,10 +2662,10 @@ public: handler->SendSysMessage(LANG_COMMAND_NO_FROZEN_PLAYERS); return true; } -
+ // Header of the names handler->PSendSysMessage(LANG_COMMAND_LIST_FREEZE); -
+ // Output of the results do { @@ -2641,120 +2674,120 @@ public: handler->PSendSysMessage(LANG_COMMAND_FROZEN_PLAYERS, player.c_str()); } while (result->NextRow()); -
+ return true; } -
+ static bool HandleGroupLeaderCommand(ChatHandler* handler, char const* args) { Player* player = NULL; Group* group = NULL; uint64 guid = 0; char* nameStr = strtok((char*)args, " "); -
+ if (handler->GetPlayerGroupAndGUIDByName(nameStr, player, group, guid)) if (group && group->GetLeaderGUID() != guid) { group->ChangeLeader(guid); group->SendUpdate(); } -
+ return true; } -
+ static bool HandleGroupDisbandCommand(ChatHandler* handler, char const* args) { Player* player = NULL; Group* group = NULL; uint64 guid = 0; char* nameStr = strtok((char*)args, " "); -
+ if (handler->GetPlayerGroupAndGUIDByName(nameStr, player, group, guid)) if (group) group->Disband(); -
+ return true; } -
+ static bool HandleGroupRemoveCommand(ChatHandler* handler, char const* args) { Player* player = NULL; Group* group = NULL; uint64 guid = 0; char* nameStr = strtok((char*)args, " "); -
+ if (handler->GetPlayerGroupAndGUIDByName(nameStr, player, group, guid, true)) if (group) group->RemoveMember(guid); -
+ return true; } -
+ static bool HandlePlayAllCommand(ChatHandler* handler, char const* args) { if (!*args) return false; -
+ uint32 soundId = atoi((char*)args); -
+ if (!sSoundEntriesStore.LookupEntry(soundId)) { handler->PSendSysMessage(LANG_SOUND_NOT_EXIST, soundId); handler->SetSentErrorMessage(true); return false; } -
+ WorldPacket data(SMSG_PLAY_SOUND, 4); data << uint32(soundId) << handler->GetSession()->GetPlayer()->GetGUID(); sWorld->SendGlobalMessage(&data); -
+ handler->PSendSysMessage(LANG_COMMAND_PLAYED_TO_ALL, soundId); return true; } -
+ static bool HandlePossessCommand(ChatHandler* handler, char const* /*args*/) { Unit* unit = handler->getSelectedUnit(); if (!unit) return false; -
+ handler->GetSession()->GetPlayer()->CastSpell(unit, 530, true); return true; } -
+ static bool HandleUnPossessCommand(ChatHandler* handler, char const* /*args*/) { Unit* unit = handler->getSelectedUnit(); if (!unit) unit = handler->GetSession()->GetPlayer(); -
+ unit->RemoveCharmAuras(); -
+ return true; } -
+ static bool HandleBindSightCommand(ChatHandler* handler, char const* /*args*/) { Unit* unit = handler->getSelectedUnit(); if (!unit) return false; -
+ handler->GetSession()->GetPlayer()->CastSpell(unit, 6277, true); return true; } -
+ static bool HandleUnbindSightCommand(ChatHandler* handler, char const* /*args*/) { Player* player = handler->GetSession()->GetPlayer(); -
+ if (player->isPossessing()) return false; -
+ player->StopCastingBindSight(); return true; } }; -
+ void AddSC_misc_commandscript() { new misc_commandscript(); diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp index 3bb29f8abfe..7d2a4304054 100644 --- a/src/server/scripts/Commands/cs_reload.cpp +++ b/src/server/scripts/Commands/cs_reload.cpp @@ -467,56 +467,57 @@ public: cInfo->rangeattacktime = fields[29].GetUInt32(); cInfo->unit_class = fields[30].GetUInt8(); cInfo->unit_flags = fields[31].GetUInt32(); - cInfo->dynamicflags = fields[32].GetUInt32(); - cInfo->family = fields[33].GetUInt8(); - cInfo->trainer_type = fields[34].GetUInt8(); - cInfo->trainer_spell = fields[35].GetUInt32(); - cInfo->trainer_class = fields[36].GetUInt8(); - cInfo->trainer_race = fields[37].GetUInt8(); - cInfo->minrangedmg = fields[38].GetFloat(); - cInfo->maxrangedmg = fields[39].GetFloat(); - cInfo->rangedattackpower = fields[40].GetUInt16(); - cInfo->type = fields[41].GetUInt8(); - cInfo->type_flags = fields[42].GetUInt32(); - cInfo->lootid = fields[43].GetUInt32(); - cInfo->pickpocketLootId = fields[44].GetUInt32(); - cInfo->SkinLootId = fields[45].GetUInt32(); + cInfo->unit_flags2 = fields[32].GetUInt32(); + cInfo->dynamicflags = fields[33].GetUInt32(); + cInfo->family = fields[34].GetUInt8(); + cInfo->trainer_type = fields[35].GetUInt8(); + cInfo->trainer_spell = fields[36].GetUInt32(); + cInfo->trainer_class = fields[37].GetUInt8(); + cInfo->trainer_race = fields[38].GetUInt8(); + cInfo->minrangedmg = fields[39].GetFloat(); + cInfo->maxrangedmg = fields[40].GetFloat(); + cInfo->rangedattackpower = fields[41].GetUInt16(); + cInfo->type = fields[42].GetUInt8(); + cInfo->type_flags = fields[43].GetUInt32(); + cInfo->lootid = fields[44].GetUInt32(); + cInfo->pickpocketLootId = fields[45].GetUInt32(); + cInfo->SkinLootId = fields[46].GetUInt32(); for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i) - cInfo->resistance[i] = fields[46 + i -1].GetUInt16(); - - cInfo->spells[0] = fields[52].GetUInt32(); - cInfo->spells[1] = fields[53].GetUInt32(); - cInfo->spells[2] = fields[54].GetUInt32(); - cInfo->spells[3] = fields[55].GetUInt32(); - cInfo->spells[4] = fields[56].GetUInt32(); - cInfo->spells[5] = fields[57].GetUInt32(); - cInfo->spells[6] = fields[58].GetUInt32(); - cInfo->spells[7] = fields[59].GetUInt32(); - cInfo->PetSpellDataId = fields[60].GetUInt32(); - cInfo->VehicleId = fields[61].GetUInt32(); - cInfo->mingold = fields[62].GetUInt32(); - cInfo->maxgold = fields[63].GetUInt32(); - cInfo->AIName = fields[64].GetString(); - cInfo->MovementType = fields[65].GetUInt8(); - cInfo->InhabitType = fields[66].GetUInt8(); - cInfo->HoverHeight = fields[67].GetFloat(); - cInfo->ModHealth = fields[68].GetFloat(); - cInfo->ModMana = fields[69].GetFloat(); - cInfo->ModArmor = fields[70].GetFloat(); - cInfo->RacialLeader = fields[71].GetBool(); - cInfo->questItems[0] = fields[72].GetUInt32(); - cInfo->questItems[1] = fields[73].GetUInt32(); - cInfo->questItems[2] = fields[74].GetUInt32(); - cInfo->questItems[3] = fields[75].GetUInt32(); - cInfo->questItems[4] = fields[76].GetUInt32(); - cInfo->questItems[5] = fields[77].GetUInt32(); - cInfo->movementId = fields[78].GetUInt32(); - cInfo->RegenHealth = fields[79].GetBool(); - cInfo->equipmentId = fields[80].GetUInt32(); - cInfo->MechanicImmuneMask = fields[81].GetUInt32(); - cInfo->flags_extra = fields[82].GetUInt32(); - cInfo->ScriptID = sObjectMgr->GetScriptId(fields[83].GetCString()); + cInfo->resistance[i] = fields[47 + i -1].GetUInt16(); + + cInfo->spells[0] = fields[53].GetUInt32(); + cInfo->spells[1] = fields[54].GetUInt32(); + cInfo->spells[2] = fields[55].GetUInt32(); + cInfo->spells[3] = fields[56].GetUInt32(); + cInfo->spells[4] = fields[57].GetUInt32(); + cInfo->spells[5] = fields[58].GetUInt32(); + cInfo->spells[6] = fields[59].GetUInt32(); + cInfo->spells[7] = fields[60].GetUInt32(); + cInfo->PetSpellDataId = fields[61].GetUInt32(); + cInfo->VehicleId = fields[62].GetUInt32(); + cInfo->mingold = fields[63].GetUInt32(); + cInfo->maxgold = fields[64].GetUInt32(); + cInfo->AIName = fields[65].GetString(); + cInfo->MovementType = fields[66].GetUInt8(); + cInfo->InhabitType = fields[67].GetUInt8(); + cInfo->HoverHeight = fields[68].GetFloat(); + cInfo->ModHealth = fields[69].GetFloat(); + cInfo->ModMana = fields[70].GetFloat(); + cInfo->ModArmor = fields[71].GetFloat(); + cInfo->RacialLeader = fields[72].GetBool(); + cInfo->questItems[0] = fields[73].GetUInt32(); + cInfo->questItems[1] = fields[74].GetUInt32(); + cInfo->questItems[2] = fields[75].GetUInt32(); + cInfo->questItems[3] = fields[76].GetUInt32(); + cInfo->questItems[4] = fields[77].GetUInt32(); + cInfo->questItems[5] = fields[78].GetUInt32(); + cInfo->movementId = fields[79].GetUInt32(); + cInfo->RegenHealth = fields[80].GetBool(); + cInfo->equipmentId = fields[81].GetUInt32(); + cInfo->MechanicImmuneMask = fields[82].GetUInt32(); + cInfo->flags_extra = fields[83].GetUInt32(); + cInfo->ScriptID = sObjectMgr->GetScriptId(fields[84].GetCString()); sObjectMgr->CheckCreatureTemplate(cInfo); } diff --git a/src/server/scripts/Commands/cs_reset.cpp b/src/server/scripts/Commands/cs_reset.cpp index 82fb409faa7..76a4eb5d943 100644 --- a/src/server/scripts/Commands/cs_reset.cpp +++ b/src/server/scripts/Commands/cs_reset.cpp @@ -60,7 +60,7 @@ public: return false; if (target) - target->GetAchievementMgr().Reset(); + target->ResetAchievements(); else AchievementMgr::DeleteFromDB(GUID_LOPART(targetGuid)); diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp index d5add0f0bb7..f4195620dda 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp @@ -233,7 +233,7 @@ public: SWPainTimer = 20000; AmplifyDamageTimer = 5000; Cleave_Timer = 8000; - InfernalTimer = 45000; + InfernalTimer = 40000; InfernalCleanupTimer = 47000; AxesTargetSwitchTimer = urand(7500, 20000); SunderArmorTimer = urand(5000, 10000); diff --git a/src/server/scripts/EasternKingdoms/MoltenCore/boss_golemagg.cpp b/src/server/scripts/EasternKingdoms/MoltenCore/boss_golemagg.cpp index 84e9957a60c..fa99078cedb 100644 --- a/src/server/scripts/EasternKingdoms/MoltenCore/boss_golemagg.cpp +++ b/src/server/scripts/EasternKingdoms/MoltenCore/boss_golemagg.cpp @@ -77,7 +77,7 @@ class boss_golemagg : public CreatureScript void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) { - if (HealthBelowPct(10) || me->HasAura(SPELL_ENRAGE)) + if (!HealthBelowPct(10) || me->HasAura(SPELL_ENRAGE)) return; DoCast(me, SPELL_ENRAGE, true); diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp index 46fb62eae7f..0aad2857a45 100644 --- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp @@ -283,6 +283,12 @@ public: DoScriptText(SAY_WH_KILL, me); } + void DamageTaken(Unit* /*attacker*/, uint32& damage) + { + if (!_bCanResurrectCheck && damage >= me->GetHealth()) + damage = me->GetHealth() - 1; + } + void UpdateAI(const uint32 diff) { if (!UpdateVictim()) diff --git a/src/server/scripts/Kalimdor/ashenvale.cpp b/src/server/scripts/Kalimdor/ashenvale.cpp index 248932ecbb6..6a9dd77433a 100644 --- a/src/server/scripts/Kalimdor/ashenvale.cpp +++ b/src/server/scripts/Kalimdor/ashenvale.cpp @@ -447,7 +447,7 @@ class npc_muglash : public CreatureScript DoScriptText(SAY_MUG_START1, creature); creature->setFaction(113); - pEscortAI->Start(true, true, player->GetGUID()); + pEscortAI->Start(true, false, player->GetGUID()); } } return true; diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp index 89fdcc7f725..564df34462b 100755 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp @@ -85,8 +85,10 @@ enum BossSpells SPELL_SPIDER_FRENZY = 66128, SPELL_EXPOSE_WEAKNESS = 67720, //Passive - Triggered SPELL_SHADOW_STRIKE = 66134, - SPELL_SUBMERGE_EFFECT = 53421, - SPELL_EMERGE_EFFECT = 66947, + SPELL_SUBMERGE_EFFECT = 68394, + SPELL_EMERGE_EFFECT = 65982, + SPELL_AWAKENED = 66311, + SPELL_PERSISTENT_DIRT = 68048, SUMMON_SCARAB = NPC_SCARAB, SUMMON_FROSTSPHERE = NPC_FROST_SPHERE, @@ -96,6 +98,7 @@ enum BossSpells SPELL_FROST_SPHERE = 67539, SPELL_PERMAFROST = 66193, SPELL_PERMAFROST_VISUAL = 65882, + SPELL_PERMAFROST_MODEL = 66185, //Spike SPELL_SUMMON_SPIKE = 66169, @@ -117,12 +120,12 @@ enum SummonActions const Position SphereSpawn[6] = { - { 786.6439f, 108.2498f, 155.6701f, 0 }, - { 806.8429f, 150.5902f, 155.6701f, 0 }, - { 759.1386f, 163.9654f, 155.6701f, 0 }, - { 744.3701f, 119.5211f, 155.6701f, 0 }, - { 710.0211f, 120.8152f, 155.6701f, 0 }, - { 706.6383f, 161.5266f, 155.6701f, 0 }, + {779.8038f, 150.6580f, 158.1426f, 0}, + {736.0243f, 113.4201f, 158.0226f, 0}, + {712.5712f, 160.9948f, 158.4368f, 0}, + {701.4271f, 126.4740f, 158.0205f, 0}, + {747.9202f, 155.0920f, 158.0613f, 0}, + {769.6285f, 121.1024f, 158.0504f, 0}, }; enum MovementPoints @@ -219,7 +222,10 @@ public: //Summon Scarab Swarms neutral at random places for (int i=0; i < 10; i++) if (Creature* temp = me->SummonCreature(NPC_SCARAB, AnubarakLoc[1].GetPositionX()+urand(0, 50)-25, AnubarakLoc[1].GetPositionY()+urand(0, 50)-25, AnubarakLoc[1].GetPositionZ())) + { temp->setFaction(31); + temp->GetMotionMaster()->MoveRandom(10); + } } void JustDied(Unit* /*killer*/) @@ -447,10 +453,9 @@ public: m_uiDeterminationTimer = urand(5*IN_MILLISECONDS, 60*IN_MILLISECONDS); DoCast(me, SPELL_ACID_MANDIBLE); me->SetInCombatWithZone(); - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) - me->AddThreat(target, 20000.0f); - if (!me->isInCombat()) - me->DisappearAndDie(); + if (me->isInCombat()) + if (Creature* Anubarak = ObjectAccessor::GetCreature(*me, instance->GetData64(NPC_ANUBARAK))) + Anubarak->AI()->JustSummoned(me); } void DoAction(const int32 actionId) @@ -511,14 +516,16 @@ public: void Reset() { - me->SetCorpseDelay(0); + me->SetCorpseDelay(10); m_uiSpiderFrenzyTimer = urand(10*IN_MILLISECONDS, 20*IN_MILLISECONDS); m_uiSubmergeTimer = 30*IN_MILLISECONDS; DoCast(me, SPELL_EXPOSE_WEAKNESS); DoCast(me, SPELL_SPIDER_FRENZY); + DoCast(me, SPELL_AWAKENED); me->SetInCombatWithZone(); - if (!me->isInCombat()) - me->DisappearAndDie(); + if (me->isInCombat()) + if (Creature* Anubarak = ObjectAccessor::GetCreature(*me, instance->GetData64(NPC_ANUBARAK))) + Anubarak->AI()->JustSummoned(me); } void DoAction(const int32 actionId) @@ -526,8 +533,9 @@ public: switch (actionId) { case ACTION_SHADOW_STRIKE: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(target, SPELL_SHADOW_STRIKE); + if (!me->HasAura(SPELL_AWAKENED)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_SHADOW_STRIKE); break; } } @@ -537,22 +545,25 @@ public: if (!UpdateVictim()) return; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + if ((m_uiSubmergeTimer <= uiDiff) && HealthBelowPct(80)) { if (me->HasAura(SPELL_SUBMERGE_EFFECT)) { me->RemoveAurasDueToSpell(SPELL_SUBMERGE_EFFECT); DoCast(me, SPELL_EMERGE_EFFECT); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE); - me->CombatStart(me->SelectNearestTarget()); + DoCast(me, SPELL_AWAKENED); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } else { if (!me->HasAura(SPELL_PERMAFROST_HELPER)) { DoCast(me, SPELL_SUBMERGE_EFFECT); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE); - me->CombatStop(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(me, SPELL_PERSISTENT_DIRT, true); } } m_uiSubmergeTimer = 20*IN_MILLISECONDS; @@ -577,16 +588,10 @@ class mob_frost_sphere : public CreatureScript void Reset() { - _isFalling = false; me->SetReactState(REACT_PASSIVE); - //! Confirmed sniff 3.3.5.a - me->SetDisableGravity(true); - me->SetByteValue(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); - //! end + DoCast(SPELL_FROST_SPHERE); me->SetDisplayId(me->GetCreatureTemplate()->Modelid2); - me->SetSpeed(MOVE_RUN, 0.5f, false); me->GetMotionMaster()->MoveRandom(20.0f); - DoCast(SPELL_FROST_SPHERE); } void DamageTaken(Unit* /*who*/, uint32& damage) @@ -594,9 +599,20 @@ class mob_frost_sphere : public CreatureScript if (me->GetHealth() <= damage) { damage = 0; - if (!_isFalling) + float floorZ = me->GetMap()->GetHeight(me->GetPhaseMask(), me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); + if (fabs(me->GetPositionZ() - floorZ) < 0.1f) { - _isFalling = true; + // we are close to the ground + me->GetMotionMaster()->MoveIdle(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveAurasDueToSpell(SPELL_FROST_SPHERE); + DoCast(SPELL_PERMAFROST_MODEL); + DoCast(SPELL_PERMAFROST); + me->SetObjectScale(2.0f); + } + else + { + // we are in air me->GetMotionMaster()->MoveIdle(); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); //At hit the ground @@ -615,16 +631,13 @@ class mob_frost_sphere : public CreatureScript { case POINT_FALL_GROUND: me->RemoveAurasDueToSpell(SPELL_FROST_SPHERE); - me->SetDisplayId(me->GetCreatureTemplate()->Modelid1); + DoCast(SPELL_PERMAFROST_MODEL); DoCast(SPELL_PERMAFROST_VISUAL); DoCast(SPELL_PERMAFROST); me->SetObjectScale(2.0f); break; } } - - private: - bool _isFalling; }; CreatureAI* GetAI(Creature* creature) const diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp index 10f7150351e..87e7801566e 100755 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp @@ -329,6 +329,8 @@ public: // used to despawn corpse immediately me->DespawnOrUnsummon(); } + + void UpdateAI(uint32 const /*diff*/) {} }; }; @@ -438,6 +440,8 @@ public: // used to despawn corpse immediately me->DespawnOrUnsummon(); } + + void UpdateAI(uint32 const /*diff*/) {} }; }; diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp index 9767126371b..af6104008ff 100755 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp @@ -332,7 +332,8 @@ class instance_trial_of_the_crusader : public InstanceMapScript } if (tributeChest) if (Creature* tirion = instance->GetCreature(TirionGUID)) - if (GameObject* chest = tirion->SummonGameObject(tributeChest, 805.62f, 134.87f, 142.16f, 3.27f, 0, 0, 0, 0, 90000000)) + // need proper location.this one is guessed based on videos + if (GameObject* chest = tirion->SummonGameObject(tributeChest, 643.814f, 136.027f, 141.295f, 0, 0, 0, 0, 0, 90000000)) chest->SetRespawnTime(chest->GetRespawnDelay()); break; } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp index 37d08484f0b..0476b2cbacb 100755 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp @@ -25,7 +25,6 @@ EndScriptData */ //Known Bugs: // - Need better implementation of Gossip and correct gossip text and option -// - Misses Dalaran Teleport at the end. #include "ScriptMgr.h" #include "ScriptedCreature.h" @@ -121,11 +120,8 @@ class npc_announcer_toc10 : public CreatureScript { npc_announcer_toc10AI(Creature* creature) : ScriptedAI(creature) { - instance = creature->GetInstanceScript(); } - InstanceScript* instance; - void Reset() { me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); @@ -219,7 +215,7 @@ class npc_announcer_toc10 : public CreatureScript return true; if (GameObject* floor = GameObject::GetGameObject(*player, instanceScript->GetData64(GO_ARGENT_COLISEUM_FLOOR))) - floor->SetDestructibleState(GO_DESTRUCTIBLE_DESTROYED); + floor->SetDestructibleState(GO_DESTRUCTIBLE_DAMAGED); creature->CastSpell(creature, 69016, false); @@ -275,7 +271,7 @@ class boss_lich_king_toc : public CreatureScript void MovementInform(uint32 uiType, uint32 uiId) { - if (uiType != POINT_MOTION_TYPE) + if (uiType != POINT_MOTION_TYPE || !instance) return; switch (uiId) { @@ -337,22 +333,20 @@ class boss_lich_king_toc : public CreatureScript break; case 5080: if (GameObject* go = instance->instance->GetGameObject(instance->GetData64(GO_ARGENT_COLISEUM_FLOOR))) - go->SetDestructibleState(GO_DESTRUCTIBLE_DESTROYED); + go->SetDestructibleState(GO_DESTRUCTIBLE_DAMAGED); me->CastSpell(me, 69016, false); - if (instance) - { - instance->SetData(TYPE_LICH_KING, DONE); - Creature* temp = Unit::GetCreature(*me, instance->GetData64(NPC_ANUBARAK)); - if (!temp || !temp->isAlive()) - temp = me->SummonCreature(NPC_ANUBARAK, AnubarakLoc[0].GetPositionX(), AnubarakLoc[0].GetPositionY(), AnubarakLoc[0].GetPositionZ(), 3, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + instance->SetData(TYPE_LICH_KING, DONE); + Creature* temp = Unit::GetCreature(*me, instance->GetData64(NPC_ANUBARAK)); + if (!temp || !temp->isAlive()) + temp = me->SummonCreature(NPC_ANUBARAK, AnubarakLoc[0].GetPositionX(), AnubarakLoc[0].GetPositionY(), AnubarakLoc[0].GetPositionZ(), 3, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); - instance->SetData(TYPE_EVENT, 0); - } + instance->SetData(TYPE_EVENT, 0); me->DespawnOrUnsummon(); m_uiUpdateTimer = 20000; break; } } else m_uiUpdateTimer -= uiDiff; + instance->SetData(TYPE_EVENT_TIMER, m_uiUpdateTimer); } }; @@ -797,7 +791,9 @@ class npc_tirion_toc : public CreatureScript instance->SetData(TYPE_EVENT, 0); break; case 6000: - me->NearTeleportTo(AnubarakLoc[0].GetPositionX(), AnubarakLoc[0].GetPositionY(), AnubarakLoc[0].GetPositionZ(), 4.0f); + me->SummonCreature(NPC_TIRION_FORDRING, EndSpawnLoc[0].GetPositionX(), EndSpawnLoc[0].GetPositionY(), EndSpawnLoc[0].GetPositionZ()); + me->SummonCreature(NPC_ARGENT_MAGE, EndSpawnLoc[1].GetPositionX(), EndSpawnLoc[1].GetPositionY(), EndSpawnLoc[1].GetPositionZ()); + me->SummonGameObject(GO_PORTAL_TO_DALARAN, EndSpawnLoc[2].GetPositionX(), EndSpawnLoc[2].GetPositionY(), EndSpawnLoc[2].GetPositionZ(), 5, 0, 0, 0, 0, 0); m_uiUpdateTimer = 20000; instance->SetData(TYPE_EVENT, 6005); break; diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h index ba230551b24..58cbd727963 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h @@ -129,6 +129,13 @@ const Position AnubarakLoc[]= {740.184509f, 193.443390f, 142.117584f, 0}, // 4 - Nerub Spawn }; +const Position EndSpawnLoc[]= +{ + {648.9167f, 131.0208f, 141.6161f, 0}, // 0 - Highlord Tirion Fordring + {649.1614f, 142.0399f, 141.3057f ,0}, // 1 - Argent Mage + {644.6250f, 149.2743f, 140.6015f ,0}, // 2 - Portal to Dalaran +}; + enum euiWorldStates { UPDATE_STATE_UI_SHOW = 4390, @@ -163,6 +170,7 @@ enum eCreature NPC_BARRENT = 34816, NPC_TIRION = 34996, NPC_TIRION_FORDRING = 36095, + NPC_ARGENT_MAGE = 36097, NPC_FIZZLEBANG = 35458, NPC_GARROSH = 34995, NPC_VARIAN = 34990, @@ -245,6 +253,7 @@ enum eGameObject GO_MAIN_GATE_DOOR = 195647, GO_EAST_PORTCULLIS = 195648, GO_WEB_DOOR = 195485, + GO_PORTAL_TO_DALARAN = 195682, }; enum eAchievementData diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp index 57d99908bfb..0d6e779c006 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp @@ -228,13 +228,13 @@ class boss_ick : public CreatureScript case EVENT_TOXIC_WASTE: if (Creature* krick = GetKrick()) if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - krick->CastSpell(target, SPELL_TOXIC_WASTE, false); + krick->CastSpell(target, SPELL_TOXIC_WASTE, TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE); events.ScheduleEvent(EVENT_TOXIC_WASTE, urand(7000, 10000)); break; case EVENT_SHADOW_BOLT: if (Creature* krick = GetKrick()) if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1)) - krick->CastSpell(target, SPELL_SHADOW_BOLT, false); + krick->CastSpell(target, SPELL_SHADOW_BOLT, TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE); events.ScheduleEvent(EVENT_SHADOW_BOLT, 15000); return; case EVENT_MIGHTY_KICK: diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp index a9ba0baa86f..7f6448382ba 100755 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp @@ -23,6 +23,7 @@ #include "Spell.h" #include "icecrown_citadel.h" #include "Vehicle.h" +#include "GridNotifiers.h" enum ScriptTexts { @@ -185,12 +186,15 @@ class AbominationDespawner if (Vehicle* veh = summon->GetVehicleKit()) veh->RemoveAllPassengers(); // also despawns the vehicle + // Found unit is Mutated Abomination, remove it return true; } + // Found unit is not Mutated Abomintaion, leave it return false; } + // No unit found, remove from SummonList return true; } @@ -198,6 +202,19 @@ class AbominationDespawner Unit* _owner; }; +struct RotfaceHeightCheck +{ + RotfaceHeightCheck(Creature* rotface) : _rotface(rotface) { } + + bool operator()(Creature* stalker) const + { + return stalker->GetPositionZ() < _rotface->GetPositionZ() + 5.0f; + } + +private: + Creature* _rotface; +}; + class boss_professor_putricide : public CreatureScript { public: @@ -246,7 +263,7 @@ class boss_professor_putricide : public CreatureScript events.Reset(); events.ScheduleEvent(EVENT_BERSERK, 600000); events.ScheduleEvent(EVENT_SLIME_PUDDLE, 10000); - events.ScheduleEvent(EVENT_UNSTABLE_EXPERIMENT, urand(25000, 30000)); + events.ScheduleEvent(EVENT_UNSTABLE_EXPERIMENT, urand(30000, 35000)); if (IsHeroic()) events.ScheduleEvent(EVENT_UNBOUND_PLAGUE, 20000); @@ -295,18 +312,16 @@ class boss_professor_putricide : public CreatureScript // no possible aura seen in sniff adding the aurastate summon->ModifyAuraState(AURA_STATE_UNKNOWN22, true); summon->CastSpell(summon, SPELL_GASEOUS_BLOAT_PROC, true); - summon->CastCustomSpell(SPELL_GASEOUS_BLOAT, SPELLVALUE_AURA_STACK, 10, summon, false); summon->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true); summon->SetReactState(REACT_PASSIVE); - return; + break; case NPC_VOLATILE_OOZE: // no possible aura seen in sniff adding the aurastate summon->ModifyAuraState(AURA_STATE_UNKNOWN19, true); summon->CastSpell(summon, SPELL_OOZE_ERUPTION_SEARCH_PERIODIC, true); - summon->CastSpell(summon, SPELL_VOLATILE_OOZE_ADHESIVE, false); summon->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true); summon->SetReactState(REACT_PASSIVE); - return; + break; case NPC_CHOKING_GAS_BOMB: summon->CastSpell(summon, SPELL_CHOKING_GAS_BOMB_PERIODIC, true); summon->CastSpell(summon, SPELL_CHOKING_GAS_EXPLOSION_TRIGGER, true); @@ -428,7 +443,8 @@ class boss_professor_putricide : public CreatureScript if (Creature* rotface = Unit::GetCreature(*me, instance->GetData64(DATA_ROTFACE))) { std::list<Creature*> list; - GetCreatureListWithEntryInGrid(list, rotface, NPC_PUDDLE_STALKER, 36.0f); + GetCreatureListWithEntryInGrid(list, rotface, NPC_PUDDLE_STALKER, 50.0f); + list.remove_if(RotfaceHeightCheck(rotface)); if (list.size() > 4) { list.sort(Trinity::ObjectDistanceOrderPred(rotface)); @@ -510,7 +526,6 @@ class boss_professor_putricide : public CreatureScript SetPhase(PHASE_COMBAT_3); events.ScheduleEvent(EVENT_MUTATED_PLAGUE, 25000); events.CancelEvent(EVENT_UNSTABLE_EXPERIMENT); - summons.remove_if(AbominationDespawner(me)); break; default: break; @@ -643,7 +658,7 @@ class boss_professor_putricide : public CreatureScript case EVENT_UNBOUND_PLAGUE: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(me))) { - me->CastCustomSpell(SPELL_UNBOUND_PLAGUE, SPELLVALUE_BASE_POINT0, 775, target); + DoCast(target, SPELL_UNBOUND_PLAGUE); DoCast(target, SPELL_UNBOUND_PLAGUE_SEARCHER); } events.ScheduleEvent(EVENT_UNBOUND_PLAGUE, 90000); @@ -668,6 +683,7 @@ class boss_professor_putricide : public CreatureScript me->SetFacingToObject(face); me->HandleEmoteCommand(EMOTE_ONESHOT_KNEEL); Talk(SAY_TRANSFORM_2); + summons.remove_if(AbominationDespawner(me)); events.ScheduleEvent(EVENT_RESUME_ATTACK, 8500, 0, PHASE_COMBAT_3); break; default: @@ -702,57 +718,78 @@ class boss_professor_putricide : public CreatureScript } }; -class npc_volatile_ooze : public CreatureScript +class npc_putricide_oozeAI : public ScriptedAI { public: - npc_volatile_ooze() : CreatureScript("npc_volatile_ooze") { } + npc_putricide_oozeAI(Creature* creature, uint32 hitTargetSpellId) : ScriptedAI(creature), + _newTargetSelectTimer(0), _hitTargetSpellId(hitTargetSpellId) + { + } - struct npc_putricide_oozeAI : public ScriptedAI + void SpellHitTarget(Unit* /*target*/, SpellInfo const* spell) { - npc_putricide_oozeAI(Creature* creature) : ScriptedAI(creature) - { - _newTargetSelectTimer = 0; - } + if (!_newTargetSelectTimer && spell->Id == sSpellMgr->GetSpellIdForDifficulty(_hitTargetSpellId, me)) + _newTargetSelectTimer = 1000; + } - void SpellHitTarget(Unit* /*target*/, SpellInfo const* spell) - { - if (!_newTargetSelectTimer && spell->Id == sSpellMgr->GetSpellIdForDifficulty(SPELL_OOZE_ERUPTION, me)) - _newTargetSelectTimer = 1000; - } + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) + { + if (spell->Id == SPELL_TEAR_GAS_CREATURE) + _newTargetSelectTimer = 1000; + } - void SpellHit(Unit* /*caster*/, SpellInfo const* spell) + void UpdateAI(uint32 const diff) + { + if (!UpdateVictim() && !_newTargetSelectTimer) + return; + + if (!_newTargetSelectTimer && !me->IsNonMeleeSpellCasted(false, false, true, false, true)) + _newTargetSelectTimer = 1000; + + DoMeleeAttackIfReady(); + + if (!_newTargetSelectTimer) + return; + + if (me->HasAura(SPELL_TEAR_GAS_CREATURE)) + return; + + if (_newTargetSelectTimer <= diff) { - if (spell->Id == SPELL_TEAR_GAS_CREATURE) - _newTargetSelectTimer = 1000; + _newTargetSelectTimer = 0; + CastMainSpell(); } + else + _newTargetSelectTimer -= diff; + } - void UpdateAI(uint32 const diff) - { - if (!UpdateVictim() && !_newTargetSelectTimer) - return; + virtual void CastMainSpell() = 0; - if (!_newTargetSelectTimer) - return; + private: + uint32 _hitTargetSpellId; + uint32 _newTargetSelectTimer; +}; - if (me->HasAura(SPELL_TEAR_GAS_CREATURE)) - return; +class npc_volatile_ooze : public CreatureScript +{ + public: + npc_volatile_ooze() : CreatureScript("npc_volatile_ooze") { } - if (_newTargetSelectTimer <= diff) - { - _newTargetSelectTimer = 0; - me->CastSpell(me, SPELL_VOLATILE_OOZE_ADHESIVE, false); - } - else - _newTargetSelectTimer -= diff; + struct npc_volatile_oozeAI : public npc_putricide_oozeAI + { + npc_volatile_oozeAI(Creature* creature) : npc_putricide_oozeAI(creature, SPELL_OOZE_ERUPTION) + { } - private: - uint32 _newTargetSelectTimer; + void CastMainSpell() + { + me->CastSpell(me, SPELL_VOLATILE_OOZE_ADHESIVE, false); + } }; CreatureAI* GetAI(Creature* creature) const { - return GetIcecrownCitadelAI<npc_putricide_oozeAI>(creature); + return GetIcecrownCitadelAI<npc_volatile_oozeAI>(creature); } }; @@ -761,45 +798,16 @@ class npc_gas_cloud : public CreatureScript public: npc_gas_cloud() : CreatureScript("npc_gas_cloud") { } - struct npc_gas_cloudAI : public ScriptedAI + struct npc_gas_cloudAI : public npc_putricide_oozeAI { - npc_gas_cloudAI(Creature* creature) : ScriptedAI(creature) + npc_gas_cloudAI(Creature* creature) : npc_putricide_oozeAI(creature, SPELL_EXPUNGED_GAS) { _newTargetSelectTimer = 0; } - void SpellHitTarget(Unit* /*target*/, SpellInfo const* spell) - { - if (!_newTargetSelectTimer && spell->Id == sSpellMgr->GetSpellIdForDifficulty(SPELL_EXPUNGED_GAS, me)) - _newTargetSelectTimer = 1000; - } - - void SpellHit(Unit* /*caster*/, SpellInfo const* spell) + void CastMainSpell() { - if (spell->Id == SPELL_TEAR_GAS_CREATURE) - _newTargetSelectTimer = 1000; - } - - void UpdateAI(uint32 const diff) - { - if (!UpdateVictim() && !_newTargetSelectTimer) - return; - - DoMeleeAttackIfReady(); - - if (!_newTargetSelectTimer) - return; - - if (me->HasAura(SPELL_TEAR_GAS_CREATURE)) - return; - - if (_newTargetSelectTimer <= diff) - { - _newTargetSelectTimer = 0; - me->CastCustomSpell(SPELL_GASEOUS_BLOAT, SPELLVALUE_AURA_STACK, 10, me, false); - } - else - _newTargetSelectTimer -= diff; + me->CastCustomSpell(SPELL_GASEOUS_BLOAT, SPELLVALUE_AURA_STACK, 10, me, false); } private: @@ -900,23 +908,12 @@ class spell_putricide_ooze_channel : public SpellScriptLoader GetCaster()->AddThreat(GetHitUnit(), 500000000.0f); // value seen in sniff } - // temporary, until SelectTarget are not called on empty lists - void CheckTarget() - { - if (_target) - return; - - FinishCast(SPELL_FAILED_NO_VALID_TARGETS); - GetCaster()->ToCreature()->DespawnOrUnsummon(1); // despawn next update - } - void Register() { OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_putricide_ooze_channel_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_putricide_ooze_channel_SpellScript::SetTarget, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_putricide_ooze_channel_SpellScript::SetTarget, EFFECT_2, TARGET_UNIT_SRC_AREA_ENEMY); AfterHit += SpellHitFn(spell_putricide_ooze_channel_SpellScript::StartAttack); - OnCast += SpellCastFn(spell_putricide_ooze_channel_SpellScript::CheckTarget); } WorldObject* _target; @@ -1125,6 +1122,22 @@ class spell_putricide_unbound_plague : public SpellScriptLoader return true; } + void FilterTargets(std::list<WorldObject*>& targets) + { + if (AuraEffect const* eff = GetCaster()->GetAuraEffect(SPELL_UNBOUND_PLAGUE_SEARCHER, EFFECT_0)) + { + if (eff->GetTickNumber() < 2) + { + targets.clear(); + return; + } + } + + + targets.remove_if(Trinity::UnitAuraCheck(true, sSpellMgr->GetSpellIdForDifficulty(SPELL_UNBOUND_PLAGUE, GetCaster()))); + Trinity::Containers::RandomResizeList(targets, 1); + } + void HandleScript(SpellEffIndex /*effIndex*/) { if (!GetHitUnit()) @@ -1159,6 +1172,7 @@ class spell_putricide_unbound_plague : public SpellScriptLoader void Register() { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_putricide_unbound_plague_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); OnEffectHitTarget += SpellEffectFn(spell_putricide_unbound_plague_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } }; 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 a8657925131..ba1a0614cdf 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -2112,7 +2112,7 @@ class spell_the_lich_king_necrotic_plague : public SpellScriptLoader CustomSpellValues values; //values.AddSpellMod(SPELLVALUE_AURA_STACK, 2); values.AddSpellMod(SPELLVALUE_MAX_TARGETS, 1); - GetTarget()->CastCustomSpell(SPELL_NECROTIC_PLAGUE_JUMP, values, NULL, true, NULL, NULL, GetCasterGUID()); + GetTarget()->CastCustomSpell(SPELL_NECROTIC_PLAGUE_JUMP, values, NULL, TRIGGERED_FULL_MASK, NULL, NULL, GetCasterGUID()); if (Unit* caster = GetCaster()) caster->CastSpell(caster, SPELL_PLAGUE_SIPHON, true); } @@ -2204,7 +2204,7 @@ class spell_the_lich_king_necrotic_plague_jump : public SpellScriptLoader CustomSpellValues values; values.AddSpellMod(SPELLVALUE_AURA_STACK, GetStackAmount()); - GetTarget()->CastCustomSpell(SPELL_NECROTIC_PLAGUE_JUMP, values, NULL, true, NULL, NULL, GetCasterGUID()); + GetTarget()->CastCustomSpell(SPELL_NECROTIC_PLAGUE_JUMP, values, NULL, TRIGGERED_FULL_MASK, NULL, NULL, GetCasterGUID()); if (Unit* caster = GetCaster()) caster->CastSpell(caster, SPELL_PLAGUE_SIPHON, true); } @@ -2223,7 +2223,7 @@ class spell_the_lich_king_necrotic_plague_jump : public SpellScriptLoader CustomSpellValues values; values.AddSpellMod(SPELLVALUE_AURA_STACK, GetStackAmount()); values.AddSpellMod(SPELLVALUE_BASE_POINT1, AURA_REMOVE_BY_ENEMY_SPELL); // add as marker (spell has no effect 1) - GetTarget()->CastCustomSpell(SPELL_NECROTIC_PLAGUE_JUMP, values, NULL, true, NULL, NULL, GetCasterGUID()); + GetTarget()->CastCustomSpell(SPELL_NECROTIC_PLAGUE_JUMP, values, NULL, TRIGGERED_FULL_MASK, NULL, NULL, GetCasterGUID()); if (Unit* caster = GetCaster()) caster->CastSpell(caster, SPELL_PLAGUE_SIPHON, true); diff --git a/src/server/scripts/Northrend/Nexus/Oculus/boss_eregos.cpp b/src/server/scripts/Northrend/Nexus/Oculus/boss_eregos.cpp index 708ed600933..76237fe1890 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/boss_eregos.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/boss_eregos.cpp @@ -113,6 +113,13 @@ enum EmeraldDrake SPELL_EMERALD_DREAM_FUNNEL = 50344 //(60 yds) - Channeled - Transfers 5% of the caster's max health to a friendly drake every second for 10 seconds as long as the caster channels. }; +enum EregosData +{ + DATA_RUBY_VOID = 0, // http://www.wowhead.com/achievement=2044 + DATA_EMERALD_VOID = 1, // http://www.wowhead.com/achievement=2045 + DATA_AMBER_VOID = 2 // http://www.wowhead.com/achievement=2046 +}; + class boss_eregos : public CreatureScript { public: @@ -126,12 +133,15 @@ public: struct boss_eregosAI : public BossAI { boss_eregosAI(Creature* creature) : BossAI(creature, DATA_EREGOS_EVENT) { } - + void Reset() { _Reset(); + _phase = PHASE_NORMAL; - phase = PHASE_NORMAL; + _rubyVoid = true; + _emeraldVoid = true; + _amberVoid = true; DoAction(ACTION_SET_NORMAL_EVENTS); } @@ -141,6 +151,31 @@ public: _EnterCombat(); Talk(SAY_AGGRO); + /* Checks for present drakes vehicles from each type and deactivate achievement that corresponds to each found + The checks are so big in case some party try weird things like pulling boss down or hiding out of check range, the only thing player need is to get the boss kill credit after the check /even if he or his drake die/ + Drakes mechanic would despawn all after unmount and also drakes should be auto mounted after item use, item use after Eregos is engaged leads to his despawn - based on retail data. */ + if (me->FindNearestCreature(NPC_RUBY_DRAKE_VEHICLE, 500.0f, true)) + _rubyVoid = false; + if (me->FindNearestCreature(NPC_EMERALD_DRAKE_VEHICLE, 500.0f, true)) + _emeraldVoid = false; + if (me->FindNearestCreature(NPC_AMBER_DRAKE_VEHICLE, 500.0f, true)) + _amberVoid = false; + } + + uint32 GetData(uint32 type) + { + switch (type) + { + case DATA_RUBY_VOID: + return _rubyVoid; + case DATA_EMERALD_VOID: + return _emeraldVoid; + case DATA_AMBER_VOID: + return _amberVoid; + default: + break; + } + return 0; } void DoAction(const int32 action) @@ -180,11 +215,11 @@ public: if (!me->GetMap()->IsHeroic()) return; - if ( (me->GetHealthPct() < 60.0f && me->GetHealthPct() > 20.0f && phase < PHASE_FIRST_PLANAR) - || (me->GetHealthPct() < 20.0f && phase < PHASE_SECOND_PLANAR) ) + if ( (me->GetHealthPct() < 60.0f && me->GetHealthPct() > 20.0f && _phase < PHASE_FIRST_PLANAR) + || (me->GetHealthPct() < 20.0f && _phase < PHASE_SECOND_PLANAR) ) { events.Reset(); - phase = (me->GetHealthPct() < 60.0f && me->GetHealthPct() > 20.0f) ? PHASE_FIRST_PLANAR : PHASE_SECOND_PLANAR; + _phase = (me->GetHealthPct() < 60.0f && me->GetHealthPct() > 20.0f) ? PHASE_FIRST_PLANAR : PHASE_SECOND_PLANAR; DoCast(SPELL_PLANAR_SHIFT); @@ -241,8 +276,11 @@ public: _JustDied(); } - private: - uint8 phase; + private: + uint8 _phase; + bool _rubyVoid; + bool _emeraldVoid; + bool _amberVoid; }; }; @@ -274,8 +312,25 @@ class spell_eregos_planar_shift : public SpellScriptLoader } }; -void AddSC_boss_eregos() +class achievement_gen_eregos_void : public AchievementCriteriaScript { + public: + achievement_gen_eregos_void(char const* name, uint32 data) : AchievementCriteriaScript(name), _data(data) { } + + bool OnCheck(Player* /*player*/, Unit* target) + { + return target && target->GetAI()->GetData(_data); + } + + private: + uint32 _data; +}; + + void AddSC_boss_eregos() + { new boss_eregos(); new spell_eregos_planar_shift(); -} + new achievement_gen_eregos_void("achievement_ruby_void", DATA_RUBY_VOID); + new achievement_gen_eregos_void("achievement_emerald_void", DATA_EMERALD_VOID); + new achievement_gen_eregos_void("achievement_amber_void", DATA_AMBER_VOID); + } 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 7ee67060f97..dcd3a3a91f5 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 @@ -1328,7 +1328,7 @@ class spell_algalon_supermassive_fail : public SpellScriptLoader if (!GetHitPlayer()) return; - GetHitPlayer()->GetAchievementMgr().ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, ACHIEVEMENT_CRITERIA_CONDITION_NO_SPELL_HIT, GetSpellInfo()->Id, true); + GetHitPlayer()->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, ACHIEVEMENT_CRITERIA_CONDITION_NO_SPELL_HIT, GetSpellInfo()->Id, true); } void Register() diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp index 48667053373..aaa95631792 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp @@ -56,13 +56,16 @@ enum Events EVENT_DARK_SMASH, EVENT_DREADFUL_ROAR, EVENT_WOE_STRIKE, - EVENT_SHADOW_AXE + EVENT_SHADOW_AXE, + EVENT_JUST_TRANSFORMED, + EVENT_SUMMON_BANSHEE }; enum Phases { PHASE_HUMAN = 1, PHASE_UNDEAD, + PHASE_EVENT }; enum Spells @@ -83,7 +86,7 @@ enum Spells SPELL_WOE_STRIKE = 42730, ENTRY_THROW_TARGET = 23996, - SPELL_SHADOW_AXE_SUMMON = 42749 + SPELL_SHADOW_AXE_SUMMON = 42748 }; class boss_ingvar_the_plunderer : public CreatureScript @@ -107,9 +110,6 @@ public: InstanceScript* instance; bool bIsUndead; - bool bEventInProgress; - - uint32 uiSpawnResTimer; void Reset() { @@ -117,7 +117,6 @@ public: me->UpdateEntry(MOB_INGVAR_HUMAN); bIsUndead = false; - bEventInProgress = false; me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); me->SetStandState(UNIT_STAND_STATE_STAND); @@ -130,13 +129,6 @@ public: events.ScheduleEvent(EVENT_ENRAGE, urand(7,14)*IN_MILLISECONDS, 0, PHASE_HUMAN); events.ScheduleEvent(EVENT_SMASH, urand(12,17)*IN_MILLISECONDS, 0, PHASE_HUMAN); - events.ScheduleEvent(EVENT_DARK_SMASH, urand(14,22)*IN_MILLISECONDS, 0, PHASE_UNDEAD); - events.ScheduleEvent(EVENT_DREADFUL_ROAR, urand(18,21)*IN_MILLISECONDS, 0, PHASE_UNDEAD); - events.ScheduleEvent(EVENT_WOE_STRIKE, urand(10,14)*IN_MILLISECONDS, 0, PHASE_UNDEAD); - events.ScheduleEvent(EVENT_SHADOW_AXE, 30*IN_MILLISECONDS, 0, PHASE_UNDEAD); - - uiSpawnResTimer = 3000; - if (instance) instance->SetData(DATA_INGVAR_EVENT, NOT_STARTED); } @@ -156,37 +148,34 @@ public: me->SetStandState(UNIT_STAND_STATE_DEAD); // visuel hack end - bEventInProgress = true; - bIsUndead = true; - events.SetPhase(PHASE_UNDEAD); + events.SetPhase(PHASE_EVENT); + events.ScheduleEvent(EVENT_SUMMON_BANSHEE, 3 * IN_MILLISECONDS, 0, PHASE_EVENT); DoScriptText(YELL_DEAD_1, me); } - if (bEventInProgress) - { + if (events.GetPhaseMask() & (1 << PHASE_EVENT)) damage = 0; - } } void StartZombiePhase() { bIsUndead = true; - bEventInProgress = false; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); me->UpdateEntry(MOB_INGVAR_UNDEAD); - me->SetInCombatWith(me->getVictim()); - me->GetMotionMaster()->MoveChase(me->getVictim()); + events.ScheduleEvent(EVENT_JUST_TRANSFORMED, 2 * IN_MILLISECONDS, 0, PHASE_EVENT); DoScriptText(YELL_AGGRO_2, me); } void EnterCombat(Unit* /*who*/) { - DoScriptText(YELL_AGGRO_1, me); + if (!bIsUndead) + DoScriptText(YELL_AGGRO_1, me); if (instance) instance->SetData(DATA_INGVAR_EVENT, IN_PROGRESS); + + me->SetInCombatWithZone(); } void JustDied(Unit* /*killer*/) @@ -201,6 +190,15 @@ public: } } + void ScheduleSecondPhase() + { + events.SetPhase(PHASE_UNDEAD); + events.ScheduleEvent(EVENT_DARK_SMASH, urand(14,18)*IN_MILLISECONDS, 0, PHASE_UNDEAD); + events.ScheduleEvent(EVENT_DREADFUL_ROAR, urand(18,22)*IN_MILLISECONDS, 0, PHASE_UNDEAD); + events.ScheduleEvent(EVENT_WOE_STRIKE, urand(10,14)*IN_MILLISECONDS, 0, PHASE_UNDEAD); + events.ScheduleEvent(EVENT_SHADOW_AXE, 30*IN_MILLISECONDS, 0, PHASE_UNDEAD); + } + void KilledUnit(Unit* /*victim*/) { if (bIsUndead) @@ -211,24 +209,9 @@ public: void UpdateAI(const uint32 diff) { - if (!UpdateVictim()) + if (!UpdateVictim() && !(events.GetPhaseMask() & (1 << PHASE_EVENT))) return; - if (bEventInProgress) - { - if (uiSpawnResTimer) - { - if (uiSpawnResTimer <= diff) - { - DoCast(me, SPELL_SUMMON_BANSHEE); // Summons directly on caster position - // DoCast(me, SPELL_SCOURG_RESURRECTION, true); // Not needed ? - uiSpawnResTimer = 0; - } else uiSpawnResTimer -= diff; - } - - return; - } - events.Update(diff); if (me->HasUnitState(UNIT_STATE_CASTING)) @@ -245,24 +228,33 @@ public: break; case EVENT_STAGGERING_ROAR: DoCast(me, SPELL_STAGGERING_ROAR); - events.ScheduleEvent(EVENT_STAGGERING_ROAR, urand(18,21)*IN_MILLISECONDS, 0, PHASE_HUMAN); + events.ScheduleEvent(EVENT_STAGGERING_ROAR, urand(18,22)*IN_MILLISECONDS, 0, PHASE_HUMAN); break; case EVENT_ENRAGE: DoCast(me, SPELL_ENRAGE); events.ScheduleEvent(EVENT_ENRAGE, urand(7,14)*IN_MILLISECONDS, 0, PHASE_HUMAN); break; case EVENT_SMASH: - DoCastVictim(SPELL_SMASH); - events.ScheduleEvent(EVENT_SMASH, urand(12,17)*IN_MILLISECONDS, 0, PHASE_HUMAN); + DoCastAOE(SPELL_SMASH); + events.ScheduleEvent(EVENT_SMASH, urand(12,16)*IN_MILLISECONDS, 0, PHASE_HUMAN); break; + case EVENT_JUST_TRANSFORMED: + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetInCombatWithZone(); + me->GetMotionMaster()->MoveChase(me->getVictim()); + ScheduleSecondPhase(); + return; + case EVENT_SUMMON_BANSHEE: + DoCast(me, SPELL_SUMMON_BANSHEE); + return; // PHASE TWO case EVENT_DARK_SMASH: DoCastVictim(SPELL_DARK_SMASH); - events.ScheduleEvent(EVENT_DARK_SMASH, urand(14,22)*IN_MILLISECONDS, 0, PHASE_UNDEAD); + events.ScheduleEvent(EVENT_DARK_SMASH, urand(12,16)*IN_MILLISECONDS, 0, PHASE_UNDEAD); break; case EVENT_DREADFUL_ROAR: DoCast(me, SPELL_DREADFUL_ROAR); - events.ScheduleEvent(EVENT_DREADFUL_ROAR, urand(18,21)*IN_MILLISECONDS, 0, PHASE_UNDEAD); + events.ScheduleEvent(EVENT_DREADFUL_ROAR, urand(18,22)*IN_MILLISECONDS, 0, PHASE_UNDEAD); break; case EVENT_WOE_STRIKE: DoCastVictim(SPELL_WOE_STRIKE); @@ -271,8 +263,7 @@ public: case EVENT_SHADOW_AXE: if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1)) { - me->SummonCreature(ENTRY_THROW_TARGET, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 2000); - DoCast(me, SPELL_SHADOW_AXE_SUMMON); + DoCast(target, SPELL_SHADOW_AXE_SUMMON); } events.ScheduleEvent(EVENT_SHADOW_AXE, 30*IN_MILLISECONDS, 0, PHASE_UNDEAD); break; @@ -411,7 +402,8 @@ public: enum eShadowAxe { SPELL_SHADOW_AXE_DAMAGE = 42750, - H_SPELL_SHADOW_AXE_DAMAGE = 59719 + H_SPELL_SHADOW_AXE_DAMAGE = 59719, + POINT_TARGET = 28 }; class mob_ingvar_throw_dummy : public CreatureScript @@ -430,32 +422,34 @@ public: { } - uint32 uiDespawnTimer; - void Reset() { - Unit* target = me->FindNearestCreature(ENTRY_THROW_TARGET, 50); - if (target) + if (Creature* target = me->FindNearestCreature(ENTRY_THROW_TARGET, 50.0f)) { - DoCast(me, SPELL_SHADOW_AXE_DAMAGE); float x, y, z; target->GetPosition(x, y, z); - me->GetMotionMaster()->MovePoint(0, x, y, z); + me->GetMotionMaster()->MoveCharge(x, y, z, 42.0f, POINT_TARGET); + target->DisappearAndDie(); + } + else + { + me->DisappearAndDie(); } - uiDespawnTimer = 7000; } - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void EnterCombat(Unit* /*who*/) {} - void UpdateAI(const uint32 diff) + void MovementInform(uint32 type, uint32 id) { - if (uiDespawnTimer <= diff) + if (type == EFFECT_MOTION_TYPE && id == POINT_TARGET) { - me->DealDamage(me, me->GetHealth()); - me->RemoveCorpse(); - uiDespawnTimer = 0; - } else uiDespawnTimer -= diff; + DoCast(me, SPELL_SHADOW_AXE_DAMAGE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + if (TempSummon* summon = me->ToTempSummon()) + { + summon->UnSummon(10000); + } + else + me->DisappearAndDie(); + } } }; }; diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp index f53020a72c4..e718942d091 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp @@ -43,6 +43,9 @@ enum KelsethEncounter NPC_FROSTTOMB = 23965, NPC_SKELETON = 23970, + NPC_RUNEMAGE = 23960, + NPC_STRATEGIST = 23956, + SAY_START_COMBAT = 1, SAY_SUMMON_SKELETONS, SAY_FROST_TOMB, @@ -118,14 +121,12 @@ public: struct boss_kelesethAI : public BossAI { - boss_kelesethAI(Creature* creature) : BossAI(creature, DATA_PRINCEKELESETH_EVENT) - { - creature->SetReactState(REACT_DEFENSIVE); - } + boss_kelesethAI(Creature* creature) : BossAI(creature, DATA_PRINCEKELESETH_EVENT){} void Reset() { - instance->SetData(DATA_PRINCEKELESETH_EVENT, NOT_STARTED); + if (instance) + instance->SetData(DATA_PRINCEKELESETH_EVENT, NOT_STARTED); events.Reset(); events.ScheduleEvent(EVENT_SHADOWBOLT, urand(2,3)*IN_MILLISECONDS); @@ -137,16 +138,43 @@ public: onTheRocks = true; } - void EnterCombat(Unit* /*who*/) + void EnterCombat(Unit* who) { me->SetInCombatWithZone(); - instance->SetData(DATA_PRINCEKELESETH_EVENT, IN_PROGRESS); + if (instance) + instance->SetData(DATA_PRINCEKELESETH_EVENT, IN_PROGRESS); Talk(SAY_START_COMBAT); + + if (!who) + return; + + std::list<Creature*> runemages; + me->GetCreatureListWithEntryInGrid(runemages, NPC_RUNEMAGE, 60.0f); + if (!runemages.empty()) + { + for (std::list<Creature*>::iterator itr = runemages.begin(); itr != runemages.end(); ++itr) + { + if ((*itr)->isAlive() && (*itr)->IsWithinLOSInMap(me)) + (*itr)->AI()->AttackStart(who); + } + } + + std::list<Creature*> strategists; + me->GetCreatureListWithEntryInGrid(strategists, NPC_STRATEGIST, 60.0f); + if (!strategists.empty()) + { + for (std::list<Creature*>::iterator itr = strategists.begin(); itr != strategists.end(); ++itr) + { + if ((*itr)->isAlive() && (*itr)->IsWithinLOSInMap(me)) + (*itr)->AI()->AttackStart(who); + } + } } void JustDied(Unit* /*killer*/) { - instance->SetData(DATA_PRINCEKELESETH_EVENT, DONE); + if (instance) + instance->SetData(DATA_PRINCEKELESETH_EVENT, DONE); summons.DespawnAll(); Talk(SAY_DEATH); } @@ -165,10 +193,20 @@ public: return 0; } - void ExecuteEvent(uint32 const eventId) + void UpdateAI(uint32 const diff) { - switch (eventId) + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) { + switch (eventId) + { case EVENT_SUMMON_SKELETONS: Talk(SAY_SUMMON_SKELETONS); SummonSkeletons(); @@ -189,7 +227,10 @@ public: } events.ScheduleEvent(EVENT_FROST_TOMB, urand(14,19)*IN_MILLISECONDS); break; + } } + + DoMeleeAttackIfReady(); } void SummonSkeletons() @@ -222,7 +263,6 @@ public: events.Reset(); events.ScheduleEvent(EVENT_DECREPIFY, urand(4,6)*IN_MILLISECONDS); - DoCast(SPELL_BONE_ARMOR); } void DamageTaken(Unit* /*done_by*/, uint32 &damage) @@ -275,6 +315,13 @@ public: break; case EVENT_SHADOW_FISSURE: DoCast(me, SPELL_SHADOW_FISSURE, true); + if (TempSummon* temp = me->ToTempSummon()) + { + if (Unit* summoner = temp->GetSummoner()) + { + DoCast(summoner, SPELL_BONE_ARMOR); + } + } me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->RemoveFlag(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD); me->GetMotionMaster()->MoveChase(me->getVictim()); diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp index be8d60fbeb9..7c977250e79 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp @@ -47,6 +47,7 @@ enum eEnums SPELL_CHARGE = 43651, SPELL_STONE_STRIKE = 48583, SPELL_SUMMON_SKARVALD_GHOST = 48613, + SPELL_ENRAGE = 48193, MOB_SKARVALD_GHOST = 27390, //Spells of Dalronn and his Ghost MOB_DALRONN_THE_CONTROLLER = 24201, @@ -58,6 +59,20 @@ enum eEnums MOB_DALRONN_GHOST = 27389 }; +class SkarvaldChargePredicate +{ + public: + SkarvaldChargePredicate(Unit* unit) : me(unit) {} + + bool operator() (WorldObject* object) const + { + return object->GetDistance2d(me) >= 5.0f && object->GetDistance2d(me) <= 30.0f; + } + + private: + Unit* me; +}; + class boss_skarvald_the_constructor : public CreatureScript { public: @@ -83,6 +98,7 @@ public: uint32 Response_Timer; uint32 Check_Timer; bool Dalronn_isDead; + bool Enraged; void Reset() { @@ -90,6 +106,7 @@ public: StoneStrike_Timer = 10000; Dalronn_isDead = false; Check_Timer = 5000; + Enraged = false; ghost = (me->GetEntry() == MOB_SKARVALD_GHOST); if (!ghost && instance) @@ -116,6 +133,15 @@ public: } } + void DamageTaken(Unit* /*attacker*/, uint32& damage) + { + if (!Enraged && !ghost && me->HealthBelowPctDamaged(15, damage)) + { + Enraged = true; + DoCast(me, SPELL_ENRAGE); + } + } + void JustDied(Unit* killer) { if (!ghost && instance) @@ -194,7 +220,7 @@ public: if (Charge_Timer <= diff) { - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 1), SPELL_CHARGE); + DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, SkarvaldChargePredicate(me)), SPELL_CHARGE); Charge_Timer = 5000+rand()%5000; } else Charge_Timer -= diff; @@ -204,7 +230,8 @@ public: StoneStrike_Timer = 5000+rand()%5000; } else StoneStrike_Timer -= diff; - DoMeleeAttackIfReady(); + if (!me->HasUnitState(UNIT_STATE_CASTING)) + DoMeleeAttackIfReady(); } }; diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp index 2d53e7062eb..35bf7ee0b10 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp @@ -18,6 +18,8 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "utgarde_keep.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" uint32 entry_search[3] = { @@ -164,7 +166,82 @@ public: }; }; +enum TickingTimeBomb +{ + SPELL_TICKING_TIME_BOMB_EXPLODE = 59687 +}; +class spell_ticking_time_bomb : public SpellScriptLoader +{ + public: + spell_ticking_time_bomb() : SpellScriptLoader("spell_ticking_time_bomb") { } + + class spell_ticking_time_bomb_AuraScript : public AuraScript + { + PrepareAuraScript(spell_ticking_time_bomb_AuraScript); + + bool Validate(SpellInfo const* /*spellEntry*/) + { + return (bool) sSpellMgr->GetSpellInfo(SPELL_TICKING_TIME_BOMB_EXPLODE); + } + + void HandleOnEffectRemove(AuraEffect const* /* aurEff */, AuraEffectHandleModes /* mode */) + { + if (GetCaster() == GetTarget()) + { + GetTarget()->CastSpell(GetTarget(), SPELL_TICKING_TIME_BOMB_EXPLODE, true); + } + } + + void Register() + { + OnEffectRemove += AuraEffectRemoveFn(spell_ticking_time_bomb_AuraScript::HandleOnEffectRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_ticking_time_bomb_AuraScript(); + } +}; + +enum Fixate +{ + SPELL_FIXATE_TRIGGER = 40415 +}; +class spell_fixate : public SpellScriptLoader +{ + public: + spell_fixate() : SpellScriptLoader("spell_fixate") { } + + class spell_fixate_SpellScript : public SpellScript + { + PrepareSpellScript(spell_fixate_SpellScript); + + bool Validate(SpellInfo const* /*spellEntry*/) + { + return (bool) sSpellMgr->GetSpellInfo(SPELL_FIXATE_TRIGGER); + } + + void HandleScriptEffect(SpellEffIndex /*effIndex*/) + { + // The unit has to cast the taunt on hisself, but we need the original caster for SPELL_AURA_MOD_TAUNT + GetCaster()->CastSpell(GetCaster(), SPELL_FIXATE_TRIGGER, true, 0, 0, GetHitUnit()->GetGUID()); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_fixate_SpellScript::HandleScriptEffect, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_fixate_SpellScript(); + } +}; void AddSC_utgarde_keep() { new npc_dragonflayer_forge_master(); + new spell_ticking_time_bomb(); + new spell_fixate(); } diff --git a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp index 122d051f1dd..870ea893b78 100644 --- a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp +++ b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp @@ -782,10 +782,13 @@ struct violet_hold_trashAI : public npc_escortAI void JustDied(Unit* /*killer*/) { - if (Creature* portal = Unit::GetCreature((*me), instance->GetData64(DATA_TELEPORTATION_PORTAL))) - CAST_AI(npc_teleportation_portal_vh::npc_teleportation_portalAI, portal->AI())->SummonedMobDied(me); if (instance) + { + if (Creature* portal = Unit::GetCreature((*me), instance->GetData64(DATA_TELEPORTATION_PORTAL))) + CAST_AI(npc_teleportation_portal_vh::npc_teleportation_portalAI, portal->AI())->SummonedMobDied(me); + instance->SetData(DATA_NPC_PRESENCE_AT_DOOR_REMOVE, 1); + } } void CreatureStartAttackDoor() diff --git a/src/server/scripts/Northrend/borean_tundra.cpp b/src/server/scripts/Northrend/borean_tundra.cpp index 9b207c257fc..f4139f2ffc2 100644 --- a/src/server/scripts/Northrend/borean_tundra.cpp +++ b/src/server/scripts/Northrend/borean_tundra.cpp @@ -1667,7 +1667,6 @@ public: /*###### ## npc_imprisoned_beryl_sorcerer ######*/ - enum eImprisionedBerylSorcerer { SPELL_NEURAL_NEEDLE = 45634, @@ -1692,103 +1691,81 @@ public: { npc_imprisoned_beryl_sorcererAI(Creature* creature) : ScriptedAI(creature) {} - uint64 CasterGUID; - - uint32 uiStep; - uint32 uiPhase; + uint32 rebuff; void Reset() { - uiStep = 1; - uiPhase = 0; - CasterGUID = 0; + if (me->GetReactState() != REACT_PASSIVE) + { + me->SetReactState(REACT_PASSIVE); + } + + rebuff = 0; + } + + void UpdateAI(const uint32 diff) + { + UpdateVictim(); + + if (rebuff <= diff) + { + if (!me->HasAura(SPELL_COSMETIC_ENSLAVE_CHAINS_SELF)) + { + DoCast(me, SPELL_COSMETIC_ENSLAVE_CHAINS_SELF); + } + rebuff = 180000; + } + else + rebuff -= diff; + + DoMeleeAttackIfReady(); } void EnterCombat(Unit* /*who*/) { } - void SpellHit(Unit* unit, const SpellInfo* pSpell) + void SpellHit(Unit* unit, const SpellInfo* spell) { - if (pSpell->Id == SPELL_NEURAL_NEEDLE && unit->GetTypeId() == TYPEID_PLAYER) + if (spell->Id == SPELL_NEURAL_NEEDLE && unit->GetTypeId() == TYPEID_PLAYER) { - ++uiPhase; - CasterGUID = unit->GetGUID(); + if (Player* player = unit->ToPlayer()) + { + GotStinged(player->GetGUID()); + } } } - void UpdateAI(const uint32 uiDiff) + void GotStinged(uint64 casterGUID) { - ScriptedAI::UpdateAI(uiDiff); - - if (!me->HasAura(SPELL_COSMETIC_ENSLAVE_CHAINS_SELF)) - DoCast(me, SPELL_COSMETIC_ENSLAVE_CHAINS_SELF); - - if (me->GetReactState() != REACT_PASSIVE) - me->SetReactState(REACT_PASSIVE); - - switch (uiPhase) + if(Player* caster = Player::GetPlayer(*me, casterGUID)) { + uint32 step = caster->GetAuraCount(SPELL_NEURAL_NEEDLE) + 1; + switch (step) + { case 1: - if (uiStep == 1) - { - DoScriptText(SAY_IMPRISIONED_BERYL_1, me); - uiStep = 2; - } + DoScriptText(SAY_IMPRISIONED_BERYL_1, me); break; - case 2: - if (uiStep == 2) - { - DoScriptText(SAY_IMPRISIONED_BERYL_2, me); - uiStep = 3; - } + DoScriptText(SAY_IMPRISIONED_BERYL_2, me, caster); break; - case 3: - if (uiStep == 3) - { - DoScriptText(SAY_IMPRISIONED_BERYL_3, me); - uiStep = 4; - } + DoScriptText(SAY_IMPRISIONED_BERYL_3, me); break; - case 4: - if (uiStep == 4) - { - DoScriptText(SAY_IMPRISIONED_BERYL_4, me); - uiStep = 5; - } + DoScriptText(SAY_IMPRISIONED_BERYL_4, me); break; - case 5: - if (uiStep == 5) - { - if (Player* pCaster = Unit::GetPlayer(*me, CasterGUID)) - { - DoScriptText(SAY_IMPRISIONED_BERYL_5, me); - pCaster->KilledMonsterCredit(25478, 0); - uiStep = 6; - } - } + DoScriptText(SAY_IMPRISIONED_BERYL_5, me); break; - case 6: - if (uiStep == 6) - { - DoScriptText(SAY_IMPRISIONED_BERYL_6, me); - uiStep = 7; - } + DoScriptText(SAY_IMPRISIONED_BERYL_6, me, caster); break; - case 7: - if (uiStep == 7) - { - DoScriptText(SAY_IMPRISIONED_BERYL_7, me); - uiStep = 1; - uiPhase = 0; - } + DoScriptText(SAY_IMPRISIONED_BERYL_7, me); + caster->KilledMonsterCredit(25478, 0); break; + } } } }; diff --git a/src/server/scripts/Northrend/dragonblight.cpp b/src/server/scripts/Northrend/dragonblight.cpp index 1f1d24453ee..a26ee4e9270 100644 --- a/src/server/scripts/Northrend/dragonblight.cpp +++ b/src/server/scripts/Northrend/dragonblight.cpp @@ -190,7 +190,7 @@ class npc_wyrmrest_defender : public CreatureScript npc_wyrmrest_defender() : CreatureScript("npc_wyrmrest_defender") { } bool OnGossipHello(Player* player, Creature* creature) - { + { if (player->GetQuestStatus(QUEST_DEFENDING_WYRMREST_TEMPLE) == QUEST_STATUS_INCOMPLETE) { player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); diff --git a/src/server/scripts/Northrend/storm_peaks.cpp b/src/server/scripts/Northrend/storm_peaks.cpp index 60c289dc8de..976a6e5dba5 100644 --- a/src/server/scripts/Northrend/storm_peaks.cpp +++ b/src/server/scripts/Northrend/storm_peaks.cpp @@ -20,6 +20,7 @@ #include "ScriptedGossip.h" #include "ScriptedEscortAI.h" #include "Vehicle.h" +#include "CombatAI.h" /*###### ## npc_agnetta_tyrsdottar @@ -131,132 +132,6 @@ public: } }; -/*###### -## npc_thorim -######*/ - -#define GOSSIP_HN "Thorim?" -#define GOSSIP_SN1 "Can you tell me what became of Sif?" -#define GOSSIP_SN2 "He did more than that, Thorim. He controls Ulduar now." -#define GOSSIP_SN3 "It needn't end this way." - -enum eThorim -{ - QUEST_SIBLING_RIVALRY = 13064, - NPC_THORIM = 29445, - GOSSIP_TEXTID_THORIM1 = 13799, - GOSSIP_TEXTID_THORIM2 = 13801, - GOSSIP_TEXTID_THORIM3 = 13802, - GOSSIP_TEXTID_THORIM4 = 13803 -}; - -class npc_thorim : public CreatureScript -{ -public: - npc_thorim() : CreatureScript("npc_thorim") { } - - bool OnGossipHello(Player* player, Creature* creature) - { - if (creature->isQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (player->GetQuestStatus(QUEST_SIBLING_RIVALRY) == QUEST_STATUS_INCOMPLETE) { - player->ADD_GOSSIP_ITEM(0, GOSSIP_HN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_THORIM1, creature->GetGUID()); - return true; - } - return false; - } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) - { - player->PlayerTalkClass->ClearMenus(); - switch (action) - { - case GOSSIP_ACTION_INFO_DEF+1: - player->ADD_GOSSIP_ITEM(0, GOSSIP_SN1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_THORIM2, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - player->ADD_GOSSIP_ITEM(0, GOSSIP_SN2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_THORIM3, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - player->ADD_GOSSIP_ITEM(0, GOSSIP_SN3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_THORIM4, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - player->CLOSE_GOSSIP_MENU(); - player->CompleteQuest(QUEST_SIBLING_RIVALRY); - break; - } - return true; - } -}; - -/*###### -## npc_loklira_crone -######*/ - -#define GOSSIP_LOKLIRACRONE "Tell me about this proposal" -#define GOSSIP_LOKLIRACRONE1 "What happened then?" -#define GOSSIP_LOKLIRACRONE2 "You want me to take part in the Hyldsmeet to end the war?" -#define GOSSIP_LOKLIRACRONE3 "Very well. I'll take part in this competition." - -enum eLokliraCrone -{ - QUEST_HYLDSMEET = 12970, - - GOSSIP_TEXTID_LOK1 = 13778, - GOSSIP_TEXTID_LOK2 = 13779, - GOSSIP_TEXTID_LOK3 = 13780 -}; - -class npc_loklira_crone : public CreatureScript -{ -public: - npc_loklira_crone() : CreatureScript("npc_loklira_crone") { } - - bool OnGossipHello(Player* player, Creature* creature) - { - if (creature->isQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (player->GetQuestStatus(QUEST_HYLDSMEET) == QUEST_STATUS_INCOMPLETE) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOKLIRACRONE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - return true; - } - return false; - } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) - { - player->PlayerTalkClass->ClearMenus(); - switch (action) - { - case GOSSIP_ACTION_INFO_DEF+1: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOKLIRACRONE1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_LOK1, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOKLIRACRONE2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_LOK2, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOKLIRACRONE3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_LOK3, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - player->CLOSE_GOSSIP_MENU(); - player->CompleteQuest(QUEST_HYLDSMEET); - break; - } - return true; - } -}; - ///////////////////// ///npc_injured_goblin ///////////////////// @@ -409,14 +284,12 @@ public: ## npc_brunnhildar_prisoner ######*/ -enum brunhildar { - NPC_QUEST_GIVER = 29592, - +enum BrunnhildarPrisoner { SPELL_ICE_PRISON = 54894, - SPELL_KILL_CREDIT_PRISONER = 55144, - SPELL_KILL_CREDIT_DRAKE = 55143, - SPELL_SUMMON_LIBERATED = 55073, - SPELL_ICE_LANCE = 55046 + SPELL_ICE_LANCE = 55046, + SPELL_FREE_PRISONER = 55048, + SPELL_RIDE_DRAKE = 55074, + SPELL_SHARD_IMPACT = 55047 }; class npc_brunnhildar_prisoner : public CreatureScript @@ -428,129 +301,169 @@ public: { npc_brunnhildar_prisonerAI(Creature* creature) : ScriptedAI(creature) {} - uint64 drakeGUID; - uint16 enter_timer; - bool hasEmptySeats; + bool freed; void Reset() { + freed = false; me->CastSpell(me, SPELL_ICE_PRISON, true); - enter_timer = 0; - drakeGUID = 0; - hasEmptySeats = false; } - void UpdateAI(const uint32 diff) + void JustRespawned() { - //TODO: not good script - if (!drakeGUID) + Reset(); + } + + void UpdateAI(const uint32 /*diff*/) + { + if (!freed) return; - Creature* drake = Unit::GetCreature(*me, drakeGUID); - if (!drake) + if (!me->HasUnitState(UNIT_STATE_ONVEHICLE)) { - drakeGUID = 0; - return; + me->DespawnOrUnsummon(); } + } - // drake unsummoned, passengers dropped - if (!me->IsOnVehicle(drake) && !hasEmptySeats) - me->DespawnOrUnsummon(3000); - - if (enter_timer <= 0) + void SpellHit(Unit* caster, const SpellInfo* spell) + { + if (spell->Id != SPELL_ICE_LANCE) return; - if (enter_timer < diff) + if (caster->GetVehicleKit()->GetAvailableSeatCount() != 0) { - enter_timer = 0; - if (hasEmptySeats) - me->JumpTo(drake, 25.0f); - else - Reset(); + me->CastSpell(me, SPELL_FREE_PRISONER, true); + me->CastSpell(caster, SPELL_RIDE_DRAKE, true); + me->CastSpell(me, SPELL_SHARD_IMPACT, true); + freed = true; } - else - enter_timer -= diff; } + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_brunnhildar_prisonerAI(creature); + } +}; + +/*###### +## npc_freed_protodrake +######*/ + +enum FreedProtoDrake +{ + AREA_VALLEY_OF_ANCIENT_WINTERS = 4437, + TEXT_EMOTE = 0, + SPELL_KILL_CREDIT_PRISONER = 55144, + SPELL_SUMMON_LIBERATED = 55073, + SPELL_KILL_CREDIT_DRAKE = 55143 +}; + +const Position FreedDrakeWaypoints[16] = +{ + {7294.96f, -2418.733f, 823.869f, 0.0f}, + {7315.984f, -2331.46f, 826.3972f, 0.0f}, + {7271.826f, -2271.479f, 833.5917f, 0.0f}, + {7186.253f, -2218.475f, 847.5632f, 0.0f}, + {7113.195f, -2164.288f, 850.2301f, 0.0f}, + {7078.018f, -2063.106f, 854.7581f, 0.0f}, + {7073.221f, -1983.382f, 861.9246f, 0.0f}, + {7061.455f, -1885.899f, 865.119f, 0.0f}, + {7033.32f, -1826.775f, 876.2578f, 0.0f}, + {6999.902f, -1784.012f, 897.4521f, 0.0f}, + {6954.913f, -1747.043f, 897.4521f, 0.0f}, + {6933.856f, -1720.698f, 882.2022f, 0.0f}, + {6932.729f, -1687.306f, 866.1189f, 0.0f}, + {6952.458f, -1663.802f, 849.8133f, 0.0f}, + {7002.819f, -1651.681f, 831.397f, 0.0f}, + {7026.531f, -1649.239f, 828.8406f, 0.0f} +}; - void MoveInLineOfSight(Unit* who) + +class npc_freed_protodrake : public CreatureScript +{ +public: + npc_freed_protodrake() : CreatureScript("npc_freed_protodrake") { } + + struct npc_freed_protodrakeAI : public VehicleAI + { + npc_freed_protodrakeAI(Creature* creature) : VehicleAI(creature) {} + + bool autoMove; + bool wpReached; + uint16 CheckTimer; + uint16 countWP; + + void Reset() { - if (!who || !drakeGUID) + autoMove = false; + wpReached = false; + CheckTimer = 5000; + countWP = 0; + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) return; - Creature* drake = Unit::GetCreature(*me, drakeGUID); - if (!drake) + if (id < 15) { - drakeGUID = 0; - return; + ++countWP; + wpReached = true; } - - if (!me->IsOnVehicle(drake) && !me->HasAura(SPELL_ICE_PRISON)) + else + // drake reached village { - if (who->IsVehicle() && me->IsWithinDist(who, 25.0f, true) && who->ToCreature() && who->ToCreature()->GetEntry() == 29709) + // get player that rides drake (from seat 0) + Unit* player = me->GetVehicleKit()->GetPassenger(0); + if (player && player->GetTypeId() == TYPEID_PLAYER) { - uint8 seat = who->GetVehicleKit()->GetNextEmptySeat(0, true); - if (seat <= 0) - return; - - me->EnterVehicle(who, seat); - me->SendMovementFlagUpdate(); - hasEmptySeats = false; + // for each prisoner on drake,give credit + for (uint8 i = 1; i < 4; ++i) + if (Unit* prisoner = me->GetVehicleKit()->GetPassenger(i)) + { + if (prisoner->GetTypeId() != TYPEID_UNIT) + return; + prisoner->CastSpell(player, SPELL_KILL_CREDIT_PRISONER, true); + prisoner->CastSpell(prisoner, SPELL_SUMMON_LIBERATED, true); + prisoner->ExitVehicle(); + } + me->CastSpell(me, SPELL_KILL_CREDIT_DRAKE, true); + player->ExitVehicle(); } } + } - if (who->ToCreature() && me->IsOnVehicle(drake)) + void UpdateAI(const uint32 diff) + { + if (!autoMove) { - if (who->ToCreature()->GetEntry() == NPC_QUEST_GIVER && me->IsWithinDist(who, 15.0f, false)) + if (CheckTimer < diff) { - Unit* rider = drake->GetVehicleKit()->GetPassenger(0); - if (!rider) - return; - - rider->CastSpell(rider, SPELL_KILL_CREDIT_PRISONER, true); - - me->ExitVehicle(); - me->CastSpell(me, SPELL_SUMMON_LIBERATED, true); - me->DespawnOrUnsummon(500); - - // drake is empty now, deliver credit for drake and despawn him - if (drake->GetVehicleKit()->HasEmptySeat(1) && - drake->GetVehicleKit()->HasEmptySeat(2) && - drake->GetVehicleKit()->HasEmptySeat(3)) + CheckTimer = 5000; + if (me->GetAreaId() == AREA_VALLEY_OF_ANCIENT_WINTERS) { - // not working rider->CastSpell(rider, SPELL_KILL_CREDIT_DRAKE, true); - if (rider->ToPlayer()) - rider->ToPlayer()->KilledMonsterCredit(29709, 0); - - drake->DespawnOrUnsummon(0); + Talk(TEXT_EMOTE, me->GetVehicleKit()->GetPassenger(0)->GetGUID()); + autoMove = true; + wpReached = true; } } + else + CheckTimer -= diff; } - } - - void SpellHit(Unit* hitter, const SpellInfo* spell) - { - if (!hitter || !spell) - return; - - if (spell->Id != SPELL_ICE_LANCE) - return; - me->RemoveAura(SPELL_ICE_PRISON); - enter_timer = 500; - - if (hitter->IsVehicle()) - drakeGUID = hitter->GetGUID(); - else - return; - - if (hitter->GetVehicleKit()->GetNextEmptySeat(0, true)) - hasEmptySeats = true; + if (wpReached && autoMove) + { + wpReached = false; + me->GetMotionMaster()->MovePoint(countWP, FreedDrakeWaypoints[countWP]); + } } }; CreatureAI* GetAI(Creature* creature) const { - return new npc_brunnhildar_prisonerAI(creature); + return new npc_freed_protodrakeAI(creature); } }; @@ -655,11 +568,10 @@ void AddSC_storm_peaks() { new npc_agnetta_tyrsdottar(); new npc_frostborn_scout(); - new npc_thorim(); - new npc_loklira_crone(); new npc_injured_goblin(); new npc_roxi_ramrocket(); new npc_brunnhildar_prisoner(); + new npc_freed_protodrake(); new npc_icefang(); new npc_hyldsmeet_protodrake(); } diff --git a/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp b/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp index 44c37fc9753..ec9e4e116bf 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp @@ -181,6 +181,23 @@ public: me->RemoveAurasDueToSpell(SPELL_SUBMERGE); } + void MoveInLineOfSight(Unit* who) + { + if (!who) + return; + + if (me->isInCombat()) + return; + + if (who->GetTypeId() != TYPEID_PLAYER) + return; + + if (me->GetDistance(who) > 50.0f) + return; + + AttackStartNoMove(who); + } + void EnterCombat(Unit* who) { me->AddThreat(who, 10000.0f); @@ -412,6 +429,7 @@ public: me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->Yell(SUFF_SAY_RECAP, LANG_UNIVERSAL, 0); DoScriptText(SUFF_SAY_RECAP, me); + me->SetReactState(REACT_PASSIVE); } } @@ -532,6 +550,7 @@ public: damage = 0; me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); DoScriptText(SUFF_SAY_RECAP, me); + me->SetReactState(REACT_PASSIVE); } else { diff --git a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp index 84d292e1fe4..b42641c5171 100644 --- a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp @@ -160,7 +160,7 @@ class go_broggok_lever : public GameObjectScript public: go_broggok_lever() : GameObjectScript("go_broggok_lever") {} - bool OnGossipHello(Player* player, GameObject* go) + bool OnGossipHello(Player* /*player*/, GameObject* go) { if (InstanceScript* instance = go->GetInstanceScript()) if (instance->GetData(TYPE_BROGGOK_EVENT) != DONE && instance->GetData(TYPE_BROGGOK_EVENT) != IN_PROGRESS) diff --git a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/instance_blood_furnace.cpp b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/instance_blood_furnace.cpp index 893f97fe711..233a8d82497 100644 --- a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/instance_blood_furnace.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/instance_blood_furnace.cpp @@ -133,7 +133,7 @@ class instance_blood_furnace : public InstanceMapScript } } - void OnCreatureDeath(Creature* unit) + void OnUnitDeath(Unit* unit) { if (unit && unit->GetTypeId() == TYPEID_UNIT && unit->GetEntry() == 17398) PrisonerDied(unit->GetGUID()); @@ -350,10 +350,10 @@ class instance_blood_furnace : public InstanceMapScript ++PrisonerCounter8; } else - return; + return; } else - return; + return; ResetPrisoner(creature); } diff --git a/src/server/scripts/Outland/shadowmoon_valley.cpp b/src/server/scripts/Outland/shadowmoon_valley.cpp index 1656f7221ed..c84df2ee3d4 100644 --- a/src/server/scripts/Outland/shadowmoon_valley.cpp +++ b/src/server/scripts/Outland/shadowmoon_valley.cpp @@ -839,19 +839,10 @@ public: return 1500; break; case 16: - if (player) - { - Illi->CastSpell(player, SPELL_TWO, true); - player->RemoveAurasDueToSpell(SPELL_THREE); - player->RemoveAurasDueToSpell(SPELL_FOUR); - return 5000; - } - else - { - player->FailQuest(QUEST_LORD_ILLIDAN_STORMRAGE); - Step = 30; - return 100; - } + Illi->CastSpell(player, SPELL_TWO, true); + player->RemoveAurasDueToSpell(SPELL_THREE); + player->RemoveAurasDueToSpell(SPELL_FOUR); + return 5000; break; case 17: DoScriptText(LORD_ILLIDAN_SAY_5, Illi); @@ -1871,8 +1862,8 @@ public: enum ZuluhedChains { - QUEST_ZULUHED = 10866, - NPC_KARYNAKU = 22112, + QUEST_ZULUHED = 10866, + NPC_KARYNAKU = 22112, }; class spell_unlocking_zuluheds_chains : public SpellScriptLoader @@ -1884,18 +1875,21 @@ class spell_unlocking_zuluheds_chains : public SpellScriptLoader { PrepareSpellScript(spell_unlocking_zuluheds_chains_SpellScript); - void HandleOnCast() + bool Load() { - // FIXME: Hackish solution, a better way to reward killcredit should be found - if (Unit* caster = GetCaster()) - if(Player* player = caster->ToPlayer()) - if (player->GetQuestStatus(QUEST_ZULUHED) == QUEST_STATUS_INCOMPLETE) - player->CastedCreatureOrGO(NPC_KARYNAKU, MAKE_NEW_GUID(0, NPC_KARYNAKU, HIGHGUID_UNIT), 0); + return GetCaster()->GetTypeId() == TYPEID_PLAYER; + } + + void HandleAfterHit() + { + Player* caster = GetCaster()->ToPlayer(); + if (caster->GetQuestStatus(QUEST_ZULUHED) == QUEST_STATUS_INCOMPLETE) + caster->KilledMonsterCredit(NPC_KARYNAKU, 0); } void Register() { - OnCast += SpellCastFn(spell_unlocking_zuluheds_chains_SpellScript::HandleOnCast); + AfterHit += SpellHitFn(spell_unlocking_zuluheds_chains_SpellScript::HandleAfterHit); } }; @@ -1905,6 +1899,96 @@ class spell_unlocking_zuluheds_chains : public SpellScriptLoader } }; +enum ShadowMoonTuberEnum +{ + SPELL_WHISTLE = 36652, + SPELL_SHADOWMOON_TUBER = 36462, + + NPC_BOAR_ENTRY = 21195, + GO_SHADOWMOON_TUBER_MOUND = 184701, + + POINT_TUBER = 1, + TYPE_BOAR = 1, + DATA_BOAR = 1 +}; + +class npc_shadowmoon_tuber_node : public CreatureScript +{ +public: + npc_shadowmoon_tuber_node() : CreatureScript("npc_shadowmoon_tuber_node") {} + + struct npc_shadowmoon_tuber_nodeAI : public ScriptedAI + { + npc_shadowmoon_tuber_nodeAI(Creature* creature) : ScriptedAI(creature) {} + + void Reset() + { + tapped = false; + tuberGUID = 0; + resetTimer = 60000; + } + + void SetData(uint32 id, uint32 data) + { + if (id == TYPE_BOAR && data == DATA_BOAR) + { + // Spawn chest GO + DoCast(SPELL_SHADOWMOON_TUBER); + + // Despawn the tuber + if (GameObject* tuber = me->FindNearestGameObject(GO_SHADOWMOON_TUBER_MOUND, 5.0f)) + { + tuberGUID = tuber->GetGUID(); + // @Workaround: find how to properly despawn the GO + tuber->SetPhaseMask(2, true); + } + } + } + + void SpellHit(Unit* /*caster*/, const SpellInfo* spell) + { + if (!tapped && spell->Id == SPELL_WHISTLE) + { + if (Creature* boar = me->FindNearestCreature(NPC_BOAR_ENTRY, 30.0f)) + { + // Disable trigger and force nearest boar to walk to him + tapped = true; + boar->SetWalk(false); + boar->GetMotionMaster()->MovePoint(POINT_TUBER, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (tapped) + { + if (resetTimer <= diff) + { + // Respawn the tuber + if (tuberGUID) + if (GameObject* tuber = GameObject::GetGameObject(*me, tuberGUID)) + // @Workaround: find how to properly respawn the GO + tuber->SetPhaseMask(1, true); + + Reset(); + } + else + resetTimer -= diff; + } + } + private: + bool tapped; + uint64 tuberGUID; + uint32 resetTimer; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_shadowmoon_tuber_nodeAI(creature); + } +}; + void AddSC_shadowmoon_valley() { new mob_mature_netherwing_drake(); @@ -1923,4 +2007,5 @@ void AddSC_shadowmoon_valley() new mob_torloth_the_magnificent(); new npc_enraged_spirit(); new spell_unlocking_zuluheds_chains(); + new npc_shadowmoon_tuber_node(); } diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp index b213f3df624..32a92da5e3a 100644 --- a/src/server/scripts/Spells/spell_druid.cpp +++ b/src/server/scripts/Spells/spell_druid.cpp @@ -34,6 +34,36 @@ enum DruidSpells DRUID_SURVIVAL_INSTINCTS = 50322, DRUID_SAVAGE_ROAR = 62071, SPELL_DRUID_ITEM_T8_BALANCE_RELIC = 64950, + SPELL_KING_OF_THE_JUNGLE = 48492, + SPELL_TIGER_S_FURY_ENERGIZE = 51178, + SPELL_ENRAGE_MOD_DAMAGE = 51185, +}; + +class spell_dru_enrage : public SpellScriptLoader +{ + public: + spell_dru_enrage() : SpellScriptLoader("spell_dru_enrage") { } + + class spell_dru_enrage_SpellScript : public SpellScript + { + PrepareSpellScript(spell_dru_enrage_SpellScript); + + void OnHit() + { + if (AuraEffect const* aurEff = GetHitUnit()->GetAuraEffectOfRankedSpell(SPELL_KING_OF_THE_JUNGLE, EFFECT_0)) + GetHitUnit()->CastCustomSpell(SPELL_ENRAGE_MOD_DAMAGE, SPELLVALUE_BASE_POINT0, aurEff->GetAmount(), GetHitUnit(), true); + } + + void Register() + { + AfterHit += SpellHitFn(spell_dru_enrage_SpellScript::OnHit); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_dru_enrage_SpellScript(); + } }; // 54846 Glyph of Starfire @@ -88,6 +118,115 @@ class spell_dru_glyph_of_starfire : public SpellScriptLoader } }; +class spell_dru_insect_swarm : public SpellScriptLoader +{ + public: + spell_dru_insect_swarm() : SpellScriptLoader("spell_dru_insect_swarm") { } + + class spell_dru_insect_swarm_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_insect_swarm_AuraScript); + + void CalculateAmount(AuraEffect const* aurEff, int32 & amount, bool & /*canBeRecalculated*/) + { + if (Unit* caster = GetCaster()) + if (AuraEffect const* relicAurEff = caster->GetAuraEffect(SPELL_DRUID_ITEM_T8_BALANCE_RELIC, EFFECT_0)) + amount += relicAurEff->GetAmount() / aurEff->GetTotalTicks(); + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dru_insect_swarm_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dru_insect_swarm_AuraScript(); + } +}; + +class spell_dru_lifebloom : public SpellScriptLoader +{ + public: + spell_dru_lifebloom() : SpellScriptLoader("spell_dru_lifebloom") { } + + class spell_dru_lifebloom_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_lifebloom_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(DRUID_LIFEBLOOM_FINAL_HEAL)) + return false; + if (!sSpellMgr->GetSpellInfo(DRUID_LIFEBLOOM_ENERGIZE)) + return false; + return true; + } + + void AfterRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + // Final heal only on duration end + if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE) + return; + + // final heal + int32 stack = GetStackAmount(); + int32 healAmount = aurEff->GetAmount(); + if (Unit* caster = GetCaster()) + { + healAmount = caster->SpellHealingBonusDone(GetTarget(), GetSpellInfo(), healAmount, HEAL, stack); + healAmount = GetTarget()->SpellHealingBonusTaken(caster, GetSpellInfo(), healAmount, HEAL, stack); + + GetTarget()->CastCustomSpell(GetTarget(), DRUID_LIFEBLOOM_FINAL_HEAL, &healAmount, NULL, NULL, true, NULL, aurEff, GetCasterGUID()); + + // restore mana + int32 returnMana = CalculatePctU(caster->GetCreateMana(), GetSpellInfo()->ManaCostPercentage) * stack / 2; + caster->CastCustomSpell(caster, DRUID_LIFEBLOOM_ENERGIZE, &returnMana, NULL, NULL, true, NULL, aurEff, GetCasterGUID()); + return; + } + + GetTarget()->CastCustomSpell(GetTarget(), DRUID_LIFEBLOOM_FINAL_HEAL, &healAmount, NULL, NULL, true, NULL, aurEff, GetCasterGUID()); + } + + void HandleDispel(DispelInfo* dispelInfo) + { + if (Unit* target = GetUnitOwner()) + { + if (AuraEffect const* aurEff = GetEffect(EFFECT_1)) + { + // final heal + int32 healAmount = aurEff->GetAmount(); + if (Unit* caster = GetCaster()) + { + healAmount = caster->SpellHealingBonusDone(target, GetSpellInfo(), healAmount, HEAL, dispelInfo->GetRemovedCharges()); + healAmount = target->SpellHealingBonusTaken(caster, GetSpellInfo(), healAmount, HEAL, dispelInfo->GetRemovedCharges()); + target->CastCustomSpell(target, DRUID_LIFEBLOOM_FINAL_HEAL, &healAmount, NULL, NULL, true, NULL, NULL, GetCasterGUID()); + + // restore mana + int32 returnMana = CalculatePctU(caster->GetCreateMana(), GetSpellInfo()->ManaCostPercentage) * dispelInfo->GetRemovedCharges() / 2; + caster->CastCustomSpell(caster, DRUID_LIFEBLOOM_ENERGIZE, &returnMana, NULL, NULL, true, NULL, NULL, GetCasterGUID()); + return; + } + + target->CastCustomSpell(target, DRUID_LIFEBLOOM_FINAL_HEAL, &healAmount, NULL, NULL, true, NULL, NULL, GetCasterGUID()); + } + } + } + + void Register() + { + AfterEffectRemove += AuraEffectRemoveFn(spell_dru_lifebloom_AuraScript::AfterRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + AfterDispel += AuraDispelFn(spell_dru_lifebloom_AuraScript::HandleDispel); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dru_lifebloom_AuraScript(); + } +}; + // 69366 - Moonkin Form passive class spell_dru_moonkin_form_passive : public SpellScriptLoader { @@ -132,6 +271,34 @@ class spell_dru_moonkin_form_passive : public SpellScriptLoader } }; +class spell_dru_predatory_strikes : public SpellScriptLoader +{ + public: + spell_dru_predatory_strikes() : SpellScriptLoader("spell_dru_predatory_strikes") { } + + class spell_dru_predatory_strikes_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_predatory_strikes_AuraScript); + + void UpdateAmount(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Player* target = GetTarget()->ToPlayer()) + target->UpdateAttackPowerAndDamage(); + } + + void Register() + { + AfterEffectApply += AuraEffectApplyFn(spell_dru_predatory_strikes_AuraScript::UpdateAmount, EFFECT_ALL, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + AfterEffectRemove += AuraEffectRemoveFn(spell_dru_predatory_strikes_AuraScript::UpdateAmount, EFFECT_ALL, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dru_predatory_strikes_AuraScript(); + } +}; + // 33851 - Primal Tenacity class spell_dru_primal_tenacity : public SpellScriptLoader { @@ -219,57 +386,67 @@ class spell_dru_savage_defense : public SpellScriptLoader } }; -class spell_dru_t10_restoration_4p_bonus : public SpellScriptLoader +class spell_dru_savage_roar : public SpellScriptLoader { public: - spell_dru_t10_restoration_4p_bonus() : SpellScriptLoader("spell_dru_t10_restoration_4p_bonus") { } + spell_dru_savage_roar() : SpellScriptLoader("spell_dru_savage_roar") { } - class spell_dru_t10_restoration_4p_bonus_SpellScript : public SpellScript + class spell_dru_savage_roar_SpellScript : public SpellScript { - PrepareSpellScript(spell_dru_t10_restoration_4p_bonus_SpellScript); + PrepareSpellScript(spell_dru_savage_roar_SpellScript); - bool Load() + SpellCastResult CheckCast() { - return GetCaster()->GetTypeId() == TYPEID_PLAYER; + Unit* caster = GetCaster(); + if (caster->GetShapeshiftForm() != FORM_CAT) + return SPELL_FAILED_ONLY_SHAPESHIFT; + + return SPELL_CAST_OK; } - void FilterTargets(std::list<WorldObject*>& targets) + void Register() { - if (!GetCaster()->ToPlayer()->GetGroup()) - { - targets.clear(); - targets.push_back(GetCaster()); - } - else - { - targets.remove(GetExplTargetUnit()); - std::list<Unit*> tempTargets; - for (std::list<WorldObject*>::const_iterator itr = targets.begin(); itr != targets.end(); ++itr) - if ((*itr)->GetTypeId() == TYPEID_PLAYER && GetCaster()->IsInRaidWith((*itr)->ToUnit())) - tempTargets.push_back((*itr)->ToUnit()); + OnCheckCast += SpellCheckCastFn(spell_dru_savage_roar_SpellScript::CheckCast); + } + }; - if (tempTargets.empty()) - { - targets.clear(); - FinishCast(SPELL_FAILED_DONT_REPORT); - return; - } + class spell_dru_savage_roar_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_savage_roar_AuraScript); - Unit* target = Trinity::Containers::SelectRandomContainerElement(tempTargets); - targets.clear(); - targets.push_back(target); - } + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(DRUID_SAVAGE_ROAR)) + return false; + return true; + } + + void AfterApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + Unit* target = GetTarget(); + target->CastSpell(target, DRUID_SAVAGE_ROAR, true, NULL, aurEff, GetCasterGUID()); + } + + void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->RemoveAurasDueToSpell(DRUID_SAVAGE_ROAR); } void Register() { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dru_t10_restoration_4p_bonus_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ALLY); + AfterEffectApply += AuraEffectApplyFn(spell_dru_savage_roar_AuraScript::AfterApply, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_dru_savage_roar_AuraScript::AfterRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); } }; SpellScript* GetSpellScript() const { - return new spell_dru_t10_restoration_4p_bonus_SpellScript(); + return new spell_dru_savage_roar_SpellScript(); + } + + AuraScript* GetAuraScript() const + { + return new spell_dru_savage_roar_AuraScript(); } }; @@ -299,40 +476,6 @@ class spell_dru_starfall_aoe : public SpellScriptLoader } }; -// 40121 - Swift Flight Form (Passive) -class spell_dru_swift_flight_passive : public SpellScriptLoader -{ - public: - spell_dru_swift_flight_passive() : SpellScriptLoader("spell_dru_swift_flight_passive") { } - - class spell_dru_swift_flight_passive_AuraScript : public AuraScript - { - PrepareAuraScript(spell_dru_swift_flight_passive_AuraScript); - - bool Load() - { - return GetCaster()->GetTypeId() == TYPEID_PLAYER; - } - - void CalculateAmount(AuraEffect const* /*aurEff*/, int32 & amount, bool & /*canBeRecalculated*/) - { - if (Player* caster = GetCaster()->ToPlayer()) - if (caster->Has310Flyer(false)) - amount = 310; - } - - void Register() - { - DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dru_swift_flight_passive_AuraScript::CalculateAmount, EFFECT_1, SPELL_AURA_MOD_INCREASE_VEHICLE_FLIGHT_SPEED); - } - }; - - AuraScript* GetAuraScript() const - { - return new spell_dru_swift_flight_passive_AuraScript(); - } -}; - class spell_dru_starfall_dummy : public SpellScriptLoader { public: @@ -378,128 +521,19 @@ class spell_dru_starfall_dummy : public SpellScriptLoader } }; -class spell_dru_lifebloom : public SpellScriptLoader -{ - public: - spell_dru_lifebloom() : SpellScriptLoader("spell_dru_lifebloom") { } - - class spell_dru_lifebloom_AuraScript : public AuraScript - { - PrepareAuraScript(spell_dru_lifebloom_AuraScript); - - bool Validate(SpellInfo const* /*spell*/) - { - if (!sSpellMgr->GetSpellInfo(DRUID_LIFEBLOOM_FINAL_HEAL)) - return false; - if (!sSpellMgr->GetSpellInfo(DRUID_LIFEBLOOM_ENERGIZE)) - return false; - return true; - } - - void AfterRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) - { - // Final heal only on duration end - if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE) - return; - - // final heal - int32 stack = GetStackAmount(); - int32 healAmount = aurEff->GetAmount(); - if (Unit* caster = GetCaster()) - { - healAmount = caster->SpellHealingBonusDone(GetTarget(), GetSpellInfo(), healAmount, HEAL, stack); - healAmount = GetTarget()->SpellHealingBonusTaken(caster, GetSpellInfo(), healAmount, HEAL, stack); - - GetTarget()->CastCustomSpell(GetTarget(), DRUID_LIFEBLOOM_FINAL_HEAL, &healAmount, NULL, NULL, true, NULL, aurEff, GetCasterGUID()); - - // restore mana - int32 returnMana = CalculatePctU(caster->GetCreateMana(), GetSpellInfo()->ManaCostPercentage) * stack / 2; - caster->CastCustomSpell(caster, DRUID_LIFEBLOOM_ENERGIZE, &returnMana, NULL, NULL, true, NULL, aurEff, GetCasterGUID()); - return; - } - - GetTarget()->CastCustomSpell(GetTarget(), DRUID_LIFEBLOOM_FINAL_HEAL, &healAmount, NULL, NULL, true, NULL, aurEff, GetCasterGUID()); - } - - void HandleDispel(DispelInfo* dispelInfo) - { - if (Unit* target = GetUnitOwner()) - { - if (AuraEffect const* aurEff = GetEffect(EFFECT_1)) - { - // final heal - int32 healAmount = aurEff->GetAmount(); - if (Unit* caster = GetCaster()) - { - healAmount = caster->SpellHealingBonusDone(target, GetSpellInfo(), healAmount, HEAL, dispelInfo->GetRemovedCharges()); - healAmount = target->SpellHealingBonusTaken(caster, GetSpellInfo(), healAmount, HEAL, dispelInfo->GetRemovedCharges()); - target->CastCustomSpell(target, DRUID_LIFEBLOOM_FINAL_HEAL, &healAmount, NULL, NULL, true, NULL, NULL, GetCasterGUID()); - - // restore mana - int32 returnMana = CalculatePctU(caster->GetCreateMana(), GetSpellInfo()->ManaCostPercentage) * dispelInfo->GetRemovedCharges() / 2; - caster->CastCustomSpell(caster, DRUID_LIFEBLOOM_ENERGIZE, &returnMana, NULL, NULL, true, NULL, NULL, GetCasterGUID()); - return; - } - - target->CastCustomSpell(target, DRUID_LIFEBLOOM_FINAL_HEAL, &healAmount, NULL, NULL, true, NULL, NULL, GetCasterGUID()); - } - } - } - - void Register() - { - AfterEffectRemove += AuraEffectRemoveFn(spell_dru_lifebloom_AuraScript::AfterRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); - AfterDispel += AuraDispelFn(spell_dru_lifebloom_AuraScript::HandleDispel); - } - }; - - AuraScript* GetAuraScript() const - { - return new spell_dru_lifebloom_AuraScript(); - } -}; - -class spell_dru_predatory_strikes : public SpellScriptLoader -{ - public: - spell_dru_predatory_strikes() : SpellScriptLoader("spell_dru_predatory_strikes") { } - - class spell_dru_predatory_strikes_AuraScript : public AuraScript - { - PrepareAuraScript(spell_dru_predatory_strikes_AuraScript); - - void UpdateAmount(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - if (Player* target = GetTarget()->ToPlayer()) - target->UpdateAttackPowerAndDamage(); - } - - void Register() - { - AfterEffectApply += AuraEffectApplyFn(spell_dru_predatory_strikes_AuraScript::UpdateAmount, EFFECT_ALL, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); - AfterEffectRemove += AuraEffectRemoveFn(spell_dru_predatory_strikes_AuraScript::UpdateAmount, EFFECT_ALL, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); - } - }; - - AuraScript* GetAuraScript() const - { - return new spell_dru_predatory_strikes_AuraScript(); - } -}; - -class spell_dru_savage_roar : public SpellScriptLoader +class spell_dru_survival_instincts : public SpellScriptLoader { public: - spell_dru_savage_roar() : SpellScriptLoader("spell_dru_savage_roar") { } + spell_dru_survival_instincts() : SpellScriptLoader("spell_dru_survival_instincts") { } - class spell_dru_savage_roar_SpellScript : public SpellScript + class spell_dru_survival_instincts_SpellScript : public SpellScript { - PrepareSpellScript(spell_dru_savage_roar_SpellScript); + PrepareSpellScript(spell_dru_survival_instincts_SpellScript); SpellCastResult CheckCast() { Unit* caster = GetCaster(); - if (caster->GetShapeshiftForm() != FORM_CAT) + if (!caster->IsInFeralForm()) return SPELL_FAILED_ONLY_SHAPESHIFT; return SPELL_CAST_OK; @@ -507,17 +541,17 @@ class spell_dru_savage_roar : public SpellScriptLoader void Register() { - OnCheckCast += SpellCheckCastFn(spell_dru_savage_roar_SpellScript::CheckCast); + OnCheckCast += SpellCheckCastFn(spell_dru_survival_instincts_SpellScript::CheckCast); } }; - class spell_dru_savage_roar_AuraScript : public AuraScript + class spell_dru_survival_instincts_AuraScript : public AuraScript { - PrepareAuraScript(spell_dru_savage_roar_AuraScript); + PrepareAuraScript(spell_dru_survival_instincts_AuraScript); bool Validate(SpellInfo const* /*spell*/) { - if (!sSpellMgr->GetSpellInfo(DRUID_SAVAGE_ROAR)) + if (!sSpellMgr->GetSpellInfo(DRUID_SURVIVAL_INSTINCTS)) return false; return true; } @@ -525,138 +559,163 @@ class spell_dru_savage_roar : public SpellScriptLoader void AfterApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) { Unit* target = GetTarget(); - target->CastSpell(target, DRUID_SAVAGE_ROAR, true, NULL, aurEff, GetCasterGUID()); + int32 bp0 = target->CountPctFromMaxHealth(aurEff->GetAmount()); + target->CastCustomSpell(target, DRUID_SURVIVAL_INSTINCTS, &bp0, NULL, NULL, true); } void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - GetTarget()->RemoveAurasDueToSpell(DRUID_SAVAGE_ROAR); + GetTarget()->RemoveAurasDueToSpell(DRUID_SURVIVAL_INSTINCTS); } void Register() { - AfterEffectApply += AuraEffectApplyFn(spell_dru_savage_roar_AuraScript::AfterApply, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); - AfterEffectRemove += AuraEffectRemoveFn(spell_dru_savage_roar_AuraScript::AfterRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + AfterEffectApply += AuraEffectApplyFn(spell_dru_survival_instincts_AuraScript::AfterApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + AfterEffectRemove += AuraEffectRemoveFn(spell_dru_survival_instincts_AuraScript::AfterRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); } }; SpellScript* GetSpellScript() const { - return new spell_dru_savage_roar_SpellScript(); + return new spell_dru_survival_instincts_SpellScript(); } AuraScript* GetAuraScript() const { - return new spell_dru_savage_roar_AuraScript(); + return new spell_dru_survival_instincts_AuraScript(); } }; -class spell_dru_survival_instincts : public SpellScriptLoader +// 40121 - Swift Flight Form (Passive) +class spell_dru_swift_flight_passive : public SpellScriptLoader { public: - spell_dru_survival_instincts() : SpellScriptLoader("spell_dru_survival_instincts") { } + spell_dru_swift_flight_passive() : SpellScriptLoader("spell_dru_swift_flight_passive") { } - class spell_dru_survival_instincts_SpellScript : public SpellScript + class spell_dru_swift_flight_passive_AuraScript : public AuraScript { - PrepareSpellScript(spell_dru_survival_instincts_SpellScript); + PrepareAuraScript(spell_dru_swift_flight_passive_AuraScript); - SpellCastResult CheckCast() + bool Load() { - Unit* caster = GetCaster(); - if (!caster->IsInFeralForm()) - return SPELL_FAILED_ONLY_SHAPESHIFT; + return GetCaster()->GetTypeId() == TYPEID_PLAYER; + } - return SPELL_CAST_OK; + void CalculateAmount(AuraEffect const* /*aurEff*/, int32 & amount, bool & /*canBeRecalculated*/) + { + if (Player* caster = GetCaster()->ToPlayer()) + if (caster->Has310Flyer(false)) + amount = 310; } void Register() { - OnCheckCast += SpellCheckCastFn(spell_dru_survival_instincts_SpellScript::CheckCast); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dru_swift_flight_passive_AuraScript::CalculateAmount, EFFECT_1, SPELL_AURA_MOD_INCREASE_VEHICLE_FLIGHT_SPEED); } }; - class spell_dru_survival_instincts_AuraScript : public AuraScript + AuraScript* GetAuraScript() const { - PrepareAuraScript(spell_dru_survival_instincts_AuraScript); + return new spell_dru_swift_flight_passive_AuraScript(); + } +}; - bool Validate(SpellInfo const* /*spell*/) - { - if (!sSpellMgr->GetSpellInfo(DRUID_SURVIVAL_INSTINCTS)) - return false; - return true; - } +class spell_dru_tiger_s_fury : public SpellScriptLoader +{ + public: + spell_dru_tiger_s_fury() : SpellScriptLoader("spell_dru_tiger_s_fury") { } - void AfterApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) - { - Unit* target = GetTarget(); - int32 bp0 = target->CountPctFromMaxHealth(aurEff->GetAmount()); - target->CastCustomSpell(target, DRUID_SURVIVAL_INSTINCTS, &bp0, NULL, NULL, true); - } + class spell_dru_tiger_s_fury_SpellScript : public SpellScript + { + PrepareSpellScript(spell_dru_tiger_s_fury_SpellScript); - void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + void OnHit() { - GetTarget()->RemoveAurasDueToSpell(DRUID_SURVIVAL_INSTINCTS); + if (AuraEffect const* aurEff = GetHitUnit()->GetAuraEffectOfRankedSpell(SPELL_KING_OF_THE_JUNGLE, EFFECT_1)) + GetHitUnit()->CastCustomSpell(SPELL_TIGER_S_FURY_ENERGIZE, SPELLVALUE_BASE_POINT0, aurEff->GetAmount(), GetHitUnit(), true); } void Register() { - AfterEffectApply += AuraEffectApplyFn(spell_dru_survival_instincts_AuraScript::AfterApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); - AfterEffectRemove += AuraEffectRemoveFn(spell_dru_survival_instincts_AuraScript::AfterRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + AfterHit += SpellHitFn(spell_dru_tiger_s_fury_SpellScript::OnHit); } }; SpellScript* GetSpellScript() const { - return new spell_dru_survival_instincts_SpellScript(); - } - - AuraScript* GetAuraScript() const - { - return new spell_dru_survival_instincts_AuraScript(); + return new spell_dru_tiger_s_fury_SpellScript(); } }; -class spell_dru_insect_swarm : public SpellScriptLoader +class spell_dru_t10_restoration_4p_bonus : public SpellScriptLoader { public: - spell_dru_insect_swarm() : SpellScriptLoader("spell_dru_insect_swarm") { } + spell_dru_t10_restoration_4p_bonus() : SpellScriptLoader("spell_dru_t10_restoration_4p_bonus") { } - class spell_dru_insect_swarm_AuraScript : public AuraScript + class spell_dru_t10_restoration_4p_bonus_SpellScript : public SpellScript { - PrepareAuraScript(spell_dru_insect_swarm_AuraScript); + PrepareSpellScript(spell_dru_t10_restoration_4p_bonus_SpellScript); - void CalculateAmount(AuraEffect const* aurEff, int32 & amount, bool & /*canBeRecalculated*/) + bool Load() { - if (Unit* caster = GetCaster()) - if (AuraEffect const* relicAurEff = caster->GetAuraEffect(SPELL_DRUID_ITEM_T8_BALANCE_RELIC, EFFECT_0)) - amount += relicAurEff->GetAmount() / aurEff->GetTotalTicks(); + return GetCaster()->GetTypeId() == TYPEID_PLAYER; + } + + void FilterTargets(std::list<WorldObject*>& targets) + { + if (!GetCaster()->ToPlayer()->GetGroup()) + { + targets.clear(); + targets.push_back(GetCaster()); + } + else + { + targets.remove(GetExplTargetUnit()); + std::list<Unit*> tempTargets; + for (std::list<WorldObject*>::const_iterator itr = targets.begin(); itr != targets.end(); ++itr) + if ((*itr)->GetTypeId() == TYPEID_PLAYER && GetCaster()->IsInRaidWith((*itr)->ToUnit())) + tempTargets.push_back((*itr)->ToUnit()); + + if (tempTargets.empty()) + { + targets.clear(); + FinishCast(SPELL_FAILED_DONT_REPORT); + return; + } + + Unit* target = Trinity::Containers::SelectRandomContainerElement(tempTargets); + targets.clear(); + targets.push_back(target); + } } void Register() { - DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dru_insect_swarm_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dru_t10_restoration_4p_bonus_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ALLY); } }; - AuraScript* GetAuraScript() const + SpellScript* GetSpellScript() const { - return new spell_dru_insect_swarm_AuraScript(); + return new spell_dru_t10_restoration_4p_bonus_SpellScript(); } }; void AddSC_druid_spell_scripts() { + new spell_dru_enrage(); new spell_dru_glyph_of_starfire(); + new spell_dru_insect_swarm(); + new spell_dru_lifebloom(); new spell_dru_moonkin_form_passive(); + new spell_dru_predatory_strikes(); new spell_dru_primal_tenacity(); new spell_dru_savage_defense(); - new spell_dru_t10_restoration_4p_bonus(); + new spell_dru_savage_roar(); new spell_dru_starfall_aoe(); - new spell_dru_swift_flight_passive(); new spell_dru_starfall_dummy(); - new spell_dru_lifebloom(); - new spell_dru_predatory_strikes(); - new spell_dru_savage_roar(); new spell_dru_survival_instincts(); - new spell_dru_insect_swarm(); + new spell_dru_swift_flight_passive(); + new spell_dru_tiger_s_fury(); + 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 5153010c0cc..3085472749c 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -907,9 +907,22 @@ class spell_gen_profession_research : public SpellScriptLoader return SPELL_CAST_OK; } + void HandleScript(SpellEffIndex /*effIndex*/) + { + Player* caster = GetCaster()->ToPlayer(); + uint32 spellId = GetSpellInfo()->Id; + + // learn random explicit discovery recipe (if any) + if (uint32 discoveredSpellId = GetExplicitDiscoverySpell(spellId, caster)) + caster->learnSpell(discoveredSpellId, false); + + caster->UpdateCraftSkill(spellId); + } + void Register() { OnCheckCast += SpellCheckCastFn(spell_gen_profession_research_SpellScript::CheckRequirement); + OnEffectHitTarget += SpellEffectFn(spell_gen_profession_research_SpellScript::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); } }; @@ -2428,7 +2441,7 @@ class spell_gen_on_tournament_mount : public SpellScriptLoader case NPC_ARGENT_STEED_ASPIRANT: case NPC_STORMWIND_STEED: { - if (player->GetAchievementMgr().HasAchieved(ACHIEVEMENT_CHAMPION_STORMWIND)) + if (player->HasAchieved(ACHIEVEMENT_CHAMPION_STORMWIND)) return SPELL_PENNANT_STORMWIND_CHAMPION; else if (player->GetQuestRewardStatus(QUEST_VALIANT_OF_STORMWIND) || player->GetQuestRewardStatus(QUEST_A_VALIANT_OF_STORMWIND)) return SPELL_PENNANT_STORMWIND_VALIANT; @@ -2437,7 +2450,7 @@ class spell_gen_on_tournament_mount : public SpellScriptLoader } case NPC_GNOMEREGAN_MECHANOSTRIDER: { - if (player->GetAchievementMgr().HasAchieved(ACHIEVEMENT_CHAMPION_GNOMEREGAN)) + if (player->HasAchieved(ACHIEVEMENT_CHAMPION_GNOMEREGAN)) return SPELL_PENNANT_GNOMEREGAN_CHAMPION; else if (player->GetQuestRewardStatus(QUEST_VALIANT_OF_GNOMEREGAN) || player->GetQuestRewardStatus(QUEST_A_VALIANT_OF_GNOMEREGAN)) return SPELL_PENNANT_GNOMEREGAN_VALIANT; @@ -2446,7 +2459,7 @@ class spell_gen_on_tournament_mount : public SpellScriptLoader } case NPC_DARK_SPEAR_RAPTOR: { - if (player->GetAchievementMgr().HasAchieved(ACHIEVEMENT_CHAMPION_SEN_JIN)) + if (player->HasAchieved(ACHIEVEMENT_CHAMPION_SEN_JIN)) return SPELL_PENNANT_SEN_JIN_CHAMPION; else if (player->GetQuestRewardStatus(QUEST_VALIANT_OF_SEN_JIN) || player->GetQuestRewardStatus(QUEST_A_VALIANT_OF_SEN_JIN)) return SPELL_PENNANT_SEN_JIN_VALIANT; @@ -2456,7 +2469,7 @@ class spell_gen_on_tournament_mount : public SpellScriptLoader case NPC_ARGENT_HAWKSTRIDER_ASPIRANT: case NPC_SILVERMOON_HAWKSTRIDER: { - if (player->GetAchievementMgr().HasAchieved(ACHIEVEMENT_CHAMPION_SILVERMOON)) + if (player->HasAchieved(ACHIEVEMENT_CHAMPION_SILVERMOON)) return SPELL_PENNANT_SILVERMOON_CHAMPION; else if (player->GetQuestRewardStatus(QUEST_VALIANT_OF_SILVERMOON) || player->GetQuestRewardStatus(QUEST_A_VALIANT_OF_SILVERMOON)) return SPELL_PENNANT_SILVERMOON_VALIANT; @@ -2465,7 +2478,7 @@ class spell_gen_on_tournament_mount : public SpellScriptLoader } case NPC_DARNASSIAN_NIGHTSABER: { - if (player->GetAchievementMgr().HasAchieved(ACHIEVEMENT_CHAMPION_DARNASSUS)) + if (player->HasAchieved(ACHIEVEMENT_CHAMPION_DARNASSUS)) return SPELL_PENNANT_DARNASSUS_CHAMPION; else if (player->GetQuestRewardStatus(QUEST_VALIANT_OF_DARNASSUS) || player->GetQuestRewardStatus(QUEST_A_VALIANT_OF_DARNASSUS)) return SPELL_PENNANT_DARNASSUS_VALIANT; @@ -2474,7 +2487,7 @@ class spell_gen_on_tournament_mount : public SpellScriptLoader } case NPC_EXODAR_ELEKK: { - if (player->GetAchievementMgr().HasAchieved(ACHIEVEMENT_CHAMPION_THE_EXODAR)) + if (player->HasAchieved(ACHIEVEMENT_CHAMPION_THE_EXODAR)) return SPELL_PENNANT_EXODAR_CHAMPION; else if (player->GetQuestRewardStatus(QUEST_VALIANT_OF_THE_EXODAR) || player->GetQuestRewardStatus(QUEST_A_VALIANT_OF_THE_EXODAR)) return SPELL_PENNANT_EXODAR_VALIANT; @@ -2483,7 +2496,7 @@ class spell_gen_on_tournament_mount : public SpellScriptLoader } case NPC_IRONFORGE_RAM: { - if (player->GetAchievementMgr().HasAchieved(ACHIEVEMENT_CHAMPION_IRONFORGE)) + if (player->HasAchieved(ACHIEVEMENT_CHAMPION_IRONFORGE)) return SPELL_PENNANT_IRONFORGE_CHAMPION; else if (player->GetQuestRewardStatus(QUEST_VALIANT_OF_IRONFORGE) || player->GetQuestRewardStatus(QUEST_A_VALIANT_OF_IRONFORGE)) return SPELL_PENNANT_IRONFORGE_VALIANT; @@ -2492,7 +2505,7 @@ class spell_gen_on_tournament_mount : public SpellScriptLoader } case NPC_FORSAKEN_WARHORSE: { - if (player->GetAchievementMgr().HasAchieved(ACHIEVEMENT_CHAMPION_UNDERCITY)) + if (player->HasAchieved(ACHIEVEMENT_CHAMPION_UNDERCITY)) return SPELL_PENNANT_UNDERCITY_CHAMPION; else if (player->GetQuestRewardStatus(QUEST_VALIANT_OF_UNDERCITY) || player->GetQuestRewardStatus(QUEST_A_VALIANT_OF_UNDERCITY)) return SPELL_PENNANT_UNDERCITY_VALIANT; @@ -2501,7 +2514,7 @@ class spell_gen_on_tournament_mount : public SpellScriptLoader } case NPC_ORGRIMMAR_WOLF: { - if (player->GetAchievementMgr().HasAchieved(ACHIEVEMENT_CHAMPION_ORGRIMMAR)) + if (player->HasAchieved(ACHIEVEMENT_CHAMPION_ORGRIMMAR)) return SPELL_PENNANT_ORGRIMMAR_CHAMPION; else if (player->GetQuestRewardStatus(QUEST_VALIANT_OF_ORGRIMMAR) || player->GetQuestRewardStatus(QUEST_A_VALIANT_OF_ORGRIMMAR)) return SPELL_PENNANT_ORGRIMMAR_VALIANT; @@ -2510,7 +2523,7 @@ class spell_gen_on_tournament_mount : public SpellScriptLoader } case NPC_THUNDER_BLUFF_KODO: { - if (player->GetAchievementMgr().HasAchieved(ACHIEVEMENT_CHAMPION_THUNDER_BLUFF)) + if (player->HasAchieved(ACHIEVEMENT_CHAMPION_THUNDER_BLUFF)) return SPELL_PENNANT_THUNDER_BLUFF_CHAMPION; else if (player->GetQuestRewardStatus(QUEST_VALIANT_OF_THUNDER_BLUFF) || player->GetQuestRewardStatus(QUEST_A_VALIANT_OF_THUNDER_BLUFF)) return SPELL_PENNANT_THUNDER_BLUFF_VALIANT; @@ -2519,9 +2532,9 @@ class spell_gen_on_tournament_mount : public SpellScriptLoader } case NPC_ARGENT_WARHORSE: { - if (player->GetAchievementMgr().HasAchieved(ACHIEVEMENT_CHAMPION_ALLIANCE) || player->GetAchievementMgr().HasAchieved(ACHIEVEMENT_CHAMPION_HORDE)) + if (player->HasAchieved(ACHIEVEMENT_CHAMPION_ALLIANCE) || player->HasAchieved(ACHIEVEMENT_CHAMPION_HORDE)) return player->getClass() == CLASS_DEATH_KNIGHT ? SPELL_PENNANT_EBON_BLADE_CHAMPION : SPELL_PENNANT_ARGENT_CRUSADE_CHAMPION; - else if (player->GetAchievementMgr().HasAchieved(ACHIEVEMENT_ARGENT_VALOR)) + else if (player->HasAchieved(ACHIEVEMENT_ARGENT_VALOR)) return player->getClass() == CLASS_DEATH_KNIGHT ? SPELL_PENNANT_EBON_BLADE_VALIANT : SPELL_PENNANT_ARGENT_CRUSADE_VALIANT; else return player->getClass() == CLASS_DEATH_KNIGHT ? SPELL_PENNANT_EBON_BLADE_ASPIRANT : SPELL_PENNANT_ARGENT_CRUSADE_ASPIRANT; @@ -3237,6 +3250,58 @@ class spell_gen_bonked : public SpellScriptLoader } }; +class spell_gen_gift_of_naaru : public SpellScriptLoader +{ + public: + spell_gen_gift_of_naaru() : SpellScriptLoader("spell_gen_gift_of_naaru") { } + + class spell_gen_gift_of_naaru_AuraScript : public AuraScript + { + PrepareAuraScript(spell_gen_gift_of_naaru_AuraScript); + + void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster()) + return; + + float heal = 0.0f; + switch (GetSpellInfo()->SpellFamilyName) + { + case SPELLFAMILY_MAGE: + case SPELLFAMILY_WARLOCK: + case SPELLFAMILY_PRIEST: + heal = 1.885f * float(GetCaster()->SpellBaseDamageBonusDone(GetSpellInfo()->GetSchoolMask())); + break; + case SPELLFAMILY_PALADIN: + case SPELLFAMILY_SHAMAN: + heal = std::max(1.885f * float(GetCaster()->SpellBaseDamageBonusDone(GetSpellInfo()->GetSchoolMask())), 1.1f * float(GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK))); + break; + case SPELLFAMILY_WARRIOR: + case SPELLFAMILY_HUNTER: + case SPELLFAMILY_DEATHKNIGHT: + heal = 1.1f * float(std::max(GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK), GetCaster()->GetTotalAttackPowerValue(RANGED_ATTACK))); + break; + case SPELLFAMILY_GENERIC: + default: + break; + } + + int32 healTick = floor(heal / aurEff->GetTotalTicks()); + amount += int32(std::max(healTick, 0)); + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_gift_of_naaru_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_HEAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_gen_gift_of_naaru_AuraScript(); + } +}; + void AddSC_generic_spell_scripts() { new spell_gen_absorb0_hitlimit1(); @@ -3312,4 +3377,5 @@ void AddSC_generic_spell_scripts() new spell_gen_mount("spell_x53_touring_rocket", 0, 0, 0, SPELL_X53_TOURING_ROCKET_150, SPELL_X53_TOURING_ROCKET_280, SPELL_X53_TOURING_ROCKET_310); new spell_gen_upper_deck_create_foam_sword(); new spell_gen_bonked(); + new spell_gen_gift_of_naaru(); } diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp index 3c89cb7005a..0508d95a60b 100644 --- a/src/server/scripts/Spells/spell_item.cpp +++ b/src/server/scripts/Spells/spell_item.cpp @@ -836,9 +836,20 @@ class spell_item_book_of_glyph_mastery : public SpellScriptLoader return SPELL_CAST_OK; } + void HandleScript(SpellEffIndex /*effIndex*/) + { + Player* caster = GetCaster()->ToPlayer(); + uint32 spellId = GetSpellInfo()->Id; + + // learn random explicit discovery recipe (if any) + if (uint32 discoveredSpellId = GetExplicitDiscoverySpell(spellId, caster)) + caster->learnSpell(discoveredSpellId, false); + } + void Register() { OnCheckCast += SpellCheckCastFn(spell_item_book_of_glyph_mastery_SpellScript::CheckRequirement); + OnEffectHitTarget += SpellEffectFn(spell_item_book_of_glyph_mastery_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } }; diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp index cbf45910495..06d3602d8e8 100644 --- a/src/server/scripts/Spells/spell_quest.cpp +++ b/src/server/scripts/Spells/spell_quest.cpp @@ -25,6 +25,9 @@ #include "ScriptedCreature.h" #include "SpellScript.h" #include "Vehicle.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "CellImpl.h" class spell_generic_quest_update_entry_SpellScript : public SpellScript { @@ -1314,6 +1317,174 @@ class spell_q12372_destabilize_azure_dragonshrine_dummy : public SpellScriptLoad } }; +// "Bombing Run" and "Bomb Them Again!" +enum Quest11010_11102_11023Data +{ + // Spell + SPELL_FLAK_CANNON_TRIGGER = 40110, + SPELL_CHOOSE_LOC = 40056, + SPELL_AGGRO_CHECK = 40112, + // NPCs + NPC_FEL_CANNON2 = 23082 +}; + +// 40113 Knockdown Fel Cannon: The Aggro Check Aura +class spell_q11010_q11102_q11023_aggro_check_aura : public SpellScriptLoader +{ + public: + spell_q11010_q11102_q11023_aggro_check_aura() : SpellScriptLoader("spell_q11010_q11102_q11023_aggro_check_aura") { } + + class spell_q11010_q11102_q11023_aggro_check_aura_AuraScript : public AuraScript + { + PrepareAuraScript(spell_q11010_q11102_q11023_aggro_check_aura_AuraScript); + + void HandleTriggerSpell(AuraEffect const* /*aurEff*/) + { + if (Unit* target = GetTarget()) + // On trigger proccing + target->CastSpell(target, SPELL_AGGRO_CHECK); + } + + void Register() + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_q11010_q11102_q11023_aggro_check_aura_AuraScript::HandleTriggerSpell, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_q11010_q11102_q11023_aggro_check_aura_AuraScript(); + } +}; + +// 40112 Knockdown Fel Cannon: The Aggro Check +class spell_q11010_q11102_q11023_aggro_check : public SpellScriptLoader +{ + public: + spell_q11010_q11102_q11023_aggro_check() : SpellScriptLoader("spell_q11010_q11102_q11023_aggro_check") { } + + class spell_q11010_q11102_q11023_aggro_check_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q11010_q11102_q11023_aggro_check_SpellScript); + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + if (Player* playerTarget = GetHitPlayer()) + // Check if found player target is on fly mount or using flying form + if (playerTarget->HasAuraType(SPELL_AURA_FLY) || playerTarget->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED)) + playerTarget->CastSpell(playerTarget, SPELL_FLAK_CANNON_TRIGGER, TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_q11010_q11102_q11023_aggro_check_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_q11010_q11102_q11023_aggro_check_SpellScript(); + } +}; + +// 40119 Knockdown Fel Cannon: The Aggro Burst +class spell_q11010_q11102_q11023_aggro_burst : public SpellScriptLoader +{ + public: + spell_q11010_q11102_q11023_aggro_burst() : SpellScriptLoader("spell_q11010_q11102_q11023_aggro_burst") { } + + class spell_q11010_q11102_q11023_aggro_burst_AuraScript : public AuraScript + { + PrepareAuraScript(spell_q11010_q11102_q11023_aggro_burst_AuraScript); + + void HandleEffectPeriodic(AuraEffect const* /*aurEff*/) + { + if (Unit* target = GetTarget()) + // On each tick cast Choose Loc to trigger summon + target->CastSpell(target, SPELL_CHOOSE_LOC); + } + + void Register() + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_q11010_q11102_q11023_aggro_burst_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_q11010_q11102_q11023_aggro_burst_AuraScript(); + } +}; + +// 40056 Knockdown Fel Cannon: Choose Loc +class spell_q11010_q11102_q11023_choose_loc : public SpellScriptLoader +{ + public: + spell_q11010_q11102_q11023_choose_loc() : SpellScriptLoader("spell_q11010_q11102_q11023_choose_loc") { } + + class spell_q11010_q11102_q11023_choose_loc_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q11010_q11102_q11023_choose_loc_SpellScript); + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + // Check for player that is in 65 y range + std::list<Player*> playerList; + Trinity::AnyPlayerInObjectRangeCheck checker(caster, 765.0f); + Trinity::PlayerListSearcher<Trinity::AnyPlayerInObjectRangeCheck> searcher(caster, playerList, checker); + caster->VisitNearbyWorldObject(65.0f, searcher); + for (std::list<Player*>::const_iterator itr = playerList.begin(); itr != playerList.end(); ++itr) + // Check if found player target is on fly mount or using flying form + if ((*itr)->HasAuraType(SPELL_AURA_FLY) || (*itr)->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED)) + // Summom Fel Cannon (bunny version) at found player + caster->SummonCreature(NPC_FEL_CANNON2, (*itr)->GetPositionX(), (*itr)->GetPositionY(), (*itr)->GetPositionZ()); + } + + void Register() + { + OnEffectHit += SpellEffectFn(spell_q11010_q11102_q11023_choose_loc_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_q11010_q11102_q11023_choose_loc_SpellScript(); + } +}; + +// 39844 - Skyguard Blasting Charge +// 40160 - Throw Bomb +class spell_q11010_q11102_q11023_q11008_check_fly_mount : public SpellScriptLoader +{ + public: + spell_q11010_q11102_q11023_q11008_check_fly_mount() : SpellScriptLoader("spell_q11010_q11102_q11023_q11008_check_fly_mount") { } + + class spell_q11010_q11102_q11023_q11008_check_fly_mount_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q11010_q11102_q11023_q11008_check_fly_mount_SpellScript); + + SpellCastResult CheckRequirement() + { + Unit* caster = GetCaster(); + // This spell will be cast only if caster has one of these auras + if (!(caster->HasAuraType(SPELL_AURA_FLY) || caster->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED))) + return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW; + return SPELL_CAST_OK; + } + + void Register() + { + OnCheckCast += SpellCheckCastFn(spell_q11010_q11102_q11023_q11008_check_fly_mount_SpellScript::CheckRequirement); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_q11010_q11102_q11023_q11008_check_fly_mount_SpellScript(); + } +}; + void AddSC_quest_spell_scripts() { new spell_q55_sacred_cleansing(); @@ -1345,4 +1516,9 @@ void AddSC_quest_spell_scripts() new spell_q12735_song_of_cleansing(); new spell_q12372_cast_from_gossip_trigger(); new spell_q12372_destabilize_azure_dragonshrine_dummy(); + new spell_q11010_q11102_q11023_aggro_check_aura(); + new spell_q11010_q11102_q11023_aggro_check(); + new spell_q11010_q11102_q11023_aggro_burst(); + new spell_q11010_q11102_q11023_choose_loc(); + new spell_q11010_q11102_q11023_q11008_check_fly_mount(); } diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp index e0131190916..0def62b7d3a 100644 --- a/src/server/scripts/Spells/spell_warlock.cpp +++ b/src/server/scripts/Spells/spell_warlock.cpp @@ -41,6 +41,10 @@ enum WarlockSpells WARLOCK_HAUNT_HEAL = 48210, WARLOCK_UNSTABLE_AFFLICTION_DISPEL = 31117, WARLOCK_CURSE_OF_DOOM_EFFECT = 18662, + WARLOCK_IMPROVED_HEALTH_FUNNEL_R1 = 18703, + WARLOCK_IMPROVED_HEALTH_FUNNEL_R2 = 18704, + WARLOCK_IMPROVED_HEALTH_FUNNEL_BUFF_R1 = 60955, + WARLOCK_IMPROVED_HEALTH_FUNNEL_BUFF_R2 = 60956, }; class spell_warl_banish : public SpellScriptLoader @@ -671,6 +675,48 @@ class spell_warl_curse_of_doom : public SpellScriptLoader } }; +class spell_warl_health_funnel : public SpellScriptLoader +{ +public: + spell_warl_health_funnel() : SpellScriptLoader("spell_warl_health_funnel") { } + + class spell_warl_health_funnel_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_health_funnel_AuraScript); + + void ApplyEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Unit* caster = GetCaster(); + if (!caster) + return; + + Unit* target = GetTarget(); + if (caster->HasAura(WARLOCK_IMPROVED_HEALTH_FUNNEL_R2)) + target->CastSpell(target, WARLOCK_IMPROVED_HEALTH_FUNNEL_BUFF_R2, true); + else if (caster->HasAura(WARLOCK_IMPROVED_HEALTH_FUNNEL_R1)) + target->CastSpell(target, WARLOCK_IMPROVED_HEALTH_FUNNEL_BUFF_R1, true); + } + + void RemoveEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Unit* target = GetTarget(); + target->RemoveAurasDueToSpell(WARLOCK_IMPROVED_HEALTH_FUNNEL_BUFF_R1); + target->RemoveAurasDueToSpell(WARLOCK_IMPROVED_HEALTH_FUNNEL_BUFF_R2); + } + + void Register() + { + OnEffectRemove += AuraEffectRemoveFn(spell_warl_health_funnel_AuraScript::RemoveEffect, EFFECT_0, SPELL_AURA_PERIODIC_HEAL, AURA_EFFECT_HANDLE_REAL); + OnEffectApply += AuraEffectApplyFn(spell_warl_health_funnel_AuraScript::ApplyEffect, EFFECT_0, SPELL_AURA_PERIODIC_HEAL, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_warl_health_funnel_AuraScript(); + } +}; + void AddSC_warlock_spell_scripts() { new spell_warl_banish(); @@ -686,4 +732,5 @@ void AddSC_warlock_spell_scripts() new spell_warl_haunt(); new spell_warl_unstable_affliction(); new spell_warl_curse_of_doom(); + new spell_warl_health_funnel(); } |
