Skip to content

Combat Trainer Plugins

Mahtra edited this page Aug 2, 2026 · 1 revision

Combat-Trainer Plugins

combat-trainer supports the shared Script Plugin System - read that page first for how plugins are written, loaded, and dispatched. This page lists the hooks combat-trainer fires.

Plugin file scripts/custom/combat-trainer-plugin-<name>.rb
Register with CombatTrainer.register_plugin(MyPlugin.new)
Global handle $COMBAT_TRAINER
Debug flag $debug_mode_ct (set ;e $debug_mode_ct = true to see plugin errors and traces)

Hook catalog

In the signatures below, trainer is the live CombatTrainer instance and game_state is the current combat GameState. Kind is either decision (first non-nil return wins) or notify (all plugins called, return ignored).

Lifecycle hooks

Hook Kind Fires
after_initialize(trainer) notify Once, when the trainer has finished constructing, before combat begins
before_combat(trainer, game_state) notify Once, at the top of the combat loop, before the first iteration
combat_tick(trainer, game_state, counter:) decision Once per loop iteration, after the combat processes run
after_combat(trainer, game_state) notify Once, after the combat loop exits
cleanup(trainer) notify Once, during teardown (including abnormal exits)

combat_tick is the only lifecycle hook whose return value is honored: return :break to stop the combat loop. counter is the 1-based iteration count. Any other return value is ignored.

Feature seams

These are fired by combat-trainer's internal combat processes at specific decision points:

Hook Kind Fires
warhorn_cooldown_active?(room_id:) decision Before applying a warhorn/egg room effect, to decide whether it is still active
warhorn_applied(room_id:, type:) notify Right after a warhorn/egg room effect is applied
  • warhorn_cooldown_active? - return true to skip a fresh application (still on cooldown), false to allow it now, or nil to defer to combat-trainer's built-in per-character 600-second timer.
  • warhorn_applied - type is "warhorn" or "egg". Use it to record the application in your own store (e.g. a shared, room-scoped cooldown).

More seams may be added over time. Implement only the hooks you need, and tolerate new ones appearing.

Example: stop combat after N ticks

# scripts/custom/combat-trainer-plugin-ticklimit.rb
class TickLimitPlugin
  def initialize(max_ticks: 500)
    @max_ticks = max_ticks
  end

  def after_initialize(_trainer)
    echo "[ticklimit] loaded; will stop after #{@max_ticks} ticks"
  end

  # Decision hook: returning :break ends the combat loop.
  def combat_tick(_trainer, _game_state, counter:)
    :break if counter >= @max_ticks
  end

  def cleanup(_trainer)
    echo '[ticklimit] cleaning up'
  end
end

CombatTrainer.register_plugin(TickLimitPlugin.new(max_ticks: 300))

Clone this wiki locally