View: Multi-Page Single Page

Turn Systems

Five pluggable turn systems — from classic round-robin to press turns and spend/save AP.

ITurnSystem Interface

All turn systems implement ITurnSystem. This is the shared contract that Battle uses to manage turn order. You can also implement your own.

public interface ITurnSystem
{
    void Init(List<ICombatant> combatants);
    ICombatant GetNextActor();
    IReadOnlyList<ICombatant> GetTimeline();
    void OnActorDied(ICombatant combatant);
    void OnActorAdded(ICombatant combatant);
    void OnTurnEnd();
}

Methods

  • Init(combatants) — called once when the battle starts. Sets up internal state from the combatant list.
  • GetNextActor() — returns the next combatant who should act, or null if no one is ready.
  • GetTimeline() — returns a read-only list representing upcoming turn order. Useful for UI previews.
  • OnActorDied(combatant) — notifies the turn system that a combatant died so it can clean up.
  • OnActorAdded(combatant) — notifies the turn system that a combatant was added mid-battle.
  • OnTurnEnd() — called after an actor finishes their turn. Advances internal state.

ClassicTurnSystem

DQ-style speed-sorted round-robin. Simple and predictable.

Constructor

new ClassicTurnSystem()  // No parameters

Behavior

  • On init (and at the start of each new round), all alive combatants are sorted by Speed descending.
  • Dead combatants are skipped automatically in GetNextActor().
  • Mid-round additions via OnActorAdded() are appended to the end of the current round.
  • When all combatants in the round have acted, a new round begins with a fresh speed sort.

Additional Methods

None. ClassicTurnSystem only exposes the ITurnSystem interface.

Usage

var battle = new Battle();
battle.Start(combatants, new ClassicTurnSystem());

var actor = battle.BeginNextTurn(); // Fastest combatant
// ... do action ...
battle.EndTurn();

ATBTurnSystem

Active Time Battle (gauge-based, FF-style). Gauges fill in real time based on speed.

Constructor

new ATBTurnSystem(float gaugeMax = 100f)
  • gaugeMax — the gauge value a combatant must reach before they can act. Default: 100f.

Behavior

  • Each combatant has a gauge starting at 0.
  • Tick(deltaTime) fills each alive combatant's gauge by Speed * deltaTime. Already-full gauges do not overflow.
  • GetNextActor() returns the ready combatant (gauge >= max) with the highest gauge. Ties broken by speed. Returns null if no one is ready.
  • After acting, OnTurnEnd() resets the actor's gauge to 0.
  • Dead combatants have their gauge removed entirely.

Additional Methods

MethodDescription
Tick(float deltaTime)Advances all alive combatants' gauges by Speed * deltaTime.
IsReady(ICombatant)Returns true if the combatant's gauge >= max.
GetGauge(ICombatant)Returns current gauge value (or 0 if not tracked).
SetGauge(ICombatant, float)Sets gauge value directly (e.g. for slow/haste effects).
HasReadyActor()Returns true if any alive combatant's gauge >= max.

Usage

var atb = new ATBTurnSystem(100f);
battle.Start(combatants, atb);

// Game loop
atb.Tick(1f); // Advance time
if (atb.HasReadyActor())
{
    var actor = battle.BeginNextTurn();
    // ... do action ...
    battle.EndTurn();
}
Real-time system. You drive the clock by calling Tick() yourself. This works with Unity's Time.deltaTime, fixed timesteps, or any custom tick rate.

TimelineTurnSystem

Charge Time Battle (timeline-based, FFT-style). Combatants sit on a tick timeline; lower tick = sooner turn.

Constructor

new TimelineTurnSystem(int defaultActionCost = 100, int baseTick = 100)
  • defaultActionCost — the default cost added after an action. Default: 100.
  • baseTick — base tick value used for initial placement and new combatants. Default: 100.

Behavior

  • On init, each combatant is placed on the timeline at tick baseTick / Speed. Faster combatants start closer to 0.
  • GetNextActor() returns the alive combatant with the lowest tick. Ties broken by highest speed, then init order.
  • After acting, the actor's tick advances by actionCost (default or overridden via SetActionCost()).
  • Heavy actions with higher costs push the actor further down the timeline. Light actions let them act again sooner.
  • New combatants added mid-battle are placed at currentTick + baseTick.

Additional Methods

MethodDescription
SetActionCost(int cost)Override the cost for the current action. Call between BeginNextTurn() and EndTurn(). Resets to default each turn.
GetTick(ICombatant)Returns the combatant's current tick value on the timeline.

Usage

var timeline = new TimelineTurnSystem(100, 100);
battle.Start(combatants, timeline);

var actor = battle.BeginNextTurn(); // Lowest tick actor

// Light attack — default cost
battle.EndTurn();

var next = battle.BeginNextTurn();
timeline.SetActionCost(200); // Heavy attack — delays next turn more
battle.EndTurn();
Action cost strategy. Use SetActionCost() to make different abilities cost different amounts of time. A quick jab might cost 50, a powerful spell 300. This creates meaningful tactical decisions about speed vs. power.

PressTurnSystem

SMT-style press turn system. Teams take turns in phases, spending turn points to act.

Constructor

new PressTurnSystem(int maxPointsPerTeam = 0)
  • maxPointsPerTeam — cap on points per phase. 0 = auto (one point per alive team member).

Behavior

  • Teams are determined from combatant Team values, sorted ascending. Team 0 goes first.
  • Each team phase starts with full points = number of alive members (capped by maxPointsPerTeam if set).
  • You choose who acts via SelectActor(), then call GetNextActor() to retrieve them.
  • Actions consume or convert points. When points are exhausted, the next team's phase begins.
  • A KO mid-phase does not retroactively shrink points — dead actors simply cannot be selected.

Properties

PropertyTypeDescription
ActiveTeamintThe team ID currently taking their phase.
FullPointsintRemaining full turn points.
HalfPointsintRemaining half turn points.
TotalPointsintFull + half points combined.
HasActionsRemainingbooltrue if TotalPoints > 0.

Additional Methods

MethodDescription
SelectActor(ICombatant)Choose who acts next. Must be alive and on the active team. Throws if not.
ConsumeAction()Spends one point. Consumes a half point first; if none, consumes a full point.
ConvertAction()Converts one full point into a half point. If no full points, consumes a half point instead.
ConsumeActions(int count)Consumes multiple points (half first, then full).
ConsumeAllActions()Ends the team's phase immediately by zeroing all points.

Usage

var press = new PressTurnSystem();
battle.Start(combatants, press);

// Team 0's phase — 1 point per alive member
press.SelectActor(myChosenActor);
var actor = battle.BeginNextTurn();
// ... do action ...
press.ConsumeAction();
battle.EndTurn();

// If points remain, select another actor
if (press.HasActionsRemaining)
{
    press.SelectActor(anotherActor);
    var next = battle.BeginNextTurn();
    // ... hit a weakness? Convert instead of consume ...
    press.ConvertAction();
    battle.EndTurn();
}
You manage the points. SimpleJRPG does not decide when to consume vs. convert — that is your game logic. Hitting a weakness, getting a critical, or missing are all your system's responsibility. Call the appropriate point method based on your rules.

ActionPointTurnSystem

Action Point system. Combatants save or spend Action Points for extra actions.

Constructor

new ActionPointTurnSystem(int defaultAP = 0, int minAP = -4, int maxAP = 4)
  • defaultAP — starting AP for each combatant. Default: 0.
  • minAP — lowest AP can go (going negative means skipping future turns). Default: -4.
  • maxAP — highest AP can be saved. Default: 4.

Behavior

  • Uses speed-sorted round-robin like ClassicTurnSystem for base turn order.
  • At the start of each round, all alive combatants gain +1 AP passively (capped at maxAP).
  • SpendAP() spends 1 AP to queue an extra action this turn. Can be called multiple times. AP can go negative down to minAP.
  • SaveAP() gains 1 AP (capped at maxAP) and the combatant skips their action.
  • Combatants with negative AP are skipped when their turn comes — they must wait for passive AP to bring them back to 0.
  • If a combatant dies mid-action-chain, remaining extra actions are cleared.

Properties

PropertyTypeDescription
MinAPintThe minimum AP value (constructor param).
MaxAPintThe maximum AP value (constructor param).

Additional Methods

MethodDescription
GetAP(ICombatant)Returns the combatant's current Action Points.
SpendAP()Spend 1 AP for an extra action this turn. Throws if already at minAP.
SaveAP()Gain 1 AP (capped at maxAP). The combatant should skip their action.

Usage

var ap = new ActionPointTurnSystem(0, -4, 4);
battle.Start(combatants, ap);

var actor = battle.BeginNextTurn();

// Option A: Spend AP — take multiple actions now, risk negative AP
ap.SpendAP(); // AP: 0 -> -1, queues 1 extra action
// ... do first action ...
battle.EndTurn();
// Extra action fires — same actor again
var same = battle.BeginNextTurn();
// ... do second action ...
battle.EndTurn();

// Option B: Save AP — skip turn, bank AP for later
var next = battle.BeginNextTurn();
ap.SaveAP(); // AP +1
battle.EndTurn(); // Skips action
Risk vs. reward. Spending AP lets you burst multiple actions in one turn but leaves you vulnerable if AP goes negative. Saving AP is safe but costs a turn. The tension between the two is the core of this system.

Comparison Table

Feature Classic ATB Timeline Press Turn Action Point
Turn order Speed sort Gauge fill Tick timeline Team phase Round-robin
Real-time No Yes (Tick) No No No
Player choice in order No No Via action cost SelectActor Spend/Save AP
Team-based No No No Yes No
Resource management None None Action cost Turn points AP
↓ ↑