Jump to content
Sign in to follow this  
fabrizio_t

bDetect | bullet detection framework

Recommended Posts

WHAT IS IT

It's a small framework in form of single .sqf file, named "bdetect.sqf".

It was made in order to easily detect any flying bullets close to infantrymen on foot, given some basic configuration.

Once a bullet is found being closer enough to some unit, a custom callback function is called: it's up to you defining name and contents of this callback function.

Basic scripting knowledge is required to run it, see Readme.

CAVEAT

* bDetect is currently in BETA stage. Use at your own risk.

* bDetect is actually working in SP (Stable) and MP (alpha stage of development). MP is officially available since v0.70 BETA.

REQUIREMENTS

* ArmA2 CO v1.61 BETA or higher (but v1.60 should work too)

* CBA - Community Made Addons: https://dev-heaven.net/projects/cca/wiki/CBA

DOWNLOAD

* Download bdetect.sqf - v0.74 BETA SP/MP (09 Aug 2012)

* Readme

* Variable configuration guide (Little outdated)

* Changelog

* GNU/GPL License

GITHUB

https://github.com/fabrizioT/bDetect

NOTES

* bDetect is used in TPWC AI suppression system

* bDetect is used in Zub mission by SaOk as part of TPWC AI suppression system

Enjoy.

Edited by fabrizio_T

Share this post


Link to post
Share on other sites

Very nice, also good documented/commented, thanks for sharing.

A few suggestions:

  • KilledEH is local; The eventhandler and count removals are not executed on any machine except where the unit is local (and is a bit random depending on unit, as locality can switch)
  • The debug messages are formatted even if debug is disabled - which is pointless and also string formatting is afaik considered as one of the slower aspects of ARMA scripting
  • More of a preference thing; you could save a lot of typing by using the CBA macros: PARAMS_# (does private, and _var = _this select # etc) and ISNILS
  • The body of bdetect_fnc_detect is rather huge and is triggered each frame, it might be beneficial to split this up somewhat, like the content of the for loop could perhaps be it's own function for starters. Also, though minor, the private declaration, _t and _dt might be better moved to within the bdetect_enable condition statement

Edited by Sickboy

Share this post


Link to post
Share on other sites

Thanks for suggestions.

I'm aware of the weakness of debug, I'll work it out.

I wrote this framework with SP in mind, since i have no experience with MP.

I imagine there's a lot that should be changed, maybe somebody can help.

Can you explain why splitting bdetect_fnc_detect would be beneficial? I am interested in that as i thought the opposite and was evidently wrong.

I agree it would be easy to split it up taking the loop out, passing just _t and _tot to a bdetect_fnc_detect_sub function call.

Edited by fabrizio_T

Share this post


Link to post
Share on other sites
Thanks for suggestions.
NP
I wrote this framework with SP in mind, since i have no esperience with MP.

I imagine there's a lot that should be changed, maybe somebody can help.

Very low on time myself, but who knows, might just have an opening one time or the other and take a look :)
Can you explain why splitting bdetect_fnc_detect would be beneficial? I am interested in that as i thought the opposite and was evidently wrong.

I agree it would be easy to split it up taking the loop out, passing just _t and _tot to a bdetect_fnc_detect_sub function call.

It's a feeling, not based on any tests/evidence, that calling a larger code body would cost more resources than calling a smaller one.

Since youre using the PerFrameHandler, and having this large code body called each frame, even if it doesn't need to be run (the conditions are in the code body itself), I feel it could be beneficial.

Certainly would be an interesting test.

Share this post


Link to post
Share on other sites

Thanks for the separate thread for bdetect!!! I think this is an important project (bdetect and TPWS) and warrants a functional MP version, if possible (it really is a game changer). Unfortunately the limit of my assistance would be testing and troubleshooting.

Share this post


Link to post
Share on other sites

Certainly would be an interesting test.

Agree. Thanks Sickboy.

Any help on MP would be precious.

---------- Post added at 14:52 ---------- Previous post was at 14:50 ----------

Thanks for the separate thread for bdetect!!! I think this is an important project (bdetect and TPWS) and warrants a functional MP version, if possible (it really is a game changer). Unfortunately the limit of my assistance would be testing and troubleshooting.

I agree MP would be interesting, sadly it's off my capabilities.

Let's see if somebody would volunteer in helping.

Share this post


Link to post
Share on other sites

Could be an interesting idea to throw it on GitHub, with a BSD, MIT or GPL or so license :)

It would definitely be a plus for me personally.

I could throw it on there, but found that you cannot Fork your own repositories easily with Github, so if you're up for it, you could add it, and others could fork it and e.g work on MP aspects.

Share this post


Link to post
Share on other sites
Could be an interesting idea to throw it on GitHub, with a BSD, MIT or GPL or so license :)

It would definitely be a plus for me personally.

I could throw it on there, but found that you cannot Fork your own repositories easily with Github, so if you're up for it, you could add it, and others could fork it and e.g work on MP aspects.

Ok, a little jargon to me, but i'll try set it up.

EDIT: i hope i did it correctly, see: https://github.com/fabrizioT/bDetect

bDetect v0.66 is up, including some debug tweaks and bdetect_fnc_detect() splitting.

Edited by fabrizio_T

Share this post


Link to post
Share on other sites

Perfect, thanks a bunch fabrizio!

Forking, hacking and merging the changes from different versions should be very easy now.

Share this post


Link to post
Share on other sites

I'd like to propose to include '_pbos' by default in the return of the callback around line 337?

Reason for this is I did use the equivalent 'getPosATL _bullet' in the callback, but had several occasions where by the time the getPosATL was called, the bullet no longer existed and resulted in error.

Alternative could be to return '_pbos' in stead of '_x distance _bpos': _x is send by default anyway, so the distance could also be done in the callback function itself.

if( bdetect_callback_mode == "spawn" ) then {
							_nul = [_x, _bullet, _x distance _bpos, _data] spawn bdetect_callback_compiled;
						} else {
							[_x, _bullet, _x distance _bpos, _data] call bdetect_callback_compiled;
						};

Share this post


Link to post
Share on other sites
I'd like to propose to include '_pbos' by default in the return of the callback around line 337?

Reason for this is I did use the equivalent 'getPosATL _bullet' in the callback, but had several occasions where by the time the getPosATL was called, the bullet no longer existed and resulted in error.

Alternative could be to return '_pbos' in stead of '_x distance _bpos': _x is send by default anyway, so the distance could also be done in the callback function itself.

if( bdetect_callback_mode == "spawn" ) then {
							_nul = [_x, _bullet, _x distance _bpos, _data] spawn bdetect_callback_compiled;
						} else {
							[_x, _bullet, _x distance _bpos, _data] call bdetect_callback_compiled;
						};

Good suggestion.

I'll include bullet position to callback in v0.68, as substitute for distance.

Thank you.

Edited by fabrizio_T

Share this post


Link to post
Share on other sites

I've done some more dedicated server testing.

created a dedicated server on same system as client, so basically no network latency.

Still, any shots fired by me on the client were hardly detected in time: only 1 bullet

Often the bullet has traveled over 200m before being detected.

For dedicated we may have to increase the detection area significantly, in order to detect passing bullets.

We could reduce the sideway detection by determining the shooter direction - by adding getDir to EH, and then use some good ole SIN calculation based on distance and angle to reduce to e.g. 10 m sideways.

(I already tested this last week and it works)

Another approach could be to run a bullet framework for just the player on the client, based on a single EH for just the client.

Conclusion: Dedicated Server support still needs some attention...

[font=Courier New][b]
time	frame					bullet				Time		Distance	Speed				nr[/b]
31.878	69748	L2:	bullet			438946	" tracer_red.p3d added"""											1
32.178	69763	L2:	Following bullet 	438946	 tracer_red.p3d. Time	0.300001.	207.736		930.				6
32.680	69788	L2:	Following bullet 	438946	 tracer_red.p3d. Time	0.802.		341.833		930.				8
32.038	69756	L2:	bullet 			438948	" tracer_red.p3d added"""											4
32.178	69763	L2:	Following bullet 	438948	 tracer_red.p3d. Time	0.140003.	136.310		930.001.			7
32.680	69788	L2:	Following bullet 	438948	 tracer_red.p3d. Time	0.642002.	305.080		930.001.			10
34.186	69863	L2:	bullet 			438974	" tracer_red.p3d added"""											12
34.186	69863	L2:	Following bullet 	438974	 tracer_red.p3d. Time	0.186.002			930.001.			14
34.688	69888	L2:	Following bullet 	438974	 tracer_red.p3d. Time	0.501999.	266.783		930.001.			19
34.347	69871	L2:	bullet 			438976	" tracer_red.p3d added"""											16
34.688	69888	L2:	Following bullet 	438976	 tracer_red.p3d. Time	0.341.		220.107		930.002.			21
35.188	69913	L2:	Following bullet 	438976	 tracer_red.p3d. Time	0.841.		355.699		930.002.			22
35.688	69938	L2:	Following bullet 	438976	 tracer_red.p3d. Time	1.341.		441.723		930.002.			23
36.909	69999	L2:	bullet 			438997	" tracer_red.p3d added"""											25
37.169	70012	L2:	Following bullet 	438997	 tracer_red.p3d. Time	0.259998.	195.559		930.				30
37.069	70007	L2:	bullet 			438999	" tracer_red.p3d added"""											28
37.169	70012	L2:	Following bullet 	438999	 tracer_red.p3d. Time	0.0999985.	104.691		930.				31
37.673	70037	L2:	Following bullet 	438999	 tracer_red.p3d. Time	0.604.		294.965		930.				32
79.484	72126	L2:	bullet 			439011	" tracer_red.p3d added"""											40
79.684	72136	L2:	Following bullet 	439011	 tracer_red.p3d. Time	0.199997.	176.602		930.002.			45
79.624	72133	L2:	bullet 			439013	" tracer_red.p3d added"""											43
80.184	72160	L2:	Following bullet 	439013	 tracer_red.p3d. Time	0.559998.	282.969		930.				48
79.684	72136	L2:	Following bullet 	439013	 tracer_red.p3d. Time	0.0599976.	715.429		930.				46
80.624	72182	L2:	bullet 			439024	" tracer_red.p3d added"""											50
81.184	72210	L2:	Following bullet 	439024	 tracer_red.p3d. Time	0.559998.	282.925		930.002.			56
80.684	72185	L2:	Following bullet 	439024	 tracer_red.p3d. Time	0.0599976.	715.432		930.002.			52
80.784	72190	L2:	bullet 			439026	" tracer_red.p3d added"""											54
81.184	72210	L2:	Following bullet 	439026	 tracer_red.p3d. Time	0.400002.	237.472		930.001.			58
81.787	72240	L2:	bullet 			439038	" tracer_red.p3d added"""											60
82.187	72260	L2:	Following bullet 	439038	 tracer_red.p3d. Time	0.399994.	237.651		930.001.			65
82.669	72284	L2:	Following bullet 	439038	 tracer_red.p3d. Time	0.881996.	365.855		930.001.			67
81.947	72248	L2:	bullet 			439040	" tracer_red.p3d added"""											63
82.187	72260	L2:	Following bullet 	439040	 tracer_red.p3d. Time	0.239998.	189.201		930.001.			66
82.669	72284	L2:	Following bullet 	439040	 tracer_red.p3d. Time	0.722.		326.066		930.001.			69
82.789	72290	L2:	bullet 			439048	" tracer_red.p3d added"""											70
82.949	72298	L2:	bullet 			439051	" tracer_red.p3d added"""											73
83.169	72309	L2:	Following bullet 	439051	 tracer_red.p3d. Time	0.220001.	182.939		930.001.			75
83.672	72334	L2:	Following bullet 	439051	 tracer_red.p3d. Time	0.723.		326.310		930.001.			76
84.172	72359	L2:	Following bullet 	439051	 tracer_red.p3d. Time	1.223.		422.959		930.001.			82
83.992	72350	L2:	bullet 			439059	" tracer_red.p3d added"""											77
84.172	72359	L2:	Following bullet 	439059	 tracer_red.p3d. Time	0.18.		166.538		930.001.			84
84.152	72358	L2:	bullet 			439061	" tracer_red.p3d added"""											80
84.672	72384	L2:	Following bullet 	439061	 tracer_red.p3d. Time	0.519997.	271.955		930.001.			87
84.172	72359	L2:	Following bullet 	439061	 tracer_red.p3d. Time	0.0199966.	367.074		930.001.			85
85.175	72409	L2:	Following bullet 	439061	 tracer_red.p3d. Time	1.023.		386.612		930.001.			88
85.677	72434	L2:	Following bullet 	439061	 tracer_red.p3d. Time	1.525.		455.826		930.001.			94
85.295	72415	L2:	bullet 			439075	" tracer_red.p3d added"""											89
85.455	72423	L2:	bullet 			439077	" tracer_red.p3d added"""											92
85.677	72434	L2:	Following bullet 	439077	 tracer_red.p3d. Time	0.222.		183.512		930.				97
86.177	72459	L2:	Following bullet 	439077	 tracer_red.p3d. Time	0.722.		325.937		930.				98
86.498	72475	L2:	bullet 			439085	" tracer_red.p3d added"""											100
86.679	72484	L2:	Following bullet 	439085	 tracer_red.p3d. Time	0.181.		167.284		930.001.			105
86.658	72483	L2:	bullet 			439089	" tracer_red.p3d added"""											103
87.180	72509	L2:	Following bullet 	439089	 tracer_red.p3d. Time	0.522003.	272.212		930.002.			107
86.679	72484	L2:	Following bullet 	439089	 tracer_red.p3d. Time	0.0210037.	376.121		930.002.			106
356.879	85980	L2:	bullet 			439115	" tracer_red.p3d added"""											145
357.499	86011	L2:	bullet 			439117	" tracer_red.p3d added"""											147
358.040	86038	L2:	bullet 			439119	" tracer_red.p3d added"""											149
358.180	86045	L2:	Following bullet 	439119	 tracer_red.p3d. Time	0.139984.	136.319		930.				151
358.180	86045	L9:	[O 1-1-A:1	439119	"Close to bullet ;"	7.8549m													152
358.180	86045	L9:	[O 1-1-A:2	439119	"Close to bullet ;"	2.15786m												153
358.180	86045	L9:	[O 1-1-A:3	439119	"Close to bullet ;"	5.30886m												154
359.603	86116	L2:	bullet 			439121	" tracer_red.p3d added"""											155
359.683	86120	L2:	Following bullet 	439121	 tracer_red.p3d. Time	0.0800171.	883.206		930.				157
359.703	86121	L2:	bullet 			439122	" tracer_red.p3d added"""											158
360.323	86152	L2:	bullet 			439127	" tracer_red.p3d added"""											161
360.683	86170	L2:	Following bullet 	439127	 tracer_red.p3d. Time	0.360016.	192.865		930.				166
361.184	86195	L2:	Following bullet 	439127	 tracer_red.p3d. Time	0.860992.	276.016		930.				172
361.684	86220	L2:	Following bullet 	439127	 tracer_red.p3d. Time	1.36099.	351.635		930.				177
360.483	86160	L2:	bullet 			439130	" tracer_red.p3d added"""											164
360.683	86170	L2:	Following bullet 	439130	 tracer_red.p3d. Time	0.200012.	176.511		930.001.			167
361.184	86195	L2:	Following bullet 	439130	 tracer_red.p3d. Time	0.700989.	362.986		930.001.			173
361.064	86189	L2:	bullet 			439134	" tracer_red.p3d added"""											168
361.184	86195	L2:	Following bullet 	439134	 tracer_red.p3d. Time	0.119995.	120.689		930.001.			174
361.164	86194	L2:	bullet 			439135	" tracer_red.p3d added"""											170
361.184	86195	L2:	Following bullet 	439135	 tracer_red.p3d. Time	0.019989.	367.074		930.001.			175
361.889	86229	L2:	bullet 			439141	" tracer_red.p3d added"""											182
362.169	86243	L2:	Following bullet 	439141	 tracer_red.p3d. Time	0.279999.	216.222		930.001.			187
362.669	86268	L2:	Following bullet 	439141	 tracer_red.p3d. Time	0.779999.	429.064		930.001.			192
363.170	86293	L2:	Following bullet 	439141	 tracer_red.p3d. Time	1.28101.	592.554		930.001.			200
362.029	86236	L2:	bullet 			439143	" tracer_red.p3d added"""											185
362.169	86243	L2:	Following bullet 	439143	 tracer_red.p3d. Time	0.140015.	136.318		930.002.			188
362.169	86243	L9:	[O 1-1-A:2	439143	"Close to bullet ;"				6.87299m									189
362.169	86243	L9:	[O 1-1-A:3	439143	"Close to bullet ;"				4.61316m									190
362.169	86243	L9:	[O 1-1-A:4	439143	"Close to bullet ;"				9.06002m									191
362.689	86269	L2:	bullet 			439149	" tracer_red.p3d added"""											194
362.790	86274	L2:	bullet 			439150	" tracer_red.p3d added"""											196
363.170	86293	L2:	Following bullet 	439150	 tracer_red.p3d. Time	0.380005.	239.339		930.001.			204
363.670	86318	L2:	Following bullet 	439150	 tracer_red.p3d. Time	0.880005.	387.874		930.001.			208
364.170	86343	L2:	Following bullet 	439150	 tracer_red.p3d. Time	1.38.		511.055		930.001.			214
362.890	86279	L2:	bullet 			439151	" tracer_red.p3d added"""											198
363.670	86318	L2:	bullet 			439157	" tracer_red.p3d added"""											206
363.670	86318	L2:	Following bullet 	439157	 tracer_red.p3d. Time	0.			186.001		930.001.			210
364.170	86343	L2:	Following bullet 	439157	 tracer_red.p3d. Time	0.5.		268.888		930.001.			217
364.670	86368	L2:	Following bullet 	439157	 tracer_red.p3d. Time	1.			410.637		930.001.			223
365.170	86393	L2:	Following bullet 	439157	 tracer_red.p3d. Time	1.5.		528.719		930.001.			228
363.830	86326	L2:	bullet 			439159	" tracer_red.p3d added"""											212
364.550	86362	L2:	bullet 			439163	" tracer_red.p3d added"""											219
364.670	86368	L2:	Following bullet 	439163	 tracer_red.p3d. Time	0.120026.	120.689		930.001.			225
364.710	86370	L2:	bullet 			439166	" tracer_red.p3d added"""											226
365.170	86393	L2:	Following bullet 	439166	 tracer_red.p3d. Time	0.460022.	286.107		930.002.			232
365.670	86418	L2:	Following bullet 	439166	 tracer_red.p3d. Time	0.960022.	458.367		930.002.			233
366.184	86440	L2:	Following bullet 	439166	 tracer_red.p3d. Time	1.474.		600.208		930.002.			234
367.085	86485	L2:	bullet 			439171	" tracer_red.p3d added"""											236
367.185	86490	L2:	Following bullet 	439171	 tracer_red.p3d. Time	0.100006.	106.334		930.				239
367.247	86493	L2:	bullet 			439173	" tracer_red.p3d added"""											240
367.827	86522	L2:	bullet 			439178	" tracer_red.p3d added"""											242
368.188	86540	L2:	Following bullet 	439178	 tracer_red.p3d. Time	0.360992.	218.570		930.				247
368.688	86565	L2:	Following bullet 	439178	 tracer_red.p3d. Time	0.860992.	367.024		930.				249
369.169	86589	L2:	Following bullet 	439178	 tracer_red.p3d. Time	1.34201.	485.352		930.				251
368.007	86531	L2:	bullet 			439180	" tracer_red.p3d added"""											245
368.188	86540	L2:	Following bullet 	439180	 tracer_red.p3d. Time	0.181.		165.265		930.				248
368.688	86565	L2:	Following bullet 	439180	 tracer_red.p3d. Time	0.681.		398.090		930.				250
369.169	86589	L2:	Following bullet 	439180	 tracer_red.p3d. Time	1.16202.	566.226		930.				253

[/font]

CSV export:

time;frame;;;bullet;;Time;Distance;Speed;;;nr

31.878;69748;L2:;bullet ;438946;" tracer_red.p3d added""";;;;;;1

32.178;69763;L2:;Following bullet ;438946; tracer_red.p3d. Time;0.300001.;207.736;930.;;;6

32.680;69788;L2:;Following bullet ;438946; tracer_red.p3d. Time;0.802.;341.833;930.;;;8

32.038;69756;L2:;bullet ;438948;" tracer_red.p3d added""";;;;;;4

32.178;69763;L2:;Following bullet ;438948; tracer_red.p3d. Time;0.140003.;136.310;930.001.;;;7

32.680;69788;L2:;Following bullet ;438948; tracer_red.p3d. Time;0.642002.;305.080;930.001.;;;10

34.186;69863;L2:;bullet ;438974;" tracer_red.p3d added""";;;;;;12

34.186;69863;L2:;Following bullet ;438974; tracer_red.p3d. Time;0.;186.002;930.001.;;;14

34.688;69888;L2:;Following bullet ;438974; tracer_red.p3d. Time;0.501999.;266.783;930.001.;;;19

34.347;69871;L2:;bullet ;438976;" tracer_red.p3d added""";;;;;;16

34.688;69888;L2:;Following bullet ;438976; tracer_red.p3d. Time;0.341.;220.107;930.002.;;;21

35.188;69913;L2:;Following bullet ;438976; tracer_red.p3d. Time;0.841.;355.699;930.002.;;;22

35.688;69938;L2:;Following bullet ;438976; tracer_red.p3d. Time;1.341.;441.723;930.002.;;;23

36.909;69999;L2:;bullet ;438997;" tracer_red.p3d added""";;;;;;25

37.169;70012;L2:;Following bullet ;438997; tracer_red.p3d. Time;0.259998.;195.559;930.;;;30

37.069;70007;L2:;bullet ;438999;" tracer_red.p3d added""";;;;;;28

37.169;70012;L2:;Following bullet ;438999; tracer_red.p3d. Time;0.0999985.;104.691;930.;;;31

37.673;70037;L2:;Following bullet ;438999; tracer_red.p3d. Time;0.604.;294.965;930.;;;32

79.484;72126;L2:;bullet ;439011;" tracer_red.p3d added""";;;;;;40

79.684;72136;L2:;Following bullet ;439011; tracer_red.p3d. Time;0.199997.;176.602;930.002.;;;45

79.624;72133;L2:;bullet ;439013;" tracer_red.p3d added""";;;;;;43

80.184;72160;L2:;Following bullet ;439013; tracer_red.p3d. Time;0.559998.;282.969;930.;;;48

79.684;72136;L2:;Following bullet ;439013; tracer_red.p3d. Time;0.0599976.;715.429;930.;;;46

80.624;72182;L2:;bullet ;439024;" tracer_red.p3d added""";;;;;;50

81.184;72210;L2:;Following bullet ;439024; tracer_red.p3d. Time;0.559998.;282.925;930.002.;;;56

80.684;72185;L2:;Following bullet ;439024; tracer_red.p3d. Time;0.0599976.;715.432;930.002.;;;52

80.784;72190;L2:;bullet ;439026;" tracer_red.p3d added""";;;;;;54

81.184;72210;L2:;Following bullet ;439026; tracer_red.p3d. Time;0.400002.;237.472;930.001.;;;58

81.787;72240;L2:;bullet ;439038;" tracer_red.p3d added""";;;;;;60

82.187;72260;L2:;Following bullet ;439038; tracer_red.p3d. Time;0.399994.;237.651;930.001.;;;65

82.669;72284;L2:;Following bullet ;439038; tracer_red.p3d. Time;0.881996.;365.855;930.001.;;;67

81.947;72248;L2:;bullet ;439040;" tracer_red.p3d added""";;;;;;63

82.187;72260;L2:;Following bullet ;439040; tracer_red.p3d. Time;0.239998.;189.201;930.001.;;;66

82.669;72284;L2:;Following bullet ;439040; tracer_red.p3d. Time;0.722.;326.066;930.001.;;;69

82.789;72290;L2:;bullet ;439048;" tracer_red.p3d added""";;;;;;70

82.949;72298;L2:;bullet ;439051;" tracer_red.p3d added""";;;;;;73

83.169;72309;L2:;Following bullet ;439051; tracer_red.p3d. Time;0.220001.;182.939;930.001.;;;75

83.672;72334;L2:;Following bullet ;439051; tracer_red.p3d. Time;0.723.;326.310;930.001.;;;76

84.172;72359;L2:;Following bullet ;439051; tracer_red.p3d. Time;1.223.;422.959;930.001.;;;82

83.992;72350;L2:;bullet ;439059;" tracer_red.p3d added""";;;;;;77

84.172;72359;L2:;Following bullet ;439059; tracer_red.p3d. Time;0.18.;166.538;930.001.;;;84

84.152;72358;L2:;bullet ;439061;" tracer_red.p3d added""";;;;;;80

84.672;72384;L2:;Following bullet ;439061; tracer_red.p3d. Time;0.519997.;271.955;930.001.;;;87

84.172;72359;L2:;Following bullet ;439061; tracer_red.p3d. Time;0.0199966.;367.074;930.001.;;;85

85.175;72409;L2:;Following bullet ;439061; tracer_red.p3d. Time;1.023.;386.612;930.001.;;;88

85.677;72434;L2:;Following bullet ;439061; tracer_red.p3d. Time;1.525.;455.826;930.001.;;;94

85.295;72415;L2:;bullet ;439075;" tracer_red.p3d added""";;;;;;89

85.455;72423;L2:;bullet ;439077;" tracer_red.p3d added""";;;;;;92

85.677;72434;L2:;Following bullet ;439077; tracer_red.p3d. Time;0.222.;183.512;930.;;;97

86.177;72459;L2:;Following bullet ;439077; tracer_red.p3d. Time;0.722.;325.937;930.;;;98

86.498;72475;L2:;bullet ;439085;" tracer_red.p3d added""";;;;;;100

86.679;72484;L2:;Following bullet ;439085; tracer_red.p3d. Time;0.181.;167.284;930.001.;;;105

86.658;72483;L2:;bullet ;439089;" tracer_red.p3d added""";;;;;;103

87.180;72509;L2:;Following bullet ;439089; tracer_red.p3d. Time;0.522003.;272.212;930.002.;;;107

86.679;72484;L2:;Following bullet ;439089; tracer_red.p3d. Time;0.0210037.;376.121;930.002.;;;106

356.879;85980;L2:;bullet ;439115;" tracer_red.p3d added""";;;;;;145

357.499;86011;L2:;bullet ;439117;" tracer_red.p3d added""";;;;;;147

358.040;86038;L2:;bullet ;439119;" tracer_red.p3d added""";;;;;;149

358.180;86045;L2:;Following bullet ;439119; tracer_red.p3d. Time;0.139984.;136.319;930.;;;151

358.180;86045;L9:;[O 1-1-A:1;439119;"Close to bullet ;";7.8549m;;;;;152

358.180;86045;L9:;[O 1-1-A:2;439119;"Close to bullet ;";2.15786m;;;;;153

358.180;86045;L9:;[O 1-1-A:3;439119;"Close to bullet ;";5.30886m;;;;;154

359.603;86116;L2:;bullet ;439121;" tracer_red.p3d added""";;;;;;155

359.683;86120;L2:;Following bullet ;439121; tracer_red.p3d. Time;0.0800171.;883.206;930.;;;157

359.703;86121;L2:;bullet ;439122;" tracer_red.p3d added""";;;;;;158

360.323;86152;L2:;bullet ;439127;" tracer_red.p3d added""";;;;;;161

360.683;86170;L2:;Following bullet ;439127; tracer_red.p3d. Time;0.360016.;192.865;930.;;;166

361.184;86195;L2:;Following bullet ;439127; tracer_red.p3d. Time;0.860992.;276.016;930.;;;172

361.684;86220;L2:;Following bullet ;439127; tracer_red.p3d. Time;1.36099.;351.635;930.;;;177

360.483;86160;L2:;bullet ;439130;" tracer_red.p3d added""";;;;;;164

360.683;86170;L2:;Following bullet ;439130; tracer_red.p3d. Time;0.200012.;176.511;930.001.;;;167

361.184;86195;L2:;Following bullet ;439130; tracer_red.p3d. Time;0.700989.;362.986;930.001.;;;173

361.064;86189;L2:;bullet ;439134;" tracer_red.p3d added""";;;;;;168

361.184;86195;L2:;Following bullet ;439134; tracer_red.p3d. Time;0.119995.;120.689;930.001.;;;174

361.164;86194;L2:;bullet ;439135;" tracer_red.p3d added""";;;;;;170

361.184;86195;L2:;Following bullet ;439135; tracer_red.p3d. Time;0.019989.;367.074;930.001.;;;175

361.889;86229;L2:;bullet ;439141;" tracer_red.p3d added""";;;;;;182

362.169;86243;L2:;Following bullet ;439141; tracer_red.p3d. Time;0.279999.;216.222;930.001.;;;187

362.669;86268;L2:;Following bullet ;439141; tracer_red.p3d. Time;0.779999.;429.064;930.001.;;;192

363.170;86293;L2:;Following bullet ;439141; tracer_red.p3d. Time;1.28101.;592.554;930.001.;;;200

362.029;86236;L2:;bullet ;439143;" tracer_red.p3d added""";;;;;;185

362.169;86243;L2:;Following bullet ;439143; tracer_red.p3d. Time;0.140015.;136.318;930.002.;;;188

362.169;86243;L9:;[O 1-1-A:2;439143;"Close to bullet ;";;;;6.87299m;;189

362.169;86243;L9:;[O 1-1-A:3;439143;"Close to bullet ;";;;;4.61316m;;190

362.169;86243;L9:;[O 1-1-A:4;439143;"Close to bullet ;";;;;9.06002m;;191

362.689;86269;L2:;bullet ;439149;" tracer_red.p3d added""";;;;;;194

362.790;86274;L2:;bullet ;439150;" tracer_red.p3d added""";;;;;;196

363.170;86293;L2:;Following bullet ;439150; tracer_red.p3d. Time;0.380005.;239.339;930.001.;;;204

363.670;86318;L2:;Following bullet ;439150; tracer_red.p3d. Time;0.880005.;387.874;930.001.;;;208

364.170;86343;L2:;Following bullet ;439150; tracer_red.p3d. Time;1.38.;511.055;930.001.;;;214

362.890;86279;L2:;bullet ;439151;" tracer_red.p3d added""";;;;;;198

363.670;86318;L2:;bullet ;439157;" tracer_red.p3d added""";;;;;;206

363.670;86318;L2:;Following bullet ;439157; tracer_red.p3d. Time;0.;186.001;930.001.;;;210

364.170;86343;L2:;Following bullet ;439157; tracer_red.p3d. Time;0.5.;268.888;930.001.;;;217

364.670;86368;L2:;Following bullet ;439157; tracer_red.p3d. Time;1.;410.637;930.001.;;;223

365.170;86393;L2:;Following bullet ;439157; tracer_red.p3d. Time;1.5.;528.719;930.001.;;;228

363.830;86326;L2:;bullet ;439159;" tracer_red.p3d added""";;;;;;212

364.550;86362;L2:;bullet ;439163;" tracer_red.p3d added""";;;;;;219

364.670;86368;L2:;Following bullet ;439163; tracer_red.p3d. Time;0.120026.;120.689;930.001.;;;225

364.710;86370;L2:;bullet ;439166;" tracer_red.p3d added""";;;;;;226

365.170;86393;L2:;Following bullet ;439166; tracer_red.p3d. Time;0.460022.;286.107;930.002.;;;232

365.670;86418;L2:;Following bullet ;439166; tracer_red.p3d. Time;0.960022.;458.367;930.002.;;;233

366.184;86440;L2:;Following bullet ;439166; tracer_red.p3d. Time;1.474.;600.208;930.002.;;;234

367.085;86485;L2:;bullet ;439171;" tracer_red.p3d added""";;;;;;236

367.185;86490;L2:;Following bullet ;439171; tracer_red.p3d. Time;0.100006.;106.334;930.;;;239

367.247;86493;L2:;bullet ;439173;" tracer_red.p3d added""";;;;;;240

367.827;86522;L2:;bullet ;439178;" tracer_red.p3d added""";;;;;;242

368.188;86540;L2:;Following bullet ;439178; tracer_red.p3d. Time;0.360992.;218.570;930.;;;247

368.688;86565;L2:;Following bullet ;439178; tracer_red.p3d. Time;0.860992.;367.024;930.;;;249

369.169;86589;L2:;Following bullet ;439178; tracer_red.p3d. Time;1.34201.;485.352;930.;;;251

368.007;86531;L2:;bullet ;439180;" tracer_red.p3d added""";;;;;;245

368.188;86540;L2:;Following bullet ;439180; tracer_red.p3d. Time;0.181.;165.265;930.;;;248

368.688;86565;L2:;Following bullet ;439180; tracer_red.p3d. Time;0.681.;398.090;930.;;;250

369.169;86589;L2:;Following bullet ;439180; tracer_red.p3d. Time;1.16202.;566.226;930.;;;253

Edited by Ollem

Share this post


Link to post
Share on other sites

Ho Ollem,

thanks for testing.

The first thing i noticed is the bullets are not really checked per-frame.

That makes me wonder whether cba_fnc_addPerFrameHandler is working on dedi.

First bullet is checked almost each 25 frames for example.

Also, the same bullet is traveling 130 meters ( 207 to 341 ) in 0.5 seconds, which is just plain absurd, since speed was marked 930.

It happens also in SP though.

I think the first thing is to understand why dedi is behaving strange, regarding per-frame execution.

Can you please install on dedi most recent CBA and check again?

Also which are the specs of the server?

Maybe Sickboy or some MP experts can give us some hints ...

EDIT: using higher radius won't solve the problem, as we'd have to put it as high as around 100-150 meters with such a low execution frequency.

Such a value would be completely unrealistic and unreliable.

EDIT2: sorry, i missed the part the bullets where fired by you: can you check what happens for bullets fired by AI units in own groups ( since they're locale to server ) ?

Chance is they're being correctly checked. In that case cba_fnc_addPerFrameHandler is absolved, problem would be (maybe) related to syncronization frequency of EH.

Thanks.

I'll try adding some addMPeventHandler to check whether things improve, but i doubt it.

For sure it will helpusing a "MPKilled" MPEH, i bet i'll have to fire it only if unit is local to client.

Regarding the "FIRED" EH, it's already global so theoretically no need for changes ...

Maybe i'm wrong, i lack any MP scripting background.

Edited by fabrizio_T

Share this post


Link to post
Share on other sites
The first thing i noticed is the bullets are not really checked per-frame.

That makes me wonder whether cba_fnc_addPerFrameHandler is working on dedi.

First bullet is checked almost each 25 frames for example.

Also, the same bullet is traveling 130 meters ( 207 to 341 ) in 0.5 seconds, which is just plain absurd, since speed was marked 930.

It happens also in SP though.

I think the first thing is to understand why dedi is behaving strange, regarding per-frame execution.

Can you please install on dedi most recent CBA and check again?

Also which are the specs of the server?

Hey,

You are correct that PerFrame handles differently on the server side, instead of running each frame, it runs each trigger iteration (~0.5s).

The issue is that the game does not provide a mechanic on dedicated servers to achieve per-frame handling.

There's a ticket open requesting this functionality out of the box, on any machine type; https://dev-heaven.net/issues/24926

Share this post


Link to post
Share on other sites

Here is the raw log (I removed a few non-related messages) which includes in the upper part just me shooting AI, lower part it's some 15 vs 15 (or more) AI shooting each other.

Arma_server_bDetect.log

settings used:

- bdetect_bullet_max_distance = 1000;

- bdetect_bullet_max_lifespan = 1.1;

- bdetect_debug_levels = [0,1,2,5,6,7,8,9];

---------- Post added at 08:25 ---------- Previous post was at 08:10 ----------

Dedicated Server most likely has a different need (in general; or at least speaking for myself): Dedicated game play is focused around COOP vs AI, or PvP.

In theory that would mean AI suppression is primarily needed based on players shooting AI only.

So I will investigate if bDetect could just run on each client, monitoring a local EH tracing bullets fired by the player only (assuming cba_fnc_addPerFrameHandler is working normally on MP clients)

If thresholds are met, the info about which _unit should be considered suppressed should be sent to the server, which would collect and process the suppressing info.

Share this post


Link to post
Share on other sites
Hey,

You are correct that PerFrame handles differently on the server side, instead of running each frame, it runs each trigger iteration (~0.5s).

The issue is that the game does not provide a mechanic on dedicated servers to achieve per-frame handling.

There's a ticket open requesting this functionality out of the box, on any machine type; https://dev-heaven.net/issues/24926

Ah! That clarifies things. Thanks for the advice Sickboy.

I imagine we can partially overcome this with doing some looping doing very frequent polling, but i bet that would have quite some overhead.

I'll check it out.

Share this post


Link to post
Share on other sites
some looping doing very frequent polling
Probably not, without per-frame-handler it is very hard to get loops run reliably, let alone each frame, this is the downside of the script scheduler.

Let's hope for a mechanic to make it work under Deddies :)

Share this post


Link to post
Share on other sites
Probably not, without per-frame-handler it is very hard to get loops run reliably, let alone each frame, this is the downside of the script scheduler.

Let's hope for a mechanic to make it work under Deddies :)[/color]

Yes, but in this case per-frame execution would not be strictly critical.

If we manage to poll each 0.02-0.05 seconds we may catch a decent number of bullets, probably 50-80%.

Of course it's not that reliable as it greatly depends on server load, however i can't see any other way around, except for BIS intervention.

Ollem, care to try the following experimental build?

// ------------------------------------
// bDetect | bullet detection framework
// ------------------------------------
// Version: 0.68
// Date: 06/07/2012
// Author: Fabrizio_T 
// Additional code: TPW 
// File Name: bdetect.sqf
// License: GNU/GPL
// ------------------------------------

// BEGINNING OF FRAMEWORK CODE
// -----------------------------
// Constants
// -----------------------------

bdetect_name = "bDetect | Bullet Detection Framework"; 
bdetect_short_name = "bDetect"; 
bdetect_version = "0.68";
bdetect_init_done = false;

// -----------------------------
// Global variables
// -----------------------------

// You should set these variables elsewhere, don't edit them here since they're default. 
// See bottom of this file for framework initialization example.
if(isNil "bdetect_enable") then { bdetect_enable = true; }; // (Boolean, Default true) Toggle to Enable / Disable bdetect altogether.
if(isNil "bdetect_startup_hint") then { bdetect_startup_hint = true; }; // (Boolean, Default true) Toggle to Enable / Disable bDetect startup Hint.

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_callback_mode") then { bdetect_callback_mode = "spawn"; }; // (String, Default "spawn") Allowed values: "call" or "spawn"

if(isNil "bdetect_fps_adaptation") then { bdetect_fps_adaptation = true; }; // (Boolean, Default true) Whether bDetect should try to keep over "bdetect_fps_min" FPS while degrading quality of detection
if(isNil "bdetect_fps_min") then { bdetect_fps_min = 20; }; // (Number, Default 20) The minimum FPS you wish to keep
if(isNil "bdetect_fps_calc_each_x_frames") then { bdetect_fps_calc_each_x_frames = 16; }; // (Number, Default 16) 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_max_delay") then { bdetect_bullet_max_delay = 1.5; }; // (Seconds, Default 2)
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 havin travelled more than distance are ignored
if(isNil "bdetect_bullet_max_lifespan") then { bdetect_bullet_max_lifespan = 0.5; }; // (Seconds, Default 0.5) Bullets living more than these seconds are ignored
if(isNil "bdetect_bullet_max_height") then { bdetect_bullet_max_height = 6; }; // (Meters, Default 6)  Bullets going higher than this -and- diverging from ground are ignored
if(isNil "bdetect_bullet_skip_mags") then { bdetect_bullet_skip_mags = []; }; // (Array) Skip these bullet types altogether. Example: ["30rnd_9x19_MP5", "30rnd_9x19_MP5SD", "15Rnd_9x19_M9"]

if(isNil "bdetect_mp") then { bdetect_mp = false; }; // (Boolean, Default false) Toggle to Enable / Disable MP experimental support
if(isNil "bdetect_mp_per_frame_emulation") then { bdetect_mp_per_frame_emulation = false; }; // (Boolean, Default false) Toggle to Enable / Disable experimental server per-frame-execution emulation
if(isNil "bdetect_mp_per_frame_emulation_frame_d") then { bdetect_mp_per_frame_emulation_frame_d = 0.025; };  // (Seconds, Default 0.025) Experimental server per-frame-execution emulation timeout

// NEVER edit the variables below, please.
if(isNil "bdetect_fired_bullets") then { bdetect_fired_bullets = []; };
if(isNil "bdetect_fired_bullets_count") then { bdetect_fired_bullets_count = 0; };
if(isNil "bdetect_fired_bullets_count_tracked") then { bdetect_fired_bullets_count_tracked = 0; };
if(isNil "bdetect_fired_bullets_count_detected") then { bdetect_fired_bullets_count_detected = 0; };
if(isNil "bdetect_fired_bullets_count_blacklisted") then { bdetect_fired_bullets_count_blacklisted = 0; };	
if(isNil "bdetect_units_count") then { bdetect_units_count = 0; };
if(isNil "bdetect_units_count_killed") then { bdetect_units_count_killed = 0; };
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 / 600) max .01; };

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

bdetect_fnc_per_frame_emulation = 
{
private ["_fnc", "_msg"];

if( bdetect_debug_enable ) then {
	_msg = format["Started bdetect_fnc_per_frame_emulation()"];
	[ _msg, 8 ] call bdetect_fnc_debug;
};

while { true } do 
{
	call bdetect_fnc_detect;

	if( bdetect_debug_enable ) then {
		_msg = format["bdetect_fnc_per_frame_emulation() iteration"];
		[ _msg, 8 ] call bdetect_fnc_debug;
	};

	sleep bdetect_mp_per_frame_emulation_frame_d;
};
};

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

if( bdetect_debug_enable ) then {
	_msg = format["%1 v%2 is starting ...", bdetect_short_name, bdetect_version];
	[ _msg, 0 ] call bdetect_fnc_debug;
};

// 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];

// Add per-frame execution of time-critical function
if( bdetect_mp && bdetect_mp_per_frame_emulation ) then 
{
	_nul = [] spawn bdetect_fnc_per_frame_emulation;  
}
else
{
	[bdetect_fnc_detect,0] call cba_fnc_addPerFrameHandler;   
};

// Assign event handlers to any units (even spawned ones)
bdetect_spawned_loop_handler = [] spawn bdetect_fnc_eh_loop;   
};

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

{ 
	[_x] call bdetect_fnc_eh_add;

} foreach allUnits;

if( !bdetect_init_done ) then 
{ 
	bdetect_init_done = true; 

	if( bdetect_debug_enable ) then {
		_msg = format["%1 v%2 has started", bdetect_short_name, bdetect_version];
		[ _msg, 0 ] call bdetect_fnc_debug;
	};

	if( bdetect_startup_hint ) then {
		_msg = format["%1 v%2 has started", bdetect_short_name, bdetect_version];
		hint _msg;
	};
};

while { true } do
{
	sleep bdetect_eh_assign_cycle_wait;
	{ 
		[_x] call bdetect_fnc_eh_add;

	} foreach allUnits;
};
};

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

_unit = _this select 0;
_vehicle = assignedVehicle _unit;

if( isNull _vehicle && _unit != vehicle _unit ) then { _vehicle =  vehicle _unit };

// handling units
if( isNil { _unit getVariable "bdetect_fired_eh" } ) then
{
	_e = _unit addeventHandler ["Fired", bdetect_fnc_fired];
	_unit setVariable ["bdetect_fired_eh", _e]; 

	_e = _unit addeventHandler ["Killed", bdetect_fnc_killed];
	_unit setVariable ["bdetect_killed_eh", _e]; 

	if( bdetect_mp ) then
	{
		_e = _unit addMPeventHandler ["MPKilled", bdetect_fnc_killed];
		_unit setVariable ["bdetect_killed_eh_mp", _e]; 
	};

	bdetect_units_count = bdetect_units_count + 1;

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

// handling vehicles
if( !( isNull _vehicle ) ) then
{
	if ( isNil { _vehicle getVariable "bdetect_fired_eh" } && ( assignedVehicleRole _unit) select 0 == "Turret"  ) then   
	{		
		_vehicle addeventhandler ["Fired", bdetect_fnc_fired];  
		_vehicle setVariable ["bdetect_fired_eh", _e]; 

		_vehicle addeventHandler ["Killed", bdetect_fnc_killed];		
		_vehicle setVariable ["bdetect_killed_eh", _e]; 

		if( bdetect_mp ) then
		{
			_vehicle addMPeventHandler ["MPKilled", bdetect_fnc_killed];		
			_vehicle setVariable ["bdetect_killed_eh_mp", _e]; 	
		};

		bdetect_units_count = bdetect_units_count + 1;			

		if( bdetect_debug_enable ) then {
			_msg = format["[%1] was assigned 'Fired' EH", _vehicle];
			[ _msg, 3 ] call bdetect_fnc_debug;	
		};
	}
	else
	{
		if( bdetect_debug_enable ) then {
			_msg = format["[%1] already had an assigned 'Fired' EH", _vehicle];
			[ _msg, 3 ] call bdetect_fnc_debug;
		};
	};
};
};

// Killed EH
bdetect_fnc_killed =
{
private ["_unit", "_e"];

_unit = _this select 0;

if( local _unit) then
{
	_e = _unit getVariable "bdetect_fired_eh";
	_unit removeEventHandler ["fired", _e];

	_e = _unit getVariable "bdetect_killed_eh";
	_unit removeEventHandler ["killed", _e];

	_unit setVariable ["bdetect_fired_eh", nil];
	_unit setVariable ["bdetect_killed_eh", nil];

	if( bdetect_mp ) then
	{
		_unit setVariable ["bdetect_killed_eh_mp", nil];
	};

	bdetect_units_count_killed = bdetect_units_count_killed + 1;
};
};

// 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] );

	bdetect_fired_bullets_count = bdetect_fired_bullets_count + 1;

	if( _dt > bdetect_bullet_delay 
		&& !( _magazine in bdetect_bullet_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;

		bdetect_fired_bullets_count_tracked = bdetect_fired_bullets_count_tracked + 1;

		if( bdetect_debug_enable ) then {
			_msg = format["[%1] Tracking bullet: speed=%2, type=%3, Delay=%4", _unit, _speed, typeOf _bullet, _dt ];
			[ _msg, 2 ] call bdetect_fnc_debug;
		};
	}
	else
	{
		if( bdetect_debug_enable ) then {
			_msg = format["[%1] Skipping 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 ["_tot", "_msg"];

if( bdetect_enable ) then
{
	private ["_t", "_dt"];

	_t = time; //diag_tickTime
	_dt = _t - bdetect_frame_tstamp;

	if( _dt >= bdetect_frame_min_duration ) then
	{
		bdetect_frame_tstamp = _t;

		if( bdetect_debug_enable ) then {
			_msg = format["Frame duration=%1, min duration:%2", _dt , bdetect_frame_min_duration ];
			[ _msg, 4 ] call bdetect_fnc_debug;
		};

		_tot = count bdetect_fired_bullets;

		if ( _tot > 0 ) then 
		{ 
			if( bdetect_fps_adaptation && diag_frameno % bdetect_fps_calc_each_x_frames == 0) then
			{
				call bdetect_fnc_diag_min_fps;
			};

			[ _tot, _t ] call bdetect_fnc_detect_sub;
		};
	};

	bdetect_fired_bullets = bdetect_fired_bullets - [-1];
};
};

// Subroutine executed within bdetect_fnc_detect()
bdetect_fnc_detect_sub = 
{
private ["_tot", "_t", "_n", "_bullet", "_data", "_shooter", "_pos", "_time", "_blacklist", "_update_blacklist", "_bpos", "_dist", "_units", "_x", "_data", "_nul"];

_tot = _this select 0;
_t = _this select 1;

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;

	if( !( isnull _bullet ) ) then
	{
		_bpos = getPosATL _bullet;
		_dist = _bpos distance _pos;	

		if( bdetect_debug_enable ) then {
			_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 // funny rebounds handling
		|| ( ( _bpos 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 nearEntities [ ["MAN"] , bdetect_bullet_max_proximity];

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

						bdetect_fired_bullets_count_detected = bdetect_fired_bullets_count_detected + 1;

						if( bdetect_callback_mode == "spawn" ) then {
							_nul = [_x, _bullet, _bpos, _data] spawn bdetect_callback_compiled;
						} else {
							[_x, _bullet, _bpos, _data] call bdetect_callback_compiled;
						};

						if( bdetect_debug_enable ) then {
							_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
				{
					bdetect_fired_bullets_count_blacklisted = bdetect_fired_bullets_count_blacklisted + 1;

					if( bdetect_debug_enable ) then {
						_msg = format["[%1] Blacklisted for bullet %2", _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] ];
			};
		};
	};
};
};

// Adapt frequency of some bullet checking depending on minimum FPS
bdetect_fnc_diag_min_fps =
{
private ["_fps", "_msg"];

_fps = diag_fps;

if( bdetect_debug_enable ) then {
	_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  < bdetect_bullet_max_delay ) then 
	{
		bdetect_bullet_delay = ( ( bdetect_bullet_delay + 0.2) min bdetect_bullet_max_delay );

		if( bdetect_debug_enable ) then {
			_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 > bdetect_bullet_min_delay ) then
	{
		bdetect_bullet_delay = (bdetect_bullet_delay - 0.1) max bdetect_bullet_min_delay;

		if( bdetect_debug_enable ) then {
			_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;
};

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

_bullet = _this select 0; // bullet object
_shooter = _this select 1;	// shooter
_pos = getPosATL _bullet;	// bullet start position
_time = _this select 2;	// bullet shoot time
_n = count bdetect_fired_bullets;

bdetect_fired_bullets set [ _n,  _bullet  ];
bdetect_fired_bullets set [ _n + 1, [ _shooter, _pos, _time, [] ] ];

if( bdetect_debug_enable ) then {
	_msg = format["bullet %1 added", _bullet, _n / 2];
	[ _msg, 2] call bdetect_fnc_debug;
};
};

// Tag a bullet to be removed 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 ];

	if( bdetect_debug_enable ) then {
		_msg = format["null/expired bullet tag to be removed"];
		[ _msg, 2 ] call bdetect_fnc_debug;
	};
};
};

// Prototype for callback function to be executed 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
_bpos = _this select 2;	// bullet position
_data = _this select 3;		// Array containing more data
_proximity = _bpos distance _unit;	// distance between _bullet and _unit

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

if( bdetect_debug_enable ) then {
	_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
...
8 = MP related 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 
{
	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)\nS.DELAY: %6 (Min FPS: %7)\nFIRED: %8\nTRACKED: %9\nDETECTED: %10\nBLACKLISTED: %11\nUNITS: %12\nKILLED: %13", 
			time, 
			diag_fps, 
			bdetect_stats_min_fps, 
			_cnt, 
			bdetect_stats_max_bullets, 
			bdetect_bullet_delay, 
			bdetect_fps_min,
			bdetect_fired_bullets_count,
			bdetect_fired_bullets_count_tracked,
			bdetect_fired_bullets_count_detected,
			bdetect_fired_bullets_count_blacklisted,
			bdetect_units_count,
			bdetect_units_count_killed
		];

		sleep .25;
	};
};
};

// END OF FRAMEWORK CODE
// -------------------------------------------------------------------------------------------
// Example for running the framework
// -------------------------------------------------------------------------------------------
// The following commented code is not part of the framework, just an example of how to run it
// -------------------------------------------------------------------------------------------

/*
// Cut & paste the following code into your own sqf. file.
// Place "bdetect.sqf" into your own mission folder.

// First load the framework
call compile preprocessFileLineNumbers "bdetect.sqf";  // CAUTION: comment this line if you wish to execute the framework from -within- bdetect.sqf file

// Set any optional configuration variables whose value should be other than Default (see all the defined variables in bdetect.sqf, function bdetect_fnc_init() ). 
// Below some examples.
bdetect_debug_enable = true;		// Example only - Enable debug / logging in .rpt file. Beware, full levels logging may be massive.
bdetect_debug_levels = [0,9];		// Example only - Log only some basic messages (levels 0 and 9). Read comment about levels meanings into "bdetect.sqf, function bdetect_fnc_debug()
bdetect_debug_chat = true;			// Example only - log also into globalChat.

// Now name your own unit callback function (the one that will be triggered when a bullet is detected close to an unit)
bdetect_callback = "my_function";

// Define your own callback function and its contents, named as above. Here's a prototypical function: 
my_function = {
private [ "_unit", "_bullet", "_proximity", "_data", "_shooter", "_pos", "_time", "_msg" ];

_unit = _this select 0;			// unit whi detecting nearby bullet
_bullet = _this select 1;		// bullet object
_proximity = _this select 2;	// distance between bullet and unit
_data = _this select 3;			// Container (array) of misc data, see below:

_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_function() - [%1] close to bullet %2 fired by %3, proximity=%4m, data=%5", _unit, _bullet, _shooter, _proximity, _data];
[ _msg, 9 ] call bdetect_fnc_debug;
};

// Now initialize framework
sleep 5; // wait some seconds if you want to load other scripts
call bdetect_fnc_init;

// Wait for framework to be fully loaded
waitUntil { bdetect_init_done};

// You are done. Optional: care to activate display of some runtime stats ?
sleep 5;	// wait some more seconds for CPU load to normalize
call bdetect_fnc_benchmark; 

// All done, place your other fancy stuff below ...
*/

Please add these lines to configuration:

bdetect_mp = true;
bdetect_mp_per_frame_emulation = true;
bdetect_mp_per_frame_emulation_frame_d = 0.02;

Please run and check results.

Raise a bit bdetect_mp_per_frame_emulation_frame_d, up to 0.05, to see how much detection will change ( we should lose some bullets).

Thanks.

Share this post


Link to post
Share on other sites

Hi Fabrizio

Doing a bit of testing of the latest TPWCAS and I noticed that if a unit is firing even slightly uphill, he can't suppress anyone

I changed line 322 of bDetect 0.67

|| ( ( _bpos select 2) > bdetect_bullet_max_height && ( ( vectordir _bullet ) select 2 ) > 0 ) 

to

|| ( ( _bpos select 2) > bdetect_bullet_max_height && ( ( vectordir _bullet ) select 2 ) > 0.2 )

to allow for firing at units uphill, and it seems to work.

Share this post


Link to post
Share on other sites

Here are 2 logs:

1 - Me shooting bursts and multiple single shots at a single AI: dDetect_mp_player_ai.log

(added some comments in the log)

2 - AI USMC squad versus AI Takistani Militia squad: dDetect_mp_ai_vs_ai.log

(remarkable: the logs consistently show 2 detected bullets instead of 3 for bursts..)

Edited by Ollem

Share this post


Link to post
Share on other sites
Hi Fabrizio

Doing a bit of testing of the latest TPWCAS and I noticed that if a unit is firing even slightly uphill, he can't suppress anyone

I changed line 322 of bDetect 0.67

|| ( ( _bpos select 2) > bdetect_bullet_max_height && ( ( vectordir _bullet ) select 2 ) > 0 ) 

to

|| ( ( _bpos select 2) > bdetect_bullet_max_height && ( ( vectordir _bullet ) select 2 ) > 0.2 )

to allow for firing at units uphill, and it seems to work.

Thank you, i overlooked that case.

---------- Post added at 12:04 ---------- Previous post was at 11:58 ----------

Here are 2 logs:

1 - Me shooting bursts and multiple single shots at a single AI: dDetect_mp_player_ai.log

(added some comments in the log)

2 - AI USMC squad versus AI Takistani Militia squad: dDetect_mp_ai_vs_ai.log

Looking better.

What do you think ? Improved ?

I see strange things into player firing log, e.g. trajectory for "bullet 439041: tracer_red.p3d" suffers of the "Matrix syndrome" (slomo), but that's nother matter.

---------- Post added at 12:06 ---------- Previous post was at 12:04 ----------

(remarkable: the logs consistently show 2 detected bullets instead of 3 for bursts..)

That's good and expected.

We don't pick more than 1 bullet per-shooter each 0.1 seconds.

It should be no problem, because in a burst bullets are supposed to fly along close trajectories, so we may pick some of them and discard others to avoid overhead.

You may tweak this by lowering bdetect_bullet_min_delay, but i wouldn't.

Share this post


Link to post
Share on other sites
Looking better.

What do you think ? Improved ?

I see strange things into player firing log, e.g. trajectory for "bullet 439041: tracer_red.p3d" suffers of the "Matrix syndrome" (slomo), but that's nother matter.

:p indeed strange flight path - It looks like the bullet got stuck in the wall.. ;-)

Can't tell yet if it improved, but at least you somehow were able to mimic per frame EH at the server.

(I did not have time to look at the details of the script)

I did test another test with me vs single AI: 15 single shots from +/- 70m:

with bdetect_bullet_max_proximity = 10 less then half of the bullets were discovered

However, with bdetect_bullet_max_proximity = 16 all 15 of the fired bullets were discovered.

This looks promising.. if only performance isn't impacted that bad..

bDetect_mp_player_ai_15-10.log

dDetect_mp_player_ai_15-16.log

Share this post


Link to post
Share on other sites

If you two can come up with an MP compatible bDetect the Arma community will nominate you both for a Nobel Prize.

Share this post


Link to post
Share on other sites

This looks promising.. if only performance isn't impacted that bad..

Are you seeing some noticeable overhead with emulation ?

I tried in SP both native per-frame execution and emulation and difference in FPS is almost negligible.

Stange but true.

However it was a pretty simple mission involving about 30 AI units.

About bdetect_bullet_max_proximity, sure raising it will give better detection, but at the sime time will cause more overhead (and need for blacklisting) and give less reliability (a unit behind a house can be suppressed by a bullet hitting near the other side). 10-12 would be optimal in my opinion, 15 may be the limit.

If server is very fast you may achieve same effect by lowering bdetect_mp_per_frame_emulation_frame_d to 0.015.

It should give good results as long CPU load on server is not a matter.

---------- Post added at 14:09 ---------- Previous post was at 13:47 ----------

If you two can come up with an MP compatible bDetect the Arma community will nominate you both for a Nobel Prize.

At least we were able to gather some more bullets.

As long as you have a pretty fast server and the mission itself is not putting it on its knees, now you should be able to see suppression effects, at least for AI units local to the server.

A dedi server capable of keeping stable 40-50fps should cut it, waiting for BIS fixes ...

Edited by fabrizio_T

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×