Skip to content

Client: spell cast sync for remote players#56

Merged
Kheartz merged 3 commits into
mainfrom
spell-cast
Jun 27, 2026
Merged

Client: spell cast sync for remote players#56
Kheartz merged 3 commits into
mainfrom
spell-cast

Conversation

@Kheartz

@Kheartz Kheartz commented Jun 27, 2026

Copy link
Copy Markdown
Collaborator

Remote players' spell casts now replay on their proxies; the cast animation plus the real spell VFX/projectile, aimed in 3D. Stacks on the locomotion/broom wire (the Cast flag + spellId/aimPitch fields were already reserved in human_sync.hpp), so no new netcode bump.

Owning client publishes (UpdateLocal):

  • Detects a combat cast via the combat-AnimBP's FullBodyState == 7 (full-body/rooted casts).
  • Publishes the Cast flag, which spell as a 1-based id into the spell_records.hpp allowlist (~80 DA_*SpellRecords), and the aim pitch (GetControlRotation().Pitch, clamped ±90 into a signed byte — the on-foot body never pitches, so vertical aim needs its own field).

Remote proxy applies (UpdateCast, on the Cast flag's rising edge):

  • Plays a cast montage into the AnimBP's DefaultSlot (over the running locomotion).
  • Resolves the synced id → record path, loads it, and fires the real spell via SpellHelper::CastSpell, aimed from synced facing-yaw + the synced pitch (forward = (cosP·cosY, cosP·sinY, sinP)).

The allowlist (range-checked, append-only, 1-based) bounds what a proxy can load — an out-of-range/hostile id just no-ops, never an arbitrary asset load.

Test command: /spawnnpc, t

  • Arm pose is generic--only the fired spell's direction follows aimPitch; the cast arm montage is one full-body clip and doesn't bend to the angle. Matching the arm would need an aim-offset/additive pose (tracked as a follow-up, cosmetic).
  • v1 plays one generic cast montage regardless of spell; per-spell cast clips are out of scope here.
  • New reflection helper PlaySlotMontageOnSkin; shared HumanEntity::IsCasting().

Kheartz added 3 commits June 27, 2026 03:46
On the owning client, detect a combat cast (combat-AnimBP FullBodyState==7),
publish the Cast flag + which spell (1-based spell_records.hpp allowlist id) +
aim pitch (the body never pitches on foot). On the rising edge the proxy plays a
cast montage into DefaultSlot and fires the real spell via SpellHelper::CastSpell
(VFX/projectile), aimed from synced facing-yaw + pitch. Allowlist id (not a raw
path) so a proxy can only ever load a known spell record. Adds PlaySlotMontageOnSkin.
Add Human.setCasting(bool, spellId) binding and a /castnpcs command that loop-
toggles the Cast flag on spawned NPCs (id 6 = Confringo) so each rising edge
makes the proxy play the cast montage + fire the real spell — single-client test.
@Kheartz Kheartz merged commit 740beb2 into main Jun 27, 2026
2 checks passed
@Kheartz Kheartz deleted the spell-cast branch June 27, 2026 08:06
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