diff --git a/src/ChatCommands.cc b/src/ChatCommands.cc index 4593f7bb..78016ea6 100644 --- a/src/ChatCommands.cc +++ b/src/ChatCommands.cc @@ -1224,6 +1224,41 @@ static void proxy_command_item( } } +static void server_command_enable_ep3_battle_debug_menu( + shared_ptr, shared_ptr l, shared_ptr c, const std::u16string& args) { + if (!c->options.debug) { + send_text_message(l, u"$C6This command can only\nbe run in debug mode\n(run %sdebug first)"); + return; + } + + check_is_game(l, true); + check_is_ep3(c, true); + if (l->episode != Episode::EP3) { + throw logic_error("non-Ep3 client in Ep3 game"); + } + auto base = l->ep3_server_base; + if (!base) { + send_text_message(l, u"$C6Episode 3 server\nis not initialized"); + return; + } + auto server = base->server; + if (!server) { + send_text_message(l, u"$C6Episode 3 server\nis not initialized"); + return; + } + + if (!args.empty()) { + server->override_environment_number = stoul(encode_sjis(args), nullptr, 16); + send_text_message_printf(l, "$C6Override environment\nnumber set to %02hhX", server->override_environment_number); + } else if (server->override_environment_number == 0xFF) { + server->override_environment_number = 0x1A; + send_text_message(l, u"$C6Battle setup debug\nmenu enabled"); + } else { + server->override_environment_number = 0xFF; + send_text_message(l, u"$C6Battle setup debug\nmenu disabled"); + } +} + //////////////////////////////////////////////////////////////////////////////// typedef void (*server_handler_t)(shared_ptr s, shared_ptr l, @@ -1256,6 +1291,7 @@ static const unordered_map chat_commands({ {u"$i", {server_command_item, proxy_command_item}}, {u"$kick", {server_command_kick, nullptr}}, {u"$li", {server_command_lobby_info, proxy_command_lobby_info}}, + {u"$ep3battledebug", {server_command_enable_ep3_battle_debug_menu, nullptr}}, {u"$maxlevel", {server_command_max_level, nullptr}}, {u"$minlevel", {server_command_min_level, nullptr}}, {u"$next", {server_command_next, proxy_command_next}}, diff --git a/src/Episode3/DataIndexes.hh b/src/Episode3/DataIndexes.hh index 1298f073..e9ee7b4d 100644 --- a/src/Episode3/DataIndexes.hh +++ b/src/Episode3/DataIndexes.hh @@ -794,27 +794,38 @@ struct MapDefinition { // .mnmd format; also the format of (decompressed) quests // - The color of the battle tile outlines (probably) // - The preview image to show in the upper-left corner in the map select menu // The environment numbers are: - // 00 - Unguis Lapis - // 01 - Nebula Montana (1) - // 02 - Lupus Silva (1) - // 03 - Lupus Silva (2) - // 04 - Molae Venti - // 05 - Nebula Montana (2) - // 06 - Tener Sinus - // 07 - Mortis Fons - // 08 - Morgue (destroyed) - // 09 - Tower of Caelum - // 0A = ??? (referred to as "^mapname"; crashes) - // 0B = Cyber - // 0C = Morgue (not destroyed) - // 0D = (Castor/Pollux map) - // 0E - Dolor Odor - // 0F = Ravum Aedes Sacra - // 10 - (Amplum Umbla map) - // 11 - Via Tubus - // 12 = Morgue (same as 08?) - // 13 = ??? (crashes) - // Environment numbers beyond 13 are not used in any known quests or maps. + // 00 = Unguis Lapis ("BONE") + // 01 = Nebula Montana 1 ("ALPINE") + // 02 = Lupus Silva 1 ("FOREST 2-1") + // 03 = Lupus Silva 2 ("FOREST 2-2") + // 04 = Molae Venti ("WINDMILL") + // 05 = Nebula Montana 2 ("ALPINE 2") + // 06 = Tener Sinus ("COAST") + // 07 = Mortis Fons ("GEYSER") + // 08 = Morgue (destroyed) ("BROKEN MORGUE") + // 09 = Tower of Caelum ("TOWER") + // 0A = ??? (crashes) ("MAPMAN") + // 0B = Cyber ("CYBER") + // 0C = Morgue (not destroyed) ("BOSS") + // 0D = (Castor/Pollux map) ("REAL BOSS") + // 0E = Dolor Odor ("STOMACH") + // 0F = Ravum Aedes Sacra ("SACRAMENT") + // 10 = (Amplum Umbla map) ("RUIN") + // 11 = Via Tubus ("METRO") + // 12 = Morgue ("NORMAL MORGUE") + // Environment numbers above 12 are replaced with 0B (Cyber) if specified in + // a map definition. The following environment numbers are used internally by + // the game for various functions, but cannot be specified in MapDefinitions: + // 13 = TCardDemo (sends CAx14 and CAx13, then softlocks at black screen) + // 14 = crashes + // 15 = crashes + // 16 = Battle results screen + // 17 = Game Over screen (if used online, client disconnects without saving) + // 18 = Episode 3 staff roll + // 19 = View Battle waiting room + // 1A = TCard00_Select (debug battle setup menu) + // 1B = nothing (softlocks at black screen) + // TCard00_Select is accessible on newserv with the $ep3battledebug command. /* 000A */ uint8_t environment_number; // All alt_maps fields (including the floats) past num_alt_maps are filled in diff --git a/src/Episode3/MapState.cc b/src/Episode3/MapState.cc index ce37b38b..d48646e2 100644 --- a/src/Episode3/MapState.cc +++ b/src/Episode3/MapState.cc @@ -38,7 +38,7 @@ void MapAndRulesState::clear() { this->map.clear(); this->num_players = 0; this->unused1 = 0; - this->unused_by_server = 0; + this->environment_number = 0; this->num_players_per_team = 0; this->num_team0_players = 0; this->unused2 = 0; diff --git a/src/Episode3/MapState.hh b/src/Episode3/MapState.hh index 1c78f7aa..8ffcb3ee 100644 --- a/src/Episode3/MapState.hh +++ b/src/Episode3/MapState.hh @@ -25,7 +25,7 @@ struct MapAndRulesState { MapState map; uint8_t num_players; uint8_t unused1; - uint8_t unused_by_server; + uint8_t environment_number; uint8_t num_players_per_team; uint8_t num_team0_players; uint8_t unused2; diff --git a/src/Episode3/Server.cc b/src/Episode3/Server.cc index 80a47b5c..5b7de22a 100644 --- a/src/Episode3/Server.cc +++ b/src/Episode3/Server.cc @@ -66,6 +66,7 @@ void ServerBase::recreate_server() { Server::Server(shared_ptr base) : w_base(base), tournament_match_result_sent(false), + override_environment_number(0xFF), battle_finished(false), battle_in_progress(false), round_num(1), @@ -1841,6 +1842,11 @@ void Server::handle_6xB3x13_update_map_during_setup(const string& data) { (this->registration_phase != RegistrationPhase::BATTLE_STARTED)) { *b->map_and_rules1 = in_cmd.map_and_rules_state; *b->map_and_rules2 = in_cmd.map_and_rules_state; + if (this->override_environment_number != 0xFF) { + b->map_and_rules1->environment_number = this->override_environment_number; + b->map_and_rules2->environment_number = this->override_environment_number; + this->override_environment_number = 0xFF; + } b->overlay_state = in_cmd.overlay_state; if (b->behavior_flags & BehaviorFlag::DISABLE_TIME_LIMITS) { b->map_and_rules1->rules.overall_time_limit = 0; diff --git a/src/Episode3/Server.hh b/src/Episode3/Server.hh index dfcd9d4b..d43f6ea9 100644 --- a/src/Episode3/Server.hh +++ b/src/Episode3/Server.hh @@ -247,6 +247,7 @@ private: public: bool tournament_match_result_sent; // Not part of original implementation + uint8_t override_environment_number; // Not part of original implementation uint32_t battle_finished; uint32_t battle_in_progress;