Wait and both kinds of until loops; blocks run directly
Script runs are resumable threads saved with the game; Rhai is gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
95cf3ce81c
commit
d17668f3b2
13 files changed
+466
-686
No files matched your search
+18
-22
@@ -1,12 +1,12 @@
|
||||
# Mission scripting with blocks
|
||||
|
||||
Missions of editor campaigns are scripted with **blocks** (like Blockly): coloured puzzle pieces
|
||||
put together in the block editor (see [CAMPAIGN_EDITOR.md](CAMPAIGN_EDITOR.md)). Players never see
|
||||
code – internally the blocks are translated into Rhai, compiled once per mission and run inside the
|
||||
game's fixed simulation step, so a co-op match runs them identically on every computer.
|
||||
put together in the block editor (see [CAMPAIGN_EDITOR.md](CAMPAIGN_EDITOR.md)). There is no code:
|
||||
the game runs the blocks directly, inside its fixed simulation step, so a co-op match runs them
|
||||
identically on every computer.
|
||||
|
||||
Code: `src/blocks.rs` (blocks, values, checking, translation), `src/mscript.rs` (run time, triggers,
|
||||
zones), `src/campaign_doc.rs` (`MissionScripts`, `TriggerDoc`, `TriggerKind`).
|
||||
Code: `src/blocks.rs` (blocks, values, checking), `src/mscript.rs` (run time, triggers, zones),
|
||||
`src/campaign_doc.rs` (`MissionScripts`, `TriggerDoc`, `TriggerKind`).
|
||||
|
||||
## Scripts of a mission
|
||||
|
||||
@@ -64,6 +64,9 @@ creatures and heroes.
|
||||
| | Gold + / Mana + | amount (negative takes) |
|
||||
| Logic | If / else | condition; blocks inside |
|
||||
| | Repeat | times (0–100); blocks inside |
|
||||
| | Repeat until | condition, checked **before** each run (already true: the inside never runs); blocks inside |
|
||||
| | Repeat, then check: until | condition, checked **after** each run (the inside runs at least once); blocks inside |
|
||||
| | Wait | seconds – the script pauses here and goes on with the next block later (also inside loops and "if") |
|
||||
| | Switch trigger | trigger, on/off |
|
||||
| Variables | Set | variable, value |
|
||||
| | Change | variable, value to add |
|
||||
@@ -91,28 +94,21 @@ campaign file check (`CampaignDoc::validate`).
|
||||
|
||||
## At run time (`src/mscript.rs`)
|
||||
|
||||
- The mission's program is generated by `mscript::program` – one Rhai function per script and
|
||||
trigger (`s_start`, `s_victory`, `s_defeat`, `s_tick`, `t_0`, `t_1`, ...) – and compiled once.
|
||||
- Scripts read the game (`m.gold()`, `m.count(side, kind)`, `m.in_zone(zone, side, kind)`, ...)
|
||||
and collect actions (`m.message`, `m.spawn_unit`, `m.terrain`, `m.win`, ...), which are applied
|
||||
after the call. Variables, the random state, fired triggers and zone contents are part of
|
||||
`ScriptState` and saved with the game.
|
||||
- Every run of a script (the start, each second's checks, each fired trigger) is a **thread**: the
|
||||
lists of blocks it is in and where. *Wait* parks a thread until its time; threads are saved with
|
||||
the game, so a waiting script goes on after loading.
|
||||
- The victory check, defeat check and clock start every second, but not while their previous run is
|
||||
still waiting. A trigger that fires again while its last run waits starts a second run.
|
||||
- Loops without a *Wait* run up to 2000 blocks per check (ten checks a second) and then go on at the
|
||||
next check – a script can never hang the game.
|
||||
- Blocks act at once, in order: a *Count* after a *Spawn* already sees the new units. Variables, the
|
||||
random state, fired triggers, zone contents and waiting threads are part of `ScriptState`.
|
||||
- Scripts always run from the first player's side; messages reach every player of a match.
|
||||
- A script error stops nothing else: it is shown once as a message and written to the test log.
|
||||
- Test play shows the variables and the trigger log at the top right, and the zones on the map.
|
||||
|
||||
### Rhai API (internal)
|
||||
|
||||
`gold() mana() time() get(name) set(name, v) count(side, kind) in_zone(zone, side, kind)
|
||||
random(a, b) div(a, b) times(n) event_is(kind) message(t) objective(t) hint(t)
|
||||
spawn_unit(side, kind, count, level, place, zone, name) wave(n) add_gold(n) add_mana(n) win() lose()
|
||||
reveal(zone) camera(zone) terrain(zone, kind) kill(zone, side) trigger(name, on)` – numbers are
|
||||
floats; `spawn` is a reserved word in Rhai, hence `spawn_unit`. The Rhai dependency keeps the
|
||||
`no_time` feature (WASM).
|
||||
|
||||
## The demo
|
||||
|
||||
*Open the demo* in the campaign editor: mission 1 ("The Trial of Triggers") uses all 14 trigger
|
||||
kinds, all special scripts and nearly every block on a painted map with five zones (rectangle,
|
||||
kinds, all special scripts and every block (including both kinds of *until* loops and *Wait*) on a painted map with five zones (rectangle,
|
||||
circle, line, tiles); mission 2 is a random map behind a branch. Play it with *Test play* and watch
|
||||
the debug view.
|
||||
Reference in new issue
Block a user