quake513 wrote: Thu Aug 24, 2023 12:41 am
However I know you can add events …
Most modders don't
add events, but
react to events by adding handlers for specific events to their code.
Basically, if the game wants to tell all active mods that something has happened, it will "raise" an event. Such an event has an internal ID (numeric) that is mapped to a human-readable name in
defines.events. Whenever an event is raised, it is guaranteed to have the two parameters "name" (the numeric ID) and "tick" (when the event was raised). Additionally, there will be at least one parameter that is specific to each event (for example, "entity" for defines.events.on_entity_color_changed, or "player_index" for defines.events.on_player_joined_game). Here is a
list of all vanilla events with their parameters.
Events work a bit like radio: Whenever an event is raised, this is broadcast globally, to all mods. However, only mods that have turned on their radio and have tuned in to the right channel will notice that the event has been raised. Mods can "listen" to a specific event by calling
LuaBootstrap::on_event(ID, handler, filters). Whenever the event with the given numeric ID is raised, the mod's handler (a function) for that event will be run with the event data as argument. Some (not all!) events can be
filtered, but even if an event supports filters, they are optional.
Some mods define their own "custom events" by using
LuaBootstrap::generate_event_name():
Code: Select all
local my_event_id = script.generate_event_name()
This will return a unique numeric ID for your event. As this ID will be generated as a consequence of your mod's code being run by the game, it may be different when a saved game is loaded with added/removed mods (mods
loaded before your mod will also
generate their event IDs before your mod). Therefore, you must make sure to re-generate the ID in response to
LuaBootstrap::on_configuration_changed.
Once you have a unique ID for your custom event you must publish it, so other mods can use it to listen to your event. This is commonly done via the
remote interface:
Code: Select all
my_event_id = script.generate_event_name()
remote.add_interface("YOUR_INTERFACE_NAME", {
get_event_id = function()
return my_event_id
end,
something_else = function()
…
end,
})
Now, other mods can register to your custom event by asking yours for its event ID:
Code: Select all
local custom_id
if remote.interfaces["YOUR_INTERFACE_NAME"] then
custom_id = remote.call("YOUR_INTERFACE_NAME", "get_event_id")
script.on_event(custom_id, function(event)
-- Logs the parameters of your custom event
log(serpent.block(event))
end)
end
However, nothing will happen yet because the event will never be raised! The game has provided a unique event ID, but of course it can't know when it should raise the event, or what parameters it should pass on. That's entirely your responsibility, but the game provides a tool you can use:
LuaBootstrap::raise_event(my_event_id, event_data), where "my_event_id" is the ID you've generated for your custom event, and "event_data" is a table with whatever parameters you want to include. (Note: event_data.name and event_data.tick will be automatically added by the game. The game will also add event_data.mod_name, so other mods can tell which mod raised the event.)
Events are only relevant during the control stage (roughly speaking, when you've started a new game or loaded/joined a game using Factorio's main menu). Triggers are somewhat different: They will be set off during the control stage, but they must be defined in the data stage. Here is an example from my WIP-version of "Bio Industries", where we create an "ammo" item that will set off a
ScriptTriggerEffectItem when our cannon fires this ammo:
Code: Select all
ammo_type = {
category = BI.additional_categories.Bio_Cannon.cannon_ammo.name,
target_type = "direction",
action = {
{
type = "direct",
trigger_target_mask = { BI.additional_categories.Bio_Cannon.trigger_target.name },
filter_enabled = true,
action_delivery = {
type = "projectile",
projectile = "bi-bio-cannon-ammo-proto",
starting_speed = 0.2,
direction_deviation = 0.5,
max_range = 90,
min_range = 20,
source_effects = {
type = "script",
effect_id = "BI_cannon-ammo-proto_create_pollution",
},
}
}
}
},
The important thing is this:
Code: Select all
source_effects = {
type = "script",
effect_id = "BI_cannon-ammo-proto_create_pollution",
},
Now, whenever the ammo is fired in the game, this will raise the
on_script_trigger_effect event, and we can act whenever the event has been raised for the defined effect_id:
Code: Select all
script.on_event(defines.events.on_script_trigger_effect, function(event)
if event.effect_id == "BI_cannon-ammo-proto_create_pollution" then
-- Do stuff
end
end)