Engine lifecycles

June 4, 2026 · View on GitHub

State machines and execution sequences in the LBA2 engine. Each section lists states with their code-level constants, the typical sequence, and where the logic lives.

Truth hierarchy: code > this document > external sources.

Main loop frame order

Each game frame executes these steps in order. Defined in MainLoop().

StepFunctionWhat it does
1MyGetInput() + ManageTime()Read player input and advance timer
2DoDir(i) per objectCompute movement direction
3DoTrack(i) per objectExecute track script (pathing)
4PtrDoAnim(i) per objectAdvance animations
5CheckZoneSce(i) per objectTest zone triggers
6DoLife(i) per objectExecute life script (behavior AI)
7AffScene()Render the scene

Code: SOURCES/PERSO.CPP (MainLoop), SOURCES/GERETRAK.CPP (DoTrack), SOURCES/GERELIFE.CPP (DoLife), SOURCES/OBJECT.CPP (CheckZoneSce)

Scene (cube) loading

Triggered by ChangeCube() when the hero enters a zone-type-0 trigger or a life script executes LM_CHANGE_CUBE.

PhaseWhat happens
1Unload current scene objects and zones
2Load collision grid (BufCube[]) for the new cube
3Load objects into ListObjet[] (up to MAX_OBJETS=100)
4Load zones into ListZone[] (up to MAX_ZONES=255)
5Set CubeMode (0=interior, 1=exterior)
6Initialize camera position

Code: SOURCES/OBJECT.CPP (ChangeCube), SOURCES/GRILLE.CPP (grid loading)

Object lifecycle

Objects are loaded when a scene starts and can be killed during gameplay.

StateMeaningTerminal?
AliveObject exists, scripts run each frameNo
DeadOBJ_DEAD bit set in WorkFlagsYes

Happy path: Alive (scripts running) -> LM_KILL_OBJ or LM_SUICIDE -> Dead

Transitions:

  • LM_KILL_OBJ (opcode 37): another object's life script kills this object
  • LM_SUICIDE (opcode 38): object kills itself
  • Both set OBJ_DEAD (bit 5) in WorkFlags

Code:

  • Constants: SOURCES/COMMON.H (OBJ_DEAD, LM_KILL_OBJ, LM_SUICIDE)
  • Transitions: SOURCES/GERELIFE.CPP (DoLife opcode handlers)

Hero behavior modes

The hero's Comportement determines movement style, available actions, and combat behavior. Changed by player input or by LM_COMPORTEMENT_HERO in life scripts.

Modes 0–3 are player-switchable; 4–13 are context-triggered. Full enum (constants and meanings): GLOSSARY.md#comportement-hero-behavior-modes.

Player-switchable core modes: Normal <-> Athletic <-> Aggressive <-> Stealth (via COMPORTEMENT input or NORMAL/SPORTIF/AGRESSIF/DISCRET direct inputs).

Other modes are context-triggered by life scripts (LM_COMPORTEMENT_HERO, opcode 30).

Code:

  • Constants: SOURCES/COMMON.H (C_NORMAL through C_SKELETON)
  • Transitions: SOURCES/PERSO.CPP, SOURCES/GERELIFE.CPP

Animation state

Each object has an animation that progresses through frames each tick.

StateMeaningTerminal?
PlayingLastFrame < NbFrames, NEW_FRAME set each tickNo
EndedANIM_END (bit 2) set in WorkFlagsYes (until new anim)

Happy path: Anim set (via LM_ANIM / LM_ANIM_OBJ) -> Playing -> ANIM_END

Scripts typically check ANIM_END before assigning the next animation. Looping animations restart automatically without setting ANIM_END.

Code:

  • State: T_OBJ_3D.LastFrame, T_OBJ_3D.NbFrames in LIB386/H/OBJECT/AFF_OBJ.H
  • Flags: ANIM_END, NEW_FRAME in SOURCES/COMMON.H
  • Anim engine: LIB386/ANIM/

This is the temporal view of the engine. Two companion maps give the other axes:

  • ARCHITECTURE_GLOBALS.mdstructure: the ~200 globals grouped into eight owning domains, with the shared-bus offenders. The pivots in the state machines above (ListObjet, CubeMode, Comportement) are its worst offenders.
  • ENGINE_GAME_SEAM.mdlayer: engine vs game vs platform, from a three-way diff against the LBA1 source. The main-loop steps DoTrack (3) and DoLife (6) are where the engine crosses into the game's Life/Track scripts.