diff --git a/common/ruletypes.h b/common/ruletypes.h index 9457313ec..b0c8074b1 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -781,6 +781,10 @@ RULE_BOOL(Cheat, EnableMQFastMemDetector, true, "Enable the MQFastMem Detector. RULE_BOOL(Cheat, MarkMQWarpLT, false, "Mark clients makeing smaller warps") RULE_CATEGORY_END() +RULE_CATEGORY(Command) +RULE_BOOL(Command, DyeCommandRequiresDyes, false, "Enable this to require a Prismatic Dye (32557) each time someone uses #dye.") +RULE_CATEGORY_END() + #undef RULE_CATEGORY #undef RULE_INT #undef RULE_REAL diff --git a/zone/command.cpp b/zone/command.cpp index 4db232d80..7fc61208b 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -205,6 +205,7 @@ int command_init(void) command_add("distance", "- Reports the distance between you and your target.", 80, command_distance) || command_add("door", "Door editing command", 80, command_door) || command_add("doanim", "[animnum] [type] - Send an EmoteAnim for you or your target", 50, command_doanim) || + command_add("dye", "[slot|'help'] [red] [green] [blue] [use_tint] - Dyes the specified armor slot to Red, Green, and Blue provided, allows you to bypass darkness limits.", 20, command_dye) || command_add("dz", "Manage expeditions and dynamic zone instances", 80, command_dz) || command_add("dzkickplayers", "Removes all players from current expedition. (/kickplayers alternative for pre-RoF clients)", 0, command_dzkickplayers) || command_add("editmassrespawn", "[name-search] [second-value] - Mass (Zone wide) NPC respawn timer editing command", 100, command_editmassrespawn) || @@ -14677,6 +14678,91 @@ void command_viewzoneloot(Client *c, const Seperator *sep) ); } } + +void command_dye(Client *c, const Seperator *sep) +{ + int arguments = sep->argnum; + + if (arguments == 0) { + c->Message(Chat::White, "Command Syntax: #dye help | #dye [slot] [red] [green] [blue] [use_tint]"); + return; + } + + uint8 slot = 0; + uint8 red = 255; + uint8 green = 255; + uint8 blue = 255; + uint8 use_tint = 255; + + std::vector dye_slots = { + "Helmet", + "Chest", + "Arms", + "Wrist", + "Hands", + "Legs", + "Feet" + }; + + if (arguments == 1 && !strcasecmp(sep->arg[1], "help")) { + int slot_id = 0; + std::vector slot_messages; + c->Message(Chat::White, "Command Syntax: #dye help | #dye [slot] [red] [green] [blue] [use_tint]"); + c->Message(Chat::White, "Red, Green, and Blue go from 0 to 255."); + + for (const auto& slot : dye_slots) { + slot_messages.push_back(fmt::format("({}) {}", slot_id, slot)); + slot_id++; + } + + c->Message( + Chat::White, + fmt::format( + "{} {}", + "Slots are as follows:", + implode(", ", slot_messages) + ).c_str() + ); + return; + } + + if (arguments >= 1 && sep->IsNumber(1)) { + slot = atoi(sep->arg[1]); + } + + if (arguments >= 2 && sep->IsNumber(2)) { + red = atoi(sep->arg[2]); + } + + if (arguments >= 3 && sep->IsNumber(3)) { + green = atoi(sep->arg[3]); + } + + if (arguments >= 4 && sep->IsNumber(4)) { + blue = atoi(sep->arg[4]); + } + + if (arguments >= 5 && sep->IsNumber(5)) { + use_tint = atoi(sep->arg[5]); + } + + if (RuleB(Command, DyeCommandRequiresDyes)) { + uint32 dye_item_id = 32557; + if (c->CountItem(dye_item_id) >= 1) { + c->RemoveItem(dye_item_id); + } else { + EQ::SayLinkEngine linker; + linker.SetLinkType(EQ::saylink::SayLinkItemData); + const EQ::ItemData *dye_item = database.GetItem(dye_item_id); + linker.SetItemData(dye_item); + c->Message(Chat::White, fmt::format("This command requires a {} to use.", linker.GenerateLink()).c_str()); + return; + } + } + + c->DyeArmorBySlot(slot, red, green, blue, use_tint); +} + // All new code added to command.cpp should be BEFORE this comment line. Do no append code to this file below the BOTS code block. #ifdef BOTS #include "bot_command.h" diff --git a/zone/command.h b/zone/command.h index 9c2aef51b..f2e8922d1 100644 --- a/zone/command.h +++ b/zone/command.h @@ -93,6 +93,7 @@ void command_disarmtrap(Client *c, const Seperator *sep); void command_door(Client *c, const Seperator *sep); void command_distance(Client *c, const Seperator *sep); void command_doanim(Client *c, const Seperator *sep); +void command_dye(Client *c, const Seperator *sep); void command_dz(Client *c, const Seperator *sep); void command_dzkickplayers(Client *c, const Seperator *sep); void command_editmassrespawn(Client* c, const Seperator* sep);