OpenXcom Forum

Modding => OpenXcom Extended => OXCE Suggestions DONE => Topic started by: Delian on March 20, 2022, 01:43:18 pm

Title: [Bug] Damage display when holding alt key
Post by: Delian on March 20, 2022, 01:43:18 pm
When you're aiming at an enemy and have a crosshair shown, you can hold the alt key to display the possible damage range. It's possible that the displayed damage is incorrect if the weapon has a "Power reduction/tile" rule. This probably happens because the calculated distance is rounded precisely, instead of rounded up, like the game normally does with distances.

For instance, let's say a weapon has a powerRangeThreshold of 10 tiles and you're x=10 and y=1 distance away from the target. Normally, the game would consider this as a distance of 11m (10.05m rounded up). If you hold the alt key, the displayed damage will be reduced by 1x powerRangeReduction. However, according to my tests, the actual damage is not reduced.

I'm assuming that the distance is rounded correctly so that melee weapons with 1 range can function correctly on targets vertically (x=1,y=1) 1 tile away. That's fine, but then, the displayed crosshair damage should take this correct rounding into account, which it currently does not.
Title: Re: [Bug] Damage display when holding alt key
Post by: Meridian on March 20, 2022, 03:02:27 pm
When you're aiming at an enemy and have a crosshair shown, you can hold the alt key to display the possible damage range. It's possible that the displayed damage is incorrect if the weapon has a "Power reduction/tile" rule. This probably happens because the calculated distance is rounded precisely, instead of rounded up, like the game normally does with distances.

Wrong. The calculated distance (for the alt display) is rounded up:

Code: [Select]
int distanceSq = action->actor->distance3dToPositionSq(Position(itX, itY,itZ));
int distance = (int)std::ceil(sqrt(float(distanceSq)));

For instance, let's say a weapon has a powerRangeThreshold of 10 tiles and you're x=10 and y=1 distance away from the target. Normally, the game would consider this as a distance of 11m (10.05m rounded up). If you hold the alt key, the displayed damage will be reduced by 1x powerRangeReduction. However, according to my tests, the actual damage is not reduced.

Ruleset is in tiles.
Alt display calculates in tiles.
Actual power reduction calculation is in voxels (exact projectile trajectory length).

Since display is rounded up to whole tiles, there can be a difference at the end.

I'm assuming that the distance is rounded correctly so that melee weapons with 1 range can function correctly on targets vertically (x=1,y=1) 1 tile away. That's fine, but then, the displayed crosshair damage should take this correct rounding into account, which it currently does not.

Melee weapons don't use power reduction at all.
"Projectile trajectory length" is zero both in straight and diagonal direction.

If you meant ranged weapons with range 1, it works the same way as for any other range, there is no special case handling.
Title: Re: [Bug] Damage display when holding alt key
Post by: Delian on March 20, 2022, 04:27:31 pm
Wrong. The calculated distance (for the alt display) is rounded up:

Ah, sorry, yes, that's what I meant. When holding the alt key, it uses a rounded-up distance. (I never liked this rounding up heh)

Still, the problem remains. The alt-displayed damage isn't correct. Something must be terribly wrong if the amount of voxels travelled (optimal path) produces a distance that is less than the one used for alt-display. Because that would imply that the visible distance can be greater than the actual distance, which logically doesn't make sense since the visible distance should be the shortest distance to the enemy. But even if we ignore this logical conundrum, the alt-displayed damage should still do a better job trying to estimate the damage. It should try to use the voxel distance instead of the visible distance then.

If you meant ranged weapons with range 1, it works the same way as for any other range, there is no special case handling.

What's that stuff in the Mod/RuleItem::isOutOfRange() then? ;)

Yeah, some melee weapons are disguised ranged weapons.
Title: Re: [Bug] Damage display when holding alt key
Post by: Meridian on March 20, 2022, 04:58:23 pm
Ah, sorry, yes, that's what I meant. When holding the alt key, it uses a rounded-up distance. (I never liked this rounding up heh)

Still, the problem remains. The alt-displayed damage isn't correct. Something must be terribly wrong if the amount of voxels travelled (optimal path) produces a distance that is less than the one used for alt-display. Because that would imply that the visible distance can be greater than the actual distance, which logically doesn't make sense since the visible distance should be the shortest distance to the enemy. But even if we ignore this logical conundrum, the alt-displayed damage should still do a better job trying to estimate the damage. It should try to use the voxel distance instead of the visible distance then.

In worst case, the difference can be almost 2 whole tiles.
On the attached picture, the trajectory is ~10.1 tiles long (real length), and 12 tiles long (in tile math).

Anyway, everything is as designed, there is no bug.
If the display approximation bothers you, feel free to implement a crosshair that targets voxels instead of tiles; or just go vanilla and don't use it :)

What's that stuff in the Mod/RuleItem::isOutOfRange() then? ;)

It's used for something else.

If you found the method, I'm sure you can find where it's used too ;)
Title: Re: [Bug] Damage display when holding alt key
Post by: Delian on March 20, 2022, 05:29:06 pm
Meh, I don't have C++ dev environment installed.

Ok. Hmm, is there a case where you actually need the voxel distance? Like, you said that the actual distance is the voxel distance. But would it cause any problems if this was changed into a simple tile distance? Tile distance between the attacker and the tile in which the projectile landed? Or, if the tile distance was used only for the purpose of calculating the range-reduced damage? It's not a vanilla feature anyway.
Title: Re: [Bug] Damage display when holding alt key
Post by: Meridian on March 20, 2022, 05:43:50 pm
Meh, I don't have C++ dev environment installed.

Ok. Hmm, is there a case where you actually need the voxel distance? Like, you said that the actual distance is the voxel distance. But would it cause any problems if this was changed into a simple tile distance? Tile distance between the attacker and the tile in which the projectile landed?

Depends on person's definition/meaning of the word "problem".

Using tile distance instead of voxel distance would produce different results.
I personally don't care much in this case, but I guess nitpickers would call it a huge problem.

If I had to change it, I would add a config setting anyway... changing behavior without backwards-compatibility would just make modders go after me with torches and pitchforks.
Title: Re: [Bug] Damage display when holding alt key
Post by: Delian on March 21, 2022, 04:42:42 pm
I've done a few more tests and I've come to a conclusion that... using voxel distance is bugged.

For instance, my distance from the enemy is x=10, y=26. So tile distance is 27.86. But the voxel distance? 30. So first the distance was smaller, but in this case it's larger?

would just make modders go after me with torches and pitchforks.

I'm pretty sure no one actually tested this and they just assumed that tile distance was used.
Title: Re: [Bug] Damage display when holding alt key
Post by: Meridian on March 21, 2022, 05:04:10 pm
I've done a few more tests and I've come to a conclusion that... using voxel distance is bugged.

For instance, my distance from the enemy is x=10, y=26. So tile distance is 27.86. But the voxel distance? 30. So first the distance was smaller, but in this case it's larger?

How did you test voxel distance?
Using c++ dev environment? (I can't think of any other way to test it atm)

If you give me a save and exact instructions how and what to reproduce, I can debug and explain what's going on in detail for that particular scenario.

However, I have to say that I am 99.9% sure it works correctly, and I am not looking forward to (likely) waste my time.

I'm pretty sure no one actually tested this and they just assumed that tile distance was used.

It was extensively tested by Yankes; and it was tested also by modders, for example in Piratez.
Title: Re: [Bug] Damage display when holding alt key
Post by: Delian on March 21, 2022, 06:07:21 pm
I tested it in game. I attached the savegame (piratez ver: v.M4.1.2 OXCE 7.4 10-Jan-2022) demonstrating the bug.

Use the soldier to attack the enemy (Megapol Wolfman hp=48 stun=47) with the Wand of Peace.
Expected result: enemy should be knocked unconscious
Actual result: no damage (enemy gets hit but the hit log registers it as a miss due to damage being less than 0)

The friendly unit has psiStrength: 73. Wand of Peace does 0.01 x psiStrength² damage. 0.01x73x73=53.29 (rounded to 53). So average damage is 53.
Tile distance to the enemy is 27.86->28 tiles. Wand of Peace has damage reduction of 3 per tile after 12. So at 28 tiles, the damage should be reduced by 16x3=48. After hit, the actual damage should be 2.5 - 7.5 (rounded to 2-7, as shown on the alt-key display; Wolfman has 175% CHARM res, so the actual final damage range should be 3.5-12.5 (rounded to 3-12)).

However, due to the "voxel distance" being 30, the actual damage is reduced by 18x3=54.
Title: Re: [Bug] Damage display when holding alt key
Post by: Meridian on March 21, 2022, 07:25:15 pm
I'll check tomorrow.
Title: Re: [Bug] Damage display when holding alt key
Post by: Meridian on March 22, 2022, 10:44:13 am
Tile distance is ~27.86, rounded up to 28.

Projectile trajectory length is ~474 voxels (~29.625 tiles).
The attached text file contains all 409 voxels in the trajectory, with the contribution of each step and the subtotals.
Title: Re: [Bug] Damage display when holding alt key
Post by: Delian on March 22, 2022, 11:18:24 am
So, it looks like the produced trajectory length is incorrect.
Title: Re: [Bug] Damage display when holding alt key
Post by: Meridian on March 22, 2022, 11:35:33 am
So, it looks like the produced trajectory length is incorrect.

Dude, what's wrong with you?

The trajectory length is absolutely 100% correct, I gave you even the entire derivation of it... if you want, calculate and check it by hand.
Title: Re: [Bug] Damage display when holding alt key
Post by: Meridian on March 22, 2022, 11:57:55 am
Here's a few examples to illustrate the difference between "distance between two points" and "trajectory length".

Hopefully it helps.
Title: Re: [Bug] Damage display when holding alt key
Post by: Delian on March 22, 2022, 02:08:58 pm
Thank you for the examples. I think the example of non-arcing weapons correctly shows the issue, but the arcing weapons and the waypoints weapons do not. I've attached an example for an arcing weapon (side view).

As you explained, there's a difference between a "distance between two points" and "trajectory length", I agree with this.
But what I'd like to point out is the difference between "precise trajectory" and "approximate trajectory". The approximate trajectory is trajectory that is approximated to voxels, but otherwise tries to follow the line/curve of the precise trajectory. You've already snown this on your non-arcing example, but just for the sake of clarity, I've attached an edit where I've rearranged the black lines so that we can easily see why the voxel-approximated trajectory length is longer than the simple distance between two points.
Anyway, what I'm trying to argue here is that, a projectile that follows a trajectory, the total distance that it travelled should come from the "precise trajectory" and not from the "approximate trajectory", even though the projectile was drawn following the approximate trajectory.
In case of an arcing trajectory, the distance should be the length of the precise trajectory curve (not the shortest distance). In case of waypoints, the distance should be the sum of line lengths between waypoint voxels.

If we return to the savegame I provided, the starting voxel is 200,207,18 and ending voxel is 359,614,15, right? In this case, the precise trajectory length would be the distance between these two voxels.
sqrt ( (359-200)² + (614-207)² + (15-18)² ) = 436.9657 -> 27.3104 tiles. But if we add up the lengths between voxels in the approximate trajectory, then we get a distance of 29.625 tiles.

Which distance is the correct one?
27.31 tiles of the precise trajectory?
27.86 tiles of the visible distance?
29.62 tiles of the approximate trajectory?

You've convinced me that the trajectory length should be used instead of the visible distance. But then, I think it should be the precise trajectory.
But why? Why should we use the length of the precise trajectory instead of the approximate trajectory? Well, that's because, to begin with, I think the main purpose of the "approximate trajectory" is for graphical drawing and for hit tests. It was never supposed to have been used to measure any distance, because, as an approximation, it can produce weird results.
Title: Re: [Bug] Damage display when holding alt key
Post by: Meridian on March 22, 2022, 04:26:23 pm
Thank you for the examples. I think the example of non-arcing weapons correctly shows the issue, but the arcing weapons and the waypoints weapons do not. I've attached an example for an arcing weapon (side view).

For alt display of arcing weapons, the zig-zag trajectory "issue" is negligible, because the arc itself makes the length much longer than if it was just a straight line.
So the alt display is completely off anyway.

For waypoint weapons, it's even more visible, there you can shoot five times around the whole map and target yourself at the end... distance=zero, length="as long as you want".
The alt display is currently practically useless here if the weapon has range power reduction.

Anyway, what I'm trying to argue here is that, a projectile that follows a trajectory, the total distance that it travelled should come from the "precise trajectory" and not from the "approximate trajectory", even though the projectile was drawn following the approximate trajectory.

It's really not simple.

At the point of impact, we don't have the "length of the precise trajectory" anymore.
And recalculating it from just the start point and the impact point is not straightforward... for example for arcing trajectories there is an unlimited number of parabolas between point A and B with different heights.
Also, there is RNG involved, we don't try all parabolas (obviously), just a few based on RNG... btw. that's why we can't predict trajectory length before we actually shoot.

And for alt display, there's yet more problems.
Even with having "precise trajectory" and even just considering straight line trajectories... the display just considers zero deviation... and no obstacles.
But the ideal trajectory (zero deviation) and the actual trajectory (with deviation) can easily be different.
Even two hits of the same tile/unit can have quite different results depending on whether you hit a unit at [0,0,0] or [15,15,23]... that's ~1.95 tiles difference! And for a 2x2 unit, the difference can be up to ~4.01 tiles.
And let's not even start with non-square tiles, we don't even have equal "distances" between all neighboring voxels... moving 16 voxels horizontally translates to moving 1 full tile, moving 16  voxels vertically translates to moving only ~0.666 tiles.


Bottomline:
1. in my opinion, the damage calculation is decent enough, serves the intended purpose and doesn't have bugs (i.e. works exactly as designed)
2. we could make a different one, but there's a LOT of things to consider... IMO not worth it
3. the alt display calculation is just a crude approximation given many limitations, some of which *cannot* even be worked around... it is objectively imprecise, but it's the best I can do
Title: Re: [Bug] Damage display when holding alt key
Post by: Delian on March 24, 2022, 12:35:18 pm
Well, let's say that alt-display works well enough. Let's forget about that.

I'm more worried about the distance calculation, since I personally think it's currently not precise enough for the range-reduced damage. But as you say, it would be too much work to make the calculation perfect for every case. Hmm.

Ok, I have two relatively simple propositions.

1. In the Projectile::getDistance() we're returning the calculated approximate trajectory distance used for range-reduced damage.
I propose that we add an if statement there, if it's a non-arcing projectile and without waypoints, then return a distance calculated from the first and the last voxel in the trajectory.
Code: [Select]
if (_action.type != BA_THROW && _action.type != BA_LAUNCH && !_trajectory.empty())
{
    return Position::distance(_trajectory[0], _trajectory[_trajectory.size() - 1]);
}
else
{
    return _distance;
}

2. In the Projectile::move(), we're adding up distance based on the last 1 voxel (either √1, √2 or √3).
I propose to increase accuracy of this by adding up distance based on the last 2 voxels. (half of the distance between the last two voxels)
Code: [Select]
if (_position > 1)
{
    _distance += Position::distance(_trajectory[_position], _trajectory[_position - 2]) / 2;
}
else
{
    _distance += Position::distance(_trajectory[_position], _trajectory[_position - 1]);
}
Title: Re: [Bug] Damage display when holding alt key
Post by: Meridian on March 24, 2022, 01:07:10 pm
For potential changes, Yankes will need to approve. (It's his feature.)
Title: Re: [Bug] Damage display when holding alt key
Post by: Yankes on March 24, 2022, 02:03:04 pm
I could agree to only second change aka, make distance step bit more accurate. First change is nogo as it not handle correctly arcing shots and make big difference between them and linear shots, especially when arcing shoot is very shallow.
Title: Re: [Bug] Damage display when holding alt key
Post by: Meridian on March 24, 2022, 02:14:02 pm
@Delian: Just to maybe clarify on point 1... "_action.type != BA_THROW" doesn't represent arcing shots. You can also have arcing shots for example on BA_SNAPSHOT and other actions.
Title: Re: [Bug] Damage display when holding alt key
Post by: Delian on March 24, 2022, 02:52:17 pm
Oops, sorry, you're right. The first proposition should be:
Code: [Select]
if (_action.type != BA_THROW && _action.type != BA_LAUNCH && !_action.weapon->getArcingShot(_action.type) && !_trajectory.empty())
{
    return Position::distance(_trajectory[0], _trajectory[_trajectory.size() - 1]);
}
else
{
    return _distance;
}
Title: Re: [Bug] Damage display when holding alt key
Post by: Yankes on March 24, 2022, 03:37:06 pm
Yes, but this is only half solution, bigger problem is that you can make very flat arc weapons, in theory they should have path distance close to strength line path distance, when we add this `if` we have two different values.

If we look now on circle and try measure distance from center using current code there are 8 points where `_distance` match 2d distance.
When we add this "avg" operation for each step, number of correct points is 16. And more importantly all other points have error reduced a lot.

I do not know if complicating further code is beneficial, especially if this `if` add more special cases.
Title: Re: [Bug] Damage display when holding alt key
Post by: Delian on March 24, 2022, 05:29:52 pm
bigger problem is that you can make very flat arc weapons, in theory they should have path distance close to strength line path distance, when we add this `if` we have two different values.

There's a hardcoded minimum parabola curvature value of 0.48, so I don't think you can make flat arc weapons. Arcing and non-arcing weapons will always have somewhat different distances, with or without the "if" statement.

Yes, it's only half of the solution, but wouldn't the full solution be difficult to implement?

I do not know if complicating further code is beneficial, especially if this `if` add more special cases.

It's your choice, but in my opinion, I don't think that adding the "if" statement there adds any complexity, because there's already plenty of code that handles arcing and non-arcing weapons in a different manner.
Title: Re: [Bug] Damage display when holding alt key
Post by: Yankes on March 24, 2022, 05:57:07 pm
Adding one `if` is indeed trivial, but you not see long term cost and increasing conceptual complexity.
Current answer for "what voxel distance is" is very very trivial `return _distance;`, no special cases, what value is we return it.
After your change answer will not be that trivial, and when I would like change handling of voxel trajectory I would need check this `if` to see if he
need updates too.
One of my goals in OXCE was remove `if` like this, I would even consider polynomial calculation of `_distance` than adding special cases.
Title: Re: [Bug] Damage display when holding alt key
Post by: Yankes on March 24, 2022, 11:19:41 pm
I pushed in new version update with:
Code: [Select]
_distance += Position::distance(_trajectory[_position], _trajectory[_position - 2]) / 2;
Save test case work fine now, enemy get stunned.
Title: Re: [Bug] Damage display when holding alt key
Post by: Delian on March 25, 2022, 01:25:29 am
Thanks :)

Altho it may take a while until the next version of X-Piratez before I'm able to test it.
Title: Re: [Bug] Damage display when holding alt key
Post by: Yankes on March 25, 2022, 01:41:51 am
You could replace exe, we recently did not do any big breaking changes and XPZ should work with new exe.
Title: Re: [Bug] Damage display when holding alt key
Post by: Delian on March 27, 2022, 11:38:14 pm
Where do I get the new exe?
Title: Re: [Bug] Damage display when holding alt key
Post by: Yankes on March 28, 2022, 01:29:23 am
https://lxnt.wtf/oxem/#/Extended
Title: Re: [Bug] Damage display when holding alt key
Post by: Delian on March 28, 2022, 03:19:57 am
k, works

thread can be closed