diff --git a/zone/client.cpp b/zone/client.cpp index 198fa18a5..4f9a362bf 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -66,6 +66,7 @@ extern volatile bool RunLoops; #include "../common/repositories/discovered_items_repository.h" #include "../common/events/player_events.h" #include "../common/events/player_event_logs.h" +#include "dialogue_window.h" extern QueryServ* QServ; @@ -12243,3 +12244,101 @@ void Client::PlayerTradeEventLog(Trade *t, Trade *t2) RecordPlayerEventLogWithClient(trader, PlayerEvent::TRADE, e); RecordPlayerEventLogWithClient(trader2, PlayerEvent::TRADE, e); } + +void Client::ShowSpells(Client* c, ShowSpellType show_spell_type) +{ + std::string spell_string; + + switch (show_spell_type) { + case ShowSpellType::Disciplines: + spell_string = "Discipline"; + break; + case ShowSpellType::Spells: + spell_string = "Spell"; + break; + default: + return; + } + + std::string spell_table; + + // Headers + spell_table += DialogueWindow::TableRow( + fmt::format( + "{}{}{}", + DialogueWindow::TableCell("Slot"), + DialogueWindow::TableCell(spell_string), + DialogueWindow::TableCell("Spell ID") + ) + ); + + std::map m; + auto spell_count = 0; + + if (show_spell_type == ShowSpellType::Disciplines) { + for (auto index = 0; index < MAX_PP_DISCIPLINES; index++) { + if (IsValidSpell(m_pp.disciplines.values[index])) { + m[index] = static_cast(m_pp.disciplines.values[index]); + } + } + } else if (show_spell_type == ShowSpellType::Spells) { + for (auto index = 0; index < EQ::spells::SPELL_GEM_COUNT; index++) { + if (IsValidSpell(m_pp.mem_spells[index])) { + m[index] = static_cast(m_pp.mem_spells[index]); + } + } + } + + for (const auto& s : m) { + spell_table += DialogueWindow::TableRow( + fmt::format( + "{}{}{}", + DialogueWindow::TableCell(std::to_string(s.first)), + DialogueWindow::TableCell(GetSpellName(s.second)), + DialogueWindow::TableCell(Strings::Commify(s.second)) + ) + ); + + spell_count++; + } + + if (!spell_count) { + c->Message( + Chat::White, + fmt::format( + "{} {} not have any {}s {}.", + c->GetTargetDescription(this, TargetDescriptionType::UCYou), + c == this ? "do" : "does", + Strings::ToLower(spell_string), + show_spell_type == ShowSpellType::Disciplines ? "learned" : "memorized" + ).c_str() + ); + return; + } + + if (spell_table.size() >= 4096) { + for (const auto& [index, spell_id] : m) { + c->Message( + Chat::White, + fmt::format( + "{}. {} ({})", + index, + GetSpellName(spell_id), + Strings::Commify(spell_id) + ).c_str() + ); + } + return; + } + + spell_table = DialogueWindow::Table(spell_table); + + c->SendPopupToClient( + fmt::format( + "{}s for {}", + spell_string, + c->GetTargetDescription(this, TargetDescriptionType::UCSelf) + ).c_str(), + spell_table.c_str() + ); +} diff --git a/zone/client.h b/zone/client.h index 60ce67718..eb144e2c9 100644 --- a/zone/client.h +++ b/zone/client.h @@ -131,6 +131,12 @@ enum { HideCorpseNPC = 5 }; +typedef enum +{ + Disciplines, + Spells +} ShowSpellType; + typedef enum { Empty = 0, @@ -669,6 +675,8 @@ public: inline const int32 GetInstanceID() const { return zone->GetInstanceID(); } void SetZoning(bool in) { bZoning = in; } + void ShowSpells(Client* c, ShowSpellType show_spell_type); + FACTION_VALUE GetReverseFactionCon(Mob* iOther); FACTION_VALUE GetFactionLevel(uint32 char_id, uint32 npc_id, uint32 p_race, uint32 p_class, uint32 p_deity, int32 pFaction, Mob* tnpc); bool ReloadCharacterFaction(Client *c, uint32 facid, uint32 charid); diff --git a/zone/command.cpp b/zone/command.cpp index d39da78ab..fdb72abb9 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -297,6 +297,7 @@ int command_init(void) command_add("shownumhits", "Shows buffs numhits for yourself.", AccountStatus::Player, command_shownumhits) || command_add("shownpcgloballoot", "Show global loot entries for your target NPC", AccountStatus::Guide, command_shownpcgloballoot) || command_add("showskills", "[Start Skill ID] [All] - Show the values of your or your player target's skills in a popup 50 at a time, use 'all' as second argument to show non-usable skill's values", AccountStatus::Guide, command_showskills) || + command_add("showspells", "[disciplines|spells] - Show your or your target's memorized spells or learned disciplines", AccountStatus::GMAdmin, command_showspells) || command_add("showspellslist", "Shows spell list of targeted NPC", AccountStatus::GMAdmin, command_showspellslist) || command_add("showstats", "Show details about you or your target", AccountStatus::Guide, command_showstats) || command_add("showzonegloballoot", "Show global loot entries for your current zone", AccountStatus::Guide, command_showzonegloballoot) || @@ -1134,6 +1135,7 @@ void command_bot(Client *c, const Seperator *sep) #include "gm_commands/shownpcgloballoot.cpp" #include "gm_commands/shownumhits.cpp" #include "gm_commands/showskills.cpp" +#include "gm_commands/showspells.cpp" #include "gm_commands/showspellslist.cpp" #include "gm_commands/showstats.cpp" #include "gm_commands/showzonegloballoot.cpp" diff --git a/zone/command.h b/zone/command.h index ca5003181..c967229a0 100644 --- a/zone/command.h +++ b/zone/command.h @@ -244,6 +244,7 @@ void command_showbuffs(Client *c, const Seperator *sep); void command_shownumhits(Client *c, const Seperator *sep); void command_shownpcgloballoot(Client *c, const Seperator *sep); void command_showskills(Client *c, const Seperator *sep); +void command_showspells(Client *c, const Seperator *sep); void command_showspellslist(Client *c, const Seperator *sep); void command_showstats(Client *c, const Seperator *sep); void command_showzonegloballoot(Client *c, const Seperator *sep); diff --git a/zone/gm_commands/showspells.cpp b/zone/gm_commands/showspells.cpp new file mode 100755 index 000000000..3cfbe8cd7 --- /dev/null +++ b/zone/gm_commands/showspells.cpp @@ -0,0 +1,37 @@ +#include "../client.h" + +void command_showspells(Client *c, const Seperator *sep) +{ + const auto arguments = sep->argnum; + if (!arguments) { + c->Message(Chat::White, "Usages: #showspells disciplines - Show your or your target's learned disciplines"); + c->Message(Chat::White, "Usages: #showspells spells - Show your or your target's memorized spells"); + return; + } + + auto t = c; + if (c->GetTarget() && c->GetTarget()->IsClient()) { + t = c->GetTarget()->CastToClient(); + } + + const auto is_disciplines = !strcasecmp(sep->arg[1], "disciplines"); + const auto is_spells = !strcasecmp(sep->arg[1], "spells"); + if ( + !is_disciplines && + !is_spells + ) { + c->Message(Chat::White, "Usages: #showspells disciplines - Show your or your target's learned disciplines"); + c->Message(Chat::White, "Usages: #showspells spells - Show your or your target's memorized spells"); + } + + ShowSpellType show_spell_type; + + if (is_disciplines) { + show_spell_type = ShowSpellType::Disciplines; + } else if (is_spells) { + show_spell_type = ShowSpellType::Spells; + } + + t->ShowSpells(c, show_spell_type); +} +