diff --git a/zone/command.cpp b/zone/command.cpp index 569d846bc..ada2bdf6f 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -246,6 +246,7 @@ int command_init(void) command_add("zoneinstance", "[Instance ID] [X] [Y] [Z] - Teleport to specified Instance by ID (coordinates are optional)", AccountStatus::Guide, command_zone_instance) || command_add("zoneshard", "[zone] [instance_id] - Teleport explicitly to a zone shard", AccountStatus::Player, command_zone_shard) || command_add("zoneshutdown", "[instance|zone] [Instance ID|Zone ID|Zone Short Name] - Shut down a zone server by Instance ID, Zone ID, or Zone Short Name", AccountStatus::GMLeadAdmin, command_zoneshutdown) || + command_add("zonevariable", "[clear|delete|set|view] - Modify zone variables for your current zone", AccountStatus::GMAdmin, command_zonevariable) || command_add("zsave", " Saves zheader to the database", AccountStatus::QuestTroupe, command_zsave) ) { command_deinit(); @@ -928,6 +929,7 @@ void command_bot(Client *c, const Seperator *sep) #include "gm_commands/zone.cpp" #include "gm_commands/zonebootup.cpp" #include "gm_commands/zoneshutdown.cpp" +#include "gm_commands/zonevariable.cpp" #include "gm_commands/zone_instance.cpp" #include "gm_commands/zone_shard.cpp" #include "gm_commands/zsave.cpp" diff --git a/zone/command.h b/zone/command.h index 1745bbadf..0159d4d65 100644 --- a/zone/command.h +++ b/zone/command.h @@ -198,6 +198,7 @@ void command_zone_instance(Client *c, const Seperator *sep); void command_zone_shard(Client *c, const Seperator *sep); void command_zonebootup(Client *c, const Seperator *sep); void command_zoneshutdown(Client *c, const Seperator *sep); +void command_zonevariable(Client *c, const Seperator *sep); void command_zsave(Client *c, const Seperator *sep); #include "bot.h" diff --git a/zone/gm_commands/zonevariable.cpp b/zone/gm_commands/zonevariable.cpp new file mode 100644 index 000000000..713830e42 --- /dev/null +++ b/zone/gm_commands/zonevariable.cpp @@ -0,0 +1,164 @@ +#include "../client.h" + +void command_zonevariable(Client *c, const Seperator *sep) +{ + const auto arguments = sep->argnum; + + if (!arguments) { + c->Message(Chat::White, "Usage: #zonevariable clear - Clear all zone variables"); + c->Message(Chat::White, "Usage: #zonevariable delete [Variable Name] - Delete a zone variable"); + c->Message(Chat::White, "Usage: #zonevariable set [Variable Name] [Variable Value] - Set a zone variable"); + c->Message(Chat::White, "Usage: #zonevariable view [Variable Name] - View a zone variable"); + c->Message(Chat::White, "Note: You can have spaces in variable names and values by wrapping in double quotes like this"); + c->Message(Chat::White, "Example: #zonevariable set \"Test Variable\" \"Test Value\""); + c->Message(Chat::White, "Note: Variable Value is optional and can be set to empty by not providing a value"); + return; + } + + const bool is_clear = !strcasecmp(sep->arg[1], "clear"); + const bool is_delete = !strcasecmp(sep->arg[1], "delete"); + const bool is_set = !strcasecmp(sep->arg[1], "set"); + const bool is_view = !strcasecmp(sep->arg[1], "view"); + + if ( + !is_clear && + !is_delete && + !is_set && + !is_view + ) { + c->Message(Chat::White, "Usage: #zonevariable clear - Clear all zone variables"); + c->Message(Chat::White, "Usage: #zonevariable delete [Variable Name] - Delete a zone variable"); + c->Message(Chat::White, "Usage: #zonevariable set [Variable Name] [Variable Value] - Set a zone variable"); + c->Message(Chat::White, "Usage: #zonevariable view [Variable Name] - View a zone variable"); + c->Message(Chat::White, "Note: You can have spaces in variable names and values by wrapping in double quotes like this"); + c->Message(Chat::White, "Example: #zonevariable set \"Test Variable\" \"Test Value\""); + c->Message(Chat::White, "Note: Variable Value is optional and can be set to empty by not providing a value"); + return; + } + + if (is_clear) { + const bool cleared = zone->ClearVariables(); + + if (!cleared) { + c->Message(Chat::White, "There are no zone variables to clear."); + return; + } + + c->Message(Chat::White, "Cleared all zone variables."); + } else if (is_delete) { + const std::string variable_name = sep->argplus[2]; + + if (!zone->VariableExists(variable_name)) { + c->Message( + Chat::White, + fmt::format( + "A zone variable named '{}' does not exist.", + variable_name + ).c_str() + ); + + return; + } + + zone->DeleteVariable(variable_name); + + c->Message( + Chat::White, + fmt::format( + "Deleted a zone variable named '{}'.", + variable_name + ).c_str() + ); + + return; + } else if (is_set) { + const std::string variable_name = sep->arg[2]; + const std::string variable_value = sep->arg[3]; + + zone->SetVariable(variable_name, variable_value); + + c->Message( + Chat::White, + fmt::format( + "Set a zone variable named '{}' to a value of '{}'.", + variable_name, + variable_value + ).c_str() + ); + } else if (is_view) { + const auto &l = zone->GetVariables(); + + uint32 variable_count = 0; + uint32 variable_number = 1; + + const std::string search_criteria = arguments >= 2 ? sep->argplus[2] : ""; + + for (const auto &e: l) { + if ( + search_criteria.empty() || + Strings::Contains(Strings::ToLower(e), Strings::ToLower(search_criteria)) + ) { + c->Message( + Chat::White, + fmt::format( + "Variable {} | Name: {} Value: {} | {}", + variable_number, + e, + zone->GetVariable(e), + Saylink::Silent( + fmt::format( + "#zonevariable delete {}", + e + ), + "Delete" + ) + ).c_str() + ); + + variable_count++; + variable_number++; + } + } + + if (!variable_count) { + c->Message( + Chat::White, + fmt::format( + "There are no zone variables{}.", + ( + !search_criteria.empty() ? + fmt::format( + " matching '{}'", + search_criteria + ) : + "" + ) + ).c_str() + ); + + return; + } + + c->Message( + Chat::White, + fmt::format( + "There {} {} zone variable{}{}, would you like to {} zone variables?", + variable_count != 1 ? "are" : "is", + variable_count, + variable_count != 1 ? "s" : "", + ( + !search_criteria.empty() ? + fmt::format( + " matching '{}'", + search_criteria + ) : + "" + ), + Saylink::Silent( + "#zonevariable clear", + "clear" + ) + ).c_str() + ); + } +} diff --git a/zone/lua_zone.cpp b/zone/lua_zone.cpp index 904e46a15..79f4f0982 100644 --- a/zone/lua_zone.cpp +++ b/zone/lua_zone.cpp @@ -727,10 +727,10 @@ std::string Lua_Zone::GetBucketRemaining(const std::string& bucket_name) return self->GetBucketRemaining(bucket_name); } -void Lua_Zone::ClearVariables() +bool Lua_Zone::ClearVariables() { - Lua_Safe_Call_Void(); - self->ClearVariables(); + Lua_Safe_Call_Bool(); + return self->ClearVariables(); } bool Lua_Zone::DeleteVariable(const std::string& variable_name) diff --git a/zone/lua_zone.h b/zone/lua_zone.h index fa10fb649..48d297bb6 100644 --- a/zone/lua_zone.h +++ b/zone/lua_zone.h @@ -141,7 +141,7 @@ public: void SetInstanceTimeRemaining(uint32 time_remaining); void SetIsHotzone(bool is_hotzone); void ShowZoneGlobalLoot(Lua_Client c); - void ClearVariables(); + bool ClearVariables(); bool DeleteVariable(const std::string& variable_name); std::string GetVariable(const std::string& variable_name); luabind::object GetVariables(lua_State* L); diff --git a/zone/perl_zone.cpp b/zone/perl_zone.cpp index 497f9dff2..0d9cd8ddb 100644 --- a/zone/perl_zone.cpp +++ b/zone/perl_zone.cpp @@ -561,9 +561,9 @@ std::string Perl_Zone_GetBucketRemaining(Zone* self, const std::string bucket_na return self->GetBucketRemaining(bucket_name); } -void Perl_Zone_ClearVariables(Zone* self) +bool Perl_Zone_ClearVariables(Zone* self) { - self->ClearVariables(); + return self->ClearVariables(); } bool Perl_Zone_DeleteVariable(Zone* self, const std::string variable_name) diff --git a/zone/zone.cpp b/zone/zone.cpp index 97d6973cd..6f00f805e 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -3225,9 +3225,14 @@ void Zone::DisableRespawnTimers() } } -void Zone::ClearVariables() +bool Zone::ClearVariables() { + if (m_zone_variables.empty()) { + return false; + } + m_zone_variables.clear(); + return true; } bool Zone::DeleteVariable(const std::string& variable_name) diff --git a/zone/zone.h b/zone/zone.h index 3a130818a..b8ba80dcb 100755 --- a/zone/zone.h +++ b/zone/zone.h @@ -197,7 +197,7 @@ public: int32 MobsAggroCount() { return aggroedmobs; } DynamicZone *GetDynamicZone(); - void ClearVariables(); + bool ClearVariables(); bool DeleteVariable(const std::string& variable_name); std::string GetVariable(const std::string& variable_name); std::vector GetVariables();