Scripting Engine Execution
Relevant source files
The following files were used as context for generating this wiki page:
Scripting Engine Execution manages the runtime logic and state for game actors using the SOUP (Scripted Object Universal Processor) system. It processes compiled bytecode programs exported from the original game assets to drive actor behavior, animations, and gameplay outcomes.
The engine operates on a stage-based execution model where logical updates occur in distinct phases, such as body execution, task processing, and animation updates. It maintains a strictly validated state through content identities to ensure fidelity to the original game specification.
Core Architecture and Data Model
The scripting engine centers around the Scripts asset, which contains the complete logical definition of a game world. This includes global flags, function declarations, actor programs, and initial placement instances.
Script Components
- Scripts Asset: The top-level container for a world's logical state. It includes weapon definitions, combat tables, clock settings, and the global function/flag registry.
- Actor: A logical template defining a script program. Actors contain bytecode steps, default attributes, and combat taunts.
- Instance: A specific placement of an actor in the world. Each instance retains its unique ID, map position, and initial angles.
- Program: The compiled bytecode logic consisting of
Steps. Each step contains anOperationand a reference to thenextlogical instruction.
Sources: crates/cyrus-assets/src/script.rs:149-166, crates/cyrus-assets/src/script.rs:188-230
The diagram above represents the hierarchical relationship between the world's script asset, individual actor programs, and world instances. Sources: crates/cyrus-assets/src/script.rs:149-230
Execution Lifecycle and Stages
Script execution occurs in logical stages to maintain synchronization between game logic, physics, and rendering. The engine uses a nominal tick system derived from the frame rate.
Logical Stages
- Body: Processes the main execution thread of the script. This typically handles logic branching and state changes.
- Tasks: Processes asynchronous operations that span multiple frames, such as movement or rotation.
- Animation: Updates the current animation frame and processes sound cues associated with animation commands.
Sources: crates/cyrus-game/tests/script_animation_host.rs:133-145, crates/cyrus-game/tests/script_presentation.rs:252-270
Execution Flow
The flowchart describes the sequence of execution for a single logical update within a script world. Sources: crates/cyrus-game/tests/script_animation_host.rs:147-172
Task System and Native Functions
Tasks handle time-dependent behaviors like locomotion and rotation. The engine distinguishes between Task (blocks main execution) and Multitask (runs in parallel).
Common Locomotion Tasks
| Task | Description | Parameters |
|---|---|---|
RotateByAxis | Rotates actor on a specific axis over time. | Axis, Delta, Duration |
MoveByAxis | Moves actor along an axis. | Axis, Delta, Duration |
MoveToLocation | Moves actor to a predefined RALC offset. | Selector, Duration |
FacePlayer | Turns actor toward the player. | Duration |
Sources: crates/cyrus-game/tests/script_animation_host.rs:256-265, crates/cyrus-game/tests/script_animation_host.rs:480-496, crates/cyrus-game/tests/script_animation_host.rs:1044-1060
Native Execution Example: Rotation
When a rotation task is called, the engine calculates the increment per tick based on the duration and frame scale. If the duration is zero or the target is reached, the task completes and releases the script if it was blocking.
Sources: crates/cyrus-game/tests/script_animation_host.rs:288-316
// Example of a Task initialization in a script program
Operation::Call {
call: Call {
function_id: 3,
kind: CallKind::Task,
target: Object::Me,
function: "RotateByAxis".into(),
arguments: vec![
Value::Integer { value: 1 }, // Y-Axis
Value::Integer { value: 128 }, // Delta
Value::Integer { value: 4 }, // Duration
],
},
}
Sources: crates/cyrus-game/tests/script_animation_host.rs:356-368
Asset Preparation and Validation
Cyrus prepares script data by disassembling bytecode from original .rgm files and applying configuration from SYSTEM.INI and COMBAT.INI.
- Disassembly: The
prepare_sourcefunction decodes bytecode into logical steps and validates them against the SOUP definition. - Attributes: The engine initializes 256 attributes per actor, applying overrides from
SOUP.INI. - Identity Matching: A
content_idis generated by hashing the entire script definition. This ID must match between script and animation assets for execution to proceed.
Sources: crates/cyrus-assets/src/script_export.rs:65-120, crates/cyrus-assets/src/script.rs:234-255
Conclusion
The Scripting Engine Execution system provides a robust framework for reproducing the original Redguard logic. By separating execution into body, task, and animation stages, it ensures deterministic behavior while supporting the complex asynchronous task system required for character locomotion and interaction. The strict validation of asset identities and program definitions guarantees that only faithful logical states are executed at runtime.
Sources: crates/cyrus-game/README.md, crates/cyrus-assets/src/script.rs:271-285