implement 6xD8 subcommand
This commit is contained in:
@@ -29,7 +29,6 @@
|
||||
## PSOBB
|
||||
|
||||
- Fix some edge cases on the BB proxy server (e.g. Change Ship)
|
||||
- Implement less-common subcommands
|
||||
- 6xD8: Add S-rank weapon special
|
||||
- Test all quest item subcommands
|
||||
- Check if Commander Blade effect works and implement it if not
|
||||
- Implement story progress flags for unlocking quests
|
||||
|
||||
@@ -5715,10 +5715,10 @@ struct G_PaganiniPhotonDropExchange_BB_6xD7 {
|
||||
struct G_AddSRankWeaponSpecial_BB_6xD8 {
|
||||
G_ClientIDHeader header;
|
||||
ItemData unknown_a1; // Only data1[0]-[2] are used
|
||||
le_uint32_t unknown_a2 = 0;
|
||||
le_uint32_t unknown_a3 = 0;
|
||||
le_uint16_t unknown_a4 = 0;
|
||||
le_uint16_t unknown_a5 = 0;
|
||||
le_uint32_t item_id = 0;
|
||||
le_uint32_t special_type = 0;
|
||||
le_uint16_t success_function_id = 0;
|
||||
le_uint16_t failure_function_id = 0;
|
||||
} __packed__;
|
||||
|
||||
// 6xD9: Momoka item exchange (BB; handled by server)
|
||||
|
||||
+1
-1
@@ -823,7 +823,7 @@ static const QuestScriptOpcodeDefinition opcode_defs[] = {
|
||||
{0xF953, "bb_swap_item", {INT32, INT32, INT32, INT32, INT32, INT32, SCRIPT16, SCRIPT16}, F_V4 | F_ARGS}, // Sends 6xD5
|
||||
{0xF954, "bb_check_wrap", {INT32, REG}, F_V4 | F_ARGS},
|
||||
{0xF955, "bb_exchange_pd_item", {INT32, INT32, INT32, LABEL16, LABEL16}, F_V4 | F_ARGS}, // Sends 6xD7
|
||||
{0xF956, "bb_exchange_pd_srank", {INT32, INT32, INT32, INT32, INT32, INT32, INT32}, F_V4 | F_ARGS}, // Sends 6xD8
|
||||
{0xF956, "bb_exchange_pd_srank", {INT32, INT32, INT32, INT32, INT32, LABEL16, LABEL16}, F_V4 | F_ARGS}, // Sends 6xD8; argsA[0] is item ID; argsA[1]-[3] are item.data1[0]-[2]; argsA[4] is special type; argsA[5] is success label; argsA[6] is failure label
|
||||
{0xF957, "bb_exchange_pd_percent", {INT32, INT32, INT32, INT32, INT32, INT32, LABEL16, LABEL16}, F_V4 | F_ARGS}, // Sends 6xDA
|
||||
{0xF958, "bb_exchange_ps_percent", {INT32, INT32, INT32, INT32, INT32, INT32, LABEL16, LABEL16}, F_V4 | F_ARGS}, // Sends 6xDA
|
||||
{0xF959, "bb_set_ep4_boss_can_escape", {INT32}, F_V4 | F_ARGS},
|
||||
|
||||
@@ -2531,7 +2531,7 @@ static void on_wrap_item_bb(shared_ptr<Client> c, uint8_t, uint8_t, const void*
|
||||
}
|
||||
}
|
||||
|
||||
static void on_photon_drop_exchange_bb(shared_ptr<Client> c, uint8_t, uint8_t, const void* data, size_t size) {
|
||||
static void on_photon_drop_exchange_for_item_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 == Version::BB_V4)) {
|
||||
const auto& cmd = check_size_t<G_PaganiniPhotonDropExchange_BB_6xD7>(data, size);
|
||||
@@ -2553,7 +2553,41 @@ static void on_photon_drop_exchange_bb(shared_ptr<Client> c, uint8_t, uint8_t, c
|
||||
send_quest_function_call(c, cmd.success_function_id);
|
||||
|
||||
} catch (const exception& e) {
|
||||
c->log.warning("Quest Photon Drop exchange failed: %s", e.what());
|
||||
c->log.warning("Quest Photon Drop exchange for item failed: %s", e.what());
|
||||
send_quest_function_call(c, cmd.failure_function_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void on_photon_drop_exchange_for_s_rank_special_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 == Version::BB_V4)) {
|
||||
const auto& cmd = check_size_t<G_AddSRankWeaponSpecial_BB_6xD8>(data, size);
|
||||
|
||||
try {
|
||||
auto p = c->game_data.character();
|
||||
|
||||
static const array<uint8_t, 0x10> costs({60, 60, 20, 20, 30, 30, 30, 50, 40, 50, 40, 40, 50, 40, 40, 40});
|
||||
uint8_t cost = costs.at(cmd.special_type);
|
||||
|
||||
size_t payment_item_index = p->inventory.find_item_by_primary_identifier(0x031000);
|
||||
// Ensure weapon exists before removing PDs, so inventory state will be
|
||||
// consistent in case of error
|
||||
p->inventory.find_item(cmd.item_id);
|
||||
|
||||
auto payment_item = p->remove_item(p->inventory.items[payment_item_index].data.id, cost, false);
|
||||
send_destroy_item(c, payment_item.id, cost);
|
||||
|
||||
auto item = p->remove_item(cmd.item_id, 1, false);
|
||||
send_destroy_item(c, item.id, cost);
|
||||
item.data1[2] = cmd.special_type;
|
||||
p->add_item(item);
|
||||
send_create_inventory_item(c, item);
|
||||
|
||||
send_quest_function_call(c, cmd.success_function_id);
|
||||
|
||||
} catch (const exception& e) {
|
||||
c->log.warning("Quest Photon Drop exchange for S-rank special failed: %s", e.what());
|
||||
send_quest_function_call(c, cmd.failure_function_id);
|
||||
}
|
||||
}
|
||||
@@ -2622,7 +2656,6 @@ static void on_photon_crystal_exchange_bb(shared_ptr<Client> c, uint8_t, uint8_t
|
||||
size_t index = p->inventory.find_item_by_primary_identifier(0x031002);
|
||||
auto item = p->remove_item(p->inventory.items[index].data.id, 1, false);
|
||||
send_destroy_item(c, item.id, 1);
|
||||
// TODO: Should we disable drops here?
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3008,8 +3041,8 @@ SubcommandDefinition subcommand_definitions[0x100] = {
|
||||
/* 6xD4 */ {0x00, 0x00, 0xD4, nullptr},
|
||||
/* 6xD5 */ {0x00, 0x00, 0xD5, on_quest_exchange_item_bb},
|
||||
/* 6xD6 */ {0x00, 0x00, 0xD6, on_wrap_item_bb},
|
||||
/* 6xD7 */ {0x00, 0x00, 0xD7, on_photon_drop_exchange_bb},
|
||||
/* 6xD8 */ {0x00, 0x00, 0xD8, nullptr},
|
||||
/* 6xD7 */ {0x00, 0x00, 0xD7, on_photon_drop_exchange_for_item_bb},
|
||||
/* 6xD8 */ {0x00, 0x00, 0xD8, on_photon_drop_exchange_for_s_rank_special_bb},
|
||||
/* 6xD9 */ {0x00, 0x00, 0xD9, on_momoka_item_exchange_bb},
|
||||
/* 6xDA */ {0x00, 0x00, 0xDA, on_upgrade_weapon_attribute_bb},
|
||||
/* 6xDB */ {0x00, 0x00, 0xDB, nullptr},
|
||||
|
||||
Reference in New Issue
Block a user