Jump to content
Sign in to follow this  
tpw

TPWC AI suppression system

Recommended Posts

fabrizio_T, Thanks for your feedback. Unfortunately no time to look at it.

Here a short comparison video: No TPWC - Dedicated Server TPWC - SP TPWC

You will clearly see the diff...

Share this post


Link to post
Share on other sites

Quick obs:

if (unitpos _unit != "DOWN") then { _unit setunitpos "middle"};

This won't work. You can have units that went prone by themselves while unitpos will give you "Auto" for them.

From Biki (and I can confirm since I've played with this command a lot):

Return the unit position rules.

The return value is always "Auto" unless the unit has gotten a setUnitPos command. In that case the value is the last stance the unit was ordered to.

So the proper way to do it is to check unit's animation, for which I gave you a solution earlier in this thread.

Share this post


Link to post
Share on other sites

Here a short comparison video: No TPWC - Dedicated Server TPWC - SP TPWC

You will clearly see the diff...

I get exactly the same as you Ollem on my dedi vs local.

Share this post


Link to post
Share on other sites
Quick obs:

if (unitpos _unit != "DOWN") then { _unit setunitpos "middle"};

This won't work. You can have units that went prone by themselves while unitpos will give you "Auto" for them.

From Biki (and I can confirm since I've played with this command a lot):

So the proper way to do it is to check unit's animation, for which I gave you a solution earlier in this thread.

Or you may prefer some creative usage of recently introduced eyepos or aimpos ;)

FLEXAI_get_stance = {

private ["_unit", "_h", "_ret"];

_unit = _this select 0;
_ret = "UP";

_h = ((aimpos _unit) select 2) - ((getPosASL _unit) select 2);

if( _h < 1.15) then { _ret = "MIDDLE";};
if( _h < .5) then { _ret = "DOWN";};

_ret
};

It checks the true stance by measuring current aiming position height.

Function is a draft and may be refined, but it's simple and you get the idea, right?

usage:

[_unit] call  FLEXAI_get_stance;

return values: "UP", "DOWN" or "MIDDLE";

Share this post


Link to post
Share on other sites

Ollem and Fabrizio_T, you guys are bloody great! I think I should retire and let the experts take over. Or rename it TPWCCF. I'll incorporate the changes ASAP.

Robalo, thanks for the heads up.

Seriously, I just love this level of input and collaboration. This community is awesome.

Share this post


Link to post
Share on other sites
Ollem and Fabrizio_T, you guys are bloody great! I think I should retire and let the experts take over. Or rename it TPWCCF. I'll incorporate the changes ASAP.

Many people are glad to support you, as you notice.

That's because you all (You, Coulum, Ollem, ...) are doing a great work.

Simple as that. Keep it going.

Edited by fabrizio_T

Share this post


Link to post
Share on other sites
Many people are glad to support you, as you notice.

That's because you all (You, Coulum, Ollem, ...) are doing a great work.

Simple as that. Keep it going.

I actually have thought of using eyepos previously, the only problem being that it won't work without beta 93666 or greater.

Something like:

if ((((eyepos _unit) select 2) - ((getPosASL _unit) select 2)) > 0.5) then 
{	
_unit setvehicleinit format ["this setunitpos 'middle';"]; 
processinitcommands; 
clearVehicleInit _unit; 
};

This would ensure that a unit would only crouch if he wasn't low to the ground (prone).

Checking animation as per Robalo is independent of beta, but more work for a lazy bastard like me..

Share this post


Link to post
Share on other sites
Checking animation as per Robalo is independent of beta, but more work for a lazy bastard like me..

Nah, it's too easy.

Probably less efficient than fabrizio's smart little function, but should cover at least until 1.61 comes.

Edited by Robalo

Share this post


Link to post
Share on other sites
Nah, it's too easy.

Probably less efficient than fabrizio's smart little function, but should cover at least until 1.61 comes.

Brilliant! I'm always reluctant to make something rely on a beta.

---------- Post added at 09:25 ---------- Previous post was at 08:50 ----------

Mega update!

We are inching closer towards a legitimate release thanks to Ollem, Fabrizio_T and Robalo. Thanks again guys.

  • Units only crouch if they're not prone (Robalo)
  • Overhauled debug code, more efficient and should work better for dedi servers (Ollem)
  • Use of switch instead of if for more efficient unit behaviour changes under suppression (Ollem)
  • Modified bullet detection to check for foot units earlier on (Fabrizio_T)
  • Overhauled visual fx (blur and gamma), gamma should be more noticeable
  • Other cleanups

1.03 Code:

/*   
TPWC AI SUPPRESSION   

Authors: TPW & -Coulum-   
Additional code: Fabrizio_T, Ollem  
Version: 1.03 
Last modified: 20120629
Requires: CBA

Disclaimer: Feel free to use and modify this code, on the proviso that you post back changes and improvements so that everyone can benefit from them, and acknowledge the original authors in any derivative works.
*/   

if (isServer || isDedicated) then {  

//Log it  
diag_log format ["AI SUPPRESS STARTED: Server: %1 - Dedicated: %2", isServer, isDedicated];  

////////////   
//VARIABLES   
///////////   

//Suppression mode. 1 = basic , 2 = light, 3 = full stance / skills modification  
tpwc_ai_sup_mode = 3;  

//Delay before suppression functions start. Allows time for other AI mods to set unit skills
tpwc_ai_sup_sleep = 5;

//Debugging. Will display red balls over any suppressed units. Set to 1 for debugging
tpwc_ai_sup_debug = 1;

//Bullet detection radius (m). Bullets must pass within this distance of unit to suppress them. If set much below 10m, bullets may not be detected
tpwc_ai_sup_br = 10;

//Bullet ignore radius (m). Bullets from a shooter closer than this will not suppress. 
tpwc_ai_sup_ir = 25;

//Shot threshold. More shots than this will cause unit to drop/crawl
tpwc_ai_sup_st = 5;

//Pistol and SMG ammo to ignore. Add custom ammo (eg suppressed) or change to taste    
tpwc_ai_sup_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"   
]; 

//Startup hint. 0 = no hint, 1 = hint
tpwc_ai_sup_hint = 1; 

//Player suppression (shake and visuals). 0 = no suppression, 1 = suppression    
tpwc_ai_sup_playersup = 1;

//////////   
// SET UP   
//////////   

//DECLARE PRIVATE VARIABLES   
private ["_stanceregain","_skillregain","_unit","_bc","_shots","_originalaccuracy","_originalshake","_originalcourage","_general","_ball1","_ball2","_ball3","_skillset","_asr","_tint","_blur","_x","_ppmod","_ppmodifier"];   

//WAIT
sleep tpwc_ai_sup_sleep;   

//START HINT      
if (tpwc_ai_sup_hint == 1) then {   
0 = [] spawn {  
hintsilent "TPWC AI Suppress 1.03 Active";   
sleep 3;   
hintsilent ""};   
};      


//////////////////   
// MAIN FUNCTIONS    
//////////////////    

//BASIC VERSION
tpwc_ai_sup_basic =     
{   
   {   
   if (alive _x) then    
       { 
       _unit = _x;      
       _stanceregain = _unit getvariable ["tpwc_stanceregain", -1];  

       if (_stanceregain == -1) then    
           {      
           _unit setvariable ["tpwc_stanceregain", diag_ticktime];  
           _unit addeventhandler ["fired",{tpwc_ai_sup_fired = _this select 0;tpwc_ai_sup_bullet = _this select 6}];   
           _ball = "Sign_sphere25cm_EP1" createvehicle getposatl _unit;_ball attachTo [_unit,[0,0,2]]; _unit setvariable ["tpwc_supball",_ball]; 
           };  

       if ( diag_ticktime >= _stanceregain) then    
           {  
           _ball = _unit getvariable "tpwc_supball"; _ball hideobject true;          
           _unit setvariable ["tpwc_supshots", 0];   
           _unit setunitpos "auto";  
		_unit setvariable ["tpwc_suppressedstance", 0]; 
           _unit setvariable ["tpwc_stanceregain", diag_ticktime + 10];  
           };  

       if !(isnull tpwc_ai_sup_bullet) then    
           {   
           _bc = count ((getposatl _unit) nearobjects ["bulletbase",tpwc_ai_sup_br]);   
           if (_bc > 0) then    
               {  
               if ((tpwc_ai_sup_fired distance _unit) > tpwc_ai_sup_ir) then    
                   {   
                   _unit setvariable ["tpwc_stanceregain", diag_ticktime + 10];   
                   _shots = _unit getvariable "tpwc_supshots";   
                   _unit setvariable ["tpwc_supshots", _shots + _bc];   
                   _shots = _unit getvariable "tpwc_supshots";  
                   _unit setunitpos "middle"; 
				_unit setvariable ["tpwc_suppressedstance", 1]; 
                   if (tpwc_ai_sup_debug == 1) then  
                       { 
                       _ball = _unit getvariable "tpwc_supball";_ball hideobject false; 
                       };             
                   if (_shots > tpwc_ai_sup_st) then   
                       {  
                       _unit setunitpos "down";  
                       };   
                   };   
               };   
           };   
       };    
   } foreach allunits;   
};   

//LITE VERSION 
tpwc_ai_sup_lite =     
{    
   {   
   if (alive _x) then    
       { 
       _unit = _x;      
       _stanceregain = _unit getvariable ["tpwc_stanceregain", -1];  

       if (_stanceregain == -1) then    
           {      
           _unit setvariable ["tpwc_stanceregain", diag_ticktime];  
           _unit addeventhandler ["fired",{tpwc_ai_sup_fired = _this select 0;tpwc_ai_sup_mag = _this select 5; tpwc_ai_sup_bullet = _this select 6}];   
           _ball = "Sign_sphere25cm_EP1" createvehicle getposatl _unit;_ball attachTo [_unit,[0,0,2]]; _unit setvariable ["tpwc_supball",_ball]; 
           };  

       if ( diag_ticktime >= _stanceregain) then    
           {  
           _ball = _unit getvariable "tpwc_supball"; _ball hideobject true;              
           _unit setvariable ["tpwc_supshots", 0];   
           _unit setunitpos "auto";  
		_unit setvariable ["tpwc_suppressedstance", 0]; 
           _unit setvariable ["tpwc_stanceregain", diag_ticktime + 10];  
           };  

       if (!(isnull tpwc_ai_sup_bullet)  && (vehicle _unit == _unit)) then    
           {   
           _bc = count ((getposatl _unit) nearobjects ["bulletbase",tpwc_ai_sup_br]);   
           if (_bc > 0) then    
               {  
               if ((tpwc_ai_sup_fired distance _unit) > tpwc_ai_sup_ir) then    
                   {   
                   if !(tpwc_ai_sup_mag in tpwc_ai_sup_mags) then    
                       {  
                       _unit setvariable ["tpwc_stanceregain", diag_ticktime + 10];   
                       _shots = _unit getvariable "tpwc_supshots";   
                       _unit setvariable ["tpwc_supshots", _shots + _bc];   
                       _unit setunitpos "middle"; 
					_unit setvariable ["tpwc_suppressedstance", 1]; 						
                       if (side tpwc_ai_sup_fired != side _unit) then    
                           { 
                           _shots = _unit getvariable "tpwc_supshots";  
                           if (tpwc_ai_sup_debug == 1) then  
                               { 
                               _ball = _unit getvariable "tpwc_supball";_ball hideobject false; 
                               }; 
                           if (_shots > tpwc_ai_sup_st) then   
                               {  
                               _unit setunitpos "down";  
                               };   
                           };    
                       };   
                   };   
               };   
           };   
       };    
   } foreach allunits;   
};   

//BULLET DETECTION LOOP (TIME CRITICAL)  
//Do not touch this please  
tpwc_ai_sup_detect =        
{       
   {      
   _unit = _x; 
   if (!(isnull tpwc_ai_sup_bullet) && (vehicle _unit == _unit)) then       
       {      
       _bc = count ((getposatl _unit) nearobjects ["bulletbase",tpwc_ai_sup_br]);      
       if (_bc > 0) then       
           {     
           if ((tpwc_ai_sup_fired distance _unit) > tpwc_ai_sup_ir) then       
               {      
               if !(tpwc_ai_sup_mag in tpwc_ai_sup_mags) then       
                   {     
                   _unit setvariable ["tpwc_skillregain", diag_ticktime + (random 4)-((_unit getvariable "tpwc_general")+(_unit getvariable "tpwc_originalcourage"))];       
                   _unit setvariable ["tpwc_stanceregain", diag_ticktime + 10];      
                   _unit setvariable ["tpwc_supshots",(_unit getvariable "tpwc_supshots") + _bc];      
                   _unit setvariable ["tpwc_suppressedstance", 1];  
                   if (side tpwc_ai_sup_fired != side _unit) then  
                       {  
                       _unit setvariable ["tpwc_suppressedstance", 2];                              
                       if (_unit getvariable "tpwc_supshots" > tpwc_ai_sup_st) then      
                           {  
                           _unit setvariable ["tpwc_suppressedstance", 3];                                  
                           };      
                       };       
                   };      
               };      
           };      
       };      
   } foreach allunits;      
};      

//UNIT STANCE/SKILL MODIFICATION LOOP (NON TIME CRITICAL)  
tpwc_ai_sup_behaviour =   
{  
tpwc_ai_sup_supvisflag = 0;  
while {true} do   
   {  
       {  
       if (alive _x) then   
           {  
           _unit  = _x; 
           _skillregain = _unit getvariable ["tpwc_skillregain", -1];       
           _stanceregain = _unit getvariable ["tpwc_stanceregain", -1]; 

           //SET INITIAL PARAMETERS FOR EACH UNIT  
           if (_stanceregain == -1) then       
               {   
               _unit setvariable ["asr_ai_sys_aiskill_configured", false];    
               _unit setvariable ["tpwc_skillset", false];    
               _unit setvariable ["tpwc_combatmode", "unchanged"];   
               _unit setvariable ["tpwc_originalaccuracy", _unit skill "aimingaccuracy"];     
               _unit setvariable ["tpwc_originalshake",  _unit skill "aimingshake"];    
               _unit setvariable ["tpwc_originalcourage", _unit skill "courage"];     
               _unit setvariable ["tpwc_general", _unit skill "general"];    
               _unit setvariable ["tpwc_stanceregain", diag_ticktime];     
               _unit setvariable ["tpwc_skillregain", diag_ticktime]; 
               _unit addeventhandler ["fired",{tpwc_ai_sup_fired = _this select 0;tpwc_ai_sup_mag = _this select 5; tpwc_ai_sup_bullet = _this select 6}];      
               if ( ( assignedVehicleRole _unit) select 0 == "Turret"  ) then   
                   {  
                   (vehicle _unit) addeventhandler ["fired",{tpwc_ai_sup_fired = _this select 0;tpwc_ai_sup_mag = _this select 5; tpwc_ai_sup_bullet = _this select 6}];   
                   };  
               if (tpwc_ai_sup_debug == 1) then     
                   { 
                   _ball1 = "Sign_sphere25cm_EP1" createvehicle getposatl _unit;  
                   _ball1 setObjectTexture [0,"#(argb,8,8,3)color(0.2,0.9,0.2,0.5,ca)"];  
                   _ball1 attachTo [_unit,[0,0,2]];   
                   _unit setvariable ["tpwc_sup1ball",_ball1]; 
                   _ball1 hideobject true;  

                   _ball2 = "Sign_sphere25cm_EP1" createvehicle getposatl _unit;  
                   _ball2 setObjectTexture [0,"#(argb,8,8,3)color(0.6,0.9,0.0,0.7,ca)"]; //yellow  
                   _ball2 attachTo [_unit,[0,0,2]];   
                   _unit setvariable ["tpwc_sup2ball",_ball2]; 
                   _ball2 hideobject true;  

                   _ball3 = "Sign_sphere25cm_EP1" createvehicle getposatl _unit;  
                   _ball3 setObjectTexture [0,"#(argb,8,8,3)color(0.8,0.5,0.5,0.5,ca)"]; //red  
                   _ball3 attachTo [_unit,[0,0,2]];   
                   _unit setvariable ["tpwc_sup3ball",_ball3]; 
                   _ball3 hideobject true;                       
                   };  
               };   

           //IF UNIT SKILLS ARE UNSUPPRESSED  
           if (diag_ticktime >= _skillregain) then      
               {  
               _originalaccuracy = _unit getvariable "tpwc_originalaccuracy";        
               _originalshake = _unit getvariable "tpwc_originalshake";                 
               _originalcourage = _unit getvariable "tpwc_originalcourage";     
               _general = _unit getvariable "tpwc_general";           
               if((_unit skill "aimingaccuracy") < _originalaccuracy) then      
                   {    
                   _unit setskill ["aimingaccuracy",(_unit skill "aimingaccuracy")+((_originalaccuracy-(_unit skill "aimingaccuracy"))*.325)];       
                   };     
               if((_unit skill "aimingshake") < _originalshake) then      
                   {      
                   _unit setskill ["aimingshake",(_unit skill "aimingshake")+((_originalshake-(_unit skill "aimingshake"))*.325)];      
                   };    
               };  

           //IF UNIT STANCE IS UNSUPPRESSED  
           if ( diag_ticktime >= _stanceregain) then       
               { 
               _unit setvariable ["tpwc_supshots", 0];      
               _unit setunitpos "auto";     
               _originalcourage = _unit getvariable "tpwc_originalcourage";     
               _general = _unit getvariable "tpwc_general"; 
               _unit setvariable ["tpwc_suppressedstance", 0]; 
               //if ( _statusColor != 0 ) then { _statusColor = 1; };// status has been reset so set > 0             
               if((_unit skill "courage") < (_originalcourage - 0.1)) then      
                   {      
                   _unit setskill ["courage",(_unit skill "courage")+(_general)*(0.1)];       
                   }     
                   else    
                   {    
                   if (_unit getvariable "tpwc_combatmode" != "unchanged") then   
                       {  
                       _unit setbehaviour str(_unit getvariable "tpwc_combatmode");  
                       _unit setvariable ["tpwc_combatmode", "unchanged"];   
                       };  
                   };    
               };     

		//UNIT CHANGES FOR DIFFERENT SUPPRESSION
           switch ( _unit getvariable "tpwc_suppressedstance" ) do 
           { 
		case 1: //IF ANY BULLETS NEAR UNIT 
			{ 
			if ((_unit call CBA_fnc_getunitanim) select 0 != "prone") then 
				{	
				_unit setvehicleinit format ["this setunitpos 'middle';"]; 
				processinitcommands; 
				clearVehicleInit _unit; 
				}; 
			}; 

		case 2: //IF ENEMY BULLETS NEAR UNIT 
			{
			if ((_unit call CBA_fnc_getunitanim) select 0 != "prone") then 
				{	
				_unit setvehicleinit format ["this setunitpos 'middle';"]; 
				processinitcommands; 
				clearVehicleInit _unit; 
				};
			_unit setvariable ["tpwc_combatmode", behaviour _unit];   
			if( !( behaviour _unit in ["COMBAT", "STEALTH"] ) ) then   
				{  
				_unit setbehaviour "COMBAT";   
				};      
			_originalaccuracy = _unit getvariable "tpwc_originalaccuracy";       
			_originalshake = _unit getvariable "tpwc_originalshake";     
			_originalcourage = _unit getvariable "tpwc_originalcourage";      
			_general = _unit getvariable "tpwc_general";    
			_shots = _unit getvariable "tpwc_supshots";    
			if (diag_ticktime < _skillregain) then   
			{         
			_unit setskill ["aimingaccuracy",_originalaccuracy*_originalcourage*_general-(_shots*(1-_general)*((_unit skill "aimingaccuracy")-.1)*.025)];        
			_unit setskill ["aimingshake",_originalshake*_originalcourage*_general-(_shots*(1-_general)*((_unit skill "aimingshake")-.1)*.025)];       
			_unit setskill ["courage",(_unit skill "courage")-(_shots*(1-_general)*(1-_originalcourage)*((_unit skill "courage")-.1)*.1)];   
			};  
			if ((_unit == player) and (tpwc_ai_sup_playersup == 1) and (diag_ticktime < _skillregain)) then   
				{   
				addCamShake [1.5 - (skill player),(random 4)-((_unit getvariable "tpwc_general")+(_unit getvariable "tpwc_originalcourage")) , 2.5]  
				};
			}; 

		case 3: //IF UNIT IS SUPPRESSED WITH MORE THAN 5 ENEMY BULLETS  
			{ 
			_unit setvehicleinit format ["this setunitpos 'down';"]; 
			processinitcommands; 
			clearVehicleInit _unit; 
			_unit forcespeed -1;  
			if( !( behaviour _unit in ["COMBAT", "STEALTH"] ) ) then   
				{  
				_unit setbehaviour "COMBAT";   
				}; 
			_unit setvariable ["tpwc_combatmode", behaviour _unit];    //TODO: verify right order 
			_originalaccuracy = _unit getvariable "tpwc_originalaccuracy";       
			_originalshake = _unit getvariable "tpwc_originalshake";     
			_originalcourage = _unit getvariable "tpwc_originalcourage";      
			_general = _unit getvariable "tpwc_general";    
			_shots = _unit getvariable "tpwc_supshots";    
			if (diag_ticktime < _skillregain) then   
				{         
				_unit setskill ["aimingaccuracy",_originalaccuracy*_originalcourage*_general-(_shots*(1-_general)*.003)];        
				_unit setskill ["aimingshake",_originalshake*_originalcourage*_general-(_shots*(1-_general)*.003)];       
				_unit setskill ["courage",(_unit skill "courage")-(_shots*(1-_general)*(1-_originalcourage)*.07)];   
				};  
			if ((isPlayer _unit) and (tpwc_ai_sup_playersup == 1) and (diag_ticktime < _skillregain)) then   
				{  
				[] spawn tpwc_ai_sup_visuals;  
				addCamShake [2 - (skill _unit),(random 6)-((_unit getvariable "tpwc_general")+(_unit getvariable "tpwc_originalcourage")) , 5]  
				};  
			}; 
           }; 

           //DISPLAY APPROPRIATE DEBUG BALLS
           if (tpwc_ai_sup_debug == 1) then 
               { 
               _ball1 = _unit getvariable "tpwc_sup1ball";   
               _ball2 = _unit getvariable "tpwc_sup2ball";   
               _ball3 = _unit getvariable "tpwc_sup3ball";  

               switch ( _unit getvariable "tpwc_suppressedstance" ) do 
                   { 
                   case 1:  
                       { 
                       tpwc_ballstatus = [_ball1, false, _ball2, true, _ball3, true]; 
                       }; 

                   case 2: 
                       { 
                       tpwc_ballstatus = [_ball1, true, _ball2, false, _ball3, true]; 
                       }; 

                   case 3: 
                       { 
                       tpwc_ballstatus = [_ball1, true, _ball2, true, _ball3, false]; 
                       }; 

                   default 
                       { 
                       tpwc_ballstatus = [_ball1, true, _ball2, true, _ball3, true]; 
                       }; 
                   }; 

               tpwc_ballstatus call 
			{
			(_this select 0) hideobject (_this select 1);
			(_this select 2) hideobject (_this select 3);
			(_this select 4) hideobject (_this select 5);
			};

               if ( isDedicated ) then 
                   { 
                   [-1, {(_this select 0) hideobject (_this select 1);(_this select 2) hideobject (_this select 3);(_this select 4) hideobject (_this select 5);}, tpwc_ballstatus] call CBA_fnc_globalExecute; 
                   }; 
               }; 
           };  
       } foreach allunits;   

       //REMOVE DEBUG BALLS FROM DEAD AI  
       if (tpwc_ai_sup_debug == 1) then  
           {  
               {  
                   _unit = _x;  
                   _ball1 = _unit getvariable "tpwc_sup1ball";  
                   if ( !(_ball1 == objNull) ) then   
                       {    
                       detach _ball1;   
                       deleteVehicle _ball1;  
                       _unit setvariable ["tpwc_sup1ball",nil];          
                       };  
                       _ball2 = _unit getvariable "tpwc_sup2ball";  
                   if ( !(_ball2 == objNull) ) then   
                       {    
                       detach _ball2;   
                       deleteVehicle _ball2;  
                       _unit setvariable ["tpwc_sup2ball",nil];          
                       };  
                       _ball3 = _unit getvariable "tpwc_sup3ball";  
                   if ( !(_ball3 == objNull) ) then   
                       {    
                       detach _ball3;   
                       deleteVehicle _ball3;  
                       _unit setvariable ["tpwc_sup3ball",nil];          
                       };  
               } foreach allDead;  
           };  
   sleep 1;      
   }  
};  

//BLUR PLAYER VISION WHEN SUPPRESSED  
tpwc_ai_sup_visuals =   
{  
if (tpwc_ai_sup_supvisflag == 0) then   
   { 
tpwc_ai_sup_supvisflag = 1;  	
_tint = ppEffectCreate ["Colorcorrections", 1552];  
   _tint ppEffectEnable true;  
   _blur = ppEffectCreate ["RadialBlur", 1551];  
   _blur ppEffectEnable true;  

_ppmodifier = 0.001;
{
_ppmod = _ppmodifier * _x;
_blur ppEffectAdjust [_ppmod,_ppmod,0.1,0.1]; 
_blur ppEffectCommit 0; 
_tint ppEffectAdjust[1, 1, (-5 * _ppmod), [0,0,0,0], [0,0,0,1], [0,0,0,1]];
_tint ppEffectCommit 0; 
sleep 0.1; 	
} foreach [1,2,3,4,5];
   sleep 5;  
{
_ppmod = _ppmodifier * _x;
_blur ppEffectAdjust [_ppmod,_ppmod,0.1,0.1]; 
_blur ppEffectCommit 0; 
_tint ppEffectAdjust[1, 1, (-5 * _ppmod), [0,0,0,0], [0,0,0,1], [0,0,0,1]];
_tint ppEffectCommit 0; 
sleep 0.1; 	
} foreach [5,4,3,2,1]; 
   ppEffectDestroy _blur;  
   ppEffectDestroy _tint;  
   tpwc_ai_sup_supvisflag = 0;  
   };  
};  

//IF ASR AI HAS SET UNIT SKILLS, MAKE THESE THE "ORIGINALS" FOR EACH UNIT    
tpwc_ai_sup_asrskills =   
{   
sleep 3;   
while {true} do    
   {   
       {   
       _unit = _x;   
       _asr = _unit getVariable "asr_ai_sys_aiskill_configured";   
       _skillset = _unit getVariable "tpwc_skillset";   
       if ((_asr) && !(_skillset))then    
           {   
           _unit setvariable ["tpwc_originalaccuracy", _unit skill "aimingaccuracy"];     
           _unit setvariable ["tpwc_originalshake", _unit skill "aimingshake"];    
           _unit setvariable ["tpwc_originalcourage", _unit skill "courage"];     
           _unit setvariable ["tpwc_general",_unit skill "general"];    
           _unit setvariable ["tpwc_skillset", true];   
           };   
       } foreach allunits;   
   sleep 30;   
   };   
};    

/////////////////  
// RUN IT  
/////////////////  
//BASIC MODE
if (tpwc_ai_sup_mode ==1) then 
{
[tpwc_ai_sup_basic,0] call cba_fnc_addPerFrameHandler;
};

//LITE MODE	
if (tpwc_ai_sup_mode ==2) then 
{
[tpwc_ai_sup_lite,0] call cba_fnc_addPerFrameHandler;
};	

//FULL MODE	
if (tpwc_ai_sup_mode ==3) then 
{	
//Spawn behaviour loop  
[] spawn tpwc_ai_sup_behaviour;   
sleep 1;  

//Spawn ASR_AI skill set loop if running ASR_AI > 1.15.1       
if (isclass (configfile >> "cfgPatches">>"asr_ai_sys_aiskill")) then    
	{   
	_asr_ai_va = getArray (configfile>>"cfgPatches">>"asr_ai_main">>"versionAr");  
	if (_asr_ai_va select 0 >= 1 && _asr_ai_va select 1 >= 15 && _asr_ai_va select 2 >= 1) then   
		{  
		[] spawn tpwc_ai_sup_asrskills;   
		};      
	};   

//Call time critical bullet detection loop  
[tpwc_ai_sup_detect,0] call cba_fnc_addPerFrameHandler;    
};
}; 

Edited by tpw

Share this post


Link to post
Share on other sites

Not seeing a single unitpos in that entire script. I am disappoint. :p A-so, setunitpos doesn't count.

Keep up the good work, gentlemans.

Share this post


Link to post
Share on other sites

Really great.

Can you update first post with the new script and addon version?

Share this post


Link to post
Share on other sites
Really great.

Can you update first post with the new script and addon version?

Just a little bit more polishing and I will

Share this post


Link to post
Share on other sites

Shaping up really nicely. Keep up the good work guys!

Regarding the camerashake, I always use the latest beta, and I do get the ground shaking as tanks go past. However the script fails when addCameraShake is present. Anyone else using the latest betas that get the same thing ?

Edited by Kremator

Share this post


Link to post
Share on other sites
Shaping up really nicely. Keep up the good work guys!

Regarding the camerashake, I always use the latest beta, and I do get the ground shaking as tanks go past. However the script fails when addCameraShake is present. Anyone else using the latest betas that get the same thing ?

I'm on 94209 and addcamerashake is fine.

Edited by tpw

Share this post


Link to post
Share on other sites

It may be some mod conflict.

Although I'm on latest beta, use ASR AI and ACE and I'm fine.

Share this post


Link to post
Share on other sites

So unfortunately there is some self suppression, especially in heavy fighting. but usually it is only light (green ball). I can look into trying to reduce sway from this type of suppression though.

The only thing I can think of to truly fix the problem would be to make it so that more than one unit can be tpwc_ai_sup_fired - so that instead of a single unit, an array of units can be there. But I am not sure if this is possible and how you would then take away a unit from the tpwc_sup_fired array so he can once again be suppressed.

Would it be possible to give the player unit a different variable (e.g., tpwc_P_sup_fired)? - then you could indeed use an array if you wanted to. Using switch early on to discriminate between player & AI might be useful to avoid slowing the script. Sorry, can't test today as I'm on mobile (& anyway I still maintain my claim to the title of shittiest coder in the thread).

Share this post


Link to post
Share on other sites

I'm having no problems with the latest beta and a swag of mods, ASR AI included. Not sure what it might be, Kremator.

Share this post


Link to post
Share on other sites
Would it be possible to give the player unit a different variable (e.g., tpwc_P_sup_fired)? - then you could indeed use an array if you wanted to. Using switch early on to discriminate between player & AI might be useful to avoid slowing the script. Sorry, can't test today as I'm on mobile (& anyway I still maintain my claim to the title of shittiest coder in the thread).

It's not actually possible to be self-suppressed, or by anyone less than 25m away.

if ((tpwc_ai_sup_fired distance _unit) > tpwc_ai_sup_ir) then

Translation: only if shooter distance from unit is greater than 25m then proceed with rest of suppression calculations.

---------- Post added at 21:27 ---------- Previous post was at 21:17 ----------

OK, last code post before bed.

I've done a bit more fiddling and refining, here's what's what

1 - Debug balls are now hidden on injured units (Ollem, please check that the dedi code is right for this)

2 - Only uninjured units can be suppressed (Thanks Fabrizio_T)

3 -I had to revert from

_unit setvehicleinit format ["this setunitpos 'whateverpos';"]; 
processinitcommands; 
clearVehicleInit _unit; 

to

_unit setunitpos "whateverpos"

as this was causing the player unit to occasionally not be able to fire. No idea why.

I was just thinking that part of the problem with dedi being less sensitive to bullets might be the bullet detection radius. When the whole thing is local, the 10m radius is sufficient to catch bullets. When running via dedi, the latency might mean that you need a bigger radius. Can someone check this out?

1.03 code:

/*   
TPWC AI SUPPRESSION   

Authors: TPW & -Coulum-   
Additional code: Fabrizio_T, Ollem  
Version: 1.03 
Last modified: 20120629
Requires: CBA
Disclaimer: Feel free to use and modify this code, on the proviso that you post back changes and improvements so that everyone can benefit from them, and acknowledge the original authors in any derivative works.
*/   

if (isServer || isDedicated) then {  

//Log it  
diag_log format ["TPWC AI SUPPRESS STARTED: Server: %1 - Dedicated: %2", isServer, isDedicated];  


////////////   
//VARIABLES   
///////////  

//Suppression mode. 1 = basic , 2 = light, 3 = full stance / skills modification.  
tpwc_ai_sup_mode = 3;  

//Delay before suppression functions start. 
tpwc_ai_sup_sleep = 5;

//Debugging. Will display coloured balls over any suppressed units. 0 = no debugging, 1 = debugging.
tpwc_ai_sup_debug = 1;

//Bullet detection radius (m). Bullets must pass within this distance of unit to suppress them. If set much below 10m, bullets may not be detected.
tpwc_ai_sup_br = 10;

//Bullet ignore radius (m). Bullets from a shooter closer than this will not suppress. 
tpwc_ai_sup_ir = 25;

//Shot threshold. More shots than this will cause unit to drop/crawl.
tpwc_ai_sup_st = 5;

//Pistol and SMG ammo to ignore. Add custom ammo (eg suppressed) or change to taste.    
tpwc_ai_sup_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"   
]; 

//Startup hint. 0 = no hint, 1 = hint.
tpwc_ai_sup_hint = 1; 

//Player suppression (shake and visuals). 0 = no suppression, 1 = suppression .   
tpwc_ai_sup_playersup = 1;


//////////   
// SET UP   
//////////   

//DECLARE PRIVATE VARIABLES   
private ["_stanceregain","_skillregain","_unit","_bc","_shots","_originalaccuracy","_originalshake","_originalcourage","_general","_ball","_ball1","_ball2","_ball3","_skillset","_asr","_tint","_blur","_x","_ppmod","_ppmodifier"];   

//WAIT
sleep tpwc_ai_sup_sleep;   

//START HINT      
if (tpwc_ai_sup_hint == 1) then {   
0 = [] spawn {  
hintsilent "TPWC AI Suppress 1.03 Active";   
sleep 3;   
hintsilent ""};   
};      


//////////////////   
// MAIN FUNCTIONS    
//////////////////    

//BASIC VERSION
tpwc_ai_sup_basic =     
{   
   {   
   if (alive _x) then    
       { 
       _unit = _x;      
       _stanceregain = _unit getvariable ["tpwc_stanceregain", -1];  

       if (_stanceregain == -1) then    
           {      
           _unit setvariable ["tpwc_stanceregain", diag_ticktime];  
           _unit addeventhandler ["fired",{tpwc_ai_sup_fired = _this select 0;tpwc_ai_sup_bullet = _this select 6}];   
           if (tpwc_ai_sup_debug == 1) then  
			{
			_ball = "Sign_sphere25cm_EP1" createvehicle getposatl _unit;
			_ball attachTo [_unit,[0,0,2]]; 
			_unit setvariable ["tpwc_supball",_ball];
			};
           };  

       if ( diag_ticktime >= _stanceregain) then    
           {  
           _ball = _unit getvariable "tpwc_supball"; _ball hideobject true;          
           _unit setvariable ["tpwc_supshots", 0];   
		_unit setunitpos "auto";
		_unit setvariable ["tpwc_suppressedstance", 0]; 
           _unit setvariable ["tpwc_stanceregain", diag_ticktime + 10];  
           };  

       if !(isnull tpwc_ai_sup_bullet) then    
           {   
           _bc = count ((getposatl _unit) nearobjects ["bulletbase",tpwc_ai_sup_br]);   
           if (_bc > 0) then    
               {  
               if ((tpwc_ai_sup_fired distance _unit) > tpwc_ai_sup_ir) then    
                   {   
                   _unit setvariable ["tpwc_stanceregain", diag_ticktime + 10];   
                   _shots = _unit getvariable "tpwc_supshots";   
                   _unit setvariable ["tpwc_supshots", _shots + _bc];   
                   _shots = _unit getvariable "tpwc_supshots";  
                   if ((_unit call CBA_fnc_getunitanim) select 0 != "prone") then 
					{	
					_unit setunitpos "middle";
					};
				_unit setvariable ["tpwc_suppressedstance", 1]; 
                   if (tpwc_ai_sup_debug == 1) then  
                       { 
                       _ball = _unit getvariable "tpwc_supball";_ball hideobject false; 
                       };             
                   if (_shots > tpwc_ai_sup_st) then   
                       {  
                       _unit setunitpos "down"; 
                       };   
                   };   
               };   
           };   
       };    
   } foreach allunits;   
};   

//LITE VERSION 
tpwc_ai_sup_lite =     
{    
   {   
   if ((alive _x) && (vehicle _unit == _unit) && (lifeState _unit == "ALIVE")) then    
       { 
       _unit = _x;      
       _stanceregain = _unit getvariable ["tpwc_stanceregain", -1];  

       if (_stanceregain == -1) then    
           {      
           _unit setvariable ["tpwc_stanceregain", diag_ticktime];  
           _unit addeventhandler ["fired",{tpwc_ai_sup_fired = _this select 0;tpwc_ai_sup_mag = _this select 5; tpwc_ai_sup_bullet = _this select 6}];   
           if (tpwc_ai_sup_debug == 1) then  
			{
			_ball = "Sign_sphere25cm_EP1" createvehicle getposatl _unit;
			_ball attachTo [_unit,[0,0,2]]; 
			_unit setvariable ["tpwc_supball",_ball];
			};			
           };  

       if ( diag_ticktime >= _stanceregain) then    
           {  
           _ball = _unit getvariable "tpwc_supball"; _ball hideobject true;              
           _unit setvariable ["tpwc_supshots", 0];   
           _unit setunitpos "auto";  
		_unit setvariable ["tpwc_suppressedstance", 0]; 
           _unit setvariable ["tpwc_stanceregain", diag_ticktime + 10];  
           };  

       if !(isnull tpwc_ai_sup_bullet) then    
           {   
           _bc = count ((getposatl _unit) nearobjects ["bulletbase",tpwc_ai_sup_br]);   
           if (_bc > 0) then    
               {  
               if ((tpwc_ai_sup_fired distance _unit) > tpwc_ai_sup_ir) then    
                   {   
                   if !(tpwc_ai_sup_mag in tpwc_ai_sup_mags) then    
                       {  
                       _unit setvariable ["tpwc_stanceregain", diag_ticktime + 10];   
                       _shots = _unit getvariable "tpwc_supshots";   
                       _unit setvariable ["tpwc_supshots", _shots + _bc];   
                       if ((_unit call CBA_fnc_getunitanim) select 0 != "prone") then 
						{	
						_unit setunitpos "middle";
						};
					_unit setvariable ["tpwc_suppressedstance", 1]; 						
                       if (side tpwc_ai_sup_fired != side _unit) then    
                           { 
                           _shots = _unit getvariable "tpwc_supshots";  
                           if (tpwc_ai_sup_debug == 1) then  
                               { 
                               _ball = _unit getvariable "tpwc_supball";_ball hideobject false; 
                               }; 
                           if (_shots > tpwc_ai_sup_st) then   
                               {  
                               _unit setunitpos "down";
                               };   
                           };    
                       };   
                   };   
               };   
           };   
       };    
   } foreach allunits;   
};   

//BULLET DETECTION LOOP (TIME CRITICAL)  
//Do not touch this please  
tpwc_ai_sup_detect =        
{       
   {      
   _unit = _x; 
   if (!(isnull tpwc_ai_sup_bullet) && (vehicle _unit == _unit) && (lifeState _unit == "ALIVE")) then       
       {      
       _bc = count ((getposatl _unit) nearobjects ["bulletbase",tpwc_ai_sup_br]);      
       if (_bc > 0) then       
           {     
           if ((tpwc_ai_sup_fired distance _unit) > tpwc_ai_sup_ir) then       
               {      
               if !(tpwc_ai_sup_mag in tpwc_ai_sup_mags) then       
                   {     
                   _unit setvariable ["tpwc_skillregain", diag_ticktime + (random 4)-((_unit getvariable "tpwc_general")+(_unit getvariable "tpwc_originalcourage"))];       
                   _unit setvariable ["tpwc_stanceregain", diag_ticktime + 10];      
                   _unit setvariable ["tpwc_supshots",(_unit getvariable "tpwc_supshots") + _bc];      
                   _unit setvariable ["tpwc_suppressedstance", 1];  
                   if (side tpwc_ai_sup_fired != side _unit) then  
                       {  
                       _unit setvariable ["tpwc_suppressedstance", 2];                              
                       if (_unit getvariable "tpwc_supshots" > tpwc_ai_sup_st) then      
                           {  
                           _unit setvariable ["tpwc_suppressedstance", 3];                                  
                           };      
                       };       
                   };      
               };      
           };      
       };      
   } foreach allunits;      
};      

//UNIT STANCE/SKILL MODIFICATION LOOP (NON TIME CRITICAL)  
tpwc_ai_sup_behaviour =   
{  
tpwc_ai_sup_supvisflag = 0;  
while {true} do   
   {  
       {  
       if (alive _x) then   
           {  
           _unit  = _x; 
           _skillregain = _unit getvariable ["tpwc_skillregain", -1];       
           _stanceregain = _unit getvariable ["tpwc_stanceregain", -1]; 

           //SET INITIAL PARAMETERS FOR EACH UNIT  
           if (_stanceregain == -1) then       
               {   
               _unit setvariable ["asr_ai_sys_aiskill_configured", false];    
               _unit setvariable ["tpwc_skillset", false];    
               _unit setvariable ["tpwc_combatmode", "unchanged"];   
               _unit setvariable ["tpwc_originalaccuracy", _unit skill "aimingaccuracy"];     
               _unit setvariable ["tpwc_originalshake",  _unit skill "aimingshake"];    
               _unit setvariable ["tpwc_originalcourage", _unit skill "courage"];     
               _unit setvariable ["tpwc_general", _unit skill "general"];    
               _unit setvariable ["tpwc_stanceregain", diag_ticktime];     
               _unit setvariable ["tpwc_skillregain", diag_ticktime]; 
               _unit addeventhandler ["fired",{tpwc_ai_sup_fired = _this select 0;tpwc_ai_sup_mag = _this select 5; tpwc_ai_sup_bullet = _this select 6}];      
               if ( ( assignedVehicleRole _unit) select 0 == "Turret"  ) then   
                   {  
                   (vehicle _unit) addeventhandler ["fired",{tpwc_ai_sup_fired = _this select 0;tpwc_ai_sup_mag = _this select 5; tpwc_ai_sup_bullet = _this select 6}];   
                   };  
               if (tpwc_ai_sup_debug == 1) then     
                   { 
                   _ball1 = "Sign_sphere25cm_EP1" createvehicle getposatl _unit;  
                   _ball1 setObjectTexture [0,"#(argb,8,8,3)color(0.2,0.9,0.2,0.5,ca)"];  
                   _ball1 attachTo [_unit,[0,0,2]];   
                   _unit setvariable ["tpwc_sup1ball",_ball1]; 
                   _ball1 hideobject true;  

                   _ball2 = "Sign_sphere25cm_EP1" createvehicle getposatl _unit;  
                   _ball2 setObjectTexture [0,"#(argb,8,8,3)color(0.6,0.9,0.0,0.7,ca)"]; //yellow  
                   _ball2 attachTo [_unit,[0,0,2]];   
                   _unit setvariable ["tpwc_sup2ball",_ball2]; 
                   _ball2 hideobject true;  

                   _ball3 = "Sign_sphere25cm_EP1" createvehicle getposatl _unit;  
                   _ball3 setObjectTexture [0,"#(argb,8,8,3)color(0.8,0.5,0.5,0.5,ca)"]; //red  
                   _ball3 attachTo [_unit,[0,0,2]];   
                   _unit setvariable ["tpwc_sup3ball",_ball3]; 
                   _ball3 hideobject true;                       
                   };  
               };   

           //IF UNIT SKILLS ARE UNSUPPRESSED  
           if (diag_ticktime >= _skillregain) then      
               {  
               _originalaccuracy = _unit getvariable "tpwc_originalaccuracy";        
               _originalshake = _unit getvariable "tpwc_originalshake";                 
               _originalcourage = _unit getvariable "tpwc_originalcourage";     
               _general = _unit getvariable "tpwc_general";           
               if((_unit skill "aimingaccuracy") < _originalaccuracy) then      
                   {    
                   _unit setskill ["aimingaccuracy",(_unit skill "aimingaccuracy")+((_originalaccuracy-(_unit skill "aimingaccuracy"))*.325)];       
                   };     
               if((_unit skill "aimingshake") < _originalshake) then      
                   {      
                   _unit setskill ["aimingshake",(_unit skill "aimingshake")+((_originalshake-(_unit skill "aimingshake"))*.325)];      
                   };    
               };  

           //IF UNIT STANCE IS UNSUPPRESSED  
           if ( diag_ticktime >= _stanceregain) then       
               { 
               _unit setvariable ["tpwc_supshots", 0];      
               _unit setunitpos "auto";					
               _originalcourage = _unit getvariable "tpwc_originalcourage";     
               _general = _unit getvariable "tpwc_general"; 
               _unit setvariable ["tpwc_suppressedstance", 0]; 
               if((_unit skill "courage") < (_originalcourage - 0.1)) then      
                   {      
                   _unit setskill ["courage",(_unit skill "courage")+(_general)*(0.1)];       
                   }     
                   else    
                   {    
                   if (_unit getvariable "tpwc_combatmode" != "unchanged") then   
                       {  
                       _unit setbehaviour str(_unit getvariable "tpwc_combatmode");  
                       _unit setvariable ["tpwc_combatmode", "unchanged"];   
                       };  
                   };    
               };     

		//UNIT CHANGES FOR DIFFERENT SUPPRESSION
           switch ( _unit getvariable "tpwc_suppressedstance" ) do 
           { 
		case 1: //IF ANY BULLETS NEAR UNIT 
			{ 
			_unit setunitpos "middle";	
			}; 

		case 2: //IF ENEMY BULLETS NEAR UNIT 
			{
			if ((_unit call CBA_fnc_getunitanim) select 0 != "prone") then 
				{	
				_unit setunitpos "middle";	
				};
			_unit setvariable ["tpwc_combatmode", behaviour _unit];   
			if( !( behaviour _unit in ["COMBAT", "STEALTH"] ) ) then   
				{  
				_unit setbehaviour "COMBAT";   
				};      
			_originalaccuracy = _unit getvariable "tpwc_originalaccuracy";       
			_originalshake = _unit getvariable "tpwc_originalshake";     
			_originalcourage = _unit getvariable "tpwc_originalcourage";      
			_general = _unit getvariable "tpwc_general";    
			_shots = _unit getvariable "tpwc_supshots";    
			if (diag_ticktime < _skillregain) then   
			{         
			_unit setskill ["aimingaccuracy",_originalaccuracy*_originalcourage*_general-(_shots*(1-_general)*((_unit skill "aimingaccuracy")-.1)*.025)];        
			_unit setskill ["aimingshake",_originalshake*_originalcourage*_general-(_shots*(1-_general)*((_unit skill "aimingshake")-.1)*.025)];       
			_unit setskill ["courage",(_unit skill "courage")-(_shots*(1-_general)*(1-_originalcourage)*((_unit skill "courage")-.1)*.1)];   
			};  
			if ((_unit == player) and (tpwc_ai_sup_playersup == 1) and (diag_ticktime < _skillregain)) then   
				{   
				addCamShake [1.5 - (skill player),(random 4)-((_unit getvariable "tpwc_general")+(_unit getvariable "tpwc_originalcourage")) , 2.5]  
				};
			}; 

		case 3: //IF UNIT IS SUPPRESSED WITH MORE THAN 5 ENEMY BULLETS  
			{ 
			_unit setunitpos "down";	
			_unit forcespeed -1; 
			_unit setvariable ["tpwc_combatmode", behaviour _unit];  
			if( !( behaviour _unit in ["COMBAT", "STEALTH"] ) ) then   
				{  
				_unit setbehaviour "COMBAT";   
				}; 
			_originalaccuracy = _unit getvariable "tpwc_originalaccuracy";       
			_originalshake = _unit getvariable "tpwc_originalshake";     
			_originalcourage = _unit getvariable "tpwc_originalcourage";      
			_general = _unit getvariable "tpwc_general";    
			_shots = _unit getvariable "tpwc_supshots";    
			if (diag_ticktime < _skillregain) then   
				{         
				_unit setskill ["aimingaccuracy",_originalaccuracy*_originalcourage*_general-(_shots*(1-_general)*.003)];        
				_unit setskill ["aimingshake",_originalshake*_originalcourage*_general-(_shots*(1-_general)*.003)];       
				_unit setskill ["courage",(_unit skill "courage")-(_shots*(1-_general)*(1-_originalcourage)*.07)];   
				};  
			if ((isPlayer _unit) and (tpwc_ai_sup_playersup == 1) and (diag_ticktime < _skillregain)) then   
				{  
				[] spawn tpwc_ai_sup_visuals;  
				addCamShake [2 - (skill _unit),(random 6)-((_unit getvariable "tpwc_general")+(_unit getvariable "tpwc_originalcourage")) , 5]  
				};  
			}; 
           }; 

           //DISPLAY APPROPRIATE DEBUG BALLS
           if (tpwc_ai_sup_debug == 1) then 
               { 
               _ball1 = _unit getvariable "tpwc_sup1ball";   
               _ball2 = _unit getvariable "tpwc_sup2ball";   
               _ball3 = _unit getvariable "tpwc_sup3ball";  

               switch ( _unit getvariable "tpwc_suppressedstance" ) do 
                   { 
                   case 1:  
                       { 
                       tpwc_ballstatus = [_ball1,false,_ball2,true,_ball3,true]; 
                       }; 
                   case 2: 
                       { 
                       tpwc_ballstatus = [_ball1,true,_ball2,false,_ball3,true]; 
                       }; 
				case 3: 
                       { 
                       tpwc_ballstatus = [_ball1,true,_ball2,true,_ball3,false]; 
                       }; 
				default 
                       { 
                       tpwc_ballstatus = [_ball1,true,_ball2,true,_ball3,true]; 
                       }; 
                   }; 
			tpwc_ballstatus call 
			{
			(_this select 0) hideobject (_this select 1);
			(_this select 2) hideobject (_this select 3);
			(_this select 4) hideobject (_this select 5);
			};

               if ( isDedicated ) then 
                   { 
                   [-1, {(_this select 0) hideobject (_this select 1);(_this select 2) hideobject (_this select 3);(_this select 4) hideobject (_this select 5);}, tpwc_ballstatus] call CBA_fnc_globalExecute; 
                   }; 
               }; 
           };  
       } foreach allunits;   

       if (tpwc_ai_sup_debug == 1) then  
           {  
		//REMOVE DEBUG BALLS FROM DEAD AI  
			{  
                   _unit = _x;  
                   _ball1 = _unit getvariable "tpwc_sup1ball";  
                   if ( !(_ball1 == objNull) ) then   
                       {    
                       detach _ball1;   
                       deleteVehicle _ball1;  
                       _unit setvariable ["tpwc_sup1ball",nil];          
                       };  
                       _ball2 = _unit getvariable "tpwc_sup2ball";  
                   if ( !(_ball2 == objNull) ) then   
                       {    
                       detach _ball2;   
                       deleteVehicle _ball2;  
                       _unit setvariable ["tpwc_sup2ball",nil];          
                       };  
                       _ball3 = _unit getvariable "tpwc_sup3ball";  
                   if ( !(_ball3 == objNull) ) then   
                       {    
                       detach _ball3;   
                       deleteVehicle _ball3;  
                       _unit setvariable ["tpwc_sup3ball",nil];          
                       };  
               } foreach allDead;  

		//HIDE DEBUG BALLS FROM INJURED UNITS
		if (lifestate _unit != "ALIVE") then		
			{
			_ball1 = _unit getvariable "tpwc_sup1ball";
			_ball2 = _unit getvariable "tpwc_sup2ball";
			_ball3 = _unit getvariable "tpwc_sup3ball";
			_ball1 hideobject true; 
			_ball2 hideobject true; 
			_ball3 hideobject true;
			if ( isDedicated ) then 
                   { 
                   [-1, {(_this select 0) hideobject true;(_this select 2) hideobject true;(_this select 4) hideobject true;}, tpwc_ballstatus] call CBA_fnc_globalExecute; 
                   }; 				
			};	
           };  
   sleep 1.5;      
   }  
};  

//BLUR PLAYER VISION WHEN SUPPRESSED  
tpwc_ai_sup_visuals =   
{  
if (tpwc_ai_sup_supvisflag == 0) then   
   { 
tpwc_ai_sup_supvisflag = 1;  	
_tint = ppEffectCreate ["Colorcorrections", 1552];  
   _tint ppEffectEnable true;  
   _blur = ppEffectCreate ["RadialBlur", 1551];  
   _blur ppEffectEnable true;  
_ppmodifier = 0.001;

	{
	_ppmod = _ppmodifier * _x;
	_blur ppEffectAdjust [_ppmod,_ppmod,0.1,0.1]; 
	_blur ppEffectCommit 0; 
	_tint ppEffectAdjust[1, 1, (-5 * _ppmod), [0,0,0,0], [0,0,0,1], [0,0,0,1]];
	_tint ppEffectCommit 0; 
	sleep 0.1; 	
	} foreach [1,2,3,4,5];

sleep 5;  

	{
	_ppmod = _ppmodifier * _x;
	_blur ppEffectAdjust [_ppmod,_ppmod,0.1,0.1]; 
	_blur ppEffectCommit 0; 
	_tint ppEffectAdjust[1, 1, (-5 * _ppmod), [0,0,0,0], [0,0,0,1], [0,0,0,1]];
	_tint ppEffectCommit 0; 
	sleep 0.1; 	
	} foreach [5,4,3,2,1]; 

ppEffectDestroy _blur;  
   ppEffectDestroy _tint;  
   tpwc_ai_sup_supvisflag = 0;  
   };  
};  

//IF ASR AI HAS SET UNIT SKILLS, MAKE THESE THE "ORIGINALS" FOR EACH UNIT    
tpwc_ai_sup_asrskills =   
{   
sleep 3;   
while {true} do    
   {   
       {   
       _unit = _x;   
       _asr = _unit getVariable "asr_ai_sys_aiskill_configured";   
       _skillset = _unit getVariable "tpwc_skillset";   
       if ((_asr) && !(_skillset))then    
           {   
           _unit setvariable ["tpwc_originalaccuracy", _unit skill "aimingaccuracy"];     
           _unit setvariable ["tpwc_originalshake", _unit skill "aimingshake"];    
           _unit setvariable ["tpwc_originalcourage", _unit skill "courage"];     
           _unit setvariable ["tpwc_general",_unit skill "general"];    
           _unit setvariable ["tpwc_skillset", true];   
           };   
       } foreach allunits;   
   sleep 30;   
   };   
};    


/////////////////  
// RUN IT  
/////////////////  

//BASIC MODE
if (tpwc_ai_sup_mode ==1) then 
{
[tpwc_ai_sup_basic,0] call cba_fnc_addPerFrameHandler;
};

//LITE MODE	
if (tpwc_ai_sup_mode ==2) then 
{
[tpwc_ai_sup_lite,0] call cba_fnc_addPerFrameHandler;
};	

//FULL MODE	
if (tpwc_ai_sup_mode ==3) then 
{	
//Spawn behaviour loop  
[] spawn tpwc_ai_sup_behaviour;   
sleep 1;  

//Spawn ASR_AI skill set loop if running ASR_AI > 1.15.1       
if (isclass (configfile >> "cfgPatches">>"asr_ai_sys_aiskill")) then    
	{   
	_asr_ai_va = getArray (configfile>>"cfgPatches">>"asr_ai_main">>"versionAr");  
	if (_asr_ai_va select 0 >= 1 && _asr_ai_va select 1 >= 15 && _asr_ai_va select 2 >= 1) then   
		{  
		[] spawn tpwc_ai_sup_asrskills;   
		};      
	};   

//Call time critical bullet detection loop  
[tpwc_ai_sup_detect,0] call cba_fnc_addPerFrameHandler;    
};
};

,

Share this post


Link to post
Share on other sites

1 - Debug balls are now hidden on injured units (Ollem, please check that the dedi code is right for this)

Gave it a quick try, but injured units were still showing debug balls.. not sure about unconcious..

Current code has only 2 options on Dedicated: no balls and red balls => I will look into this

I was just thinking that part of the problem with dedi being less sensitive to bullets might be the bullet detection radius. When the whole thing is local, the 10m radius is sufficient to catch bullets. When running via dedi, the latency might mean that you need a bigger radius. Can someone check this out?

I tested with detection radius of 20 meters and shot threshold of 3 bullets, and the results were hopeful: again still not as responsive as SP, but for sure much more natural effect compared to no TWPC-Suppress :cool:

Needs some fine tuning for best settings.

CVhxZRBlLl0

Also for Dedicated server I might add 'player only' option to only enable the 'fired' eventhandler for players - I usually play coop versus AI - so then there's no need for AI Eventhandlers.

On Dedicated I did not notice the 'player shake' anyway, though I'm running latests beta.

Edited by Ollem

Share this post


Link to post
Share on other sites
I still maintain my claim to the title of shittiest coder in the thread).

*raises hand*

Many people are glad to support you, as you notice.

That's because you all (You, Coulum, Ollem, ...) are doing a great work.

Simple as that. Keep it going.

Quoted for Truth

@twp/coulum - you've probably had offers already but if MP testing is needed with a group of players I can offer a dedicated server and warm bodies

Edited by SavageCDN

Share this post


Link to post
Share on other sites
Can someone check this out?

I've been having a lot of fun with this combined with the Line of Sight script and ASR AI - well done. I have only tested in Invasion 44 which tends to have shorter engagement ranges.

In Single Player 1.03 copied out of your post, there seemed to be a little more of a performance hit than in the previous version - just a slightly laggier feel that I didn't get on the previous version. I reverted to the previous and it seemed to be 1 or 2 FPS quicker in similar circumstances (which, in a very intense scene, was about a 10% difference).

No errors in the RPT.

Level 3 suppression.

Beta 94209

Also, in 1.03, I experienced a few instances of not being able to fire which I hadn't had before.

This was on a 2500k overclocked to 4.7Ghz, Nvidia 580, with about 25 five to eight man groups, largely CQB in a built up area.

JJ

Edited by jiltedjock

Share this post


Link to post
Share on other sites
Quoted for Truth

+1

Also, I confirm the occasional inability to fire with 1.03; running with latest LOS pbo, asr_ai 1.15.1; using beta 94209. Not too much of an issue, hit the trigger again immediately & the weapon fires.

Did try this with the 3rd 'real' Harvest Red mission and hit big trouble:

after Reaper 1 called for support I headed towards the factory to take out the sniper. When I got near the large round towers (silos?) the FPS dropped to ~7 then 2 then the game froze. Had to use task manger to restart the PC. Reproducible, However, I suspect that this is a heavily scripted mission. Will test a few more offical & user missions/campaigns during the next week or two, since my 14-18 hrs/day work stint is over

Gameplay is soooo much better with this combination. Wheee!

Share this post


Link to post
Share on other sites
Gave it a quick try, but injured units were still showing debug balls.. not sure about unconcious..

The code i suggested was aimed to handle exclusively the unconscious state.

Wounded units do need to be suppresed in my opinion.

However looks like we have to skip also units who can't stand anymore (because of wounded legs).

So:

if (!(isnull tpwc_ai_sup_bullet) && (vehicle _unit == _unit) && (lifeState _unit == "ALIVE")) then 

will become:

if (!(isnull tpwc_ai_sup_bullet) && (vehicle _unit == _unit) && (lifeState _unit == "ALIVE") && canStand _unit ) then 

It may be debatable whether these legs-wounded units should skip being suppressed altogether (as per-example) or just for the stance handling part.

Probably the latter solution would be better?

If so then leave the above original code unchanged and edit:

if !(tpwc_ai_sup_mag in tpwc_ai_sup_mags) then 

to:

if ( !(tpwc_ai_sup_mag in tpwc_ai_sup_mags) && canStand _unit ) then 

Finally: there is a problem with:

if (side tpwc_ai_sup_fired != side _unit) then 

The problem is it does not take in account other friendly sides, so you may end up being suppressed by allies.

In this case it would suffice to change to:

if ( ( side tpwc_ai_sup_fired ) getFriend ( side _unit) < 0.6 ) then 

Edited by fabrizio_T
ortho

Share this post


Link to post
Share on other sites
The code i suggested was aimed to handle exclusively the unconscious state.

Wounded units do need to be suppresed in my opinion.

However looks like we have to skip also units who can't stand anymore (because of wounded legs).

So:

if (!(isnull tpwc_ai_sup_bullet) && (vehicle _unit == _unit) && (lifeState _unit == "ALIVE")) then 

will become:

if (!(isnull tpwc_ai_sup_bullet) && (vehicle _unit == _unit) && (lifeState _unit == "ALIVE") && canStand _unit ) then 

Using COSLX, prone injured units will occasionally lob a grenade at you (quite accurately, too if their arms aren't damaged) so keeping them pinned may not be such a bad idea. Perhaps it could be a config option?

Share this post


Link to post
Share on other sites

A notice: in tpwc_ai_sup_basic part of the initial IF statement is missing, compared to tpwc_ai_sup_lite. Unintentional i bet.

Share this post


Link to post
Share on other sites
Guest
This topic is now closed to further replies.
Sign in to follow this  

×