Observers are builtin CET functions that allow developers to detect when a function/method is executed by the game. They must be registered inside the onInit event, in the init.lua file.
There are two kinds observers:
ObserveBefore() which is triggered right at the moment the function/method is called
ObserveAfter() which is triggered once the game finished to execute the function/method
The provided callback is always filled as follow:
The first argument is the current object that execute the function/method. This argument is not present when function/method is static.
Others arguments passed to the targeted function/method, if any.
You can now generate Observable and ObservableAfter using NativeDB. You need to configure option Clipboard syntax to Lua. You can click on the "copy" button of a function, pick Copy Observable or Copy ObservableAfter and it will copy the code in your clipboard.
Definition
Observe(className, method, callback) -- alias of ObserveBefore()
ObserveBefore(className, method, callback)
ObserveAfter(className, method, callback)
---- ObserveBefore()---- @param string className The parent class name-- @param string method The method name to target-- @param function callback The callback function--ObserveBefore('className', 'method', function(self [, arg1, arg2, ...])-- method() has just been calledend)
---- ObserveAfter()---- @param string className The parent class name-- @param string method The method name to target-- @param function callback The callback function--ObserveAfter('className', 'method', function(self [, arg1, arg2, ...])-- method() has been called and fully executedend)
Observe() is an alias of ObserveBefore(). They both work the same.
If you observe a static function, you must define the field 'method' with the full name of the function. Otherwise it won't work. You can find the full name using NativeDB. See below for an example.
Representation
Here is a visual representation showing where observers are executed in the game's script:
In this representation, the observer callback would be filled with the following arguments:
Observe('AimingStateEvents', 'OnEnter', function(self,stateContext,scriptInterface)-- self the 'AimingStateEvents' class-- stateContext the original method argument-- scriptInterface the original method argumentend)
The self parameter can be renamed at your convenience:
_
this
class
whatever
In the code above, the observer listens to AimingStateEvents:OnEnter(), which is triggered everytime the player enters in ADS state.
Additionally, the OnEnter() method is responsible to apply different effects, like the camera zoom, the initial stamina drain etc... Following this logic, this means:
Using ObserveBefore() allows to hook in before these effects are applied
Using ObserveAfter() guarantees the method finished to apply all the effects
-- onInitregisterForEvent('onInit', function()-- observe crouch OnUpdate state-- this is triggered continuously, as long as the player is crouched Observe('CrouchEvents', 'OnUpdate', function(self,timeDelta,stateContext,scriptInterface) Game.AddToInventory('Items.money', 20)end)end)
Observe event send to an AnimationControllerComponent (click on function's name in NativeDB to copy the full name in your clipboard):
-- init.lua-- onInitregisterForEvent('onInit', function()-- NativeDB will copy 'entAnimationControllerComponent::PushEvent;GameObjectCName'-- We can ignore the left part to only keep: Observe('AnimationControllerComponent', 'PushEvent;GameObjectCName', function(gameObject,eventName)print('GameObject:', gameObject:GetClassName())print('Event:', eventName)end)end)
Advanced Example
Give money when the player is crouched and in ADS:
init.lua
-- set initial varsisADS =falseisCrouch =false-- decide to give money-- this function can be defined outside of onInit-- as it is only called within observersshouldGiveMoney=function()-- is in ADS and is crouchedif isADS and isCrouch then Game.AddToInventory('Items.money', 1000)endend-- onInitregisterForEvent('onInit', function()-- observe ADS OnEnter state Observe('AimingStateEvents', 'OnEnter', function(self,stateContext,scriptInterface) isADS =true shouldGiveMoney()end)-- observe ADS OnExit state Observe('AimingStateEvents', 'OnExit', function(self,stateContext,scriptInterface) isADS =false-- reset conditionend)-- observe Crouch OnEnter state Observe('CrouchEvents', 'OnEnter', function(self,stateContext,scriptInterface) isCrouch =true shouldGiveMoney()end)-- observe Crouch OnExit state Observe('CrouchEvents', 'OnExit', function(self,stateContext,scriptInterface) isCrouch =false-- reset conditionend)end)