Documentation
¶
Overview ¶
Package sim is the headless, deterministic Total Annihilation simulation core. It runs identically on the authoritative server (native build) and in the browser (wasm build); given the same seed and the same ordered stream of orders it produces bit-identical state, which is what lets a client predict ahead of the server and reconcile cleanly.
Nothing here touches the filesystem, the clock, the network, goroutines or floats: assets arrive pre-parsed via UnitMeta, time advances in fixed ticks, and all math goes through engine/fixed. Unit iteration uses an insertion ordered slice rather than a Go map range so traversal order is stable.
Index ¶
- Constants
- func ParseYardMap(s string, fx, fz int) []yardCell
- type Binding
- type Blast
- type CobController
- type CobDebugger
- type CobInspector
- type CobPorts
- type CobScripts
- type Config
- type RestoredProjectile
- type RestoredQueued
- type RestoredUnit
- type RestoredWeapon
- type Runtime
- type SpawnFunc
- type Terrain
- type Unit
- type UnitMeta
- type WeaponMeta
- type World
- func (w *World) AddUnit(name string, meta *UnitMeta, binding Binding, at fixed.Vec2, heading int32, ...) uint32
- func (w *World) ApplyDamage(sourceID, targetID uint32, dmg fixed.Fixed) bool
- func (w *World) ApplyOrder(o order.Order)
- func (w *World) CanBuildAt(name string, x, z fixed.Fixed) bool
- func (w *World) ExportProjectiles() []RestoredProjectile
- func (w *World) ExportUnits() []RestoredUnit
- func (w *World) ForEachUnit(fn func(*Unit))
- func (w *World) Hash() uint64
- func (w *World) InitOnOff(id uint32)
- func (w *World) KillAllThreads()
- func (w *World) RemoveUnit(id uint32)
- func (w *World) Restore(tick uint64, units []RestoredUnit, projectiles []RestoredProjectile)
- func (w *World) SetTerrain(t *Terrain)
- func (w *World) Snapshot() frame.Snapshot
- func (w *World) Step(rt Runtime)
- func (w *World) Terrain() *Terrain
- func (w *World) Tick() uint64
- func (w *World) UnitAddBreakpoint(id uint32, scriptIdx int, offset uint32)
- func (w *World) UnitByID(id uint32) *Unit
- func (w *World) UnitClearBreakpointHits(id uint32)
- func (w *World) UnitClearBreakpoints(id uint32)
- func (w *World) UnitCob(id uint32) (frame.CobUnitState, bool)
- func (w *World) UnitCount() int
- func (w *World) UnitCoverage(id uint32) map[int][]uint32
- func (w *World) UnitKillThread(id uint32, threadID int32)
- func (w *World) UnitKillThreads(id uint32)
- func (w *World) UnitKillThreadsByName(id uint32, name string)
- func (w *World) UnitRemoveBreakpoint(id uint32, scriptIdx int, offset uint32)
- func (w *World) UnitReset(id uint32)
- func (w *World) UnitRestartScript(id uint32, name string, args ...int)
- func (w *World) UnitScriptNames(id uint32) []string
- func (w *World) UnitSetStatic(id uint32, idx int, v int32)
- func (w *World) UnitSetThreadLocal(id uint32, threadID int32, idx int, v int32)
- func (w *World) UnitSetThreadPC(id uint32, threadID int32, pc int)
- func (w *World) UnitSetValuePort(id uint32, port int, v int32)
- func (w *World) UnitStartScript(id uint32, name string, args ...int)
- func (w *World) UnitStepThread(id uint32, threadID int32)
- func (w *World) UnitValuePort(id uint32, port int) int32
Constants ¶
const ( MoveHold = uint8(order.MoveHold) MoveManeuver = uint8(order.MoveManeuver) MoveRoam = uint8(order.MoveRoam) FireHold = uint8(order.FireHold) FireReturn = uint8(order.FireReturn) FireAtWill = uint8(order.FireAtWill) )
Convenience aliases so the sim reads the same names the order package defines.
const ( // TickHz is the simulation rate; one tick is 25ms, matching TA's loop. TickHz = 40 // TickMs is the millisecond duration of a single tick. TickMs = 1000 / TickHz )
Variables ¶
This section is empty.
Functions ¶
func ParseYardMap ¶
ParseYardMap converts an FBI YardMap string into a row-major fz×fx cell grid. Whitespace separates rows visually but cells are consumed in reading order; a string shorter than the footprint pads with solid cells, and an empty string yields nil (callers treat a nil grid as fully solid).
Cell codes follow the TA convention: o/w/g/f and friends are ground the structure occupies, c (and the water/geo C/G variants) opens with the yard, y/Y never blocks.
Types ¶
type Binding ¶
type Binding interface {
HasScript(name string) bool
Start(name string, args ...int)
// Restart spawns the named script after cancelling any live instance of it,
// so a per-tick re-driven thread (a weapon aim loop) supersedes rather than
// stacks. It mirrors the COB START opcode's same-name supersede.
Restart(name string, args ...int)
// Pieces returns the current piece transforms for the render snapshot.
Pieces() []frame.PieceState
}
Binding is the COB script hook surface the world drives. The script VM implements it; until a unit has a script it is nil and the world degrades to pure movement/combat. Defining it here (rather than importing the script package) keeps the dependency arrow pointing into sim.
type CobController ¶
type CobController interface {
KillAllThreads()
KillThread(id int32)
ResetState()
}
CobController is the optional control surface a binding exposes for the studio's developer commands (Terminate All Scripts, per-unit Stop / Reset). The script.Unit binding implements it; script-less bindings do not. These are debug-only sandbox tools and carry no determinism contract.
type CobDebugger ¶
type CobDebugger interface {
StepThread(id int32)
SetThreadPC(id int32, pc int)
SetThreadLocal(id int32, idx int, v int32)
SetStatic(idx int, v int32)
AddBreakpoint(scriptIdx int, offset uint32)
RemoveBreakpoint(scriptIdx int, offset uint32)
ClearBreakpoints()
ClearBreakpointHits()
Coverage() map[int][]uint32
}
CobDebugger is the optional debug-control surface a binding exposes for the studio's COB debugger (single-stepping, breakpoints, variable edits, coverage) in the offline unit editor. The script.Unit binding implements it; script-less bindings do not. Like the other developer commands these mutate VM state outside the hashed contract and carry no determinism guarantee.
type CobInspector ¶
type CobInspector interface {
CobState() frame.CobUnitState
}
CobInspector is the optional inspection surface a binding may expose. The script.Unit binding implements it; script-less bindings do not, so the world reports no COB state for them.
type CobPorts ¶
CobPorts is the optional unit-value port surface a binding exposes so the offline unit editor can drive COB GET_UNIT_VALUE reads (HEALTH, build percent, activation, standing orders) from its inspector sliders. The script.Unit binding implements it; script-less bindings do not. Port writes never feed the world hash — combat-authoritative state lives on the sim unit — so they carry no determinism contract.
type CobScripts ¶
type CobScripts interface {
HasScript(name string) bool
Start(name string, args ...int)
Restart(name string, args ...int)
KillThreadsByName(name string)
ScriptNames() []string
}
CobScripts is the optional script-invocation surface a binding exposes so the offline unit editor's Actions panel can run a named entry point (Create, Activate, AimPrimary, …), list the available ones, and retract a transient pose handler. The script.Unit binding implements it; script-less bindings do not. Editor-driven invocations are offline / single-unit and carry no determinism contract.
type RestoredProjectile ¶
type RestoredProjectile struct {
ID uint32
OwnerID uint32
TargetID uint32
Slot int
Mode uint8
Phase uint8
Model string
Weapon string
Pos fixed.Vec3
Vel fixed.Vec3
Origin fixed.Vec3
Target fixed.Vec3
LaunchY fixed.Fixed
Speed fixed.Fixed
VMax fixed.Fixed
Accel fixed.Fixed
TurnAng int32
HomingR fixed.Fixed
Gravity fixed.Fixed
AoE fixed.Fixed
Damage fixed.Fixed
AgeSec fixed.Fixed
LifeSec fixed.Fixed
LastDist fixed.Fixed
Closing bool
Heading int32
Pitch int32
FromPiece int
}
RestoredProjectile is one in-flight model weapon (missile/rocket/bomb) carried across a join. The projectile struct is self-contained — every field stepProjectile reads is stored on it — so resuming flight on a late joiner only needs these values copied back verbatim. Carrying them keeps the joiner's in-flight shots from vanishing AND keeps hashed state in lockstep: a missile the authority still has in the air will detonate and apply damage, so a joiner that dropped it would otherwise diverge on the target's health the moment it lands.
type RestoredQueued ¶
RestoredQueued is one deferred order on a unit's shift-queue, carried across a join. Kind mirrors order.Kind numerically (1 = move, 2 = attack).
type RestoredUnit ¶
type RestoredUnit struct {
ID uint32
Name string
Side int
Pos fixed.Vec3
Heading fixed.Fixed // raw fractional TA-angle
Speed fixed.Fixed
HasMove bool
MoveTarget fixed.Vec2
Health fixed.Fixed
Dead bool
// Combat state so a late joiner's prediction re-engages weapons that were
// firing / aiming on the authority. Without it a restored unit re-runs only
// its Create script and renders at its base pose, so a weapon caught
// mid-recoil snaps back to rest on the joining client.
HasAttack bool
AttackTarget uint32
// Queue carries the unit's shift-queued follow-up orders so a joiner's
// world advances through the same waypoint chain as the authority.
Queue []RestoredQueued
Weapons [3]RestoredWeapon
// BuildPercent carries construction progress (a buildee below 100% stays
// inert on the joiner too); the Build* fields carry a builder's live job
// so the joiner keeps raising the same buildee; ProdQueue a factory's
// pending production run.
BuildPercent fixed.Fixed
BuildState uint8
BuildName string
BuildSite fixed.Vec2
BuildTargetID uint32
BuildGateMs int64
ProdQueue []string
// Standing orders + their working state, so a joiner's units keep the
// same stances, posts and patrol/auto-engage status.
MoveMode uint8
FireMode uint8
HomePos fixed.Vec2
AutoEngaged bool
CurIsPatrol bool
SelfDAtMs int64
// Transport links: who carries this unit, who it carries, and any
// in-flight pickup / drop job.
CarriedBy uint32
Carrying []uint32
LoadTarget uint32
StallTicks uint16
AvoidFlip bool
ProgressX fixed.Fixed
ProgressZ fixed.Fixed
HasUnload bool
UnloadAt fixed.Vec2
// Cob carries the unit's full live script VM state (piece animators, threads,
// statics, visibility) when the binding can export it. With it the joiner
// resumes the exact piece poses the authority holds — a turret's aim angle, a
// half-played recoil — instead of re-deriving them by replaying Create and
// StartMoving, which only ever reproduces a rest pose. Nil when the binding
// has no script or cannot export, in which case Restore falls back to replay.
Cob *frame.CobSnapshot
}
RestoredUnit carries the full per-unit motion state needed to resume the simulation elsewhere — a late-joining client rebuilding its local world from an authoritative snapshot. Heading and Speed are the raw fixed-point locostate (not the truncated render values), and the move target is included so a unit caught mid-move keeps driving identically rather than freezing. Weapon cooldowns are not carried, so combat state remains approximate.
type RestoredWeapon ¶
type RestoredWeapon struct {
HasTarget bool
TargetUnit uint32
TargetPt fixed.Vec3
Source string
LastFireMs int64
}
RestoredWeapon is one weapon slot's standing aim/fire order, carried across a join so the joiner re-aims and re-fires it. LastFireMs carries the slot's last shot time so the joiner inherits the authority's reload cadence: with it the next shot lands on the same tick on every window instead of the joiner kicking off a fresh reload cycle (the "firing on two separate cycles" desync). The aim thread itself re-runs from scratch, replaying the turret turn and muzzle animation; only the fire clock is inherited.
type Runtime ¶
type Runtime interface {
Tick(ms int64)
}
Runtime is the optional COB script VM the world advances each tick before movement, mirroring game-engine.js which ticks the runtime first.
type SpawnFunc ¶
SpawnFunc builds the meta and (optional) script binding for a unit type. Returning a nil binding yields a script-less unit (movement/combat only).
type Terrain ¶
type Terrain struct {
W, H int // cells
CellWU fixed.Fixed // world units per cell (16 for TNT attr grid)
HeightScale fixed.Fixed // world Y per height unit (TA renders at 1/2)
SeaLevel int // height units; cells below it are underwater
Data []uint8 // row-major heights, len = W*H
// Void marks cells the map carves out entirely (the TNT 0xFFFC
// sentinel): nothing stands, walks or builds there. Optional —
// nil means no voids.
Void []uint8
// SlopeScalePct scales a unit's declared MaxSlope onto THIS heightmap's
// per-cell delta scale, as a percentage (0 → defaultSlopeScalePct). TA's
// coarse attribute grid inflates per-cell deltas ~2.5x relative to the
// MaxSlope authoring scale, so TA maps use 40 (the 2/5 calibration that
// makes KOTH's spiral ramps the only way up). TA:Kingdoms maps carry a
// native heightmap whose deltas sit on the MaxSlope scale directly and run
// far steeper (Athri-Cay island edges hit ~30 vs KOTH's ~11), so they use
// 100 — otherwise GROUND2 units (MaxSlope 30 → 12) can't climb any island.
SlopeScalePct int
}
Terrain is the map's height field, sampled by the simulation for unit elevation, movement legality (slope and water-depth limits), build-site checks and projectile-vs-ground hits. The grid is the TNT attribute- resolution heightmap (one cell per 16 world units); heights are the raw 0..255 bytes, scaled to world Y by HeightScale. A nil terrain (The Grid) behaves as an infinite flat plane at Y 0 with no movement restrictions.
Terrain is configuration, not simulation state: every lockstep peer must install the identical grid before stepping (exactly like unit meta), so it is never hashed or carried in snapshots.
type Unit ¶
type Unit struct {
ID uint32
Name string
Side int
Meta *UnitMeta
PosY fixed.Fixed
Health fixed.Fixed // 0..100
Dead bool
BuildPercent fixed.Fixed
IsMoving bool
// contains filtered or unexported fields
}
Unit is one live simulated unit.
type UnitMeta ¶
type UnitMeta struct {
Name string
CanMove bool
MaxVelocity fixed.Fixed // world-units per frame (30 Hz)
TurnRate fixed.Fixed // TA-angle per frame
Accel fixed.Fixed // world-units per frame^2
BrakeRate fixed.Fixed // world-units per frame^2
IsAircraft bool
IsHover bool
IsShip bool
IsSub bool
IsHovercraft bool
CruiseAltitude fixed.Fixed
// Terrain limits (FBI maxslope / maxwaterdepth / minwaterdepth, in
// height units): the steepest cell delta the unit climbs, the deepest
// water a surface unit wades, the shallowest water a ship needs.
MaxSlope int
MaxWaterDepth int
MinWaterDepth int
IsBuilder bool
OnOffable bool
// ActivateWhenBuilt — the unit's Activate script runs the moment its
// construction completes (FBI activatewhenbuilt; ARM Solar's panels).
ActivateWhenBuilt bool
// Construction stats. BuildTime is the unit's own build-effort points
// (FBI buildtime — how long IT takes to construct); WorkerTime is the
// builder's effort output per second (FBI workertime); BuildDistance is
// how close (wu) a mobile builder must stand to its construction site.
BuildTime fixed.Fixed
WorkerTime int
BuildDistance fixed.Fixed
// FootprintX/Z are the FBI footprint in map squares; collisionRadius
// derives the body circle the collision/avoidance passes use.
FootprintX int
FootprintZ int
// TransportSlots — how many units this transport carries (0 = not a
// transport).
TransportSlots int
// Yard is the parsed YardMap occupancy grid (row-major FootprintZ rows ×
// FootprintX cols). Nil means the whole footprint is solid. Only standing
// structures collide by yard; mobile units stay on the circle model.
Yard []yardCell
// Resource prices, drained over the unit's build (TA metal+energy,
// TA:K mana). Pools are infinite in the sandbox; the drain feeds the
// per-side usage stats only.
CostMetal fixed.Fixed
CostEnergy fixed.Fixed
CostMana fixed.Fixed
// Default standing orders the unit spawns with (FBI standingmoveorder /
// standingfireorder, already resolved to the game defaults — Maneuver /
// Fire at Will — when the FBI is silent).
StandMove uint8
StandFire uint8
// Death blasts: the resolved explodeas weapon (ordinary death) and
// selfdestructas weapon (Ctrl+D). Damage is absolute per-shot, AoE the
// blast diameter in world units, Edge the damage fraction left at the
// rim. A zero-damage blast deals no splash (visual only).
Explode Blast
SelfD Blast
// Economy contributions per second while the unit stands (generation)
// and the storage capacity it adds to its side's pools. The sandbox
// never gates on stock — these feed the economy bar's accounting only.
MakeMetal fixed.Fixed
MakeEnergy fixed.Fixed
MakeMana fixed.Fixed
StoreMetal fixed.Fixed
StoreEnergy fixed.Fixed
StoreMana fixed.Fixed
// MaxHealth is the unit's absolute hit points (FBI maxdamage). The sim's
// health bar stays on a 0..100 scale; ApplyDamage divides each weapon's
// absolute damage by this to land TDF-faithful percentage hits. Zero
// means unknown — damage then applies at face value, the legacy scale.
MaxHealth fixed.Fixed
Weapons [3]WeaponMeta
}
UnitMeta is the FBI-derived stat block a unit type carries into the simulation. Floats from the parsed FBI are converted to fixed-point exactly once, here at the asset boundary, so the tick loop only ever sees integers.
type WeaponMeta ¶
type WeaponMeta struct {
Name string
Range fixed.Fixed // world units
ReloadMs int // milliseconds between shots
Burst int // shots per burst (>=1)
Damage fixed.Fixed // per shot
Present bool
// CommandFire weapons (the D-gun) discharge only on an explicit fire
// order — one shot per order, never as part of a standing attack.
CommandFire bool
// Per-shot economy drain (TDF energypershot / metalpershot).
EnergyShot fixed.Fixed
MetalShot fixed.Fixed
// Tolerance is the weapon's firing arc in TA-angle units (65536 = full
// turn); 0 = no arc constraint. Aircraft aim by pointing the whole airframe
// (no rotating turret), so the body heading must be within tolerance of the
// target bearing before the weapon may open fire.
Tolerance int32
// Ballistic / projectile fields. Every weapon except an instant-hit beam
// flies a tracked projectile through the subsystem and applies its damage on
// detonation — a missile/rocket/bomb carries a 3DO mesh, while a cannon shell
// or EMG bolt flies the same flight path with no model. Tracking the
// model-less shots is what lets a late joiner restore in-flight cannon/EMG
// fire, not just missiles. All rates derive from the weapon TDF.
Model string // 3DO projectile model; empty = model-less shot
BeamWeapon bool // instant-hit beam (lasers): never flies
VelocityWU fixed.Fixed // top speed, world units/sec
StartVelocityWU fixed.Fixed // launch speed; 0 = top speed (no ramp)
AccelerationWU fixed.Fixed // ramp to top speed, wu/s^2; 0 = instant
TurnRateAng int32 // homing turn rate, TA-angle/sec; 0 = unguided
FlightTimeSec fixed.Fixed // self-destruct timer; 0 = derive from range/vel
AreaOfEffectWU fixed.Fixed // blast diameter for detonation damage
Dropped bool // gravity bomb: released with no thrust
VLaunch bool // vertical launch: climbs then homes
Tracks bool // guided: homes on the target
SelfProp bool // self-propelled (with Tracks + turn rate, homes)
Ballistic bool // unpowered arc under gravity
}
WeaponMeta holds the per-slot weapon stats the engine acts on.
type World ¶
type World struct {
// contains filtered or unexported fields
}
World holds all simulation state for one match/session.
func (*World) AddUnit ¶
func (w *World) AddUnit(name string, meta *UnitMeta, binding Binding, at fixed.Vec2, heading int32, side int) uint32
AddUnit registers a new unit and returns its id.
func (*World) ApplyDamage ¶
ApplyDamage subtracts dmg from target HP, emitting hit and (on lethal) death.
func (*World) ApplyOrder ¶
ApplyOrder dispatches a player order into the world. This is the single mutation entry point the session/network layer calls.
func (*World) CanBuildAt ¶
CanBuildAt reports whether unit type `name` may legally occupy the ground point — the exported form the studio client calls to colour the build placement ghost (green vs red). Unknown types stay neutral (true) so a missing spawn fn never paints a false negative.
func (*World) ExportProjectiles ¶
func (w *World) ExportProjectiles() []RestoredProjectile
ExportProjectiles captures every in-flight model weapon's full flight state so a late joiner resumes the authority's live shots rather than starting with an empty sky. The projectile struct is self-contained, so each export is a flat copy of its fields.
func (*World) ExportUnits ¶
func (w *World) ExportUnits() []RestoredUnit
ExportUnits captures every live unit's full motion state in insertion order, for assembling an authoritative snapshot a client can resync from.
func (*World) ForEachUnit ¶
ForEachUnit visits every live unit in stable insertion order. Used to build authoritative wire snapshots without disturbing the render event buffer.
func (*World) Hash ¶
Hash returns a deterministic digest of the authoritative unit state. The server broadcasts it periodically and clients compare against their own to detect prediction divergence. Iteration follows the stable insertion order.
func (*World) InitOnOff ¶
InitOnOff settles a freshly-placed on/off-able unit's activation so the studio's Active pill matches what's drawn: an ActivateWhenBuilt structure (a solar collector) opens at once and reads on, while any other toggleable unit pins the ACTIVATION port to off so the pill doesn't inherit GET_UNIT_VALUE's resting default of 1 and lie about a closed unit. No-op for units that can't be toggled, and only meaningful for a completed unit — buildees raise through the construction path, which activates them on completion instead. Called from the direct-placement entry point; networked buildees never pass here.
func (*World) KillAllThreads ¶
func (w *World) KillAllThreads()
KillAllThreads terminates every COB thread on every unit (the "Terminate All Scripts" developer command). Bindings without scripts are skipped.
func (*World) Restore ¶
func (w *World) Restore(tick uint64, units []RestoredUnit, projectiles []RestoredProjectile)
Restore replaces the world's unit set and resets the tick so a client can initialize its local prediction engine to the authority's current state. Meta and binding are re-resolved by name through the spawn provider; the nextID counter is advanced past every restored id so later spawns stay in lockstep with the authority. In-flight projectiles are rebuilt verbatim so the joiner's sky matches the authority's and any shot still en route lands (and applies its damage) on the same tick everywhere.
func (*World) SetTerrain ¶
SetTerrain installs (or clears, with nil) the world's height field.
func (*World) Snapshot ¶
Snapshot builds the render snapshot for the current tick and drains the events accumulated since the last call. The local renderer consumes this; it never crosses the wire.
func (*World) Step ¶
Step advances the simulation exactly one fixed tick. It is the only time source the world has; callers must invoke it once per TickMs.
func (*World) UnitAddBreakpoint ¶
UnitAddBreakpoint / UnitRemoveBreakpoint / UnitClearBreakpoints manage a unit's breakpoints by script index + byte offset.
func (*World) UnitClearBreakpointHits ¶
UnitClearBreakpointHits releases every thread of a unit parked on a breakpoint (the debugger's "Continue").
func (*World) UnitClearBreakpoints ¶
func (*World) UnitCob ¶
func (w *World) UnitCob(id uint32) (frame.CobUnitState, bool)
UnitCob returns a unit's inspectable script state (static vars + live threads), or ok=false when the unit is missing or has no script binding. It is debug-only — the studio's Runtime / Script Variables panels read it — and never participates in the world hash.
func (*World) UnitCount ¶
UnitCount returns the number of units currently in the world (live or dead until reaped). It is a cheap map length read used for session listings.
func (*World) UnitCoverage ¶
UnitCoverage returns a unit's executed-offset coverage, keyed by script index, or nil for a missing / script-less unit.
func (*World) UnitKillThread ¶
func (*World) UnitKillThreads ¶
UnitKillThreads stops every thread on one unit; UnitKillThread stops a single thread by id; UnitReset returns a unit to a clean script state. Each is a no-op for a missing unit or a script-less binding.
func (*World) UnitKillThreadsByName ¶
UnitKillThreadsByName marks dead every live thread running the named script.
func (*World) UnitRemoveBreakpoint ¶
func (*World) UnitRestartScript ¶
func (*World) UnitScriptNames ¶
UnitScriptNames lists a unit type's script entry-point names, or nil for a missing / script-less unit.
func (*World) UnitSetStatic ¶
UnitSetStatic writes one of a unit's static variables.
func (*World) UnitSetThreadLocal ¶
UnitSetThreadLocal writes one of a thread's local variables.
func (*World) UnitSetThreadPC ¶
UnitSetThreadPC moves a thread's program counter to an instruction index.
func (*World) UnitSetValuePort ¶
UnitSetValuePort writes a COB unit-value port on a unit's script binding. A missing or script-less unit is a silent no-op.
func (*World) UnitStartScript ¶
UnitStartScript spawns a thread on the named entry point. UnitRestartScript does the same but first cancels any live instance of that script (the COB START supersede). Both are no-ops for a missing / script-less unit or an unknown script name.
func (*World) UnitStepThread ¶
UnitStepThread advances one thread of a unit by a single instruction.