add BB-only NPC skins

This commit is contained in:
Martin Michelsen
2024-11-09 19:19:47 -08:00
parent a140cdbedb
commit 0279b20bb7
4 changed files with 64 additions and 14 deletions
+4 -1
View File
@@ -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:
+1 -1
View File
@@ -1484,7 +1484,7 @@ static void server_command_edit(shared_ptr<Client> 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;
+57 -11
View File
@@ -220,10 +220,56 @@ const unordered_map<string, uint8_t> name_to_lobby_type({
{"morgue", 0xFF},
});
const vector<string> npc_id_to_name({"ninja", "rico", "sonic", "knuckles", "tails", "flowen", "elly"});
const vector<string> npc_id_to_name({
"ninja",
"rico",
"sonic",
"knuckles",
"tails",
"flowen",
"elly",
"momoka",
"irene",
"guild",
"nurse",
});
const unordered_map<string, uint8_t> 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) {
+2 -1
View File
@@ -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);