add $qgread and $qgwrite commands
This commit is contained in:
@@ -375,6 +375,51 @@ static void proxy_command_qclear(shared_ptr<ProxyServer::LinkedSession> ses, con
|
||||
return proxy_command_qset_qclear(ses, args, false);
|
||||
}
|
||||
|
||||
static void server_command_qgread(shared_ptr<Client> c, const std::string& args) {
|
||||
uint8_t flag_num = stoul(args, nullptr, 0);
|
||||
const auto& flags = c->character()->quest_counters;
|
||||
if (flag_num >= flags.size()) {
|
||||
send_text_message_printf(c, "$C7Flag number must be\nless than %zu", flags.size());
|
||||
} else {
|
||||
send_text_message_printf(c, "$C7Quest counter %hhu\nhas value %" PRIu32,
|
||||
flag_num, flags[flag_num].load());
|
||||
}
|
||||
}
|
||||
|
||||
static void server_command_qgwrite(shared_ptr<Client> c, const std::string& args) {
|
||||
if (c->version() != Version::BB_V4) {
|
||||
send_text_message(c, "$C6This command can\nonly be used on BB");
|
||||
return;
|
||||
}
|
||||
if (!c->config.check_flag(Client::Flag::DEBUG_ENABLED)) {
|
||||
send_text_message(c, "$C6This command can only\nbe run in debug mode\n(run %sdebug first)");
|
||||
return;
|
||||
}
|
||||
auto l = c->require_lobby();
|
||||
if (!l->is_game()) {
|
||||
send_text_message(c, "$C6This command cannot\nbe used in the lobby");
|
||||
return;
|
||||
}
|
||||
|
||||
auto tokens = split(args, ' ');
|
||||
if (tokens.size() != 2) {
|
||||
send_text_message(c, "$C6Incorrect number\nof arguments");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t flag_num = stoul(tokens[0], nullptr, 0);
|
||||
uint32_t value = stoul(tokens[1], nullptr, 0);
|
||||
auto& flags = c->character()->quest_counters;
|
||||
if (flag_num >= flags.size()) {
|
||||
send_text_message_printf(c, "$C7Flag number must be\nless than %zu", flags.size());
|
||||
} else {
|
||||
c->character()->quest_counters[flag_num] = value;
|
||||
G_SetQuestCounter_BB_6xD2 cmd = {{0xD2, sizeof(G_SetQuestCounter_BB_6xD2) / 4, c->lobby_client_id}, flag_num, value};
|
||||
send_command_t(c, 0x60, 0x00, cmd);
|
||||
send_text_message_printf(c, "$C7Quest counter %hhu\nset to %" PRIu32, flag_num, value);
|
||||
}
|
||||
}
|
||||
|
||||
static void server_command_qsync_qsyncall(shared_ptr<Client> c, const std::string& args, bool send_to_lobby) {
|
||||
if (!c->config.check_flag(Client::Flag::DEBUG_ENABLED)) {
|
||||
send_text_message(c, "$C6This command can only\nbe run in debug mode\n(run %sdebug first)");
|
||||
@@ -2021,6 +2066,8 @@ static const unordered_map<string, ChatCommandDefinition> chat_commands({
|
||||
{"$qcall", {server_command_qcall, proxy_command_qcall}},
|
||||
{"$qcheck", {server_command_qcheck, nullptr}},
|
||||
{"$qclear", {server_command_qclear, proxy_command_qclear}},
|
||||
{"$qgread", {server_command_qgread, nullptr}},
|
||||
{"$qgwrite", {server_command_qgwrite, nullptr}},
|
||||
{"$qset", {server_command_qset, proxy_command_qset}},
|
||||
{"$qsync", {server_command_qsync, proxy_command_qsync}},
|
||||
{"$qsyncall", {server_command_qsyncall, proxy_command_qsyncall}},
|
||||
|
||||
+1
-1
@@ -811,7 +811,7 @@ void Client::load_all_files() {
|
||||
this->character_data->battle_records = nsc_data.battle_records;
|
||||
this->character_data->challenge_records = nsc_data.challenge_records;
|
||||
this->character_data->tech_menu_config = nsc_data.tech_menu_config;
|
||||
this->character_data->quest_global_flags = nsc_data.quest_global_flags;
|
||||
this->character_data->quest_counters = nsc_data.quest_counters;
|
||||
if (nsa_data) {
|
||||
this->character_data->option_flags = nsa_data->option_flags;
|
||||
this->character_data->symbol_chats = nsa_data->symbol_chats;
|
||||
|
||||
@@ -5881,10 +5881,10 @@ struct G_ChallengeModeGraveRecoveryItemRequest_BB_6xD1 {
|
||||
le_uint32_t item_type = 0; // Should be < 6
|
||||
} __packed__;
|
||||
|
||||
// 6xD2: Set quest global flag (BB)
|
||||
// 6xD2: Set quest counter (BB)
|
||||
// Writes 4 bytes to the 32-bit field specified by index.
|
||||
|
||||
struct G_SetQuestGlobalFlag_BB_6xD2 {
|
||||
struct G_SetQuestCounter_BB_6xD2 {
|
||||
G_ClientIDHeader header;
|
||||
le_uint32_t index = 0; // There are 0x10 of them (0x00-0x0F)
|
||||
le_uint32_t value = 0;
|
||||
|
||||
@@ -827,7 +827,7 @@ struct PlayerConfig {
|
||||
/* 000C:---- */ parray<uint8_t, 0x1C> unknown_a1;
|
||||
/* 0028:---- */ parray<be_uint16_t, 20> tech_menu_shortcut_entries;
|
||||
/* 0050:---- */ parray<be_uint32_t, 10> choice_search_config;
|
||||
// This field maps to quest_global_flags on Episodes 1 & 2
|
||||
// This field maps to quest_counters on Episodes 1 & 2
|
||||
/* 0078:---- */ parray<be_uint32_t, 0x30> scenario_progress;
|
||||
// place_counts[0] and [1] from this field are added to the player's win and
|
||||
// loss count respectively when they're shown in the status menu. However,
|
||||
|
||||
+7
-7
@@ -279,11 +279,11 @@ static const QuestScriptOpcodeDefinition opcode_defs[] = {
|
||||
{0x0010, "set", {REG}, F_V0_V4}, // Sets a register to 1
|
||||
{0x0011, "clear", {REG}, F_V0_V4}, // Sets a register to 0
|
||||
{0x0012, "rev", {REG}, F_V0_V4}, // Sets a register to 0 if it's nonzero and vice versa
|
||||
{0x0013, "gset", {INT16}, F_V0_V4}, // Sets a global flag
|
||||
{0x0014, "gclear", {INT16}, F_V0_V4}, // Clears a global flag
|
||||
{0x0015, "grev", {INT16}, F_V0_V4}, // Flips a global flag
|
||||
{0x0016, "glet", {INT16, REG}, F_V0_V4}, // Sets a global flag to a specific value
|
||||
{0x0017, "gget", {INT16, REG}, F_V0_V4}, // Gets a global flag
|
||||
{0x0013, "gset", {INT16}, F_V0_V4}, // Sets a quest flag
|
||||
{0x0014, "gclear", {INT16}, F_V0_V4}, // Clears a quest flag
|
||||
{0x0015, "grev", {INT16}, F_V0_V4}, // Flips a quest flag
|
||||
{0x0016, "glet", {INT16, REG}, F_V0_V4}, // Sets a quest flag to a specific value
|
||||
{0x0017, "gget", {INT16, REG}, F_V0_V4}, // Gets a quest flag
|
||||
{0x0018, "add", {REG, REG}, F_V0_V4}, // regA += regB
|
||||
{0x0019, "addi", {REG, INT32}, F_V0_V4}, // regA += imm
|
||||
{0x001A, "sub", {REG, REG}, F_V0_V4}, // regA -= regB
|
||||
@@ -779,8 +779,8 @@ static const QuestScriptOpcodeDefinition opcode_defs[] = {
|
||||
{0xF922, "get_player_hp", {CLIENT_ID, {REG_SET_FIXED, 4}}, F_V3_V4 | F_ARGS},
|
||||
{0xF923, "get_floor_number", {CLIENT_ID, {REG_SET_FIXED, 2}}, F_V3_V4 | F_ARGS},
|
||||
{0xF924, "get_coord_player_detect", {{REG_SET_FIXED, 3}, {REG_SET_FIXED, 4}}, F_V3_V4},
|
||||
{0xF925, "read_global_flag", {INT32, REG}, F_V3_V4 | F_ARGS},
|
||||
{0xF926, "write_global_flag", {INT32, INT32}, F_V3_V4 | F_ARGS},
|
||||
{0xF925, "read_counter", {INT32, REG}, F_V3_V4 | F_ARGS},
|
||||
{0xF926, "write_counter", {INT32, INT32}, F_V3_V4 | F_ARGS},
|
||||
{0xF927, "item_detect_bank2", {{REG_SET_FIXED, 4}, REG}, F_V3_V4},
|
||||
{0xF928, "floor_player_detect", {{REG_SET_FIXED, 4}}, F_V3_V4},
|
||||
{0xF929, "prepare_gba_rom_from_disk", {CSTRING}, F_V3 | F_ARGS}, // Prepares to load a GBA ROM from a local GSL file
|
||||
|
||||
@@ -3567,9 +3567,9 @@ static void on_upgrade_weapon_attribute_bb(shared_ptr<Client> c, uint8_t, uint8_
|
||||
}
|
||||
}
|
||||
|
||||
static void on_write_quest_global_flag_bb(shared_ptr<Client> c, uint8_t, uint8_t, void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_SetQuestGlobalFlag_BB_6xD2>(data, size);
|
||||
c->character()->quest_global_flags[cmd.index] = cmd.value;
|
||||
static void on_write_quest_counter_bb(shared_ptr<Client> c, uint8_t, uint8_t, void* data, size_t size) {
|
||||
const auto& cmd = check_size_t<G_SetQuestCounter_BB_6xD2>(data, size);
|
||||
c->character()->quest_counters[cmd.index] = cmd.value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -3785,7 +3785,7 @@ const SubcommandDefinition subcommand_definitions[0x100] = {
|
||||
/* 6xCF */ {0x00, 0x00, 0xCF, on_battle_restart_bb},
|
||||
/* 6xD0 */ {0x00, 0x00, 0xD0, on_battle_level_up_bb},
|
||||
/* 6xD1 */ {0x00, 0x00, 0xD1, on_request_challenge_grave_recovery_item_bb},
|
||||
/* 6xD2 */ {0x00, 0x00, 0xD2, on_write_quest_global_flag_bb},
|
||||
/* 6xD2 */ {0x00, 0x00, 0xD2, on_write_quest_counter_bb},
|
||||
/* 6xD3 */ {0x00, 0x00, 0xD3, on_invalid},
|
||||
/* 6xD4 */ {0x00, 0x00, 0xD4, on_forward_check_game},
|
||||
/* 6xD5 */ {0x00, 0x00, 0xD5, on_quest_exchange_item_bb},
|
||||
|
||||
@@ -210,7 +210,7 @@ struct PSOBBCharacterFile {
|
||||
/* 2DF8 */ parray<le_uint16_t, 0x0014> tech_menu_config;
|
||||
/* 2E20 */ ChoiceSearchConfig choice_search_config;
|
||||
/* 2E38 */ parray<uint8_t, 0x0010> unknown_a6;
|
||||
/* 2E48 */ parray<le_uint32_t, 0x0010> quest_global_flags;
|
||||
/* 2E48 */ parray<le_uint32_t, 0x0010> quest_counters;
|
||||
/* 2E88 */ parray<uint8_t, 0x1C> unknown_a7;
|
||||
/* 2EA4 */
|
||||
|
||||
@@ -360,7 +360,7 @@ struct PSOGCCharacterFile {
|
||||
/* 25E0:21C4 */ PlayerRecordsV3_Challenge<true> challenge_records;
|
||||
/* 26E0:22C4 */ parray<be_uint16_t, 20> tech_menu_shortcut_entries;
|
||||
/* 2708:22EC */ parray<uint8_t, 0x28> unknown_a6;
|
||||
/* 2730:2314 */ parray<be_uint32_t, 0x10> quest_global_flags;
|
||||
/* 2730:2314 */ parray<be_uint32_t, 0x10> quest_counters;
|
||||
/* 2770:2354 */ PlayerRecords_Battle<true> offline_battle_records;
|
||||
/* 2788:236C */ parray<uint8_t, 4> unknown_f5;
|
||||
/* 278C:2370 */ be_uint32_t unknown_f6;
|
||||
@@ -766,7 +766,7 @@ struct LegacySavedPlayerDataBB { // .nsc file format
|
||||
/* 1D00 */ parray<uint8_t, 4> unknown_a2;
|
||||
/* 1D04 */ QuestFlags quest_flags;
|
||||
/* 1F04 */ le_uint32_t death_count;
|
||||
/* 1F08 */ parray<le_uint32_t, 0x0016> quest_global_flags;
|
||||
/* 1F08 */ parray<le_uint32_t, 0x0016> quest_counters;
|
||||
/* 1F60 */ parray<le_uint16_t, 0x0014> tech_menu_config;
|
||||
/* 1F88 */
|
||||
} __attribute__((packed));
|
||||
|
||||
Reference in New Issue
Block a user