Mod:Creation Kit/Remote Papyrus Event Registration

Remote event registration allows any script in the game to receive events from any other script in the game whenever that event is triggered on the source object. For example, it would allow a quest script to get the death event from one of its aliases without having to add a new script to the alias to tell the quest that it died.

=How to Register= Registration is easy, just use the RegisterForRemoteEvent function. Pass it the object you want to receive events from, and the name of the event you want to receive. Then, until you unregister (or are unregistered by the game) your specially-defined remote event will be triggered whenever the event is fired by the game on the source object. Note that you must pass the event name to the function as a raw string, and cannot pass it a variable.

Examples
RegisterForRemoteEvent(Game.GetPlayer, "OnItemAdded")
 * We want to know when the player picks up an item

RegisterForRemoteEvent(QuestTarget_Alias, "OnDeath")
 * We want to know when our quest target dies

string myEvent = "OnDeath" RegisterForRemoteEvent(Game.GetPlayer, myEvent)
 * This will fail to compile because you cannot pass a variable as the event name
 * (even though the variable's value contains a valid event name)

RegisterForRemoteEvent(MyQuest, "OnDeath")
 * This will fail to compile because a quest will never get an OnDeath event

=How to Unregister= To stop receiving events, use the UnregisterForRemoteEvent function. You will then no longer receive the specified event from the specified source object. You will be unregistered automatically if you are on an active magic effect which is removed, or are on a quest or alias when the quest restarts. Like the register call, you must pass the event name to the function as a raw string, and cannot pass it a variable.

Examples
UnregisterForRemoteEvent(Game.GetPlayer, "OnItemAdded")
 * We no longer want to know when the player picks up an item

UnregisterForRemoteEvent(QuestTarget_Alias, "OnDeath")
 * We no longer want to know when our quest target dies

=How to Handle the Event= To handle the event, you'll need to define the event in your script in a special form. The event you define must have a name that consists of the script that the event comes from, followed by a dot, then followed by the name of the event itself. The parameters of the event must first start with a parameter of the same type as the event source script, which is the source of the event, and then followed by the normal event parameters that are defined on the event.

Note that the type used in the event name and in the first parameter of the event must be the "root" script where the event is defined. In other words, it must be the script where the event first appears in the script inheritance tree. For example, if you wanted to get the OnItemAdded event, you must use ObjectReference, since that is where the event is defined, even though Actor can also receive the event. However if you wanted the OnDeath event, you would use Actor instead.

Also note that the type should be the type you registered for. If you register for the OnDeath event on a ReferenceAlias, then the event will be sent to the ReferenceAlias.OnDeath event in your script, whereas if you register for the event on an Actor it would instead go to Actor.OnDeath.

In most cases, the compiler should catch any errors in the definition and give you a bit of advice on fixing the issue.

Examples
Event Actor.OnDeath(Actor akSender, Actor akKiller) Debug.Trace("Got OnDeath for " + akSender + ". The killer was " + akKiller) EndEvent
 * This event is called when an actor we registered for has died. Note the first parameter is the actor
 * that sent the event, and the following parameters match the OnDeath event itself

Event ReferenceAlias.OnDeath(ReferenceAlias akSender, Actor akKiller) Debug.Trace("Got OnDeath for " + akSender + ". The killer was " + akKiller) EndEvent
 * This event is called when a ReferenceAlias we registered for has died. Note that it's different then the
 * above event, because the type of object we care about has changed.

Event SpecialActor.OnDeath(SpecialActor akSender, Actor akKiller) Debug.Trace("Got OnDeath for " + akSender + ". The killer was " + akKiller) EndEvent
 * This event will fail to compile. Even though SpecialActor may extend Actor, the OnDeath event was first
 * defined in Actor, and so that is the type you should be using instead. In this case the compiler will
 * issue an error, and give its best guess at the type you should be using in the error message

Event Actor.OnDeath(ReferenceAlias akSender, Actor akKiller) Debug.Trace("Got OnDeath for " + akSender + ". The killer was " + akKiller) EndEvent
 * This event will fail to compile because the type of the first parameter does not match the type in the
 * event name.

Event Actor.OnDeath(Actor akSender, ObjectReference akParam1, int aiParam2) Debug.Trace("Got OnDeath for " + akSender) EndEvent
 * This event will fail to compile because the parameters after the first one do not match the original
 * definition of the OnDeath event.

=Additional Notes=
 * If a script has registered for an event from a sender, and another script calls that event directly (like a function call), the event will not be relayed to the target script. Only events originating from the game can be relayed via this mechanism.
 * You cannot call the remote events directly in script, they can only be called by the game. If you want the functionality to be shared, you should probably look at encapsulating the functionality in a separate function, which the remote event then calls.
 * The script receiving the remote event will persist its object while registered - the object that is sending the event will not be persisted.

=See Also=
 * Mod:Creation Kit/RegisterForRemoteEvent - ScriptObject
 * Mod:Creation Kit/UnregisterForRemoteEvent - ScriptObject
 * Mod:Creation Kit/Events Reference