The Interrupt Meta — How Stagger, Priority, and Cancel Windows Create Combat Depth

If your roguelike combat feels like two characters trading HP until one dies, the way to fix it is not bigger damage numbers. It is interaction rules between actions. The Interrupt Meta pattern gives every attack a priority tier so combat becomes a readable game of rock-paper-scissors.

Who This Helps

The Problem

In many roguelike combat systems, when player and enemy attack simultaneously, the result is just "whoever has more DPS wins." This flattens combat into a damage race. The Interrupt Meta solves this by giving every action a priority value and defining what happens when priorities collide:

Core Ideas

Priority Tiers

Assign every attack action a tier:

TIER_0: Light attacks (normal strikes, basic ranged)
TIER_1: Medium attacks (charged strikes, strong attacks)
TIER_2: Special attacks (ultimates, boss breath attacks)
TIER_3: Invulnerable actions (roar attacks, super-armor)

Rules: Same tier = both stagger. Lower tier gets interrupted by higher tier. Higher tier ignores lower tier.

Hyper Armor

During specific attacks, a combatant ignores lower-tier interruptions. This:

Stagger Chain

When an enemy takes enough stagger damage, they enter a staggered state:

Cancel Window

Players need to cancel out of attacks on reaction:

How to Apply It

1. Start With the Interrupt Resolver

type PriorityTier = 0 | 1 | 2 | 3;

interface CombatAction {
  actor: 'player' | 'enemy';
  priority: PriorityTier;
  damage: number;
  hasHyperArmor: boolean;
  staggerPower: number;
  recoveryFrames: number;
}

function resolveInterrupt(
  attacker: Combatant,
  defender: Combatant,
  incoming: CombatAction
): { attackerInterrupted: boolean; defenderInterrupted: boolean } {
  const current = defender.currentAction;
  if (!current) return { attackerInterrupted: false, defenderInterrupted: false };

  // Hyper armor ignores lower-tier attacks
  if (defender.hyperArmorActive && incoming.priority < current.priority) {
    return { attackerInterrupted: true, defenderInterrupted: false };
  }

  if (incoming.priority > current.priority) {
    defender.applyStagger(incoming.staggerPower);
    return { attackerInterrupted: false, defenderInterrupted: true };
  } else if (incoming.priority === current.priority) {
    attacker.applyStagger(current.staggerPower * 0.5);
    defender.applyStagger(incoming.staggerPower);
    return { attackerInterrupted: true, defenderInterrupted: true };
  } else {
    attacker.applyStagger(current.staggerPower);
    return { attackerInterrupted: true, defenderInterrupted: false };
  }
}

2. Add Stagger Accumulation

function applyStagger(target: Combatant, power: number) {
  if (target.isDowned) return;

  target.staggerGauge += power;

  if (target.staggerGauge >= target.staggerThreshold) {
    target.isStaggered = true;
    target.staggerDuration = 1500; // ms
    target.staggerGauge = 0;
    target.currentAction = null;
    eventBus.emit('combat:stagger', { target, duration: target.staggerDuration });
  }
}

3. Implement Player Cancel Windows

class PlayerActionState {
  private frameCount: number = 0;
  private commitWindow: number = 6;     // ~100ms at 60fps
  private recoveryStart: number = 12;   // ~200ms

  canCancel(): boolean { return this.frameCount >= this.recoveryStart; }
  isCommitted(): boolean { return this.frameCount < this.commitWindow; }
  tick() { this.frameCount++; }
}

4. Use Frame-Time, Not Frame-Count

For cross-engine portability, express windows in milliseconds rather than frame counts. This prevents the system from feeling different at 30fps vs. 144fps.

Reference Games

GameInterrupt MechanismNotable Trait
Monster HunterStagger system, part destructionStagger thresholds per body part; weapon types differ in stagger power
For HonorGuard break, riposteGuard break during block → defenseless; 3-direction attack system
Risk of Rain 2Stun lockConsecutive hits build stagger; Vandal class specializes in stagger
HadesDash-strike priorityDash attacks interrupt normal strikes; boss hyper-armor blocks dashes
Dead CellsStun + down5-hit chain → stun → bonus damage; no dodge during stun
Hyper Light DrifterInterrupt chainFast attacks interrupt slow ones; charged attacks have hyper-armor
SekiroPosture systemStagger gauge at zero = instant death; "push" rather than interrupt model

Common Mistakes

Stagger Lock

If the player can perpetually stagger an enemy, the boss feels weak. Fix: Stagger immunity gauge — each successive stagger in a window reduces the threshold, eventually granting full immunity.

Hyper Armor Abuse

If the boss has hyper-armor on everything, the player feels helpless. Fix: Hyper armor must come with explicit telegraphs (glowing body, audio sting) and time limits.

Opaque Priority System

If the player cannot understand why their attack got interrupted, they feel cheated. Fix: Show tier indicators visually (color, effect size) and teach the system explicitly in a tutorial.

Simultaneous Hit Ambiguity

When both sides attack on the same frame, who wins? Fix: Frame-level adjudication (1–2 frame difference decides) or always treat as a clash.

Checklist

References

  1. Monster Hunter series — stagger/down system (Capcom, 2004–)
  2. For Honor — guard break/riposte (Ubisoft, 2017)
  3. Risk of Rain 2 — stun lock mechanism (Hopoo Games, 2020)
  4. Hades — dash-strike priority (Supergiant Games, 2020)
  5. Dead Cells — stun/down system (Motion Twin, 2018)
  6. Hyper Light Drifter — interrupt chain (Heart Machine, 2016)
  7. Sekiro — posture system (FromSoftware, 2019)
  8. GDC Talk: "Combat Design in Action Games" (various years)