From 99d2e3a8b1520c679920ebaec20a14fe6a01be0d Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Sat, 6 Jan 2024 23:18:21 -0500 Subject: [PATCH] [Commands] Add #clearxtargets Command (#3833) # Perl - Add `$client->ClearXTargets()`. # Lua - Add `client:ClearXTargets()`. # Notes - Add `#clearxtargets` command for players. - Allows operators/players to clear their XTargets if something get stuck on it. --- common/ptimer.h | 5 +-- common/ruletypes.h | 1 + zone/client.cpp | 23 ++++++++++++++ zone/client.h | 1 + zone/command.cpp | 2 ++ zone/command.h | 1 + zone/gm_commands/clearxtargets.cpp | 50 ++++++++++++++++++++++++++++++ zone/lua_client.cpp | 7 +++++ zone/lua_client.h | 1 + zone/perl_client.cpp | 6 ++++ 10 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 zone/gm_commands/clearxtargets.cpp diff --git a/common/ptimer.h b/common/ptimer.h index 349f20534..ad5e5a8c8 100644 --- a/common/ptimer.h +++ b/common/ptimer.h @@ -44,9 +44,10 @@ enum : int { //values for pTimerType pTimerBeggingPickPocket = 27, pTimerLinkedSpellReuseStart = 28, pTimerLinkedSpellReuseEnd = 48, + pTimerClearXTarget = 50, + + pTimerShieldAbility = 86, - pTimerShieldAbility = 86, - pTimerLayHands = 87, //these IDs are used by client too pTimerHarmTouch = 89, //so dont change them diff --git a/common/ruletypes.h b/common/ruletypes.h index 98d993827..a66f0518e 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -216,6 +216,7 @@ RULE_BOOL(Character, EnableRaidMemberEXPModifier, true, "Enable or disable the r RULE_BOOL(Character, LeaveCursorMoneyOnCorpse, false, "Enable or disable leaving cursor money on player corpses") RULE_BOOL(Character, ItemExtraSkillDamageCalcAsPercent, false, "If enabled, apply Item Extra Skill Damage as Percentage-based modifiers") RULE_BOOL(Character, UseForageCommonFood, true, "If enabled, use the common foods specified in the code.") +RULE_INT(Character, ClearXTargetDelay, 10, "Seconds between uses of the #clearxtargets command (Set to 0 to disable)") RULE_CATEGORY_END() RULE_CATEGORY(Mercs) diff --git a/zone/client.cpp b/zone/client.cpp index 6ee451cff..0b50d5592 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -11981,3 +11981,26 @@ std::string GetZoneModeString(ZoneMode mode) return "Unknown"; } } + +void Client::ClearXTargets() +{ + if (!XTargettingAvailable()) { + return; + } + + for (int i = 0; i < GetMaxXTargets(); ++i) { + if (XTargets[i].ID) { + Mob* m = entity_list.GetMob(XTargets[i].ID); + + if (m) { + RemoveXTarget(m, false); + } + + XTargets[i].ID = 0; + XTargets[i].Name[0] = 0; + XTargets[i].dirty = false; + + SendXTargetPacket(i, nullptr); + } + } +} diff --git a/zone/client.h b/zone/client.h index 70fedd9b2..3af24cc33 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1528,6 +1528,7 @@ public: void JoinGroupXTargets(Group *g); void LeaveGroupXTargets(Group *g); void LeaveRaidXTargets(Raid *r); + void ClearXTargets(); bool GroupFollow(Client* inviter); inline bool GetRunMode() const { return runmode; } diff --git a/zone/command.cpp b/zone/command.cpp index bec051a3f..a989ee56f 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -100,6 +100,7 @@ int command_init(void) command_add("camerashake", "[Duration (Milliseconds)] [Intensity (1-10)] - Shakes the camera on everyone's screen globally.", AccountStatus::QuestTroupe, command_camerashake) || command_add("castspell", "[Spell ID] [Instant (0 = False, 1 = True, Default is 1 if Unused)] - Cast a spell", AccountStatus::Guide, command_castspell) || command_add("chat", "[Channel ID] [Message] - Send a channel message to all zones", AccountStatus::GMMgmt, command_chat) || + command_add("clearxtargets", "Clears XTargets", AccountStatus::Player, command_clearxtargets) || command_add("copycharacter", "[source_char_name] [dest_char_name] [dest_account_name] - Copies character to destination account", AccountStatus::GMImpossible, command_copycharacter) || command_add("corpse", "Manipulate corpses, use with no arguments for help", AccountStatus::Guide, command_corpse) || command_add("corpsefix", "Attempts to bring corpses from underneath the ground within close proximity of the player", AccountStatus::Player, command_corpsefix) || @@ -792,6 +793,7 @@ void command_bot(Client *c, const Seperator *sep) #include "gm_commands/camerashake.cpp" #include "gm_commands/castspell.cpp" #include "gm_commands/chat.cpp" +#include "gm_commands/clearxtargets.cpp" #include "gm_commands/copycharacter.cpp" #include "gm_commands/corpse.cpp" #include "gm_commands/corpsefix.cpp" diff --git a/zone/command.h b/zone/command.h index 4062749cd..f57513d7b 100644 --- a/zone/command.h +++ b/zone/command.h @@ -52,6 +52,7 @@ void command_bugs(Client *c, const Seperator *sep); void command_camerashake(Client *c, const Seperator *sep); void command_castspell(Client *c, const Seperator *sep); void command_chat(Client *c, const Seperator *sep); +void command_clearxtargets(Client *c, const Seperator *sep); void command_copycharacter(Client *c, const Seperator *sep); void command_corpse(Client *c, const Seperator *sep); void command_corpsefix(Client *c, const Seperator *sep); diff --git a/zone/gm_commands/clearxtargets.cpp b/zone/gm_commands/clearxtargets.cpp new file mode 100644 index 000000000..58700675b --- /dev/null +++ b/zone/gm_commands/clearxtargets.cpp @@ -0,0 +1,50 @@ +#include "../client.h" + +void command_clearxtargets(Client *c, const Seperator *sep) +{ + const int reuse_timer = RuleI(Character, ClearXTargetDelay); + + const int arguments = sep->argnum; + if (arguments) { + const bool is_help = !strcasecmp(sep->arg[1], "help"); + + if (is_help) { + c->Message(Chat::White, "Usage: #clearxtargets"); + c->Message( + Chat::White, + "Note: Use this if your Extended Target window is bugged or has lingering targets that are invalid." + ); + if (reuse_timer) { + c->Message( + Chat::White, + fmt::format( + "Note: This can only be used every {}.", + Strings::SecondsToTime(reuse_timer) + ).c_str() + ); + } + return; + } + } + + if (reuse_timer) { + const uint32 time_left = c->GetPTimers().GetRemainingTime(pTimerClearXTarget); + if (!c->GetPTimers().Expired(&database, pTimerClearXTarget, false)) { + c->Message( + Chat::White, + fmt::format( + "You must wait {} before using this command again.", + Strings::SecondsToTime(time_left) + ).c_str() + ); + return; + } + } + + c->ClearXTargets(); + c->Message(Chat::White, "Extended Target window has been cleared."); + + if (reuse_timer) { + c->GetPTimers().Start(pTimerClearXTarget, reuse_timer); + } +} diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 919cd504a..d73ec3cc1 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -3252,6 +3252,12 @@ bool Lua_Client::HasItemOnCorpse(uint32 item_id) return self->HasItemOnCorpse(item_id); } +void Lua_Client::ClearXTargets() +{ + Lua_Safe_Call_Void(); + self->ClearXTargets(); +} + luabind::scope lua_register_client() { return luabind::class_("Client") .def(luabind::constructor<>()) @@ -3323,6 +3329,7 @@ luabind::scope lua_register_client() { .def("ClearCompassMark",(void(Lua_Client::*)(void))&Lua_Client::ClearCompassMark) .def("ClearAccountFlag", (void(Lua_Client::*)(const std::string&))&Lua_Client::ClearAccountFlag) .def("ClearPEQZoneFlag", (void(Lua_Client::*)(uint32))&Lua_Client::ClearPEQZoneFlag) + .def("ClearXTargets", (void(Lua_Client::*)(void))&Lua_Client::ClearXTargets) .def("ClearZoneFlag", (void(Lua_Client::*)(uint32))&Lua_Client::ClearZoneFlag) .def("Connected", (bool(Lua_Client::*)(void))&Lua_Client::Connected) .def("CountAugmentEquippedByID", (int(Lua_Client::*)(uint32))&Lua_Client::CountAugmentEquippedByID) diff --git a/zone/lua_client.h b/zone/lua_client.h index 627b16537..f7ba792db 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -488,6 +488,7 @@ public: void RemoveRadiantCrystals(uint32 amount); void SummonItemIntoInventory(luabind::object item_table); bool HasItemOnCorpse(uint32 item_id); + void ClearXTargets(); void ApplySpell(int spell_id); void ApplySpell(int spell_id, int duration); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 1e3c70689..8259424fc 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -3063,6 +3063,11 @@ bool Perl_Client_HasItemOnCorpse(Client* self, uint32 item_id) return self->HasItemOnCorpse(item_id); } +void Perl_Client_ClearXTargets(Client* self) +{ + self->ClearXTargets(); +} + void perl_register_client() { perl::interpreter perl(PERL_GET_THX); @@ -3137,6 +3142,7 @@ void perl_register_client() package.add("ClearCompassMark", &Perl_Client_ClearCompassMark); package.add("ClearAccountFlag", &Perl_Client_ClearAccountFlag); package.add("ClearPEQZoneFlag", &Perl_Client_ClearPEQZoneFlag); + package.add("ClearXTargets", &Perl_Client_ClearXTargets); package.add("ClearZoneFlag", &Perl_Client_ClearZoneFlag); package.add("Connected", &Perl_Client_Connected); package.add("CountAugmentEquippedByID", &Perl_Client_CountAugmentEquippedByID);