Eldrin Scripting Language
Even if you use visual scripting, having a basic understanding of the underlying Eldrin Script is helpful.
Eldrin is a fast, easy-to-understand scripting language based on a virtual machine. To get a basic understanding, let's look at the Orc source code from the Hideout2D example.
This code was automatically generated by the visual script editor:
fn event(event, value) {
if event == "startup" {
random_walk_in_sector( 1.0, 1.0, 4);
set_proximity_tracking( true, 4);
add_item( "GoldenKey");
set_attr( "target", "");
}
if event == "proximity_warning" {
let alignment = get_attr_of( value, "ALIGNMENT");
if alignment > 0 {
close_in( value, 1.5, 1.0);
}
}
if event == "closed_in" {
let target = get_attr( "target");
if target == "" {
let damage = random( 1, 3);
deal_damage( value, damage);
set_attr( "target", value);
notify_in( 4, "attack");
}
}
if event == "attack" {
let target = get_attr( "target");
if target != "" {
let damage = random( 1, 3);
deal_damage( target, damage);
notify_in( 4, "attack");
}
}
if event == "kill" {
set_proximity_tracking( false, 5.0);
goto( "Garden", 1.0);
set_attr( "target", "");
}
if event == "arrived" {
set_proximity_tracking( true, 5.0);
random_walk_in_sector( 1.0, 1.0, 4);
}
if event == "death" {
drop_items( "");
set_attr( "visible", false);
}
if event == "take_damage" {
let from_id = value.subject_id;
let amount = value.amount;
took_damage( from_id, amount);
let attacker = get_attr_of( from_id, "name");
message( id(), "You hit the Orc for " + amount + " damage", "");
}
}
Events
The behavior of characters and items is based on an event system. Characters and items are sent events of a certain type with a given value.
Characters and items respond to events by issuing commands and setting attributes.
Events are chained to break complex tasks into small, manageable chunks.
All supported event types are listed in the Events chapter.
Values
Values in Eldrin Script are represented by a built-in data container called a Packet. A packet holds three numeric fields and an optional string and is used for all commands, events, and attributes.
In Rust a Packet would look like this:
pub struct Packet {
pub x: f32,
pub y: f32,
pub z: f32,
pub string: Option<String>,
}
Creating Packets
The following examples all create a valid Packet:
// Creating numerical values
let a = 10.5; // Sets all three numerical fields to 10.5
let a = 10;
let a = vec2(10, 5);
let a = vec3(1, 2, 3.0);
// Creating strings
let a = "This is a string";
let a = "This has a value of: " + 10;
Accessing Packet fields
let b = a; // Creates a copy of a (Packets are copied by value, not by reference)
let b = a.x; // All numerical fields of b are set to the value of a.x
let b = a.xy; // Packets support swizzles
let b = a.string; // b is the value of a.string
// Setting packet fields
b.y = 10.0;
Comparison
When comparing Packets, the VM first checks if one of the packets has a valid string, if yes it compares the strings of the packets, otherwise it compares the .x fields.
if event == "startup" {} // Compares the string values of the packets
if value == 10 // Checks if value.x == 10
if value.y == 5 // Checks if value.y == 5
Field Aliases and Conventions
As events can set multiple fields of a packet, Eldrin supports conventions and aliases.
If a packet contains the id of another character or item, you can reference it with
value.subject_id // an alias for value.x.
As subject_id is an alias for the .x, you can also always just use value directly without the .x reference.
distance and amount are aliases for .y.
count is an alias for .z. Some events send a "," separated list of character or item ids in the string field, you can check how many ids are in the list via .count.
In this example the door checks how many entities are in its radius (to test if it is safe to close the door):
if event == "close_door" {
let entities = entities_in_radius();
if entities.count == 0 {
set_attr( "visible", true);
set_attr( "blocking", true);
}
else {
// Somebody blocks the door, test again later.
notify_in( 2, "close_door");
}
}