完善客户端功能并同步差距文档

This commit is contained in:
shenlei
2026-09-03 18:40:01 +09:00
parent f93a172296
commit 13ccb8d02d
135 changed files with 21881 additions and 1259 deletions
+19 -2
View File
@@ -197,15 +197,32 @@ ItemRecord parse_item(const uint8_t *r, uint32_t stride) {
it.sub_type = r[139];
it.weight = r[140];
it.size = r[141];
it.anti_flags = rd_u32(r + 142);
it.flags = rd_u32(r + 146);
it.wear_flags = rd_u32(r + 150);
it.buy_price = rd_u32(r + 158);
it.sell_price = rd_u32(r + 162);
// aLimits[2] (5B each) @166, aApplies[3] (5B each) @176, alValues[6] @191.
// (bSpecular @234 anchors the whole chain.)
for (int i = 0; i < 2; ++i) {
const size_t off = 166 + static_cast<size_t>(i) * 5;
it.limits[i].type = r[off];
it.limits[i].value = static_cast<int32_t>(rd_u32(r + off + 1));
}
for (int i = 0; i < 3; ++i) {
const size_t off = 176 + static_cast<size_t>(i) * 5;
it.applies[i].type = r[off];
it.applies[i].value = static_cast<int32_t>(rd_u32(r + off + 1));
}
for (int i = 0; i < 6; ++i) {
it.values[i] = (int32_t)rd_u32(r + 191 + i * 4);
}
for (int i = 0; i < 3; ++i) {
it.sockets[i] = static_cast<int32_t>(rd_u32(r + 215 + i * 4));
}
it.refined_vnum = rd_u32(r + 227);
it.refine_set = static_cast<uint16_t>(r[231] | (static_cast<uint16_t>(r[232]) << 8));
it.alter_to_magic_pct = r[233];
it.specular = r[234];
it.gain_socket_pct = r[235];
return it;
}
+19
View File
@@ -43,6 +43,16 @@ bool load_proto(const std::string &path, const std::array<uint32_t, 4> &key, Pro
// --- typed views over the leading fields (rest is offset-stable per stride) ---
struct ItemLimit {
uint8_t type = 0;
int32_t value = 0;
};
struct ItemApply {
uint8_t type = 0;
int32_t value = 0;
};
struct ItemRecord {
uint32_t vnum = 0;
uint32_t vnum_range = 0;
@@ -52,11 +62,20 @@ struct ItemRecord {
uint8_t sub_type = 0; // @ 139
uint8_t weight = 0; // @ 140
uint8_t size = 0; // @ 141
uint32_t anti_flags = 0; // @ 142 (ITEM_ANTIFLAG_*; sell = 1 << 8)
uint32_t flags = 0; // @ 146 (ITEM_FLAG_*; count-per-1-gold = 1 << 3)
uint32_t wear_flags = 0; // @ 150
uint32_t buy_price = 0; // @ 158
uint32_t sell_price = 0; // @ 162
std::array<ItemLimit, 2> limits{}; // aLimits[2] @ 166 (type + long)
std::array<ItemApply, 3> applies{}; // aApplies[3] @ 176 (type + long)
int32_t values[6] = {0}; // alValues[6] @ 191 (armor: values[3] = body shape index)
int32_t sockets[3] = {0}; // alSockets[3] @ 215
uint32_t refined_vnum = 0; // dwRefinedVnum @ 227
uint16_t refine_set = 0; // wRefineSet @ 231
uint8_t alter_to_magic_pct = 0; // bAlterToMagicItemPct @ 233
uint8_t specular = 0; // @ 234 -> PARITY §2.7 fSpecular = specular/100
uint8_t gain_socket_pct = 0; // bGainSocketPct @ 235
};
ItemRecord parse_item(const uint8_t *rec, uint32_t stride);
+33
View File
@@ -71,9 +71,31 @@ Dictionary Metin2Proto::item(int vnum) const {
d["sub_type"] = (int)r.sub_type;
d["weight"] = (int)r.weight;
d["size"] = (int)r.size;
d["anti_flags"] = (int)r.anti_flags;
d["flags"] = (int)r.flags;
d["wear_flags"] = (int)r.wear_flags;
d["buy_price"] = (int)r.buy_price;
d["sell_price"] = (int)r.sell_price;
{
Array limits;
for (const mtproto::ItemLimit &limit : r.limits) {
Dictionary entry;
entry["type"] = (int)limit.type;
entry["value"] = (int)limit.value;
limits.push_back(entry);
}
d["limits"] = limits;
}
{
Array applies;
for (const mtproto::ItemApply &apply : r.applies) {
Dictionary entry;
entry["type"] = (int)apply.type;
entry["value"] = (int)apply.value;
applies.push_back(entry);
}
d["applies"] = applies;
}
{
Array vals;
for (int i = 0; i < 6; ++i) {
@@ -81,7 +103,18 @@ Dictionary Metin2Proto::item(int vnum) const {
}
d["values"] = vals; // armor: values[3] = body shape index for the race .msm
}
{
Array sockets;
for (int socket : r.sockets) {
sockets.push_back(socket);
}
d["sockets"] = sockets;
}
d["refined_vnum"] = (int)r.refined_vnum;
d["refine_set"] = (int)r.refine_set;
d["alter_to_magic_pct"] = (int)r.alter_to_magic_pct;
d["specular"] = (int)r.specular;
d["gain_socket_pct"] = (int)r.gain_socket_pct;
return d;
}