Logic System
Mods can extend Besiege's level editor logic system in two ways:
- Adding new triggers
- Adding new events
There are step-by-step guides to creating triggers and events available as well.
Triggers
Adding Triggers
Triggers are defined in the mod manifest:
<Mod>
....
<Triggers>
<Trigger>
<Name>Scream</Name>
<ID>1</ID>
<AvailableOn>
<Entity>1000</Entity> <!-- Cottage -->
<Entity>Windmill</Entity>
<ModdedEntity>
<ModID>00000000-0000-0000-0000-000000000000</ModID>
<LocalID>0</LocalID>
</ModdedEntity>
<!--<AllOfficialEntities />-->
<!--<AllModdedEntities />-->
</AvailableOn>
</Trigger>
</Triggers>
</Mod>
- The
Nameelement is displayed in the user interface when using the trigger. - The
IDelement is used to uniquely identify the trigger within the mod. The ID must uniquely identify the trigger among all triggers in the same mod; the easiest way to handle this is to just use sequential IDs (1, 2, 3, ...). - The
AvailableOnelement specifies what entities the trigger can be added to:<Entity>someId</Entity>enables it on the vanilla entity with the given ID or name.<ModdedEntity>enables it on a modded entity by specifying the mod's ID and the local ID of the entity within that mod. TheModIDelement may be omitted when the entity is in the same mod as the trigger.<AllOfficialEntities />enables it on all vanilla entities.<AllModdedEntities />enables it on all modded entities.
Activating Triggers
To activate the custom triggers, it is necessary to add custom code to the game.
The ModTriggers class provides an API to interact with custom triggers.
There are two ways of activating triggers: 1) Activating all triggers of a specific type that currently exist in the level. 2) Activating triggers per-entity.
In either case, this will only work correctly when called on the instance running the simulation.
== Activating Triggers Globally
Use the ModTriggers.GetCallback(id) method to get an Action that you can call to
activate all instances of the trigger with the specified ID.
== Activating Triggers Per-Entity
Create an OnTriggerChanged callback, which has the following signature:
void OnTriggerChanged(Entity entity, Action activate, bool removed).
Then call ModTriggers.RegisterCallback(id, callback).
Your callback will now be called whenever the trigger with the specified ID is added to or removed from an entity:
- The first argument is the entity which was modified.
- The second argument is an
Actionwhich you can call to activate the trigger, similar to the one returned byGetCallbackbut only activating the trigger on that entity. - The third argument indicates whether the trigger was added or removed from the entity.
(
falsemeans added,truemeans removed).
With this approach you are responsible for storing these callbacks for when you need them.
Events
Adding Events
Events are also first declared in the mod manifest.
<Mod>
....
<Events>
<Event>
<Name>Some Event</Name>
<ID>someId</ID>
<Icon name="some-icon" />
<Properties>
<NumberInput name="numberinput" title="Test" />
</Properties>
</Event>
</Events>
</Mod>
The Name and ID elements work similarly to their Trigger equivalents.
The Icon element specifies an icon to be displayed ain the mapper when the event is selected.
Unlike Triggers, Events also support various values that can be entered by the player
when using the event, these are called Event Properties and declared in the Properties
element. See the Event Properties section for details.
Because the declaration for events with many properties can get quite long and complex, it is possible to instead define an event in its own XML file, similar to how Blocks and Entities work. To do so, reference the file in the mod manifest like this:
<Mod>
...
<Events>
<Event path="SomeEvent.xml" />
</Events>
</Mod>
The path attribute is relative to the mod's directory, i.e. the directory that contains
the Mod.xml file. The SomeEvent.xml file would then have to contain the complete Event
element as described above.
Event Properties
Events support custom "parameters" that can be set by the users. Think of the official vanilla events and you'll see that almost all of them have some values to be set by players when setting up their level. These are called Event Properties in the mod loader.
The mod loader provides several Event Property types that modded events can use:
- TextInput
- NumberInput
- Choice
- Toggle
- TeamButton
An event can contain any combination of these as required and multiple elements of the
same type are permissible.
In addition, there is the Picker element. When specified, the event will also contain
a picker, however an event can contain at most one picker.
Lastly, the Icon and Text elements can be added to give additional information to the
player, they are only displayed and otherwise ignored by the API.
Each Property must have a name attribute that uniquely identifies it among the
properties of the same event. The name attribute may not contain | and = characters.
Apart from that, each property has various attributes that can be used to modify its behaviour and appearance. See Event Properties for a full reference.
Properties will generally be displayed in the order they are declared in, from top to bottom.
It is also possible to group multiple elements in a Row XML element to make them
appear on the same line.
Elements inside a Row are required to have an x (float) attribute to specify their
position. Elements outside Row elements are always centered automatically.
Adding Behaviour to Events
The ModEvents class contains an API to make your events actually do something.
The API consists of a single method:
ModEvents.RegisterCallback(int id, OnEventExecute callback)
This method registers a callback that will be called whenever an event of the specified
type is activated by the logic system.
The id parameter corresponds to the ID element of the XML declaration.
OnEventExecute has the following signature:
OnEventExecute(LogicChain logic, IDictionary<string, EventProperty> properties).
logic is the LogicChain that the event is a part of.
This also provides access to the entity on which the event is set up.
properties provides a way to access the values set up in the event:
Every Event Property type has a corresponding class in EventProperty
(e.g. EventProperty.TextInput, EventProperty.Choice etc.).
These all inherit from the base EventProperty class.
Using the properties dictionary, you can access properties by the name defined in
the XML declaration. You can then cast the resulting object to the appropriate class
which provides ways of accessing the values set up by the player.
Again, see Event Properties for a full reference.
Note that the name property is not only used for accessing the data from code,
it's also used when saving and loading level files.
This means that if you ever change one of the names, this will break compatibility
with levels saved using an earlier version of the mod.
Considering this and the fact that the names are purely internal and not user-facing,
it is recommended to never change the property names in any mod that was already published.