Skip to content

feat: show melee swing errors and the periodic, miss and energize combat log - #700

Merged
Mathih13 merged 3 commits into
mainfrom
feat/opcode-parity-combat-spell
Oct 15, 2026
Merged

Mathih13 merged 3 commits into
mainfrom
feat/opcode-parity-combat-spell

Conversation

@Mathih13

@Mathih13 Mathih13 commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

The 1.12.1 client gave too little combat feedback on LyraCore. A player who swung at a target out of reach or behind them got no message. Damage-over-time, heal-over-time and energize ticks did not show in the combat log. A spell that missed looked like a hit for zero damage. Bystanders of an interrupted player cast kept a full cast bar.

The Module now records these outcomes, and the Gateway sends the vanilla messages for them:

  • Swing Error. A player's due melee swing (either hand) that is out of reach or faces away stores a Swing Error on the engagement row. A landed swing clears it. The Gateway sends SMSG_ATTACKSWING_NOTINRANGE or SMSG_ATTACKSWING_BADFACING once per change, as vmangos Unit::UpdateMeleeAttackingState does.
  • Periodic ticks. Each periodic damage, heal or energize tick writes a PERIODIC_LOG Spell Cast Event (kind 6), addressed at the target. A heal tick on a unit at full health writes nothing, as in vmangos. The Gateway sends SMSG_PERIODICAURALOG as raw bytes because gtker writes the damage school as one byte where the client reads a u32.
  • Cast Miss. A damage spell now rolls its hit once per target, before any effect lands, as vmangos rolls one hit result per target. A missed target takes none of the spell's effects, so a resisted Frostbolt no longer slows and a resisted Moonfire no longer ticks. The GO row records the Cast Miss. Observers read it in the SMSG_SPELL_GO miss list: a miss for a physical spell, a resist for a magic one. The caster of a synced instant cast already holds a GO from the cast handler, so it gets SMSG_SPELLLOGMISS instead.
  • Energize. A direct energize records the amount and power type on the GO row. The Gateway sends SMSG_SPELLENERGIZELOG.
  • Gateway-only changes.
    • SMSG_SPELL_FAILED_OTHER goes to bystanders of an interrupted player cast.
    • SMSG_AI_REACTION (hostile) plays before a creature's attack start, for live engagements only. A reconnect replays only the attack start.
    • The player who lands a melee killing blow gets SMSG_PARTYKILLLOG. A swing that ends a Duel is no killing blow. vmangos sends the line to the tagger or a pet's owner, and to the party. Those copies and spell kills are not sent, because the tag is gone from the cache when the relay runs.
    • Mount refusals name the vanilla cast failure.
    • A pet-bar cast gets SMSG_PET_CAST_FAILED and a System Message.
    • CMSG_CANCEL_GROWTH_AURA and CMSG_REQUEST_PET_INFO are ignored explicitly.

The new columns are end-appended with defaults. The paired packages branch feat/opcode-parity-combat-spell sets swing_error: 0 in the playerbots fixture. CONTEXT.md adds Swing Error and Cast Miss.

Verification

Rebased onto main after #696, #698, #699, #701, #702 and #704. #699's root relay and #702's stand-up on damage are unchanged. A missed spell applies no effects, so it deals no damage and stands no one up.

Checks run locally, under the build lock:

  • cargo fmt --all -- --check
  • cargo clippy -p lyracore-gateway --all-targets -- -D warnings
  • cargo test -p lyracore-gateway
  • cargo clippy -p lyracore-module --all-targets --features=debug_reducers -- -D warnings
  • cargo test -p lyracore-module --lib --features=debug_reducers
  • cargo test -p lyracore-shared
  • the wasm check
  • the durable targets with --no-run

The durable tests are module/tests/swing_error.rs, module/tests/combat_log.rs (periodic ticks, energize, and a resisted spell applying none of its effects) and module/tests/duel_killing_blow.rs. I did not run them locally: they start SpacetimeDB, which crashes this machine. CI's module-durable workflow runs them.

Comment review (CODING_STANDARDS.md, "Comment review"):

  • Scope. Every added or changed comment in the final diff against main, across Gateway and Module source, the Gateway tests and the three new durable test files.
  • Result: passed. Each remaining comment is one of these:
    • a packet layout, opcode or constant value;
    • a compatibility quirk, such as gtker's one-byte damage school or 1.12 having no line-of-sight swing message;
    • a lockstep code contract;
    • an ordering constraint (the instant caster already holds a GO);
    • one-line reasons for the two explicit ignores.
  • Moved to docs. The kill-line audience reasoning is now in docs/benilla-compatibility.md under "Combat feedback". A pointer remains in the relay, and the resolver comment points to CONTEXT.md "Cast Miss". Both pointers resolve.
  • No contracts lost. The diff removes no comment from main.

Made with Claude Opus 5.5 in Claude Code.

🤖 Generated with Claude Code

Mathih13 and others added 3 commits October 15, 2026 13:17
…ergize

A player's due melee swing that cannot reach or face its target stores a
Swing Error on the engagement row; a landed swing clears it. Each periodic
damage, heal or energize tick writes a PERIODIC_LOG cast event at the target,
except a heal on a full-health unit. A damage spell rolls its hit once per
target, so a missed target takes none of its effects, and the GO row carries
the Cast Miss and any energize. A swing that ends a Duel is no killing blow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…sages

Relay SMSG_ATTACKSWING_NOTINRANGE and _BADFACING on a Swing Error change,
SMSG_PERIODICAURALOG for each tick, SMSG_SPELLENERGIZELOG, the GO miss list
and SMSG_SPELLLOGMISS for an instant caster, SMSG_SPELL_FAILED_OTHER to
bystanders, SMSG_AI_REACTION on a live creature aggro and SMSG_PARTYKILLLOG
to the killer. Refuse pet-bar casts, ignore growth-aura and pet-info requests,
and name mount refusals.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Mathih13
Mathih13 force-pushed the feat/opcode-parity-combat-spell branch from d96c322 to f692c89 Compare October 15, 2026 11:17
@Mathih13
Mathih13 merged commit 9be23cd into main Oct 15, 2026
9 checks passed
@Mathih13
Mathih13 deleted the feat/opcode-parity-combat-spell branch October 15, 2026 11:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant