/* * 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 "CharacterCache.h" #include "Chat.h" #include "CommandScript.h" #include "GameEventMgr.h" #include "ObjectAccessor.h" #include "ObjectMgr.h" #include "Player.h" #include "ReputationMgr.h" #include "SharedDefines.h" #include "SpellInfo.h" #include "SpellMgr.h" using namespace Acore::ChatCommands; class lookup_commandscript : public CommandScript { public: lookup_commandscript() : CommandScript("lookup_commandscript") { } ChatCommandTable GetCommands() const override { static ChatCommandTable lookupPlayerCommandTable = { { "ip", HandleLookupPlayerIpCommand, SEC_GAMEMASTER, Console::Yes }, { "account", HandleLookupPlayerAccountCommand, SEC_GAMEMASTER, Console::Yes }, { "email", HandleLookupPlayerEmailCommand, SEC_GAMEMASTER, Console::Yes } }; static ChatCommandTable lookupCommandTable = { { "area", HandleLookupAreaCommand, SEC_MODERATOR, Console::Yes }, { "creature", HandleLookupCreatureCommand, SEC_MODERATOR, Console::Yes }, { "event", HandleLookupEventCommand, SEC_MODERATOR, Console::Yes }, { "faction", HandleLookupFactionCommand, SEC_MODERATOR, Console::Yes }, { "item", HandleLookupItemCommand, SEC_MODERATOR, Console::Yes }, { "item set", HandleLookupItemSetCommand, SEC_MODERATOR, Console::Yes }, { "map", HandleLookupMapCommand, SEC_MODERATOR, Console::Yes }, { "object", HandleLookupObjectCommand, SEC_MODERATOR, Console::Yes }, { "gobject", HandleLookupObjectCommand, SEC_MODERATOR, Console::Yes }, { "quest", HandleLookupQuestCommand, SEC_MODERATOR, Console::Yes }, { "skill", HandleLookupSkillCommand, SEC_MODERATOR, Console::Yes }, { "taxinode", HandleLookupTaxiNodeCommand, SEC_MODERATOR, Console::Yes }, { "teleport", HandleLookupTeleCommand, SEC_MODERATOR, Console::Yes }, { "title", HandleLookupTitleCommand, SEC_MODERATOR, Console::Yes }, { "spell", HandleLookupSpellCommand, SEC_MODERATOR, Console::Yes }, { "spell id", HandleLookupSpellIdCommand, SEC_MODERATOR, Console::Yes }, { "player", lookupPlayerCommandTable }, }; static ChatCommandTable commandTable = { { "lookup", lookupCommandTable } }; return commandTable; } static bool HandleLookupAreaCommand(ChatHandler* handler, Tail namePart) { if (namePart.empty()) { return false; } std::wstring wNamePart; if (!Utf8toWStr(namePart, wNamePart)) { return false; } bool found = false; uint32 count = 0; uint32 maxResults = sWorld->getIntConfig(CONFIG_MAX_RESULTS_LOOKUP_COMMANDS); // converting string that we try to find to lower case wstrToLower(wNamePart); // Search in AreaTable.dbc for (auto areaEntry : sAreaTableStore) { int locale = handler->GetSessionDbcLocale(); std::string name = areaEntry->area_name[locale]; if (name.empty()) { continue; } if (!Utf8FitTo(name, wNamePart)) { locale = 0; for (; locale < TOTAL_LOCALES; ++locale) { if (locale == handler->GetSessionDbcLocale()) { continue; } name = areaEntry->area_name[locale]; if (name.empty()) { continue; } if (Utf8FitTo(name, wNamePart)) { break; } } } if (locale < TOTAL_LOCALES) { if (maxResults && count++ == maxResults) { handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults); return true; } // send area in "id - [name]" format std::ostringstream ss; if (handler->GetSession()) { ss << areaEntry->ID << " - |cffffffff|Harea:" << areaEntry->ID << "|h[" << name << ' ' << localeNames[locale] << "]|h|r"; } else { ss << areaEntry->ID << " - " << name << ' ' << localeNames[locale]; } handler->SendSysMessage(ss.str().c_str()); if (!found) { found = true; } } } if (!found) { handler->SendSysMessage(LANG_COMMAND_NOAREAFOUND); } return true; } static bool HandleLookupCreatureCommand(ChatHandler* handler, Tail namePart) { if (namePart.empty()) { return false; } std::wstring wNamePart; // converting string that we try to find to lower case if (!Utf8toWStr(namePart, wNamePart)) { return false; } wstrToLower(wNamePart); bool found = false; uint32 count = 0; uint32 maxResults = sWorld->getIntConfig(CONFIG_MAX_RESULTS_LOOKUP_COMMANDS); for (auto const& [entry, creatureTemplate] : *sObjectMgr->GetCreatureTemplates()) { uint32 id = creatureTemplate.Entry; uint8 localeIndex = handler->GetSessionDbLocaleIndex(); if (CreatureLocale const* creatureLocale = sObjectMgr->GetCreatureLocale(id)) { if (creatureLocale->Name.size() > localeIndex && !creatureLocale->Name[localeIndex].empty()) { std::string name = creatureLocale->Name[localeIndex]; if (Utf8FitTo(name, wNamePart)) { if (maxResults && count++ == maxResults) { handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults); return true; } if (handler->GetSession()) { handler->PSendSysMessage(LANG_CREATURE_ENTRY_LIST_CHAT, id, id, name); } else { handler->PSendSysMessage(LANG_CREATURE_ENTRY_LIST_CONSOLE, id, name); } if (!found) { found = true; } continue; } } } std::string name = creatureTemplate.Name; if (name.empty()) { continue; } if (Utf8FitTo(name, wNamePart)) { if (maxResults && count++ == maxResults) { handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults); return true; } if (handler->GetSession()) { handler->PSendSysMessage(LANG_CREATURE_ENTRY_LIST_CHAT, id, id, name); } else { handler->PSendSysMessage(LANG_CREATURE_ENTRY_LIST_CONSOLE, id, name); } if (!found) { found = true; } } } if (!found) { handler->SendSysMessage(LANG_COMMAND_NOCREATUREFOUND); } return true; } static bool HandleLookupEventCommand(ChatHandler* handler, Tail namePart) { if (namePart.empty()) return false; std::wstring wNamePart; // converting string that we try to find to lower case if (!Utf8toWStr(namePart, wNamePart)) return false; wstrToLower(wNamePart); bool found = false; uint32 count = 0; uint32 maxResults = sWorld->getIntConfig(CONFIG_MAX_RESULTS_LOOKUP_COMMANDS); GameEventMgr::GameEventDataMap const& events = sGameEventMgr->GetEventMap(); GameEventMgr::ActiveEvents const& activeEvents = sGameEventMgr->GetActiveEventList(); for (uint32 id = 0; id < events.size(); ++id) { GameEventData const& eventData = events[id]; std::string descr = eventData.Description; if (descr.empty()) continue; if (Utf8FitTo(descr, wNamePart)) { if (maxResults && count++ == maxResults) { handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults); return true; } std::string active = activeEvents.find(id) != activeEvents.end() ? handler->GetAcoreString(LANG_ACTIVE) : ""; if (handler->GetSession()) handler->PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT, id, id, eventData.Description, active); else handler->PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE, id, eventData.Description, active); if (!found) found = true; } } if (!found) handler->SendSysMessage(LANG_NOEVENTFOUND); return true; } static bool HandleLookupFactionCommand(ChatHandler* handler, Tail namePart) { if (namePart.empty()) { return false; } // Can be nullptr at console call Player* target = handler->getSelectedPlayer(); std::wstring wNamePart; if (!Utf8toWStr(namePart, wNamePart)) { return false; } // converting string that we try to find to lower case wstrToLower(wNamePart); bool found = false; uint32 count = 0; uint32 maxResults = sWorld->getIntConfig(CONFIG_MAX_RESULTS_LOOKUP_COMMANDS); for (auto factionEntry : sFactionStore) { FactionState const* factionState = target ? target->GetReputationMgr().GetState(factionEntry) : nullptr; int locale = handler->GetSessionDbcLocale(); std::string name = factionEntry->name[locale]; if (name.empty()) { continue; } if (!Utf8FitTo(name, wNamePart)) { locale = 0; for (; locale < TOTAL_LOCALES; ++locale) { if (locale == handler->GetSessionDbcLocale()) { continue; } name = factionEntry->name[locale]; if (name.empty()) { continue; } if (Utf8FitTo(name, wNamePart)) { break; } } } if (locale < TOTAL_LOCALES) { if (maxResults && count++ == maxResults) { handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults); return true; } // send faction in "id - [faction] rank reputation [visible] [at war] [own team] [unknown] [invisible] [inactive]" format // or "id - [faction] [no reputation]" format std::ostringstream ss; if (handler->GetSession()) { ss << factionEntry->ID << " - |cffffffff|Hfaction:" << factionEntry->ID << "|h[" << name << ' ' << localeNames[locale] << "]|h|r"; } else { ss << factionEntry->ID << " - " << name << ' ' << localeNames[locale]; } if (factionState) // and then target != nullptr also { uint32 index = target->GetReputationMgr().GetReputationRankStrIndex(factionEntry); std::string rankName = handler->GetAcoreString(index); ss << ' ' << rankName << "|h|r (" << target->GetReputationMgr().GetReputation(factionEntry) << ')'; if (factionState->Flags & FACTION_FLAG_VISIBLE) { ss << handler->GetAcoreString(LANG_FACTION_VISIBLE); } if (factionState->Flags & FACTION_FLAG_AT_WAR) { ss << handler->GetAcoreString(LANG_FACTION_ATWAR); } if (factionState->Flags & FACTION_FLAG_PEACE_FORCED) { ss << handler->GetAcoreString(LANG_FACTION_PEACE_FORCED); } if (factionState->Flags & FACTION_FLAG_HIDDEN) { ss << handler->GetAcoreString(LANG_FACTION_HIDDEN); } if (factionState->Flags & FACTION_FLAG_INVISIBLE_FORCED) { ss << handler->GetAcoreString(LANG_FACTION_INVISIBLE_FORCED); } if (factionState->Flags & FACTION_FLAG_INACTIVE) { ss << handler->GetAcoreString(LANG_FACTION_INACTIVE); } } else { ss << handler->GetAcoreString(LANG_FACTION_NOREPUTATION); } handler->SendSysMessage(ss.str().c_str()); if (!found) { found = true; } } } if (!found) { handler->SendSysMessage(LANG_COMMAND_FACTION_NOTFOUND); } return true; } static bool HandleLookupItemCommand(ChatHandler* handler, Tail namePart) { if (namePart.empty()) { return false; } std::wstring wNamePart; // converting string that we try to find to lower case if (!Utf8toWStr(namePart, wNamePart)) { return false; } wstrToLower(wNamePart); bool found = false; uint32 count = 0; uint32 maxResults = sWorld->getIntConfig(CONFIG_MAX_RESULTS_LOOKUP_COMMANDS); // Search in `item_template` for (auto const& [entry, itemTemplate] : *sObjectMgr->GetItemTemplateStore()) { int localeIndex = handler->GetSessionDbLocaleIndex(); if (localeIndex >= 0) { uint8 ulocaleIndex = uint8(localeIndex); if (ItemLocale const* il = sObjectMgr->GetItemLocale(itemTemplate.ItemId)) { if (il->Name.size() > ulocaleIndex && !il->Name[ulocaleIndex].empty()) { std::string name = il->Name[ulocaleIndex]; if (Utf8FitTo(name, wNamePart)) { if (maxResults && count++ == maxResults) { handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults); return true; } if (handler->GetSession()) { std::ostringstream color; color << std::hex << ItemQualityColors[itemTemplate.Quality]; handler->PSendSysMessage(LANG_ITEM_LIST_CHAT, itemTemplate.ItemId, color.str(), itemTemplate.ItemId, name); } else { handler->PSendSysMessage(LANG_ITEM_LIST_CONSOLE, itemTemplate.ItemId, name); } if (!found) { found = true; } continue; } } } } std::string name = itemTemplate.Name1; if (name.empty()) { continue; } if (Utf8FitTo(name, wNamePart)) { if (maxResults && count++ == maxResults) { handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults); return true; } if (handler->GetSession()) { std::ostringstream color; color << std::hex << ItemQualityColors[itemTemplate.Quality]; handler->PSendSysMessage(LANG_ITEM_LIST_CHAT, itemTemplate.ItemId, color.str(), itemTemplate.ItemId, name); } else { handler->PSendSysMessage(LANG_ITEM_LIST_CONSOLE, itemTemplate.ItemId, name); } if (!found) { found = true; } } } if (!found) { handler->SendSysMessage(LANG_COMMAND_NOITEMFOUND); } return true; } static bool HandleLookupItemSetCommand(ChatHandler* handler, Tail namePart) { if (namePart.empty()) { return false; } std::wstring wNamePart; if (!Utf8toWStr(namePart, wNamePart)) { return false; } // converting string that we try to find to lower case wstrToLower(wNamePart); bool found = false; uint32 count = 0; uint32 maxResults = sWorld->getIntConfig(CONFIG_MAX_RESULTS_LOOKUP_COMMANDS); // Search in ItemSet.dbc for (uint32 id = 0; id < sItemSetStore.GetNumRows(); id++) { ItemSetEntry const* set = sItemSetStore.LookupEntry(id); if (set) { int locale = handler->GetSessionDbcLocale(); std::string name = set->name[locale]; if (name.empty()) { continue; } if (!Utf8FitTo(name, wNamePart)) { locale = 0; for (; locale < TOTAL_LOCALES; ++locale) { if (locale == handler->GetSessionDbcLocale()) { continue; } name = set->name[locale]; if (name.empty()) { continue; } if (Utf8FitTo(name, wNamePart)) { break; } } } if (locale < TOTAL_LOCALES) { if (maxResults && count++ == maxResults) { handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults); return true; } // send item set in "id - [namedlink locale]" format if (handler->GetSession()) { handler->PSendSysMessage(LANG_ITEMSET_LIST_CHAT, id, id, name, localeNames[locale]); } else { handler->PSendSysMessage(LANG_ITEMSET_LIST_CONSOLE, id, name, localeNames[locale]); } if (!found) { found = true; } } } } if (!found) { handler->SendSysMessage(LANG_COMMAND_NOITEMSETFOUND); } return true; } static bool HandleLookupObjectCommand(ChatHandler* handler, Tail namePart) { if (namePart.empty()) { return false; } std::wstring wNamePart; // converting string that we try to find to lower case if (!Utf8toWStr(namePart, wNamePart)) { return false; } wstrToLower(wNamePart); bool found = false; uint32 count = 0; uint32 maxResults = sWorld->getIntConfig(CONFIG_MAX_RESULTS_LOOKUP_COMMANDS); for (auto const& [entry, gameObjectTemplate] : *sObjectMgr->GetGameObjectTemplates()) { uint8 localeIndex = handler->GetSessionDbLocaleIndex(); if (GameObjectLocale const* objectLocalte = sObjectMgr->GetGameObjectLocale(gameObjectTemplate.entry)) { if (objectLocalte->Name.size() > localeIndex && !objectLocalte->Name[localeIndex].empty()) { std::string name = objectLocalte->Name[localeIndex]; if (Utf8FitTo(name, wNamePart)) { if (maxResults && count++ == maxResults) { handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults); return true; } if (handler->GetSession()) { handler->PSendSysMessage(LANG_GO_ENTRY_LIST_CHAT, gameObjectTemplate.entry, gameObjectTemplate.entry, name); } else { handler->PSendSysMessage(LANG_GO_ENTRY_LIST_CONSOLE, gameObjectTemplate.entry, name); } if (!found) { found = true; } continue; } } } std::string name = gameObjectTemplate.name; if (name.empty()) { continue; } if (Utf8FitTo(name, wNamePart)) { if (maxResults && count++ == maxResults) { handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults); return true; } if (handler->GetSession()) { handler->PSendSysMessage(LANG_GO_ENTRY_LIST_CHAT, gameObjectTemplate.entry, gameObjectTemplate.entry, name); } else { handler->PSendSysMessage(LANG_GO_ENTRY_LIST_CONSOLE, gameObjectTemplate.entry, name); } if (!found) { found = true; } } } if (!found) { handler->SendSysMessage(LANG_COMMAND_NOGAMEOBJECTFOUND); } return true; } static bool HandleLookupQuestCommand(ChatHandler* handler, Tail namePart) { if (namePart.empty()) { return false; } // can be nullptr at console call Player* target = handler->getSelectedPlayer(); std::wstring wNamePart; // converting string that we try to find to lower case if (!Utf8toWStr(namePart, wNamePart)) { return false; } wstrToLower(wNamePart); bool found = false; uint32 count = 0; uint32 maxResults = sWorld->getIntConfig(CONFIG_MAX_RESULTS_LOOKUP_COMMANDS); for (auto const& [entry, qInfo] : sObjectMgr->GetQuestTemplates()) { int localeIndex = handler->GetSessionDbLocaleIndex(); if (localeIndex >= 0) { uint8 ulocaleIndex = uint8(localeIndex); if (QuestLocale const* questLocale = sObjectMgr->GetQuestLocale(qInfo->GetQuestId())) { if (questLocale->Title.size() > ulocaleIndex && !questLocale->Title[ulocaleIndex].empty()) { std::string title = questLocale->Title[ulocaleIndex]; if (Utf8FitTo(title, wNamePart)) { if (maxResults && count++ == maxResults) { handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults); return true; } std::string statusStr = ""; if (target) { QuestStatus status = target->GetQuestStatus(qInfo->GetQuestId()); switch (status) { case QUEST_STATUS_COMPLETE: statusStr = handler->GetAcoreString(LANG_COMPLETE); break; case QUEST_STATUS_INCOMPLETE: statusStr = handler->GetAcoreString(LANG_ACTIVE); break; case QUEST_STATUS_REWARDED: statusStr = handler->GetAcoreString(LANG_REWARDED); break; default: break; } } if (handler->GetSession()) { handler->PSendSysMessage(LANG_QUEST_LIST_CHAT, qInfo->GetQuestId(), qInfo->GetQuestId(), qInfo->GetQuestLevel(), title, statusStr); } else { handler->PSendSysMessage(LANG_QUEST_LIST_CONSOLE, qInfo->GetQuestId(), title, statusStr); } if (!found) { found = true; } continue; } } } } std::string title = qInfo->GetTitle(); if (title.empty()) { continue; } if (Utf8FitTo(title, wNamePart)) { if (maxResults && count++ == maxResults) { handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults); return true; } std::string statusStr = ""; if (target) { QuestStatus status = target->GetQuestStatus(qInfo->GetQuestId()); switch (status) { case QUEST_STATUS_COMPLETE: statusStr = handler->GetAcoreString(LANG_COMPLETE); break; case QUEST_STATUS_INCOMPLETE: statusStr = handler->GetAcoreString(LANG_ACTIVE); break; case QUEST_STATUS_REWARDED: statusStr = handler->GetAcoreString(LANG_REWARDED); break; default: break; } } if (handler->GetSession()) { handler->PSendSysMessage(LANG_QUEST_LIST_CHAT, qInfo->GetQuestId(), qInfo->GetQuestId(), qInfo->GetQuestLevel(), title, statusStr); } else { handler->PSendSysMessage(LANG_QUEST_LIST_CONSOLE, qInfo->GetQuestId(), title, statusStr); } if (!found) { found = true; } } } if (!found) { handler->SendSysMessage(LANG_COMMAND_NOQUESTFOUND); } return true; } static bool HandleLookupSkillCommand(ChatHandler* handler, Tail namePart) { if (namePart.empty()) { return false; } // can be nullptr in console call Player* target = handler->getSelectedPlayer(); std::wstring wNamePart; if (!Utf8toWStr(namePart, wNamePart)) { return false; } // converting string that we try to find to lower case wstrToLower(wNamePart); bool found = false; uint32 count = 0; uint32 maxResults = sWorld->getIntConfig(CONFIG_MAX_RESULTS_LOOKUP_COMMANDS); // Search in SkillLine.dbc for (auto skillInfo : sSkillLineStore) { int locale = handler->GetSessionDbcLocale(); std::string name = skillInfo->name[locale]; if (name.empty()) { continue; } if (!Utf8FitTo(name, wNamePart)) { locale = 0; for (; locale < TOTAL_LOCALES; ++locale) { if (locale == handler->GetSessionDbcLocale()) { continue; } name = skillInfo->name[locale]; if (name.empty()) { continue; } if (Utf8FitTo(name, wNamePart)) { break; } } } if (locale < TOTAL_LOCALES) { if (maxResults && count++ == maxResults) { handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults); return true; } std::string valStr; std::string knownStr; if (target && target->HasSkill(skillInfo->id)) { knownStr = handler->GetAcoreString(LANG_KNOWN); uint32 curValue = target->GetPureSkillValue(skillInfo->id); uint32 maxValue = target->GetPureMaxSkillValue(skillInfo->id); uint32 permValue = target->GetSkillPermBonusValue(skillInfo->id); uint32 tempValue = target->GetSkillTempBonusValue(skillInfo->id); valStr = Acore::StringFormat(handler->GetAcoreString(LANG_SKILL_VALUES), curValue, maxValue, permValue, tempValue); } // send skill in "id - [namedlink locale]" format if (handler->GetSession()) { handler->PSendSysMessage(LANG_SKILL_LIST_CHAT, skillInfo->id, skillInfo->id, name, localeNames[locale], knownStr, valStr); } else { handler->PSendSysMessage(LANG_SKILL_LIST_CONSOLE, skillInfo->id, name, localeNames[locale], knownStr, valStr); } if (!found) { found = true; } } } if (!found) { handler->SendSysMessage(LANG_COMMAND_NOSKILLFOUND); } return true; } static bool HandleLookupSpellCommand(ChatHandler* handler, Tail namePart) { if (namePart.empty()) { return false; } // can be nullptr at console call Player* target = handler->getSelectedPlayer(); std::wstring wNamePart; if (!Utf8toWStr(namePart, wNamePart)) { return false; } // converting string that we try to find to lower case wstrToLower(wNamePart); bool found = false; uint32 count = 0; uint32 maxResults = sWorld->getIntConfig(CONFIG_MAX_RESULTS_LOOKUP_COMMANDS); // Search in Spell.dbc for (uint32 id = 0; id < sSpellMgr->GetSpellInfoStoreSize(); id++) { SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(id); if (spellInfo) { int locale = handler->GetSessionDbcLocale(); std::string name = spellInfo->SpellName[locale]; if (name.empty()) { continue; } if (!Utf8FitTo(name, wNamePart)) { locale = 0; for (; locale < TOTAL_LOCALES; ++locale) { if (locale == handler->GetSessionDbcLocale()) { continue; } name = spellInfo->SpellName[locale]; if (name.empty()) { continue; } if (Utf8FitTo(name, wNamePart)) { break; } } } if (locale < TOTAL_LOCALES) { if (maxResults && count++ == maxResults) { handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults); return true; } bool known = target && target->HasSpell(id); bool learn = (spellInfo->Effects[0].Effect == SPELL_EFFECT_LEARN_SPELL); SpellInfo const* learnSpellInfo = sSpellMgr->GetSpellInfo(spellInfo->Effects[0].TriggerSpell); uint32 talentCost = GetTalentSpellCost(id); bool talent = (talentCost > 0); bool passive = spellInfo->IsPassive(); bool active = target && target->HasAura(id); // unit32 used to prevent interpreting uint8 as char at output // find rank of learned spell for learning spell, or talent rank uint32 rank = talentCost ? talentCost : learn && learnSpellInfo ? learnSpellInfo->GetRank() : spellInfo->GetRank(); // send spell in "id - [name, rank N] [talent] [passive] [learn] [known]" format std::ostringstream ss; if (handler->GetSession()) { ss << id << " - |cffffffff|Hspell:" << id << "|h[" << name; } else { ss << id << " - " << name; } // include rank in link name if (rank) { ss << handler->GetAcoreString(LANG_SPELL_RANK) << rank; } if (handler->GetSession()) { ss << ' ' << localeNames[locale] << "]|h|r"; } else { ss << ' ' << localeNames[locale]; } if (talent) { ss << handler->GetAcoreString(LANG_TALENT); } if (passive) { ss << handler->GetAcoreString(LANG_PASSIVE); } if (learn) { ss << handler->GetAcoreString(LANG_LEARN); } if (known) { ss << handler->GetAcoreString(LANG_KNOWN); } if (active) { ss << handler->GetAcoreString(LANG_ACTIVE); } handler->SendSysMessage(ss.str().c_str()); if (!found) { found = true; } } } } if (!found) { handler->SendSysMessage(LANG_COMMAND_NOSPELLFOUND); } return true; } static bool HandleLookupSpellIdCommand(ChatHandler* handler, SpellInfo const* spell) { // can be nullptr at console call Player* target = handler->getSelectedPlayer(); bool found = false; uint32 count = 0; uint32 maxResults = 1; if (!SpellMgr::IsSpellValid(spell)) { handler->SendErrorMessage(LANG_COMMAND_SPELL_BROKEN, spell->Id); return false; } int locale = handler->GetSessionDbcLocale(); std::string name = spell->SpellName[locale]; if (name.empty()) { handler->SendSysMessage(LANG_COMMAND_NOSPELLFOUND); return true; } if (locale < TOTAL_LOCALES) { if (maxResults && count++ == maxResults) { handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults); return true; } bool known = target && target->HasSpell(spell->Id); bool learn = (spell->Effects[0].Effect == SPELL_EFFECT_LEARN_SPELL); SpellInfo const* learnSpellInfo = sSpellMgr->GetSpellInfo(spell->Effects[0].TriggerSpell); uint32 talentCost = GetTalentSpellCost(spell->Id); bool talent = (talentCost > 0); bool passive = spell->IsPassive(); bool active = target && target->HasAura(spell->Id); // unit32 used to prevent interpreting uint8 as char at output // find rank of learned spell for learning spell, or talent rank uint32 rank = talentCost ? talentCost : learn && learnSpellInfo ? learnSpellInfo->GetRank() : spell->GetRank(); // send spell in "id - [name, rank N] [talent] [passive] [learn] [known]" format std::ostringstream ss; if (handler->GetSession()) { ss << spell->Id << " - |cffffffff|Hspell:" << spell->Id << "|h[" << name; } else { ss << spell->Id << " - " << name; } // include rank in link name if (rank) { ss << handler->GetAcoreString(LANG_SPELL_RANK) << rank; } if (handler->GetSession()) { ss << ' ' << localeNames[locale] << "]|h|r"; } else { ss << ' ' << localeNames[locale]; } if (talent) { ss << handler->GetAcoreString(LANG_TALENT); } if (passive) { ss << handler->GetAcoreString(LANG_PASSIVE); } if (learn) { ss << handler->GetAcoreString(LANG_LEARN); } if (known) { ss << handler->GetAcoreString(LANG_KNOWN); } if (active) { ss << handler->GetAcoreString(LANG_ACTIVE); } handler->SendSysMessage(ss.str().c_str()); if (!found) { found = true; } } if (!found) { handler->SendSysMessage(LANG_COMMAND_NOSPELLFOUND); } return true; } static bool HandleLookupTaxiNodeCommand(ChatHandler* handler, Tail namePart) { if (namePart.empty()) { return false; } std::wstring wNamePart; if (!Utf8toWStr(namePart, wNamePart)) { return false; } // converting string that we try to find to lower case wstrToLower(wNamePart); bool found = false; uint32 count = 0; uint32 maxResults = sWorld->getIntConfig(CONFIG_MAX_RESULTS_LOOKUP_COMMANDS); // Search in TaxiNodes.dbc for (auto nodeEntry : sTaxiNodesStore) { int locale = handler->GetSessionDbcLocale(); std::string name = nodeEntry->name[locale]; if (name.empty()) { continue; } if (!Utf8FitTo(name, wNamePart)) { locale = 0; for (; locale < TOTAL_LOCALES; ++locale) { if (locale == handler->GetSessionDbcLocale()) { continue; } name = nodeEntry->name[locale]; if (name.empty()) { continue; } if (Utf8FitTo(name, wNamePart)) { break; } } } if (locale < TOTAL_LOCALES) { if (maxResults && count++ == maxResults) { handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults); return true; } // send taxinode in "id - [name] (Map:m X:x Y:y Z:z)" format if (handler->GetSession()) { handler->PSendSysMessage(LANG_TAXINODE_ENTRY_LIST_CHAT, nodeEntry->ID, nodeEntry->ID, name, localeNames[locale], nodeEntry->map_id, nodeEntry->x, nodeEntry->y, nodeEntry->z); } else { handler->PSendSysMessage(LANG_TAXINODE_ENTRY_LIST_CONSOLE, nodeEntry->ID, name, localeNames[locale], nodeEntry->map_id, nodeEntry->x, nodeEntry->y, nodeEntry->z); } if (!found) { found = true; } } } if (!found) { handler->SendSysMessage(LANG_COMMAND_NOTAXINODEFOUND); } return true; } // Find teleport in game_tele order by name static bool HandleLookupTeleCommand(ChatHandler* handler, Tail namePart) { if (namePart.empty()) { return false; } std::wstring wNamePart; if (!Utf8toWStr(namePart, wNamePart)) { return false; } // converting string that we try to find to lower case wstrToLower(wNamePart); std::ostringstream reply; uint32 count = 0; uint32 maxResults = sWorld->getIntConfig(CONFIG_MAX_RESULTS_LOOKUP_COMMANDS); bool limitReached = false; for (auto const& [id, tele] : sObjectMgr->GetGameTeleMap()) { if (tele.wnameLow.find(wNamePart) == std::wstring::npos) { continue; } if (maxResults && count++ == maxResults) { limitReached = true; break; } if (handler->GetSession()) { reply << " |cffffffff|Htele:" << id << "|h[" << tele.name << "]|h|r\n"; } else { reply << " " << id << ' ' << tele.name << "\n"; } } if (reply.str().empty()) { handler->SendSysMessage(LANG_COMMAND_TELE_NOLOCATION); } else { handler->PSendSysMessage(LANG_COMMAND_TELE_LOCATION, reply.str()); } if (limitReached) { handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults); } return true; } static bool HandleLookupTitleCommand(ChatHandler* handler, Tail namePart) { if (namePart.empty()) { return false; } // can be nullptr in console call Player* target = handler->getSelectedPlayer(); // title name have single string arg for player name char const* targetName = target ? target->GetName().c_str() : "NAME"; std::wstring wNamePart; if (!Utf8toWStr(namePart, wNamePart)) { return false; } // converting string that we try to find to lower case wstrToLower(wNamePart); uint32 counter = 0; // Counter for figure out that we found smth. uint32 maxResults = sWorld->getIntConfig(CONFIG_MAX_RESULTS_LOOKUP_COMMANDS); // Search in CharTitles.dbc for (auto titleInfo : sCharTitlesStore) { int locale = handler->GetSessionDbcLocale(); std::string name = titleInfo->nameMale[locale]; if (name.empty()) { continue; } if (!Utf8FitTo(name, wNamePart)) { locale = 0; for (; locale < TOTAL_LOCALES; ++locale) { if (locale == handler->GetSessionDbcLocale()) { continue; } name = titleInfo->nameMale[locale]; if (name.empty()) { continue; } if (Utf8FitTo(name, wNamePart)) { break; } } } if (locale < TOTAL_LOCALES) { if (maxResults && counter == maxResults) { handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults); return true; } std::string knownStr = target && target->HasTitle(titleInfo) ? handler->GetAcoreString(LANG_KNOWN) : ""; std::string activeStr = target && target->GetUInt32Value(PLAYER_CHOSEN_TITLE) == titleInfo->bit_index ? handler->GetAcoreString(LANG_ACTIVE) : ""; std::string titleNameStr = Acore::StringFormat(name, targetName); // send title in "id (idx:idx) - [namedlink locale]" format if (handler->GetSession()) handler->PSendSysMessage(LANG_TITLE_LIST_CHAT, titleInfo->ID, titleInfo->bit_index, titleInfo->ID, titleNameStr, localeNames[locale], knownStr, activeStr); else handler->PSendSysMessage(LANG_TITLE_LIST_CONSOLE, titleInfo->ID, titleInfo->bit_index, titleNameStr, localeNames[locale], knownStr, activeStr); ++counter; } } if (!counter) // if counter == 0 then we found nth { handler->SendSysMessage(LANG_COMMAND_NOTITLEFOUND); } return true; } static bool HandleLookupMapCommand(ChatHandler* handler, Tail namePart) { if (namePart.empty()) { return false; } std::wstring wNamePart; if (!Utf8toWStr(namePart, wNamePart)) { return false; } wstrToLower(wNamePart); uint32 counter = 0; uint32 maxResults = sWorld->getIntConfig(CONFIG_MAX_RESULTS_LOOKUP_COMMANDS); uint8 locale = handler->GetSession() ? handler->GetSession()->GetSessionDbcLocale() : sWorld->GetDefaultDbcLocale(); // search in Map.dbc for (auto mapInfo : sMapStore) { std::string name = mapInfo->name[locale]; if (name.empty()) { continue; } if (Utf8FitTo(name, wNamePart) && locale < TOTAL_LOCALES) { if (maxResults && counter == maxResults) { handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults); return true; } std::ostringstream ss; ss << mapInfo->MapID << " - [" << name << ']'; if (mapInfo->IsContinent()) { ss << handler->GetAcoreString(LANG_CONTINENT); } switch (mapInfo->map_type) { case MAP_INSTANCE: ss << handler->GetAcoreString(LANG_INSTANCE); break; case MAP_RAID: ss << handler->GetAcoreString(LANG_RAID); break; case MAP_BATTLEGROUND: ss << handler->GetAcoreString(LANG_BATTLEGROUND); break; case MAP_ARENA: ss << handler->GetAcoreString(LANG_ARENA); break; } handler->SendSysMessage(ss.str().c_str()); ++counter; } } if (!counter) { handler->SendSysMessage(LANG_COMMAND_NOMAPFOUND); } return true; } static bool HandleLookupPlayerIpCommand(ChatHandler* handler, Optional ip, Optional limit) { Player* target = handler->getSelectedPlayerOrSelf(); if (!ip) { // nullptr only if used from console if (!target || target == handler->GetSession()->GetPlayer()) { return false; } *ip = target->GetSession()->GetRemoteAddress(); } else { ip = *ip; } LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_BY_IP); stmt->SetData(0, *ip); PreparedQueryResult result = LoginDatabase.Query(stmt); return LookupPlayerSearchCommand(result, *limit ? *limit : -1, handler); } static bool HandleLookupPlayerAccountCommand(ChatHandler* handler, std::string account, Optional limit) { if (!Utf8ToUpperOnlyLatin(account)) { return false; } LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_LIST_BY_NAME); stmt->SetData(0, account); PreparedQueryResult result = LoginDatabase.Query(stmt); return LookupPlayerSearchCommand(result, *limit ? *limit : -1, handler); } static bool HandleLookupPlayerEmailCommand(ChatHandler* handler, std::string email, Optional limit) { LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_LIST_BY_EMAIL); stmt->SetData(0, email); PreparedQueryResult result = LoginDatabase.Query(stmt); return LookupPlayerSearchCommand(result, *limit ? *limit : -1, handler); } static bool LookupPlayerSearchCommand(PreparedQueryResult result, int32 limit, ChatHandler* handler) { if (!result) { handler->SendErrorMessage(LANG_NO_PLAYERS_FOUND); return false; } int32 counter = 0; uint32 count = 0; uint32 maxResults = sWorld->getIntConfig(CONFIG_MAX_RESULTS_LOOKUP_COMMANDS); do { if (maxResults && count++ == maxResults) { handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults); return true; } Field* fields = result->Fetch(); uint32 accountId = fields[0].Get(); std::string accountName = fields[1].Get(); CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_GUID_NAME_BY_ACC); stmt->SetData(0, accountId); PreparedQueryResult result2 = CharacterDatabase.Query(stmt); if (result2) { handler->PSendSysMessage(LANG_LOOKUP_PLAYER_ACCOUNT, accountName, accountId); do { Field* characterFields = result2->Fetch(); ObjectGuid::LowType guid = characterFields[0].Get(); std::string name = characterFields[1].Get(); uint8 plevel = 0, prace = 0, pclass = 0; bool online = ObjectAccessor::FindPlayerByLowGUID(guid) != nullptr; if (CharacterCacheEntry const* gpd = sCharacterCache->GetCharacterCacheByName(name)) { plevel = gpd->Level; prace = gpd->Race; pclass = gpd->Class; } if (plevel > 0 && prace > 0 && prace <= RACE_DRAENEI && pclass > 0 && pclass <= CLASS_DRUID) { handler->PSendSysMessage(" {} (GUID {}) - {} - {} - {}{}", name, guid, EnumUtils::ToTitle(Races(prace)), EnumUtils::ToTitle(Classes(pclass)), plevel, (online ? " - [ONLINE]" : "")); } else { handler->PSendSysMessage(LANG_LOOKUP_PLAYER_CHARACTER, name, guid); } ++counter; } while (result2->NextRow() && (limit == -1 || counter < limit)); } } while (result->NextRow()); if (!counter) // empty accounts only { handler->SendErrorMessage(LANG_NO_PLAYERS_FOUND); return false; } return true; } }; void AddSC_lookup_commandscript() { new lookup_commandscript(); }