diff --git a/src/CommandFormats.hh b/src/CommandFormats.hh index f272efc0..16b516d7 100644 --- a/src/CommandFormats.hh +++ b/src/CommandFormats.hh @@ -5629,15 +5629,15 @@ struct G_BattleModeLevelUp_BB_6xD0 { le_uint32_t num_levels = 0; } __packed__; -// 6xD1: Challenge mode grave (BB; handled by server) +// 6xD1: Request Challenge Mode grave recovery item (BB; handled by server) -struct G_ChallengeModeGrave_BB_6xD1 { +struct G_ChallengeModeGraveRecoveryItemRequest_BB_6xD1 { G_ClientIDHeader header; - le_uint16_t unknown_a1 = 0; + le_uint16_t floor = 0; le_uint16_t unknown_a2 = 0; - le_uint32_t unknown_a3 = 0; - le_uint32_t unknown_a4 = 0; - le_uint32_t unknown_a5 = 0; + le_float x = 0; + le_float z = 0; + le_uint32_t item_type = 0; // Should be < 6 } __packed__; // 6xD2: Set quest global flag (BB) diff --git a/src/ItemData.cc b/src/ItemData.cc index ab42465a..0a60bb7e 100644 --- a/src/ItemData.cc +++ b/src/ItemData.cc @@ -18,6 +18,12 @@ ItemData::ItemData(const ItemData& other) { this->data2d = other.data2d; } +ItemData::ItemData(uint64_t first, uint64_t second) { + *reinterpret_cast(&this->data1[0]) = first; + this->data1d[2] = bswap32((second >> 32) & 0xFFFFFFFF); + this->data2d = bswap32(second & 0xFFFFFFFF); +} + ItemData& ItemData::operator=(const ItemData& other) { this->data1d = other.data1d; this->id = other.id; diff --git a/src/ItemData.hh b/src/ItemData.hh index a1979c55..9494dbb4 100644 --- a/src/ItemData.hh +++ b/src/ItemData.hh @@ -122,6 +122,7 @@ struct ItemData { // 0x14 bytes ItemData(); ItemData(const ItemData& other); + ItemData(uint64_t first, uint64_t second = 0); ItemData& operator=(const ItemData& other); bool operator==(const ItemData& other) const; diff --git a/src/ReceiveSubcommands.cc b/src/ReceiveSubcommands.cc index 99ab0568..6762be21 100644 --- a/src/ReceiveSubcommands.cc +++ b/src/ReceiveSubcommands.cc @@ -2302,6 +2302,28 @@ static void on_battle_level_up_bb(shared_ptr c, uint8_t, uint8_t, const } } +static void on_request_challenge_grave_recovery_item_bb(shared_ptr 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->mode == GameMode::CHALLENGE) && + l->check_flag(Lobby::Flag::QUEST_IN_PROGRESS)) { + const auto& cmd = check_size_t(data, size); + static const array items = { + ItemData(0x0300000000010000), // Monomate x1 + ItemData(0x0300010000010000), // Dimate x1 + ItemData(0x0300020000010000), // Trimate x1 + ItemData(0x0301000000010000), // Monofluid x1 + ItemData(0x0301010000010000), // Difluid x1 + ItemData(0x0301020000010000), // Trifluid x1 + }; + ItemData item = items.at(cmd.item_type); + item.id = l->generate_item_id(0xFF); + l->add_item(item, cmd.floor, cmd.x, cmd.z); + send_drop_stacked_item(l, item, cmd.floor, cmd.x, cmd.z); + } +} + static void on_quest_exchange_item_bb(shared_ptr c, uint8_t, uint8_t, const void* data, size_t size) { auto l = c->require_lobby(); if (l->is_game() && @@ -2875,7 +2897,7 @@ subcommand_handler_t subcommand_handlers[0x100] = { /* 6xCE */ nullptr, /* 6xCF */ on_battle_restart_bb, /* 6xD0 */ on_battle_level_up_bb, - /* 6xD1 */ nullptr, + /* 6xD1 */ on_request_challenge_grave_recovery_item_bb, /* 6xD2 */ on_write_quest_global_flag_bb, /* 6xD3 */ nullptr, /* 6xD4 */ nullptr, diff --git a/src/SendCommands.hh b/src/SendCommands.hh index c6410abf..a2c51955 100644 --- a/src/SendCommands.hh +++ b/src/SendCommands.hh @@ -296,10 +296,8 @@ void send_drop_item(std::shared_ptr s, Channel& ch, const ItemData& bool from_enemy, uint8_t floor, float x, float z, uint16_t request_id); void send_drop_item(std::shared_ptr l, const ItemData& item, bool from_enemy, uint8_t floor, float x, float z, uint16_t request_id); -void send_drop_stacked_item(std::shared_ptr s, Channel& ch, const ItemData& item, - uint8_t floor, float x, float z); -void send_drop_stacked_item(std::shared_ptr l, const ItemData& item, - uint8_t floor, float x, float z); +void send_drop_stacked_item(std::shared_ptr s, Channel& ch, const ItemData& item, uint8_t floor, float x, float z); +void send_drop_stacked_item(std::shared_ptr l, const ItemData& item, uint8_t floor, float x, float z); void send_pick_up_item(std::shared_ptr c, uint32_t id, uint8_t floor); void send_create_inventory_item(std::shared_ptr c, const ItemData& item); void send_destroy_item(std::shared_ptr c, uint32_t item_id, uint32_t amount);