SetEventHandler

From GECK
Jump to: navigation, search


A function added by the New Vegas Script Extender.

Description

Registers a User-Defined Function (UDF) as an Event Handler for the specified event.

This means that whenever the specified event occurs in-game, if a UDF was set as an Event Handler for that event, the UDF's script will run, allowing for instant reactions to certain events.

Note that Event Handlers only stay set for the current session, and are not tied to saves in any way. This means that in most cases, it should be reset each time a new session starts. See GetGameRestarted for further details on sessions and how new ones can be detected.

To track if an event has been set for the session, consider using a Temporary Auxiliary Variable, which is also tied to the session.

Specifying The Event

To specify the event, the function accepts a string containing the event's name. See Event Handling for standard NVSE event names.

For example, "OnHitWith" is a valid event specifier.

Arguments

The Handler script must be able to receive the standard arguments for the specified event. See Event Handling to learn which arguments come standard with which events.

For example, a Handler script for "OnHitWith" must have the following arguments, specified in the "{ }" brackets:

scn OnHitWithHandlerScript

ref rTarget
ref rWeapon

begin Function {rTarget, rWeapon}

Note that "rTarget" and "rWeapon" could be named differently.

With this, when the Handler script is called, the provided arguments will be filled with the relevant information. For instance, when "OnHitWithHandlerScript" is called when the Player attacks SunnyREF with a 10mm Pistol, rTarget will be SunnyREF and rWeapon will be the 10mm Pistol.

As soon as the Handler script runs once, all Variables are cleared, just as with regular UDFs. Note that the issue with string_vars and array_vars not being properly cleared is still pertinent here. While xNVSE 6.0+ fixes the issue, in order to maintain backwards compatibility with older versions of NVSE, string_vars should be cleared using Sv_Destruct, and array_vars should be cleared using Ar_Null.

Filters

Depending on the given event's arguments, up to two optional arguments can be supplied to SetEventHandler to filter events. Filters prevent event handlers being called unnecessarily. It is more efficient to set up a filter for the event than it is to filter inside the UDF Handler script.

These filters need to be specified in "key"::value pairs. The key to the first filter, generally what the event happens to, should be "first". The key to the second filter, generally what causes the event, should be "second".

If the filter's value is a Formlist, the handler script will run if an event happens to or because of any element in the list, including elements in sublists. NVSE doesn't attempt to detect loops in Formlists, so avoid any variation of placing Formlist A in or under Formlist B after you've already placed Formlist B in or under Formlist A. Attempting to pass an array as a filter will fail, and the event handler will simply bypass the filter.

When passing the Player as a filter, playerref must be used.

For example, the following line will set up "OnHitWithHandlerScript" as a Handler script for the "OnHitWith" event, which will only run if the Target is SunnyREF and the Weapon is a 10mm Pistol:

 SetEventHandler "OnHitWith" OnHitWithHandlerScript "first"::SunnyREF "second"::Weap10mmPistol 

Note that in the above example, SunnyREF is a Reference and Weap10mmPistol is a Base Form. It is important to test and verify if an event's arguments return either References or Base Forms, and therefore if filters should be References or Base Forms. To this end, IsReference and IsFormValid can be useful.

Priority

To determine when an event handler should run relative to other handlers, priority can be specified with the following syntax: "priority"::SomeInt. More information is in the Priority System section.

Syntax

[help]
(success:bool) SetEventHandler eventID:string functionScript:form filters(up to 2):pair priority:pair{"priority"::1}

Example

scn FnOnHitByPlayer
ref rTarget
ref attacker

begin Function { rTarget, attacker }
	; we know the attacker must be the player, but the argument is still required
	print $rTarget+ " was hit by the player"
end
scn FnOnPlayerRestoreHealth
ref rTarget
int effectCode

begin Function { rTarget, effectCode }
	print "The player has been hit by a restore health effect"
end
scn FnOnLoadGame
string_var filename
int iSaveFileNameLength

begin Function { filename, iSaveFileNameLength }
	print "Loading game from " + $filename
        print "Save file name length: " + $iSaveFileNameLength 

        ;code
     
        sv_Destruct filename  ;not destroying strings in UDFs can cause savebloat, unless using newer versions of xNVSE. 
end
scn SomeQuestScript
begin gamemode
	if getGameRestarted
		SetEventHandler "OnHit" FnOnHitByPlayer "first"::playerref
		SetEventHandler "OnMagicEffectHit" FnOnPlayerRestoreHealth "first"::playerref "second"::RestoreHealth
		SetEventHandler "LoadGame" FnOnLoadGame
	endif
end

Lambda example

Lambdas can be used instead of creating new scripts with SetEventHandler:

begin GameMode
	if GetGameRestarted
		; multiline
		SetEventHandler "OnHit" (begin function {rTarget, rAttacker}
			print $rTarget + " was hit by the player"
		end) "first"::playerref

		; single-line only shorthand
		SetEventHandler "OnHit" ({rTarget, rAttacker} => print $rTarget + " was hit by the player") "first"::playerref
	endif
end

Priority System (New in xNVSE 6.2.9)

If unspecified, default priority while setting an event is 1.
Highest (greatest) priority means the handler will run first before other handlers, lowest means it will run last.
Handlers on the same priority will execute based on registration order. To debug priority conflicts, use IsEventHandlerFirst / IsEventHandlerLast.

0 is reserved as an invalid priority, for use in other functions where we don't want to filter by priority.
It cannot be used for this function, as you must register a handler with a valid priority.
Besides that, any number, even a negative number, can be used as a priority.

Priority CANNOT be set for LN event handlers, such as OnCellEnter.

For more details, see Event Handler Priority System.

Examples for how to specify priority:

SetEventHandler "SomeEvent" SomeUDF "priority"::2

Will set an event handler with priority 2, which will be guaranteed to execute sooner than any handler that didn't specify a priority.

The priority arg can be swapped around with the filter args. For example, these lines do the same thing:

 SetEventHandler "SomeEvent" SomeUDF "priority"::2 "first"::Player
 SetEventHandler "SomeEvent" SomeUDF "first"::Player "priority"::2 

See Also