From f8162d442aac41f04733ea0b58cbb3c54948296e Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Sun, 28 Jul 2024 12:42:13 -0700 Subject: [PATCH] add material reset to $edit --- README.md | 34 +++++++++++++++++++++++++++++++++- src/ChatCommands.cc | 39 +++++++++++++++++++++++++++++++++++---- src/SaveFileFormats.cc | 22 +++++++++++++++++----- src/SaveFileFormats.hh | 1 + 4 files changed, 86 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 790e5630..6036d7ee 100644 --- a/README.md +++ b/README.md @@ -553,7 +553,7 @@ Some commands only work on the game server and not on the proxy server. The chat * `$savechar `: Save your current character data on the server in the specified slot. See the "Server-side saves" section for more details. * `$loadchar `: Save your current character data on the server in the specified slot. See the "Server-side saves" section for more details. * `$bbchar `: Save your current character data on the server in a different account's BB character slots. See the "Server-side saves" section for more details. - * `$edit `: Modify your character data. If you are on V3 (GameCube/Xbox), this command does nothing. If you are on V1 or V2 (DC or PC, not BB), your changes will be undone if you join a game - to save your changes, disconnect from the lobby. If cheats are allowed on the server, `` can be any of `atp`, `mst`, `evp`, `hp`, `dfp`, `ata`, `lck`, `meseta`, `exp`, `level`, `namecolor`, `secid`, `name`, `language`, `npc`, or `tech`. If cheats are not allowed, only `namecolor`, `name`, `language`, and `npc` can be used. Changing your character's language is only useful on BB; to do so, use a single-character language code (e.g. to switch your character to English, use `$edit language E`; for Japanese, use `$edit language J`). + * `$edit `: Modify your character data. See "Using $edit" below for details. * Blue Burst player commands (game server only) * `$bank [number]`: Switch your current bank, so you can access your other character's banks (if `number` is 1-4) or your shared account bank (if `number` is 0). If `number` is not given, switch back to your current character's bank. @@ -599,6 +599,38 @@ Some commands only work on the game server and not on the proxy server. The chat * `$kick `: Disconnect a player. The identifier may be the player's name or Guild Card number. * `$ban `: Ban a player. The duration should be of the form `10m` (minutes), `10h` (hours), `10d` (days), `10w` (weeks), `10M` (months), or `10y` (years). (Numbers other than 10 may be used, of course.) As with `$kick`, the identifier may be the player's name or Guild Card number. +### Using $edit + +The $edit command modifies your character data. This command doesn't work on V3 (GameCube/Xbox). If you are on V1 or V2 (DC or PC, not BB), your changes will be undone if you join a game - to save your changes, disconnect from the lobby. + +Some subcommands are always available. They are: +* `$edit mat reset power`: Clear your usage of power materials (BB only) +* `$edit mat reset mind`: Clear your usage of mind materials (BB only) +* `$edit mat reset evade`: Clear your usage of evade materials (BB only) +* `$edit mat reset def`: Clear your usage of def materials (BB only) +* `$edit mat reset luck`: Clear your usage of luck materials (BB only) +* `$edit mat reset hp`: Clear your usage of hp materials (BB only) +* `$edit mat reset tp`: Clear your usage of tp materials (BB only) +* `$edit mat reset all`: Clear your usage of all materials (BB only) +* `$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) + +The remaining subcommands are only available if cheat mode is enabled on the server. They are: +* `$edit atp N`: Set your ATP to N until stats are updated (e.g. by leveling up) +* `$edit mst N`: Set your MST to N until stats are updated +* `$edit evp N`: Set your EVP to N until stats are updated +* `$edit dfp N`: Set your DFP to N until stats are updated +* `$edit ata N`: Set your ATA to N until stats are updated +* `$edit lck N`: Set your LCK to N until stats are updated +* `$edit hp N`: Set your MST to N until stats are updated +* `$edit meseta N`: Set the amount of Meseta in your inventory +* `$edit exp N`: Set your total amount of EXP (does not affect level) +* `$edit level N`: Set your current level (recomputes stats, but does not affect EXP) +* `$edit secid SECID-NAME`: Set your section ID +* `$edit tech TECH-NAME LEVEL`: Set the level of one of your techniques + # Non-server features newserv has many CLI options, which can be used to access functionality other than the game and proxy server. Run `newserv help` to see a full list of the options and how to use each one. diff --git a/src/ChatCommands.cc b/src/ChatCommands.cc index ea2a4e6e..df5a1569 100644 --- a/src/ChatCommands.cc +++ b/src/ChatCommands.cc @@ -1310,6 +1310,8 @@ static void server_command_edit(shared_ptr c, const std::string& args) { string encoded_args = phosg::tolower(args); vector tokens = phosg::split(encoded_args, ' '); + using MatType = PSOBBCharacterFile::MaterialType; + try { auto p = c->character(); if (tokens.at(0) == "atp" && cheats_allowed) { @@ -1331,10 +1333,39 @@ static void server_command_edit(shared_ptr c, const std::string& args) { } else if (tokens.at(0) == "exp" && cheats_allowed) { p->disp.stats.experience = stoul(tokens.at(1)); } else if (tokens.at(0) == "level" && cheats_allowed) { - uint32_t level = stoul(tokens.at(1)) - 1; - auto level_table = s->level_table(c->version()); - level_table->reset_to_base(p->disp.stats, p->disp.visual.char_class); - level_table->advance_to_level(p->disp.stats, level, p->disp.visual.char_class); + p->disp.stats.level = stoul(tokens.at(1)) - 1; + p->recompute_stats(s->level_table(c->version())); + } else if (((tokens.at(0) == "material") || (tokens.at(0) == "mat")) && !is_v1_or_v2(c->version())) { + if (tokens.at(1) == "reset") { + const auto& which = tokens.at(2); + if (which == "power") { + p->set_material_usage(MatType::POWER, 0); + } else if (which == "mind") { + p->set_material_usage(MatType::MIND, 0); + } else if (which == "evade") { + p->set_material_usage(MatType::EVADE, 0); + } else if (which == "def") { + p->set_material_usage(MatType::DEF, 0); + } else if (which == "luck") { + p->set_material_usage(MatType::LUCK, 0); + } else if (which == "hp") { + p->set_material_usage(MatType::HP, 0); + } else if (which == "tp") { + p->set_material_usage(MatType::TP, 0); + } else if (which == "all") { + p->set_material_usage(MatType::POWER, 0); + p->set_material_usage(MatType::MIND, 0); + p->set_material_usage(MatType::EVADE, 0); + p->set_material_usage(MatType::DEF, 0); + p->set_material_usage(MatType::LUCK, 0); + p->set_material_usage(MatType::HP, 0); + p->set_material_usage(MatType::TP, 0); + } + } else { + send_text_message(c, "$C6Invalid subcommand"); + return; + } + p->recompute_stats(s->level_table(c->version())); } else if (tokens.at(0) == "namecolor") { uint32_t new_color; sscanf(tokens.at(1).c_str(), "%8X", &new_color); diff --git a/src/SaveFileFormats.cc b/src/SaveFileFormats.cc index 6c065e59..5e5342e9 100644 --- a/src/SaveFileFormats.cc +++ b/src/SaveFileFormats.cc @@ -1124,11 +1124,23 @@ void PSOBBCharacterFile::import_tethealla_material_usage(std::shared_ptrset_material_usage(PSOBBCharacterFile::MaterialType::POWER, pow); - this->set_material_usage(PSOBBCharacterFile::MaterialType::MIND, mind); - this->set_material_usage(PSOBBCharacterFile::MaterialType::EVADE, evade); - this->set_material_usage(PSOBBCharacterFile::MaterialType::DEF, def); - this->set_material_usage(PSOBBCharacterFile::MaterialType::LUCK, luck); + this->set_material_usage(MaterialType::POWER, pow); + this->set_material_usage(MaterialType::MIND, mind); + this->set_material_usage(MaterialType::EVADE, evade); + this->set_material_usage(MaterialType::DEF, def); + this->set_material_usage(MaterialType::LUCK, luck); +} + +void PSOBBCharacterFile::recompute_stats(std::shared_ptr level_table) { + uint32_t level = this->disp.stats.level; + level_table->reset_to_base(this->disp.stats, this->disp.visual.char_class); + level_table->advance_to_level(this->disp.stats, level, this->disp.visual.char_class); + this->disp.stats.char_stats.atp += (this->get_material_usage(MaterialType::POWER) * 2); + this->disp.stats.char_stats.mst += (this->get_material_usage(MaterialType::MIND) * 2); + this->disp.stats.char_stats.evp += (this->get_material_usage(MaterialType::EVADE) * 2); + this->disp.stats.char_stats.dfp += (this->get_material_usage(MaterialType::DEF) * 2); + this->disp.stats.char_stats.lck += (this->get_material_usage(MaterialType::LUCK) * 2); + this->disp.stats.char_stats.hp += (this->get_material_usage(MaterialType::HP) * 2); } static uint16_t crc16(const void* data, size_t size) { diff --git a/src/SaveFileFormats.hh b/src/SaveFileFormats.hh index 8ab58aa2..24249b61 100644 --- a/src/SaveFileFormats.hh +++ b/src/SaveFileFormats.hh @@ -754,6 +754,7 @@ struct PSOBBCharacterFile { void set_material_usage(MaterialType which, uint8_t usage); void clear_all_material_usage(); void import_tethealla_material_usage(std::shared_ptr level_table); + void recompute_stats(std::shared_ptr level_table); } __packed_ws__(PSOBBCharacterFile, 0x2EA4); ////////////////////////////////////////////////////////////////////////////////