From 0279b20bb73e7f2f61b9795c32ba08b197ea108c Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Sat, 9 Nov 2024 19:19:47 -0800 Subject: [PATCH] add BB-only NPC skins --- README.md | 5 +++- src/ChatCommands.cc | 2 +- src/StaticGameData.cc | 68 ++++++++++++++++++++++++++++++++++++------- src/StaticGameData.hh | 3 +- 4 files changed, 64 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 05070c23..53557cbb 100644 --- a/README.md +++ b/README.md @@ -643,7 +643,10 @@ Some subcommands are always available. They are: * `$edit namecolor AARRGGBB`: Set your name color (AARRGGBB specified in hex) * `$edit language L`: Set your language (Generally only useful on BB; values for L: J = Japanese, E = English, G = German, F = French, S = Spanish, B = Simplified Chinese, T = Traditional Chinese, K = Korean) * `$edit name NAME`: Set your character name -* `$edit npc NPC-NAME`: Set or remove an NPC skin on your character (NPC-NAME can be ninja, rico, sonic, knuckles, tails, flowen, elly, or none) +* `$edit npc NPC-NAME`: Set or remove an NPC skin on your character (use `none` to remove a skin). The NPC names are: + * On all versions except DCv1 and early prototypes: `ninja`, `rico`, `sonic`, `knuckles`, `tails` + * On GC, Xbox, and BB: `flowen`, `elly` + * On BB only: `momoka`, `irene`, `guild`, `nurse` * `$edit secid SECID-NAME`: Set your section ID (cheat mode is required for this unless your character is Level 1) The remaining subcommands are only available if cheat mode is enabled on the server. They are: diff --git a/src/ChatCommands.cc b/src/ChatCommands.cc index 1c8cf648..4f0ea175 100644 --- a/src/ChatCommands.cc +++ b/src/ChatCommands.cc @@ -1484,7 +1484,7 @@ static void server_command_edit(shared_ptr c, const std::string& args) { p->disp.visual.unused.clear(0); } } else { - uint8_t npc = npc_for_name(tokens.at(1)); + uint8_t npc = npc_for_name(tokens.at(1), c->version()); if (npc == 0xFF) { send_text_message(c, "$C6No such NPC"); return; diff --git a/src/StaticGameData.cc b/src/StaticGameData.cc index d002c0cd..9fc53035 100644 --- a/src/StaticGameData.cc +++ b/src/StaticGameData.cc @@ -220,10 +220,56 @@ const unordered_map name_to_lobby_type({ {"morgue", 0xFF}, }); -const vector npc_id_to_name({"ninja", "rico", "sonic", "knuckles", "tails", "flowen", "elly"}); +const vector npc_id_to_name({ + "ninja", + "rico", + "sonic", + "knuckles", + "tails", + "flowen", + "elly", + "momoka", + "irene", + "guild", + "nurse", +}); const unordered_map name_to_npc_id = { - {"ninja", 0}, {"rico", 1}, {"sonic", 2}, {"knuckles", 3}, {"tails", 4}, {"flowen", 5}, {"elly", 6}}; + {"ninja", 0}, + {"rico", 1}, + {"sonic", 2}, + {"knuckles", 3}, + {"tails", 4}, + {"flowen", 5}, + {"elly", 6}, + {"momoka", 7}, + {"irene", 8}, + {"guild", 9}, + {"nurse", 10}, +}; + +bool npc_valid_for_version(uint8_t npc, Version version) { + switch (version) { + case Version::DC_NTE: + case Version::DC_V1_11_2000_PROTOTYPE: + case Version::DC_V1: + return false; + case Version::DC_V2: + case Version::PC_NTE: + case Version::PC_V2: + return (npc < 5); + case Version::GC_NTE: + case Version::GC_V3: + case Version::GC_EP3_NTE: + case Version::GC_EP3: + case Version::XB_V3: + return (npc < 7); + case Version::BB_V4: + return (npc < 11); + default: + return false; + } +} const char* abbreviation_for_section_id(uint8_t section_id) { if (section_id < section_id_to_abbreviation.size()) { @@ -317,20 +363,20 @@ const string& name_for_npc(uint8_t npc) { } } -uint8_t npc_for_name(const string& name) { +uint8_t npc_for_name(const string& name, Version version) { + uint8_t npc_id = 0xFF; try { - return name_to_npc_id.at(name); + npc_id = name_to_npc_id.at(name); } catch (const out_of_range&) { } - try { - uint64_t x = stoul(name); - if (x < npc_id_to_name.size()) { - return x; + if (npc_id == 0xFF) { + try { + npc_id = stoul(name); + } catch (const invalid_argument&) { + } catch (const out_of_range&) { } - } catch (const invalid_argument&) { - } catch (const out_of_range&) { } - return 0xFF; + return npc_valid_for_version(npc_id, version) ? npc_id : 0xFF; } const char* name_for_char_class(uint8_t cls) { diff --git a/src/StaticGameData.hh b/src/StaticGameData.hh index 44524ac8..d5b472f4 100644 --- a/src/StaticGameData.hh +++ b/src/StaticGameData.hh @@ -50,7 +50,8 @@ const std::string& name_for_lobby_type(uint8_t type); uint8_t lobby_type_for_name(const std::string& name); const std::string& name_for_npc(uint8_t npc); -uint8_t npc_for_name(const std::string& name); +uint8_t npc_for_name(const std::string& name, Version version); +bool npc_valid_for_version(uint8_t npc, Version version); const char* name_for_char_class(uint8_t cls); const char* abbreviation_for_char_class(uint8_t cls);