Skip to content

Battle Event

Battle events describe observable occurrences such as skill execution, damage, healing, and status changes. Each event contains:

  • event_type: the stable discriminator used to select the event shape
  • description: human-readable display text
  • data: structured facts for that event type

Use structured data

Use event_type and data for application logic. Do not parse description. Its wording may change without changing the event contract.

For example, an action_missed event uses its data to identify the action, source, target, and configured chance:

{
  "event_type": "action_missed",
  "description": "Heavy hit did not trigger.",
  "data": {
    "source_id": "fighter-1",
    "source_name": "Attacker",
    "target_id": "fighter-2",
    "target_name": "Defender",
    "action_source": {
      "type": "active_skill",
      "skill_id": "heavy-strike",
      "skill_name": "Heavy Strike"
    },
    "action_name": "Heavy hit",
    "action_type": "attack",
    "configured_chance": 0.8
  }
}

Looking for exact fields?

Use the OpenAPI reference for every field available on each event. This page focuses on meaning and common client uses.

Skill and action events

Event type Meaning Typical client use
execute_skill An active or fallback skill was selected. For an active skill, its energy cost was applied. Start the skill animation and update energy when an active skill runs.
execute_passive_action A passive trigger is executing one of its actions. Show the passive source before its effects.
skill_missed The selected skill failed its chance check. Show a skill-level miss and skip its actions.
action_missed One action failed its chance check for a target. Show an action-level miss. Later actions may continue.
action_no_effect A status action passed its chance check, but its target was already knocked out. Keep the skill replay in sequence without changing status state.

execute_passive_action is distinct from execute_skill: it identifies the passive trigger and action that caused the subsequent effects.

Direct damage, healing, missed actions, and no-effect actions include action_source. Its type distinguishes active_skill (including fallback skills) from passive_trigger. Use the skill identity or runtime trigger identity to connect an effect to its origin.

When an active skill continues after knocking out its opponent, later actions still produce replayable events. Attacks and heals use their normal event types with an applied amount of 0. Applying or removing a status produces action_no_effect with reason: "target_knocked_out". A failed chance check is resolved first and produces action_missed instead.

Damage, healing, and shield events

Event type Meaning Typical client use
deal_damage Direct attack damage was resolved. Animate the hit and update health and shields.
dot_damage A damage-over-time status damaged its target. Animate the status tick and health change.
heal A skill or modifier restored health or energy. Animate restoration and update the resource.
shield_changed Shield contributions changed through application, replacement, removal, or damage absorption. Update individual shields and the combined shield bar.
energy_regeneration End-of-turn energy regeneration was applied. Update energy from turn_end.events.
health_regeneration End-of-turn health regeneration was applied. Update health from turn_end.events.

Note

There is no separate receive_damage event. deal_damage and dot_damage already identify the target and resulting health change.

For dot_damage, damage_calculated is the whole-number damage after DOT reduction and rounding. damage_applied is the health actually lost, bounded by remaining health. Use the applied amount to update the health bar.

For shield_changed, data.trigger.type explains why the shield changed. data.statuses records each affected runtime status and its nested shield_contribution transition. data.aggregate_shield gives the combined before, change, and after values. Apply this transition once, even when a later deal_damage event also reports the amount absorbed by shields.

Status and passive events

Event type Meaning Typical client use
apply_passive_trigger A passive trigger was applied during preparation. Add its passive indicator.
apply_status A buff or debuff was applied. Add the new status instance and update the displayed stack count.
apply_status_rejected A stack-policy status was rejected because it was already at maximum stacks. Show rejection without changing the existing statuses.
replace_status A replace-policy status replaced an existing same-name instance. Replace the old status identity with the new one.
remove_status A status was removed, expired, or depleted, or a removal action produced no match or invalid criteria. Branch on the outcome and cause before updating statuses.

apply_passive_trigger identifies the trigger's owner with owner_id and owner_name. Applying a trigger does not itself target a fighter with an action.

Status identities matter during replay. Use the IDs in structured data rather than matching display names or descriptions.

For replace_status, data.reason: "replace_policy" identifies replacement by the active same-name group's policy.

For remove_status, branch on data.outcome first. When the outcome is removed, use data.cause to distinguish removal_action, duration_expired, or shield_depleted. Natural expiry events use cause: "duration_expired" and appear in turns[].turn_end.events.

Unsuccessful removals report no_removable_status_matched or no_removal_criteria in data.outcome. They do not change status state.

Where events appear

Battle events are grouped by when they occur:

Event array What it contains
preparation[].events Effects applied while preparing one fighter
turns[].events Skill, action, damage, healing, status, shield, and passive events processed before turn end
turns[].turn_end.events Energy regeneration, health regeneration, and natural status expiry processed at turn end

Process each array in its returned order. Within a turn, process events first, followed by turn_end.events. Then reconcile the fighter snapshots in turn_end.state.

See Understanding BattleResult for the replay order and the difference between battle_turn and actor_turn.