Combat State Replication¶
Document: Technical Design – Combat – Combat State Replication
Status: Exploratory
Last updated: 2026-01-12
1. Purpose¶
This document defines how combat state is represented, replicated, and validated in Atherion.
Goals:
- server-authoritative combat outcomes
- responsive, rhythm-safe gameplay
- readable combat at MMO scale
- scalable replication via SpacetimeDB
- predictable latency handling
Combat must feel immediate without trusting the client.
2. Core Replication Philosophy¶
2.1. Authority Model¶
-
The server (SpacetimeDB module) is authoritative over:
- health
- damage
- buffs / debuffs
- cooldowns
- threat / attention
- stagger / break states
-
The client is authoritative only over:
- local input intent
- animation playback
- camera and presentation
The client never decides outcomes.
2.2. Intent-Based Combat¶
Clients send intent, not results.
Examples:
- “Attempt Block”
- “Attempt Skill X at Target Y”
- “Attempt Dodge in Direction Z”
The server:
- validates
- resolves timing
- mutates state
- publishes results
3. Combat State Granularity¶
3.1. Persistent Combat State¶
Stored in tables and replicated via subscriptions:
CombatantState
--------------
entity_id: EntityId
current_hp: int
max_hp: int
resource: int
status_flags: bitmask
position: Vector3
facing: Vector3
Used for:
- rendering
- targeting
- validation
- UI
⸻
3.2. Transient Combat Events¶
Not stored permanently; emitted as events:
- damage application
- stagger triggers
- successful blocks
- interrupts
Events are:
- timestamped
- ordered per entity
- consumed by clients for feedback
⸻
4. Tick Rate Strategy¶
4.1. Variable Tick Domains¶
Combat uses multiple logical tick domains:
| Domain | Purpose | Tick Rate |
|---|---|---|
| World | Movement, positioning | ~10–15 Hz |
| Combat Resolution | Damage, blocks, hits | ~20–30 Hz |
| UI / FX | Visual updates | Client-side |
SpacetimeDB modules resolve combat on combat ticks, not world ticks.
4.2. Why Not Ultra-High Tick Rates¶
- MMO scale makes 60+ Hz impractical
- Latency hiding is achieved via prediction + reconciliation
- Precision comes from timing windows, not raw frequency
⸻
5. Client-Side Prediction¶
5.1. What Is Predicted¶
Clients may predict:
- movement
- animation start
- dodge start
- block posture
Clients do not predict:
- damage numbers
- stagger success
- buff application
⸻
5.2. Reconciliation Rules¶
If server disagrees:
- client corrects silently
- animation blends to authoritative state
- no rewind-based correction (avoid jank)
Visual correction is favored over mechanical rewind.
⸻
6. Timing Windows (Critical)¶
6.1. Action Windows¶
Every combat action defines:
- wind-up window
- active window
- recovery window
The server validates intent based on timestamps, not animation frames.
⸻
6.2. Example: Vanguard Block¶
- Client sends AttemptBlock(timestamp)
- Server checks:
- block window active?
- stamina/resource sufficient?
- facing valid?
- If valid:
- damage mitigated
- stagger event emitted
- Clients receive:
- block success event
- boss stagger state
No pause. No cinematic.
⸻
7. Stagger and Break States¶
7.1. Server-Owned States¶
StaggerState
------------
entity_id: EntityId
stagger_level: int
is_exposed: bool
expires_at: timestamp
- Triggered by coordinated actions
- Short-lived
- Explicitly timed
Clients react instantly.
⸻
8. Buffs and Debuffs¶
8.1. BuffState Table¶
BuffState
---------
entity_id: EntityId
buff_id: BuffId
source_id: EntityId
expires_at: timestamp
- No permanent buffs
- No infinite stacking
- Server controls duration
Clients render icons + effects.
⸻
9. Threat and Attention¶
Threat is:
- computed server-side
- soft-weighted
- influenced by taunts and mechanics
No threat UI bars by default.
⸻
10. Subscriptions and Replication Scope¶
Clients subscribe only to:
- nearby combatants
- relevant bosses
- party members
This limits:
- bandwidth
- processing cost
- visual noise
⸻
11. Instance Isolation¶
Each combat instance:
- has its own combat tick loop
- no cross-instance combat state
- clean teardown on completion
Supports Everspire and dungeon scaling.
⸻
12. Anti-Cheat and Trust Boundaries¶
- Clients cannot fabricate hits
- Clients cannot alter cooldowns
- All combat reducers validate:
- timestamps
- resources
- state preconditions
Desync resolves in favor of server.
⸻
13. Performance Considerations¶
- No per-frame combat writes
- Events are batched per tick
- State tables are compact
- Combat math avoids dynamic allocation
⸻
14. Why This Works¶
This model:
- preserves combat rhythm
- scales to MMO populations
- supports skill-based play
- works with SpacetimeDB’s strengths
- avoids client trust pitfalls
Combat feels responsive without sacrificing authority.
⸻
15. Open Questions¶
- How much client-side interpolation is acceptable?
- Should boss attacks be fully deterministic?
- Should latency tolerance vary by content type?
- How visible should correction be to players?
These will be answered via prototyping.
⸻
End of document.