From a2b381bc9edf5886f536ba5e055544248bcc71ab Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 29 Mar 2020 16:34:07 -0400 Subject: [PATCH] Added command 'editmassrespawn' for mass editing of respawn times --- zone/command.cpp | 143 ++++++++++++++++++++++++++++++++++++++++++++++- zone/command.h | 1 + 2 files changed, 142 insertions(+), 2 deletions(-) diff --git a/zone/command.cpp b/zone/command.cpp index 757e2d522..23b269395 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -196,6 +196,7 @@ int command_init(void) command_add("disarmtrap", "Analog for ldon disarm trap for the newer clients since we still don't have it working.", 80, command_disarmtrap) || command_add("distance", "- Reports the distance between you and your target.", 80, command_distance) || command_add("doanim", "[animnum] [type] - Send an EmoteAnim for you or your target", 50, command_doanim) || + command_add("editmassrespawn", "[name-search] [second-value] - Mass (Zone wide) NPC respawn timer editing command", 100, command_editmassrespawn) || command_add("emote", "['name'/'world'/'zone'] [type] [message] - Send an emote message", 80, command_emote) || command_add("emotesearch", "Searches NPC Emotes", 80, command_emotesearch) || command_add("emoteview", "Lists all NPC Emotes", 80, command_emoteview) || @@ -6525,6 +6526,144 @@ void command_doanim(Client *c, const Seperator *sep) c->DoAnim(atoi(sep->arg[1]),atoi(sep->arg[2])); } +void command_editmassrespawn(Client* c, const Seperator* sep) +{ + if (strcasecmp(sep->arg[1], "usage") == 0) { + c->Message(Chat::White, "#editmassrespawn [exact_match: =]npc_type_name new_respawn_seconds (apply)"); + return; + } + + std::string search_npc_type; + if (sep->arg[1]) { + search_npc_type = sep->arg[1]; + } + + int change_respawn_seconds = 0; + if (sep->arg[2] && sep->IsNumber(2)) { + change_respawn_seconds = atoi(sep->arg[2]); + } + + bool change_apply = false; + if (sep->arg[3] && strcasecmp(sep->arg[3], "apply") == 0) { + change_apply = true; + } + + std::string search_encapsulator = "%"; + if (search_npc_type[0] == '=') { + + search_npc_type = search_npc_type.substr(1); + search_encapsulator = ""; + } + + std::string query = fmt::format( + SQL( + SELECT tc.id, ta.spawngroupID, ta.id, tc.name, ta.respawntime + FROM spawn2 ta + INNER JOIN spawnentry tb ON ta.spawngroupID = tb.spawngroupID + INNER JOIN npc_types tc ON tb.npcID = tc.id + WHERE ta.zone LIKE '{}' + AND ta.version = '{}' + AND tc.name LIKE '{}{}{}' + ORDER BY tc.id, ta.spawngroupID, ta.id + ), + zone->GetShortName(), + zone->GetInstanceVersion(), + search_encapsulator, + search_npc_type, + search_encapsulator + ); + + std::string status = "(Searching)"; + if (change_apply) { + status = "(Applying)"; + } + + int results_count = 0; + + auto results = database.QueryDatabase(query); + if (results.Success() && results.RowCount()) { + + results_count = results.RowCount(); + + for (auto row : results) { + c->Message( + Chat::Yellow, + fmt::format( + "NPC (npcid:{}) (sgid:{}) (s2id:{}) [{}] Respawn: Current [{}] New [{}] {}", + row[0], + row[1], + row[2], + row[3], + row[4], + change_respawn_seconds, + status + ).c_str() + ); + } + + c->Message(Chat::Yellow, "Found (%i) NPC's that match this search...", results_count); + + if (change_respawn_seconds > 0) { + + if (change_apply) { + + results = database.QueryDatabase( + fmt::format( + SQL( + UPDATE spawn2 + SET respawntime = '{}' + WHERE id IN ( + SELECT ta.id + FROM spawn2 ta + INNER JOIN spawnentry tb ON ta.spawngroupID = tb.spawngroupID + INNER JOIN npc_types tc ON tb.npcID = tc.id + WHERE ta.zone LIKE '{}' + AND ta.version = '{}' + AND tc.name LIKE '{}{}{}' + ) + ), + change_respawn_seconds, + zone->GetShortName(), + zone->GetInstanceVersion(), + search_encapsulator, + search_npc_type, + search_encapsulator + ) + ); + + if (results.Success()) { + + c->Message(Chat::Yellow, "Changes applied to (%i) NPC 'Spawn2' entries", results_count); + zone->Repop(); + } + else { + + c->Message(Chat::Yellow, "Found (0) NPC's that match this search..."); + } + } + else { + + std::string saylink = fmt::format( + "#editmassrespawn {}{} {} apply", + (search_encapsulator.empty() ? "=" : ""), + search_npc_type, + change_respawn_seconds + ); + + c->Message( + Chat::Yellow, "To apply these changes, click <%s> or type [%s]", + EQEmu::SayLinkEngine::GenerateQuestSaylink(saylink, false, "Apply").c_str(), + saylink.c_str() + ); + } + } + } + else { + + c->Message(Chat::Yellow, "Found (0) NPC's that match this search..."); + } +} + void command_randomfeatures(Client *c, const Seperator *sep) { Mob *target=c->GetTarget(); @@ -7782,7 +7921,7 @@ void command_npcemote(Client *c, const Seperator *sep) void command_npceditmass(Client *c, const Seperator *sep) { if (strcasecmp(sep->arg[1], "usage") == 0) { - c->Message(Chat::White, "#npceditmass search_column [exact_match: =]search_value change_column change_value"); + c->Message(Chat::White, "#npceditmass search_column [exact_match: =]search_value change_column change_value (apply)"); return; } @@ -7930,7 +8069,7 @@ void command_npceditmass(Client *c, const Seperator *sep) std::string saylink = fmt::format( "#npceditmass {} {}{} {} {} apply", search_column, - (exact_match ? '=' : '\0'), + (exact_match ? "=" : ""), search_value, change_column, change_value diff --git a/zone/command.h b/zone/command.h index d64950f9c..7c1af0edf 100644 --- a/zone/command.h +++ b/zone/command.h @@ -91,6 +91,7 @@ void command_disablerecipe(Client *c, const Seperator *sep); void command_disarmtrap(Client *c, const Seperator *sep); void command_distance(Client *c, const Seperator *sep); void command_doanim(Client *c, const Seperator *sep); +void command_editmassrespawn(Client* c, const Seperator* sep); void command_emote(Client *c, const Seperator *sep); void command_emotesearch(Client* c, const Seperator *sep); void command_emoteview(Client* c, const Seperator *sep);