Appearance
RiftScript guide
RiftScript gives objects custom behavior without giving creator code access to JavaScript, the browser, files, secrets, or the network. Workshop compiles source into verified, budgeted instructions. The authoritative server still owns physics, scores, saves, inventory, and other trusted state.
New scripts begin with:
text
riftscript 2;This is the source format for RiftScript 1.1. Existing riftscript 1; source keeps its original meaning and bytecode. The RiftScript 1 reference remains available for old projects.
A useful first behavior
text
riftscript 2;
var collected: boolean = false;
fn reward(base: number, multiplier: number): number {
let scaled: number = base * multiplier;
return scaled + 1;
}
event player_touched {
if (!collected) {
let points: number = reward(2, 3);
collected = true;
score.add(points);
effects.play("coin_pickup");
world.destroy();
}
}var is remembered between events. let is a typed local constant for one handler or function call and cannot be reassigned. Persistent variables support number, boolean, and string. Locals, parameters, and function returns can also use opaque entity handles from the entity and gameplay API.
Expressions
RiftScript 1.1 supports:
- arithmetic:
+,-,*, and/; - comparisons:
==,!=,<,<=,>, and>=; - boolean logic:
!,&&, and||; - parentheses and deterministic
random.int(min, max).
Normal precedence applies: multiplication and division happen before addition and subtraction, comparisons happen before boolean logic, and parentheses make intent explicit. && and || short-circuit. Division by zero deterministically produces 0. Any other arithmetic result that is not finite stops the handler with a bounded runtime error instead of corrupting world state.
Creator functions
Functions name reusable calculations. Parameters and the return value are typed:
text
fn clampBonus(base: number, multiplier: number): number {
let result: number = base * multiplier;
return result;
}Functions are deliberately pure: their body contains local constants and one final return expression. Put capability calls and persistent variable assignments in events. The compiler evaluates every argument once and inlines the function into the same verified instruction stream used by other logic.
There is no recursion or dynamic dispatch. A script can declare at most 32 functions, each with at most 8 parameters. Call depth is limited to 8 and every expanded event must fit within 1,000 instructions. These limits make execution cost knowable before publishing.
Events, conditions, and capabilities
Events are bounded entry points such as start and player_touched. Use if or if/else; RiftScript has no creator-controlled loop.
Capabilities are the only way a script asks the runtime to do something. See the generated capability reference for current names, argument types, event restrictions, and authority. Unknown capabilities and incorrectly typed arguments do not compile.
Phase One includes enough authoritative state operations for multi-stage combat, RPG rewards, and quest gates. Scripts can read score with score.value(), inspect or change Health with health.current, health.maximum, health.damage, and health.heal, and manage bounded Inventory stacks with inventory.count, inventory.add, and inventory.remove. These calls use opaque entity handles and the same runtime pipelines as built-in gameplay components.
text
let hero: entity = entity.find("hero");
if (health.current(hero) < health.maximum(hero)) {
health.heal(hero, 20);
}
inventory.add(hero, "key", "Aether key", 1);Presentation audio is deliberately object-scoped. Add an approved Audio Source to the same object, then use audio.play(); or audio.stop();. These commands take no arguments, cannot load a URL, and do not affect trusted game state. See Audio assets.
Workshop help
In the script editor:
- diagnostics include a stable code and exact source location;
- Format produces canonical source;
Ctrl+Spaceopens snippets, functions, variables, types, and capabilities;- the cursor information card explains a symbol and Go to definition finds creator declarations;
- parameter hints describe capability arguments and authority;
- Compile & attach is available only after parsing, typing, expansion, bytecode, and budget checks pass.
Named animations are object-scoped in the same way as Audio Sources. Add or build an animation in Appearance, give a custom clip a stable name, and invoke it with animation.play("door_open");. animation.stop(); returns control to the default movement-aware clip.
Test failures map verified instructions back to the originating source range. Source remains an editor artifact; published Rift data contains compiled instructions and declared persistent defaults, not executable JavaScript.
Compatibility and Visual logic
The required header selects source semantics. Version 1 remains accepted and formats as version 1. Version 2 opts into RiftScript 1.1 operators, locals, and functions. Unsupported versions fail closed.
Visual logic can convert only the smaller subset it can represent exactly. Local constants, creator functions, computed arguments, and richer conditions remain as RiftScript; conversion reports the unsupported range and does not discard source.