From 57179513b817a46e39d772a6d75e128dd433f10d Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Wed, 11 May 2022 00:50:40 -0700 Subject: [PATCH] implement quest stats command --- src/CommandFormats.hh | 26 ++++++++++++++++++++++---- src/ReceiveCommands.cc | 25 +++++++++++++++++++++---- 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/CommandFormats.hh b/src/CommandFormats.hh index 34b3cc43..66f86565 100644 --- a/src/CommandFormats.hh +++ b/src/CommandFormats.hh @@ -1096,11 +1096,29 @@ struct S_QuestMenuEntry_BB_A2_A4 { // download quest menu is closed, either by downloading a quest or canceling, // the client sends A0 instead. -// AA: Invalid command -// TODO: Sylverant defines this as quest stats, specifically used during Maximum -// Attack 2. Verify this and document if needed. +// AA (C->S): Update quest statistics +// This command is used in Maximum Attack 2, but its format is unlikely to be +// specific to that quest. The structure here represents the only instance I've +// seen so far. +// The server will respond with an AB command. -// AB (S->C): Unknown (BB) +struct C_UpdateQuestStatistics_AA { + le_uint32_t quest_internal_id; + le_uint16_t request_token; + le_uint16_t unknown_a1; + le_uint32_t unknown_a2; + le_uint32_t kill_count; + le_uint32_t time_taken; // in seconds + parray unknown_a3; +}; + +// AB (S->C): Confirm update quest statistics + +struct S_ConfirmUpdateQuestStatistics_AB { + le_uint32_t unknown_a1; // 0 + le_uint16_t request_token; // Should match token sent in AA command + le_uint16_t unknown_a2; // Schtserv always sends 0xBFFF here +}; // AC: Quest barrier // No arguments diff --git a/src/ReceiveCommands.cc b/src/ReceiveCommands.cc index 61eaf455..8a2d4d72 100644 --- a/src/ReceiveCommands.cc +++ b/src/ReceiveCommands.cc @@ -1025,6 +1025,23 @@ void process_quest_ready(shared_ptr s, shared_ptr c, } } +void process_update_quest_statistics(shared_ptr s, + shared_ptr c, uint16_t, uint32_t, const string& data) { // AA + const auto& cmd = check_size_t(data); + + auto l = s->find_lobby(c->lobby_id); + if (!l || !l->is_game() || !l->loading_quest.get() || + (l->loading_quest->internal_id != cmd.quest_internal_id)) { + return; + } + + S_ConfirmUpdateQuestStatistics_AB response; + response.unknown_a1 = 0; + response.request_token = cmd.request_token; + response.unknown_a2 = 0xBFFF; + send_command_t(c, 0xAB, 0x00, response); +} + void process_gba_file_request(shared_ptr, shared_ptr c, uint16_t, uint32_t, const string& data) { // D7 string filename(data); @@ -1835,7 +1852,7 @@ static process_command_t dc_handlers[0x100] = { // A0 process_change_ship, process_change_block, process_quest_list_request, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, process_ignored_command, nullptr, nullptr, + nullptr, process_ignored_command, process_update_quest_statistics, nullptr, process_quest_ready, nullptr, nullptr, nullptr, // B0 @@ -1918,7 +1935,7 @@ static process_command_t pc_handlers[0x100] = { // A0 process_change_ship, process_change_block, process_quest_list_request, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, process_ignored_command, nullptr, nullptr, + nullptr, process_ignored_command, process_update_quest_statistics, nullptr, process_quest_ready, nullptr, nullptr, nullptr, // B0 @@ -2002,7 +2019,7 @@ static process_command_t gc_handlers[0x100] = { // A0 process_change_ship, process_change_block, process_quest_list_request, nullptr, nullptr, nullptr, process_ignored_command, process_ignored_command, - nullptr, process_ignored_command, nullptr, nullptr, + nullptr, process_ignored_command, process_update_quest_statistics, nullptr, process_quest_ready, nullptr, nullptr, nullptr, // B0 @@ -2091,7 +2108,7 @@ static process_command_t bb_handlers[0x100] = { // A0 process_change_ship, process_change_block, process_quest_list_request, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, process_ignored_command, nullptr, nullptr, + nullptr, process_ignored_command, process_update_quest_statistics, nullptr, process_quest_ready, nullptr, nullptr, nullptr, // B0