/*
* 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();
}