implement 6xDE command
This commit is contained in:
+10
-8
@@ -849,15 +849,17 @@ struct SC_GameGuardCheck_BB_0022 {
|
|||||||
// header.flag indicates if an item was exchanged: 0 means success, 1 means
|
// header.flag indicates if an item was exchanged: 0 means success, 1 means
|
||||||
// failure.
|
// failure.
|
||||||
|
|
||||||
// 24 (S->C): Good Luck result (BB)
|
// 24 (S->C): Secret Lottery Ticket exchange result (BB)
|
||||||
// Sent in response to a 6xDE command from the client.
|
// Sent in response to a 6xDE command from the client.
|
||||||
// header.flag indicates whether the client had any Secret Lottery Tickets in
|
// header.flag indicates whether the client had any Secret Lottery Tickets in
|
||||||
// their inventory (and hence could participate): 0 means success, 1 means
|
// their inventory (and hence could participate): 0 means success, 1 means
|
||||||
// failure.
|
// failure.
|
||||||
|
|
||||||
struct S_GoodLuckResult_BB_24 {
|
struct S_ExchangeSecretLotteryTicketResult_BB_24 {
|
||||||
le_uint16_t unknown_a1 = 0;
|
// 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_a2 = 0;
|
||||||
|
le_uint16_t unknown_a1 = 0;
|
||||||
parray<le_uint32_t, 8> unknown_a3;
|
parray<le_uint32_t, 8> unknown_a3;
|
||||||
} __packed__;
|
} __packed__;
|
||||||
|
|
||||||
@@ -5672,7 +5674,7 @@ struct G_UpgradeWeaponAttribute_BB_6xDA {
|
|||||||
struct G_ExchangeItemInQuest_BB_6xDB {
|
struct G_ExchangeItemInQuest_BB_6xDB {
|
||||||
G_ClientIDHeader header;
|
G_ClientIDHeader header;
|
||||||
le_uint32_t unknown_a1 = 0;
|
le_uint32_t unknown_a1 = 0;
|
||||||
le_uint32_t unknown_a2 = 0;
|
le_uint32_t item_id = 0;
|
||||||
le_uint32_t unknown_a3 = 0;
|
le_uint32_t unknown_a3 = 0;
|
||||||
} __packed__;
|
} __packed__;
|
||||||
|
|
||||||
@@ -5692,20 +5694,20 @@ struct G_SetEXPMultiplier_BB_6xDD {
|
|||||||
G_ParameterHeader header;
|
G_ParameterHeader header;
|
||||||
} __packed__;
|
} __packed__;
|
||||||
|
|
||||||
// 6xDE: Good Luck quest (BB; handled by server)
|
// 6xDE: Exchange Secret Lottery Ticket (BB; handled by server)
|
||||||
// The client sends this when it executes an F95C quest opcode.
|
// The client sends this when it executes an F95C quest opcode.
|
||||||
|
|
||||||
struct G_GoodLuckQuestActions_BB_6xDE {
|
struct G_ExchangeSecretLotteryTicket_BB_6xDE {
|
||||||
G_ClientIDHeader header;
|
G_ClientIDHeader header;
|
||||||
uint8_t unknown_a1 = 0;
|
uint8_t unknown_a1 = 0;
|
||||||
uint8_t unknown_a2 = 0;
|
uint8_t unknown_a2 = 0;
|
||||||
le_uint16_t unknown_a3 = 0;
|
le_uint16_t unknown_a3 = 0;
|
||||||
} __packed__;
|
} __packed__;
|
||||||
|
|
||||||
// 6xDF: Black Paper's Deal Photon Crystal exchange (BB; handled by server)
|
// 6xDF: Exchange Photon Crystals (BB; handled by server)
|
||||||
// The client sends this when it executes an F95D quest opcode.
|
// The client sends this when it executes an F95D quest opcode.
|
||||||
|
|
||||||
struct G_BlackPaperDealPhotonCrystalExchange_BB_6xDF {
|
struct G_ExchangePhotonCrystals_BB_6xDF {
|
||||||
G_ClientIDHeader header;
|
G_ClientIDHeader header;
|
||||||
} __packed__;
|
} __packed__;
|
||||||
|
|
||||||
|
|||||||
@@ -2291,10 +2291,65 @@ static void on_photon_drop_exchange_bb(shared_ptr<Client> c, uint8_t, uint8_t, c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void on_secret_lottery_ticket_exchange_bb(shared_ptr<Client> c, uint8_t, uint8_t, const void* data, size_t size) {
|
||||||
|
auto s = c->require_server_state();
|
||||||
|
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_ExchangeSecretLotteryTicket_BB_6xDE>(data, size);
|
||||||
|
|
||||||
|
if (s->secret_lottery_results.empty()) {
|
||||||
|
throw runtime_error("no secret lottery results are defined");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto p = c->game_data.character();
|
||||||
|
ssize_t slt_index = -1;
|
||||||
|
try {
|
||||||
|
slt_index = p->inventory.find_item_by_primary_identifier(0x031003); // Secret Lottery Ticket
|
||||||
|
} catch (const out_of_range&) {
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slt_index >= 0) {
|
||||||
|
uint32_t slt_item_id = p->inventory.items[slt_index].data.id;
|
||||||
|
|
||||||
|
G_ExchangeItemInQuest_BB_6xDB exchange_cmd;
|
||||||
|
exchange_cmd.header.subcommand = 0xDB;
|
||||||
|
exchange_cmd.header.size = 4;
|
||||||
|
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;
|
||||||
|
send_command_t(c, 0x60, 0x00, exchange_cmd);
|
||||||
|
|
||||||
|
send_destroy_item(c, slt_item_id, 1);
|
||||||
|
|
||||||
|
ItemData item = (s->secret_lottery_results.size() == 1)
|
||||||
|
? s->secret_lottery_results[0]
|
||||||
|
: s->secret_lottery_results[random_object<uint32_t>() % s->secret_lottery_results.size()];
|
||||||
|
item.id = l->generate_item_id(c->lobby_client_id);
|
||||||
|
p->add_item(item);
|
||||||
|
send_create_inventory_item(c, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
S_ExchangeSecretLotteryTicketResult_BB_24 out_cmd;
|
||||||
|
out_cmd.unknown_a1 = cmd.unknown_a1;
|
||||||
|
out_cmd.unknown_a2 = cmd.unknown_a2;
|
||||||
|
if (s->secret_lottery_results.empty()) {
|
||||||
|
out_cmd.unknown_a3.clear(0);
|
||||||
|
} else if (s->secret_lottery_results.size() == 1) {
|
||||||
|
out_cmd.unknown_a3.clear(1);
|
||||||
|
} else {
|
||||||
|
for (size_t z = 0; z < out_cmd.unknown_a3.size(); z++) {
|
||||||
|
out_cmd.unknown_a3[z] = random_object<uint32_t>() % s->secret_lottery_results.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
send_command_t(c, 0x24, (slt_index >= 0) ? 0 : 1, out_cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void on_photon_crystal_exchange_bb(shared_ptr<Client> c, uint8_t, uint8_t, const void* data, size_t size) {
|
static void on_photon_crystal_exchange_bb(shared_ptr<Client> c, uint8_t, uint8_t, const void* data, size_t size) {
|
||||||
auto l = c->require_lobby();
|
auto l = c->require_lobby();
|
||||||
if (l->is_game() && (l->base_version == GameVersion::BB) && l->check_flag(Lobby::Flag::QUEST_IN_PROGRESS)) {
|
if (l->is_game() && (l->base_version == GameVersion::BB) && l->check_flag(Lobby::Flag::QUEST_IN_PROGRESS)) {
|
||||||
check_size_t<G_BlackPaperDealPhotonCrystalExchange_BB_6xDF>(data, size);
|
check_size_t<G_ExchangePhotonCrystals_BB_6xDF>(data, size);
|
||||||
auto p = c->game_data.character();
|
auto p = c->game_data.character();
|
||||||
size_t index = p->inventory.find_item_by_primary_identifier(0x031002);
|
size_t index = p->inventory.find_item_by_primary_identifier(0x031002);
|
||||||
auto item = p->remove_item(p->inventory.items[index].data.id, 1, false);
|
auto item = p->remove_item(p->inventory.items[index].data.id, 1, false);
|
||||||
@@ -2648,7 +2703,7 @@ subcommand_handler_t subcommand_handlers[0x100] = {
|
|||||||
/* 6xDB */ nullptr,
|
/* 6xDB */ nullptr,
|
||||||
/* 6xDC */ on_forward_check_size_game,
|
/* 6xDC */ on_forward_check_size_game,
|
||||||
/* 6xDD */ nullptr,
|
/* 6xDD */ nullptr,
|
||||||
/* 6xDE */ nullptr,
|
/* 6xDE */ on_secret_lottery_ticket_exchange_bb,
|
||||||
/* 6xDF */ on_photon_crystal_exchange_bb,
|
/* 6xDF */ on_photon_crystal_exchange_bb,
|
||||||
/* 6xE0 */ on_quest_F95E_result_bb,
|
/* 6xE0 */ on_quest_F95E_result_bb,
|
||||||
/* 6xE1 */ nullptr,
|
/* 6xE1 */ nullptr,
|
||||||
|
|||||||
@@ -715,6 +715,15 @@ void ServerState::parse_config(const JSON& json, bool is_reload) {
|
|||||||
} catch (const out_of_range&) {
|
} catch (const out_of_range&) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this->secret_lottery_results.clear();
|
||||||
|
for (const auto& it : json.get_list("SecretLotteryResultItems")) {
|
||||||
|
string data = parse_data_string(it->as_string());
|
||||||
|
this->secret_lottery_results.emplace_back(ItemData::from_data(data));
|
||||||
|
}
|
||||||
|
} catch (const out_of_range&) {
|
||||||
|
}
|
||||||
|
|
||||||
set_log_levels_from_json(json.get("LogLevels", JSON::dict()));
|
set_log_levels_from_json(json.get("LogLevels", JSON::dict()));
|
||||||
|
|
||||||
if (!is_reload) {
|
if (!is_reload) {
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ struct ServerState : public std::enable_shared_from_this<ServerState> {
|
|||||||
|
|
||||||
// Indexed as [type][difficulty][random_choice]
|
// Indexed as [type][difficulty][random_choice]
|
||||||
std::vector<std::vector<std::vector<ItemData>>> quest_F95E_results;
|
std::vector<std::vector<std::vector<ItemData>>> quest_F95E_results;
|
||||||
|
std::vector<ItemData> secret_lottery_results;
|
||||||
|
|
||||||
std::shared_ptr<Episode3::TournamentIndex> ep3_tournament_index;
|
std::shared_ptr<Episode3::TournamentIndex> ep3_tournament_index;
|
||||||
|
|
||||||
|
|||||||
@@ -537,6 +537,16 @@
|
|||||||
["00BA00", "00B400", "000D03", "00B600", "00B300", "000708", "004301", "00C900", "010136", "01028A", "010299", "010285", "010348", "010351", "01035B", "010352"],
|
["00BA00", "00B400", "000D03", "00B600", "00B300", "000708", "004301", "00C900", "010136", "01028A", "010299", "010285", "010348", "010351", "01035B", "010352"],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
// Reward item definitions for Secret Lottery Ticket exchange (quest opcode
|
||||||
|
// F95C, used in the Good Luck quest).
|
||||||
|
"SecretLotteryResultItems": [
|
||||||
|
"000106", "000107", "000206", "000407", "000606", "000807", "000D01",
|
||||||
|
"001300", "002000", "002700", "002C00", "003400", "003900", "003C00",
|
||||||
|
"003E00", "004100", "004400", "004500", "004C00", "006A00", "008F07",
|
||||||
|
"009A00", "01011B", "01011C", "010129", "010129", "010130", "010131",
|
||||||
|
"010132", "010133", "010221", "010224", "010229", "01022B", "010235",
|
||||||
|
"031000",
|
||||||
|
],
|
||||||
|
|
||||||
// Cheat mode behavior. There are three values:
|
// Cheat mode behavior. There are three values:
|
||||||
// "Off": Cheat mode is disabled on the entire server. Cheat mode cannot be
|
// "Off": Cheat mode is disabled on the entire server. Cheat mode cannot be
|
||||||
|
|||||||
+9
-1
@@ -146,7 +146,7 @@
|
|||||||
[0x40, "download-ep3", "Download", "$E$C6Quests to download\nto your Memory Card"],
|
[0x40, "download-ep3", "Download", "$E$C6Quests to download\nto your Memory Card"],
|
||||||
],
|
],
|
||||||
|
|
||||||
"BlackPaperRewardItems": [
|
"QuestF95ERewardItems": [
|
||||||
[
|
[
|
||||||
["009000", "009001", "009002", "009003", "009004", "009005", "009006", "009007", "009008", "00B400", "01014E", "010307", "010341", "040000", "040000", "040000", "040000", "040000", "040000", "040000", "040000", "040000"],
|
["009000", "009001", "009002", "009003", "009004", "009005", "009006", "009007", "009008", "00B400", "01014E", "010307", "010341", "040000", "040000", "040000", "040000", "040000", "040000", "040000", "040000", "040000"],
|
||||||
["00B900", "003400", "000901", "009002", "009007", "002C00", "002D00", "010235", "000106", "000105", "040000", "040000", "040000", "040000", "040000", "040000", "040000", "040000", "040000"],
|
["00B900", "003400", "000901", "009002", "009007", "002C00", "002D00", "010235", "000106", "000105", "040000", "040000", "040000", "040000", "040000", "040000", "040000", "040000", "040000"],
|
||||||
@@ -169,4 +169,12 @@
|
|||||||
["00BA00", "00B400", "000D03", "00B600", "00B300", "000708", "004301", "00C900", "010136", "01028A", "010299", "010285", "010348", "010351", "01035B", "010352"],
|
["00BA00", "00B400", "000D03", "00B600", "00B300", "000708", "004301", "00C900", "010136", "01028A", "010299", "010285", "010348", "010351", "01035B", "010352"],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
"SecretLotteryResultItems": [
|
||||||
|
"000106", "000107", "000206", "000407", "000606", "000807", "000D01",
|
||||||
|
"001300", "002000", "002700", "002C00", "003400", "003900", "003C00",
|
||||||
|
"003E00", "004100", "004400", "004500", "004C00", "006A00", "008F07",
|
||||||
|
"009A00", "01011B", "01011C", "010129", "010129", "010130", "010131",
|
||||||
|
"010132", "010133", "010221", "010224", "010229", "01022B", "010235",
|
||||||
|
"031000",
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user