AI director

Tension and the pacing states

The director runs a six-state loop driven by how much the team is suffering. Peaks and relax phases are what give you breathing room, and Havoc takes them away.

The pacing manager is a state machine. It starts in the lowest build-up state and loops forever:

  1. Build-up low, build-up and build-up high: everything is allowed to spawn.
  2. Sustain peak: hordes, specials and trickles stop; only monsters may appear. This lasts 13-17 seconds at C5.
  3. Peak fade: still monsters only, for 30-35 seconds or until tension drops.
  4. Relax: patrols, monsters and scripted events are allowed, but no hordes, specials or trickles. This lasts 30-55 seconds at C5.
Pacing state ordermanagers/pacing/templates/default_pacing_template.lua:529
  state_orders = {
    build_up_tension_low = {
      next_state = "build_up_tension",
    },
    build_up_tension = {
      back_state = "build_up_tension_low",
      next_state = "build_up_tension_high",
    },
    build_up_tension_high = {
      back_state = "build_up_tension",
      next_state = "sustain_tension_peak",
    },
    sustain_tension_peak = {
      next_state = "tension_peak_fade",
    },
    tension_peak_fade = {
      next_state = "relax",
    },
    relax = {
      next_state = "build_up_tension_low",
    },
  },
Open managers/pacing/templates/default_pacing_template.lua at line 529 on GitHub
What each pacing state allowsmanagers/pacing/templates/default_pacing_template.lua:40
local DEFAULT_ALLOWED_SPAWN_TYPES = {
  build_up_tension_low = {
    hordes = true,
    monsters = true,
    roamers = true,
    specials = true,
    terror_events = true,
    trickle_hordes = true,
  },
  build_up_tension = {
    hordes = true,
    monsters = true,
    roamers = true,
    specials = true,
    terror_events = true,
    trickle_hordes = true,
  },
  build_up_tension_high = {
    hordes = true,
    monsters = true,
    roamers = true,
    specials = true,
    terror_events = true,
    trickle_hordes = true,
  },
  sustain_tension_peak = {
    hordes = false,
    monsters = true,
    roamers = false,
    specials = false,
    terror_events = false,
    trickle_hordes = false,
  },
  tension_peak_fade = {
    hordes = false,
    monsters = true,
    roamers = false,
    specials = false,
    terror_events = false,
    trickle_hordes = false,
  },
  relax = {
    hordes = false,
    monsters = true,
    roamers = true,
    specials = false,
    terror_events = true,
    trickle_hordes = false,
  },
}
Open managers/pacing/templates/default_pacing_template.lua at line 40 on GitHub

What raises tension

Tension is a number. The build-up states move forward when it crosses a threshold (26, 122 and 157 at C5) and back when it decays.

  • Health damage. Each point of health lost adds a small amount, divided by the number of players. Toughness damage adds nothing.
  • Bad events. At C5 a knock-down or death adds 60, a pounce 20, a net 15 and a daemonhost kill 75.
  • Kills, but only while tension is still under 50.

Tension decays at a fixed rate per state after one to three seconds without new tension. Sustain peak has a decay rate of 0, so the peak always runs its full timer.

Tension added by downs, deaths, pounces, netssettings/difficulty/minion_difficulty_settings.lua:908
minion_difficulty_settings.tension_to_add = {
  killed_by_daemonhost = {
    120,
    75,
    75,
    75,
    75,
    20,
  },
  knocked_down = {
    120,
    80,
    60,
    60,
    60,
    20,
  },
  netted = {
    15,
    15,
    15,
    15,
    15,
    5,
  },
  pounced = {
    60,
    20,
    20,
    20,
    20,
    10,
  },
  died = {
    60,
    60,
    60,
    60,
    60,
    20,
  },
}
minion_difficulty_settings.damage_tension_to_add = {
  damaged = {
    0.3,
    0.2,
Open settings/difficulty/minion_difficulty_settings.lua at line 908 on GitHub
Tension added per point of health damagesettings/difficulty/minion_difficulty_settings.lua:950
minion_difficulty_settings.damage_tension_to_add = {
  damaged = {
    0.3,
    0.2,
Open settings/difficulty/minion_difficulty_settings.lua at line 950 on GitHub
Tension decay per statemanagers/pacing/templates/default_pacing_template.lua:32
local DECAY_TENSION_RATES = {
  build_up_tension_low = _multiplier_step(1.25),
  build_up_tension = _multiplier_step(1.5),
  build_up_tension_high = _multiplier_step(2),
  sustain_tension_peak = _multiplier_step(0),
  tension_peak_fade = _multiplier_step(2),
  relax = _multiplier_step(2),
}
Open managers/pacing/templates/default_pacing_template.lua at line 32 on GitHub

What Havoc changes

From rank 16 all tension is multiplied by 0.5. That sounds kind, but tension is the thing that pushes the director into a peak and then a relax. With half the tension, the team stays in the build-up states, where everything spawns, for much longer.

Rank 16+: tension x0.5settings/mutator/templates/mutator_modify_pacing_templates.lua:710
  mutator_auric_tension_modifier = {
    class = "scripts/managers/mutator/mutators/mutator_modify_pacing",
    init_modify_pacing = {
      tension_modifier = 0.5,
    },
  },
Open settings/mutator/templates/mutator_modify_pacing_templates.lua at line 710 on GitHub

From rank 30 mutator_always_allow_all_spawn_types replaces the allowed spawns of every state with “everything”. Peaks and relax phases still happen on paper, but nothing stops spawning during them.

Rank 30+: every state allows every spawnsettings/mutator/templates/mutator_modify_pacing_templates.lua:655
  mutator_always_allow_all_spawn_types = {
    class = "scripts/managers/mutator/mutators/mutator_modify_pacing",
    init_modify_pacing = {
      override_allowed_spawn_types = {
        build_up_tension_low = {
          hordes = true,
          monsters = true,
          roamers = true,
          specials = true,
          terror_events = true,
          trickle_hordes = true,
        },
        build_up_tension = {
          hordes = true,
          monsters = true,
          roamers = true,
          specials = true,
          terror_events = true,
          trickle_hordes = true,
        },
Open settings/mutator/templates/mutator_modify_pacing_templates.lua at line 655 on GitHub

Below rank 16, a messy fight buys you a breather: a few downs push the director into a peak and then relax. At 16+ that breather comes much later, and at 30+ it never comes. The only real downtime is what you create by killing things fast. Hold a defensible spot and clear, rather than pushing ahead hoping for a lull.