Jump to content
Sign in to follow this  
tpw

TPWC AI suppression system

Recommended Posts

Did some more testing (with bdetect.sqf v0.5) and encountered a very weird issue I can't explain yet:

if shooter > +/- 400 m (+/- 385 to be precise) away from _unit being shot, it's not the _unit who is put in the _data array but the _shooter.. ???

changed some settings: bdetect_bullet_max_distance = 800 up to 1200, and changed live_time from 0.5 to 0.7 but it's still the same..

Is it just for me?

Increase bullet_max_distance and add the following debug line to 'bdetect_fnc_detect' function:

..........................
                else
               {
                   _units = _bullet nearObjects ["MAN", bdetect_min_distance];

				diag_log format ["%1 - UNITS : %2", diag_ticktime, _units];

                   {
                       if( alive _x && vehicle _x == _x && lifestate _x == "ALIVE") then
..........................

===== update =========

With v0.6 code still the same behaviour - though now no units at all at larger dist

Distance at which the issue occurs has decreased though..

Edited by Ollem
tested with v0.6

Share this post


Link to post
Share on other sites

Sorry, i didn't understand well the problem, need some more info.

Please ( within v0.6 ) try outputting variables into your bdetect_fnc_callback and please tell which datum is wrong.

Here is the commented function model:

bdetect_fnc_callback = 
{
private [ "_unit", "_bullet", "_proximity", "_data", "_shooter", "_pos", "_time", "_msg" ];

_unit = _this select 0;		// unit being under fire
_bullet = _this select 1;	// bullet object
_proximity = _this select 2;	// distance between _bullet and _unit
_data = _this select 3;		// Array containing more data

_shooter = _data select 0; // shooter
_pos = _data select 1;	// starting position of bullet
_time = _data select 2; // starting time of bullet

_msg = format["[%1] close to bullet %2 fired by %3, proximity=%4m, data=%5", _unit, _bullet, _shooter, _proximity, _data];
[ _msg, 9 ] call bdetect_fnc_debug;
};

Of course debug should be:

bdetect_debug_enable = true;
bdetect_debug_levels = [9];

In v0.6 "levels" of debug are classified this way:

DEBUG LEVELS: 
From 0-9 are reserved.

0 = unclassified messages
1 = FPS related messages
2 = "bdetect_fired_bullets" related messages
3 = EH related messages
4 = Frame related messages
5 = Unit blacklist messages
...
9 = Unit detection related messages

So you may write for instance:

bdetect_debug_levels = [2,9];

To output also "bdetect_fired_bullets" stuff.

EDIT:

Possibily both the shooter and the unit end up in the bdetect_fired_bullets array. That would make sense to me.

May happen with v0.5, but it should not happen in v0.6 ad long as bdetect_bullet_max_proximity < bdetect_bullet_min_distance.

Let me know if that's the case.

EDIT2:

Double checked code and tried to reproduce in v0.61 (which is 99.9% identical to v0.6), but couldn't.

With default settings:

bdetect_bullet_max_distance = 400;

bdetect_bullet_max_lifespan = 0.5;

i was able to have a bullet detected at 390m.

Units are correct.

"3.539 [bDetect v0.61] Frame:18288 L2: bullet 17518: tracer_red.p3d added"
"3.539 [bDetect v0.61] Frame:18288 L2: [b 1-1-A:1 (minime4)] Found bullet: speed=3240, type=B_762x51_noTracer, Delay=0"
"4.012 [bDetect v0.61] Frame:18312 L9: my_suppression_function - [O 1-1-A:1] close to bullet 17518: tracer_red.p3d fired by B 1-1-A:1 (minime4), proximity=5.97223m, data=[b 1-1-A:1 (minime4),[3326.31,3615.58,20.4838],390.055,[]]"
"4.052 [bDetect v0.61] Frame:18314 L2: null/expired bullet removed"

Edited by fabrizio_T

Share this post


Link to post
Share on other sites

Seems like very nice addon. I am trying to include the script version in my mission, but when there is bullets flying I get this error:

Error in expression <ata = _this select 2; 
_shooter = _data select 0; 
_shooterdistance = _shooter d>
 Error position: <select 0; 
_shooterdistance = _shooter d>
 Error Generic error in expression
File C:\Users\Santeri\Documents\ArmA 2\missions\NAPAmission.Chernarus\tpwc_ai_suppress.sqf, line 417
"106.611 [bDetect v0.6] Frame:64572 L2: null/expired bullet removed"

With new CBA (1 or 2 week old version), I am using the tpwc_ai_suppress.sqf v2.00 and bdetect.sqf v0.6. I am doing something wrong?

Share this post


Link to post
Share on other sites
Seems like very nice addon. I am trying to include the script version in my mission, but when there is bullets flying I get this error:

Error in expression <ata = _this select 2; 
_shooter = _data select 0; 
_shooterdistance = _shooter d>
 Error position: <select 0; 
_shooterdistance = _shooter d>
 Error Generic error in expression
File C:\Users\Santeri\Documents\ArmA 2\missions\NAPAmission.Chernarus\tpwc_ai_suppress.sqf, line 417
"106.611 [bDetect v0.6] Frame:64572 L2: null/expired bullet removed"

With new CBA (1 or 2 week old version), I am using the tpwc_ai_suppress.sqf v2.00 and bdetect.sqf v0.6. I am doing something wrong?

Hi, please don't mix bDetect v0.6 with TPWC_AI_SUPPRESS v.200.

bDetect v0.6 was released today and it's not completely backward compatible with v0.51, which was bundled with most recent TPWC_AI_SUPPRESS package to date.

Differences are minor, but do exist.

It's my fault, sorry, not tpw one: i had to redefine / modify some underlying variables in bdetect to clean up code.

I am positive that tpw will be able to hook latest bdetect version soon.

EDIT

Since i caused this problem i'll try to solve it.

For bDetect v0.6 to work with TPWC_AI_SUPPRESS v.200:

Try to overwrite function tpwcas_fnc_localbullets in tpwc_ai_suppress.sqf with the following updated code:

tpwcas_fnc_localbullets = 
{
private [ "_unit", "_distance", "_data", "_shooter","_shooterdistance","_shooterside"];

_unit = _this select 0; //suppressed unit
_distance = _this select 2; //distance of bullet from unit
_data = _this select 3; //
_shooter = _data select 0; //shooter
_shooterdistance = _shooter distance _unit; //distance of shooter from unit
_shooterside = side _shooter; //side of shooter
_bc = _unit getvariable "tpwcas_bc"; //total bullet count
_ebc = _unit getvariable "tpwcas_ebc"; //enemy bullet count

if (_shooterdistance >= tpwcas_ir) then 
{
	_bc = _bc + 1;
	_unit setvariable ["tpwcas_skillregain", diag_ticktime + 2 + random 3];       
	_unit setvariable ["tpwcas_stanceregain", diag_ticktime + 5 + random 5];  
	_unit setvariable ["tpwcas_bc", _bc];
	_unit setvariable ["tpwcas_supstate",1];

	if (_shooterside getFriend ( side _unit) < 0.6 ) then 
	{
		_ebc = _ebc + 1;
		_unit setvariable ["tpwcas_ebc", _ebc];
		_unit reveal [_shooter, 3];
	};

	if (_ebc > 0) then 
	{
		_unit setvariable ["tpwcas_supstate",2];
	};

	if (_ebc > tpwcas_st) then 
	{
		_unit setvariable ["tpwcas_supstate",3];
	};		
};
};

Edited by fabrizio_T

Share this post


Link to post
Share on other sites

Hey... having a weird problem, i play the newest version 2.00 and when the ai gets in a firefight, they tends to look up in the sky and not on the enemy. i have tried only with twp supp mod + cba??

Share this post


Link to post
Share on other sites

Thanks, fabrizio_T. That seemed to fix the error. Working now so far great. :)

Share this post


Link to post
Share on other sites
Thanks, fabrizio_T. That seemed to fix the error. Working now so far great. :)

Sorry for the problem SaOK.

Share this post


Link to post
Share on other sites

Tried again but still same issue occurs in "bdetect_fnc_detect" function

To debug, I've added at line 286, right between

 _units = _bullet nearObjects ["MAN", bdetect_bullet_max_proximity];

and

{
                           if( !(_x in _blacklist) ) then
                           {
                               if( alive _x && vehicle _x == _x && lifestate _x == "ALIVE") then 

the following debug logging:

			if ( (count _units) > 0 ) then 
				{				
				hint format ["DIST: %1",(_units select 0) distance player];		
				diag_log format ["%1 - DIST: %2 - UNITS: %3", diag_ticktime, (_units select 0) distance player, _units];
				};	

If I then engage an enemy squad with a short MG burst at around 370 m distance, I get the following result:

The (filtered) log shows entries like:

"32607.3 - DIST: 353.572 - UNITS: [O 1-1-B:5,O 1-1-B:4]"

"32608.8 - DIST: 0 - UNITS: [b 1-1-A:1 (ollem)]"

"32611.2 - DIST: 0 - UNITS: [b 1-1-A:1 (ollem)]"

"32612.9 - DIST: 0 - UNITS: [b 1-1-A:1 (ollem)]"

"32613.1 - DIST: 0 - UNITS: [b 1-1-A:1 (ollem)]"

"32613.4 - DIST: 361.813 - UNITS: [O 1-1-B:4,O 1-1-B:5]"

"32613.6 - DIST: 357.14 - UNITS: [O 1-1-B:5]"

So above a certain distance,

_units = _bullet nearObjects ["MAN", bdetect_bullet_max_proximity]

suddenly only finds the shooter in stead of units near the bullet ????

(NOTE: this is while testing on MP - Locally hosted server with no other clients connected)

Edited by Ollem

Share this post


Link to post
Share on other sites

Ollem,

post the whole mission please.

EDIT: i see it's MP. I would suspect _bullet is not existing anymore (locality issue), but i'm not really expert in MP stuff ... so far i developed code for SP only,

Try logging also bullet object and its position.

By the way, are you executing bdetect within a "isServer" statement block ?

Edited by fabrizio_T

Share this post


Link to post
Share on other sites

No, I've not yet tried to execute within isServer block - unfortunatley not behind my gamesystem now

Local server is quite close to SP - e.g. 'player' variable is showing my username - unlike at dedicated server.

As additional debug I added some bullet markers:

_bulletMarker 'createMakerLocal [str(time), getPosASL _bullet];

_bulletMarker setMarkerShapeLocal "ICON";

_bulletMarker setMarkerTypeLocal "dot";

( placed right after the code line "[_x, _bullet, _x distance _bullet, _data] call bdetect_callback_compiled;" )

To my surprise the dots allways appear quite close the shooter - I would have expected them to appear close the target unit..

------ update -----

How/when is the position of a bullet determined?

A bullet is flying and on a fast system might be detected more then once.

If system is fast (mine is above average) the detection could be in early stage already...?

Edited by Ollem

Share this post


Link to post
Share on other sites

Ollem,

speaking of bDetect v0.6x, here's the whole flow:

Let's start checking bdetect_bullet_min_distance value. Default is 25 meters.

That means no bullet should be detected closer than 25 meters to the shooter.

Flight of any bullet is tracked on a per-frame basis (roughly each 0.01-0.02 seconds), from bdetect_bullet_min_distance till bdetect_bullet_max_distance or bdetect_bullet_max_lifespan is reached, unless bullet impacts somewhere (!alive) or goes higher than "bdetect_bullet_max_height" meters while diverging from ground.

Now consider bdetect_bullet_max_proximity value: default is 10 meters,

That's how far (at maximum) a bullet should be to any unit in order to be detected.

NOTE: If the bullet is tracked from 25 meters onwards and for a 10 meters radius that would implicitly the possibility for the shooter to "detect" its own bullet.

When a bullet comes within bdetect_bullet_max_proximity meters to any healthy units on foot, detection is triggered.

As it's technically possible for a bullet being detected many times within that same 10 meters radius (if the PC is fast enough), the framework blacklists the tuple bullet-unit after first detection, so it won't happen again.

You can check the blacklist log by adding 5 to "bdetect_debug_levels", so you'll be notified about blacklisting events.

---

Try running bDetect v0.61 (below), since:

* It explicitly block the possibility for the shooter to detect own shots.

* It tracks a lot of info about bullets path.

Also changed:

 _units = _bullet  nearObjects ["MAN", bdetect_bullet_max_proximity];

To:

 _units = ( position _bullet ) nearObjects ["MAN", bdetect_bullet_max_proximity];

I see no difference in SP though and can't reproduce the issue, but it could be the culprit in my mind.

Please tell if the problem is eventually lessened with v0.61, if so i'll streamline the fix in v0.62.

NOTE: Test with these settings (only for debug purpose - fire a single bullet and see):

bdetect_debug_enable = true;

bdetect_debug_levels = [2,5,9];

bdetect_bullet_max_distance = 1000;

bdetect_bullet_max_lifespan = 10;

bdetect_bullet_max_height = 100;

Typical example of .rpt log for a single fired bullet:

"3.239 [bDetect v0.61] Frame:3849 L2: bullet 17527: tracer_red.p3d added"
"3.239 [bDetect v0.61] Frame:3849 L2: [b 1-1-A:1 (minime4)] Found bullet: speed=3348, type=B_556x45_Ball, Delay=0"
"3.255 [bDetect v0.61] Frame:3849 L2: Following bullet 17527: tracer_red.p3d. Time: 0.0149994. Distance: 15.157 Speed: 930. Position: [3628.35,3606.78,20.5767]"
"3.27 [bDetect v0.61] Frame:3850 L2: Following bullet 17527: tracer_red.p3d. Time: 0.0299988. Distance: 29.0845 Speed: 930. Position: [3642.31,3607,20.6708]"
"3.286 [bDetect v0.61] Frame:3851 L2: Following bullet 17527: tracer_red.p3d. Time: 0.0459976. Distance: 43.055 Speed: 930. Position: [3656.29,3607.22,20.7628]"
"3.301 [bDetect v0.61] Frame:3852 L2: Following bullet 17527: tracer_red.p3d. Time: 0.0619965. Distance: 56.4619 Speed: 930. Position: [3669.71,3607.44,20.8486]"
"3.317 [bDetect v0.61] Frame:3853 L2: Following bullet 17527: tracer_red.p3d. Time: 0.0779953. Distance: 70.1868 Speed: 930. Position: [3683.43,3607.65,20.9341]"
"3.333 [bDetect v0.61] Frame:3854 L2: Following bullet 17527: tracer_red.p3d. Time: 0.0939941. Distance: 83.6444 Speed: 930. Position: [3696.89,3607.86,21.0154]"
"3.349 [bDetect v0.61] Frame:3855 L2: Following bullet 17527: tracer_red.p3d. Time: 0.109993. Distance: 97.1196 Speed: 930. Position: [3710.37,3608.07,21.0942]"
"3.365 [bDetect v0.61] Frame:3856 L2: Following bullet 17527: tracer_red.p3d. Time: 0.125. Distance: 109.797 Speed: 930. Position: [3723.04,3608.27,21.1658]"
"3.381 [bDetect v0.61] Frame:3857 L2: Following bullet 17527: tracer_red.p3d. Time: 0.140999. Distance: 122.245 Speed: 930. Position: [3735.49,3608.47,21.2337]"
"3.397 [bDetect v0.61] Frame:3858 L2: Following bullet 17527: tracer_red.p3d. Time: 0.155998. Distance: 134.473 Speed: 930. Position: [3747.72,3608.66,21.2981]"
"3.413 [bDetect v0.61] Frame:3859 L2: Following bullet 17527: tracer_red.p3d. Time: 0.171997. Distance: 146.488 Speed: 930. Position: [3759.73,3608.85,21.3589]"
"3.429 [bDetect v0.61] Frame:3860 L2: Following bullet 17527: tracer_red.p3d. Time: 0.186996. Distance: 158.297 Speed: 930. Position: [3771.54,3609.04,21.4162]"
"3.444 [bDetect v0.61] Frame:3861 L2: Following bullet 17527: tracer_red.p3d. Time: 0.202995. Distance: 169.661 Speed: 930. Position: [3782.9,3609.22,21.469]"
"3.46 [bDetect v0.61] Frame:3862 L2: Following bullet 17527: tracer_red.p3d. Time: 0.217995. Distance: 181.083 Speed: 930. Position: [3794.33,3609.4,21.5198]"
"3.46 [bDetect v0.61] Frame:3862 L9: my_suppression_function - [O 1-1-A:1] close to bullet 17527: tracer_red.p3d fired by B 1-1-A:1 (minime4), proximity=4.13998m, data=[b 1-1-A:1 (minime4),[3613.78,3606.56,20.4759],110.692,[]]"
"3.475 [bDetect v0.61] Frame:3863 L2: Following bullet 17527: tracer_red.p3d. Time: 0.233994. Distance: 192.081 Speed: 930. Position: [3805.32,3609.57,21.5663]"
"3.475 [bDetect v0.61] Frame:3863 L5: [O 1-1-A:1] Blacklisted, bullet 17527: tracer_red.p3d ignored"
"3.491 [bDetect v0.61] Frame:3864 L2: Following bullet 17527: tracer_red.p3d. Time: 0.248993. Distance: 203.141 Speed: 930. Position: [3816.38,3609.74,21.6107]"
"3.506 [bDetect v0.61] Frame:3865 L2: Following bullet 17527: tracer_red.p3d. Time: 0.264999. Distance: 213.796 Speed: 930. Position: [3827.04,3609.91,21.6511]"
"3.522 [bDetect v0.61] Frame:3866 L2: Following bullet 17527: tracer_red.p3d. Time: 0.279999. Distance: 224.517 Speed: 930. Position: [3837.76,3610.08,21.6894]"
"3.537 [bDetect v0.61] Frame:3867 L2: Following bullet 17527: tracer_red.p3d. Time: 0.296997. Distance: 234.85 Speed: 930. Position: [3848.09,3610.24,21.724]"
"3.553 [bDetect v0.61] Frame:3868 L2: Following bullet 17527: tracer_red.p3d. Time: 0.311996. Distance: 245.694 Speed: 930. Position: [3858.93,3610.41,21.7579]"
"3.569 [bDetect v0.61] Frame:3869 L2: Following bullet 17527: tracer_red.p3d. Time: 0.327995. Distance: 255.935 Speed: 930. Position: [3869.17,3610.57,21.7873]"
"3.585 [bDetect v0.61] Frame:3870 L2: Following bullet 17527: tracer_red.p3d. Time: 0.344994. Distance: 266.242 Speed: 930. Position: [3879.48,3610.74,21.8145]"
"3.601 [bDetect v0.61] Frame:3871 L2: Following bullet 17527: tracer_red.p3d. Time: 0.361. Distance: 276.185 Speed: 930. Position: [3889.42,3610.89,21.8382]"

... cutting, too long for post ...

"9.295 [bDetect v0.61] Frame:4209 L2: Following bullet <NULL-object>. Time: 6.491. Distance: 1e+010 Speed: 0. Position: [0,0,0]"
"9.295 [bDetect v0.61] Frame:4209 L2: null/expired bullet removed"

Code Removed, v0.62 out, see my next post.

Edited by fabrizio_T

Share this post


Link to post
Share on other sites

I have this weird problem with units aiming their weapon in the air, too. I am running beta build 94364 and no other mods. Has somebody a solution to this problem? Great mod so far tpw, fabrizio_T and -Coulum-!

Share this post


Link to post
Share on other sites

Try running bDetect v0.61 (below), since:

* It explicitly block the possibility for the shooter to detect own shots.

* It tracks a lot of info about bullets path.

Also changed:

 _units = _bullet  nearObjects ["MAN", bdetect_bullet_max_proximity];

To:

 _units = ( position _bullet ) nearObjects ["MAN", bdetect_bullet_max_proximity];

I see no difference in SP though and can't reproduce the issue.

Grazie! Will give it a closer look tomorrow (will test SP too)

Share this post


Link to post
Share on other sites
I have this weird problem with units aiming their weapon in the air, too. I am running beta build 94364 and no other mods. Has somebody a solution to this problem? Great mod so far tpw, fabrizio_T and -Coulum-!

I think tpw is needed here, sorry i can't help on this.

---

Good Night people,

i'm releasing bDetect v0.62, bugfix release, see below.

Looking good to me, just made a test and it easily detects a single M24 bullet fired from 1000 meters away and passing into a 10 meters radius.

Code removed, v0.63 out

Edited by fabrizio_T

Share this post


Link to post
Share on other sites

I also saw units aiming up into the air (not all by any means, it's some of the the ones lying down).

Also had a couple of oddities when combined with Robalo's new test release of asr_ai - I posted in that thread tonight.

Share this post


Link to post
Share on other sites

bDetect v0.63 - bdetect.sqf code - Backward compatible with v0.6x / not compatible with 0.5x

Maintenance release.

/*
Basic bullet detection framework
Version: 0.63
Date: 03/07/2012
Author: Fabrizio_T 
Additional code: TPW 
File Name: bdetect.sqf

CHANGELOG:

-------------
Version: 0.63
-------------

* Temporarily reverted from "diag_tickTime" to "time" for issues to be looked in

-------------
Version: 0.62
-------------

* Fixed bullet position handling

-------------
Version: 0.61
-------------

* Fixed problem with units eventually detecting own shots

------------
Version: 0.6
------------

* Incorporated v0.51 changes/fixes by tpw.
* Function bdetect_fnc_callback() slightly changed. See bottom of this file for example.
* Function bdetect_fnc_init() waits for 5 seconds to pass by after mission start, before activating the framework.
* Introduced function bdetect_fnc_eh_fired_add(): suitable to force -immediate- assignment of a fired EH to any unit. Syntax: [unit] call bdetect_fnc_eh_fired_add();
* Fixed function bdetect_fnc_benchmark(): internally using code spawning, not to block code execution after function call.
* Tweaked internals so that "diag_tickTime" is used instead of "time" (Thanks Ollem).
* Introduced function bdetect_fnc_eh_loop(): iteratively checks ( each "bdetect_eh_assign_cycle_wait" seconds ) for newly spawned units to assign them a 'Fired' event Handler.
* Renamed "bdetect_bullet_min_distance" to "bdetect_bullet_max_proximity"
* Introduced variable "bdetect_init_done": (Boolean). It evaulates true when framework is loaded. Usage: "waitUntil { bdetect_init_done};"
* Introduced variable "bdetect_eh_assign_cycle_wait": (seconds, Default 10). Wait duration foreach cyclic execution of bdetect_fnc_eh_loop()
* Introduced variable "bdetect_bullet_min_distance": (meters, Default 25). Bullets not having travelled this distance are ignored
* Introduced variable "bdetect_bullet_initial_min_speed": (meters / second, Default 360). Bullets initially slower than this are ignored (good for subsonic bullets skipping). 
* Introduced variable "bdetect_debug_chat": (Boolean, Default false) Show debug messages also in globalChat.
* Changed Variable "bdetect_debug_min_level" to "bdetect_debug_levels". (Array). Default [0,1,2,3,4,5,6,7,8,9]. 0-9 are reserved levels.
* Much more

------------
Version: 0.5
------------

* Framework is named "bdetect" and contained into a single file: bdetect.sqf 
* Renamed variable "bdetect_debug" to "bdetect_debug_enable"
* Introduced variables "bdetect_name" and "bdetect_version": name and version of the framework;
* Introduced function bdetect_fnc_init() to handle the framework bootstrap.
* Introduced variable "bdetect_callback" (string). It defines the name of a custom callback function to be called on a unit when it detects a close bullet (Default: "bdetect_fnc_callback").
* Functions and variable names polishing. All vars named bdetect_<varname>. All functions named bdetect_fnc_<funcname>.
* Added some missing private vars.

------------
Version: 0.4
------------

* Introduced variables "bdetect_enable" (boolean), "bdetect_debug_levels" (Number), "bdetect_skip_mags" (array).
* Variable "bdetect_enable" act as a toggle to enable / disable framework.
* Variable "bdetect_debug_levels" allows for selective display / logging of debug messages based on level.
* Introduced function bdetect_fnc_benchmark() to display performance stats.
* Added "bdetect_skip_mags", which is a blacklist of bullet types which should not trigger detection

------------
Version: 0.3
------------

* Introduced variables "bdetect_bullet_delay" (seconds) , "bdetect_bullet_max_height" (meters).
* Variable "bdetect_bullet_delay" (seconds) changes dinamycally between "bdetect_bullet_min_delay" (lower bound) and 1 (upper bound), depending on actual FPS vs "bdetect_fps_min".
* Variable "bdetect_bullet_max_height" (meters) is the maximum height for bullets, over ground. Bullets higher than this value (Default: 10) and with up vector > 0 are skipped from detection, since they are too high and diverge from ground.
* Some Code optimization.

------------
Version: 0.2
------------

* Position of bullet as SetPosASL.
* Introduced variables "bdetect_fps_min" (fps), "bdetect_bullet_max_distance" (meters), "bdetect_bullet_max_lifespan" (seconds).
* Introduced function bdetect_fnc_diag_min_fps(): in case FPS go under "bdetect_fps_min" value (Default: 25) bdetect_bullet_delay is gradually raised. 
* Function bdetect_fnc_bullet_remove() edited and renamed to bdetect_fnc_bullet_tag_remove(), since actual removal is done elsewhere.
* Bullets are removed from bdetect_fired_bullets if distance is over "bdetect_bullet_max_distance" meters or lifespan is over "bdetect_bullet_max_lifespan" seconds.

------------
Version: 0.1
------------

* First draft
*/

//BEGINNING OF FRAMEWORK CODE

// -----------------------------
// Constants
// -----------------------------

bdetect_name = "bDetect - Bullet Detection Framework"; 
bdetect_short_name = "bDetect"; 
bdetect_version = "0.63";
bdetect_init_done= false;

// -----------------------------
// Functions
// -----------------------------

bdetect_fnc_init = 
{
private [ "_msg", "_x" ];

sleep 5;

// You may override these variables
if(isNil "bdetect_enable") then { bdetect_enable = true; }; // (Boolean, Default true) Toggle to Enable / Disable bdetect altogether.
if(isNil "bdetect_debug_enable") then { bdetect_debug_enable = false; }; // (Boolean, Default false) Toggle to Enable / Disable debug messages.
if(isNil "bdetect_debug_chat") then { bdetect_debug_chat = false; }; // (Boolean, Default false) Show debug messages also in globalChat.
if(isNil "bdetect_debug_levels") then { bdetect_debug_levels = [0,1,2,3,4,5,6,7,8,9]; }; // (Array, Default [0,1,2,3,4,5,6,7,8,9]) Filter debug messages by included levels. 
if(isNil "bdetect_callback") then { bdetect_callback = "bdetect_fnc_callback"; }; // (String, Default "bdetect_fnc_callback") Name for your own callback function
if(isNil "bdetect_fps_min") then { bdetect_fps_min = 25; }; // (Number, Default 25) The minimum FPS you wish to keep
if(isNil "bdetect_fps_calc_each_x_frames") then { bdetect_fps_calc_each_x_frames = 10; }; // (Number, Default 10) FPS check is done each "bdetect_fps_min" frames. 1 means each frame.
if(isNil "bdetect_eh_assign_cycle_wait") then { bdetect_eh_assign_cycle_wait = 10; }; // (Seconds, Default 10). Wait duration foreach cyclic execution of bdetect_fnc_eh_loop()
if(isNil "bdetect_bullet_min_delay") then { bdetect_bullet_min_delay = 0.1; }; // (Seconds, Default 0.1) Minimum time between 2 consecutive shots fired by an unit for the last bullet to be tracked. Very low values may cause lag.
if(isNil "bdetect_bullet_initial_min_speed") then { bdetect_bullet_initial_min_speed = 360; }; // (Meters/Second, Default 360) Bullets slower than this are ignored.
if(isNil "bdetect_bullet_max_proximity") then { bdetect_bullet_max_proximity = 10; }; // (Meters, Default 10) Maximum proximity to unit for triggering detection
if(isNil "bdetect_bullet_min_distance") then { bdetect_bullet_min_distance = 25; }; // (Meters, Default 25) Bullets having travelled less than this distance are ignored
if(isNil "bdetect_bullet_max_distance") then { bdetect_bullet_max_distance = 400; }; // (Meters, Default 400) Bullets past this distance are ignored
if(isNil "bdetect_bullet_max_lifespan") then { bdetect_bullet_max_lifespan = 0.5; }; // (Seconds, Default 0.5) Bullets living more than this are ignored
if(isNil "bdetect_bullet_max_height") then { bdetect_bullet_max_height = 6; }; // (Meters, Default 6) Bullets higher than this -and- diverging from ground are ignored

if(isNil "bdetect_skip_mags") then { // (Array) Skip these bullet types altogether
	bdetect_skip_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"  
	];  
};

// Do not edit the variables below.
if(isNil "bdetect_fired_bullets") then { bdetect_fired_bullets = []; };
if(isNil "bdetect_fps") then { bdetect_fps = bdetect_fps_min; };
if(isNil "bdetect_bullet_delay") then { bdetect_bullet_delay = bdetect_bullet_min_delay; };
if(isNil "bdetect_frame_tstamp") then { bdetect_frame_tstamp = 0; };
if(isNil "bdetect_frame_min_duration") then { bdetect_frame_min_duration = (bdetect_bullet_max_proximity * 2 * .66 / 900) max .01; };

// bullet speed converted to kmh
bdetect_bullet_initial_min_speed = bdetect_bullet_initial_min_speed * 3.6;

// compile callback name into function
bdetect_callback_compiled = call compile format["%1", bdetect_callback];

_msg = format["Starting %1 v%2.", bdetect_name, bdetect_version];
[ _msg, 1 ] call bdetect_fnc_debug;

bdetect_spawned_loop_handler = [] spawn bdetect_fnc_eh_loop;   

[bdetect_fnc_detect,0] call cba_fnc_addPerFrameHandler;   

bdetect_init_done= true;

hint format["%1 v%2 started.", bdetect_name, bdetect_version];
};

// Keep searching units for newly spawned ones and assign fired EH to them
bdetect_fnc_eh_loop =
{
private [ "_x", "_msg"];

while { true } do
{
	{ 
		[_x] call bdetect_fnc_eh_fired_add;

	} foreach allUnits;

	sleep bdetect_eh_assign_cycle_wait;
};
};

// Assign fired EH to a single unit
bdetect_fnc_eh_fired_add =
{
private ["_unit", "_msg"];

_unit = _this select 0;

if( isNil { _unit getVariable "bdetect_fired_eh" } ) then
{
	_unit setVariable ["bdetect_fired_eh", true]; 
	_unit addEventHandler ["Fired", bdetect_fnc_fired];

	if (  ( assignedVehicleRole _unit) select 0 == "Turret" && isNil { (vehicle _x) getVariable "bdetect_fired_eh" } ) then   
	{		
		(vehicle _x) setVariable ["bdetect_fired_eh", true]; 
		(vehicle _x) addeventhandler ["Fired", bdetect_fnc_fired];    
	}; 

	_msg = format["[%1] was assigned 'Fired' EH", _unit];
	[ _msg, 3 ] call bdetect_fnc_debug;
}
else
{
	_msg = format["[%1] already had an assigned 'Fired' EH", _unit];
	[ _msg, 3 ] call bdetect_fnc_debug;
};
};

// Fired EH
bdetect_fnc_fired =
{
	private ["_unit", "_muzzle", "_magazine", "_bullet", "_speed", "_msg", "_time", "_dt"];

if( bdetect_enable ) then
{
	_unit = _this select 0;
	_muzzle = _this select 2;
	_magazine = _this select 5;
	_bullet = _this select 6;
	_speed = speed _bullet;
	_time = time; //diag_tickTime

	_dt = _time - ( _unit getVariable ["bdetect_fired_time", 0] );

	if( _dt > bdetect_bullet_delay && !( _magazine in bdetect_skip_mags ) && _speed > bdetect_bullet_initial_min_speed ) then
	{
		_unit setVariable ["bdetect_fired_time", _time]; 

		// Append info to bullets array
		[ _bullet, _unit, _time ] call bdetect_fnc_bullet_add;

		_msg = format["[%1] Found bullet: speed=%2, type=%3, Delay=%4", _unit, _speed, typeOf _bullet, _dt ];
		[ _msg, 2 ] call bdetect_fnc_debug;
	}
	else
	{
		_msg = format["[%1] Skipped bullet: speed=%2, type=%3, Delay=%4 [%5 - %6]", _unit, _speed, typeOf _bullet, _dt,  _time , ( _unit getVariable ["bdetect_fired_time", 0] )];
		[ _msg, 2 ] call bdetect_fnc_debug;
	};
};
};

// Time-critical detection function, to be executed per-frame
bdetect_fnc_detect =         
{        
private ["_n", "_tot", "_bullet", "_data", "_side", "_pos", "_time", "_shooter", "_blacklist", "_update_blacklist", "_dist", "_units", "_x", "_data", "_func", "_t", "_k", "_bpos"];

_t = time; //diag_tickTime

if( bdetect_enable && (_t - bdetect_frame_tstamp) >= bdetect_frame_min_duration) then
{
	_msg = format["Frame duration=%1, min duration:%2", (_t - bdetect_frame_tstamp), bdetect_frame_min_duration ];
	[ _msg, 4 ] call bdetect_fnc_debug;

	_tot = count bdetect_fired_bullets;

	bdetect_frame_tstamp = _t;

	if ( _tot > 0 ) then 
	{ 
		if(_diag_frameno % bdetect_fps_calc_each_x_frames == 0) then
		{
			call bdetect_fnc_diag_min_fps;
		};

		for "_n" from 0 to _tot - 1 step 2 do 
		{
			_bullet = bdetect_fired_bullets select _n;
			_data = bdetect_fired_bullets select (_n + 1);
			_shooter = _data select 0;
			_pos = _data select 1;
			_time = _data select 2;
			_blacklist = _data select 3;
			_update_blacklist = false;
			_bpos = position _bullet;
			_dist = _bpos distance _pos;

			_msg = format["Following bullet %1. Time: %2. Distance: %3 Speed: %4. Position: %5", _bullet, _t - _time, _dist, (speed _bullet / 3.6), getPosASL _bullet];
			[ _msg, 2 ] call bdetect_fnc_debug;

			if( isNull _bullet 
				|| !(alive _bullet) 
				|| _t - _time > bdetect_bullet_max_lifespan 
				|| _dist > bdetect_bullet_max_distance	
				|| speed _bullet < bdetect_bullet_initial_min_speed
				|| ( ( (getPosATL _bullet) select 2) > bdetect_bullet_max_height && ( ( vectordir _bullet ) select 2 ) > 0 ) ) then
			{
				[_bullet] call bdetect_fnc_bullet_tag_remove;
			}
			else
			{
				if( _dist > bdetect_bullet_min_distance	) then
				{
					_units = _bpos nearObjects ["MAN", bdetect_bullet_max_proximity];

					{
						if( !(_x in _blacklist) && _x != _shooter ) then
						{
							if( alive _x && vehicle _x == _x && lifestate _x == "ALIVE") then
							{
								_blacklist = _blacklist + [_x];
								_update_blacklist = true;

								[_x, _bullet, _x distance _bpos, _data] call bdetect_callback_compiled;

								_msg = format["[%1] close to bullet %2 fired by %3, proximity=%4m, data=%5", _x, _bullet, _shooter, _x distance _bpos, _data];
								[ _msg, 9 ] call bdetect_fnc_debug;
							};
						}
						else
						{
							_msg = format["[%1] Blacklisted, bullet %2 ignored", _x, _bullet];
							[ _msg, 5 ] call bdetect_fnc_debug;
						};

					} foreach _units;

					if(_update_blacklist) then
					{
						// Update blacklist
						bdetect_fired_bullets set[ _n + 1, [_shooter, _pos, _time, _blacklist] ];
					};

					//_msg = format["bdetect_fired_bullets = %1", bdetect_fired_bullets];
					//[ _msg, 2 ] call bdetect_fnc_debug;
				};
			};
		};

		// remove dead / expired bullets
		bdetect_fired_bullets = bdetect_fired_bullets - [-1];

		//_msg = format["%1 bullets in array", count ( bdetect_fired_bullets ) / 2];
		//[ _msg, 2 ] call bdetect_fnc_debug;
	};
};
};

bdetect_fnc_diag_min_fps =
{
private ["_fps", "_msg"];

_fps = diag_fps;

_msg = format["FPS=%1, Min.FPS=%2, Prev. FPS=%3, bdetect_bullet_delay=%4)", _fps, bdetect_fps_min, bdetect_fps, bdetect_bullet_delay ];
[ _msg, 1 ] call bdetect_fnc_debug;

if( _fps < bdetect_fps_min * 1.1 ) then
{
	if( bdetect_bullet_delay < 1 && _fps < bdetect_fps_min) then
	{
		bdetect_bullet_delay = bdetect_bullet_delay + .1;

		_msg = format["FPS down to %1. Augmenting bdetect_bullet_delay to %2", _fps, bdetect_bullet_delay];
		[ _msg, 1 ] call bdetect_fnc_debug;
	};
}
else
{
	if( ( bdetect_bullet_delay - .1 ) >= bdetect_bullet_min_delay ) then
	{
		bdetect_bullet_delay = bdetect_bullet_delay - .1;

		_msg = format["FPS up to %1. Reducing bdetect_bullet_delay to %2", _fps, bdetect_bullet_delay];
		[ _msg, 1 ] call bdetect_fnc_debug;
	};
};

bdetect_fps = _fps;
};

// Function to add a bullet to bdetect_fired_bullets 
bdetect_fnc_bullet_add = 
{
private ["_bullet", "_shooter", "_pos", "_time",  "_msg"];

_bullet = _this select 0; // bullet object
_shooter = _this select 1;	// shooter
_pos = getPosASL _bullet;	// bullet start position
_time = _this select 2;	// bullet shoot time

bdetect_fired_bullets = bdetect_fired_bullets + [ _bullet, [ _shooter, _pos, _time, [] ] ];

_msg = format["bullet %1 added", _bullet, count ( bdetect_fired_bullets ) / 2];
[ _msg, 2] call bdetect_fnc_debug;

};

// Function to remove a bullet from bdetect_fired_bullets 
bdetect_fnc_bullet_tag_remove = 
{
private ["_bullet", "_n", "_msg" ];

_bullet = _this select 0;
_n = bdetect_fired_bullets find _bullet;

if( _n != -1 ) then
{
	bdetect_fired_bullets set[ _n, -1 ];
	bdetect_fired_bullets set[ _n + 1, -1 ];

	_msg = format["null/expired bullet removed"];
	[ _msg, 2 ] call bdetect_fnc_debug;
};
};

// Callback function to be executed from within bdetect_fnc_detect
bdetect_fnc_callback = 
{
private [ "_unit", "_bullet", "_proximity", "_data", "_shooter", "_pos", "_time", "_msg" ];

_unit = _this select 0;		// unit being under fire
_bullet = _this select 1;	// bullet object
_proximity = _this select 2;	// distance between _bullet and _unit
_data = _this select 3;		// Array containing more data

_shooter = _data select 0; // shooter
_pos = _data select 1;	// starting position of bullet
_time = _data select 2; // starting time of bullet

_msg = format["[%1] close to bullet %2 fired by %3, proximity=%4m, data=%5", _unit, _bullet, _shooter, _proximity, _data];
[ _msg, 9 ] call bdetect_fnc_debug;
};

// function to display and log stuff (into .rpt file) level zero is intended only for builtin messages
bdetect_fnc_debug =
{
private [ "_msg", "_level"];

/*
DEBUG LEVELS: 
From 0-9 are reserved.

0 = unclassified messages
1 = FPS related messages
2 = "bdetect_fired_bullets" related messages
3 = EH related messages
4 = Frame related messages
5 = Unit blacklist messages
...
9 = Unit detection related messages
*/

_level = _this select 1;

if( bdetect_debug_enable && _level in bdetect_debug_levels) then
{
	_msg = _this select 0;

	diag_log format["%1 [%2 v%3] Frame:%4 L%5: %6", time, bdetect_short_name, bdetect_version, diag_frameno, _level, _msg ];

	if( bdetect_debug_chat ) then 
	{
		player globalchat format["%1 - %2", time, _msg ];
	};
};
};

bdetect_fnc_benchmark = 
{
private ["_cnt"];

if(isNil "bdetect_stats_max_bullets") then { bdetect_stats_max_bullets = 0;};
if(isNil "bdetect_stats_min_fps") then { bdetect_stats_min_fps = 999;};
if(isNil "bdetect_fired_bullets") then { bdetect_fired_bullets = [];};

_nul = [] spawn 
{
	sleep 5;

	while { true } do
	{
		_cnt = count ( bdetect_fired_bullets ) / 2;

		if( _cnt > bdetect_stats_max_bullets ) then { bdetect_stats_max_bullets = _cnt; };
		if( diag_fps < bdetect_stats_min_fps ) then { bdetect_stats_min_fps = diag_fps };
		hintsilent format["TIME: %1\nFPS: %2 (min: %3)\nBULLETS: %4 (max: %5)", time, diag_fps, bdetect_stats_min_fps, _cnt, bdetect_stats_max_bullets];

		sleep .1;
	};
};
};

// END OF FRAMEWORK CODE

// -----------------------------------------------------------
// Example for running the script
// -----------------------------------------------------------
// The following commented code is not part of the framework, 
// just an advice on how to run it from within another file
// -----------------------------------------------------------

/*
// load framework
call compile preprocessFileLineNumbers "bdetect.sqf";  

// First declare any optional variables whose value should be other than Default (see the defined variables in bdetect.sqf, function bdetect_fnc_init()
bdetect_debug_enable = true;
bdetect_debug_levels = [9];
bdetect_debug_chat = true;

// Then name your own unit callback function (the one that should be triggered when a bullet is close to a unit)
bdetect_callback = "my_suppression_function";

// Define your own callback function, named as above
my_suppression_function = {
private [ "_unit", "_bullet", "_proximity", "_data", "_shooter", "_pos", "_time", "_msg" ];

_unit = _this select 0;
_bullet = _this select 1;
_proximity = _this select 2;
_data = _this select 3;
_shooter = _data select 0; // enemy shooter
_pos = _data select 1;	// starting position of bullet
_time = _data select 2; // starting time of bullet

_msg = format["my_suppression_function - [%1] close to bullet %2 fired by %3, proximity=%4m, data=%5", _unit, _bullet, _shooter, _proximity, _data];
[ _msg, 9 ] call bdetect_fnc_debug;
};

// Then initialize framework
call bdetect_fnc_init;

// Wait stuff to be loaded
waitUntil { bdetect_init_done};

// finally, activate display of stats if you wish
call bdetect_fnc_benchmark; 

// All done, now put your other stuff here ...
*/

Share this post


Link to post
Share on other sites

Good morning all.

Thanks to Fabrizio_T for a massive amount of work - that bloke must have 4 arms to code so quickly. I haven't had a chance to run the code yet but the improvements look very significant.

FT, I've got a few suggestions to speed things up incrementally:

1 - Line 291. Change

_bpos = position _bullet;

to the faster

_bpos = getposatl _bullet;

2 - Line 310. Change

_units = _bpos nearObjects ["MAN", bdetect_bullet_max_proximity];

to the much faster

_units = (_bpos) nearEntities [["Man"],bdetect_bullet_max_proximity]; 

This will also have the positive side effect of not picking up dead entities, so you can change

if( alive _x && vehicle _x == _x && lifestate _x == "ALIVE") then 

to

if(vehicle _x == _x && lifestate _x == "ALIVE") then 

3 - Line 241.

 if( _dt > bdetect_bullet_delay && !( _magazine in bdetect_skip_mags ) && _speed > bdetect_bullet_initial_min_speed ) then

Can probably just omit the

 && !( _magazine in bdetect_skip_mags )

since the subsonic bullet stuff takes care of it anyway.

4 - Line 301. And since you already screen for bullet speed, remove the check in bdetect_fnc_detect

|| speed _bullet < bdetect_bullet_initial_min_speed

although this will miss bullets which have dropped below supersonic after 400m.

5 - Line 398 Change

bdetect_fired_bullets = bdetect_fired_bullets + [ _bullet, [ _shooter, _pos, _time, [] ] ];

to the faster

bdetect_fired_bullets set [count bdetect_fired_bullets,[ _bullet, [ _shooter, _pos, _time, []]]]

Not trying to be a smartarse, just passing on what I read here: http://community.bistudio.com/wiki/Code_Optimisation

Other thoughts:

Currently there is a per frame check for bullet height. I wonder if this could be eliminated by screening on bullet angle in bdetect_fnc_fired. So bullets +/- say 30deg to the horizontal could be excluded. Something like

_bulletangle = (vectordir _bullet) select 2;
if( (_dt > bdetect_bullet_delay) && ( _bulletangle > -0.1 ) && (_bulletangle < 0.1) && (_speed > bdetect_bullet_initial_min_speed) ) then

Regarding the units pointing guns in the air. There are 2 possibilities

1 - I've seen with recent betas that over time units stop holding their guns parallel to the ground.

2 - Maybe the skills alteration code is causing an issue. -Coulum- might like to pipe up here.

Please try running the exact same mission without TPWCAS and see what happens. That will eliminate possibility 1.

Edited by tpw

Share this post


Link to post
Share on other sites

Wow, after a few days, I get back home look on the forum and see that the mod has made it to 2.00! Awesome work guys, especially Frabrizio! Man it looks like tonnes has been done, and it will probably take me a couple hours just to read an process all this new stuff.

Concerning the ai shooting into the sky, anyone who has experienced this, is there a certain behaviour the ai must be in. Ie. do they need to be suppressed, shooting, in a certain stance etc. I only ask because I personally can't get this to happen. Judging from the way the ai were reacting to skill modification prior to 2.00, I wouldn't say it is due to skill modification but then again I don't know how the skill stuff has changed since then, if at all, and I don't see anything else that could be causing this problem. Once I have a good grasp on how this new system works I try to figure out what's causing it but it is very hard to find the cause of a problem when I can't repro it myself, so any info on what causes this behaviour is much appreciated.

Once again great work to Fabrizio, tpw, Ollem and all others involved, this is really looking great. Now I'm going back ten pages to catch up on what I missed...

Share this post


Link to post
Share on other sites

I also never had the pointing to air problem... just to be sure, please remove older tpwc_ai_sup pbos in the addons folder... they could cause conflict

Share this post


Link to post
Share on other sites

I think the air shooting only happens with ASR

Share this post


Link to post
Share on other sites

I used ASR with this mod, haven't seen that odd behavior either.

Share this post


Link to post
Share on other sites

i tried it four times yesterday, 3 times with different mod constelations, asr_ai, ACE and zeus, and one time with only with tpw_supp 2.00 everytime some of the ai they looked in the air when the shooting began, initial the firefight starts okay, but a couple of seconds later the "looking in to the sky" begins, one thing is the graphical look, but it alsom seems that they dont see the enemy, and gets pretty easy to kill. I play without beta.

After the four tries i went back to 1.04, and played a full mission without any problems, with all my normal mods, a combi of the three mods above.

I really like this mod, so i hope you find a solution :-)

Robert (sixt)

Share this post


Link to post
Share on other sites
i tried it four times yesterday, 3 times with different mod constelations, asr_ai, ACE and zeus, and one time with only with tpw_supp 2.00 everytime some of the ai they looked in the air when the shooting began, initial the firefight starts okay, but a couple of seconds later the "looking in to the sky" begins, one thing is the graphical look, but it alsom seems that they dont see the enemy, and gets pretty easy to kill. I play without beta.

After the four tries i went back to 1.04, and played a full mission without any problems, with all my normal mods, a combi of the three mods above.

I really like this mod, so i hope you find a solution :-)

Robert (sixt)

Thanks for that report. I will prepare a test version of the system with no skills modification (only stance), so that you can help us to determine if this could be the problem. I hate these kind of bugs which don't appear for everyone (especially the developers!).

It also occurred to me that the reveal which was added when a unit is suppressed might also cause issues. I will disable this in the test version too.

Edited by tpw

Share this post


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

×