Cryonic. 2 Posted July 4, 2017 I am currently using the below script as a safe zone, where players and vehicles do not take damage, for Bluefor's deployment and it works fine, but I'm trying to find a way for only that specific side to be affected and how I can add another safe zone in for Opfor. I put it in my init.sqf file. Please help, I'm new to this. Thanks! 0 = [] spawn { while{true} do { { if(_x distance (getMarkerPos "bluefor_safe_zone") < 200) then {_x allowDamage false} else {_x allowDamage true}; } forEach allUnits + vehicles; sleep 1; }; }; Share this post Link to post Share on other sites
pokertour 30 Posted July 4, 2017 hi, Did you try something like this ? 0 = [] spawn { while{true} do { { if ((_x distance (getMarkerPos "bluefor_safe_zone") < 200) && (side _x == west)) then {_x allowDamage false} else {_x allowDamage true}; if ((_x distance (getMarkerPos "opfor_safe_zone") < 200) && (side _x == east)) then {_x allowDamage false} else {_x allowDamage true}; } forEach allUnits + vehicles; sleep 1; }; }; Share this post Link to post Share on other sites
Cryonic. 2 Posted July 4, 2017 Something similar, but I think I did it wrong. I'll try this now. Thanks! Share this post Link to post Share on other sites
Cryonic. 2 Posted July 4, 2017 That script didn't work well. Only my player was invincible as opfor. All vehicles still took damage. Share this post Link to post Share on other sites
killzone_kid 1332 Posted July 4, 2017 Some guy has same problem as you here you should team up and help each other 4 Share this post Link to post Share on other sites
Cryonic. 2 Posted July 4, 2017 Yes, because that is me. Share this post Link to post Share on other sites
MKD3 27 Posted July 4, 2017 Probably cos empty vehicles dont have a side? Look into it. Share this post Link to post Share on other sites
sarogahtyp 1108 Posted July 4, 2017 two topics fro the same op and for the same problem? Are u serious? Share this post Link to post Share on other sites
Tankbuster 1747 Posted July 4, 2017 I'd suggest using distance2d instead of distance. Share this post Link to post Share on other sites
pierremgi 4905 Posted July 4, 2017 That can't work anyway, for a logical reason: if ((_x distance (getMarkerPos "bluefor_safe_zone") < 200) && (side _x == west)) then {_x allowDamage false} else {_x allowDamage true}; if ((_x distance (getMarkerPos "opfor_safe_zone") < 200) && (side _x == east)) then {_x allowDamage false} else {_x allowDamage true}; two "if then else" ruins your code. Place/edit 2 repeatable markers with act/deact or try something like: 0 = [] spawn { while{true} do { { Call { if ((_x distance (getMarkerPos "bluefor_safe_zone") < 200) && (side _x == west)) exitWith {_x allowDamage false}; if ((_x distance (getMarkerPos "opfor_safe_zone") < 200) && (side _x == east)) exitWith {_x allowDamage false}; _x allowDamage true; }; } forEach (allUnits + (vehicles select {!(_x isKindOf "weaponHolderSimulated")})); sleep 1; }; } Share this post Link to post Share on other sites
Grumpy Old Man 3546 Posted July 4, 2017 2 hours ago, pierremgi said: That can't work anyway, for a logical reason: if ((_x distance (getMarkerPos "bluefor_safe_zone") < 200) && (side _x == west)) then {_x allowDamage false} else {_x allowDamage true}; if ((_x distance (getMarkerPos "opfor_safe_zone") < 200) && (side _x == east)) then {_x allowDamage false} else {_x allowDamage true}; two "if then else" ruins your code. Place/edit 2 repeatable markers with act/deact or try something like: 0 = [] spawn { while{true} do { { Call { if ((_x distance (getMarkerPos "bluefor_safe_zone") < 200) && (side _x == west)) exitWith {_x allowDamage false}; if ((_x distance (getMarkerPos "opfor_safe_zone") < 200) && (side _x == east)) exitWith {_x allowDamage false}; _x allowDamage true; }; } forEach (allUnits + (vehicles select {!(_x isKindOf "weaponHolderSimulated")})); sleep 1; }; } Any reason for the "call" inside the forEach statement? Cheers Share this post Link to post Share on other sites
Cryonic. 2 Posted July 4, 2017 I've been given a new script but it only protects opfor's side. //Untested script. 0 = [] spawn { //[[Marker Name, Side], [Marker Name, Side], etc...] _safeZones = [["blufor_safe_zone", west], ["opfor_safe_zone", east]]; while {true} do { { //stores the current marker name _markerName = _x select 0; //stores the current marker side _markerSide = _x select 1; { //see if unit/vehicle position is in the area of the marker if((position _x) inArea _markerName) then { //comparing the unit/vehicle side to the current marker side. will also protects empty vehicles if((side _x) == _markerSide || (side _x) == civilian) then { //if unit side belongs to zone side _x allowDamage false; }else{ //if unit side does not belong to zone side _x allowDamage true; } }else{ //if unit isn't in zone _x allowDamage true; } }forEach (allUnits + vehicles); }forEach _safeZones; sleep 1.0; }; }; Anyone know why this would be? Share this post Link to post Share on other sites
Tankbuster 1747 Posted July 4, 2017 inareaarray and inArea Of interest? Share this post Link to post Share on other sites
Cryonic. 2 Posted July 4, 2017 3 minutes ago, Tankbuster said: inareaarray and inArea Of interest? I don't know. This was given to me. I know very little about scripting. Share this post Link to post Share on other sites
Tankbuster 1747 Posted July 4, 2017 Oh, I see you used that command. I'm pretty sure they are the way forward. Also, what does the ProtectionZone_F do? https://community.bistudio.com/wiki/File:ProtectionZone_F.jpg Share this post Link to post Share on other sites
Cryonic. 2 Posted July 4, 2017 3 minutes ago, Tankbuster said: Oh, I see you used that command. I'm pretty sure they are the way forward. Also, what does the ProtectionZone_F do? https://community.bistudio.com/wiki/File:ProtectionZone_F.jpg It would work but it is very minimal. You cant change the shape, size, or which side it protects, nor does it protect vehicles. Share this post Link to post Share on other sites
Tankbuster 1747 Posted July 4, 2017 Ah OK. I do remember the grumpy German mission maker using it in A2 a while back. Share this post Link to post Share on other sites
pierremgi 4905 Posted July 5, 2017 6 hours ago, Grumpy Old Man said: Any reason for the "call" inside the forEach statement? Cheers Yes: Call { if ... exitWith >> bail out the call if most common occurrence is met if ... exitWith >> bail out if a less met occurrence (2nd most wanted) ..... general code (by defaut) if no condition met }; // end call then exitWtih (s) scope. Faster, selective; Share this post Link to post Share on other sites
sarogahtyp 1108 Posted July 5, 2017 15 hours ago, Grumpy Old Man said: Any reason for the "call" inside the forEach statement? Cheers Thought as a fast switch alternative: https://community.bistudio.com/wiki/Code_Optimisation#Make_it_pretty but I doubt that it's really faster in this context. Share this post Link to post Share on other sites
pierremgi 4905 Posted July 5, 2017 2 hours ago, sarogahtyp said: Thought as a fast switch alternative: https://community.bistudio.com/wiki/Code_Optimisation#Make_it_pretty but I doubt that it's really faster in this context. Yes, faster (just try it with 200 units, even with distanceSqr) and selective: that's the solution to avoid multiplying checks with if then else lines: for a double condition: if blue in blue area, else will fire for: not blue or not in area. Share this post Link to post Share on other sites
sarogahtyp 1108 Posted July 5, 2017 5 minutes ago, pierremgi said: Yes, faster (just try it with 200 units, even with distanceSqr) and selective: that's the solution to avoid multiplying checks with if then else lines: for a double condition: if blue in blue area, else will fire for: not blue or not in area. 200 units in one (or maybe 2) safezones at the same time? ll not happen such often I guess Share this post Link to post Share on other sites
pierremgi 4905 Posted July 5, 2017 1 minute ago, sarogahtyp said: 200 units in one (or maybe 2) safezones at the same time? ll not happen such often I guess Sure. Good demonstration. Just keep your doubt. Share this post Link to post Share on other sites
sarogahtyp 1108 Posted July 5, 2017 4 minutes ago, pierremgi said: Sure. Good demonstration. Just keep your doubt. I do not doubt that it is very usefull generally. And I think it's mostly used too little. But my opinion in this context is that it's overpowered. but nobody has to do what I think. Share this post Link to post Share on other sites
Grumpy Old Man 3546 Posted July 5, 2017 1 hour ago, sarogahtyp said: I do not doubt that it is very usefull generally. And I think it's mostly used too little. But my opinion in this context is that it's overpowered. but nobody has to do what I think. If you ask me there's no such thing as overpowered in terms of script performance /CPU time needed. Well, let's test it then. In the VR map, placing myself, those 2 safezone markers and populating the map using this: _westgrp = creategroup west; _eastgrp = creategroup east; _worldcenter = getArray (configfile >> "CfgWorlds" >> worldName >> "centerPosition"); for "_i" from 1 to 100 do { _unit = _westgrp createUnit ["B_Soldier_F",getmarkerpos "bluefor_safe_zone",[],200,"NONE"]; dostop _unit; _unit disableAI "ALL"; _unit = _eastgrp createUnit ["O_Soldier_F",getmarkerpos "opfor_safe_zone",[],200,"NONE"]; dostop _unit; _unit disableAI "ALL"; }; for "_i" from 1 to 100 do { _unit = _westgrp createUnit ["B_Soldier_F",_worldcenter,[],(worldSize / 2) * 1.4142,"NONE"]; dostop _unit; _unit disableAI "ALL"; _unit = _eastgrp createUnit ["O_Soldier_F",_worldcenter,[],(worldSize / 2) * 1.4142,"NONE"]; dostop _unit; _unit disableAI "ALL"; }; {_x setbehaviour "CARELESS"} foreach allunits; Gives 100 units within range of each safezone and 200 more units spread out over the map. Also setting them careless to prevent accidents, heh. Now using this to check for safezone distance: { Call { if ((_x distance (getMarkerPos "bluefor_safe_zone") < 200) && (side _x == west)) exitWith {_x allowDamage false}; if ((_x distance (getMarkerPos "opfor_safe_zone") < 200) && (side _x == east)) exitWith {_x allowDamage false}; _x allowDamage true; }; } forEach (allUnits + (vehicles select {!(_x isKindOf "weaponHolderSimulated")})); Runs for 2.46798 ms on my machine in this example, average of 10000 iterations, which could be improved for sure. Even when ran only once every second trying to squeeze out any performance while maintaining functionality has priority in my opinion. Considering one frame at 60fps runs for around 16.67ms the runtime of 2.4ms is pretty long and close to the 3ms rule. Replacing == with isEqualTo: { Call { if ((_x distance (getMarkerPos "bluefor_safe_zone") < 200) && (side _x isEqualTo west)) exitWith {_x allowDamage false}; if ((_x distance (getMarkerPos "opfor_safe_zone") < 200) && (side _x isEqualTo east)) exitWith {_x allowDamage false}; _x allowDamage true; }; } forEach (allUnits + (vehicles select {!(_x isKindOf "weaponHolderSimulated")})); Runs for 2.33878 ms. 5.5% performance increase, not too shabby. Now lets add lazy evaluation: { Call { if ((_x distance (getMarkerPos "bluefor_safe_zone") < 200) && {(side _x isEqualTo west)}) exitWith {_x allowDamage false}; if ((_x distance (getMarkerPos "opfor_safe_zone") < 200) && {(side _x isEqualTo east)}) exitWith {_x allowDamage false}; _x allowDamage true; }; } forEach (allUnits + (vehicles select {!(_x isKindOf "weaponHolderSimulated")})); 2.079 ms. That's a 18.7% increase from the original example. Let's exchange the distance check with a distancesqr and use the squared distance of 200 (40000) to check for: { Call { if ((_x distancesqr (getMarkerPos "bluefor_safe_zone") < 40000) && {(side _x isEqualTo west)}) exitWith {_x allowDamage false}; if ((_x distancesqr (getMarkerPos "opfor_safe_zone") < 40000) && {(side _x isEqualTo east)}) exitWith {_x allowDamage false}; _x allowDamage true; }; } forEach (allUnits + (vehicles select {!(_x isKindOf "weaponHolderSimulated")})); 2.03252 ms - 21.4% increase from the original, definitely gonna take that! Now we tried quite some stuff, functionality remains intact, performance increase is pretty decent. But there's more, we don't have to check the marker position for every unit that's being iterated, instead we define it as a global variable and check this as a constant instead. Can improve performance a good bit, especially with a high unit count: westPos = getMarkerPos "bluefor_safe_zone"; eastPos = getMarkerPos "opfor_safe_zone"; { Call { if ((_x distancesqr westPos < 40000) && {(side _x isEqualTo west)}) exitWith {_x allowDamage false}; if ((_x distancesqr eastPos < 40000) && {(side _x isEqualTo east)}) exitWith {_x allowDamage false}; _x allowDamage true; }; } forEach (allUnits + (vehicles select {!(_x isKindOf "weaponHolderSimulated")})); Runs for 1.94553 ms - 26.8% faster than the original. Don't forget to update the respective global variables when the marker position changes! So much for this approach. There's probably folks out there who could make it run even faster. Maybe there's a way, heh. Cheers 2 Share this post Link to post Share on other sites
sarogahtyp 1108 Posted July 5, 2017 (edited) _westPos = getMarkerPos "bluefor_safe_zone"; _eastPos = getMarkerPos "opfor_safe_zone"; { [_westPos, _eastPos] call { if ((_x distancesqr _this select 0 < 40000) && {(side _x isEqualTo west)}) exitWith {_x allowDamage false}; if ((_x distancesqr _this select 1 < 40000) && {(side _x isEqualTo east)}) exitWith {_x allowDamage false}; _x allowDamage true; }; true } count (allUnits + (vehicles select {!(_x isKindOf "weaponHolderSimulated")})); what bout using count instead of forEach? and I don't like global things if not necessary ;-) Edited July 5, 2017 by sarogahtyp typo Share this post Link to post Share on other sites