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
Name
element is displayed in the user interface when using the trigger. - The
ID
element 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
AvailableOn
element 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. TheModID
element 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
Action
which you can call to activate the trigger, similar to the one returned byGetCallback
but only activating the trigger on that entity. - The third argument indicates whether the trigger was added or removed from the entity.
(
false
means added,true
means 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.