Jump to content
Varn

How to fire trigger when a percentage of items are present

Recommended Posts

I've never used Event Handlers before, and the fact that I'm not seeing any module for them in the editor tells me that I'm probably way further in above my head than I originally though.

Share this post


Link to post
Share on other sites

Well, an easy way to do it would be to create an init.sqf (Single Player) or initServer.sqf (Multi-Player) and type the following inside

addMissionEventHandler["EntityKilled", {
	private _killedUnit = _this select 0; // The unit that died
	if(((getPos _killedUnit) inArea _areaInsideWhichYouWantToCheck) then { // Check if killed unit is inside the desired area
		systemChat "Someone died in the specified area...!!!"; // Do something just because the condition evaluated to true
	};
}];

where the variable _areaInsideWhichYouWantToCheck should be a trigger, a marker or a location. Alternatively you could specify the area of interest in the format [centre, xLen, yLen, angle, isRectangle, zLen]. Just keep in mind that xLenyLen and zLen are actually x/2, y/2 and z/2. For more information you can check the doc of inArea.

 

One more thing... Please avoid long names such as the one I used here because it makes code really hard to read, hard to maintain (and reuse) and you decrease efficiency (length of variable names does have an impact on performance).

 

Finally, keep in mind that this is untested and you should treat with caution. Please feel free to post here if you encounter further problems and have fun :).

  • Like 1

Share this post


Link to post
Share on other sites

How do I make this DO something though, like initiate a trigger or execute the change side code? If I'm reading this right, it should go where the "systemChat" bit is, but I have no idea what the proper command or syntax should be.

Share this post


Link to post
Share on other sites
addMissionEventHandler["EntityKilled", {
	private _killedUnit = _this select 0; 
	if(((getPos _killedUnit) inArea _AO) 
then {_allIndforGroups = allgroups select {side _x isEqualTo resistance}; 
_allIndforGroups apply {_grp = creategroup west;units _x joinSilent _grp};
	};
}];

I probably messed up the syntax there, but would that work if I stuck that in the init.sqf and had a trigger that covered the whole mission area named "AO"?

Share this post


Link to post
Share on other sites

Well, more like this:

addMissionEventHandler ["EntityKilled", {
    params ["_unit", "_killer", "_instigator", "_useEffects"];
    if ((getPos _unit) inArea AO) 
    then {
        _allIndforGroups = allGroups select {side _x isEqualTo resistance};
        _allIndforGroups apply {_grp = creategroup [west, true]; units _x joinSilent _grp};
    };
}];

But all that does is change all INDFOR units to WEST when anyone dies in AO.

  • Like 1

Share this post


Link to post
Share on other sites

Well that's kind of exactly what I want to happen. My players are all trigger happy retards, so I look forward to having all the locals turn on them once they "accidentally" shoot one. I take it I can add multiple event handlers all linked to separate trigger areas to simulate different populations far away still remaining friendly by just copy pasting the code with different "AO" entries? Or is it going to turn all the units on the map and not just the ones in the trigger area? In which case I guess if I wanted to get squirly I could make another trigger to change them back

Share this post


Link to post
Share on other sites

I don't think you understand. If any unit, regardless of side, dies in the AO area for any reason, all Independent units will be switched to West, AI included.

Something like this makes more sense:

addMissionEventHandler ["EntityKilled", { 
    params ["_unit", "_killer", "_instigator", "_useEffects"]; 
    if ((getPos _unit) inArea AO && (side _unit isEqualTo resistance || side _unit isEqualTo civilian))
    then { 
        if (isNull _instigator) then {_instigator = UAVControl vehicle _killer select 0}; 
        if (isNull _instigator) then {_instigator = _killer};
        if (isPlayer _instigator) then {
            _rating = rating _instigator;
            _instigator addRating - (_rating) - 10000;
        };
    }; 
}];

If a player kills either a civilian or Independent unit in the AO area, their rating will drop to -10000, making them sideEnemy, which is to say everyone's enemy. Side note - you only need to set the rating to -2001 to switch a unit to sideEnemy, but let's go all in.

One could get clever and work out a "three strikes" policy, probably by setting/modifying a variable on _instigator. I'm going to sleep.

*edit* - cleaned up/fixed, don't Arma while sleepy

  • Like 1

Share this post


Link to post
Share on other sites

Understandable, but it still works in my case. I only have 4-5 players and they have no AI on their team, and IND is friendly with RED, and the RED unit won't show up until a bit after the IND controlled areas. There are only going to be a few dozen non-civ units in the map. Again, thanks for all the help. I'm crap at learning code, but I can generally figure out how stuff sort of works if I can pick apart something that already works.

Share this post


Link to post
Share on other sites
11 minutes ago, Varn said:

but it still works in my case.


Again:

 

20 minutes ago, Harzach said:

If any unit, regardless of side, dies in the AO area for any reason

 

So if a player is killed by OPFOR, they all get switched.

  • Like 1

Share this post


Link to post
Share on other sites

Harzach is most probably right... I believe that the initial code I provided does not solve your problem and you should somehow filter the entities in a way (Harzach's way seems to work fine).

 

@Harzach, not sure what the

_rating = _rating - _rating;

line is supposed to do though. It seems to me that you should delete it since you don't use _rating anywhere. May be missing something though.

 

What I would do for your problem would be something like

addMissionEventHandler["EntityKilled", {
	// Get parameters
	private _unitKilled = _this select 0; // Get the killed unit
	private _killer = _this select 1; // Get the killer
	
	// Get the players
	private _hummies = allPlayers - (entities "HeadlessClient_F");

	// Perform checks
	if(_hummies findIf {_x isEqualTo _killer} != -1 && {side _killedUnit isEqualTo resistance || {side _killedUnit isEqualTo civilian}}) then {
		// Make sure to make all civilian and independent units in an area close to the players hostile
		private _unitsInArea = allUnits inAreaArray [getPos _killer, 50, 50, 0, false, 50]; // The area will be a sphere of radius 50 metres
		_unitsInArea = _unitsInArea - _hummies; // Make sure you won't make the players change side
		
		_unitsInArea = _unitsInArea select {side _x isEqualTo resistance || {side _x isEqualTo civilian}}; // Pick only the IndFor and Civs

		// Create a west group to add the units
		private _grp = createGroup[west, true];

		// Put all the units in the area in the group
		{
			_x joinSilent _grp; // Join the west group
		} forEach _unitsInArea;
	};
}];

You can change the values in inAreaArray to make the area to make units hostile greater or smaller (see the doc for more details).

 

Additionally, just a small note. In multiple checks, most often than not, it helps to use {} to place the all checks after the first one. In this way, if one of the checks fails the rest are not evaluated.

 

Once more...... This code is not tested so please test before you use it in "real conditions".

Edited by ZaellixA
  • Like 1

Share this post


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

Harzach is most probably right

 

What fantasy world are you living in 😄

Fixed my snippet above.  

I find it best practice to stick to the params as described in the Biki entry 

addMissionEventHandler ["EntityKilled", { 
    params ["_unit", "_killer", "_instigator", "_useEffects"]; 

It keeps things consistent and easy for others to read.

  • Like 1
  • Haha 1

Share this post


Link to post
Share on other sites
On 5/27/2020 at 10:10 AM, ZaellixA said:

// Get parameters

Params.

 

On 5/27/2020 at 10:10 AM, ZaellixA said:

// Put all the units in the area in the group

{

_x joinSilent _grp; // Join the west group

} forEach _unitsInArea;

uh... forEach? why?

Also you have syntax error, joinSilent takes array, not object.

https://community.bistudio.com/wiki/joinSilent

 

_unitsInArea joinSilent _grp;

 

On 5/27/2020 at 10:10 AM, ZaellixA said:

side _x isEqualTo resistance || {side _x isEqualTo civilian}

 

side _x in [resistance, civilian]

 

On 5/27/2020 at 10:10 AM, ZaellixA said:

_hummies findIf {_x isEqualTo _killer}

 

_hummies find _killer

 

On 5/27/2020 at 10:10 AM, ZaellixA said:

{side _killedUnit isEqualTo resistance || {side _killedUnit isEqualTo civilian}}

 

{side _killedUnit in [resistance, civilian]}

 

  • 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

×