Many vehicles/guns (incl M45 & FlaK 38) cannot be damaged by blast damage

Issue #463 resolved
Colin Basnett created an issue

In general the M45 & FlaK 38 seem completely invulnerable to splash damage.

Comments (5)

  1. Matt Hands

    Shows HE explosion close to Cromwell, which has hull origin modeled on the ground, with red debug line showing how trace for any shielding terrain disappears into the ground. Green line shows trace to Location with raised Z offset, which would hit the vehicle correctly, without meeting a blocking obstacle.

  2. Matt Hands

    Ok, I've thoroughly investigated this and I see what's causing the problem and have two solutions. As usual, it's a symptom of a much wider problem, nothing specifically about the M45 or FlaK 38.

    This lack of blast damage affects any vehicle hull/base, which includes AT guns, that have been modelled with the mesh origin on the ground, rather than in the middle of the mesh (in terms of Z). The blast function traces from the point of explosion, which is usually on the ground, to the Location of any colliding actor within range. If any terrain or a vehicle is in the way, the actor is considered shielded & no blast damage is done.

    The actor's Location is its mesh origin, so if the origin is in the ground, the trace becomes a ground-hugging daisy-cutter and any slight ground protrusion will block it. Even on perfectly flat terrain like the target range map, vehicles and guns tend to sink slightly into the ground, so their Location ends up being slightly below ground and the trace is always blocked. You can see this very clearly on the screenshot I've uploaded of an HE blast near a Cromwell: the red line is the original trace, disappearing into the ground (the green line is a modified trace to a slightly higher point). That's what is happening very visibly to our two new weapons - but it also happening less obviously to may other vehicles.

    RO hulls are all modelled with the origin roughly centrally in Z, but DH models are split between the two methods. There is some logic in the 'ground origin' method, although it is coming back to bite us here. Ground origin models include all Shermans, Cromwell, Stuart, Greyhound, Wolverine/Achilles, Jackson, Higgins boat, Jagdpanther and the 88m gun. And I've rigged the M45 and FlaK 38 in the same way.

    One pretty simple fix for the two new weapons would be to re-rig the bases with a raised origin. Pretty quick since the bases have no anims to re-make. On current maps their placement would then be slightly below ground, but I'm pretty sure the physics would push them up, so they would spawn ok. And it would also be quick to edit those maps. But it won't solve the wider problem - and I feel we need to.

    A little background on blast damage: It's always caused by the function HurtRadius(), which is a server/authority only function, as with all damage. It gets called when a shell explodes. At its heart is a foreach VisibleCollidingActors iteration. The colliding part is fairly efficient, as it iterates over the 'collision hash', identifying colliding actors within the specified blast radius (although we are warned against very large radius checks). But the 2nd, 'visible' part isn't very efficient, as it does a fast trace on every colliding actor to check it can be 'seen' from the point of the explosion.

    There are invisible, non-blocking, colliding actors that get caught in this, which blast should not be concerned with, e.g. VehicleAvoidArea actors. Standard advice is if we are applying our own checks that would screen out a fair proportion of colliding actors, to instead use the faster CollidingActors iterator, then apply our own script checks, then perform our own FastTrace only on those that are relevant. But in this case it's an absolute no-brainer ! Because HurtRadius() performs a full trace on every visible colliding actor, just to check whether a vehicle would shield it from blast. So that full trace is just repeating the FastTrace already done along the same path. What we need to do is use CollidingActors, then check for bBlockActors=true (screening out the invisible/irrelevant actors), then do the trace to see if EITHER terrain or a vehicle is in the way. The need for this trace makes the FastTrace totally redundant. I've stopwatched this using both methods over a loop of 1000 iterations and the revised method I describe above is typically around 8 times faster in execution! But doing our own 'visible' trace also allows us to control the point we trace to, giving us a means of fixing this problem.

    So, on to the two solutions. Firstly, I can trace to a point above the vehicle's Location/origin. Now we have control over the 'visible' check (i.e. not screened by something), we can choose where we trace to. On the flat target range, an increase in Z by as little as 2 units (33mm) caused the hit to register. On more realistic bumpy terrain it needs more Z offset. A sensible point would be to trace to roughly the vehicle's centre of gravity. Arbitrarily, we could always trace to say 10 units above the origin. Rather hacky. A better way would be to add a float in DHArmoredVehicle, allowing us to specify a location/COG/blast check Z offset. For ground origin meshes, it would just need a quick check in a modelling programme to see how many units up we need to go. AT gun bases all extend DHArmoredVehicle, so it would cover everything in my list above, except the Higgins. And the nature of the Higgins means this isn't really a problem, because it will always be on water, and a shell exploding in water plausibly isn't going to blow the boat up anyway. So it needs a little work, but not much, and it is a pretty clean solution, I think.

    The second option is to use the fact that VehicleWeapons are pretty reliably caught in the blast check. Originally VWs did not take any damage, i.e. even if we called TakeDamage() on them, nothing happened. Projectiles originally called TD on a turret's base vehicle, if they hit a turret. I changed that so that projectiles now call TD on the VW and let that decide what to do. A cannon now simply passes TD on to the vehicle, so damaging it as before. An MG now does nothing by default with the damage (as before), but allows TD to be subclassed so, for example, a hit on a top-mounted MG can easily be made to wreck that MG. This change is important because HurtRadius() is hitting things like M45 turrets, so that gives us the potential to use that to cause blast damage to the vehicle, even if its base isn't 'hit'. The problem currently is that the trace for any blocking actor always hits a turret's base, so the base/vehicle is shielding its own turret from damage! But that's easy to fix by ignoring any shielding actor if it is a VW's own base. The turret will then pass the damage on to the base. That does raise the problem of a vehicle potentially being blast damaged twice - once on the hull/base and once on the turret, but that's a separate issue and again is easily dealt with.

    Hope you followed all that folks! :) I'm tending towards solution 2, which I've tested and appears sound, without the need for settings in individual vehicles. I'll get it committed and you can try it out.

  3. Matt Hands

    Fixed in ce1289e.

    I came up with a better solution: an armoured vehicle (includes AT gun) always has an attached turret, so we can use the Z location of the turret attachment bone as a good Z location for a blast damage trace. In other words, we end up tracing to the height where the cannon mesh attaches to the hull.

    For turreted vehicles this works very well, as it gives a natural centre mass point for the overall vehicle, which is the ideal. And for German casemate tank destroyers its also a very good centre point in Z, being about half way 'up' the hull structure. For AT guns (which are based on a DHArmoredVehicle) it ends up being exactly the same as if we trace hits on the cannon actor, as the cannon mesh's origin/location is always at the hull/cannon attachment point.

    Guns with a very low base, like the M45, flakvierling or static based FlaK 38, will always have a relatively low blast trace point. But they still get blown up pretty reliably, unless there's some jagged terrain that shields their bottom section. So I think it's a good solution even for them.

    With this method I skip blast damage effects on cannons, to avoid the possibility of doubling up blast damage on the same vehicle, i.e. register damage on both hull and turret.

    Uses CollidingActors instead of VisibleCollidingActors, which is a much faster iteration. The trace we do to check for any blocking vehicle makes the extra trace in VisibleCA pointless anyway.

  4. Log in to comment