- Duels. Challenge another player from their right-click menu, or with `/duel`, and `/forfeit` to give it up. Both popups are there — the challenge you accept or decline, and the warning when you leave the field — with the flag countdown between them, and the outcome printed in chat when someone is knocked out or flees. Read off the reference client's own duel packets and the three globals it keeps client-side, which is why the challenger reads "You have requested a duel." even though the server never echoes that back. - Inspect. Right-click a player and open their paper doll: their nineteen publicly visible equipment slots with icon, name, quality and a linkable item, and their body standing in the pane, which follows along if you retarget while the window is open. No stack counts and no durability — those are not fields another player publishes, which is exactly why the reference client's inspect doll has never shown them either. - Water knows where it stops. Swimming used to trigger in the dry tunnel thirty yards under Stormwind's canal, and in mid-air over Blackrock's lava. A liquid is now the grid the map file actually stores — one wet flag per cell, and the surface height a bilinear over the four corners of the cell you are standing in, the same sample the reference client takes — so the water starts at the bank and its surface sits where your eye puts it. Lava is a liquid you swim in, an indoor liquid asks the building you are inside, and `/liquid` prints every surface claiming your feet and where each one came from. - Creature parts authored to appear only on death — the voidwalker, the banshee, the ooze, the stone elemental, the infernal — were drawing the whole time: material alpha now bakes per animation sequence and the unit lane actually evaluates it. The character and inspect model panes are lit by the reference widget's own single light instead of blowing out white, the rotate arrows spin while you hold them, and the transparent sort ladder had its sign backwards, so overhead names draw over water again instead of being painted out by a canal behind them. Underneath, the protocol writer's 95-verb drawer and its thousand-line spell module split into per-family files — no behaviour change, just a tree you can find things in. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
32 lines
2.0 KiB
Rust
32 lines
2.0 KiB
Rust
//! The two **client-volunteered pose** bodies — sheath state and stand state. Split out of
|
|
//! `messages/spells.rs` (`set_sheathed`) and `messages/client.rs` (`stand_state_change`) by
|
|
//! decision 0640, which is also what mirrors `world::writer::pose`.
|
|
//!
|
|
//! They were apart for no reason anyone recorded, and they are plainly one thing: the client
|
|
//! decides, the server stores whatever we send with no validation of its own, and the echo into our
|
|
//! `UNIT_FIELD_BYTES_2` / `UNIT_FIELD_BYTES_1` is what every observer's body reads (decisions
|
|
//! 0080 / 0080c). The server has no independent way to know a weapon is drawn or that we sat down —
|
|
//! so the only consequence of getting one wrong is that other players see the wrong body.
|
|
//!
|
|
//! `CMSG_MOUNTSPECIAL_ANIM`, the third member of that family, has an empty body and so needs no
|
|
//! builder here (see `world::writer::pose`).
|
|
|
|
/// Body of `CMSG_SETSHEATHED` (vmangos `SetSheathed::ReadFromWorldPacket`: `recv_data >> sheathed`):
|
|
/// one `u32` sheath state (0 unarmed/stowed, 1 melee drawn, 2 ranged drawn). Purely
|
|
/// client-volunteered — `HandleSetSheathedOpcode` (`CombatHandler.cpp:80-87`) just stores whatever
|
|
/// we send via `Unit::SetSheath`, which lands in our own `UNIT_FIELD_BYTES_2` and relays to nearby
|
|
/// observers on the next values update; the server has no independent way to know a weapon is drawn.
|
|
pub fn set_sheathed(state: u32) -> Vec<u8> {
|
|
state.to_le_bytes().to_vec()
|
|
}
|
|
|
|
/// Body of `CMSG_STANDSTATECHANGE` (vmangos `StandStateChange::ReadFromWorldPacket`:
|
|
/// `recv_data >> animState`): one `u32` stand state. The server accepts only
|
|
/// {0 STAND, 1 SIT, 3 SLEEP, 8 KNEEL} (`HandleStandStateChangeOpcode`,
|
|
/// `MiscHandler.cpp:437`) and applies it via `Unit::SetStandState` → `UNIT_FIELD_BYTES_1`
|
|
/// byte 0, which relays to every observer — the same client-volunteers → server-echoes →
|
|
/// fields-drive-everyone pattern as sheath (decision 0080c).
|
|
pub fn stand_state_change(state: u32) -> Vec<u8> {
|
|
state.to_le_bytes().to_vec()
|
|
}
|