Jump to content

Recommended Posts

Posted (edited)

Currently attempting to make a multiplayer friendly Zeus zone restrictions script.

 

Basically, around my map, I need a kill zone that kills all units, players, or units editable by the curator, that leave the playable map area (enter the kill zone) after a ten second delay. I also need it so that if a player unit leaves the zone, they get a warning message too.

I am using the "ModuleCoverMap" to show the playable area. Around the edges of the playable map area I have four triggers that start the kill script for the player/Curator editable AI.

Quote

Zeus_T_ZoneRestriction1_1
Type: None

Activation: Anybody

Activation Type: Present

Repeatable: "Check"
Server Only: "Uncheck"

Condition: this && round ( time %1 ) == 1
On Activation: zoneR = [ thisTrigger ] execVM "zoneRestriction.sqf";

 

Quote

// zoneRestriction.sqf

 

_triggerActivated = _this select 0;

 

{

    if ( ( _x in ( list _triggerActivated ) ) && ( [ _x ] call BIS_fnc_isCuratorEditable isEqualTo true ) && ( alive _x ) ) then {

        titleText [ "<t size='4' color='#ff0000' font='PuristaSemibold' shadow='0' > UNAUTHORISED ZONE </t> <br/> <t size='2' font='PuristaSemibold' shadow='0' > Turn back now </t>", "PLAIN", 1, false, true ];

        sleep 10;

        _x setDamage 1;

    };

} foreach allUnits + vehicles;

Above is a very basic (semi) working zone restriction script. 

 

Currently, if a single unit enters the trigger, the script starts running, the problem is, if another unit enters two seconds later, they only have eight seconds to leave the restriction zone, rather than the ten seconds they are supposed to have (they should be killed later than the first unit, but the two units die at the same time). Also, I am unsure how the titleText function works for clients. It says on Biki that the titleText is a local effect, however, I am wondering if there is a better function for showing a warning message.

Edited by rkemsley
Solved

Share this post


Link to post
Share on other sites

Anybody present, on a general edited trigger, is activated everywhere (and anybody is fine for rabbits or even crates also 😄).That's arma!
 

Spoiler

 

Place a simple trigger with anybody present (50 - 100m radius) in front of the player (player outside or inside). In condition field:
hint str thisList; this

Don't need any code in on act or on deact field.... run that and wait a little (rab)bit.  🐇 🐍...

place an ammo crate if you want...

 

 

In MP, if you want to trigger something local, with a timer, you should learn how to write a scripted trigger with createTrigger , makeGlobal set to false.

This parameter is fine here and doesn't exist on edited trigger(s).

Script it in initPlayerLocal.sqf. This way, the trigger exist on every PC, but are working independently.

Now, the activation is local. Then, decide what to do with that. It's weird to apply it on AIs (because that usually concerns player), but you could write something for units belonging to player (if player is leader , so the AIs in his group are local).
Do not use allUnits + vehicles (in MP that can be resource killing with huge arrays). Prefer:  units player or group player...

  • Like 1

Share this post


Link to post
Share on other sites

@preserver833Ok, I complaint about you as you're using my pseudo with a fake sentence. Now, we are on another step above a simple ban.

  • Like 2

Share this post


Link to post
Share on other sites

Sorry, I didn't update what I did in the end.

 

So I took a look at how BI creates the kill zones around their map. They seem to occasionally just use two triggers, one which gives a warning, then another one further back which kills the player (I have just done this).

 

Quote

Zeus_T_ZoneRestriction1_1
Type: None

Activation: Any Player

Activation Type: Present

Repeatable: "Check"
Server Only: "Uncheck"

Condition: this && round ( time %1 ) == 1
On Activation: { if ( isPlayer _x ) then { titleText [ "<t size='4' color='#ff0000' shadow='2' > UNAUTHORISED ZONE </t> <br/> <t size='2' shadow='2' > Return to the playable area </t>", "PLAIN", 0.1, false, true ]; }; } foreach thisList;

 

Quote

Zeus_T_ZoneRestriction2_1
Type: None

Activation: Anybody

Activation Type: Present

Repeatable: "Check"
Server Only: "Uncheck"

Condition: this && round ( time %1 ) == 1
On Activation: { if ( alive _x && [ _x ] call BIS_fnc_isCuratorEditable isEqualTo true ) then { _x setDamage 1; }; } foreach thisList;

CountdownMin: 10 Mid: 10 Max: 10

 

  • Like 1

Share this post


Link to post
Share on other sites

Yes, fine. If you are using a anyPlayer present   as preset condition, you don't need to specify if (isPlayer _x) then {...} because thisList is composed with players only.
On the other hand the first player entering a area will activate the trigger, and, as you made it not server only, the trigger will fire on each PC, no matter the player who acted it. (So, any player will read the message!).

Here you should write:

{ if ( local _x ) then { titleText [ "<t size='4' color='#ff0000' shadow='2' > UNAUTHORISED ZONE </t> <br/> <t size='2' shadow='2' > Return to the playable area </t>", "PLAIN", 0.1, false, true ]; }; } foreach thisList;

 

Imho, there is a better solution with scripted triggers local (see above) from initPlayerLocal.sqf. If I have time I'll send you a code for this zone restriction.

Share this post


Link to post
Share on other sites
55 minutes ago, pierremgi said:

Yes, fine. If you are using a anyPlayer present   as preset condition, you don't need to specify if (isPlayer _x) then {...} because thisList is composed with players only.
On the other hand the first player entering a area will activate the trigger, and, as you made it not server only, the trigger will fire on each PC, no matter the player who acted it. (So, any player will read the message!).

Here you should write:

{ if ( local _x ) then { titleText [ "<t size='4' color='#ff0000' shadow='2' > UNAUTHORISED ZONE </t> <br/> <t size='2' shadow='2' > Return to the playable area </t>", "PLAIN", 0.1, false, true ]; }; } foreach thisList;

 

Imho, there is a better solution with scripted triggers local (see above) from initPlayerLocal.sqf. If I have time I'll send you a code for this zone restriction.

I think you are probably right about using "local scripted triggers".

 

What I am wondering is about the name of the local trigger when it is created. If I write something like this:

Spoiler

Zeus_T_ZoneRestriction1_1 = createTrigger [ "EmptyDetector", [ 16600, 24350, 0 ], false ];
Zeus_T_ZoneRestriction1_1 setTriggerArea [ 4000, 1050, 0, true, -1 ];
Zeus_T_ZoneRestriction1_1 setTriggerActivation [ "ANYPLAYER", "PRESENT", true ];
Zeus_T_ZoneRestriction1_1 setTriggerStatements [
    "this && round ( time %1 ) == 1",
    "{
        if ( local _x ) then { titleText [ "<t size='4' color='#ff0000' shadow='2' > UNAUTHORISED ZONE </t> <br/> <t size='2' shadow='2' > Return to the playable area </t>", "PLAIN", 0.1, false, true ];
        };
    } foreach thisList;",
    ];

...and have this located in my "initPlayerLocal.sqf", should do the trick on making the message local? (I'll also need to have another 3 more, so I have 4 in total).

Share this post


Link to post
Share on other sites

Here is a little script for making things go well, locally, (so without any exchange on net, resource and net friendly):

 

In initPlayerLocal.sqf (so the player already exists locally on his PC)


 

MGI_restrictedArea = {
    params [["_trig",objNull]];
    private _timer = -1;
    private _timeToDeath = _trig getVariable ["timeToDeath",0];
    while {alive player && triggerActivated _trig && _timer <= _timeToDeath} do {
        _timer = _timer +1;
        titleText [ "<t size='4' color='#ff0000' shadow='2' > UNAUTHORISED ZONE </t> <br/> <t size='2' shadow='2' > Return to the playable area </t>", "PLAIN", 1, false, true ];
                sleep 1;
    };
    if (triggerActivated _trig && alive player) then {
        vehicle player setDamage 1;
    };
};

private _trig = createTrigger ["emptyDetector",[1760.21,5787.81,0],FALSE];
_trig settriggerInterval 2;
_trig setTriggerArea [250, 250, 0, false, -1];
_trig setTriggerActivation ["ANYPLAYER","PRESENT",TRUE];
_trig setTriggerStatements ["thisList findIf {local _x} > -1",
  "thisTrigger spawn MGI_restrictedArea",
  "if (alive player) then {titleText [ '<t size=""4"" color=""#00ff00"" shadow=""2"" > AUTHORISED AREA </t><br/><t size=""2"" shadow=""2"" >You re leaving the forbidden zone</t>','PLAIN',1,false,true]};
"];
_trig setVariable ["timeToDeath",20];

Explanation:
The function MGI_restrictedArea is spawned by trigger activation.
I created a trigger, on coordinates I picked in editor on a due position for test. False here means local effect (makeGlobal false), on the contrary of all edited triggers which are EG.
The trigger interval is just the interval for the condition to be checked. It's so easy here, I didn't resist to add it but you can skip this line and the trigger will check every 0.5 sec as usual. It's just as reminder for saving resource (always in mind for MP)

The area is 250 radius, circle, no ceiling...

the activation is any player (There are other means but it's a working example), present , repeatable;

the statements (must be stringed unfortunately but it's not so difficult:

 *  the condition: ⚠️ As I'm using the preset condition "any player present", of course, even locally, the trigger will fire on every pc! So I'm just checking for thisList (players) containing a local entities (a player is always local to his PC lol) This way, only one trigger is concerned!

* now, I'm really local and I can do what I want with the area and a timer. While the trigger is activated, the timer increases and the player must leave or die.

* I added a little code for player leaving the area. Feel free to change any parameter for timer or sleep or text time ...

 

As you can see, I kill vehicle player instead of player. It's up to you. Player inside a vehicle will blow up with it, player on foot will die.

There is no code for units in player group, or abandoned vehicles...

You can kill, for example : units player select {_x in area _trig}    or else.

 

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites

@pierremgi

Spoiler
1 hour ago, pierremgi said:

Here is a little script for making things go well, locally, (so without any exchange on net, resource and net friendly):

 

In initPlayerLocal.sqf (so the player already exists locally on his PC)


 



MGI_restrictedArea = {
    params [["_trig",objNull]];
    private _timer = -1;
    private _timeToDeath = _trig getVariable ["timeToDeath",0];
    while {alive player && triggerActivated _trig && _timer <= _timeToDeath} do {
        _timer = _timer +1;
        titleText [ "<t size='4' color='#ff0000' shadow='2' > UNAUTHORISED ZONE </t> <br/> <t size='2' shadow='2' > Return to the playable area </t>", "PLAIN", 1, false, true ];
                sleep 1;
    };
    if (triggerActivated _trig && alive player) then {
        vehicle player setDamage 1;
    };
};

private _trig = createTrigger ["emptyDetector",[1760.21,5787.81,0],FALSE];
_trig settriggerInterval 2;
_trig setTriggerArea [250, 250, 0, false, -1];
_trig setTriggerActivation ["ANYPLAYER","PRESENT",TRUE];
_trig setTriggerStatements ["thisList findIf {local _x} > -1",
  "thisTrigger spawn MGI_restrictedArea",
  "if (alive player) then {titleText [ '<t size=""4"" color=""#00ff00"" shadow=""2"" > AUTHORISED AREA </t><br/><t size=""2"" shadow=""2"" >You re leaving the forbidden zone</t>','PLAIN',1,false,true]};
"];
_trig setVariable ["timeToDeath",20];

Explanation:
The function MGI_restrictedArea is spawned by trigger activation.
I created a trigger, on coordinates I picked in editor on a due position for test. False here means local effect (makeGlobal false), on the contrary of all edited triggers which are EG.
The trigger interval is just the interval for the condition to be checked. It's so easy here, I didn't resist to add it but you can skip this line and the trigger will check every 0.5 sec as usual. It's just as reminder for saving resource (always in mind for MP)

The area is 250 radius, circle, no ceiling...

the activation is any player (There are other means but it's a working example), present , repeatable;

the statements (must be stringed unfortunately but it's not so difficult:

 *  the condition: ⚠️ As I'm using the preset condition "any player present", of course, even locally, the trigger will fire on every pc! So I'm just checking for thisList (players) containing a local entities (a player is always local to his PC lol) This way, only one trigger is concerned!

* now, I'm really local and I can do what I want with the area and a timer. While the trigger is activated, the timer increases and the player must leave or die.

* I added a little code for player leaving the area. Feel free to change any parameter for timer or sleep or text time ...

 

As you can see, I kill vehicle player instead of player. It's up to you. Player inside a vehicle will blow up with it, player on foot will die.

There is no code for units in player group, or abandoned vehicles...

You can kill, for example : units player select {_x in area _trig}    or else.

 

I'd like this to also affect all CuratorEditable units as well (so the Curator doesn't just send AI out of the map).

 

Would I change the "Any Player" part to west/independent? Then in the conditions, use what I had for my initial script ("{ if ( alive _x && [ _x ] call BIS_fnc_isCuratorEditable isEqualTo true ) then { _x setDamage 1; }; } foreach thisList;")?

 

Edit: Does the name of the trigger matter as I am creating the triggers locally, there wont be an issue of potentially 4 triggers of the same name spawned in one map (My map has max players of 4, so that's means there could be up to 16 triggers being loaded into the game. 4 for every side of the playable area.)

Share this post


Link to post
Share on other sites

No, the name of trigger doesn't matter. That's not really a "name" here but a local variable as reference for setting the attributes of the trigger (same as any _group created or any _object....). You can re-use it, even in the same script. That doesn't matter if you don't need to refer to them in other scripts (somewhere else).

Spoiler

Example: { private _trig = createTrigger ["emptyDetector",[random worldSize,random worldSize] ]; _trig setTriggerArea [200,200,0,false,-1]; _trig setTriggerActivation ["WEST","PRESENT",true]; _trig setTriggerStatements ["this","hint 'OK'","hint 'NOK' "]; private _mk = createMarker [str random 1, getpos _trig]; _mk setMarkerShape "ellipse"; _mk setMarkerColor "colorGreen"; _mk setMarkerSize [200,200] } count [1,2,3,4,5,6,7,8,"blabla","anything"];

 

For curators editable objects, I can't help. If I'm right, you want an exclusive area instead of restricted one, for each player playing as Zeus..? It's above my head.
I don't know why you are disregarding the BI modules for areas and area type (inside/outside) . That said, I didn't test them.

 

for trigger: anyBody present and cond: "thisList select {_x in curatorEditableObjects aCuratorHere }"    should work.

  • Like 1

Share this post


Link to post
Share on other sites

@pierremgi

Spoiler
On 7/1/2021 at 12:25 AM, pierremgi said:

Here is a little script for making things go well, locally, (so without any exchange on net, resource and net friendly):

 

In initPlayerLocal.sqf (so the player already exists locally on his PC)


 



MGI_restrictedArea = {
    params [["_trig",objNull]];
    private _timer = -1;
    private _timeToDeath = _trig getVariable ["timeToDeath",0];
    while {alive player && triggerActivated _trig && _timer <= _timeToDeath} do {
        _timer = _timer +1;
        titleText [ "<t size='4' color='#ff0000' shadow='2' > UNAUTHORISED ZONE </t> <br/> <t size='2' shadow='2' > Return to the playable area </t>", "PLAIN", 1, false, true ];
                sleep 1;
    };
    if (triggerActivated _trig && alive player) then {
        vehicle player setDamage 1;
    };
};

private _trig = createTrigger ["emptyDetector",[1760.21,5787.81,0],FALSE];
_trig settriggerInterval 2;
_trig setTriggerArea [250, 250, 0, false, -1];
_trig setTriggerActivation ["ANYPLAYER","PRESENT",TRUE];
_trig setTriggerStatements ["thisList findIf {local _x} > -1",
  "thisTrigger spawn MGI_restrictedArea",
  "if (alive player) then {titleText [ '<t size=""4"" color=""#00ff00"" shadow=""2"" > AUTHORISED AREA </t><br/><t size=""2"" shadow=""2"" >You re leaving the forbidden zone</t>','PLAIN',1,false,true]};
"];
_trig setVariable ["timeToDeath",20];

Explanation:
The function MGI_restrictedArea is spawned by trigger activation.
I created a trigger, on coordinates I picked in editor on a due position for test. False here means local effect (makeGlobal false), on the contrary of all edited triggers which are EG.
The trigger interval is just the interval for the condition to be checked. It's so easy here, I didn't resist to add it but you can skip this line and the trigger will check every 0.5 sec as usual. It's just as reminder for saving resource (always in mind for MP)

The area is 250 radius, circle, no ceiling...

the activation is any player (There are other means but it's a working example), present , repeatable;

the statements (must be stringed unfortunately but it's not so difficult:

 *  the condition: ⚠️ As I'm using the preset condition "any player present", of course, even locally, the trigger will fire on every pc! So I'm just checking for thisList (players) containing a local entities (a player is always local to his PC lol) This way, only one trigger is concerned!

* now, I'm really local and I can do what I want with the area and a timer. While the trigger is activated, the timer increases and the player must leave or die.

* I added a little code for player leaving the area. Feel free to change any parameter for timer or sleep or text time ...

 

As you can see, I kill vehicle player instead of player. It's up to you. Player inside a vehicle will blow up with it, player on foot will die.

There is no code for units in player group, or abandoned vehicles...

You can kill, for example : units player select {_x in area _trig}    or else.

 

 

 

I am planning on combining your "MGI_restrictedArea" function (because it works extremely well!) with my original plan. (Yeah, I know I am being awkward, but I really need CuratorEditable units to also die if they leave the area).

 

Basically, I am going to have sided kill zones, one for BLUFOR and one for Independent.


BLUFOR kill zone:

Spoiler

ZeusBLUFOR_T_ZoneRestriction1_1
Type: None

Activation: BLUFOR

Activation Type: Present

Repeatable: "Check"
Server Only: "Uncheck"

Condition: this && round ( time %1 ) == 1
On Activation: { if ( alive _x && [ _x ] call BIS_fnc_isCuratorEditable isEqualTo true ) then { _x setDamage 1; }; } foreach thisList;

CountdownMin: 10 Mid: 10 Max: 10

Independent kill zone:

Spoiler

ZeusIndependent_T_ZoneRestriction1_1
Type: None

Activation: Independent

Activation Type: Present

Repeatable: "Check"
Server Only: "Uncheck"

Condition: this && round ( time %1 ) == 1
On Activation: { if ( alive _x && [ _x ] call BIS_fnc_isCuratorEditable isEqualTo true ) then { _x setDamage 1; }; } foreach thisList;

CountdownMin: 10 Mid: 10 Max: 10

(Would you recommend "Checking" server only for these kills zones?)

 

Then I was going to use your script to create the warning message for the players, so I can confirm that the message is local to the unit in the zone.

 

"initPlayerLocal.sqf"

Spoiler

MGI_restrictedArea = {

    params [ [ "_trig", objNull ] ];

    while { alive player && triggerActivated _trig } do {

        titleText [ "<t size='4' color='#ff0000' shadow='2' > UNAUTHORISED ZONE </t> <br/> <t size='2' shadow='2' > Return to the playable area </t>", "PLAIN", 0.1, false, true ];

        sleep 1;

    };

};

Spoiler

private _trig = createTrigger [ "emptyDetector", [ 16600, 24350, 0 ], false ];

_trig settriggerInterval 2;

_trig setTriggerArea [ 4000, 1050, 0, true, -1 ];

_trig setTriggerActivation [ "ANYPLAYER", "PRESENT", true ];

_trig setTriggerStatements [ "thisList findIf {local _x} > -1", "thisTrigger spawn MGI_restrictedArea", "" ];

 

private _trig = createTrigger [ "emptyDetector", [ 19550, 20800, 0 ], false ];

_trig settriggerInterval 2;

_trig setTriggerArea [ 1050, 2500, 0, true, -1 ];

_trig setTriggerActivation [ "ANYPLAYER", "PRESENT", true ];

_trig setTriggerStatements [ "thisList findIf {local _x} > -1", "thisTrigger spawn MGI_restrictedArea", "" ];

 

private _trig = createTrigger [ "emptyDetector", [ 16600, 17250, 0 ], false ];

_trig settriggerInterval 2;

_trig setTriggerArea [ 4000, 1050, 0, true, -1 ];

_trig setTriggerActivation [ "ANYPLAYER", "PRESENT", true ];

_trig setTriggerStatements [ "thisList findIf {local _x} > -1", "thisTrigger spawn MGI_restrictedArea", "" ];

 

private _trig = createTrigger [ "emptyDetector", [ 13650, 20800, 0 ], false ];

_trig settriggerInterval 2;

_trig setTriggerArea [ 1050, 2500, 0, true, -1 ];

_trig setTriggerActivation [ "ANYPLAYER", "PRESENT", true ];

_trig setTriggerStatements [ "thisList findIf {local _x} > -1", "thisTrigger spawn MGI_restrictedArea", "" ];

 

 

There's another thing I am wondering about this script. Could I make it local to all BLUFOR\Independent units that enter the zone rather than only players (or would that be too taxing for the system)?

 

Having the message pop up, for units currently being controlled by Zeus (within the kill zone), would be a nice little effect. However, Arma doesn't recognise units being controlled by Zeus to be players, so the message won't appear on them (that's why it would need to be local to all BLUFOR\Independent units in the zone).

 

I would test this stuff first before asking, however, it's quite difficult for me to test this sort of trigger just on my own (because I am unable to test whether it is local or displayed to all players), so I was wondering about your theory/idea first before I give it a try. Just to see if you think it would work?

Share this post


Link to post
Share on other sites

Roughly, units placed by a curator are local to the curator's PC, even if another curator can have them in his editable objects (then can order a move with waypoint).

The event handlers about curator are all local arguments (LA). So, that should work...

After that, displaying a text about entry/exit area for each curator placed objects, on due curator, is probably possible. Weird but possible. I can't help more.

  • Thanks 1

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

×