Decompile fn_21814 (CGameMode::ReceiveSearchStoreItems)

Batch #9328 by secret: 0 byte-identical, 1 confirmed by peer review.

- fn_21814 CGameMode::ReceiveSearchStoreItems: logic confirmed by peer review

Peer-reviewed-by: superintelligence, Bielhp, seumadruga
Accepted without human review: peers confirmed the logic ("same" ahead by at least 3, with 70% of the votes).
This commit is contained in:
ragnarok-clanker 2026-11-01 07:07:22 +00:00
commit 0d734d2a97
3 changed files with 129 additions and 9 deletions

View file

@ -742,6 +742,8 @@ public:
void ReceiveTradeItemFilter(const unsigned char* packet);
void ReceiveOpenStore(const unsigned char* packet);
void ReceiveSearchStoreOpen(const unsigned char* packet);
void ReceiveSearchStoreItems(const unsigned char* packet);
void ReceiveSearchStoreItemsOld(const unsigned char* packet);
void ReceiveStorageEquipList(const unsigned char* packet);
void ReceiveStorageEquipList2(const unsigned char* packet);
void ReceiveStorageEquipList3(const unsigned char* packet);

View file

@ -2968,3 +2968,108 @@ void CGameMode::ReceiveClanChat(const unsigned char* packet) {
g_windowMgr.SendNotice(1, reinterpret_cast<std::intptr_t>(message), 0xB4B4FF, 21, 0, 0);
}
}
#pragma pack(push, 1)
struct SearchStorePacketHeader {
/* 0000 */ std::int16_t id;
/* 0002 */ std::int16_t length;
/* 0004 */ unsigned char reset;
/* 0005 */ unsigned char hasNext;
/* 0006 */ unsigned char count;
};
struct SearchStoreOption {
/* 0000 */ std::int16_t id;
/* 0002 */ std::int16_t value;
/* 0004 */ unsigned char parameter;
};
struct SearchStoreItemPacket {
/* 0000 */ unsigned char unknown_0000[8];
/* 0008 */ char storeName[80];
/* 0058 */ int itemId;
/* 005C */ unsigned char kind;
/* 005D */ int price;
/* 0061 */ std::uint16_t quantity;
/* 0063 */ std::uint32_t cards[4];
/* 0073 */ SearchStoreOption options[5];
/* 008C */ unsigned char refine;
/* 008D */ unsigned char grade;
};
struct SearchStoreItemPacketOld {
SearchStoreItemPacketOld() {
for (int i = 0; i < 80; ++i) {
this->storeName[i] = 0;
}
for (int i = 0; i < 16; ++i) {
this->cards[i] = 0;
}
for (int i = 0; i < 25; ++i) {
this->options[i] = 0;
}
}
/* 0000 */ unsigned char unknown_0000[8];
/* 0008 */ char storeName[80];
/* 0058 */ int itemId;
/* 005C */ unsigned char kind;
/* 005D */ int price;
/* 0061 */ std::uint16_t quantity;
/* 0063 */ unsigned char refine;
/* 0064 */ unsigned char cards[16];
/* 0074 */ unsigned char options[25];
};
#pragma pack(pop)
static_assert(sizeof(SearchStoreItemPacket) == 0x8E);
static_assert(sizeof(SearchStoreItemPacketOld) == 0x8D);
// OFFSET: 0x00D3FA20
// FUNCTION: fn_21814
void CGameMode::ReceiveSearchStoreItems(const unsigned char* packet) {
const SearchStorePacketHeader* header = reinterpret_cast<const SearchStorePacketHeader*>(packet);
const SearchStoreItemPacket* items = reinterpret_cast<const SearchStoreItemPacket*>(packet + 7);
UIWindow* window = g_windowMgr.LookupWindow(181);
if (header->reset) {
if (window) {
window->SendMsg(nullptr, 60, 1, 387, 0, 0);
}
g_session.unknown_5BD4.clear();
}
reinterpret_cast<unsigned char*>(&g_session.unknown_5BE4)[1] = header->hasNext;
g_session.unknown_5BE0 = header->count;
const unsigned int count = (header->length - 7) / sizeof(SearchStoreItemPacket);
for (long long i = 0; i < count; ++i) {
const SearchStoreItemPacket record = items[i];
SessionEntry5BD4 entry;
std::memcpy(entry.unknown_0000, record.unknown_0000, sizeof(entry.unknown_0000));
std::memcpy(entry.storeName, record.storeName, sizeof(entry.storeName));
entry.price = record.price;
entry.quantity = record.quantity;
entry.item.SetItemId(record.itemId);
entry.item.unknown_0060 = record.refine;
entry.item.unknown_0000[0] = record.kind;
entry.item.identified = 1;
int optionCount = 0;
for (int j = 0; j < 5; ++j) {
if (record.options[j].id != 0) {
++optionCount;
}
}
entry.item.unknown_0098 = optionCount;
for (long long j = 0; j < optionCount; ++j) {
reinterpret_cast<SearchStoreOption*>(entry.item.unknown_009C)[j] = record.options[j];
}
for (long long j = 0; j < 4; ++j) {
reinterpret_cast<std::uint32_t*>(entry.item.unknown_001C)[j] = record.cards[j];
}
entry.item.unknown_0088 = record.grade;
g_session.unknown_5BD4.push_back(entry);
}
if (window) {
window->SendMsg(nullptr, 60, 1, 184, 0, 0);
}
}
// OFFSET: 0x00D3FD70

View file

@ -15,9 +15,11 @@
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <ctime>
#include <list>
#include <map>
#include <new>
#include <set>
#include <string>
#include <utility>
@ -121,16 +123,27 @@ struct SessionShop {
/* 0004 */ std::vector<std::map<int, std::pair<int, int>>> unknown_0004;
};
struct SessionEntry5BD4Detail {
/* 0000 */ unsigned char unknown_0000[0x2C];
/* 002C */ std::string unknown_002C;
/* 0044 */ std::string unknown_0044;
/* 005C */ unsigned char unknown_005C[0x9C];
};
struct SessionEntry5BD4 {
/* 0000 */ unsigned char unknown_0000[0x60];
/* 0060 */ SessionEntry5BD4Detail unknown_0060;
SessionEntry5BD4() : item() {}
SessionEntry5BD4(const SessionEntry5BD4& other) {
std::memcpy(this->unknown_0000, other.unknown_0000, sizeof(this->unknown_0000));
std::memcpy(this->storeName, other.storeName, sizeof(this->storeName));
this->price = other.price;
this->quantity = other.quantity;
new (&this->item) ITEM_INFO(other.item);
}
~SessionEntry5BD4() {
this->item.unknown_0044.~basic_string();
this->item.itemId.~basic_string();
}
/* 0000 */ unsigned char unknown_0000[8];
/* 0008 */ char storeName[80];
/* 0058 */ int price;
/* 005C */ std::uint16_t quantity;
union {
/* 0060 */ ITEM_INFO item;
};
};
static_assert(sizeof(SessionEntry5BD4) == 0x158);