Jump to content
ZaellixA

What exactly are scriptedEventHandlers? [ANSWERED but still very instructive]

Recommended Posts

Just now, ZaellixA said:

 OEF. Would you care to shed some light????

OEF (onEachFrame) aka PFH (per frame handler, CBA version)

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites
4 minutes ago, ZaellixA said:

Hhhhmmm, excuse my question @Mr H. but I am a bit unfamiliar with the "term" OEF. Would you care to shed some light????

I guess:

On Each Frame

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites
14 hours ago, jshock said:

make a custom event handler for say, entering and leaving the area of a marker

 

8 hours ago, ZaellixA said:

So, I was wondering, what is the difference of running a constant loop and when the condition is met, run a script in every "concerned" unit? Now, I do understand that tracking the "concerned" units now has become a lot easier with the use of sciptedEventHandlers, but still haven't found a way to avoid this constant loop

 

Figured out the long hand for my concept (using OEF)....probably a little messy and could use some fine tuning here and there, especially when accounting for more than just one player in SP. At least some sort of reference for what you would have to do. But open the editor, place a unit, any number of markers, follow the example function calls at the bottom, copy all and paste into debug and exec:

 

Spoiler

/////////////////////////
//  Main Background Functions
/////////////////////////
jshk_mrk_fnc_onExitMarker = {
	params [["_marker","",[""]]];
	if (allMapMarkers find _marker > -1) then {
		missionNamespace setVariable [
			"jshk_exitMarkerEH_id",
			[	true,format ["jshk_exitMarkerArea_%1",_marker],
			{
				params [
					["_obj",objNull,[objNull]],
					["_marker","",[""]],
					["_code",{},[{}]]
				];
				private _inAreaMarkers = missionNamespace getVariable ["jshk_currentInAreaMarkers",[]];
				private _areaIndex = _inAreaMarkers find _marker;
				if !(_areaIndex isEqualTo -1) then {
					[_obj,_marker] call _code;
					_inAreaMarkers deleteAt _areaIndex;
					missionNamespace setVariable ["jshk_currentInAreaMarkers",_inAreaMarkers];
					private _id = missionNamespace getVariable ["jshk_exitMarkerEH_id",-1];
					if !(_id isEqualTo -1) then
					{
						[true,format ["jshk_exitMarkerArea_%1",_marker],_id] call BIS_fnc_removeScriptedEventHandler;
					};
				};
			}] call BIS_fnc_addScriptedEventHandler
		];
	};
};

jshk_mrk_fnc_onEnterMarker = {
	params [["_marker","",[""]]];
	if (allMapMarkers find _marker > -1) then {
		[true,format ["jshk_enterMarkerArea_%1",_marker],
		{
			params [
				["_obj",objNull,[objNull]],
				["_marker","",[""]],
				["_code",{},[{}]]
			];
			private _inAreaMarkers = missionNamespace getVariable ["jshk_currentInAreaMarkers",[]];
			private _areaIndex = _inAreaMarkers find _marker;
			if (_areaIndex isEqualTo -1) then {
				_inAreaMarkers pushBack _marker;
				missionNamespace setVariable ["jshk_currentInAreaMarkers",_inAreaMarkers];
				[_obj,_marker] call _code;
				[_marker] call jshk_mrk_fnc_onExitMarker;
			};
		}] call BIS_fnc_addScriptedEventHandler;
	};
};

jshk_mrk_fnc_getMarkerHash = {
	params [["_marker","",[""]]];
	private _markerHashes = missionNamespace getVariable ["jshk_markerHashList",[]];
	private _index = _markerHashes findIf {_x select 0 isEqualTo _marker};
	private _code = [{},{}];
	if (_index > -1) then {
		_code = _markerHashes select _index select 1;
	};
	_code;
};

/////////////////////////
//  Main User Function
/////////////////////////
jshk_mrk_fnc_addMarkerAreaEH = {
	params [
		["_marker","",[""]],
		["_onEnter",{},[{}]],
		["_onExit",{},[{}]]
	];
	private _old = missionNamespace getVariable ["jshk_checkMarkerArray",[]];
	private _index = _old find _marker;
	if (_index isEqualTo -1) then {
		[_marker] call jshk_mrk_fnc_onEnterMarker;
		private _hashList = missionNamespace getVariable ["jshk_markerHashList",[]]; 
		_hashList pushBack [_marker,[_onEnter,_onExit]];
		_old pushBack _marker;
		missionNamespace setVariable ["jshk_checkMarkerArray",_old];
		missionNamespace setVariable ["jshk_markerHashList",_hashList];
	};
};


/////////////////////////
//  OEF applied (post init)
//  'Event handler handling'
//  Applied to player for testing purposes
/////////////////////////
[ "jshk_inMarkerArea_OEF", "onEachFrame", 
	{
		private _markers = missionNamespace getVariable ["jshk_checkMarkerArray",[]];
		
		params [["_obj",objNull,[objNull]]];
		if (!isNull _obj) then {
			private _outMarkers = [];
			private _inMarkers = _markers select {getPos player inArea _x};

			if !(_inMarkers isEqualTo []) then {
				{
					private _code = [_x] call jshk_mrk_fnc_getMarkerHash;
					[true,format ["jshk_enterMarkerArea_%1",_x],[player,_x,_code select 0],false] call BIS_fnc_callScriptedEventHandler;
				} forEach _inMarkers;
			} else {
				{	
					private _code = [_x] call jshk_mrk_fnc_getMarkerHash;
					[true,format ["jshk_exitMarkerArea_%1",_x],[player,_x,_code select 1],false] call BIS_fnc_callScriptedEventHandler;
				} forEach _markers;
			};
		};
	},
[player]] call BIS_fnc_addStackedEventHandler;



/////////////////////////
//  Test uses of user function jshk_mrk_fnc_addMarkerArea
//  Params: [string,code,code]
//  0: "markerName"
//	1: {code on entering marker area}
//			Params available in code: [obj EH is attached, marker name]
//	2: {code on exiting marker area}
//			Params available in code: [obj EH is attached, marker name]
/////////////////////////
["test",{systemChat "in: test";},{systemChat "out: test";}] call jshk_mrk_fnc_addMarkerAreaEH;
["test_1",{systemChat "in: test_1";},{systemChat "out: test_1";}] call jshk_mrk_fnc_addMarkerAreaEH;
["test_2",{systemChat "in: test_2";},{systemChat "out: test_2";}] call jshk_mrk_fnc_addMarkerAreaEH;
["test_3",{systemChat "in: test_3";},{systemChat "out: test_3";}] call jshk_mrk_fnc_addMarkerAreaEH;

 

Then move in and out of the marker areas as desired to see results.

 

And yes I know my “hash” function isn’t really quite that....

  • Like 2
  • Thanks 1

Share this post


Link to post
Share on other sites
1 hour ago, ZaellixA said:

Hhhhmmm, excuse my question @Mr H. but I am a bit unfamiliar with the "term" OEF. Would you care to shed some light????

OEF refers to OnEachFrame, essentially a eventhandler that runs every frame. UsefulNote: as the link says there is a stackable version which should be preferred. It's useful for drawing or physics or timesensitive stuff but otherwise it's less resource intensive to go for triggers and/or loops. 

 

Edit: darn ninjas 😛

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites
12 minutes ago, mrcurry said:

UsefulNote: as the link says there is a stackable version which should be preferred.

Use the mission OEF EH type instead.  Disregard I thought @mrcurry was linking BIS_fnc_addStackedEventHandler.

 

12 minutes ago, mrcurry said:

otherwise it's less resource intensive to go for triggers and/or loops.

As an example of triggers...

Spoiler

//initPlayerLocal.sqf

waitUntil{ time > 0 };

TAG_fnc_markerAreaEH = {
	if !( params[
		[ "_object", objNull, [ objNull ] ],
		[ "_marker", "", [ "" ] ],
		[ "_function", "", [ "" ] ]
	] ) exitWith {
		format[ "Bad parameter: OBJ: %1, MRK: '%2', FUNC: '%3'", _object, _marker, _function ] call BIS_fnc_error;
	};

	_pos = getMarkerPos _marker;

	if ( _pos isEqualTo [0,0,0] ) exitWith {
		format[ "Marker does not exist: '%1'", _marker ] call BIS_fnc_error;
	};

	if ( isNull _object ) exitWith {
		"Object is null" call BIS_fnc_error;
	};

	if ( _function isEqualTo "" || { !( missionNamespace getVariable _function isEqualType {} ) } ) exitWith {
		format[ "Invalid function supplied: '%1'", _function ] call BIS_fnc_error;
	};

	getMarkerSize _marker params[ "_radX", "_radY" ];
	_shape = markerShape _marker == "RECTANGLE";
	_dir = markerDir _marker;

	_trg = createTrigger [ "EmptyDetector", _pos, false ];
	_trg setTriggerArea [ _radX, _radY, _dir, _shape ];
	_trg triggerAttachVehicle [ _object ];
	_trg setTriggerActivation [ "VEHICLE", "PRESENT", true ];
	_trg setTriggerStatements [ "this", format[ "
		[ 'Enter', triggerAttachedVehicle thisTrigger, '%1' ] call ( missionnamespace getVariable '%2' );
	", _marker, _function ], format[ "
		[ 'Exit', triggerAttachedVehicle thisTrigger, '%1' ] call ( missionnamespace getVariable '%2' );
	", _marker, _function ]];

	_trg
};

TAG_fnc_markerCallback = {
	params[ "_mode", "_object", "_marker" ];

	_name = if ( isPlayer _object ) then {
		name _object
	}else{
		_object call BIS_fnc_objectVar;
	};

	switch ( toUpper _mode ) do {
		case "ENTER" : {
			hint format[ "%1 has entered the marker '%2'", _name, _marker ];
		};
		case "EXIT" : {
			hint format[ "%1 has exited the marker '%2'", _name, _marker ];
		};
	};
};

_eventTrig = [ player, "someMarker", "TAG_fnc_markerCallback" ] call TAG_fnc_markerAreaEH;

 

  • Like 2
  • Thanks 1

Share this post


Link to post
Share on other sites
5 minutes ago, Larrow said:

Use the mission OEF EH type instead.

 

As an example...

  Hide contents


//initPlayerLocal.sqf

waitUntil{ time > 0 };

TAG_fnc_markerAreaEH = {
	if !( params[
		[ "_object", objNull, [ objNull ] ],
		[ "_marker", "", [ "" ] ],
		[ "_function", "", [ "" ] ]
	] ) exitWith {
		format[ "Bad parameter: OBJ: %1, MRK: '%2', FUNC: '%3'", _object, _marker, _function ] call BIS_fnc_error;
	};

	_pos = getMarkerPos _marker;

	if ( _pos isEqualTo [0,0,0] ) exitWith {
		format[ "Marker does not exist: '%1'", _marker ] call BIS_fnc_error;
	};

	if ( isNull _object ) exitWith {
		"Object is null" call BIS_fnc_error;
	};

	if ( _function isEqualTo "" || { !( missionNamespace getVariable _function isEqualType {} ) } ) exitWith {
		format[ "Invalid function supplied: '%1'", _function ] call BIS_fnc_error;
	};

	getMarkerSize _marker params[ "_radX", "_radY" ];
	_shape = markerShape _marker == "RECTANGLE";
	_dir = markerDir _marker;

	_trg = createTrigger [ "EmptyDetector", _pos, false ];
	_trg setTriggerArea [ _radX, _radY, _dir, _shape ];
	_trg triggerAttachVehicle [ _object ];
	_trg setTriggerActivation [ "VEHICLE", "PRESENT", true ];
	_trg setTriggerStatements [ "this", format[ "
		[ 'Enter', triggerAttachedVehicle thisTrigger, '%1' ] call ( missionnamespace getVariable '%2' );
	", _marker, _function ], format[ "
		[ 'Exit', triggerAttachedVehicle thisTrigger, '%1' ] call ( missionnamespace getVariable '%2' );
	", _marker, _function ]];

	_trg
};

TAG_fnc_markerCallback = {
	params[ "_mode", "_object", "_marker" ];

	_name = if ( isPlayer _object ) then {
		name _object
	}else{
		_object call BIS_fnc_objectVar;
	};

	switch ( toUpper _mode ) do {
		case "ENTER" : {
			hint format[ "%1 has entered the marker '%2'", _name, _marker ];
		};
		case "EXIT" : {
			hint format[ "%1 has exited the marker '%2'", _name, _marker ];
		};
	};
};

_eventTrig = [ player, "someMarker", "TAG_fnc_markerCallback" ] call TAG_fnc_markerAreaEH;

 

Very nice example, thanks.

 

jshock, thanks for the example. It's quite long, but I do get the functionality. Still, and in addition to mrcurry's comment above, I can't see a way we avoid OEF or loop functionality.

18 minutes ago, jshock said:

 

 

Figured out the long hand for my concept (using OEF)....probably a little messy and could use some fine tuning here and there, especially when accounting for more than just one player in SP. At least some sort of reference for what you would have to do. But open the editor, place a unit, any number of markers, follow the example function calls at the bottom, copy all and paste into debug and exec:

 

  Reveal hidden contents


/////////////////////////
//  Main Background Functions
/////////////////////////
jshk_mrk_fnc_onExitMarker = {
	params [["_marker","",[""]]];
	if (allMapMarkers find _marker > -1) then {
		missionNamespace setVariable [
			"jshk_exitMarkerEH_id",
			[	true,format ["jshk_exitMarkerArea_%1",_marker],
			{
				params [
					["_obj",objNull,[objNull]],
					["_marker","",[""]],
					["_code",{},[{}]]
				];
				private _inAreaMarkers = missionNamespace getVariable ["jshk_currentInAreaMarkers",[]];
				private _areaIndex = _inAreaMarkers find _marker;
				if !(_areaIndex isEqualTo -1) then {
					[_obj,_marker] call _code;
					_inAreaMarkers deleteAt _areaIndex;
					missionNamespace setVariable ["jshk_currentInAreaMarkers",_inAreaMarkers];
					private _id = missionNamespace getVariable ["jshk_exitMarkerEH_id",-1];
					if !(_id isEqualTo -1) then
					{
						[true,format ["jshk_exitMarkerArea_%1",_marker],_id] call BIS_fnc_removeScriptedEventHandler;
					};
				};
			}] call BIS_fnc_addScriptedEventHandler
		];
	};
};

jshk_mrk_fnc_onEnterMarker = {
	params [["_marker","",[""]]];
	if (allMapMarkers find _marker > -1) then {
		[true,format ["jshk_enterMarkerArea_%1",_marker],
		{
			params [
				["_obj",objNull,[objNull]],
				["_marker","",[""]],
				["_code",{},[{}]]
			];
			private _inAreaMarkers = missionNamespace getVariable ["jshk_currentInAreaMarkers",[]];
			private _areaIndex = _inAreaMarkers find _marker;
			if (_areaIndex isEqualTo -1) then {
				_inAreaMarkers pushBack _marker;
				missionNamespace setVariable ["jshk_currentInAreaMarkers",_inAreaMarkers];
				[_obj,_marker] call _code;
				[_marker] call jshk_mrk_fnc_onExitMarker;
			};
		}] call BIS_fnc_addScriptedEventHandler;
	};
};

jshk_mrk_fnc_getMarkerHash = {
	params [["_marker","",[""]]];
	private _markerHashes = missionNamespace getVariable ["jshk_markerHashList",[]];
	private _index = _markerHashes findIf {_x select 0 isEqualTo _marker};
	private _code = [{},{}];
	if (_index > -1) then {
		_code = _markerHashes select _index select 1;
	};
	_code;
};

/////////////////////////
//  Main User Function
/////////////////////////
jshk_mrk_fnc_addMarkerAreaEH = {
	params [
		["_marker","",[""]],
		["_onEnter",{},[{}]],
		["_onExit",{},[{}]]
	];
	private _old = missionNamespace getVariable ["jshk_checkMarkerArray",[]];
	private _index = _old find _marker;
	if (_index isEqualTo -1) then {
		[_marker] call jshk_mrk_fnc_onEnterMarker;
		private _hashList = missionNamespace getVariable ["jshk_markerHashList",[]]; 
		_hashList pushBack [_marker,[_onEnter,_onExit]];
		_old pushBack _marker;
		missionNamespace setVariable ["jshk_checkMarkerArray",_old];
		missionNamespace setVariable ["jshk_markerHashList",_hashList];
	};
};


/////////////////////////
//  OEF applied (post init)
//  'Event handler handling'
//  Applied to player for testing purposes
/////////////////////////
[ "jshk_inMarkerArea_OEF", "onEachFrame", 
	{
		private _markers = missionNamespace getVariable ["jshk_checkMarkerArray",[]];
		
		params [["_obj",objNull,[objNull]]];
		if (!isNull _obj) then {
			private _outMarkers = [];
			private _inMarkers = _markers select {getPos player inArea _x};

			if !(_inMarkers isEqualTo []) then {
				{
					private _code = [_x] call jshk_mrk_fnc_getMarkerHash;
					[true,format ["jshk_enterMarkerArea_%1",_x],[player,_x,_code select 0],false] call BIS_fnc_callScriptedEventHandler;
				} forEach _inMarkers;
			} else {
				{	
					private _code = [_x,1] call jshk_mrk_fnc_getMarkerHash;
					[true,format ["jshk_exitMarkerArea_%1",_x],[player,_x,_code select 1],false] call BIS_fnc_callScriptedEventHandler;
				} forEach _markers;
			};
		};
	},
[player]] call BIS_fnc_addStackedEventHandler;



/////////////////////////
//  Test uses of user function jshk_mrk_fnc_addMarkerArea
//  Params: [string,code,code]
//  0: "markerName"
//	1: {code on entering marker area}
//			Params available in code: [obj EH is attached, marker name]
//	2: {code on exiting marker area}
//			Params available in code: [obj EH is attached, marker name]
/////////////////////////
["test",{systemChat "in: test";},{systemChat "out: test";}] call jshk_mrk_fnc_addMarkerAreaEH;
["test_1",{systemChat "in: test_1";},{systemChat "out: test_1";}] call jshk_mrk_fnc_addMarkerAreaEH;
["test_2",{systemChat "in: test_2";},{systemChat "out: test_2";}] call jshk_mrk_fnc_addMarkerAreaEH;
["test_3",{systemChat "in: test_3";},{systemChat "out: test_3";}] call jshk_mrk_fnc_addMarkerAreaEH;

 

Then move in and out of the marker areas as desired to see results.

Still, I do believe I'll find some good use for scriptedEventHandlers. If any of you have any ready example which would like to share please don't be afraid 😄.

  • Like 1

Share this post


Link to post
Share on other sites
3 hours ago, ZaellixA said:

I am a bit unfamiliar with the "term" OEF. Would you care to shed some light????

On Each Frame is an Event Handler that runs some code on each game frame (see https://community.bistudio.com/wiki/Arma_3:_Event_Handlers/addMissionEventHandler#EachFrame) so you can use it to check a condition on each frame and exit the code when it's met.
Here's an example:
 

// lets' say I want to check if a player is near a marker.:
addMissionEventHandler ["EachFrame", {
	if ((player distance (getMarkerPos "myMarkerName))<100 ) then {removeMissionEventHandler _thisEventHandler; hint "player is close to the marker"};
}];

this event handler will check the code on each frame and be removed when the condition is met. Of course it's almost the same as:

waitUntil {((player distance (getMarkerPos "myMarkerName))<100 )};
 hint "player is close to the marker"};

The difference being that this can be used in unscheduled environment.
 

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites
On 6/2/2019 at 10:06 PM, phronk said:

Doesn't work like a regular eventHandler which loops;

regular eventhandlers "loop"?

 

On 6/2/2019 at 9:13 PM, ZaellixA said:

So I can't really understand what is the difference

normal eventhandlers come straight from engine c++ code, you cannot add own eventhandlers in script, and also cannot fire eventhandlers in script.

 

Scripted eventhandlers is just, well the name says it, scripted. You can add and fire events in scripts. Make your own events.

 

On 6/2/2019 at 10:44 PM, ZaellixA said:

Hhhhmmmm, but then what is the difference with scriptedEventHandlers and the CBA eventHandlers?

There is none, it's basically the same. CBA eventhandlers are more feature rich (globalEvent, targetEvent to execute a event over network on another client) and more efficiently coded.

 

On 6/2/2019 at 11:19 PM, ZaellixA said:

in the sense that it will be called automatically by the engine when the arsenal is closed.

It's not. Its called by a script that's executed from the Arsenal UI. The whole arsenal is scripted, it's not in engine.

 

On 6/3/2019 at 12:09 AM, Larrow said:

I may be a little off and mainly going from memory of the original Xeno extended event handlers (been a long time since I read through it Arma2) which may of had extra bells and whistles added to it by CBA team.

They are normal engine events. For each engine event available an event is added to the config via their mod to each base class. That event calls their own function. You register functions to their function (either through script and they also pass the mission config for an event structure I believe ).

These are Extended eventhandlers (XEH) which is completely seperate from normal CBA Eventhandlers which are essentially the same as BI scriptd eventhandlers.

 

On 6/3/2019 at 1:51 AM, ZaellixA said:

how can you actually register events?

phronk already told you

 

 

 

Sure, for a custom event you would still have to check in a loop, BUT! If you need to do the same thing in several places, you can either run N loops, or just run one loop, with one scripted event that get's triggered, and N eventhandlers.

 

  • Like 2
  • Thanks 1

Share this post


Link to post
Share on other sites

Dedmen, thanks a lot for all the clarifications and explanations. Very insightful indeed. :thumbs-up:

 

20 minutes ago, Dedmen said:

regular eventhandlers "loop"? 

Well, I believe he meant they will be called again and again (by the engine).

 

20 minutes ago, Dedmen said:

normal eventhandlers come straight from engine c++ code, you cannot add own eventhandlers in script, and also cannot fire eventhandlers in script.

 

Scripted eventhandlers is just, well the name says it, scripted. You can add and fire events in scripts. Make your own events.

Yep, I've come to understand it now. But it's good to have confirmation (as well as minor details added :)).

20 minutes ago, Dedmen said:

There is none, it's basically the same. CBA eventhandlers are more feature rich (globalEvent, targetEvent to execute a event over network on another client) and more efficiently coded.

It's very reassuring to hear (or rather..., read) that. This is they was thinking about them and get it yet another confirmation indicating that I am on the right track is very good news to me (cheers).

20 minutes ago, Dedmen said:

It's not. Its called by a script that's executed from the Arsenal UI. The whole arsenal is scripted, it's not in engine.

Yep, Larrow has already made this clarification (still, it's good to know that the whole arsenal is scripted, cheers++).

 

20 minutes ago, Dedmen said:

These are Extended eventhandlers (XEH) which is completely seperate from normal CBA Eventhandlers which are essentially the same as BI scriptd eventhandlers.

Hhhhmmmm..., know this makes new questions begging for answers :|. So, would you care to make a short clarification on the distinction between them?

 

20 minutes ago, Dedmen said:

phronk already told you

Yep, already solved that "mystery" :).

20 minutes ago, Dedmen said:

Sure, for a custom event you would still have to check in a loop, BUT! If you need to do the same thing in several places, you can either run N loops, or just run one loop, with one scripted event that get's triggered, and N eventhandlers.

Yeah, I did realize that, and I do see the benefits of using scriptedEventHandlers against a bunch of loops.

 

All your comments were on spot and very educative. Thanks a lot for that. :thumbs-up:

  • Like 1

Share this post


Link to post
Share on other sites
3 minutes ago, ZaellixA said:

Well, I believe he meant they will be called again and again (by the engine).

They will get called everytime the event happens. Same for scripted events and CBA events or any other events.

 

 

4 minutes ago, ZaellixA said:

So, would you care to make a short clarification on the distinction between them

CBA Events are just scripted eventhandlers. Can add handlers for events, and fire events by name. That's it.

XEH is a big system which exposes config-only (mod-only) eventhandlers to any script.
They do that by registering a handler for every config event in their mod, and then checking in script if there are any scripts that registered themselves to receive the event.

 

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites
36 minutes ago, Dedmen said:

CBA Events are just scripted eventhandlers. Can add handlers for events, and fire events by name. That's it.

XEH is a big system which exposes config-only (mod-only) eventhandlers to any script.
They do that by registering a handler for every config event in their mod, and then checking in script if there are any scripts that registered themselves to receive the event.

Nice, understood. But what is a "config event"? How are these events called?

  • Like 1

Share this post


Link to post
Share on other sites
15 minutes ago, ZaellixA said:

But what is a "config event"?

A event who's handler can only be defined in config.

 

15 minutes ago, ZaellixA said:

How are these events called?

Engine.

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites

Hhhhhhmmmmm, so there is a way to make engine trigger events for you... But what is the process to make this happen? I mean how did the XEH make it and why can't we implement a way to give everyone the ability to define their own events to be triggered by the engine?

  • Like 1

Share this post


Link to post
Share on other sites
2 minutes ago, ZaellixA said:

Hhhhhhmmmmm, so there is a way to make engine trigger events for you

No, not at all.

 

You can define the handler in the config. Defining handlers for non-existend events won't ever fire your handler.

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites

Then how does the XEH thing make it??? :icon_confused:

  • Like 1

Share this post


Link to post
Share on other sites
7 minutes ago, ZaellixA said:

Then how does the XEH thing make it??? :icon_confused:

It just adds a config eventhandler, that calls a script.
The script then has an array of scripted eventhandlers.

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites

Alright, understood. What I have not understood is how the config eventHandler is invoked. Can it be an arbitrary event?

 

Apologize if my questions seem trivial or nonsensical but I am not familiar with config files and how they interact with the engine. So, instead of me just throwing questions to you (this may NEVER end :D), maybe you could direct me to some instructive text and show me the path of information I should follow to understand this better?

  • Like 1

Share this post


Link to post
Share on other sites
4 minutes ago, ZaellixA said:

What I have not understood is how the config eventHandler is invoked.

 

26 minutes ago, Dedmen said:

Engine.

 

Same as all other engine eventhandlers. The engine calls it. You can't.

4 minutes ago, ZaellixA said:

Can it be an arbitrary event?

 

23 minutes ago, Dedmen said:

Defining handlers for non-existend events won't ever fire your handler.

 

Config files are.. Just configuration files. The engine reads them, and does things with the config entries. Like any other config file for any other program.

  • Thanks 1

Share this post


Link to post
Share on other sites

Oooohhhh..., it seems I have missed your

5 minutes ago, Dedmen said:

Defining handlers for non-existend events won't ever fire your handler.

answer. Apologies for that.

 

So that means that we can't really add "new" eventHandlers in the sense that we can invoke EHs for "arbitrary" events that we choose. Am I right in that???

Share this post


Link to post
Share on other sites
3 minutes ago, ZaellixA said:

So that means that we can't really add "new" eventHandlers in the sense that we can invoke EHs for "arbitrary" events that we choose. Am I right in that???

Yes.

Even if you could, you have to somehow tell the engine when a event is supposed to fire, which you would do via scripting. But we already have scripts and scriptedEventhandlers to do the same, no need to turn a scripted eventhandler into a engine event, just to fire another script from it in the end.

  • Like 1

Share this post


Link to post
Share on other sites

Wonderful...!!!

 

All this information clarifies a bunch of things to me.

 

Thanks a ton Dedmen. Extremely appreciated.

Share this post


Link to post
Share on other sites

i ve read this thread up and down some times and i feel a little dumb now ...

 

what I don't get is what exactly is the difference between calling a function in a loop which checks if an event is happening and calling a scripted EH which does the same thing at least in my current understanding.

 

i know this was already explained but idk why but I didn't understood

  • Like 3

Share this post


Link to post
Share on other sites

Well, it's really nice you asked. All I can say is what I have understood through "my journey in this thread".

 

There is not much difference between the two. But now imagine that you would like to trigger 10 different behaviors when one event happens. As Dedmen posted:

4 hours ago, Dedmen said:

Sure, for a custom event you would still have to check in a loop, BUT! If you need to do the same thing in several places, you can either run N loops, or just run one loop, with one scripted event that get's triggered, and N eventhandlers.

So, when you want an event to trigger various "arbitrary" behaviors which will be defined either by you or a completely different person in case you provide just a framework, it's definitely beneficial to work with scriptedEventHandlers.

 

Hope that helps. I could possibly think of an example if you think it could help.

  • Like 1

Share this post


Link to post
Share on other sites
1 hour ago, sarogahtyp said:

calling a function in a loop which checks if an event is happening and calling a scripted EH

 

 

There is no difference when calling, however, you can add any number of scriptedEH of the same name (each with their own behavior) and subsequently call all of them at the same time.

 

So say OP here had an addon that added a scripted EH for localized messages to a player (let’s name it sendMsg). Now say you have a function that i want to use in my mission that adds sendMsg and your message says “Hello!”. And now I’ve also added a sendMsg of my own with a message that says “To infinity and...well that’s about it”. Now when sendMsg is called the player would see both our messages.

 

Think about Respawn EHs, every mission maker out there probably does their own thing for respawn as well as every outside script that accounts for respawn in their mission. When the player respawns the EH fires and all of that code gets called, the mission maker, outside scripts, etc.

 

You can essentially “stack” executions of different code on one event and when that event fires (i.e. called) the entire stack is called.

  • Like 4

Share this post


Link to post
Share on other sites

thank you both. its much clearer now. i thought i missed a performance advantage of it but it's more a thing to get a better structured code then.

thx for the explanation

  • Like 2

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×