implement 6xE1

This commit is contained in:
Martin Michelsen
2023-11-16 15:43:53 -08:00
parent c84d4b134f
commit 27608d9c11
7 changed files with 92 additions and 28 deletions
+15 -14
View File
@@ -858,8 +858,9 @@ struct SC_GameGuardCheck_BB_0022 {
struct S_ExchangeSecretLotteryTicketResult_BB_24 {
// These fields map to unknown_a1 and unknown_a2 in the 6xDE command (but
// their order is swapped here).
le_uint16_t unknown_a2 = 0;
le_uint16_t unknown_a1 = 0;
le_uint16_t function_id = 0;
uint8_t start_index = 0;
uint8_t unused = 0;
parray<le_uint32_t, 8> unknown_a3;
} __packed__;
@@ -867,7 +868,7 @@ struct S_ExchangeSecretLotteryTicketResult_BB_24 {
// Sent in response to a 6xE1 command from the client.
struct S_GallonPlanResult_BB_25 {
le_uint16_t unknown_a1 = 0;
le_uint16_t function_id = 0;
uint8_t offset1 = 0;
uint8_t offset2 = 0;
uint8_t value1 = 0;
@@ -5695,7 +5696,7 @@ struct G_ExchangeItemInQuest_BB_6xDB {
G_ClientIDHeader header;
le_uint32_t unknown_a1 = 0;
le_uint32_t item_id = 0;
le_uint32_t unknown_a3 = 0;
le_uint32_t amount = 0;
} __packed__;
// 6xDC: Saint-Million boss actions (BB)
@@ -5719,9 +5720,9 @@ struct G_SetEXPMultiplier_BB_6xDD {
struct G_ExchangeSecretLotteryTicket_BB_6xDE {
G_ClientIDHeader header;
uint8_t unknown_a1 = 0;
uint8_t unknown_a2 = 0;
le_uint16_t unknown_a3 = 0;
uint8_t index = 0;
uint8_t function_id1 = 0;
le_uint16_t function_id2 = 0;
} __packed__;
// 6xDF: Exchange Photon Crystals (BB; handled by server)
@@ -5744,17 +5745,17 @@ struct G_RequestItemDropFromQuest_BB_6xE0 {
le_float z = 0.0f; // argsA[2]
} __packed__;
// 6xE1: Gallon's Plan quest (BB; handled by server)
// 6xE1: Exchange Photon Tickets (BB; handled by server)
// The client sends this when it executes an F95F quest opcode.
struct G_GallonsPlanQuestActions_BB_6xE1 {
struct G_ExchangePhotonTickets_BB_6xE1 {
G_ClientIDHeader header;
uint8_t unknown_a1 = 0;
uint8_t unknown_a2 = 0;
uint8_t unknown_a3 = 0;
uint8_t unknown_a1 = 0; // argsA[0]
uint8_t unknown_a2 = 0; // argsA[1]
uint8_t result_index = 0; // argsA[2]
uint8_t unused = 0;
le_uint16_t unknown_a4 = 0;
le_uint16_t unknown_a5 = 0;
le_uint16_t function_id1 = 0; // argsA[3]
le_uint16_t unknown_a5 = 0; // argsA[4]
} __packed__;
// 6xE2: Coren actions (BB)
+43 -4
View File
@@ -2344,7 +2344,7 @@ static void on_secret_lottery_ticket_exchange_bb(shared_ptr<Client> c, uint8_t,
exchange_cmd.header.client_id = c->lobby_client_id;
exchange_cmd.unknown_a1 = 1;
exchange_cmd.item_id = slt_item_id;
exchange_cmd.unknown_a3 = 1;
exchange_cmd.amount = 1;
send_command_t(c, 0x60, 0x00, exchange_cmd);
send_destroy_item(c, slt_item_id, 1);
@@ -2358,8 +2358,8 @@ static void on_secret_lottery_ticket_exchange_bb(shared_ptr<Client> c, uint8_t,
}
S_ExchangeSecretLotteryTicketResult_BB_24 out_cmd;
out_cmd.unknown_a1 = cmd.unknown_a1;
out_cmd.unknown_a2 = cmd.unknown_a2;
out_cmd.start_index = cmd.index;
out_cmd.function_id = cmd.function_id1;
if (s->secret_lottery_results.empty()) {
out_cmd.unknown_a3.clear(0);
} else if (s->secret_lottery_results.size() == 1) {
@@ -2415,6 +2415,45 @@ static void on_quest_F95E_result_bb(shared_ptr<Client> c, uint8_t, uint8_t, cons
}
}
static void on_quest_F95F_result_bb(shared_ptr<Client> c, uint8_t, uint8_t, const void* data, size_t size) {
auto l = c->require_lobby();
if (l->is_game() && (l->base_version == GameVersion::BB) && l->check_flag(Lobby::Flag::QUEST_IN_PROGRESS)) {
const auto& cmd = check_size_t<G_ExchangePhotonTickets_BB_6xE1>(data, size);
auto s = c->require_server_state();
auto p = c->game_data.character();
const auto& result = s->quest_F95F_results.at(cmd.result_index);
if (result.second.empty()) {
throw runtime_error("invalid result index");
}
size_t index = p->inventory.find_item_by_primary_identifier(0x031004); // Photon Ticket
auto ticket_item = p->remove_item(p->inventory.items[index].data.id, result.first, false);
// TODO: Shouldn't we send a 6x29 here? Check if this causes desync in an
// actual game
G_ExchangeItemInQuest_BB_6xDB cmd_6xDB;
cmd_6xDB.header = {0xDB, 0x04, c->lobby_client_id};
cmd_6xDB.unknown_a1 = 1;
cmd_6xDB.item_id = ticket_item.id;
cmd_6xDB.amount = result.first;
send_command_t(c, 0x60, 0x00, cmd_6xDB);
ItemData new_item = result.second;
new_item.id = l->generate_item_id(c->lobby_client_id);
p->add_item(new_item);
send_create_inventory_item(c, new_item);
S_GallonPlanResult_BB_25 out_cmd;
out_cmd.function_id = cmd.function_id1;
out_cmd.offset1 = 0x3C;
out_cmd.offset2 = 0x08;
out_cmd.value1 = 0x00;
out_cmd.value2 = cmd.result_index;
send_command_t(c, 0x25, 0x00, out_cmd);
}
}
static void on_momoka_item_exchange_bb(shared_ptr<Client> c, uint8_t, uint8_t, const void* data, size_t size) {
auto l = c->require_lobby();
if (l->is_game() && (l->base_version == GameVersion::BB) && l->check_flag(Lobby::Flag::QUEST_IN_PROGRESS)) {
@@ -2733,7 +2772,7 @@ subcommand_handler_t subcommand_handlers[0x100] = {
/* 6xDE */ on_secret_lottery_ticket_exchange_bb,
/* 6xDF */ on_photon_crystal_exchange_bb,
/* 6xE0 */ on_quest_F95E_result_bb,
/* 6xE1 */ nullptr,
/* 6xE1 */ on_quest_F95F_result_bb,
/* 6xE2 */ nullptr,
/* 6xE3 */ nullptr,
/* 6xE4 */ nullptr,
+11 -2
View File
@@ -703,7 +703,7 @@ void ServerState::parse_config(const JSON& json, bool is_reload) {
try {
this->quest_F95E_results.clear();
for (const auto& type_it : json.get_list("QuestF95ERewardItems")) {
for (const auto& type_it : json.get_list("QuestF95EResultItems")) {
auto& type_res = this->quest_F95E_results.emplace_back();
for (const auto& difficulty_it : type_it->as_list()) {
auto& difficulty_res = type_res.emplace_back();
@@ -715,7 +715,16 @@ void ServerState::parse_config(const JSON& json, bool is_reload) {
}
} catch (const out_of_range&) {
}
try {
this->quest_F95F_results.clear();
for (const auto& it : json.get_list("QuestF95FResultItems")) {
auto& list = it->as_list();
size_t price = list.at(0)->as_int();
string data = parse_data_string(list.at(1)->as_string());
this->quest_F95F_results.emplace_back(make_pair(price, ItemData::from_data(data)));
}
} catch (const out_of_range&) {
}
try {
this->secret_lottery_results.clear();
for (const auto& it : json.get_list("SecretLotteryResultItems")) {
+1
View File
@@ -115,6 +115,7 @@ struct ServerState : public std::enable_shared_from_this<ServerState> {
// Indexed as [type][difficulty][random_choice]
std::vector<std::vector<std::vector<ItemData>>> quest_F95E_results;
std::vector<std::pair<size_t, ItemData>> quest_F95F_results; // [(num_photon_tickets, item)]
std::vector<ItemData> secret_lottery_results;
uint16_t bb_global_exp_multiplier;