the guild window opens: roster, ranks, notes and the message of the day
- the social window's third tab is live — the roster in both its views, the member card with its promote/demote/remove verbs, the rank editor's thirteen permissions, the guild information board, and the invite, leave, kick and note dialogs behind them - setting your hearthstone at an innkeeper now asks before it takes and says so afterwards, and the innkeeper's gossip lines get their own icons back - unavailable talents grey out, and every greyed icon in the client now goes through the same luminance fold the original used - the buff tooltip's remaining-time line reads gold with the client's own hour/minute ladder, the macro editor takes a shift-click to paste a spell, trainer rows repaint after a purchase, and a long book page stops flickering its ellipsis Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -442,6 +442,19 @@ const FIELD_PLAYER_FLAGS: u16 = 190;
|
||||
// three reads `UnitReaction 0x6061e0`'s duel leg makes (decision 0633).
|
||||
const FIELD_PLAYER_DUEL_ARBITER: u16 = 188;
|
||||
const FIELD_PLAYER_DUEL_TEAM: u16 = 196;
|
||||
// PLAYER_GUILDID = UNIT_END(188) + 0x3, PLAYER_GUILDRANK = UNIT_END + 0x4 — both INT and both
|
||||
// **PUBLIC** (VERIFIED vmangos `UpdateFields_1_12_1.h:120-121`), the same arithmetic that pins
|
||||
// PLAYER_FLAGS = 190 at +0x2 above. Independently VERIFIED in the binary off the very player-block
|
||||
// base the duel pair is read through: `GetGuildInfo 0x4c9330` takes the guild id at `[+0xe68]+0xc`
|
||||
// (`0x4c93a9`, whose `test ecx,ecx` IS the guildless→nil path) and the rank at `+0x10` (`0x4c93e4`,
|
||||
// `shl edx,0x6` — the 0x40-byte rank-name slot in the cached guild record). 0xc/4 + 188 = 191 and
|
||||
// 0x10/4 + 188 = 192, with `+0x8` = PLAYER_FLAGS(190) as the third point on the same line.
|
||||
//
|
||||
// PUBLIC is the load-bearing half: these stream for *every visible player*, not just for us, which
|
||||
// is what makes `GetGuildInfo(unit)` answerable for an arbitrary unit — and why the guild query
|
||||
// response carries a fixed ten rank names to decode another player's rank against (decision 1257).
|
||||
const FIELD_PLAYER_GUILDID: u16 = 191;
|
||||
const FIELD_PLAYER_GUILDRANK: u16 = 192;
|
||||
// PLAYER_FIELD_COMBO_TARGET = UNIT_END(188) + 0x20E (GUID, PRIVATE) — VERIFIED vmangos
|
||||
// `UpdateFields_1_12_1.h:251`, and independently by the binary: `GetComboPoints 0x51a190` reads the
|
||||
// pair at `[player+0xe68]+0x838/+0x83c`, and 0x838/4 + 188 = 714 (decision 0875). The same player-
|
||||
|
||||
@@ -433,6 +433,28 @@ impl ObjectFields {
|
||||
pub fn player_duel_team(&self) -> u32 {
|
||||
self.get_u32(FIELD_PLAYER_DUEL_TEAM).unwrap_or(0)
|
||||
}
|
||||
/// `PLAYER_GUILDID` (field 191) — the id of the guild this player belongs to, `0` for a
|
||||
/// guildless one (and for the absent field, which is the same thing: the descriptor skips
|
||||
/// zeroes). **PUBLIC**, so it arrives for every visible player, not only for us.
|
||||
///
|
||||
/// It names a guild but does not describe one: the name and the rank names come only from
|
||||
/// `SMSG_GUILD_QUERY_RESPONSE`, keyed by this id (decision 1257). The real client's own
|
||||
/// `GetGuildInfo 0x4c9330` reads exactly this field and answers nil on both the `0` and the
|
||||
/// cache-miss legs (`0x4c93a9`, `0x4c93d7`).
|
||||
pub fn player_guild_id(&self) -> u32 {
|
||||
self.get_u32(FIELD_PLAYER_GUILDID).unwrap_or(0)
|
||||
}
|
||||
/// `PLAYER_GUILDRANK` (field 192) — this player's rank within [`Self::player_guild_id`]'s
|
||||
/// guild, **0-based with `0` = guild master** (vmangos promotes with `rank--`). Meaningless
|
||||
/// while the guild id is `0`. Indexes both [`crate::messages::GuildQueryResponse::rank_names`]
|
||||
/// and [`crate::messages::GuildRoster::rank_rights`].
|
||||
///
|
||||
/// The reference indexes its cached rank-name array with this **unbounded**
|
||||
/// (`0x4c93e4 mov edx,[ecx+0x10]` / `shl edx,0x6`); a consumer of ours must bound it against
|
||||
/// the ten slots that array really has.
|
||||
pub fn player_guild_rank(&self) -> u32 {
|
||||
self.get_u32(FIELD_PLAYER_GUILDRANK).unwrap_or(0)
|
||||
}
|
||||
/// `PLAYER_FIELD_BYTES` byte 0 bit `0x08` — `PLAYER_FIELD_BYTE_RELEASE_TIMER`, "Display time
|
||||
/// till auto release spirit" (the header's own comment): set at death iff the map is
|
||||
/// non-instanceable, i.e. exactly when the server will force-release after 6:00. The client
|
||||
|
||||
Reference in New Issue
Block a user