Custom Papyrus Events

Custom events allow any script in the game to send an event which any number of scripts can then receive. The receivers have to register with the sender, but the sender doesn't have to know about the receivers or manage them in any way. One way this could be used would be having an actor register to receive an event from a controlling script whenever it enters a location, and unregister when they leave. Then the controller script could send the event, and all actors in that location that register would get it without having to maintain any complicated list or setting up a bunch of aliases.

How to RegisterEdit

Registration is easy, just use the RegisterForCustomEvent 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 custom event will be triggered whenever source sends the event. Note that you must pass the event name to the function as a raw string, and cannot pass it a variable.

ExamplesEdit

; We want to know when the marker sends out an earthquake event
RegisterForCustomEvent(EarthquakeMarker, "Earthquake")

; We want to know when a trigger wants us to spring an ambush
RegisterForCustomEvent(AmbushTrigger, "Ambush")

; 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)
string myEvent = "Ambush"
RegisterForCustomEvent(AmbushTrigger, myEvent)

How to UnregisterEdit

To stop receiving events, use the UnregisterForCustomEvent 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.

ExamplesEdit

; We no longer want to know when the marker sends out an earthquake event
UnregisterForCustomEvent(EarthquakeMarker, "Earthquake")

; We no longer want to know when a trigger says to ambush
UnregisterForCustomEvent(AmbushTrigger, "Ambush")

How to Handle the EventEdit

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 two parameters the event receives are one of the same type as the script the event comes from, which will contain the event's sender, and a var array which will contain any parameters.

Note that the type used in the event name and in the first parameter of the event must contain the custom event definition.

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

ExamplesEdit

; This event is called when our trigger sends the ambush event. The trigger that sent the event is in the parameter
Event AmbushTriggerScript.Ambush(AmbushTriggerScript akSender, Var[] akArgs)
  Debug.Trace("Got Ambush event for " + akSender + " with arguments: " + akArgs)
  ; Whoever sends the event says that they send the target of the ambush as the first parameter, and the delay as the second one
  if (akArgs.Length == 2)
    Actor ktarget = akArgs[0] as Actor ; For objects, doing "as" and checking for None is faster then "Is" followed by "as"
    if ktarget && akArgs[1] is float
      float fdelay = akArgs[1] as float
      Debug.Trace("We are targeting: " + ktarget + " after " + fdelay + " seconds")
    endif
  endif
EndEvent

; This event will fail to compile because the type of the first parameter does not match the type in the
; event name.
Event AmbushTriggerScript.Ambush(ObjectReference akSender, Var[] akArgs)
  Debug.Trace("Got Ambush event for " + akSender)
EndEvent

; This event will fail to compile because the parameters aren't the right type
Event AmbushTriggerScript.Ambush(AmbushTriggerScript akSender, int aiParam1)
  Debug.Trace("Got Ambush event for " + akSender)
EndEvent

How to Define a Custom EventEdit

In order for your script to send a custom event, it must define it. This is done similarly to a variable, but using "CustomEvent" rather then the variable type. You cannot name an event the same name as another function or event in your script or your parent script.

ExamplesEdit

; Defines a custom event that this script can send called Ambush
CustomEvent Ambush

How to Send a Custom EventEdit

To send a custom event, use the SendCustomEvent function. The two parameters are the raw string of the event to send (you cannot pass it a string variable) and an optional array of parameters. The compiler will make sure the event is defined in your own script, or in a parent script. The function will then return immediately and not wait for any scripts handling the event (if any) to finish. The sender given to the scripts that are listening is the object the SendCustomEvent function is called on, even if it's called from another script.

ExamplesEdit

; Assuming we've defined the Ambush event like above and we want to send the target as the first parameter and a delay as the second

; Send the ambush event, passing ourselves as the sender
Var[] kargs = new Var[2]
kargs[0] = kTargetActor
kargs[1] = 5.25
SendCustomEvent("Ambush", kargs)

; Send the ambush event from the other trigger, the other trigger will be given as the sender, this time with no arguments
OtherTrigger.SendCustomEvent("Ambush")

; Cannot use a variable, so this won't compile
string myEvent = "Ambush"
SendCustomEvent(myEvent)

Additional NotesEdit

  • You cannot call the custom events directly in script. If you want the functionality to be shared, you should probably look at encapsulating the functionality in a separate function, which the custom event then calls.

See AlsoEdit