Jump to content
johnnyboy

[Updated V1.1] JBOY Combat Up Down script

Recommended Posts

Version 1.1 Released:  Units stop popping up and down after they no longer know about enemies.

 

When placing units in static defensive positions (on roofs, behind walls, behind windows, etc.), I want the units to react more dynamically under fire, and duck down to cover, then pop up to return fire, then duck back down to cover again.  So I wrote this very simple script (its used in both my Arma 3 missions Property of Mabunga and Leper Island).  The script is called by a Fired Near event handler (so they react to fire).  Here's a short demonstration:

 

Note: Zenophon kindly incorporated this script in his Zenophon's Infantry Occupy House Script (his script is essential for your urban combat needs...very smart placement of units in/on buildings).

 

To execute this script, put the following line in the unit's init.  Note the second parameter tells the script what stances you want the script to toggle between.  Use ["Middle","Down"] for a guy in a crouch position behind a low wall.  He will alternate from crouch to prone.  Use ["Up","Down"] or ["Up","Middle"] for a guy behind taller cover that will shoot from standing position, then crouch or go prone to hide.

this addeventhandler ["FiredNear",{ [_this select 0, ["Middle","Down"]] execVM "JBOY\JBOY_UpDown.sqf";}];

Create a file called JBOY_UpDown.sqf in your mission directory, and put this simple code in it:

Quote

 

// *****************************************************
// ** JBOY_UpDown.sqf
// ** Version 1.1
// ** by JohnnyBoy
// ** AI will toggle between two stances with a delay between.  Good for defenders to duck behind walls or windows, then pop back up.
// **  Call:  null = [dude, ["Up","Middle"]] execVM "JBOY\JBOY_UpDown.sqf";
// ** To start with an eventhandler, put this in unit's init:
// this addeventhandler ["FiredNear",{ [_this select 0, ["Up","Middle"]] execVM "JBOY\JBOY_UpDown.sqf";}];
// this addeventhandler ["FiredNear",{ [_this select 0, ["Middle","Down"]] execVM "JBOY\JBOY_UpDown.sqf";}];
//
// *****************************************************
if (!isServer)  exitwith {};
diag_log ["JBOY_UpDown.sqf ",_this];
//  Parameters:
_dude = _this select 0;   
_stances = _this select 1;
_dudeOriginalStance = unitPos _dude;
_dude removeAllEventHandlers "FiredNear";
_done = false;
_iterations = 0;
while {alive _dude and !_done and _iterations < 12} do
{
    if ((unitpos _dude) == (_stances select 0)) then
    {
        _dude setUnitPos (_stances select 1);
    } else
    {
        _dude setUnitPos (_stances select 0);
    };
    sleep (1 + (random 5));
    if (isNull (_dude findNearestEnemy _dude)) then // If no known enemies then increment iterations so that guys stop popping up and down
    {
        //systemchat "no known enemies found";
        _iterations = _iterations + 1;
    };
};
if (alive _dude) then
{
    _dude setUnitPos _dudeOriginalStance;
    _dude addeventhandler ["FiredNear",{ [_this select 0, ["Middle","Down"]] execVM "JBOY\JBOY_UpDown.sqf";}];
};

 

Hope you find this useful.  Johnnyboy out.

 

Credits:

  • 4-325Ranger for reporting issue where guys bob up and down after no longer in danger.  Thanks dude!

  • Like 10
  • Thanks 2

Share this post


Link to post
Share on other sites

More awesomeness, thanks for sharing JB.  :).........Oh, and I dig the new signature.  ;)  

  • Like 1

Share this post


Link to post
Share on other sites

All of your scripts are for such cool interesting features-like the jumping fish, birds of prey, chatting enemy patrols etc.

 

This one though-is it possible to make this into an addon? So that ai will always do this with cover?

  • Like 2

Share this post


Link to post
Share on other sites

All of your scripts are for such cool interesting features-like the jumping fish, birds of prey, chatting enemy patrols etc.

 

This one though-is it possible to make this into an addon? So that ai will always do this with cover?

Thanks Ineptaphid!

 

Answer: Probably, but I don't do addons.  I have limited time, which I focus on where my interests are, so I haven't delved into how to make addons. 

 

But I give full permission for all my work to be used in any way (portions of code taken, or repackaged, turned into mods, etc.).  I just ask they credit me somewhere.

 

One could write a FOREACH ALLUNITS loop in the init to add this script to all AI units.  Problem is, I think you only want this for units in defensive positions behind objects, in windows, etc.  With current design, mission maker designates which units these are.  It would be difficult to determine which units are in defensive positions dynamically.  You wouldn't want a group walking across flat ground to be switching from Kneel to Standing constantly (the default AI of hitting the dirt and start flanking is better in that case).

  • Like 1

Share this post


Link to post
Share on other sites

I think a post with all the scripts - related to mabunga/JBOY - releases will be a great thread.

 

Think again... a script complete pack will be another good idea.

  • Like 1

Share this post


Link to post
Share on other sites

I think a post with all the scripts - related to mabunga/JBOY - releases will be a great thread.

 

Think again... a script complete pack will be another good idea.

Thanks dude.

 

Most of these are in my sig (but sig is limited to 10 links).  But all of the Mabunga related scripts are linked at bottom of first post for the Mabunga mission.  There's 13 of my scripts linked, plus links to 3 other awesome scripts I found useful by Zenophon, f2ksel, and Shuko.

Share this post


Link to post
Share on other sites

How about to make some script that enemy AI would search cover and run to it? I think it will be a nice script tho...

Share this post


Link to post
Share on other sites

How about to make some script that enemy AI would search cover and run to it? I think it will be a nice script tho...

Hi Hunter.  That's a good idea, but unrelated to the purpose of this Up/Down script.  If you are looking for an AI find cover script, then post a new topic with your request.

 

Maybe the VCOM AI mod is what you are looking for. It is supposed to be smarter at AI taking cover (among other things).

Share this post


Link to post
Share on other sites

Johnnyboy,

 

I know you put this out a while ago, but I've been having some fun out of it since I found it recently. I've been putting it on the AI and running attacks on their FOBs, OPs, bases etc.. I set up a FOB defense with Blufor, and put it on the Blufor units. Only problem, after the horde has been stopped, the units continue to pop up and down like they're at Catholic mass. Is there any way to have the script stop after there has been no shooting for x period of time, and then restart if shooting begins again with another attack wave? I can use scripts fairly well, but can't code for beans, so I figured it was worth asking. Thanks and keep 'em coming, love the Dog script too!

  • Like 1

Share this post


Link to post
Share on other sites

Johnnyboy,

 

I know you put this out a while ago, but I've been having some fun out of it since I found it recently. I've been putting it on the AI and running attacks on their FOBs, OPs, bases etc.. I set up a FOB defense with Blufor, and put it on the Blufor units. Only problem, after the horde has been stopped, the units continue to pop up and down like they're at Catholic mass. Is there any way to have the script stop after there has been no shooting for x period of time, and then restart if shooting begins again with another attack wave? I can use scripts fairly well, but can't code for beans, so I figured it was worth asking. Thanks and keep 'em coming, love the Dog script too!

Thanks for the report.  That is something that should be fixed.  My queue is long and time is short, so I can't promise anything soon though.

 

I think the fix would be to reset them  when they're nearTargets returns 0 (ie., they don't know of any near enemies) and X minutes transpire.  What should X be?

Share this post


Link to post
Share on other sites

Sounds arbitrary but, I'd say 1:30 to 2:00 would be about right from what I've observed. The enemy AI in vanilla mode (I usually use ASR, but not for this testing) can still fire somewhat sporadically when there are only a few left from one wave, but I notice they will usually start back up if any are left within that time. So anything about that long + should keep it from looking too strange :) . I get you're busy, but thanks for considering, I have an arma buddy who codes scripts, would you mind if I had him look at a solution?

Share this post


Link to post
Share on other sites

Sounds arbitrary but, I'd say 1:30 to 2:00 would be about right from what I've observed. The enemy AI in vanilla mode (I usually use ASR, but not for this testing) can still fire somewhat sporadically when there are only a few left from one wave, but I notice they will usually start back up if any are left within that time. So anything about that long + should keep it from looking too strange :) . I get you're busy, but thanks for considering, I have an arma buddy who codes scripts, would you mind if I had him look at a solution?

Yeah, no problem.  If he finds a solution I'll gladly update my script accordingly and credit him (and you for the suggestion). :)

  • Like 1

Share this post


Link to post
Share on other sites
On 11/18/2016 at 11:29 AM, 4-325Ranger said:

Johnnyboy,

 

I know you put this out a while ago, but I've been having some fun out of it since I found it recently. I've been putting it on the AI and running attacks on their FOBs, OPs, bases etc.. I set up a FOB defense with Blufor, and put it on the Blufor units. Only problem, after the horde has been stopped, the units continue to pop up and down like they're at Catholic mass. Is there any way to have the script stop after there has been no shooting for x period of time, and then restart if shooting begins again with another attack wave? I can use scripts fairly well, but can't code for beans, so I figured it was worth asking. Thanks and keep 'em coming, love the Dog script too!

Version 1.1 of this script is now released.  It fixes the problem reported by 4-325Ranger where "units continue to pop up and down like they're at Catholic mass" after they are no longer in danger.  LOL.

 

Original post is updated with new script code.

 

Enjoy!

  • Like 1

Share this post


Link to post
Share on other sites
24 minutes ago, johnnyboy said:

Version 1.1 of this script is now released.  It fixes the problem reported by 4-325Ranger where "units continue to pop up and down like they're at Catholic mass" after they are no longer in danger.  LOL.

 

Original post is updated with new script code.

 

Enjoy!

LOL, thanks Johnnyboy, my coding friend had passed on this so I'm really glad you took it on. I'm going to test it out in the original "OP defense" mission I used. I'll report back...

  • Like 1

Share this post


Link to post
Share on other sites
15 hours ago, 4-325Ranger said:

LOL, thanks Johnnyboy, my coding friend had passed on this so I'm really glad you took it on. I'm going to test it out in the original "OP defense" mission I used. I'll report back...

Thanks man.  Its easy to test, as friendly (or non-friendly) fire nearby will start them ducking, but if there is no near enemy they should stop within a minute or so (delay will be between about 30 to 90 seconds per guy...so they don't all magically stop at the same time).  They will re-start ducking if fired near again.

Share this post


Link to post
Share on other sites

Test Results:

 

My defenders are rhs_faction_usarmy_d

 

They are all positioned on the H-barrier defense wall (Land_HBarrierWall6_F).

 

They each have the following code:
this allowDamage false; // only a couple have this just spread out so the whole line isn't wiped out ;)
doStop this; // stand in place, rotate but do not leave your post soldier!
this disableAI "TARGET"; // please stay in one place and don't go chasing anyone after contact initiated, thank you...
this linkItem "ANPVS15_Camo_V2"; // oh lookie I can see at night wow!
this addeventhandler ["FiredNear",{ [_this select 0, ["Up","Middle"]] execVM "JBOY\JBOY_UpDown.sqf";}]; // Ah hey I'll actually take cover!!!! Nice!
this addEventHandler  [  "Fired",  { _mag = _this select 5;  _unit = _this select 0;  if ({_x isEqualTo _mag} count magazines _unit < 2) then  { _unit addMagazines [_mag, 3];  };  } ]; // I have unlimited ammo! but I will change magazines and belts as appropriate; this is after all a static OP on an insurgency, like you're going to resupply your friendly AI Ha!

 

So I needed to add some controls just in case positioning on the H-barrier, or any other soldier init code may interfere.

 

I added an RHS rifleman control on flat ground with just the JBOY code:
doStop this; this addeventhandler ["FiredNear",{ [_this select 0, ["Up","Middle"]] execVM "JBOY\JBOY_UpDown.sqf";}];

 

I added a Vanilla soldier control on flat ground (has full code of my mission defenders on wall):

 

Finally, I added a Vanilla soldier control standing with my defenders on (Land_HBarrierWall6_F) wall with just JBOY code:
this addeventhandler ["FiredNear",{ [_this select 0, ["Up","Middle"]] execVM "JBOY\JBOY_UpDown.sqf";}];

 

Findings:

 

1st pass, up/middle repeat, stopped in less than 2 minutes after last shot fired.
2nd pass (same testing iteration), up to middle to down (prone), then proceed to toggle middle/down for duration; after appropriate time passed from final shot they recovered to the up position.
3rd and subsequent pass, same as #2; so having an issue with the exception of the first iteration - up/middle becomes up/ ...middle/down...middle/down..../ up.

 

I looked at your code and made the following change:

 

I took this line (#40): _dude addeventhandler ["FiredNear",{ [_this select 0, ["Middle","Down"]] execVM "JBOY\JBOY_UpDown.sqf";}];
and changed it to this: _dude addeventhandler ["FiredNear",{ [_this select 0, ["Up","Middle"]] execVM "JBOY\JBOY_UpDown.sqf";}];

 

I don't know diddly about coding, but this change fixed the issue. I'm not sure what would happen if you wanted a combination of up/middle and middle/down, but for my purposes, I only need up/middle and this fixes it.
Thanks!

  • Like 2

Share this post


Link to post
Share on other sites
Spoiler

_debugText = "";
allUnits select {_x != player} apply {_x addeventhandler ["FiredNear",{ 
params ["_unit", "_firer", "_distance", "_weapon", "_muzzle", "_mode", "_ammo", "_gunner"];

_stances = ["Up","Middle"];
_unitOriStan = unitPos _unit;
_debugText = "";
if ((_unit getVariable ["FIREDLOCKOUT",[false,-1]] select 0)) exitWith {};
hint "nonexit";
_unit setVariable ["FIREDLOCKOUT",[true, time + random [1, 10, 3]],true]; 
[_stances, _unit, _unitOriStan, _distance,_debugText ] spawn 
	{

		params ["_stances","_unit", "_unitOriStan", "_distance", "_debugText"];
		
		while {(_unit getVariable ["FIREDLOCKOUT",[true,-1]] select 0) && alive _unit} do
		{
			
			_debugText = _debugText + format ["%1 in stance for %2 secs\n", _unit,(_unit getVariable ["FIREDLOCKOUT",[true,-1]] select 1) - time];
			waitUntil {time > (_unit getVariable ["FIREDLOCKOUT",[true,(time + 1)]]) select 1};
				
				if ((unitpos _unit) == (_stances select 0)) then
				{
					_unit setUnitPos (_stances select 1);
				} else
				{
					_unit setUnitPos (_stances select 0);
				};


				if (isNull (_unit findNearestEnemy _unit)) exitwith {hint "exit"; _unit setVariable ["FIREDLOCKOUT",[false, -1],true];};
				if !(alive _unit) exitWith {_unit setVariable ["FIREDLOCKOUT",[false, -1],true];};
				_unit setVariable ["FIREDLOCKOUT",[true,time + random [1, 10, 3]],true];
				hintsilent str _debugText;
			
		};
		
		_unit setUnitPos _unitOriStan;
		
	};
	
}];};

 

 

used _unit variables to store time between stance changes and firednear EH timeouts to avoid adding and removing EHs..

 

 

this one finds objects close to unit and changes stance

Spoiler

params [["_side", east,[east]], ["_staticMG", false], ["_debug", false]];
missionNamespace setVariable ["staticmg", _staticMG];
missionNamespace setVariable ["debug", _debug];
allUnits select {side _x == _side && _x != player} apply {_x addeventhandler ["FiredNear",{ 
params ["_unit", "_firer", "_distance", "_weapon", "_muzzle", "_mode", "_ammo", "_gunner"];
_stances = ["Up","Middle"];
_staticMG = missionNamespace getVariable ["staticmg", false];
_debug = missionNamespace getVariable ["debug", false];
if (_unit getVariable ["FIREDLOCKOUT", false]) exitWith {};
_unit setVariable ["FIREDLOCKOUT", true, false];
_unit setVariable ["COVERTIMEOUT", (time + 60), false]; 

[_stances, _unit, _staticMG, _debug] spawn 
	{

		params ["_stances","_unit", "_staticMG", "_debug"];
		_Nearobject = nearestObjects [_unit, ["strategic", "house", "Rocks_base_F"], 4];
		if (_staticMG && {_unit == (units _unit select 0)}) then {[_unit,50] execvm "staticgun.sqf";};
		if (count _Nearobject == 0) exitWith {sleep 5; _unit setVariable ["FIREDLOCKOUT", false, false];}; 
		if !([getPosATL  _unit, getDir _unit, 30, getPosATL (_Nearobject select 0)] call BIS_fnc_inAngleSector) exitwith {sleep 5; _unit setVariable ["FIREDLOCKOUT", false, false];}; 
		while {_unit getVariable ["FIREDLOCKOUT", true]} do
		{	
			_unit disableAI "PATH";
			_unit setVariable ["COVERTIME", floor(random[1, 4, 20]), false];
		
			waitUntil {sleep(_unit getVariable ["COVERTIME", 4]); true;}; 
			_target = assignedTarget _unit;
			switch (unitPos _unit) do { 
				case "Auto" : {_unit setUnitPos (_stances select 0);};
				case "Up" : {_unit setUnitPos (_stances select 1); if (floor(random (5))> 3) then {_unit doSuppressiveFire _target;};};
				case "Middle" : {_unit setUnitPos (_stances select 0);};  
				case "Down" : {_unit setUnitPos (_stances select 1);};};
				if (_debug) then {diag_log format ["%1 in %4 stance for %2 secs. Nearobject %3", _unit,(_unit getVariable ["COVERTIME", -1]), _Nearobject, unitPos _unit];};
				if !(alive _unit) exitwith {_unit removeEventHandler ["FiredNear", 0]; if (_debug) then {diag_log format ["removing EventHandler from killed %1", _unit];};};
				if (isNull (_unit findNearestEnemy _unit)) then {_unit setVariable ["FIREDLOCKOUT",false, false]; if (_debug) then {diag_log format ["%1 no enemy sighted", _unit];};};
				if (time > (_unit getVariable ["COVERTIMEOUT", -1]) && {!(isNull _target)}) then 
				{
					if !((_unit getRelDir _target) < 30 or (_unit getRelDir _target) > 315) then {_unit setVariable ["FIREDLOCKOUT", false, false]; if (_debug) then {diag_log format ["%1 turned %2 from target enabling 'PATH'", _unit, _unit getRelDir _target];};};
				};
		};
		
	_unit setUnitPos "AUTO";
	_unit enableAI "PATH";
	};
	
}];};

staticgun.sqf


params ["_unit","_searchDist"];
if (isNil "_searchDist") then {_searchDist = 100};


private _weaps = nearestObjects [(getPos _unit),["StaticWeapon", "StaticATWeapon","StaticCannon"],_searchDist];

if (_weaps isEqualType []) exitWith
{
private _units = units _unit;
private _manned = [];
private _time = time + 90;
  {
    _gun = _x;
	if !([_gun] call compile preprocessFileLineNumbers "staticempty.sqf") exitWith {hint "exit";};
    _sortedEntites = _units apply {[_gun distance2D _x,_x]};
    _sortedEntites sort True;
    if (count _sortedEntites >0) then {
      _c = _sortedEntites select 0 select 1;
	  _manned pushback [_c,_gun];
      _units deleteAt 0;
      _c assignasturret [_gun, [0] ];
	 [_c] allowGetIn true;
	 [_c] orderGetIn true;
	 _c forcespeed 100;
	 _c setDestination [getPosATL _gun, "LEADER PLANNED", true];
	 waitUntil {if ((_c distance _gun) < 6 or {_time < time}) exitwith {true};};
	 _c moveInTurret [_gun,[0]];
    };
  } forEach _weaps;
 };

staticempty.sqf

 


params ["_staticWp"];

_crew = fullCrew [_staticWp, "gunner", true]; 
if (isNull ((_crew#0)#0)) exitwith {true}; 
if !(alive ((_crew#0)#0)) exitwith {true}; 
false;

 

  • Like 1

Share this post


Link to post
Share on other sites

I keep getting this error trying this script:

 

_dude = _this select 0;   
_stances = _this select 1;
_dudeOr>
Error position: <  
_stances = _this select 1;
_dudeOr>
 Error Invalid number in expression
File C:\Users\sixte\Documents\Arma 3 - Other Profiles\Robert\mpmissions\[HAL]rodopoli_01.Altis\JBOY\JBOY_UpDown.sqf..., line 15
Error in expression <.sqf ",_this];

Share this post


Link to post
Share on other sites

At the end of the first line you posted is a weird character.

Check this and check if it is an invisible character. That happens "sometimes" when copying scripts from forums.

  • Like 2

Share this post


Link to post
Share on other sites

Ya I just gave it a try and it ran fine (I'm going to use it, thanks JB)

That character as sarogahtyp pointed out is out of place.

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

×