#include "../client.h" #include "../groups.h" #include "../raids.h" #include "../../common/repositories/npc_types_repository.h" void SendNPCEditSubCommands(Client *c) { c->Message(Chat::White, "Usage: #npcedit name [Name] - Sets an NPC's Name"); c->Message(Chat::White, "Usage: #npcedit lastname [Last Name] - Sets an NPC's Last Name"); c->Message(Chat::White, "Usage: #npcedit level [Level] - Sets an NPC's Level"); c->Message(Chat::White, "Usage: #npcedit race [Race ID] - Sets an NPC's Race"); c->Message(Chat::White, "Usage: #npcedit class [Class ID] - Sets an NPC's Class"); c->Message(Chat::White, "Usage: #npcedit bodytype [Body Type ID] - Sets an NPC's Bodytype"); c->Message(Chat::White, "Usage: #npcedit hp [HP] - Sets an NPC's HP"); c->Message(Chat::White, "Usage: #npcedit mana [Mana] - Sets an NPC's Mana"); c->Message(Chat::White, "Usage: #npcedit gender [Gender ID] - Sets an NPC's Gender"); c->Message(Chat::White, "Usage: #npcedit texture [Texture] - Sets an NPC's Texture"); c->Message(Chat::White, "Usage: #npcedit helmtexture [Helmet Texture] - Sets an NPC's Helmet Texture"); c->Message(Chat::White, "Usage: #npcedit herosforgemodel [Model Number] - Sets an NPC's Hero's Forge Model"); c->Message(Chat::White, "Usage: #npcedit size [Size] - Sets an NPC's Size"); c->Message(Chat::White, "Usage: #npcedit hpregen [HP Regen] - Sets an NPC's HP Regen Rate Per Tick"); c->Message(Chat::White, "Usage: #npcedit hp_regen_per_second [HP Regen] - Sets an NPC's HP Regen Rate Per Second"); c->Message(Chat::White, "Usage: #npcedit manaregen [Mana Regen] - Sets an NPC's Mana Regen Rate Per Tick"); c->Message(Chat::White, "Usage: #npcedit loottable [Loottable ID] - Sets an NPC's Loottable ID"); c->Message(Chat::White, "Usage: #npcedit merchantid [Merchant ID] - Sets an NPC's Merchant ID"); c->Message(Chat::White, "Usage: #npcedit alt_currency_id [Alternate Currency ID] - Sets an NPC's Alternate Currency ID"); c->Message(Chat::White, "Usage: #npcedit spell [Spell List ID] - Sets an NPC's Spells List ID"); c->Message(Chat::White, "Usage: #npcedit npc_spells_effects_id [Spell Effects ID] - Sets an NPC's Spell Effects ID"); c->Message(Chat::White, "Usage: #npcedit faction [Faction ID] - Sets an NPC's Faction ID"); c->Message(Chat::White, "Usage: #npcedit adventure_template_id [Template ID] - Sets an NPC's Adventure Template ID"); c->Message(Chat::White, "Usage: #npcedit trap_template [Template ID] - Sets an NPC's Trap Template ID"); c->Message(Chat::White, "Usage: #npcedit damage [Minimum] [Maximum] - Sets an NPC's Damage"); c->Message(Chat::White, "Usage: #npcedit attackcount [Attack Count] - Sets an NPC's Attack Count"); c->Message(Chat::White, "Usage: #npcedit special_attacks [Special Attacks] - Sets an NPC's Special Attacks"); c->Message(Chat::White, "Usage: #npcedit special_abilities [Special Abilities] - Sets an NPC's Special Abilities"); c->Message(Chat::White, "Usage: #npcedit aggroradius [Radius] - Sets an NPC's Aggro Radius"); c->Message(Chat::White, "Usage: #npcedit assistradius [Radius] - Sets an NPC's Assist Radius"); c->Message(Chat::White, "Usage: #npcedit featuresave - Saves an NPC's current facial features to the database"); c->Message(Chat::White, "Usage: #npcedit armortint_id [Armor Tint ID] - Sets an NPC's Armor Tint ID"); c->Message(Chat::White, "Usage: #npcedit color [Red] [Green] [Blue] - Sets an NPC's Red, Green, and Blue armor tint"); c->Message(Chat::White, "Usage: #npcedit ammoidfile [ID File] - Sets an NPC's Ammo ID File"); c->Message(Chat::White, "Usage: #npcedit weapon [Primary Model] [Secondary Model] - Sets an NPC's Primary and Secondary Weapon Model"); c->Message(Chat::White, "Usage: #npcedit meleetype [Primary Type] [Secondary Type] - Sets an NPC's Melee Skill Types"); c->Message(Chat::White, "Usage: #npcedit rangedtype [Type] - Sets an NPC's Ranged Skill Type"); c->Message(Chat::White, "Usage: #npcedit runspeed [Run Speed] - Sets an NPC's Run Speed"); c->Message(Chat::White, "Usage: #npcedit mr [Resistance] - Sets an NPC's Magic Resistance"); c->Message(Chat::White, "Usage: #npcedit pr [Resistance] - Sets an NPC's Poison Resistance"); c->Message(Chat::White, "Usage: #npcedit dr [Resistance] - Sets an NPC's Disease Resistance"); c->Message(Chat::White, "Usage: #npcedit fr [Resistance] - Sets an NPC's Fire Resistance"); c->Message(Chat::White, "Usage: #npcedit cr [Resistance] - Sets an NPC's Cold Resistance"); c->Message(Chat::White, "Usage: #npcedit corrup [Resistance] - Sets an NPC's Corruption Resistance"); c->Message(Chat::White, "Usage: #npcedit phr [Resistance] - Sets and NPC's Physical Resistance"); c->Message(Chat::White, "Usage: #npcedit seeinvis [Flag] - Sets an NPC's See Invisible Flag [0 = Cannot See Invisible, 1 = Can See Invisible]"); c->Message(Chat::White, "Usage: #npcedit seeinvisundead [Flag] - Sets an NPC's See Invisible vs. Undead Flag [0 = Cannot See Invisible vs. Undead, 1 = Can See Invisible vs. Undead]"); c->Message(Chat::White, "Usage: #npcedit qglobal [Flag] - Sets an NPC's Quest Global Flag [0 = Quest Globals Off, 1 = Quest Globals On]"); c->Message(Chat::White, "Usage: #npcedit ac [Armor Class] - Sets an NPC's Armor Class"); c->Message(Chat::White, "Usage: #npcedit npcaggro [Flag] - Sets an NPC's NPC Aggro Flag [0 = Aggro NPCs Off, 1 = Aggro NPCs On]"); c->Message(Chat::White, "Usage: #npcedit spawn_limit [Limit] - Sets an NPC's Spawn Limit Counter"); c->Message(Chat::White, "Usage: #npcedit attackspeed [Attack Speed] - Sets an NPC's Attack Speed Modifier"); c->Message(Chat::White, "Usage: #npcedit attackdelay [Attack Delay] - Sets an NPC's Attack Delay"); c->Message(Chat::White, "Usage: #npcedit findable [Flag] - Sets an NPC's Findable Flag [0 = Not Findable, 1 = Findable]"); c->Message(Chat::White, "Usage: #npcedit str [Strength] - Sets an NPC's Strength"); c->Message(Chat::White, "Usage: #npcedit sta [Stamina] - Sets an NPC's Stamina"); c->Message(Chat::White, "Usage: #npcedit agi [Agility] - Sets an NPC's Agility"); c->Message(Chat::White, "Usage: #npcedit dex [Dexterity] - Sets an NPC's Dexterity"); c->Message(Chat::White, "Usage: #npcedit int [Intelligence] - Sets an NPC's Intelligence"); c->Message(Chat::White, "Usage: #npcedit wis [Wisdom] - Sets an NPC's Wisdom"); c->Message(Chat::White, "Usage: #npcedit cha [Charisma] - Sets an NPC's Charisma"); c->Message(Chat::White, "Usage: #npcedit seehide [Flag] - Sets an NPC's See Hide Flag [0 = Cannot See Hide, 1 = Can See Hide]"); c->Message(Chat::White, "Usage: #npcedit seeimprovedhide [Flag] - Sets an NPC's See Improved Hide Flag [0 = Cannot See Improved Hide, 1 = Can See Improved Hide]"); c->Message(Chat::White, "Usage: #npcedit trackable [Flag] - Sets an NPC's Trackable Flag [0 = Not Trackable, 1 = Trackable]"); c->Message(Chat::White, "Usage: #npcedit atk [Attack] - Sets an NPC's Attack"); c->Message(Chat::White, "Usage: #npcedit accuracy [Accuracy] - Sets an NPC's Accuracy"); c->Message(Chat::White, "Usage: #npcedit avoidance [Avoidance] - Sets an NPC's Avoidance"); c->Message(Chat::White, "Usage: #npcedit slow_mitigation [Slow Mitigation] - Sets an NPC's Slow Mitigation"); c->Message(Chat::White, "Usage: #npcedit version [Version] - Sets an NPC's Version"); c->Message(Chat::White, "Usage: #npcedit maxlevel [Max Level] - Sets an NPC's Maximum Level"); c->Message(Chat::White, "Usage: #npcedit scalerate [Scale Rate] - Sets an NPC's Scaling Rate [50 = 50%, 100 = 100%, 200 = 200%]"); c->Message(Chat::White, "Usage: #npcedit emoteid [Emote ID] - Sets an NPC's Emote ID"); c->Message(Chat::White, "Usage: #npcedit spellscale [Scale Rate] - Sets an NPC's Spell Scaling Rate [50 = 50%, 100 = 100%, 200 = 200%]"); c->Message(Chat::White, "Usage: #npcedit healscale [Scale Rate] - Sets an NPC's Heal Scaling Rate [50 = 50%, 100 = 100%, 200 = 200%]"); c->Message(Chat::White, "Usage: #npcedit no_target [Flag] - Sets an NPC's No Target Hotkey Flag [0 = Not Targetable with Target Hotkey, 1 = Targetable with Target Hotkey]"); c->Message(Chat::White, "Usage: #npcedit raidtarget [Flag] - Sets an NPC's Raid Target Flag [0 = Not a Raid Target, 1 = Raid Target]"); c->Message(Chat::White, "Usage: #npcedit armtexture [Texture] - Sets an NPC's Arm Texture"); c->Message(Chat::White, "Usage: #npcedit bracertexture [Texture] - Sets an NPC's Bracer Texture"); c->Message(Chat::White, "Usage: #npcedit handtexture [Texture] - Sets an NPC's Hand Texture"); c->Message(Chat::White, "Usage: #npcedit legtexture [Texture] - Sets an NPC's Leg Texture"); c->Message(Chat::White, "Usage: #npcedit feettexture [Texture] - Sets an NPC's Feet Texture"); c->Message(Chat::White, "Usage: #npcedit walkspeed [Walk Speed] - Sets an NPC's Walk Speed"); c->Message(Chat::White, "Usage: #npcedit show_name [Flag] - Sets an NPC's Show Name Flag [0 = Hidden, 1 = Shown]"); c->Message(Chat::White, "Usage: #npcedit untargetable [Flag] - Sets an NPC's Untargetable Flag [0 = Targetable, 1 = Untargetable]"); c->Message(Chat::White, "Usage: #npcedit charm_ac [Armor Class] - Sets an NPC's Armor Class while Charmed"); c->Message(Chat::White, "Usage: #npcedit charm_min_dmg [Damage] - Sets an NPC's Minimum Damage while Charmed"); c->Message(Chat::White, "Usage: #npcedit charm_max_dmg [Damage] - Sets an NPC's Maximum Damage while Charmed"); c->Message(Chat::White, "Usage: #npcedit charm_attack_delay [Attack Delay] - Sets an NPC's Attack Delay while Charmed"); c->Message(Chat::White, "Usage: #npcedit charm_accuracy_rating [Accuracy] - Sets an NPC's Accuracy Rating while Charmed"); c->Message(Chat::White, "Usage: #npcedit charm_avoidance_rating [Avoidance] - Sets an NPC's Avoidance Rating while Charmed"); c->Message(Chat::White, "Usage: #npcedit charm_atk [Attack] - Sets an NPC's Attack while Charmed"); c->Message(Chat::White, "Usage: #npcedit skip_global_loot [Flag] - Sets an NPC's Skip Global Loot Flag [0 = Don't Skip, 1 = Skip"); c->Message(Chat::White, "Usage: #npcedit rarespawn [Flag] - Sets an NPC's Rare Spawn Flag [0 = Not a Rare Spawn, 1 = Rare Spawn]"); c->Message(Chat::White, "Usage: #npcedit stuck_behavior [Stuck Behavior] - Sets an NPC's Stuck Behavior [0 = Run to Target, 1 = Warp to Target, 2 = Take No Action, 3 = Evade Combat]"); c->Message(Chat::White, "Usage: #npcedit model [Race ID] - Sets an NPC's Race Model"); c->Message(Chat::White, "Usage: #npcedit flymode [Fly Mode] - Sets an NPC's Fly Mode [0 = Ground, 1 = Flying, 2 = Levitating, 3 = Water, 4 = Floating, 5 = Levitating While Running]"); c->Message(Chat::White, "Usage: #npcedit always_aggro [Flag] - Sets an NPC's Always Aggro Flag [0 = Does not Always Aggro, 1 = Always Aggro]"); c->Message(Chat::White, "Usage: #npcedit exp_mod [Modifier] - Sets an NPC's Experience Modifier [50 = 50%, 100 = 100%, 200 = 200%]"); c->Message(Chat::White, "Usage: #npcedit heroic_strikethrough [Heroic Strikethrough] - Sets an NPC's Heroic Strikethrough"); c->Message(Chat::White, "Usage: #npcedit faction_amount [Faction Amount] - Sets an NPC's Faction Amount"); c->Message(Chat::White, "Usage: #npcedit keeps_sold_items [Flag] - Sets an NPC's Keeps Sold Items Flag [0 = False, 1 = True]"); c->Message(Chat::White, "Usage: #npcedit is_parcel_merchant [Flag] - Sets an NPC's Parcel Merchant Flag [0 = False, 1 = True]"); c->Message(Chat::White, "Usage: #npcedit setanimation [Animation ID] - Sets an NPC's Animation on Spawn (Stored in spawn2 table)"); c->Message(Chat::White, "Usage: #npcedit respawntime [Respawn Time] - Sets an NPC's Respawn Timer in Seconds (Stored in spawn2 table)"); c->Message(Chat::White, "Usage: #npcedit set_grid [Grid ID] - Sets an NPC's Grid ID"); c->Message(Chat::White, "Usage: #npcedit npc_tint_id [NPC Tint ID] - Sets an NPC's Tint ID (0 to 78 for RoF2)"); } void command_npcedit(Client *c, const Seperator *sep) { if (!c->GetTarget() || !c->GetTarget()->IsNPC()) { c->Message(Chat::White, "You must target an NPC to use this command."); return; } int arguments = sep->argnum; bool is_help = (!arguments || !strcasecmp(sep->arg[1], "help")); if (is_help) { SendNPCEditSubCommands(c); return; } std::string sub_command = sep->arg[1]; auto t = c->GetTarget()->CastToNPC(); auto npc_id = t->GetNPCTypeID(); auto npc_id_string = fmt::format( "NPC ID {}", npc_id ); auto n = NpcTypesRepository::FindOne(content_db, npc_id); if (!n.id) { c->Message(Chat::White, "You must target a valid NPC to use this command."); return; } std::string d; if (!strcasecmp(sep->arg[1], "name")) { std::string name = sep->argplus[2]; if (!name.empty()) { n.name = name; d = fmt::format( "{} is now named '{}'.", npc_id_string, name ); } else { c->Message(Chat::White, "Usage: #npcedit name [Name] - Sets an NPC's Name"); return; } } else if (!strcasecmp(sep->arg[1], "lastname")) { std::string last_name = sep->argplus[2]; n.lastname = last_name; d = fmt::format( "{} now has the lastname '{}'.", npc_id_string, last_name ); } else if (!strcasecmp(sep->arg[1], "level")) { if (sep->IsNumber(2)) { auto level = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.level = level; d = fmt::format( "{} is now level {}.", npc_id_string, level ); } else { c->Message(Chat::White, "Usage: #npcedit level [Level] - Sets an NPC's Level"); return; } } else if (!strcasecmp(sep->arg[1], "race")) { if (sep->IsNumber(2)) { auto race_id = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.race = race_id; d = fmt::format( "{} is now a(n) {} ({}).", npc_id_string, GetRaceIDName(race_id), race_id ); } else { c->Message(Chat::White, "Usage: #npcedit race [Race ID] - Sets an NPC's Race"); return; } } else if (!strcasecmp(sep->arg[1], "class")) { if (sep->IsNumber(2)) { auto class_id = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.class_ = class_id; d = fmt::format( "{} is now a(n) {} ({}).", npc_id_string, GetClassIDName(class_id), class_id ); } else { c->Message(Chat::White, "Usage: #npcedit class [Class ID] - Sets an NPC's Class"); return; } } else if (!strcasecmp(sep->arg[1], "bodytype")) { if (sep->IsNumber(2)) { const uint8 body_type_id = static_cast(Strings::ToUnsignedInt(sep->arg[2])); const std::string& body_type_name = BodyType::GetName(body_type_id); if (Strings::EqualFold(body_type_name, "UNKNOWN BODY TYPE")) { c->Message( Chat::White, fmt::format( "Body Type {} does not exist.", body_type_id ).c_str() ); return; } n.bodytype = body_type_id; d = fmt::format( "{} is now using Body Type {} ({}).", npc_id_string, body_type_name, body_type_id ); } else { c->Message(Chat::White, "Usage: #npcedit bodytype [Body Type ID] - Sets an NPC's Bodytype"); return; } } else if (!strcasecmp(sep->arg[1], "hp")) { if (sep->IsNumber(2)) { auto hp = Strings::ToBigInt(sep->arg[2]); n.hp = hp; d = fmt::format( "{} now has {} Health.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message(Chat::White, "Usage: #npcedit hp [HP] - Sets an NPC's HP"); return; } } else if (!strcasecmp(sep->arg[1], "mana")) { if (sep->IsNumber(2)) { auto mana = Strings::ToBigInt(sep->arg[2]); n.mana = mana; d = fmt::format( "{} now has {} Mana.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message(Chat::White, "Usage: #npcedit mana [Mana] - Sets an NPC's Mana"); return; } } else if (!strcasecmp(sep->arg[1], "gender")) { if (sep->IsNumber(2)) { auto gender_id = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.gender = gender_id; d = fmt::format( "{} is now a {} ({}).", npc_id_string, gender_id, GetGenderName(gender_id) ); } else { c->Message(Chat::White, "Usage: #npcedit gender [Gender ID] - Sets an NPC's Gender"); return; } } else if (!strcasecmp(sep->arg[1], "texture")) { if (sep->IsNumber(2)) { auto texture = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.texture = texture; d = fmt::format( "{} is now using Texture {}.", npc_id_string, texture ); } else { c->Message(Chat::White, "Usage: #npcedit texture [Texture] - Sets an NPC's Texture"); return; } } else if (!strcasecmp(sep->arg[1], "helmtexture")) { if (sep->IsNumber(2)) { auto helmet_texture = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.helmtexture = helmet_texture; d = fmt::format( "{} is now using Helmet Texture {}.", npc_id_string, helmet_texture ); } else { c->Message(Chat::White, "Usage: #npcedit helmtexture [Helmet Texture] - Sets an NPC's Helmet Texture"); return; } } else if (!strcasecmp(sep->arg[1], "herosforgemodel")) { if (sep->IsNumber(2)) { auto heros_forge_model = Strings::ToInt(sep->arg[2]); n.herosforgemodel = heros_forge_model; d = fmt::format( "{} is now using Hero's Forge Model {}.", npc_id_string, heros_forge_model ); } else { c->Message( Chat::White, "Usage: #npcedit herosforgemodel [Model Number] - Sets an NPC's Hero's Forge Model" ); return; } } else if (!strcasecmp(sep->arg[1], "size")) { if (sep->IsNumber(2)) { auto size = Strings::ToFloat(sep->arg[2]); n.size = size; d = fmt::format( "{} is now Size {:.2f}.", npc_id_string, size ); } else { c->Message(Chat::White, "Usage: #npcedit size [Size] - Sets an NPC's Size"); return; } } else if (!strcasecmp(sep->arg[1], "hpregen")) { if (sep->IsNumber(2)) { auto hp_regen = Strings::ToBigInt(sep->arg[2]); n.hp_regen_rate = hp_regen; d = fmt::format( "{} now regenerates {} Health per Tick.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message(Chat::White, "Usage: #npcedit hpregen [HP Regen] - Sets an NPC's HP Regen Rate Per Tick"); return; } } else if (!strcasecmp(sep->arg[1], "hp_regen_per_second")) { if (sep->IsNumber(2)) { auto hp_regen_per_second = Strings::ToBigInt(sep->arg[2]); n.hp_regen_per_second = hp_regen_per_second; d = fmt::format( "{} now regenerates {} HP per Second.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message( Chat::White, "Usage: #npcedit hp_regen_per_second [HP Regen] - Sets an NPC's HP Regen Rate Per Second" ); return; } } else if (!strcasecmp(sep->arg[1], "manaregen")) { if (sep->IsNumber(2)) { auto mana_regen = Strings::ToBigInt(sep->arg[2]); n.mana_regen_rate = mana_regen; d = fmt::format( "{} now regenerates {} Mana per Tick.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message(Chat::White, "Usage: #npcedit manaregen [Mana Regen] - Sets an NPC's Mana Regen Rate Per Tick"); return; } } else if (!strcasecmp(sep->arg[1], "loottable")) { if (sep->IsNumber(2)) { auto loottable_id = Strings::ToUnsignedInt(sep->arg[2]); n.loottable_id = loottable_id; d = fmt::format( "{} is now using Loottable ID {}.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message(Chat::White, "Usage: #npcedit loottable [Loottable ID] - Sets an NPC's Loottable ID"); return; } } else if (!strcasecmp(sep->arg[1], "merchantid")) { if (sep->IsNumber(2)) { auto merchant_id = Strings::ToUnsignedInt(sep->arg[2]); n.merchant_id = merchant_id; d = fmt::format( "{} is now using Merchant ID {}.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message(Chat::White, "Usage: #npcedit merchantid [Merchant ID] - Sets an NPC's Merchant ID"); return; } } else if (!strcasecmp(sep->arg[1], "alt_currency_id")) { if (sep->IsNumber(2)) { auto alternate_currency_id = Strings::ToUnsignedInt(sep->arg[2]); auto alternate_currency_item_id = zone->GetCurrencyItemID(alternate_currency_id); n.alt_currency_id = alternate_currency_id; d = fmt::format( "{} is now using Alternate Currency {}.", npc_id_string, ( alternate_currency_item_id ? fmt::format( "{} ({})", database.CreateItemLink(alternate_currency_item_id), alternate_currency_id ) : std::to_string(alternate_currency_id) ) ); } else { c->Message( Chat::White, "Usage: #npcedit alt_currency_id [Alternate Currency ID] - Sets an NPC's Alternate Currency ID" ); return; } } else if (!strcasecmp(sep->arg[1], "spell")) { if (sep->IsNumber(2)) { auto spell_list_id = Strings::ToUnsignedInt(sep->arg[2]); n.npc_spells_id = spell_list_id; d = fmt::format( "{} is now using Spell List ID {}.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message(Chat::White, "Usage: #npcedit spell [Spell List ID] - Sets an NPC's Spells List ID"); return; } } else if (!strcasecmp(sep->arg[1], "npc_spells_effects_id")) { if (sep->IsNumber(2)) { auto spell_effects_id = Strings::ToUnsignedInt(sep->arg[2]); n.npc_spells_effects_id = spell_effects_id; d = fmt::format( "{} is now using Spells Effects ID {}.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message( Chat::White, "Usage: #npcedit npc_spells_effects_id [Spell Effects ID] - Sets an NPC's Spell Effects ID" ); return; } } else if (!strcasecmp(sep->arg[1], "faction")) { if (sep->IsNumber(2)) { auto npc_faction_id = Strings::ToInt(sep->arg[2]); const auto f = zone->GetNPCFaction(npc_faction_id); if (f) { auto faction_id = f->primaryfaction; auto faction_name = content_db.GetFactionName(faction_id); n.npc_faction_id = npc_faction_id; d = fmt::format( "{} is now using Faction {}.", npc_id_string, ( !faction_name.empty() ? fmt::format( "{} ({})", faction_name, faction_id ) : Strings::Commify(sep->arg[2]) ) ); } else { c->Message(Chat::White, "Need to provide a valid, existing, npc_faction_id"); return; } } else { c->Message(Chat::White, "Usage: #npcedit faction [npc_faction_id] - Sets an NPC's npc Faction ID (not primary faction) but lookup into table."); return; } } else if (!strcasecmp(sep->arg[1], "adventure_template_id")) { if (sep->IsNumber(2)) { auto adventure_template_id = Strings::ToUnsignedInt(sep->arg[2]); n.adventure_template_id = adventure_template_id; d = fmt::format( "{} is now using Adventure Template ID {}.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message( Chat::White, "Usage: #npcedit adventure_template_id [Template ID] - Sets an NPC's Adventure Template ID" ); return; } } else if (!strcasecmp(sep->arg[1], "trap_template")) { if (sep->IsNumber(2)) { auto trap_template = Strings::ToUnsignedInt(sep->arg[2]); n.trap_template = trap_template; d = fmt::format( "{} is now using Trap Template ID {}.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message(Chat::White, "Usage: #npcedit trap_template [Template ID] - Sets an NPC's Trap Template ID"); return; } } else if (!strcasecmp(sep->arg[1], "damage")) { if (sep->IsNumber(2) && sep->IsNumber(3)) { auto minimum_damage = Strings::ToUnsignedInt(sep->arg[2]); auto maximum_damage = Strings::ToUnsignedInt(sep->arg[3]); n.mindmg = minimum_damage; n.maxdmg = maximum_damage; d = fmt::format( "{} now hits from {} to {} damage.", npc_id_string, Strings::Commify(sep->arg[2]), Strings::Commify(sep->arg[3]) ); } else { c->Message(Chat::White, "Usage: #npcedit damage [Minimum] [Maximum] - Sets an NPC's Damage"); return; } } else if (!strcasecmp(sep->arg[1], "attackcount")) { if (sep->IsNumber(2)) { auto attack_count = static_cast(Strings::ToInt(sep->arg[2])); n.attack_count = attack_count; d = fmt::format( "{} now has an Attack Count of {}.", npc_id_string, attack_count ); } else { c->Message(Chat::White, "Usage: #npcedit attackcount [Attack Count] - Sets an NPC's Attack Count"); return; } } else if (!strcasecmp(sep->arg[1], "special_attacks")) { std::string special_attacks = sep->argplus[2]; n.npcspecialattks = special_attacks; d = fmt::format( "{} is now using the following Special Attacks '{}'.", npc_id_string, special_attacks ); } else if (!strcasecmp(sep->arg[1], "special_abilities")) { std::string special_abilities = sep->argplus[2]; n.special_abilities = special_abilities; d = fmt::format( "{} is now using the following Special Abilities '{}'.", npc_id_string, special_abilities ); } else if (!strcasecmp(sep->arg[1], "aggroradius")) { if (sep->IsNumber(2)) { auto aggro_radius = Strings::ToUnsignedInt(sep->arg[2]); n.aggroradius = aggro_radius; d = fmt::format( "{} now has an Aggro Radius of {}.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message(Chat::White, "Usage: #npcedit aggroradius [Radius] - Sets an NPC's Aggro Radius"); return; } } else if (!strcasecmp(sep->arg[1], "assistradius")) { if (sep->IsNumber(2)) { auto assist_radius = Strings::ToUnsignedInt(sep->arg[2]); n.assistradius = assist_radius; d = fmt::format( "{} now has an Assist Radius of {}", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message(Chat::White, "Usage: #npcedit assistradius [Radius] - Sets an NPC's Assist Radius"); return; } } else if (!strcasecmp(sep->arg[1], "featuresave")) { d = fmt::format( "{} saved with all current body and facial feature settings.", npc_id ); n.gender = t->GetGender(); n.texture = t->GetTexture(); n.helmtexture = t->GetHelmTexture(); n.size = t->GetSize(); n.face = t->GetLuclinFace(); n.luclin_hairstyle = t->GetHairStyle(); n.luclin_haircolor = t->GetHairColor(); n.luclin_eyecolor = t->GetEyeColor1(); n.luclin_eyecolor2 = t->GetEyeColor2(); n.luclin_beardcolor = t->GetBeardColor(); n.luclin_beard = t->GetBeard(); n.drakkin_heritage = t->GetDrakkinHeritage(); n.drakkin_tattoo = t->GetDrakkinTattoo(); n.drakkin_details = t->GetDrakkinDetails(); } else if (!strcasecmp(sep->arg[1], "armortint_id")) { if (sep->IsNumber(2)) { auto armor_tint_id = Strings::ToUnsignedInt(sep->arg[2]); n.armortint_id = armor_tint_id; d = fmt::format( "{} is now using Armor Tint ID {}.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message(Chat::White, "Usage: #npcedit armortint_id [Armor Tint ID] - Sets an NPC's Armor Tint ID"); return; } } else if (!strcasecmp(sep->arg[1], "color")) { if (sep->IsNumber(2)) { auto red = static_cast(Strings::ToUnsignedInt(sep->arg[2])); uint8_t green = sep->IsNumber(3) ? static_cast(Strings::ToUnsignedInt(sep->arg[3])) : 0; uint8_t blue = sep->IsNumber(4) ? static_cast(Strings::ToUnsignedInt(sep->arg[4])) : 0; n.armortint_red = red; n.armortint_green = green; n.armortint_blue = blue; d = fmt::format( "{} now has {} Red, {} Green, and {} Blue tinting on their armor.", npc_id_string, red, green, blue ); } else { c->Message( Chat::White, "Usage: #npcedit color [Red] [Green] [Blue] - Sets an NPC's Red, Green, and Blue armor tint" ); return; } } else if (!strcasecmp(sep->arg[1], "ammoidfile")) { if (sep->IsNumber(2)) { auto ammo_id_file = Strings::ToUnsignedInt(sep->arg[2]); n.ammo_idfile = ammo_id_file; d = fmt::format( "{} is now using Ammo ID File {}.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message(Chat::White, "Usage: #npcedit ammoidfile [ID File] - Sets an NPC's Ammo ID File"); return; } } else if (!strcasecmp(sep->arg[1], "weapon")) { if (sep->IsNumber(2)) { auto primary_model = Strings::ToUnsignedInt(sep->arg[2]); uint32_t secondary_model = sep->IsNumber(3) ? Strings::ToUnsignedInt(sep->arg[3]) : 0; n.d_melee_texture1 = primary_model; n.d_melee_texture2 = secondary_model; d = fmt::format( "{} will have Model {} set to their Primary and Model {} set to their Secondary on repop.", npc_id_string, Strings::Commify(primary_model), Strings::Commify(secondary_model) ); } else { c->Message( Chat::White, "Usage: #npcedit weapon [Primary Model] [Secondary Model] - Sets an NPC's Primary and Secondary Weapon Model" ); return; } } else if (!strcasecmp(sep->arg[1], "meleetype")) { if (sep->IsNumber(2)) { auto primary_type = Strings::ToUnsignedInt(sep->arg[2]); uint32_t secondary_type = sep->IsNumber(3) ? Strings::ToUnsignedInt(sep->arg[3]) : EQ::skills::SkillHandtoHand; auto primary_skill = EQ::skills::GetSkillName(static_cast(primary_type)); auto secondary_skill = EQ::skills::GetSkillName(static_cast(secondary_type)); n.prim_melee_type = primary_type; n.sec_melee_type = secondary_type; d = fmt::format( "{} now has a Primary Melee Type of {} and a Secondary Melee Type of {}.", npc_id_string, ( !primary_skill.empty() ? fmt::format( "{} ({})", primary_skill, primary_type ) : std::to_string(primary_type) ), ( !secondary_skill.empty() ? fmt::format( "{} ({})", secondary_skill, secondary_type ) : std::to_string(secondary_type) ) ); } else { c->Message( Chat::White, "Usage: #npcedit meleetype [Primary Type] [Secondary Type] - Sets an NPC's Melee Skill Types" ); return; } } else if (!strcasecmp(sep->arg[1], "rangedtype")) { if (sep->IsNumber(2)) { auto ranged_type = Strings::ToUnsignedInt(sep->arg[2]); auto ranged_skill = EQ::skills::GetSkillName(static_cast(ranged_type)); n.ranged_type = ranged_type; d = fmt::format( "{} now has a Ranged Type of {}.", npc_id_string, ( !ranged_skill.empty() ? fmt::format( "{} ({})", ranged_skill, ranged_type ) : std::to_string(ranged_type) ) ); } else { c->Message(Chat::White, "Usage: #npcedit rangedtype [Type] - Sets an NPC's Ranged Skill Type"); return; } } else if (!strcasecmp(sep->arg[1], "runspeed")) { if (sep->IsNumber(2)) { auto run_speed = Strings::ToFloat(sep->arg[2]); n.runspeed = run_speed; d = fmt::format( "{} now runs at a Run Speed of {:.2f}.", npc_id_string, run_speed ); } else { c->Message(Chat::White, "Usage: #npcedit runspeed [Run Speed] - Sets an NPC's Run Speed"); return; } } else if (!strcasecmp(sep->arg[1], "mr")) { if (sep->IsNumber(2)) { auto magic_resist = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.MR = magic_resist; d = fmt::format( "{} now has a Magic Resistance of {}.", npc_id_string, magic_resist ); } else { c->Message(Chat::White, "Usage: #npcedit mr [Resistance] - Sets an NPC's Magic Resistance"); return; } } else if (!strcasecmp(sep->arg[1], "pr")) { if (sep->IsNumber(2)) { auto poison_resist = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.PR = poison_resist; d = fmt::format( "{} now has a Poison Resistance of {}.", npc_id_string, poison_resist ); } else { c->Message(Chat::White, "Usage: #npcedit pr [Resistance] - Sets an NPC's Poison Resistance"); return; } } else if (!strcasecmp(sep->arg[1], "dr")) { if (sep->IsNumber(2)) { auto disease_resist = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.DR = disease_resist; d = fmt::format( "{} now has a Disease Resistance of {}.", npc_id_string, disease_resist ); } else { c->Message(Chat::White, "Usage: #npcedit dr [Resistance] - Sets an NPC's Disease Resistance"); return; } } else if (!strcasecmp(sep->arg[1], "fr")) { if (sep->IsNumber(2)) { auto fire_resist = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.FR = fire_resist; d = fmt::format( "{} now has a Fire Resistance of {}.", npc_id_string, fire_resist ); } else { c->Message(Chat::White, "Usage: #npcedit fr [Resistance] - Sets an NPC's Fire Resistance"); return; } } else if (!strcasecmp(sep->arg[1], "cr")) { if (sep->IsNumber(2)) { auto cold_resist = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.CR = cold_resist; d = fmt::format( "{} now has a Cold Resistance of {}.", npc_id_string, cold_resist ); } else { c->Message(Chat::White, "Usage: #npcedit cr [Resistance] - Sets an NPC's Cold Resistance"); return; } } else if (!strcasecmp(sep->arg[1], "corrup")) { if (sep->IsNumber(2)) { auto corruption_resist = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.Corrup = corruption_resist; d = fmt::format( "{} now has a Corruption Resistance of {}.", npc_id_string, corruption_resist ); } else { c->Message(Chat::White, "Usage: #npcedit corrup [Resistance] - Sets an NPC's Corruption Resistance"); return; } } else if (!strcasecmp(sep->arg[1], "phr")) { if (sep->IsNumber(2)) { auto physical_resist = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.PhR = physical_resist; d = fmt::format( "{} now has a Physical Resistance of {}.", npc_id_string, physical_resist ); } else { c->Message(Chat::White, "Usage: #npcedit phr [Resistance] - Sets and NPC's Physical Resistance"); return; } } else if (!strcasecmp(sep->arg[1], "seeinvis")) { if (sep->IsNumber(2)) { auto see_invisible = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.see_invis = see_invisible; d = fmt::format( "{} can {} See Invisible.", npc_id_string, see_invisible ? "now" : "no longer" ); } else { c->Message( Chat::White, "Usage: #npcedit seeinvis [Flag] - Sets an NPC's See Invisible Flag [0 = Cannot See Invisible, 1 = Can See Invisible]" ); return; } } else if (!strcasecmp(sep->arg[1], "seeinvisundead")) { if (sep->IsNumber(2)) { auto see_invisible_undead = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.see_invis_undead = see_invisible_undead; d = fmt::format( "{} can {} See Invisible vs. Undead.", npc_id_string, see_invisible_undead ? "now" : "no longer" ); } else { c->Message( Chat::White, "Usage: #npcedit seeinvisundead [Flag] - Sets an NPC's See Invisible vs. Undead Flag [0 = Cannot See Invisible vs. Undead, 1 = Can See Invisible vs. Undead]" ); return; } } else if (!strcasecmp(sep->arg[1], "qglobal")) { if (sep->IsNumber(2)) { auto use_qglobals = Strings::ToUnsignedInt(sep->arg[2]); n.qglobal = use_qglobals; d = fmt::format( "{} can {} use Quest Globals.", npc_id_string, use_qglobals ? "now" : "no longer" ); } else { c->Message( Chat::White, "Usage: #npcedit qglobal [Flag] - Sets an NPC's Quest Global Flag [0 = Quest Globals Off, 1 = Quest Globals On]" ); return; } } else if (!strcasecmp(sep->arg[1], "ac")) { if (sep->IsNumber(2)) { auto armor_class = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.AC = armor_class; d = fmt::format( "{} now has {} Armor Class.", npc_id_string, armor_class ); } else { c->Message(Chat::White, "Usage: #npcedit ac [Armor Class] - Sets an NPC's Armor Class"); return; } } else if (!strcasecmp(sep->arg[1], "npcaggro")) { if (sep->IsNumber(2)) { auto aggro_npcs = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.npc_aggro = aggro_npcs; d = fmt::format( "{} will {} aggro other NPCs that have a hostile faction.", npc_id_string, aggro_npcs ? "now" : "no longer" ); } else { c->Message( Chat::White, "Usage: #npcedit npcaggro [Flag] - Sets an NPC's NPC Aggro Flag [0 = Aggro NPCs Off, 1 = Aggro NPCs On]" ); return; } } else if (!strcasecmp(sep->arg[1], "spawn_limit")) { if (sep->IsNumber(2)) { auto spawn_limit = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.spawn_limit = spawn_limit; d = fmt::format( "{} now has a Spawn Limit of {}.", npc_id_string, spawn_limit ); } else { c->Message(Chat::White, "Usage: #npcedit spawn_limit [Limit] - Sets an NPC's Spawn Limit Counter"); return; } } else if (!strcasecmp(sep->arg[1], "attackspeed")) { if (sep->IsNumber(2)) { auto attack_speed = Strings::ToFloat(sep->arg[2]); n.attack_speed = attack_speed; d = fmt::format( "{} now has an Attack Speed of {:.2f}.", npc_id_string, attack_speed ); } else { c->Message(Chat::White, "Usage: #npcedit attackspeed [Attack Speed] - Sets an NPC's Attack Speed Modifier"); return; } } else if (!strcasecmp(sep->arg[1], "attackdelay")) { if (sep->IsNumber(2)) { auto attack_delay = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.attack_delay = attack_delay; d = fmt::format( "{} now has an Attack Delay of {}.", npc_id_string, attack_delay ); } else { c->Message(Chat::White, "Usage: #npcedit attackdelay [Attack Delay] - Sets an NPC's Attack Delay"); return; } } else if (!strcasecmp(sep->arg[1], "findable")) { if (sep->IsNumber(2)) { auto is_findable = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.findable = is_findable; d = fmt::format( "{} is {} Findable.", npc_id_string, is_findable ? "now" : "no longer" ); } else { c->Message( Chat::White, "Usage: #npcedit findable [Flag] - Sets an NPC's Findable Flag [0 = Not Findable, 1 = Findable]" ); return; } } else if (!strcasecmp(sep->arg[1], "str")) { if (sep->IsNumber(2)) { auto strength = Strings::ToUnsignedInt(sep->arg[2]); n.STR = strength; d = fmt::format( "{} now has {} Strength.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message(Chat::White, "Usage: #npcedit str [Strength] - Sets an NPC's Strength"); return; } } else if (!strcasecmp(sep->arg[1], "sta")) { if (sep->IsNumber(2)) { auto stamina = Strings::ToUnsignedInt(sep->arg[2]); n.STA = stamina; d = fmt::format( "{} now has {} Stamina.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message(Chat::White, "Usage: #npcedit sta [Stamina] - Sets an NPC's Stamina"); return; } } else if (!strcasecmp(sep->arg[1], "agi")) { if (sep->IsNumber(2)) { auto agility = Strings::ToUnsignedInt(sep->arg[2]); n.AGI = agility; d = fmt::format( "{} now has {} Agility.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message(Chat::White, "Usage: #npcedit agi [Agility] - Sets an NPC's Agility"); return; } } else if (!strcasecmp(sep->arg[1], "dex")) { if (sep->IsNumber(2)) { auto dexterity = Strings::ToUnsignedInt(sep->arg[2]); n.DEX = dexterity; d = fmt::format( "{} now has {} Dexterity.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message(Chat::White, "Usage: #npcedit dex [Dexterity] - Sets an NPC's Dexterity"); return; } } else if (!strcasecmp(sep->arg[1], "int")) { if (sep->IsNumber(2)) { auto intelligence = Strings::ToUnsignedInt(sep->arg[2]); n._INT = intelligence; d = fmt::format( "{} now has {} Intelligence.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message(Chat::White, "Usage: #npcedit int [Intelligence] - Sets an NPC's Intelligence"); return; } } else if (!strcasecmp(sep->arg[1], "wis")) { if (sep->IsNumber(2)) { auto wisdom = Strings::ToUnsignedInt(sep->arg[2]); n.WIS = wisdom; d = fmt::format( "{} now has {} Wisdom.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message(Chat::White, "Usage: #npcedit wis [Wisdom] - Sets an NPC's Wisdom"); return; } } else if (!strcasecmp(sep->arg[1], "cha")) { if (sep->IsNumber(2)) { auto charisma = Strings::ToUnsignedInt(sep->arg[2]); n.CHA = charisma; d = fmt::format( "{} now has {} Charisma.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message(Chat::White, "Usage: #npcedit cha [Charisma] - Sets an NPC's Charisma"); return; } } else if (!strcasecmp(sep->arg[1], "seehide")) { if (sep->IsNumber(2)) { auto see_hide = static_cast(Strings::ToInt(sep->arg[2])); n.see_hide = see_hide; d = fmt::format( "{} can {} See Hide.", npc_id_string, see_hide ? "now" : "no longer" ); } else { c->Message( Chat::White, "Usage: #npcedit seehide [Flag] - Sets an NPC's See Hide Flag [0 = Cannot See Hide, 1 = Can See Hide]" ); return; } } else if (!strcasecmp(sep->arg[1], "seeimprovedhide")) { if (sep->IsNumber(2)) { auto see_improved_hide = static_cast(Strings::ToInt(sep->arg[2])); n.see_improved_hide = see_improved_hide; d = fmt::format( "{} can {} See Improved Hide.", npc_id_string, see_improved_hide ? "now" : "no longer" ); } else { c->Message( Chat::White, "Usage: #npcedit seeimprovedhide [Flag] - Sets an NPC's See Improved Hide Flag [0 = Cannot See Improved Hide, 1 = Can See Improved Hide]" ); return; } } else if (!strcasecmp(sep->arg[1], "trackable")) { if (sep->IsNumber(2)) { auto is_trackable = static_cast(Strings::ToInt(sep->arg[2])); n.trackable = is_trackable; d = fmt::format( "{} is {} Trackable.", npc_id_string, is_trackable ? "now" : "no longer" ); } else { c->Message( Chat::White, "Usage: #npcedit trackable [Flag] - Sets an NPC's Trackable Flag [0 = Not Trackable, 1 = Trackable]" ); return; } } else if (!strcasecmp(sep->arg[1], "atk")) { if (sep->IsNumber(2)) { auto attack = Strings::ToInt(sep->arg[2]); n.ATK = attack; d = fmt::format( "{} now has {} Attack.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message(Chat::White, "Usage: #npcedit atk [Attack] - Sets an NPC's Attack"); return; } } else if (!strcasecmp(sep->arg[1], "accuracy")) { if (sep->IsNumber(2)) { auto accuracy = Strings::ToInt(sep->arg[2]); n.Accuracy = accuracy; d = fmt::format( "{} now has {} Accuracy.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message(Chat::White, "Usage: #npcedit accuracy [Accuracy] - Sets an NPC's Accuracy"); return; } } else if (!strcasecmp(sep->arg[1], "avoidance")) { if (sep->IsNumber(2)) { auto avoidance = Strings::ToUnsignedInt(sep->arg[2]); n.Avoidance = avoidance; d = fmt::format( "{} now has {} Avoidance.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message(Chat::White, "Usage: #npcedit avoidance [Avoidance] - Sets an NPC's Avoidance"); return; } } else if (!strcasecmp(sep->arg[1], "slow_mitigation")) { if (sep->IsNumber(2)) { auto slow_mitigation = static_cast(Strings::ToInt(sep->arg[2])); n.slow_mitigation = slow_mitigation; d = fmt::format( "{} now has {} Slow Mitigation.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message( Chat::White, "Usage: #npcedit slow_mitigation [Slow Mitigation] - Sets an NPC's Slow Mitigation" ); return; } } else if (!strcasecmp(sep->arg[1], "version")) { if (sep->IsNumber(2)) { auto version = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.version = version; d = fmt::format( "{} is now using Version {}.", npc_id_string, version ); } else { c->Message(Chat::White, "Usage: #npcedit version [Version] - Sets an NPC's Version"); return; } } else if (!strcasecmp(sep->arg[1], "maxlevel")) { if (sep->IsNumber(2)) { auto max_level = static_cast(Strings::ToInt(sep->arg[2])); n.maxlevel = max_level; d = fmt::format( "{} now has a Maximum Level of {}.", npc_id_string, max_level ); } else { c->Message(Chat::White, "Usage: #npcedit maxlevel [Max Level] - Sets an NPC's Maximum Level"); return; } } else if (!strcasecmp(sep->arg[1], "scalerate")) { if (sep->IsNumber(2)) { auto scale_rate = Strings::ToInt(sep->arg[2]); n.scalerate = scale_rate; d = fmt::format( "{} now has a Scaling Rate of {}%%.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message( Chat::White, "Usage: #npcedit scalerate [Scale Rate] - Sets an NPC's Scaling Rate [50 = 50%, 100 = 100%, 200 = 200%]" ); return; } } else if (!strcasecmp(sep->arg[1], "emoteid")) { if (sep->IsNumber(2)) { const uint32 emote_id = Strings::ToUnsignedInt(sep->arg[2]); n.emoteid = emote_id; d = fmt::format( "{} now has an Emote ID of {}.", npc_id_string, Strings::Commify(emote_id) ); } else { c->Message( Chat::White, "Usage: #npcedit emoteid [Emote ID] - Sets an NPC's Emote ID" ); return; } } else if (!strcasecmp(sep->arg[1], "spellscale")) { if (sep->IsNumber(2)) { auto spell_scale = Strings::ToUnsignedInt(sep->arg[2]); n.spellscale = static_cast(spell_scale); d = fmt::format( "{} now has a Spell Scaling Rate of {}%%.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message( Chat::White, "Usage: #npcedit spellscale [Scale Rate] - Sets an NPC's Spell Scaling Rate [50 = 50%, 100 = 100%, 200 = 200%]" ); return; } } else if (!strcasecmp(sep->arg[1], "healscale")) { if (sep->IsNumber(2)) { auto heal_scale = Strings::ToUnsignedInt(sep->arg[2]); n.healscale = static_cast(heal_scale); d = fmt::format( "{} now has a Heal Scaling Rate of {}%%.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message( Chat::White, "Usage: #npcedit healscale [Scale Rate] - Sets an NPC's Heal Scaling Rate [50 = 50%, 100 = 100%, 200 = 200%]" ); return; } } else if (!strcasecmp(sep->arg[1], "no_target")) { if (sep->IsNumber(2)) { auto is_no_target = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.no_target_hotkey = is_no_target; d = fmt::format( "{} is {} Targetable with Target Hotkey.", npc_id_string, is_no_target ? "now" : "no longer" ); } else { c->Message( Chat::White, "Usage: #npcedit no_target [Flag] - Sets an NPC's No Target Hotkey Flag [0 = Not Targetable with Target Hotkey, 1 = Targetable with Target Hotkey]" ); return; } } else if (!strcasecmp(sep->arg[1], "raidtarget")) { if (sep->IsNumber(2)) { auto is_raid_target = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.raid_target = is_raid_target; d = fmt::format( "{} is {} designated as a Raid Target.", npc_id_string, is_raid_target ? "now" : "no longer" ); } else { c->Message( Chat::White, "Usage: #npcedit raidtarget [Flag] - Sets an NPC's Raid Target Flag [0 = Not a Raid Target, 1 = Raid Target]" ); } return; } else if (!strcasecmp(sep->arg[1], "armtexture")) { if (sep->IsNumber(2)) { auto arm_texture = static_cast(Strings::ToInt(sep->arg[2])); n.armtexture = arm_texture; d = fmt::format( "{} is now using Arm Texture {}.", npc_id_string, arm_texture ); } else { c->Message(Chat::White, "Usage: #npcedit armtexture [Texture] - Sets an NPC's Arm Texture"); return; } } else if (!strcasecmp(sep->arg[1], "bracertexture")) { if (sep->IsNumber(2)) { auto bracer_texture = static_cast(Strings::ToInt(sep->arg[2])); n.bracertexture = bracer_texture; d = fmt::format( "{} is now using Bracer Texture {}.", npc_id_string, bracer_texture ); } else { c->Message(Chat::White, "Usage: #npcedit bracertexture [Texture] - Sets an NPC's Bracer Texture"); return; } } else if (!strcasecmp(sep->arg[1], "handtexture")) { if (sep->IsNumber(2)) { auto hand_texture = static_cast(Strings::ToInt(sep->arg[2])); n.handtexture = hand_texture; d = fmt::format( "{} is now using Hand Texture {}.", npc_id_string, hand_texture ); } else { c->Message(Chat::White, "Usage: #npcedit handtexture [Texture] - Sets an NPC's Hand Texture"); return; } } else if (!strcasecmp(sep->arg[1], "legtexture")) { if (sep->IsNumber(2)) { auto leg_texture = static_cast(Strings::ToInt(sep->arg[2])); n.legtexture = leg_texture; d = fmt::format( "{} is now using Leg Texture {}.", npc_id_string, leg_texture ); } else { c->Message(Chat::White, "Usage: #npcedit legtexture [Texture] - Sets an NPC's Leg Texture"); return; } } else if (!strcasecmp(sep->arg[1], "feettexture")) { if (sep->IsNumber(2)) { auto feet_texture = static_cast(Strings::ToInt(sep->arg[2])); n.feettexture = feet_texture; d = fmt::format( "{} is now using Feet Texture {}.", npc_id_string, feet_texture ); } else { c->Message(Chat::White, "Usage: #npcedit feettexture [Texture] - Sets an NPC's Feet Texture"); return; } } else if (!strcasecmp(sep->arg[1], "walkspeed")) { if (sep->IsNumber(2)) { auto walk_speed = static_cast(Strings::ToInt(sep->arg[2])); n.walkspeed = walk_speed; d = fmt::format( "{} now walks at a Walk Speed of {}.", npc_id_string, walk_speed ); } else { c->Message(Chat::White, "Usage: #npcedit walkspeed [Walk Speed] - Sets an NPC's Walk Speed"); return; } } else if (!strcasecmp(sep->arg[1], "show_name")) { if (sep->IsNumber(2)) { auto show_name = static_cast(Strings::ToInt(sep->arg[2])); n.show_name = show_name; d = fmt::format( "{} will {} show their name.", npc_id_string, show_name ? "now" : "no longer" ); } else { c->Message( Chat::White, "Usage: #npcedit show_name [Flag] - Sets an NPC's Show Name Flag [0 = Hidden, 1 = Shown]" ); return; } } else if (!strcasecmp(sep->arg[1], "untargetable")) { if (sep->IsNumber(2)) { auto is_untargetable = static_cast(Strings::ToInt(sep->arg[2])); n.untargetable = is_untargetable; d = fmt::format( "{} will {} be untargetable.", npc_id_string, is_untargetable ? "now" : "no longer" ); } else { c->Message( Chat::White, "Usage: #npcedit untargetable [Flag] - Sets an NPC's Untargetable Flag [0 = Targetable, 1 = Untargetable]" ); return; } } else if (!strcasecmp(sep->arg[1], "charm_ac")) { if (sep->IsNumber(2)) { auto charm_armor_class = static_cast(Strings::ToInt(sep->arg[2])); n.charm_ac = charm_armor_class; d = fmt::format( "{} now has {} Armor Class while Charmed.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message(Chat::White, "Usage: #npcedit charm_ac [Armor Class] - Sets an NPC's Armor Class while Charmed"); return; } } else if (!strcasecmp(sep->arg[1], "charm_min_dmg")) { if (sep->IsNumber(2)) { auto charm_minimum_damage = Strings::ToInt(sep->arg[2]); n.charm_min_dmg = charm_minimum_damage; d = fmt::format( "{} now does {} Minimum Damage while Charmed.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message( Chat::White, "Usage: #npcedit charm_min_dmg [Damage] - Sets an NPC's Minimum Damage while Charmed" ); return; } } else if (!strcasecmp(sep->arg[1], "charm_max_dmg")) { if (sep->IsNumber(2)) { auto charm_maximum_damage = Strings::ToInt(sep->arg[2]); n.charm_max_dmg = charm_maximum_damage; d = fmt::format( "{} now does {} Maximum Damage while Charmed.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message( Chat::White, "Usage: #npcedit charm_max_dmg [Damage] - Sets an NPC's Maximum Damage while Charmed" ); return; } } else if (!strcasecmp(sep->arg[1], "charm_attack_delay")) { if (sep->IsNumber(2)) { auto charm_attack_delay = static_cast(Strings::ToInt(sep->arg[2])); n.charm_attack_delay = charm_attack_delay; d = fmt::format( "{} now has {} Attack Delay while Charmed.", npc_id_string, charm_attack_delay ); } else { c->Message( Chat::White, "Usage: #npcedit charm_attack_delay [Attack Delay] - Sets an NPC's Attack Delay while Charmed" ); return; } } else if (!strcasecmp(sep->arg[1], "charm_accuracy_rating")) { if (sep->IsNumber(2)) { auto charm_accuracy_rating = Strings::ToInt(sep->arg[2]); n.charm_accuracy_rating = charm_accuracy_rating; d = fmt::format( "{} now has {} Accuracy Rating while Charmed.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message( Chat::White, "Usage: #npcedit charm_accuracy_rating [Accuracy] - Sets an NPC's Accuracy Rating while Charmed" ); return; } } else if (!strcasecmp(sep->arg[1], "charm_avoidance_rating")) { if (sep->IsNumber(2)) { auto charm_avoidance_rating = Strings::ToInt(sep->arg[2]); n.charm_avoidance_rating = charm_avoidance_rating; d = fmt::format( "{} now has {} Avoidance Rating while Charmed.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message( Chat::White, "Usage: #npcedit charm_avoidance_rating [Avoidance] - Sets an NPC's Avoidance Rating while Charmed" ); return; } } else if (!strcasecmp(sep->arg[1], "charm_atk")) { if (sep->IsNumber(2)) { auto charm_attack = Strings::ToInt(sep->arg[2]); n.charm_atk = charm_attack; d = fmt::format( "{} now has {} Attack while Charmed.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message(Chat::White, "Usage: #npcedit charm_atk [Attack] - Sets an NPC's Attack while Charmed"); return; } } else if (!strcasecmp(sep->arg[1], "skip_global_loot")) { if (sep->IsNumber(2)) { auto skip_global_loot = static_cast(Strings::ToInt(sep->arg[2])); n.skip_global_loot = skip_global_loot; d = fmt::format( "{} will {} skip Global Loot.", npc_id_string, skip_global_loot ? "now" : "no longer" ); } else { c->Message( Chat::White, "Usage: #npcedit skip_global_loot [Flag] - Sets an NPC's Skip Global Loot Flag [0 = Don't Skip, 1 = Skip" ); return; } } else if (!strcasecmp(sep->arg[1], "rarespawn")) { if (sep->IsNumber(2)) { auto is_rare_spawn = static_cast(Strings::ToInt(sep->arg[2])); n.rare_spawn = is_rare_spawn; d = fmt::format( "{} is {} designated as a Rare Spawn.", npc_id_string, is_rare_spawn ? "now" : "no longer" ); } else { c->Message( Chat::White, "Usage: #npcedit rarespawn [Flag] - Sets an NPC's Rare Spawn Flag [0 = Not a Rare Spawn, 1 = Rare Spawn]" ); return; } } else if (!strcasecmp(sep->arg[1], "stuck_behavior")) { if (sep->IsNumber(2)) { auto behavior_id = static_cast(Strings::ToInt(sep->arg[2])); if (behavior_id > EQ::constants::StuckBehavior::EvadeCombat) { behavior_id = EQ::constants::StuckBehavior::EvadeCombat; } auto behavior_name = EQ::constants::GetStuckBehaviorName(behavior_id); n.stuck_behavior = behavior_id; d = fmt::format( "{} is now using Stuck Behavior {}.", npc_id_string, ( !behavior_name.empty() ? fmt::format( "{} ({})", behavior_name, behavior_id ) : std::to_string(behavior_id) ) ); } else { c->Message( Chat::White, "Usage: #npcedit stuck_behavior [Stuck Behavior] - Sets an NPC's Stuck Behavior [0 = Run to Target, 1 = Warp to Target, 2 = Take No Action, 3 = Evade Combat]" ); return; } } else if (!strcasecmp(sep->arg[1], "model")) { if (sep->IsNumber(2)) { auto race_id = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.model = race_id; if (race_id) { d = fmt::format( "{} is now using a(n) {} ({}) as their race model.", npc_id_string, GetRaceIDName(race_id), race_id ); } else { d = fmt::format( "{} is no longer using a race model.", npc_id_string ); } } else { c->Message(Chat::White, "Usage: #npcedit model [Race ID] - Sets an NPC's Race Model"); return; } } else if (!strcasecmp(sep->arg[1], "flymode")) { if (sep->IsNumber(2)) { auto flymode_id = static_cast(Strings::ToInt(sep->arg[2])); if (flymode_id > GravityBehavior::LevitateWhileRunning) { flymode_id = GravityBehavior::LevitateWhileRunning; } auto flymode_name = EQ::constants::GetFlyModeName(flymode_id); n.flymode = flymode_id; d = fmt::format( "{} is now using Fly Mode {}.", npc_id_string, ( !flymode_name.empty() ? fmt::format( "{} ({})", flymode_name, flymode_id ) : std::to_string(flymode_id) ) ); } else { c->Message( Chat::White, "Usage: #npcedit flymode [Fly Mode] - Sets an NPC's Fly Mode [0 = Ground, 1 = Flying, 2 = Levitating, 3 = Water, 4 = Floating, 5 = Levitating While Running]" ); return; } } else if (!strcasecmp(sep->arg[1], "always_aggro")) { if (sep->IsNumber(2)) { auto always_aggro = static_cast(Strings::ToInt(sep->arg[2])); n.always_aggro = always_aggro; d = fmt::format( "{} will {} Always Aggro.", npc_id_string, always_aggro ? "now" : "no longer" ); } else { c->Message( Chat::White, "Usage: #npcedit always_aggro [Flag] - Sets an NPC's Always Aggro Flag [0 = Does not Always Aggro, 1 = Always Aggro]" ); return; } } else if (!strcasecmp(sep->arg[1], "exp_mod")) { if (sep->IsNumber(2)) { auto experience_modifier = Strings::ToInt(sep->arg[2]); n.exp_mod = experience_modifier; d = fmt::format( "{} now has an Experience Modifier of {}%%.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message( Chat::White, "Usage: #npcedit exp_mod [Modifier] - Sets an NPC's Experience Modifier [50 = 50%, 100 = 100%, 200 = 200%]" ); return; } } else if (!strcasecmp(sep->arg[1], "heroic_strikethrough")) { if (sep->IsNumber(2)) { auto heroic_strikethrough = Strings::ToInt(sep->arg[2]); n.heroic_strikethrough = heroic_strikethrough; d = fmt::format( "{} now has {} Heroic Strikethrough.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message( Chat::White, "Usage: #npcedit heroic_strikethrough [Heroic Strikethrough] - Sets an NPC's Heroic Strikethrough" ); return; } } else if (!strcasecmp(sep->arg[1], "faction_amount")) { if (sep->IsNumber(2)) { auto faction_amount = Strings::ToInt(sep->arg[2]); n.faction_amount = faction_amount; d = fmt::format( "{} now has a Faction Amount of {}.", npc_id_string, Strings::Commify(sep->arg[2]) ); } else { c->Message( Chat::White, "Usage: #npcedit faction_amount [Faction Amount] - Sets an NPC's Faction Amount" ); return; } } else if (!strcasecmp(sep->arg[1], "keeps_sold_items")) { if (sep->IsNumber(2)) { auto keeps_sold_items = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.keeps_sold_items = keeps_sold_items; d = fmt::format( "{} will {} Keep Sold Items.", npc_id_string, keeps_sold_items ? "now" : "no longer" ); } else { c->Message( Chat::White, "Usage: #npcedit keeps_sold_items [Flag] - Sets an NPC's Keeps Sold Items Flag [0 = False, 1 = True]" ); return; } } else if (!strcasecmp(sep->arg[1], "is_parcel_merchant")) { if (sep->IsNumber(2)) { const bool is_parcel_merchant = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.is_parcel_merchant = is_parcel_merchant; d = fmt::format( "{} will {} be a Parcel Merchant.", npc_id_string, is_parcel_merchant ? "now" : "no longer" ); } else { c->Message( Chat::White, "Usage: #npcedit is_parcel_merchant [Flag] - Sets an NPC's Parcel Merchant Flag [0 = False, 1 = True]" ); return; } } else if (!strcasecmp(sep->arg[1], "setanimation")) { if (sep->IsNumber(2)) { auto animation_id = Strings::ToUnsignedInt(sep->arg[2]); if (animation_id > EQ::constants::SpawnAnimations::Looting) { animation_id = EQ::constants::SpawnAnimations::Looting; } auto animation_name = EQ::constants::GetSpawnAnimationName(animation_id); d = fmt::format( "{} is now using Spawn Animation {} on Spawn Group ID {}.", npc_id_string, ( !animation_name.empty() ? fmt::format( "{} ({})", animation_name, animation_id ) : std::to_string(animation_id) ), Strings::Commify(std::to_string(c->GetTarget()->CastToNPC()->GetSpawnGroupId())) ); auto query = fmt::format( "UPDATE spawn2 SET animation = {} WHERE spawngroupID = {}", animation_id, c->GetTarget()->CastToNPC()->GetSpawnGroupId() ); content_db.QueryDatabase(query); c->GetTarget()->SetAppearance(EmuAppearance(animation_id)); } else { c->Message( Chat::White, "Usage: #npcedit setanimation [Animation ID] - Sets an NPC's Animation on Spawn (Stored in spawn2 table)" ); return; } } else if (!strcasecmp(sep->arg[1], "respawntime")) { if (sep->IsNumber(2)) { auto respawn_time = Strings::ToUnsignedInt(sep->arg[2]); if (respawn_time) { d = fmt::format( "{} now has a Respawn Timer of {} ({}) on Spawn Group ID {}.", npc_id_string, Strings::SecondsToTime(respawn_time), respawn_time, Strings::Commify(std::to_string(t->GetSpawnGroupId())) ); auto query = fmt::format( "UPDATE spawn2 SET respawntime = {} WHERE spawngroupID = {} AND version = {}", respawn_time, t->GetSpawnGroupId(), zone->GetInstanceVersion() ); content_db.QueryDatabase(query); } else { c->Message(Chat::White, "Respawn Timer must be greater than 0 seconds."); return; } } else { c->Message( Chat::White, "Usage: #npcedit respawntime [Respawn Time] - Sets an NPC's Respawn Timer in Seconds (Stored in spawn2 table)" ); return; } } else if (!strcasecmp(sep->arg[1], "set_grid")) { if (sep->IsNumber(2)) { const uint32 grid_id = Strings::ToUnsignedInt(sep->arg[2]); if (grid_id >= 0) { d = fmt::format( "{} now has a Grid ID of {} on Spawn Group ID {}.", npc_id_string, grid_id, Strings::Commify(std::to_string(t->GetSpawnGroupId())) ); auto query = fmt::format( "UPDATE spawn2 SET pathgrid = {} WHERE spawngroupID = {} AND version = {} AND zone = '{}'", grid_id, t->GetSpawnGroupId(), zone->GetInstanceVersion(), zone->GetShortName() ); content_db.QueryDatabase(query); } else { c->Message(Chat::White, "Grid ID must be greater than or equal to 0."); return; } } else { c->Message(Chat::White, "Usage: #npcedit set_grid [Grid ID] - Sets an NPC's Grid ID"); return; } } else if (!strcasecmp(sep->arg[1], "npc_tint_id")) { if (sep->IsNumber(2)) { const uint32 npc_tint_id = (Strings::ToUnsignedInt(sep->arg[2])); n.npc_tint_id = npc_tint_id; d = fmt::format( "Set NPCTintID {} for {}", npc_tint_id, npc_id_string ); } else { c->Message( Chat::White, "Usage: #npcedit npc_tint_id [id] - Sets an NPC's NPCTintID [0 - 78 for RoF2]" ); return; } } else { SendNPCEditSubCommands(c); return; } if (!NpcTypesRepository::UpdateOne(content_db, n)) { c->Message( Chat::White, fmt::format( "Failed to update {}.", npc_id_string ).c_str() ); } c->Message(Chat::White, d.c_str()); }