Jump to content
Sign in to follow this  
-Coulum-

Ai suppression script help

Recommended Posts

From 20120209 - 20120618 Outdated

Hello,

So I found this neat script on armaholic and basically what it does is make the player's vision blur and darken when rounds pass nearby, kind of like in VBS2. Now I am not very knowledgeable in scripting but I managed to make it so not only does the screen blur but the player's aim jerks a little bit from incoming rounds. I put it altogether and ran it as an addon and it worked fine, making it a bit harder for the player in a firefight when suppressed. Heres the scripts.

_unit = _this select 0;

player setVariable ["apuStress",0];

_apuVBS2style = _unit addEventHandler ["Fired",{_this execVM "\Wizz\Scripts\wizz.sqf"}];

I'm guessing this is what triggers the main script by detecting whenever a shot is fired and when one is, firing up the "wizz.sqf" below. But does anybody know what the apuVBS2style is? I searched it and found nothing.

_unit = _this select 0;

_ammo = _this select 4;

_radius = 15;

if (playerSide == side _unit) exitWith {};

if (_unit == player) exitWith {};

_bullet= nearestObject [_unit, _ammo];

while {(speed _bullet) > 0.1} do {

_dist = _bullet distance player;

if (_dist < _radius) then {

_freq = 0.5-(_dist/100);

_rand = 2;

if (_rand < 5) then {

_freq = 0.4-(_dist/100);

addCamShake [1, 3, 5];

_ppColor = ppEffectCreate ["ColorCorrections", 1001];

_ppColor ppEffectEnable true;

_ppColor ppEffectAdjust [0, -1, 0, [0,0,0,0], [0,0,0,0], [0,0,0,0]];

_ppColor ppEffectCommit 1;

sleep _freq;

_ppColor ppEffectEnable false;

ppEffectDestroy _ppColor;

};

_ppBlur = ppEffectCreate ["dynamicBlur", 1001];

_ppBlur ppEffectEnable true;

_ppBlur ppEffectAdjust [1.5];

_ppBlur ppEffectCommit 1;

sleep _freq;

_ppBlur ppEffectEnable false;

ppEffectDestroy _ppBlur;

};

sleep 0.05;

};

This is the script that detects whether the round is close and triggers the blurred screen and shaky aim(camera shake).

Now what I would like help on, is how to extend this to the ai as well. I was thinking that when a round comes close to an ai his accuracy skill will be temporarily decreased and he will have setunitpos "down" applied to him temporarily to make him go prone for a while, instead of the camera shake and blurryiness the player experiences. The problem is I have no idea how to detect when rounds pass by the ai. Is it possibly to do what I am suggesting and if so does anybody here have some advice on how I would go about it. Keep in mind I really don't know much about scripting.Thanks.

From 20120618 Outdated

This thread has really developed alot from when it started. A script that makes the ai react to suppressive fire has been created. The script basically makes it so if a bullet snaps by an ai soldier he takes a knee. If several shots snap by rapidly (5 in a 5 second period right now) the ai will go prone. Here's what it looks like. Note that pistol and submachinegun rounds, whether silenced or not will not cause suppression effects.

There are two versions of the script. AIsuppress1.sqf prevents a unit from being suppressed by any friendly fire. AIsuppress2.sqf prevents a unit from being suppressed by any fire from less than 20m away.

To use either scripts, simply put the following into the init.sqf of a mission or into the init of a unit. If you want to use aisuppress2, just replace the 1 with a 2 in the following code.

nul = [] execvm "aisuppress1.sqf"

Then place aisuppress1.sqf or aisuppress2.sqf respectively in the mission folder. When you run the mission you should see "ai suppress active" in the top right of the screen after a few seconds have passed. If anyone needs further help with the setup just ask, I know I'm not the greatest at explaining things.

CBA is required to use this script!

For those interested, here are the scripts within each of those files.

aisuppress1.sqf

// ALL INFANTRY UNITS ON MAP WILL DROP IF BULLETS FROM ENEMIES AWAY PASS WITHIN 10m
// BULLETS FROM OWN SIDE ARE IGNORED
// BULLETS FROM SMG AND PISTOLS ARE IGNORED
// Original code idea by -Coulum-
// TPW 20120619 

//Start hint
0 = [] spawn {sleep 3;hintsilent "AI suppress active"; sleep 3; hintsilent ""};

private ["_supnextime","_unit","_bc","_shots","_side"]; 

//Pistol and SMG  ammo to ignore
tpw_mags =["30rnd_9x19_MP5",
"30rnd_9x19_MP5SD",
"15Rnd_9x19_M9",
"15Rnd_9x19_M9SD",
"7Rnd_45ACP_1911",
"8Rnd_9x18_Makarov",
"8Rnd_9x18_MakarovSD",
"64Rnd_9x19_Bizon",
"64Rnd_9x19_SD_Bizon",
"13Rnd_9mm_SLP",
"17Rnd_9x19_glock17",
"6Rnd_45ACP",
"30Rnd_9x19_UZI",
"30Rnd_9x19_UZI_SD"];

//Main function
tpw_sup =  
{ 
   {
_unit = _x; 
if (vehicle _x == _x) then 
	{
	_SupNextTime = _unit getVariable ["SupNextTime", -1]; 
	if (_SupNextTime == -1) then 
		{
		_unit setVariable ["SupNextTime", diag_tickTime];
		_unit setvariable ["SIDE", (side _unit)];  
		_unit addeventhandler ["Fired",{tpw_fired = (_this select 0) getvariable "SIDE";tpw_mag = _this select 5;tpw_bullet = _this select 6}]; };
	if (diag_tickTime >= _SupNextTime) then {_unit setVariable ["Shots", 0]}; 
	_bc = 0;
	if !(isnull tpw_bullet) then 
		{
		_bc = count ((getposatl _unit) nearobjects ["Bulletbase",10])
		};
	if (_bc > 0) then 
		{
		_side = _unit getvariable "SIDE";
		if (_side != tpw_fired) then 
			{
			if !(tpw_mag in tpw_mags) then {
				_unit setVariable ["SupNextTime", diag_tickTime + 3 + random 5];
				_shots = _unit getVariable "Shots";
				_unit setVariable ["Shots", _shots + _bc];
				}
			}
		};
	_shots = _unit getVariable "Shots";
	if (_shots == 0) then {_unit setunitpos "auto"};
	if (_shots > 0) then {_unit setunitpos "middle"};
	if (_shots > 5) then {_unit setunitpos "down"};
	};
} forEach allunits;
}; 

//Call function using per frame eventhandler so computer doesn't explode
[tpw_sup,0] call cba_fnc_addPerFrameHandler; 

aisuppress2.sqf

// ALL INFANTRY UNITS ON MAP WILL DROP IF ANY BULLETS PASS WITHIN 10m
// BULLETS FIRED FROM LESS THAN 20m ARE IGNORED 
// BULLETS FROM SMG AND PISTOLS ARE IGNORED
// Original code idea by -Coulum-
// TPW 20120619 

//Start hint
0 = [] spawn {sleep 3;hintsilent "AI suppress active"; sleep 3; hintsilent ""};

private ["_supnextime","_unit","_bc","_shots","_dist"]; 

//Pistol and SMG  ammo to ignore
tpw_mags =["30rnd_9x19_MP5",
"30rnd_9x19_MP5SD",
"15Rnd_9x19_M9",
"15Rnd_9x19_M9SD",
"7Rnd_45ACP_1911",
"8Rnd_9x18_Makarov",
"8Rnd_9x18_MakarovSD",
"64Rnd_9x19_Bizon",
"64Rnd_9x19_SD_Bizon",
"13Rnd_9mm_SLP",
"17Rnd_9x19_glock17",
"6Rnd_45ACP",
"30Rnd_9x19_UZI",
"30Rnd_9x19_UZI_SD"];

//Main function
tpw_sup =  
{ 
   {
_unit = _x; 
	if (vehicle _x == _x) then 
	{
	_SupNextTime = _unit getVariable ["SupNextTime", -1]; 
	if (_SupNextTime == -1) then 
		{
		_unit setVariable ["SupNextTime", diag_tickTime];
		_unit addeventhandler ["Fired",{tpw_fired = _this select 0;tpw_mag = _this select 5; tpw_bullet = _this select 6}];
		};
	if (diag_tickTime >= _SupNextTime) then {_unit setVariable ["Shots", 0]}; 
	_bc = 0;
	if !(isnull tpw_bullet) then 
		{
		_bc = count ((getposatl _unit) nearobjects ["Bulletbase",10])
		};
	if (_bc > 0) then 
		{
		_dist = tpw_fired distance _unit;
		if (_dist > 25) then 
			{
			if !(tpw_mag in tpw_mags) then {
				_unit setVariable ["SupNextTime", diag_tickTime + 3 + random 5];
				_shots = _unit getVariable "Shots";
				_unit setVariable ["Shots", _shots + _bc];
				}
			}
		};
	_shots = _unit getVariable "Shots";
	if (_shots == 0) then {_unit setunitpos "auto"};
	if (_shots > 0) then {_unit setunitpos "middle"};
	if (_shots > 5) then {_unit setunitpos "down"};
	}
} forEach allunits;
}; 

//Call function using per frame eventhandler so computer doesn't explode
[tpw_sup,0] call cba_fnc_addPerFrameHandler;  

And a huge thanks to tpw who basically wrote the whole script and Orcinus for his great ideas.

This definitely isn't a finished product, so we are still very open to feedback, suggestions and ideas. I am also interested to know how the script holds up with large numbers of ai in firefights.

From 20120619 Outdated

The scripts have been updated and there is now a mod version of the script thanks to tpw:

Based on side

Based on distance

Remember, CBA is required.

From 20120618Updated

There are three versions of the script available:

Basic (stance modifier)

/* 
ALL INFANTRY UNITS ON MAP WILL REACT IF ANY BULLETS PASS WITHIN 10m    
BULLETS FIRED FROM LESS THAN 25m ARE IGNORED     

Authors: TPW & -Coulum- 
Last changed: 20120622     
*/ 

//Allow time for ASR AI skills to propagate 
sleep 30; 

//Start hint    
0 = [] spawn {sleep 3;hintsilent "AI suppress active"; sleep 3; hintsilent ""};    

private ["_stanceregain","_unit","_bc","_shots","_ball"];     

//Main function   
tpw_ai_sup =     
{    
   {   
   if (alive _x) then    
       { 
       _unit = _x;      
       _stanceregain = _unit getvariable ["stanceregain", -1];  

       if (_stanceregain == -1) then    
           {      
           _unit setvariable ["stanceregain", diag_ticktime];  
           _unit addeventhandler ["fired",{tpw_fired = _this select 0;tpw_bullet = _this select 6}];  
           };  

       if ( diag_ticktime >= _stanceregain) then    
           {  
           _unit setvariable ["supshots", 0];   
           _unit setunitpos "auto";  
           };  

       if !(isnull tpw_bullet) then    
           {   
           _bc = count ((getposatl _unit) nearobjects ["bulletbase",10]);   
           if (_bc > 0) then    
               {  
               if ((tpw_fired distance _unit) > 25) then    
                   {   
                      _unit setvariable ["stanceregain", diag_ticktime + 10];   
                   _shots = _unit getvariable "supshots";   
                   _unit setvariable ["supshots", _shots + _bc];   
                   _shots = _unit getvariable "supshots";  
                   _unit setunitpos "middle"; 
                   if (_shots > 5) then   
                       {  
                       _unit setunitpos "down";  
                       };   
                   };   
               };   
           };   
       };    
   } foreach allunits;   
};   

//Call function using per frame eventhandler so computer doesn't explode   
[tpw_ai_sup,0] call cba_fnc_addPerFrameHandler; 

-Units react to bullets passing within 10m

-Affects all units, in vehicles or not

-Units react identically to any kind of bullet fired from more than 25m away

-Units react to identically bullets from any side

-1-5 bullets -->kneel/crouch

->5 bullets --> drop/crawl

-Units regain previous stance after 10 seconds without nearby bullets

Light (stance modifier)

/* 
ALL INFANTRY UNITS ON MAP WILL REACT IF ANY BULLETS PASS WITHIN 10m    
BULLETS FIRED FROM LESS THAN 25m ARE IGNORED     
BULLETS FROM SMG AND PISTOLS ARE IGNORED    
BULLETS FROM OWN SIDE CAUSE UNIT TO KNEEL/CROUCH    
BULLETS FROM ENEMY SIDE CAUSE UNIT TO KNEEL/DROP   

Authors: TPW & -Coulum- 
Last changed: 20120622     
*/ 

//Allow time for ASR AI skills to propagate 
sleep 30; 

//Start hint    
0 = [] spawn {sleep 3;hintsilent "AI suppress active"; sleep 3; hintsilent ""};    

private ["_stanceregain","_unit","_bc","_shots","_ball"];     

//Pistol and SMG  ammo to ignore    
tpw_mags =["30rnd_9x19_MP5",    
"30rnd_9x19_MP5SD",    
"15Rnd_9x19_M9",    
"15Rnd_9x19_M9SD",    
"7Rnd_45ACP_1911",    
"7Rnd_45ACP_1911",   
"8Rnd_9x18_Makarov",   
"8Rnd_9x18_MakarovSD",   
"64Rnd_9x19_Bizon",   
"64Rnd_9x19_SD_Bizon",   
"13Rnd_9mm_SLP",   
"17Rnd_9x19_glock17",   
"6Rnd_45ACP",   
"30Rnd_9x19_UZI",   
"30Rnd_9x19_UZI_SD"];   

//Main function   
tpw_ai_sup =     
{    
   {   
   if (alive _x) then    
       { 
       _unit = _x;      
       _stanceregain = _unit getvariable ["stanceregain", -1];  

       if (_stanceregain == -1) then    
            {      
           _unit setvariable ["stanceregain", diag_ticktime];  
           _unit addeventhandler ["fired",{tpw_fired = _this select 0;tpw_mag = _this select 5; tpw_bullet = _this select 6}];   
           };  

       if ( diag_ticktime >= _stanceregain) then    
           {  
           _unit setvariable ["supshots", 0];   
           _unit setunitpos "auto";  
           };  

       if !(isnull tpw_bullet) then    
           {   
           _bc = count ((getposatl _unit) nearobjects ["bulletbase",10]);   
           if (_bc > 0) then    
               {  
               if ((tpw_fired distance _unit) > 25) then    
                   {   
                   if !(tpw_mag in tpw_mags) then    
                       {  
                       _unit setvariable ["stanceregain", diag_ticktime + 10];   
                       _shots = _unit getvariable "supshots";   
                       _unit setvariable ["supshots", _shots + _bc];   
                       _shots = _unit getvariable "supshots";  
                       _unit setunitpos "middle";                                      
                       if ((side tpw_fired != side _unit) && (vehicle _unit == _unit)) then    
                           { 
                           if (_shots > 5) then   
                               {  
                               _unit setunitpos "down";  
                               };   
                           };    
                       };   
                   };   
               };   
           };   
       };    
   } foreach allunits;   
};   

//Call function using per frame eventhandler so computer doesn't explode   
[tpw_ai_sup,0] call cba_fnc_addPerFrameHandler;  

-Units react to bullets passing within 10m

-Only units not in vehicles are affected

-Bullets fired from less than 25m away are ignored

-Bullets from small calibre pistols and SMG are ignored

-Units react differently according to the side of the shooter

-1-5 bullets --> kneel/crouch

->5 bullets --> drop/crawl only if enemy shooter fired bullets

-Units regain previous stance after 10 seconds without nearby bullets

Full (stance and skill modifier)

/* 
ALL INFANTRY UNITS ON MAP WILL REACT IF ANY BULLETS PASS WITHIN 10m    
BULLETS FIRED FROM LESS THAN 25m ARE IGNORED     
BULLETS FROM SMG AND PISTOLS ARE IGNORED    
BULLETS FROM OWN SIDE CAUSE UNIT TO KNEEL/CROUCH    
BULLETS FROM ENEMY SIDE CAUSE UNIT TO KNEEL/DROP, AND A TEMPORARY DECREASE IN SKILL   
SKILLS WILL GRADUALLY RETURN ONCE UNIT IS NOT SUPPRESSED 

Authors: TPW & -Coulum- 
Last changed: 20120622     
*/ 

//Allow time for ASR AI skills to propagate 
sleep 30; 

//Start hint    
0 = [] spawn {sleep 3;hintsilent "AI suppress active"; sleep 3; hintsilent ""};    

private ["_stanceregain","_skillregain","_unit","_bc","_shots","_originalaccuracy","_originalshake","_originalcourage","_general","_ball"];     

//Pistol and SMG  ammo to ignore    
tpw_mags =["30rnd_9x19_MP5",    
"30rnd_9x19_MP5SD",    
"15Rnd_9x19_M9",    
"15Rnd_9x19_M9SD",    
"7Rnd_45ACP_1911",    
"7Rnd_45ACP_1911",   
"8Rnd_9x18_Makarov",   
"8Rnd_9x18_MakarovSD",   
"64Rnd_9x19_Bizon",   
"64Rnd_9x19_SD_Bizon",   
"13Rnd_9mm_SLP",   
"17Rnd_9x19_glock17",   
"6Rnd_45ACP",   
"30Rnd_9x19_UZI",   
"30Rnd_9x19_UZI_SD"];   

//Main function   
tpw_ai_sup =     
{    
   {   
   //hint format["accuracy = %1, shake = %2, courage = %3, general = %4",(ai skill "aimingaccuracy"),(ai skill "aimingshake"),(ai skill "courage"),(ai skill "general")]; // Dsiplay skills for unit named "AI" 
   if (alive _x) then    
       { 
       _unit = _x;      
       _skillregain = _unit getvariable ["skillregain", -1];    
       _stanceregain = _unit getvariable ["stanceregain", -1];  

       if (_stanceregain == -1) then    
            {      
           _unit setvariable ["stanceregain", diag_ticktime];  
           _unit setvariable ["skillregain", diag_ticktime];    
           _unit addeventhandler ["fired",{tpw_fired = _this select 0;tpw_mag = _this select 5; tpw_bullet = _this select 6}];   
           _originalaccuracy = _unit skill "aimingaccuracy";  
           _unit setvariable ["originalaccuracy", _originalaccuracy];   
           _originalshake = _unit skill "aimingshake";   
           _unit setvariable ["originalshake", _originalshake];  
           _originalcourage = _unit skill "courage";  
           _unit setvariable ["originalcourage", _originalcourage];   
           _general = _unit skill "general";  
           _unit setvariable ["general", _general];  
           };  

       if ( diag_ticktime >= _stanceregain) then    
           {  
           _unit setvariable ["supshots", 0];   
           _unit setunitpos "auto";  
           _originalcourage = _unit getvariable "originalcourage";  
           _general = _unit getvariable "general";    
           if((_unit skill "courage") < _originalcourage) then   
               {   
               _unit setskill ["courage",(_unit skill "courage")+(_general)*(0.003)];    
               };  
           };  

       if (diag_ticktime >= _skillregain) then   
           {  
           _originalaccuracy = _unit getvariable "originalaccuracy";     
           _originalshake = _unit getvariable "originalshake";              
           _originalcourage = _unit getvariable "originalcourage";  
           _general = _unit getvariable "general";        
           if((_unit skill "aimingaccuracy") < _originalaccuracy) then   
               {   
               _unit setskill ["aimingaccuracy",(_unit skill "aimingaccuracy")+((_originalaccuracy-(_unit skill "aimingaccuracy"))*.01)];    
               };  
           if((_unit skill "aimingshake") < _originalshake) then   
               {   
               _unit setskill ["aimingshake",(_unit skill "aimingshake")+((_originalshake-(_unit skill "aimingshake"))*.01)];   
               };      
           };  

       if !(isnull tpw_bullet) then    
           {   
           _bc = count ((getposatl _unit) nearobjects ["bulletbase",10]);   
           if (_bc > 0) then    
               {  
               if ((tpw_fired distance _unit) > 25) then    
                   {   
                   if !(tpw_mag in tpw_mags) then    
                       {  
                   _unit setvariable ["skillregain", diag_ticktime + (random 4)-((_unit getvariable "general")+(_unit getvariable "originalcourage"))];    
                       _unit setvariable ["stanceregain", diag_ticktime + 10];   
                       _shots = _unit getvariable "supshots";   
                       _unit setvariable ["supshots", _shots + _bc];   
                       _shots = _unit getvariable "supshots";  
                       _originalaccuracy = _unit getvariable "originalaccuracy";    
                       _originalshake = _unit getvariable "originalshake";  
                       _originalcourage = _unit getvariable "originalcourage";   
                       _general = _unit getvariable "general"; 
                       _unit setunitpos "middle";                                      
                       if ((side tpw_fired != side _unit) && (vehicle _unit == _unit)) then    
                           { 
                           _unit setskill ["aimingaccuracy",_originalaccuracy*_originalcourage*_general-(_shots*(1-_general)*.003)];   
                           _unit setskill ["aimingshake",_originalshake*_originalcourage*_general-(_shots*(1-_general)*.003)];  
                           _unit setskill ["courage",_originalcourage*_originalcourage*_general-(_shots*(1-_general)*.003)]; 
                           if (_shots > 5) then   
                               {  
                               _unit setunitpos "down";  
                               };   
                           };    
                       };   
                   };   
               };   
           };   
       };    
   } foreach allunits;   
};   

//Call function using per frame eventhandler so computer doesn't explode   
[tpw_ai_sup,0] call cba_fnc_addPerFrameHandler;    

-Units react to bullets passing within 10m

-Only units not in vehicles are affected

-Bullets fired from less than 25m away are ignored

-Bullets from small calibre pistols and SMG are ignored

-Units react differently according to the side of the shooter

-Friendly shooter: >0 bullets --> kneel/crouch

-Enemy shooter: 1-5 bullets --> kneel/crouch, >5 bullets -->drop/crawl

-Friendly shooter: no skill reduction

-Enemy shooter: skills reduced according to number of bullets

-Units regain previous stance after 10 seconds without nearby bullets

-Units gradually regain skills after 5 or so seconds without bullets

Each script only needs to be initialized once per mission. CBA is required.

Oh and I almost forgot to mention:

tpw is the one responsible for the magority of the script. Credit should really go to him. He's done an excellent job, and I believe he plans to release this as a mod soon.

Edited by -Coulum-

Share this post


Link to post
Share on other sites

Wow man if you manage to make such add-on it can literally change the game for the better. Right now no infantry tactics that incorporate suppression can work since the AI simply don't react to it, and I don't know much tactics that don't include any form of suppressing.

I wish I could help myself but all I can do is ask around and let you know if I come up with anything.

Good luck!

Share this post


Link to post
Share on other sites

Does sound promising as the current suppression effects don't REALLY work! Can the eventhandler be applied to the bullet (or would that be too CPU intensive)?

Share this post


Link to post
Share on other sites

Don't get your hopes up too much. Even if I can get this to work it would be very simplistic and like kremator said, very system intensive.

Now how exactly would I go about creating an event handler? I believe this is what the first script above has done but it seems to only apply when rounds pass near the player. How can I make an event handler that tracks when rounds pass the ai as well.

Share this post


Link to post
Share on other sites

Hi,

You should be able to set the AI aimingaccuracy, aimingspeed and aimingshake very low for a period of time, which will make him a terrible shot. See this page in the Wiki.

I am also making an addon which will affect such things on the fly. You can see how changing the values of these arrays affects the AI's ability to shoot straight in a video I posted at the end of my thread here

Share this post


Link to post
Share on other sites

Thanks Jedra. I was going to set the accuracy of the ai down by using setunitability, but it turns out it doesn't work anymore.I used

setskill ["aimingAccuracy",0.1];

setskill ["aimingShake",0.1];

in a quick editor test and it makes the ai a lot less accurate. It does require a bit of time at the start of the mission before the new skills kick in.

I also used

setunitpos "DOWN";

to make the ai go prone and that works fine and dandy too. Now does anybody have any ideas on how to make the ai skills and posture return to normal after a certain amount of time?

And of course I still can't figure out how to use an eventhandler to track when a round comes close to an ai so if anyone has any tips on how to use eventhandlers your advice would be much appreciated. Thanks.

Share this post


Link to post
Share on other sites

You could have something like;


// Save current skill
_saveAccuracy = _unit skill "aimingAccuracy";
_saveShake = _unit skill "aimingshake";

// make AI stupid
_unit setskill ["aimingAccuracy",0.1];
_unit setskill ["aimingShake",0.1];


// put him in position
setunitpos "DOWN";

sleep 30  // Sleep for 30 seconds (roughly speaking)

// Restore AI
_unit setskill ["aimingAccuracy",_saveAccuracy];
_unit setskill ["aimingShake",_saveShake];

// Stand him up again
setunitpos "UP";  // Or whatever

Eventhandler would look something like this...

_EHFiredIdx1 = badguy1 addEventHandler ["firednear", {STARTTIME = time; badguy1 removeeventhandler ["firednear",0];}];

This runs the stuff in the braces if someone fired within 60 meters of badguy1. I just use it to set a flag, but you could run a .sqf in there.

Firednear passes in an array to the handler;

[unit, firer, distance, weapon, muzzle, mode, ammo]

You can use distance to decide when supression is appropriate. See this page on the Wiki. I guess your challenge here is that the unit firing could be some distance away, yet you can still be surpressed as the rounds themselves are close. There is probably a more appropriate EH for this - I will see if I can find one tomorrow, but you may has well have a scooch round yourself at the wiki.

Edited by Jedra

Share this post


Link to post
Share on other sites

Thanks Jedra.

I was able to get the "effects" working thanks to your help. I didn't know that you could create a variable like that and then sub it in later for a number. probably common knowledge for most scripters, but that just proves how very little I know about this stuff.

As for the event handler. I couldn't get the one you described to work when I tried to exec a script from it but I didn't have much time to play around with it and try to figure out what I have done wrong so when I do get time I will give it some more research.

Your right that the "firednear" isn't exactly ideal for this type of thing because it is limited to detecting shooters within 69 m of the unit according to the wiki. Also the distance returned by the handler would be from the shooter to the target rather than from the round to the shooter, which is more relevant when dealing with suppression. Problem is there isn't many other event handlers suitable. After reading through the wiki list, the fired event handler it probably the best bet

I could use it to detect who shot and what ammo he shot,

Then I could use "nearestobject" to detect the ammo of that type nearest the shooter to find the round,

then actively measure the distance between the round and the target,

and apply effects if the distance becomes small enough.

I don't know if this kind of thing would work, or if it even makes sense. one problem I can foresee is that the script wouldn't know which unit is the target. Anyways I will try working on it soon when I have more time.

Your help is much appreciated Jedra, thanks.

Edited by -Coulum-

Share this post


Link to post
Share on other sites
Thanks Jedra.

I could use it to detect who shot and what ammo he shot,

Then I could use "nearestobject" to detect the ammo of that type nearest the shooter to find the round,

then actively measure the distance between the round and the target,

and apply effects if the distance becomes small enough.

I don't know if this kind of thing would work, or if it even makes sense. one problem I can foresee is that the script wouldn't know which unit is the target. Anyways I will try working on it soon when I have more time.

Your help is much appreciated Jedra, thanks.

This is probably your best bet to play around with. If you use firednear and add the event handler to the AI you could probably get a good approximation of supression if you are also checking for nearest object. I guess it doesn't matter who fired as in reality you could also be supressed by rounds from your own side - a bullet's a bullet at the end of the day and still hurts whoever fired it!!

I might have a play later on. I have a mod of my own to write, a mission to finish, the crap hit the fan with work as well this week, oh and there's the kids to look after - but hey you've got me interested now and it's a cool project! Anyway, I'll have a proper think about it later once I have got the kids to school!

Share this post


Link to post
Share on other sites

Isn't this solution of using the "Fired" EH will suppress the AI even when nearby AI fire on the enemy?

Suppression must occur when bullets IMPACT in close proximity to the AI. Can't that be checked somehow?

Share this post


Link to post
Share on other sites

That already happens. The idea is that rounds passing in close proximity to an AI should also make them suppressed, which doesn't currently happen.

That can be checked with:

(((position _unit) nearestObject "BulletBase") distance _unit) < 5

The easiest way to check this would probably be in a simple FSM, but obviously that would mean running one for every unit, and I don't know how system intensive that would be. AI's behaviour is already governed by FSMs anyway.

Share this post


Link to post
Share on other sites

Impact proximity maybe a good way forward. A more responsive AI to sonic cracks would be a dream! As I normally play with 200-400 AI I'm thinking about how this would work with huge numbers. Anything you do come up with - gimme a shout and I can test it for you with these HUGE numbers :)

Keep up the good work.

Share this post


Link to post
Share on other sites
That already happens.

I believe that it's not, which is the motivation behind this initiative.

The idea is that rounds passing in close proximity to an AI should also make them suppressed, which doesn't currently happen.

That would be great but suppression as reaction to bullet impact in close proximity to the AI is more important.

Edited by Variable

Share this post


Link to post
Share on other sites

It does happen. Go in the editor and put down any player unit, this setCaptive true. Then a BLUFOR rifleman, this setunitpos "up". Place an OPFOR AI 100 metres or so in front of him with this init: removeAllWeapons this; this disableai "move"; this setunitpos "up"; this allowDamage false. When you enter the mission, the armed AI will obviously start firing at the unarmed one. Stand directly behind the armed guy and shoot a few rounds within 2m of his feet. You will notice that his rate of fire decreases dramatically, his aim becomes erratic and you can hear his heavy breathing.

That would be great but suppression as reaction to bullet impact in close proximity to the AI is more important.

Depends on the proximity. If you try what I suggested above you will see that the AI is already suppressed by nearby impacts. The only problem is that the impact area is a bit too small, about 2 meters - because if you are able to hit within that distance of an AI, then more than likely you should be able to hit him too. Another problem with this impact suppression is that it does not work on gunners of static weapons, who should be a major priority for suppression.

So, if the impact area was increased to about 3-4 meters, that would be great. However, if the AI was affected by passing rounds, I think that would be equally useful. You might know the AI's approximate position behind cover, but for whatever reason be unable to hit near enough to suppress him. But if the AI was simulated to detect sonic cracks, you would be able to suppress him just as well.

Edited by 2nd Ranger

Share this post


Link to post
Share on other sites

Ai do react to nearby impacts but it is often not in the smartest way. They do not react to passing by rounds however and this is what my goal to implement is.

Thanks for all the ideas guys. I should have enough time to try some of them out when I get home tonight. Also keep in mind that I am learning this as I go.

@2nd ranger

You mentioned using fsm to track nearby rounds. Do you have any further info on how to use fsm. It may be system intensive but right now my goal is simply to get this working.

Share this post


Link to post
Share on other sites

2nd ranger, thanks for the information, I didn't know that.

Well then, I agree that increasing the range radius of the impact effect and add passing bullets effect is the priority.

Share this post


Link to post
Share on other sites

Okay guys, this is what I got so far.

I placed one opfor unit down named "ai"

I placed 1 blufor player down.

I created the following eventhandler that is started in the "init.sqf"

_fired = player addEventHandler ["fired", {_this execVM "suppression.sqf"}];

This means when I (the player) fires suppression.sqf (below) is run

_ammo = _this select 4;

_round = nearestobject [player,_ammo];
while {(speed _round) > 0.1} do {
_dist = _round distance ai;
if (_dist < 10) then {
	hint "ai is suppressed";
	ai setunitpos "down";
	_saveAccuracy = ai skill "aimingAccuracy";
	_saveShake = ai skill "aimingshake";
	ai setskill ["aimingAccuracy",0.01];
	ai setskill ["aimingShake",0.01];
	sleep 5;
	ai setskill ["aimingAccuracy",_saveaccuracy];
	ai setskill ["aimingShake",_saveshake];
	ai setunitpos "auto";
};
};

This tracks the shot I have fired and determines if it has come close (10 "units") to the opfor named "ai". if so, it causes "ai" to go prone and have decreased accuracy for 5 seconds before he goes back to his normal stance and accuracy. All this works relatviely smoothly...

Now my newbie scripting questions are:

1. How do I make it so the fired eventhandler is not only created for "player", but also for every unit on the map (Besides manually naming all the ai and typing an eventhandler out for each of these names.)

2. Right now the script only tracks whether the round comes close to "ai". How do I make it so that the distances from the round to all units on the map is measured? (without naming ai1, ai2, ai3...etc. and having corresponding "_dist = _round distance ai;","_dist1 = _round distance ai1;","_dist2 = _round distance ai2;"... etc.)

If my questions aren't clear please let me now and I will try to explain what I mean better. Thanks for your help.

P.S.

from the little "test" I created above, things are looking quite promising in terms of gameplay improvements. If you keep up suppressive fire on "ai" he will go prone and you will sustain very little accurate fire from him. don't keep up the fire and he will start laying down accurate shots and suppressing/hitting you. If this stuff isn't ridiculously system intensive (which it very well may be) I think it will provide alot more depth to firefights.

Share this post


Link to post
Share on other sites

To add the eventhandler to all the units, there are several methods;

1. If they are all placed in the editor, the in the init line for each unit, you add;

0 = this addeventhandler ["fired" , {_this execVM "supression.sqf"}];

2. If you are adding them in script then simply add the eventhandler to the unit after you create it.

3. Both of the above if you have some in the editor and some you create in script.

4. You could add it in a loop;


[font=Courier New][color=#007700]{[/color][/font] 
[font=Courier New][color=#0000bb]    _fired [/color][color=#007700]= [/color][color=#0000bb]_x addEventHandler [/color][color=#007700][[/color][color=#dd0000]"fired"[/color][color=#007700], {[/color][color=#0000bb]_this execVM [/color][color=#dd0000]"suppression.sqf"[/color][color=#007700]}];

} foreach allunits;

[/color][/font]

---------- Post added at 01:32 ---------- Previous post was at 01:28 ----------

Well, that would save some work. But I would crack on Coulum as it's good to learn this stuff.

Share this post


Link to post
Share on other sites

execVM a script everytime a unit fires is not an option.

Just think about heavy firefights with SAW and MG firing. That will start hundreds of scripts in worst case with all the problems it brings.

The execVM itself already removes the most important advantage that code executed in an eventhandler brings, running in the same frame.

Btw, the fired EH does return the projectile itself too since 1.54 or 1.55, no need for a nearestobject check.

Suppresion eventhandler is the only performant way to handle it.

Xeno

Edited by Xeno

Share this post


Link to post
Share on other sites

So wait basically this script allows detection of "shots near" as in in the air rather then having to impact near the AI? Thats stunning as that is severely needed! I gave it a whirl and put an enemy above on a high ridge to insure my shot would whizz past him and connect with no land nearby - worked! All done with a Distance variable?!?

I hope you can find a way to make this accessible to all missions without too many scripts needed to run -but this a very worthwhile endevour :)

Share this post


Link to post
Share on other sites

Hello again, just wanted to ask if you are still working on this...?

Share this post


Link to post
Share on other sites
Hello again, just wanted to ask if you are still working on this...?

Well upon hearing of the performance problems it would incur I honestly gave up...

But, lately I played sp and got so fed up with ai not being suppressable, and very short firefights that caused, so I gave it another crack. This time I approached it from a different angle I didn't know was possible before, simply due to lack of scripting knowledge/experience. It was actually pointed out by 2nd Ranger, I was just to much of a noob to actually understand what he was saying. Anyhow, I put these 2 scripts together that seem to do the job at making the ai suppressable. To use em...

Put this in the init of a mission

{nul = [_x] execvm "indcounter.sqf"; } Foreach allunits

and put both indcount.sqf and indlevel1.sqf into the missions folder. Here are the scripts within those if your interested.

indcount.sqf

//hint "bulletcounter";
//Counts the number of bullets passing by a unit and runs inlevel1.sqf (the suppression effects script)
_unit = _this select 0;

//while unit is alive, count number of bullets in the air 10 metres from a given unit.
while {alive _unit} do
{
_BulletAmount = 0;
_BulletAmount = _BulletAmount + count ((position _unit) nearObjects ["BulletBase", 10]);
sleep 0.01;
//if there are more than 2 bullet around a unit run the suppressio effects
if (_BulletAmount >= 1) then 
	{
	nul = [_unit] execvm "indlevel1.sqf";
	sleep 5.5;
	};
};

indlevel1.sqf

//hint "indlevel1"
//suppression effects. Decreases aiming accuracy, aiming shake, and courage for 5 seconds and then restores them back to default. Also forcees prone or crouched stance for 15 seconds.

//find the unit in question
_unit = _this select 0;

//apply new stances 70% prone, 30% crouched
_r = random 1;
if (_r < 0.70) then
{	
_unit setunitpos "down";
//hint "he's down";
}
else
{
_unit setunitpos "middle";
//hint "he's up";
};


//save original skills
_originalaccuracy = _unit skill "aimingAccuracy";
_originalshake = _unit skill "aimingshake";
_originalcourage = _unit skill "courage";
_originalgeneral = _unit skill "general";


//make suppressed skills
_suppressedaccuracy = _originalaccuracy*_originalgeneral*_originalcourage;
_suppressedshake = _originalshake*originalgeneral*_originalcourage;
_suppressedcourage = _originalcourage*_originalgeneral*_originalcourage;


//apply suppressed skills
_unit setskill ["aimingAccuracy",_suppressedaccuracy];
_unit setskill ["aimingShake",_suppressedshake];
_unit setskill ["courage",_suppressedcourage];

//check
//_check = _unit skill "aimingAccuracy";
//hint str (_check);

//wait 5 seconds
sleep 5;

//return original skills
_unit setskill ["aimingAccuracy",_originalaccuracy];
_unit setskill ["aimingShake",_originalshake];
_unit setskill ["courage",_originalcourage];

//check
//_check = _unit skill "aimingAccuracy";
//hint str (_check);

//wait 5 seconds
sleep 10;

//return original stance
_unit setunitpos "auto";


And for anyone who doesn't want to decipher the code, here's what it does in semi english...

Basically when a bullet snaps by an ai he will either go prone 70% or crouched 30%. Some times the script is unable to catch a round, but usually 3 shots quickly, will definitely trigger the suppression effects. Also, at close ranges, the speed of the bullet makes it pretty hard to catch the round. usually you have to be at least 50 to 100 metres back depending on the weapon. in addition to going prone the ai's shooting skill, courage, and aiming shake will be reduced by a factor of their courage and general skill. Ie. with an original aiming skill of .5, general skill of .5, and courage of .5, after suppression, the unit will have an aiming skill of 0.5 x 0.5 x 0.5 = 0.125. This skill sticks with the unit for a few seconds before being reverted back to the original skill value. After around 15 seconds the unit will also go back to default stance. And thats all for now. If the performance hit isn't to heavy though, I will probably try to refine and expand on these suppression effects Ie. having different levels of suppression - light, medium, heavy.

If anyone wants to try this out feel free. Feed back is very welcome, especially concerning large numbers of ai and performacne. I just ran a quick test, marine squad against Russian squad, on the utes airport. I would say the firefight that ensued took around twice as long as a regular one, and there was lots of crouching and prone stances being used. I didn't notice a fps drop but those weren't exactly large numbers of ai. A problem I did notice however, was one soldier remained standing, refusing to crouch no matter how many bullets passed by, at the end of a particular fight - I could only get this to happen once but anyone giving this a rip be sure to keep an eye open for this kind of problem. But by all mean give it a try and tell me what you think. I think if there is not a huge performance drop I will definitely try to expand on this and make it into an addon... once I learn how to actually compile an addon that is.

Share this post


Link to post
Share on other sites

Hi -Coulum-, beautiful little bit of code, which I'm definitely going to test out. It should be possible to wrap the whole thing into a cba_fnc_addPerFrameHandler (like I have done with the LOS stuff you've been helping me with) so that it can run without bogging down performance.

Share this post


Link to post
Share on other sites
It should be possible to wrap the whole thing into a cba_fnc_addPerFrameHandler (like I have done with the LOS stuff you've been helping me with) so that it can run without bogging down performance.
ooooh! I've never heard of cba_fnc_addPerFrameHandler but if you could help me out with implementing it when/if you have time or point me towards some documentation that would be awesome. What exactly does the cba_fnc_addPerFrameHandler do?

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
Sign in to follow this  

×