diff --git a/README.md b/README.md index 13b75f40..de7248f7 100644 --- a/README.md +++ b/README.md @@ -275,7 +275,7 @@ Some commands only work on the game server and not on the proxy server. The chat * `$arrow `: Changes your lobby arrow color. * `$secid `: Sets your override section ID. After running this command, any games you create will use your override section ID for rare drops instead of your character's actual section ID. To revert to your actual section id, run `$secid` with no name after it. On the proxy server, this will not work if the remote server controls item drops (e.g. on BB, or on Schtserv with server drops enabled). * `$rand `: Sets your override random seed (specified as a 32-bit hex value). This will make any games you create use the given seed for rare enemies. This also makes item drops deterministic in Blue Burst games hosted by newserv. On the proxy server, this command can cause desyncs with other players in the same game, since they will not see the overridden random seed. To remove the override, run `$rand` with no arguments. - * `$exit`: If you're in a lobby, sends you to the main menu (which ends your proxy session, if you're in one). If you're in an Episode 3 game or spectator team, sends you to the lobby (but does not end your proxy session if you're in one). + * `$exit`: If you're in a lobby, sends you to the main menu (which ends your proxy session, if you're in one). If you're in a game or spectator team, sends you to the lobby (but does not end your proxy session if you're in one). Does nothing if you're in a non-Episode 3 game and no quest is in progress. * `$patch `: Run a patch on your client. `` must exactly match the name of a patch on the server. * Blue Burst player commands (game server only) diff --git a/src/ChatCommands.cc b/src/ChatCommands.cc index c4a42142..ef996c6e 100644 --- a/src/ChatCommands.cc +++ b/src/ChatCommands.cc @@ -297,6 +297,9 @@ static void server_command_exit(shared_ptr s, shared_ptr l, if (l->is_game()) { if (c->flags & Client::Flag::IS_EPISODE_3) { c->channel.send(0xED, 0x00); + } else if (l->flags & (Lobby::Flag::QUEST_IN_PROGRESS | Lobby::Flag::JOINABLE_QUEST_IN_PROGRESS)) { + G_UnusedHeader cmd = {0x73, 0x01, 0x0000}; + c->channel.send(0x60, 0x00, cmd); } else { send_text_message(c, u"$C6You must return to\nthe lobby first"); } @@ -318,6 +321,9 @@ static void proxy_command_exit(shared_ptr, if (session.is_in_game) { if (session.newserv_client_config.cfg.flags & Client::Flag::IS_EPISODE_3) { session.client_channel.send(0xED, 0x00); + } else if (session.is_in_quest) { + G_UnusedHeader cmd = {0x73, 0x01, 0x0000}; + session.client_channel.send(0x60, 0x00, cmd); } else { send_text_message(session.client_channel, u"$C6You must return to\nthe lobby first"); } diff --git a/src/ProxyCommands.cc b/src/ProxyCommands.cc index 2051974f..3e105998 100644 --- a/src/ProxyCommands.cc +++ b/src/ProxyCommands.cc @@ -1281,6 +1281,7 @@ static HandlerResult S_65_67_68_EB(shared_ptr, if (command == 0x67) { session.clear_lobby_players(12); session.is_in_game = false; + session.is_in_quest = false; session.area = 0x0F; // This command can cause the client to no longer send D6 responses when @@ -1360,6 +1361,7 @@ static HandlerResult S_64(shared_ptr, session.clear_lobby_players(4); session.area = 0; session.is_in_game = true; + session.is_in_quest = false; bool modified = false; @@ -1412,6 +1414,7 @@ static HandlerResult S_E8(shared_ptr, session.clear_lobby_players(12); session.area = 0; session.is_in_game = true; + session.is_in_quest = false; bool modified = false; @@ -1457,6 +1460,16 @@ static HandlerResult S_E8(shared_ptr, return modified ? HandlerResult::Type::MODIFIED : HandlerResult::Type::FORWARD; } +static HandlerResult S_AC(shared_ptr, + ProxyServer::LinkedSession& session, uint16_t, uint32_t, string&) { + if (!session.is_in_game) { + return HandlerResult::Type::SUPPRESS; + } else { + session.is_in_quest = true; + return HandlerResult::Type::FORWARD; + } +} + static HandlerResult S_66_69_E9(shared_ptr, ProxyServer::LinkedSession& session, uint16_t, uint32_t, string& data) { const auto& cmd = check_size_t(data); @@ -1481,6 +1494,7 @@ static HandlerResult C_98(shared_ptr s, ProxyServer::LinkedSession& session, uint16_t command, uint32_t flag, string& data) { session.area = 0x0F; session.is_in_game = false; + session.is_in_quest = false; if (session.version == GameVersion::GC || session.version == GameVersion::XB || session.version == GameVersion::BB) { @@ -1852,7 +1866,7 @@ static on_command_t handlers[0x100][6][2] = { /* A9 */ {{S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}}, /* AA */ {{S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}}, /* AB */ {{S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {nullptr, nullptr}, {nullptr, nullptr}, {nullptr, nullptr}}, -/* AC */ {{S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {nullptr, nullptr}, {nullptr, nullptr}, {nullptr, nullptr}}, +/* AC */ {{S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {S_AC, nullptr}, {S_AC, nullptr}, {S_AC, nullptr}}, /* AD */ {{S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}}, /* AE */ {{S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}}, /* AF */ {{S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}}, diff --git a/src/ProxyServer.cc b/src/ProxyServer.cc index 651ddf60..bb84f977 100644 --- a/src/ProxyServer.cc +++ b/src/ProxyServer.cc @@ -473,7 +473,8 @@ ProxyServer::LinkedSession::LinkedSession( area(0), x(0.0), z(0.0), - is_in_game(false) { + is_in_game(false), + is_in_quest(false) { this->last_switch_enabled_command.header.subcommand = 0; memset(this->prev_server_command_bytes, 0, sizeof(this->prev_server_command_bytes)); } diff --git a/src/ProxyServer.hh b/src/ProxyServer.hh index 5fdaa2af..637a6e0b 100644 --- a/src/ProxyServer.hh +++ b/src/ProxyServer.hh @@ -89,6 +89,7 @@ public: float x; float z; bool is_in_game; + bool is_in_quest; std::shared_ptr detector_crypt;