ACE3 icon indicating copy to clipboard operation
ACE3 copied to clipboard

Frag - Rewrite

Open lambdatiger opened this issue 2 years ago • 31 comments

When merged, this pull request will:

  • ~~Removes old system of tracking rounds by PFEH, instead adds relevant EHs at round init~~
    • ~~Reworked dev functions to use EHs~~
    • ~~Uses EventHandler subclass to avoid conflicts with other round init EH~~
  • ~~Only called/tracked on server~~
  • Adds new config value ace_frag_fragCount that represents the maximum number of fragments created
    • Chance to hit dependent on the number of fragments generated by an explosive combined with target distance and appros crosssection $$P_{hit} = A_{target}\frac{N_{frag}}{4\pi\cdot distance^2} | P_{hit} \leq1$$
    • The same statistical sphere approach generates a more accurate range to search for entities to hit
  • Break base fragmentation function into targeted / random fragmentation
    • Allows for toggling between one or both of the options
  • Transition spawning of multiple rounds to using submunitions
    • ~~Spalling uses a single submunition spawner~~
    • Targeted frag uses either a single round or a spawner depending on the number of rounds targeted
    • Random fragmentation calls a single submunition spawner
  • ~~Transition caching to new BI hashMaps for cached simulation values~~
  • ~~Allows submunitions to fragment~~
  • ~~Fragmentation and spalling events now correctly inherit shotParents parameters~~
  • ~~Moves fragmentation blacklist to ACE Frag setting~~
  • Update relevant wiki documentation to reflect changes to the config entries
  • CBA setting QGVAR(enable) now only controls fragmentation, it no longer controls spalling as well.

I’d appreciate constructive feedback and criticism!

Todo

  • [x] Move back to Fired EH
  • [x] Initial Multiplayer testing
  • [x] Spin off basic event handler and debug function transition to it's own PR: https://github.com/acemod/ACE3/pull/10157
  • [x] Spin off spalling into a secondary PR: https://github.com/acemod/ACE3/pull/10247
  • [ ] Rebase current PR based off spin-off PRs
  • [x] ~~More complete multiplayer testing~~
  • [x] ~~Revert fnc_addBlackList.sqf to remove event handlers instead.~~
  • [ ] String table translations

lambdatiger avatar Jan 11 '24 01:01 lambdatiger

Alright, I didn't see anything else that doesn't fit with ACE coding guidelines doing another pass on the PR. I might expand the documentation a bit more, but I'll try to leave the code alone until further review/feedback. Let me know if I missed anything, and thanks for the other recommendations so far.

lambdatiger avatar Jan 17 '24 04:01 lambdatiger

I see that you have tested in MP. What was the setup? The reason I ask is because the wiki claims that some of the projectile EH use local arguments only (see https://community.bistudio.com/wiki/Arma_3:_Event_Handlers#Projectile_Event_Handlers). Do you know if the wiki is wrong or if projectiles are always local to the server (which I really don't think they are, but I haven't tested myself)?

I don't know about the event handlers, but I believe projectiles are always local to the shooter.

Drofseh avatar Jan 17 '24 10:01 Drofseh

Ok, apologies for not demonstrating this first. So far, all the testing I've done uses two clients connected to a dedicated server (all local) and Clumsy to increase ping between the server and clients (generally ~150ms). In addition, I used the code for debugging provided in this PR. The debug code is not 100% good for MP, but you still get spheres for events as described below (you could sync the round-tracking hashmaps if you wanted, but they can get big).

I initially wrote this PR to be server event-driven, similar to the current stable ace_frag. When Veteran mentioned that rounds are local on the server and to the client firing, I wanted to check because how he said it confused me. image Figure 1. Veteran's statement on round locality

Testing using this mod, I've seen two things:

  1. You can add multiple init round event handlers, and they both get called, as demonstrated in the image and video below. eventhandlers Figure 2. Two different mod init event handlers appear in the config viewer and can be seen working in the video below.

  2. While the rounds may not contribute to damage, every event handler is fired, so everyone gets a local copy. This is clear from looking at the following video. The first part demonstrates singleplayer, with debug mode enabled, showing round tracking and colored spheres for different events, generally green for hits, red for explode, yellow for hits, and blue for deflections. The second part demonstrates the locality of the init and hit event handlers, with every round being initialized on all clients. The final portion demonstrates frag grenades thrown and calling the doFrag function, which is only called through the init event handler in this PR (impact sphere indicates the server is tracking). https://www.youtube.com/watch?v=DfXHOZ8pJwM

lambdatiger avatar Jan 17 '24 23:01 lambdatiger

~~I've noticed shotParents sometimes gets lost for ACE advanced thrown grenades since they are created using createVehicle and don't seem to be propagated the same way vanilla thrown grenades are. Specifically, it seems that, sometimes, before the projectile "Explode" event handler is called, the shotParents are cleared when the grenade isn't originally local to the server. A fix that works reliably is to use setVariable/getVariable with the ace_common_setShotParents CBA event since object variables seem to be cleared after the "Explode" event handler is called.~~

~~I'll look into it further to see if there's an error with how the PR is currently retrieving shotParents or with how shotParents is handled, but if anyone has input,~~ I'd be interested to hear it. Resolved, see https://github.com/acemod/ACE3/pull/9728/commits/33afd8ab33edf567ff5a61189d3a80ae7e0d25ca

lambdatiger avatar Jan 19 '24 01:01 lambdatiger

First, thanks for all the feedback so far/help (especially @johnb432). Second, I know if this PR is reviewed/merged, it'll need updates to all the compats, including the forthcoming CUP compat. Should I add those here or create a seperate PR after this gets through review?

lambdatiger avatar Feb 08 '24 23:02 lambdatiger

Separate PR

LinkIsGrim avatar Feb 09 '24 00:02 LinkIsGrim

Did I miss a review from you @johnb432? I notice you still have pending requested changes but I don't see anything unresolved. Also thanks for continuing to make changes/reviews, sorry that the PR wasn't so neat before I marked it for review.

lambdatiger avatar Mar 03 '24 01:03 lambdatiger

It will show requested changes until @johnb432 reviews it again.

jonpas avatar Mar 03 '24 14:03 jonpas

What are the differences between the old and this version when it comes to fragmentation generation? Is there more or less fragmentation?

johnb432 avatar Apr 10 '24 21:04 johnb432

What are the differences between the old and this version when it comes to fragmentation generation? Is there more or less fragmentation?

Direct Answer

Starting with the bounds, the maximum number of targeted fragments is the same, while the maximum number of total fragments is higher for the PR. Based on the number of targets hit, this PR produces fewer fragments for fewer targets, but more fragments when the number of targeted units exceeds ten. This is because fragments created without a target are created using the ammo submunition system rather than calculating trajectories like the current version, and only a few classes are created. You can see a graph of the two below. Graph2

The big difference between this PR and the current ACE_Frag is that while this PR generates more fragments on average based on targeted fragments, it should create fewer targeted fragments. Specifically, this PR does not generate fragments for targets that would not be hit. This approach differs from the current approach of aiming off the center of the target and relying on the randomness of the target position to decide whether a target is hit. The obvious downside is that the player does not always hear very near misses. To make up for this, more random fragments are generated to create the same effect as hearing fragments hit nearby.

More Details

The simulation for fragments in this PR relies on approximating fragments generated by an explosive as being mostly interdependently and uniformly distributed in a sphere. Target crossectional area ($A_target$) and the number of fragments generated are used to calculate the probability and how many (if any) fragments should hit the target. The independent part comes in as we only track the number of fragments per 2-D direction from the explosion, setting upper limits per arc. To limit the impact of acquiring targets in a large area, a maximum distance is chosen based on a minimum change to hit of 0.5%, and objects farther than that are not "targeted." Finally, a random fragment generation component is introduced to achieve some of the aforementioned effect of hearing misses/near misses.

Here's a comparison of some of the equations to help understand the differences better.

System Current calculation PR calculation
Should Frag (not skipped or forced) $explosive > 0.5$,
$indirectHitRange \geq 4.5$, and
$indirectHit\cdot\sqrt{indirectHitRange} \geq 35 $
$explosive \geq 0.4$,
$indirectHitRange >5$,
$indirectHit >3$, and
$indirectHit > indirectHitRange$
Fragment Range $$80\cdot indirectHitRange$$ $$min\empheqbiglbrace565,\sqrt{\frac{N_{frag}}{4\pi P_{hit,min}}}\empheqbigrbrace$$
565 m is the range for 0.5% chance to hit for 20k fragments
Fragment Aimed Position Hit box center minus $R_{offset}$, $R_{offset} =$ $B\cdot[1 + \text{random}\ 2, 1 + \text{random}\ 2, 1 + \text{random}\ 2]$ $ B=\frac{10^{-6}}{\sqrt{Volume_{hitbox}}}$ Weighted random skeleton hit point for classes inheriting from CAManBase or random position within the hitBox for everything else
Fragment Hit Chance Not really straight forward, more left to simulation and fragment selection. For example, most high drag fragments do not hit after ~30 m. $$\text{random}\ min\empheqbiglbrace 1, A_{target}\frac{N_{frag}}{4\pi\cdot distance^2}\empheqbigrbrace$$
Number of fragments per target
($NTF_i$)
$$\empheqbiglceil \text{random}\sqrt{\frac{mass_{metal}}{1000}}\empheqbigrceil$$ $$\empheqbiglceil A_{target}\frac{N_{frag}}{4\pi\cdot distance^2}\empheqbigrceil$$
Number of random fragments
($NRF$)
Ceiling of 35% of the remaining fragment budget, specifically $\empheqbiglceil 0.35\cdot N_{frag,remaining} \empheqbigrceil$ If the remaining fragment budget is:
- 0 for a budget $\leq$ 3
- 4-7, then five fragments
- 8-12, then ten fragments
- 15 for a budget $\geq$ 13

Common value $$Velocity_{fragment,max} = 0.8\cdot Constant_{Gurney}\sqrt{\frac{mass_{charge}}{mass_{metal}+mass_{charge}\cdot Constant_{geometry}}}$$

lambdatiger avatar Apr 14 '24 00:04 lambdatiger

Apologies about making more changes, but I'm about 70% through all the compats (CDLC/RHS/CUP) and had some config changes to make. I also caught some incorrect config entries in the frag spawner class definitions, so I changed those to macros to make it easier to guarantee that it's error free. Finally, there was a math error with maximum range that may have been spawning more fragments than usual when the "Disable Fragment Misses" was enabled.

lambdatiger avatar Apr 14 '24 02:04 lambdatiger

Direct answer

I'm gonna trust your math.

LinkIsGrim avatar Apr 14 '24 15:04 LinkIsGrim

I asked my question only because I noticed a difference when throwing a grenade as a unit, hitting themselves only. In the old version there were more fragments hitting the unit (2-3 fragements in the old vs 0-1 for the new). In the new version, seemingly the unit that throws the grenade is not targeted as much as another player unit in the area. There's no reason for this to happen, at least not code-wise and I didn't investigate it thoroughly, so for the moment at least we can leave it aside.

I'm about 70% through all the compats (CDLC/RHS/CUP) and had some config changes to make.

I'm guessing that those are in a separate PR, as discussed previously?

I'm gonna trust your math.

I was too, but it's a bit unsettling to see non-trivial changes when in my mind, this PR was pretty much ready to go. Can you provide your sources? I think adding them to the documentation would be interesting.

johnb432 avatar Apr 16 '24 08:04 johnb432

I asked my question only because I noticed a difference when throwing a grenade as a unit, hitting themselves only. In the old version there were more fragments hitting the unit (2-3 fragements in the old vs 0-1 for the new). In the new version, seemingly the unit that throws the grenade is not targeted as much as another player unit in the area. There's no reason for this to happen, at least not code-wise and I didn't investigate it thoroughly, so for the moment at least we can leave it aside.

Can you elaborate on that? How far away from the grenade are you?

I'm guessing that those are in a separate PR, as discussed previously?

Yes, I'll submit it once I finish gathering all the data and getting it entered into the configs

I was too, but it's a bit unsettling to see non-trivial changes when in my mind, this PR was pretty much ready to go. Can you provide your sources? I think adding them to the documentation would be interesting.

Sure! Here's the most readable source: https://man.fas.org/dod-101/navy/docs/es310/dam_crit/dam_crit.htm I'll make a write-up using what I originally used, which included some papers that are a little harder to digest.

lambdatiger avatar Apr 16 '24 18:04 lambdatiger

Can you elaborate on that? How far away from the grenade are you?

I was about 10 m away from the grenade when it exploded. The observation seems to fit in with your graphs.

johnb432 avatar Apr 19 '24 21:04 johnb432

I haven't reviewed the math in detail, but from what info you have provided this seems to implement it properly. At this point more intense testing is required, something that could be done in an RC.

johnb432 avatar May 09 '24 21:05 johnb432

Alright, sounds good. Sorry, I teach and it's a busy part of the year for me. I'll post the math explanation when I have a chance to edit it down a bit, but I'll finish the Compats first since I believe those are more important.

lambdatiger avatar May 09 '24 22:05 lambdatiger

Despite what I have previously said, we do want to keep FUNC(addBlacklist) for backwards compatibility. It should only handle individual objects and not class names. Disabling fragmentation for classes should happen via config. I'm pushing changes regarding this, but I haven't tested it.

johnb432 avatar May 18 '24 09:05 johnb432

Had a moment to test it, and it should work. As an alternative, may I suggest a version that; a) exposes the "Explode" or "HitPart" event handler, and b) doesn't require multiple getVariable checks. I think either is a good option, so let me know if you prefer one over the other.

I also was able to recreate a bug from someone I had testing it. I had thought createVehicle used ATL in most cases, but it uses posAGL for every vehicle spawned on/over water. The wiki phrases it so it sounds like Arma handles amphibious vehicles differently.

lambdatiger avatar May 19 '24 05:05 lambdatiger

doesn't require multiple getVariable checks

The problems there are:

  • FUNC(addBlacklist) can be run on any machine (it isn't restricted to server only), so removing EH will not work.
  • FUNC(addBlacklist) can be run at any time, as in there might be a delay between the projectile spawn and the variable being broadcast to the server. My solution takes that sort of behaviour into account, although it's not as efficient as removing the EH.

johnb432 avatar May 19 '24 08:05 johnb432

doesn't require multiple getVariable checks

The problems there are:

* `FUNC(addBlacklist)` can be run on any machine (it isn't restricted to server only), so removing EH will not work.

* `FUNC(addBlacklist)` can be run at any time, as in there might be a delay between the projectile spawn and the variable being broadcast to the server. My solution takes that sort of behaviour into account, although it's not as efficient as removing the EH.

You're right, I missed that you were broadcasting the setVariable in the addBlacklist function. As an alternative, we could make what I propose server event driven, since currently all projectiles are tracked on the server, but I'll revert for now.

The other option is to return the entire system to server event driven system and then we don't need to broadcast blacklists to mimic the current implementation where every client had their own blacklist.

lambdatiger avatar May 19 '24 18:05 lambdatiger

You're right, I missed that you were broadcasting the setVariable in the addBlacklist function. As an alternative, we could make what I propose server event driven, since currently all projectiles are tracked on the server, but I'll revert for now.

The other option is to return the entire system to server event driven system and then we don't need to broadcast blacklists to mimic the current implementation where every client had their own blacklist.

Setting the variable on the server only on a per object basis should suffice imo, which you have already implemented.

johnb432 avatar May 21 '24 10:05 johnb432

https://github.com/acemod/ACE3/pull/10002#discussion_r1631187574

johnb432 avatar Jun 07 '24 13:06 johnb432

#10002 (comment)

Alright, I should have time here the next few days to get it sorted out.

I'm still working through the last part of the research for the cDLC compats, but would it be preferable to split the PR into two so that the event handler optimization can go forward? The two parts would be:

  1. Upgrading ACE Frag to event handler driven. That is new debug setup and etc., but with old frag calculations
  2. Updated frag and spalling to be more accurately simulated.

lambdatiger avatar Jun 20 '24 05:06 lambdatiger

[...] but would it be preferable to split the PR into [...]

Definitely. Splitting it into more than 2 would be ideal if possible, but don't sweat it if it's not possible.

johnb432 avatar Jun 22 '24 15:06 johnb432

Alright, I need to stress test multiplayer events to see if there needs to be a cooldown period per client request sent considering this PR should see that some rounds (i.e., 30mm HE cannons from the A-10D) can fragment. But the initial version works in multiplayer, with all simulation types.

I plan to spin off the event handlers and debug functions into a single separate PR and maybe the spalling changes as well since I feel there's more than a week or two of work left on this and I don't want to delay a transition away from the current custom PFH system.

I'll make a few more posts in the coming days or weeks.

lambdatiger avatar Jul 17 '24 04:07 lambdatiger

Sorry about all the errors. I'll reinstall pboProject tomorrow and fix them before my next push. The removal of all the init event handlers left some holes I should've noticed, but I guess I need something to hold my hand through it.

lambdatiger avatar Jul 17 '24 05:07 lambdatiger

I'm unsure about what the issue is this time. It works on my side, and pboProject is spitting out a line that is from an older commit unless I missed something it should already be fixed. It may be the order it was merged in I guess.

lambdatiger avatar Jul 18 '24 03:07 lambdatiger

Hey, I've started the process of breaking this down into some more manageable PRs (also ones that don't rely on waiting on me to finish the Frag compats), So far I've split a large chunk into just addressing the event handlers, debug, and caching functions here: https://github.com/acemod/ACE3/pull/10157, but I will also take the changes to spalling to their own PR in the coming week.

lambdatiger avatar Aug 01 '24 03:08 lambdatiger