Jump to content
iV - Ghost

EventHandler for killed object

Recommended Posts

How can I use a eventHandler instead of a scripted trigger?

For now the trigger looks like this:

 

// TRIGGER FOR SUCCEEDED END
_triggerSucceeded = createTrigger ["EmptyDetector", [8308, 9902, 0], true];
_triggerSucceeded setTriggerArea [0, 0, 0, false, 0];
_triggerSucceeded setTriggerActivation ["NONE", "", false];
_triggerSucceeded setTriggerTimeout [8, 8, 8, false];
_triggerSucceeded setTriggerType "NONE";
_triggerSucceeded setTriggerStatements [
  
    // CONDITIONS
    "!alive ([8308, 9902] nearestObject 170313)",
		
		
    // ON ACTIVATION
    "['Airport_T1', 'Succeeded', false] remoteExec ['BIS_fnc_taskSetState', 0, true];
    ['TaskSucceeded', ['', localize 'STR_iV_TaskSucceeded_PhoneMast']] remoteExec ['BIS_fnc_showNotification', 0, true];
	
    call iV_fnc_taskSucceededNumbers;",
		
		
     // ON DEACTIVATION
     ""
		
];

 

Share this post


Link to post
Share on other sites

Your trigger is fine! Even if you have a dozen like this one, it's OK for CPU load. You can kill the "detectors" if you spawn them during the mission. What else?

 

Share this post


Link to post
Share on other sites

1. Performance

People tell me that a eventHandler is better for the performance.

I have 50+ tasks (getting more) and for every task a scripted trigger like this.

But only 3 tasks are active on the same time. But I don't delete the trigger after the task is complete.

Maybe I should do this?

 

2. Join in progress

And a second problem is that I could not complete the mission after JIP.

And I don't know why. I think the trigger for succeeded end is not present?

Test's without JIP on server was successful. Check the conditions, ... everything all right.

Share this post


Link to post
Share on other sites

1. performance: triggers are Ok for performance.  Conditions are checked twice per second. So, it depends on what you are checking (big arrays of units or players, plenty of map objects or some specific ones...)

An EH will fire on an event (obvious). It's cool but not adapted to your aim (EH killed works on unit/vehicle but not building.)

You could test EH dammaged (if your building accept damages) or MEH "buildingChanged" is it has at least two models (normal and ruins).

 

2. Where did you fire your code? It must run on each player (init.sqf is OK for this kind of trigger. server only is rather for spawning unit on server only).

 I never use BIs_fnc_showNotification, I never remote exec anything with task, because all is already embedded with BIS_fnc_setTask ! I even create all my tasks with this function. You don't need createTask command or Bis_fnc_taskcreate. Forgot them.

Then, just play with BIS_fnc_taskState (return the task state) / BIS_fnc_tasksetState (set the state).

 

 

 

 

Share this post


Link to post
Share on other sites

The task-script are startet by the taskmanager.sqf in the ..\scripts\taskmanager-folder.

It opened with a addAction on a laptop.

 

The array of tasks is in the initServer.sqf and the iV_fnc's are in the init.sqf.

 

 

CREATE TASK

And this is may fnc for creating the tasks:

iV_fnc_createTask = {

    // TIMEOUT
    sleep 3;
	
	
    // CREATE PARENT AND CHILD TASK
    [west, [_parentTask], ["", _parentTask, _taskMarker], objNull, false, 3, false, ""] call BIS_fnc_taskCreate;
    [west, [_taskID, _parentTask], [_taskDescription, _taskTitle, _taskMarker], _taskMarker, false, 3, false, _taskMarkerType, true] call BIS_fnc_taskCreate;


    // ASSIGN TASK
    ["TaskAssigned", ["", _taskTitle]] remoteExec ["BIS_fnc_showNotification", 0, true];

};

 

Share this post


Link to post
Share on other sites

As addAction is local to the player (executing the command), you should aim at server.

Try to remoteExec the code (inside the addAction) on server (2).

 

 

Share this post


Link to post
Share on other sites

OK thx. Is the follow code the right syntax?

[this, [localize "STR_iV_AssignTask"]] remoteExec ["scripts\taskmanager\taskManager.sqf", 2, true];

 

Share this post


Link to post
Share on other sites

Probably not.

I don't understand why you are using a magic variable <this>

I'd rather write something like:

[  your array of params here, "scripts\taskmanager\taskManager.sqf"] remoteExec ["spawn", 2, true];

Share this post


Link to post
Share on other sites

Please take a look on Example 4 from the addAction Wiki.

For now my addAction looks like this:

this addAction [localize "STR_iV_AssignTask", "scripts\taskmanager\taskManager.sqf"];

 

 

I think the addAction with remoteExec could look like this?

[this, [localize "STR_iV_AssignTask", {"scripts\taskmanager\taskManager.sqf"}]] remoteExec ["addAction", 2, true];

 

What do you mean with "this"?

Isn't it the object where the addAction is assigned to?

Share this post


Link to post
Share on other sites

I know addAction and that wasn't what you wrote.

Yes, <this> apply to the object in its init field. The "empty detector" (trigger) is a "vehicle" without init field. <This> doesn't mean anything for a trigger. There is another magic variable: thisTrigger for that. But, you can't apply an addAction to a trigger anyway. Same for helipads. You need to apply addAction to a unit or a physical object. (I don't know exactly the perimeter of these workable objects but thing or thingX classes should work).

 

What you could do:

- add a standard object, useful to see the maintenance area (cones, platform,  workshop...) Add the addaction on a eligible object (just test:  this addAction ["hint",{hint "ok"}];)

- You don't need any trigger.  You just need to face the object within 15m of it. (addAction can be applied on player to skip this engine limitation but I don't recommend that here.

Just test:

this addAction ["<t color='#55ffff'>nice test</t>",
  {
    openmap [true,false];
    titleText["Select Task Position", "PLAIN"];
     onMapSingleClick "
      [west,['exampleTask'],['I decided to put the war on this area', 'Attack here', ' '], _pos,1,3,true, 'attack', true] call BIS_fnc_taskCreate;
      openmap [false,false];
      onMapSingleClick '';
      false
    "
  }
,nil, 5,false, true,"","hintSilent str time; true"];

 

NOTE: just for fun, as you can see, I can run an "onEachFramed" code in condition field of the addAction. The condition ends by true, so the standard engine one applies (15 m + facing object).

 

If you want to add a trigger condition, you just have to add: triggerActivated nameOfTrigger in this field instead of true. But you can also write some similar conditions as the ones of your trigger here and check if this one remains useful.

 

 

 

 

 

Share this post


Link to post
Share on other sites

Maybe I understood something wrong.

My addAction for the taskManager is in a init field of a laptop not in a trigger.

The trigger(s) should be created if the taskManager selected a task on random.

The triggers are all scripted in the task files. Sometimes only one for succeeded end and sometimes one more for failed end.

 

 

Share this post


Link to post
Share on other sites

Or it's my bad.

- apply your addAction on the laptop (ok)

- in addAction code , just create your task (no need to remote exec it)

- "The trigger(s) should be created if the taskManager selected a task on random." has no sense for me.

- just continue to spawn a code (inside addAction) to waitUntil {some event} (same as trigger condition);

- set the task as completed.

 

 

Share this post


Link to post
Share on other sites

Sound that I should delete the trigger and use a waitUntil instead of the trigger?

Share this post


Link to post
Share on other sites

Difficult for me to say what you are using your trigger for. But yes, there is no need to add a trigger if you check a simple building destruction . the waitUntil {sleep 2; some condition} is  smart for CPU load.

Share this post


Link to post
Share on other sites
  • Check alive or not alive buildings
  • Check if a object is distance < 100
  • Check alive or not alive unit
  • Check if deactivated minefield in areaTrigger

 

But if I change some triggers into a waitUntil loop the problem is still there?

I have still to make the addAction via remoteExec. How would the code look like?

 

If you don't understand what I mean you can have my missions to take a look.

Share this post


Link to post
Share on other sites

OK, I have delete the triggers and using a waitUntil loop. But my problems are still there.

The waitUntil loop is local (script starts via addAction) and other players or If the caller rejoin can't succeeded the task.

 

Is there a way to make a waitUntil loop global or public?

Share this post


Link to post
Share on other sites

I'm trying to use remoteExec with waitUntil but it doesn't work.

 

[{

    waitUntil {
      
        sleep 1;
        !alive ([8308, 9902] nearestObject "Land_TTowerSmall_1_F");
      
    };
	
    if (!alive ([8308, 9902] nearestObject "Land_TTowerSmall_1_F")) then {

        call iV_fnc_succeededTask;
        call iV_fnc_taskSucceededNumbers;
	
    };
		
}] remoteExec ["call", 0, true];

This is part of a script which is executed by addAction (local). But I need this part for every player.

Share this post


Link to post
Share on other sites

[ [], { waitUntil { sleep 1; !alive ([8308, 9902] nearestObject "Land_TTowerSmall_1_F"); }; if (!alive ([8308, 9902] nearestObject "Land_TTowerSmall_1_F")) then { call iV_fnc_succeededTask; call iV_fnc_taskSucceededNumbers; }}] remoteExec ["spawn",0,true]

 

But it's totally wrong. A waste of code and a network load for nuts. As I explained you, you already have all you need to make a task/ task state JIP compatible with the BI functions.

 

  • Like 1

Share this post


Link to post
Share on other sites

Yes, you have telling me. But I'm trying for hours and it doesn't work.

 

 

Thats my fnc for creating tasks:

[west, [_taskID, _parentTask], [_taskDescription, _taskTitle, _taskMarker], _taskMarker, false, 3, false, _taskMarkerType, true] call BIS_fnc_taskCreate;

And that's for setting the state:

[_taskID, "Succeeded", false] remoteExec ["BIS_fnc_taskSetState", 0, true];

 

 

Both works fine. But the "trigger" (waitUntil- & if then loop for now) is not presented on every client.

So only the caller from the script can make this task.

Share this post


Link to post
Share on other sites

That's because you mix addAction (triggering a local code on PC's caller), server where the object (building) is, and task with chosen clients.

 

Keep it simple:

objects stay on server: laptop, building(s).

addAction on laptop (ok),

run the code of addAction on server! This will avoid locality problems with player: 

laptop ["your action name", {[ [ ], { your code here} ] remoteExec ["spawn",2] }];

As you can see, I spawned the code, not called it, to make waituntil/sleep working (inside a scheduled scope)

From server, now, you have all you need, the objects and the task(s) creation and distribution.

Share this post


Link to post
Share on other sites

The problem is that I can't remoteExec the whole task file because I have some mathematics inside.

E.G. number_assignedTasks. For every active task I add +1 and for every failed or succeeded task I add -1.

In the taskManager.sqf I have task limit of 3. And if the task file is loaded x-times instead of only 1 times.

// CHECK IF A TASK IS AVAILABLE
if (!isNil "_randomTask" && (number_AssignedTasks < 3)) then {

    execVM _randomTask;
    sleep 3;
	
} else {
    hint localize "STR_iV_NoTasksAvailable";
};

 

If I wanna remoteExec the whole file I could do this.

But then I have the mathematic problem and my tasks are created twice (1x German, 1x English).

I think because the BIS_fnc_taskCreate is global too. It works twice.

// CHECK IF A TASK IS AVAILABLE
if (!isNil "_randomTask" && (number_AssignedTasks < 3)) then {

    [_randomTask] remoteExec ["execVM", 0, true];
    sleep 3;
	
} else {
    hint localize "STR_iV_NoTasksAvailable";
};

 

Share this post


Link to post
Share on other sites
2 hours ago, pierremgi said:

[ [], { waitUntil { sleep 1; !alive ([8308, 9902] nearestObject "Land_TTowerSmall_1_F"); }; if (!alive ([8308, 9902] nearestObject "Land_TTowerSmall_1_F")) then { call iV_fnc_succeededTask; call iV_fnc_taskSucceededNumbers; }}] remoteExec ["spawn",0,true]

 

But it's totally wrong. A waste of code and a network load for nuts. As I explained you, you already have all you need to make a task/ task state JIP compatible with the BI functions.

 

 

OK. This works now. Yeah!

 

 

 

SCORESYSTEM

Only a problem with my scoresystem (call iV_fnc_taskSucceededNumbers;). It count x-times (for every client).

Is there a way to exfil the scoresystem from remoteExec?

 

 

 

Some details about the scoresystem:

 

initServer.sqf

// SET NUMBERS FOR SCRIPTS
number_AssignedTasks = 0;
publicVariable "number_AssignedTasks";

number_SucceededTasks = 0;
publicVariable "number_SucceededTasks";

number_FailedTasks = 0;
publicVariable "number_FailedTasks";

number_GlobalScore = 0;
publicVariable "number_GlobalScore";

number_CivReputation = 0;
publicVariable "number_CivReputation";

 

fnc_numberFunctions.sqf

// TASK ASSIGNED NUMBERS
iV_fnc_taskAssignedNumbers = {
    
    number_AssignedTasks = number_AssignedTasks + 1;
    publicVariable "number_AssignedTasks";
	
};



// TASK SUCCEEDED NUMBERS
iV_fnc_taskSucceededNumbers = {

    number_AssignedTasks = number_AssignedTasks - 1;
    publicVariable "number_AssignedTasks";

    number_SucceededTasks = number_SucceededTasks + 1;
    publicVariable "number_SucceededTasks";
	
    number_CivReputation = number_CivReputation + 15;
    publicVariable "number_CivReputation";

    number_GlobalScore = number_GlobalScore + 10;
    publicVariable "number_GlobalScore";
	
};



// TASK FAILED NUMBERS
iV_fnc_taskFailedNumbers = {

    number_AssignedTasks = number_AssignedTasks - 1;
    publicVariable "number_AssignedTasks";

    number_FailedTasks = number_FailedTasks + 1;
    publicVariable "number_FailedTasks";
	
    number_CivReputation = number_CivReputation - 10;
    publicVariable "number_CivReputation";
	
    number_GlobalScore = number_GlobalScore - 20;
    publicVariable "number_GlobalScore";
	
};

 

The numberFunctions are called in the script files (E.G. Airport_T1, Airport_T2, ...).

iV_fnc_taskAssignedNumbers works fine on the beginning of the script. But not iV_fnc_taskSucceededNumbers after remoteExec.

Share this post


Link to post
Share on other sites

if (isServer) then {  what you want} ; This way the server keeps the reference for everything. You can publicVariable the values if you want to display them on each client.

  • Like 1

Share this post


Link to post
Share on other sites

Works fine!!! Thx a lot!!!

 

Here is one of my task files:

// VARIABLES
private ["_taskID", "_taskMarker", "_taskTitle", "_taskDescription", "_taskMarkerType", "_parentTask"];

_taskID = "Airport_T1";
_taskMarker = "Marker_Airport_1";
_taskTitle = localize "STR_iV_TaskTitle_PhoneMast";
_taskDescription = localize "STR_iV_TaskDesc_PhoneMast";
_taskMarkerType = "destroy";
_parentTask = localize "STR_iV_Airport";



// CREATE TASK, ASSIGN AND SET STATE
if (alive ([8308, 9902] nearestObject "Land_TTowerSmall_1_F")) then {
	
    // CREATE PARENT AND CHILD TASK
    call iV_fnc_taskAssignedNumbers;
    call iV_fnc_createTask;
	
	
    // SUCCEEDED END
    [[], {
	
        private ["_taskID", "_taskTitle"];
		
        _taskID = "Airport_T1";
        _taskTitle = localize "STR_iV_TaskTitle_PhoneMast";
		
	
        waitUntil {
		
            sleep 1;
            !alive ([8308, 9902] nearestObject "Land_TTowerSmall_1_F");
			
        };
		
		
        if (!alive ([8308, 9902] nearestObject "Land_TTowerSmall_1_F")) then {
		
            call iV_fnc_succeededTask;
			
            if (isServer) then {
                call iV_fnc_taskSucceededNumbers;
            };
			
        };
		
    }] remoteExec ["spawn", 0, true];
	
} else {

    hint localize "STR_iV_TaskNotAvailable";
	
};

 

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

×