/* * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Affero General Public License as published by the * Free Software Foundation; either version 3 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include "AchievementMgr.h" #include "Chat.h" #include "CommandScript.h" #include "Language.h" #include "Pet.h" #include "Player.h" #include "ScriptMgr.h" #include "WorldSessionMgr.h" using namespace Acore::ChatCommands; class reset_commandscript : public CommandScript { public: reset_commandscript() : CommandScript("reset_commandscript") { } ChatCommandTable GetCommands() const override { static ChatCommandTable resetItemsCommandTable = { { "equipped", HandleResetItemsEquippedCommand, SEC_ADMINISTRATOR, Console::Yes }, { "bags", HandleResetItemsInBagsCommand, SEC_ADMINISTRATOR, Console::Yes }, { "bank", HandleResetItemsInBankCommand, SEC_ADMINISTRATOR, Console::Yes }, { "keyring", HandleResetItemsKeyringCommand, SEC_ADMINISTRATOR, Console::Yes }, { "currency", HandleResetItemsInCurrenciesListCommand, SEC_ADMINISTRATOR, Console::Yes }, { "vendor_buyback", HandleResetItemsInVendorBuyBackTabCommand, SEC_ADMINISTRATOR, Console::Yes }, { "all", HandleResetItemsAllCommand, SEC_ADMINISTRATOR, Console::Yes }, { "allbags", HandleResetItemsAllAndDeleteBagsCommand, SEC_ADMINISTRATOR, Console::Yes }, }; static ChatCommandTable resetCommandTable = { { "achievements", HandleResetAchievementsCommand, SEC_CONSOLE, Console::Yes }, { "honor", HandleResetHonorCommand, SEC_ADMINISTRATOR, Console::Yes }, { "level", HandleResetLevelCommand, SEC_ADMINISTRATOR, Console::Yes }, { "spells", HandleResetSpellsCommand, SEC_ADMINISTRATOR, Console::Yes }, { "stats", HandleResetStatsCommand, SEC_ADMINISTRATOR, Console::Yes }, { "talents", HandleResetTalentsCommand, SEC_ADMINISTRATOR, Console::Yes }, { "items", resetItemsCommandTable }, { "all", HandleResetAllCommand, SEC_CONSOLE, Console::Yes } }; static ChatCommandTable commandTable = { { "reset", resetCommandTable } }; return commandTable; } static bool HandleResetAchievementsCommand(ChatHandler*, Optional target) { if (!target) { return false; } Player* playerTarget = target->GetConnectedPlayer(); if (playerTarget) playerTarget->ResetAchievements(); else AchievementMgr::DeleteFromDB(target->GetGUID().GetCounter()); return true; } static bool HandleResetHonorCommand(ChatHandler*, Optional target) { if (!target) { return false; } Player* playerTarget = target->GetConnectedPlayer(); playerTarget->SetHonorPoints(0); playerTarget->SetUInt32Value(PLAYER_FIELD_KILLS, 0); playerTarget->SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, 0); playerTarget->SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, 0); playerTarget->SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0); playerTarget->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL); return true; } static bool HandleResetStatsOrLevelHelper(Player* player) { ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(player->getClass()); if (!classEntry) { LOG_ERROR("dbc", "Class {} not found in DBC (Wrong DBC files?)", player->getClass()); return false; } uint8 powerType = classEntry->powerType; // reset m_form if no aura if (!player->HasShapeshiftAura()) player->SetShapeshiftForm(FORM_NONE); player->SetFactionForRace(player->getRace()); player->SetUInt32Value(UNIT_FIELD_BYTES_0, ((player->getRace()) | (player->getClass() << 8) | (player->getGender() << 16) | (powerType << 24))); // reset only if player not in some form; if (player->GetShapeshiftForm() == FORM_NONE) player->InitDisplayIds(); player->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP); player->ReplaceAllUnitFlags(UNIT_FLAG_PLAYER_CONTROLLED); //-1 is default value player->SetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, uint32(-1)); return true; } static bool HandleResetLevelCommand(ChatHandler*, Optional target) { if (!target) { return false; } Player* playerTarget = target->GetConnectedPlayer(); if (!HandleResetStatsOrLevelHelper(playerTarget)) return false; uint8 oldLevel = playerTarget->GetLevel(); // set starting level uint32 startLevel = !playerTarget->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_INIT) ? sWorld->getIntConfig(CONFIG_START_PLAYER_LEVEL) : sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL); playerTarget->_ApplyAllLevelScaleItemMods(false); playerTarget->SetLevel(startLevel); playerTarget->InitRunes(); playerTarget->InitStatsForLevel(true); playerTarget->InitTaxiNodesForLevel(); playerTarget->InitGlyphsForLevel(); playerTarget->InitTalentForLevel(); playerTarget->SetUInt32Value(PLAYER_XP, 0); playerTarget->_ApplyAllLevelScaleItemMods(true); // reset level for pet if (Pet* pet = playerTarget->GetPet()) pet->SynchronizeLevelWithOwner(); sScriptMgr->OnPlayerLevelChanged(playerTarget, oldLevel); return true; } static bool HandleResetSpellsCommand(ChatHandler* handler, Optional target) { if (!target) { target = PlayerIdentifier::FromTargetOrSelf(handler); } if (!target) { return false; } Player* playerTarget = target->GetConnectedPlayer(); if (target) { playerTarget->resetSpells(/* bool myClassOnly */); ChatHandler(playerTarget->GetSession()).SendSysMessage(LANG_RESET_SPELLS); if (!handler->GetSession() || handler->GetSession()->GetPlayer() != playerTarget) handler->PSendSysMessage(LANG_RESET_SPELLS_ONLINE, handler->GetNameLink(playerTarget)); } else { CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); stmt->SetData(0, uint16(AT_LOGIN_RESET_SPELLS)); stmt->SetData(1, playerTarget->GetGUID().GetCounter()); CharacterDatabase.Execute(stmt); handler->PSendSysMessage(LANG_RESET_SPELLS_OFFLINE, target->GetName()); } return true; } static bool HandleResetStatsCommand(ChatHandler*, Optional target) { if (!target) { return false; } Player* playerTarget = target->GetConnectedPlayer(); if (!HandleResetStatsOrLevelHelper(playerTarget)) return false; playerTarget->InitRunes(); playerTarget->InitStatsForLevel(true); playerTarget->InitTaxiNodesForLevel(); playerTarget->InitGlyphsForLevel(); playerTarget->InitTalentForLevel(); return true; } static bool HandleResetTalentsCommand(ChatHandler* handler, Optional target) { Player* targetPlayer = nullptr; if (target) { targetPlayer = target->GetConnectedPlayer(); } else { handler->SendErrorMessage(LANG_NO_CHAR_SELECTED); return false; } if (targetPlayer) { targetPlayer->resetTalents(true); targetPlayer->SendTalentsInfoData(false); ChatHandler(targetPlayer->GetSession()).SendSysMessage(LANG_RESET_TALENTS); if (!handler->GetSession() || handler->GetSession()->GetPlayer() != targetPlayer) handler->PSendSysMessage(LANG_RESET_TALENTS_ONLINE, handler->GetNameLink(targetPlayer)); Pet* pet = targetPlayer->GetPet(); Pet::resetTalentsForAllPetsOf(targetPlayer, pet); if (pet) targetPlayer->SendTalentsInfoData(true); return true; } else { CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); stmt->SetData(0, uint16(AT_LOGIN_RESET_TALENTS | AT_LOGIN_RESET_PET_TALENTS)); stmt->SetData(1, target->GetGUID().GetCounter()); CharacterDatabase.Execute(stmt); std::string nameLink = handler->playerLink(target->GetName()); handler->PSendSysMessage(LANG_RESET_TALENTS_OFFLINE, nameLink); return true; } } static bool HandleResetAllCommand(ChatHandler* handler, std::string_view caseName) { AtLoginFlags atLogin; // Command specially created as single command to prevent using short case names if (caseName == "spells") { atLogin = AT_LOGIN_RESET_SPELLS; handler->SendWorldText(LANG_RESETALL_SPELLS); if (!handler->GetSession()) handler->SendSysMessage(LANG_RESETALL_SPELLS); } else if (caseName == "talents") { atLogin = AtLoginFlags(AT_LOGIN_RESET_TALENTS | AT_LOGIN_RESET_PET_TALENTS); handler->SendWorldText(LANG_RESETALL_TALENTS); if (!handler->GetSession()) handler->SendSysMessage(LANG_RESETALL_TALENTS); } else { handler->SendErrorMessage(LANG_RESETALL_UNKNOWN_CASE, caseName); return false; } CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ALL_AT_LOGIN_FLAGS); stmt->SetData(0, uint16(atLogin)); CharacterDatabase.Execute(stmt); sWorldSessionMgr->DoForAllOnlinePlayers([&] (Player* player){ player->SetAtLoginFlag(atLogin); }); return true; } static bool HandleResetItemsEquippedCommand(ChatHandler* handler, Optional target) { Player* targetPlayer = GetPlayerFromIdentifierOrSelectedTarget(handler, target); if (!targetPlayer) { return false; } else { int16 deletedItemsCount = ResetItemsEquipped(targetPlayer); handler->PSendSysMessage(LANG_COMMAND_RESET_ITEMS_EQUIPPED, deletedItemsCount, handler->GetNameLink(targetPlayer)); } return true; } static bool HandleResetItemsInBagsCommand(ChatHandler* handler, Optional target) { Player* targetPlayer = GetPlayerFromIdentifierOrSelectedTarget(handler, target); if (!targetPlayer) { return false; } else { int16 deletedItemsCount = ResetItemsInBags(targetPlayer); handler->PSendSysMessage(LANG_COMMAND_RESET_ITEMS_BAGS, deletedItemsCount, handler->GetNameLink(targetPlayer)); } return true; } static bool HandleResetItemsKeyringCommand(ChatHandler* handler, Optional target) { Player* targetPlayer = GetPlayerFromIdentifierOrSelectedTarget(handler, target); if (!targetPlayer) { return false; } else { int16 deletedItemsCount = ResetItemsInKeyring(targetPlayer); handler->PSendSysMessage(LANG_COMMAND_RESET_ITEMS_KEYRING, deletedItemsCount, handler->GetNameLink(targetPlayer)); } return true; } static bool HandleResetItemsInCurrenciesListCommand(ChatHandler* handler, Optional target) { Player* targetPlayer = GetPlayerFromIdentifierOrSelectedTarget(handler, target); if (!targetPlayer) { return false; } else { int16 deletedItemsCount = ResetItemsInCurrenciesList(targetPlayer); handler->PSendSysMessage(LANG_COMMAND_RESET_ITEMS_CURRENCY, deletedItemsCount, handler->GetNameLink(targetPlayer)); } return true; } static bool HandleResetItemsInBankCommand(ChatHandler* handler, Optional target) { Player* targetPlayer = GetPlayerFromIdentifierOrSelectedTarget(handler, target); if (!targetPlayer) { return false; } else { int16 deletedItemsCount = ResetItemsInBank(targetPlayer); handler->PSendSysMessage(LANG_COMMAND_RESET_ITEMS_BANK, deletedItemsCount, handler->GetNameLink(targetPlayer)); } return true; } static bool HandleResetItemsInVendorBuyBackTabCommand(ChatHandler* handler, Optional target) { Player* targetPlayer = GetPlayerFromIdentifierOrSelectedTarget(handler, target); if (!targetPlayer) { return false; } else { int16 deletedItemsCount = ResetItemsInVendorBuyBackTab(targetPlayer); handler->PSendSysMessage(LANG_COMMAND_RESET_ITEMS_BUYBACK, deletedItemsCount, handler->GetNameLink(targetPlayer)); } return true; } static bool HandleResetItemsAllCommand(ChatHandler* handler, Optional target) { Player* targetPlayer = GetPlayerFromIdentifierOrSelectedTarget(handler, target); if (!targetPlayer) { return false; } else { // Delete all items destinations int16 deletedItemsEquippedCount = ResetItemsEquipped(targetPlayer); int16 deletedItemsInBagsCount = ResetItemsInBags(targetPlayer); int16 deletedItemsInBankCount = ResetItemsInBank(targetPlayer); int16 deletedItemsInKeyringCount = ResetItemsInKeyring(targetPlayer); int16 deletedItemsInCurrenciesListCount = ResetItemsInCurrenciesList(targetPlayer); int16 deletedItemsInVendorBuyBackTabCount = ResetItemsInVendorBuyBackTab(targetPlayer); handler->PSendSysMessage(LANG_COMMAND_RESET_ITEMS_ALL, handler->GetNameLink(targetPlayer), deletedItemsEquippedCount, deletedItemsInBagsCount, deletedItemsInBankCount, deletedItemsInKeyringCount, deletedItemsInCurrenciesListCount, deletedItemsInVendorBuyBackTabCount); } return true; } static bool HandleResetItemsAllAndDeleteBagsCommand(ChatHandler* handler, Optional target) { Player* targetPlayer = GetPlayerFromIdentifierOrSelectedTarget(handler, target); if (!targetPlayer) { return false; } else { // Delete all items destinations int16 deletedItemsEquippedCount = ResetItemsEquipped(targetPlayer); int16 deletedItemsInBagsCount = ResetItemsInBags(targetPlayer); int16 deletedItemsInBankCount = ResetItemsInBank(targetPlayer); int16 deletedItemsInKeyringCount = ResetItemsInKeyring(targetPlayer); int16 deletedItemsInCurrenciesListCount = ResetItemsInCurrenciesList(targetPlayer); int16 deletedItemsInVendorBuyBackTabCount = ResetItemsInVendorBuyBackTab(targetPlayer); int16 deletedItemsStandardBagsCount = ResetItemsDeleteStandardBags(targetPlayer); int16 deletedItemsBankBagsCount = ResetItemsDeleteBankBags(targetPlayer); handler->PSendSysMessage(LANG_COMMAND_RESET_ITEMS_ALL_BAGS, handler->GetNameLink(targetPlayer), deletedItemsEquippedCount, deletedItemsInBagsCount, deletedItemsInBankCount, deletedItemsInKeyringCount, deletedItemsInCurrenciesListCount, deletedItemsInVendorBuyBackTabCount, deletedItemsStandardBagsCount, deletedItemsBankBagsCount); } return true; } private: static Player* GetPlayerFromIdentifierOrSelectedTarget(ChatHandler* handler, Optional target) { Player* targetPlayer = nullptr; // Check if there is an optional target player name // Do not use TargetOrSelf, we must be sure to select ourself if (!target) { // No optional target, so try to get selected target target = PlayerIdentifier::FromTarget(handler); if (!target) { // No character selected handler->SendSysMessage(LANG_NO_CHAR_SELECTED); return targetPlayer; } targetPlayer = target->GetConnectedPlayer(); } else { targetPlayer = target->GetConnectedPlayer(); if (!targetPlayer || !target->IsConnected()) { // No character selected handler->SendSysMessage(LANG_PLAYER_NOT_EXIST_OR_OFFLINE); } } return targetPlayer; } static int16 ResetItemsEquipped(Player* playerTarget) { if (!playerTarget) { return -1; } int16 count = 0; for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; ++i) { Item* pItem = playerTarget->GetItemByPos(INVENTORY_SLOT_BAG_0, i); if (pItem) { playerTarget->DestroyItem(INVENTORY_SLOT_BAG_0, i, true); ++count; } } return count; } static int16 ResetItemsInBags(Player* playerTarget) { if (!playerTarget) { return -1; } int16 count = 0; // Default bagpack : for (uint8 i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; ++i) { Item* pItem = playerTarget->GetItemByPos(INVENTORY_SLOT_BAG_0, i); if (pItem) { playerTarget->DestroyItem(INVENTORY_SLOT_BAG_0, i, true); ++count; } } // Bag slots for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) { Bag* pBag = (Bag*)playerTarget->GetItemByPos(INVENTORY_SLOT_BAG_0, i); if (pBag) { for (uint8 j = 0; j < pBag->GetBagSize(); ++j) { Item* pItem = pBag->GetItemByPos(j); if (pItem) { playerTarget->DestroyItem(i, j, true); ++count; } } } } return count; } static int16 ResetItemsInBank(Player* playerTarget) { if (!playerTarget) { return -1; } int16 count = 0; // Normal bank slot for (uint8 i = BANK_SLOT_ITEM_START; i < BANK_SLOT_ITEM_END; ++i) { Item* pItem = playerTarget->GetItemByPos(INVENTORY_SLOT_BAG_0, i); if (pItem) { playerTarget->DestroyItem(INVENTORY_SLOT_BAG_0, i, true); ++count; } } // Bank bagslots for (uint8 i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; ++i) { Bag* pBag = (Bag*)playerTarget->GetItemByPos(INVENTORY_SLOT_BAG_0, i); if (pBag) { for (uint8 j = 0; j < pBag->GetBagSize(); ++j) { Item* pItem = pBag->GetItemByPos(j); if (pItem) { playerTarget->DestroyItem(i, j, true); ++count; } } } } return count; } static int16 ResetItemsInKeyring(Player* playerTarget) { if (!playerTarget) { return -1; } int16 count = 0; for (uint8 i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; ++i) { Item* pItem = playerTarget->GetItemByPos(INVENTORY_SLOT_BAG_0, i); if (pItem) { playerTarget->DestroyItem(INVENTORY_SLOT_BAG_0, i, true); ++count; } } return count; } static int16 ResetItemsInCurrenciesList(Player* playerTarget) { if (!playerTarget) { return -1; } int16 count = 0; for (uint8 i = CURRENCYTOKEN_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i) { Item* pItem = playerTarget->GetItemByPos(INVENTORY_SLOT_BAG_0, i); if (pItem) { playerTarget->DestroyItem(INVENTORY_SLOT_BAG_0, i, true); ++count; } } return count; } static int16 ResetItemsInVendorBuyBackTab(Player* playerTarget) { if (!playerTarget) { return -1; } int16 count = 0; for (uint8 i = BUYBACK_SLOT_START; i < BUYBACK_SLOT_END; ++i) { Item* pItem = playerTarget->GetItemFromBuyBackSlot(i); if (pItem) { playerTarget->RemoveItemFromBuyBackSlot(i, true); ++count; } } return count; } static int16 ResetItemsDeleteStandardBags(Player* playerTarget) { if (!playerTarget) { return -1; } int16 count = 0; // Standard bag slots for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) { Bag* pBag = (Bag*)playerTarget->GetItemByPos(INVENTORY_SLOT_BAG_0, i); if (pBag) { playerTarget->DestroyItem(INVENTORY_SLOT_BAG_0, i, true); ++count; } } return count; } static int16 ResetItemsDeleteBankBags(Player* playerTarget) { if (!playerTarget) { return -1; } int16 count = 0; // Bank bags for (uint8 i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; ++i) { Bag* pBag = (Bag*)playerTarget->GetItemByPos(INVENTORY_SLOT_BAG_0, i); if (pBag) { // prevent no empty ? playerTarget->DestroyItem(INVENTORY_SLOT_BAG_0, i, true); ++count; } } return count; } }; void AddSC_reset_commandscript() { new reset_commandscript(); }