Author Topic: Health damage doesn't reduce attack damage  (Read 805 times)

Online Delian

  • Commander
  • *****
  • Posts: 657
    • View Profile
Health damage doesn't reduce attack damage
« on: February 28, 2025, 11:01:18 am »
If a soldier has a weapon that scales damage with stats, and your stats are reduced because the soldier is damaged, then attack damage should be reduced. It currently is not. The accuracy of the attack get properly reduced based on the soldier's current damage and wounds, but not the power.

Offline Yankes

  • Global Moderator
  • Commander
  • *****
  • Posts: 3435
    • View Profile
Re: [Bug] Health damage doesn't reduce attack damage
« Reply #1 on: February 28, 2025, 12:08:09 pm »
I do not think that "stats are reduced" is correct view of how wounds works, they are more final modifier after all other calculations.
See `getAccuracyModifier` that is independent from rest of modifiers.
Similar is with TU and Energy. I made fast scan of code base and I do not see other places where wounds could apply penalty.

This mean stats are keep same every else.

Another thing is we could not by default alter damage calculations as base game have damage independent of unit stats and thus should
not be affected by units wounds.


One solution for now is create global script for bonus damage that will reduce current value bonuses after all other calcinations.
Question is what body parts wounds should apply penalty?


Online Meridian

  • Global Moderator
  • Commander
  • *****
  • Posts: 9413
    • View Profile
Re: [Bug] Health damage doesn't reduce attack damage
« Reply #2 on: February 28, 2025, 12:23:15 pm »
If a soldier has a weapon that scales damage with stats, and your stats are reduced because the soldier is damaged, then attack damage should be reduced. It currently is not. The accuracy of the attack get properly reduced based on the soldier's current damage and wounds, but not the power.

Well, that's how it was designed.
The accuracy is reduced if you're hurt, but the stats are NOT really reduced, they are still the same.

The stats are only "displayed as reduced" (because it is a bit more visually understandable for the player, but even that is arguable since OG and OXC displayed them "incorrectly reduced" anyway).

This was one of my first changes in OXCE, see: https://github.com/MeridianOXC/OpenXcom/commit/66ee0523750d609cca4ff0e7efa7f3aaf37a5c4d
and https://www.ufopaedia.org/index.php?title=Accuracy_formula#Stat_Screen_Accuracy

I don't consider this a bug.

Online Delian

  • Commander
  • *****
  • Posts: 657
    • View Profile
Re: [Bug] Health damage doesn't reduce attack damage
« Reply #3 on: February 28, 2025, 08:22:06 pm »
Well, that's how it was designed.
The accuracy is reduced if you're hurt, but the stats are NOT really reduced, they are still the same.

The stats are only "displayed as reduced" (because it is a bit more visually understandable for the player, but even that is arguable since OG and OXC displayed them "incorrectly reduced" anyway).

This was one of my first changes in OXCE, see: https://github.com/MeridianOXC/OpenXcom/commit/66ee0523750d609cca4ff0e7efa7f3aaf37a5c4d
and https://www.ufopaedia.org/index.php?title=Accuracy_formula#Stat_Screen_Accuracy

I don't consider this a bug.

Yes, under the hood, the stats are static. However, that doesn't mean that in practice the stats aren't reduced. Think about it. Why would you show the player reduced stats, if it's not your intention for the player to think that that's what happens when a unit is hurt? I'm pretty sure that the original intention was for the unit's secondary stats to get reduced with damage, and consequently any formulae where the secondary stats are used are affected by how damaged the unit is.
Perhaps you assume that, because, for instance, "current firing skill" stat doesn't explicitly exist, that the stat is somehow not actually reduced. But why would it need to exist when it can be calculated on the fly? If such a stat existed, it would be redundant; it would just be wasting space in the sav file.
Let's for a moment assume that the current accuracy equation is:
Chance to hit = Weapon Accuracy * Firing Skill * Health Penalty * Wounds Penalty * Other
The Current Firing Skill is already in there. If you want it to be explicit, all you need is a temporary variable:
Current Firing Skill = Firing Skill * Health Penalty * Wounds Penalty
Chance to hit = Weapon Accuracy * Current Firing Skill * Other

and the result is the same.

Well, I should note that the way accuracy penalty is currently applied is also a bit bugged. It works correctly when the attack accuracy is based purely on Firing/Throwing/Melee skill (like in the above simplified equation), where the reduction is linear. But nowadays you got mods with weapons with stuff like [50 + 0.01*Throwing²] -> accuracy equations which aren't linear. If a unit's throwing skill was reduced by 10% it would produce a different result than applying a flat 10% penalty.

Anyway, to me it seems logical that if a unit's arm has 9 holes in it, that using this arm for, for instance, punching, would result in lower damage than if the holes were not there.



>I do not think that "stats are reduced" is correct view of how wounds works, they are more final modifier after all other calculations.
Sure, it's a modifier. But the point where the modifier gets applied can be important. If, let's say, you have a homing missile launcher or a magic wand with guaranteed 100% accuracy (flatHundred: 1), then wounds shouldn't affect such a weapon because, logically, it doesn't make sense for wounds to affect a weapon that isn't skill-dependent.

>See `getAccuracyModifier` that is independent from rest of modifiers.
Based on what this function returns, it should be named getWoundsPenaltyModifier(). Also, the comment for this function says "Formula = accuracyStat * woundsPenalty(% health) * critWoundsPenalty (-10%/wound)". Which is funny, because that's almost the currect formula for the damage-reduced stats.

>Another thing is we could not by default alter damage calculations as base game have damage independent of unit stats and thus should
not be affected by units wounds.
Right. It's correct that base game weapon damage doesn't change with wounds, because that damage doesn't scale with stats. But for any damage bonus that does scale with stats, health damage and critical wounds should also be applied.

>One solution for now is create global script for bonus damage that will reduce current value bonuses after all other calcinations.
Why reduce damage after the calculations? Why not simply make it so that when a script reads unit's stats, it reads the penalized stats instead of the base stats?

>Question is what body parts wounds should apply penalty?
I'm not sure either. I guess the same way as it is for accuracy.

Online Meridian

  • Global Moderator
  • Commander
  • *****
  • Posts: 9413
    • View Profile
Re: Health damage doesn't reduce attack damage
« Reply #4 on: February 28, 2025, 09:16:46 pm »
Moved to OXCE Support.

Offline Yankes

  • Global Moderator
  • Commander
  • *****
  • Posts: 3435
    • View Profile
Re: [Bug] Health damage doesn't reduce attack damage
« Reply #5 on: February 28, 2025, 10:52:15 pm »
Yes, under the hood, the stats are static. However, that doesn't mean that in practice the stats aren't reduced. Think about it. Why would you show the player reduced stats, if it's not your intention for the player to think that that's what happens when a unit is hurt? I'm pretty sure that the original intention was for the unit's secondary stats to get reduced with damage, and consequently any formulae where the secondary stats are used are affected by how damaged the unit is.
Perhaps you assume that, because, for instance, "current firing skill" stat doesn't explicitly exist, that the stat is somehow not actually reduced. But why would it need to exist when it can be calculated on the fly? If such a stat existed, it would be redundant; it would just be wasting space in the sav file.
Let's for a moment assume that the current accuracy equation is:
Chance to hit = Weapon Accuracy * Firing Skill * Health Penalty * Wounds Penalty * Other
The Current Firing Skill is already in there. If you want it to be explicit, all you need is a temporary variable:
Current Firing Skill = Firing Skill * Health Penalty * Wounds Penalty
Chance to hit = Weapon Accuracy * Current Firing Skill * Other

and the result is the same.

Well, I should note that the way accuracy penalty is currently applied is also a bit bugged. It works correctly when the attack accuracy is based purely on Firing/Throwing/Melee skill (like in the above simplified equation), where the reduction is linear. But nowadays you got mods with weapons with stuff like [50 + 0.01*Throwing²] -> accuracy equations which aren't linear. If a unit's throwing skill was reduced by 10% it would produce a different result than applying a flat 10% penalty.

Anyway, to me it seems logical that if a unit's arm has 9 holes in it, that using this arm for, for instance, punching, would result in lower damage than if the holes were not there.

First of all, what you say "have lot of sense" but is not "correct". I make couple of time similar changes that "make more sense" but always someone complaint that I break his mod balance (see `heatVision`) or think some thing have "more sense".
This mean to touch behaviors like this we need big modders majority or My (or Meridian) will to take all flak/fallout caused by changes like this.
Beside if even we change stats to be adjusted by health lose then we need provide "raw" stats too because for some calculations people would like to
have them without it (or to revert this change all together).

Another thing is your equation is not accurate as wounds are not multiplicative with health lose but additive:
Code: [Select]
return std::max(10, 25 * _health / getBaseStats()->health + 75 + -10 * wounds);




>I do not think that "stats are reduced" is correct view of how wounds works, they are more final modifier after all other calculations.
Sure, it's a modifier. But the point where the modifier gets applied can be important. If, let's say, you have a homing missile launcher or a magic wand with guaranteed 100% accuracy (flatHundred: 1), then wounds shouldn't affect such a weapon because, logically, it doesn't make sense for wounds to affect a weapon that isn't skill-dependent.
how weapon know what it should hit? Probably half dead solders will have problems with providing this information correctly to weapon :D



>See `getAccuracyModifier` that is independent from rest of modifiers.
Based on what this function returns, it should be named getWoundsPenaltyModifier(). Also, the comment for this function says "Formula = accuracyStat * woundsPenalty(% health) * critWoundsPenalty (-10%/wound)". Which is funny, because that's almost the currect formula for the damage-reduced stats.


After looking on blame, this is WarBoy change, If I recall correctly this calc was done by comparing to exe itself, not from wiki.
I will ask him if he recall why this code work this way.


>Another thing is we could not by default alter damage calculations as base game have damage independent of unit stats and thus should
not be affected by units wounds.
Right. It's correct that base game weapon damage doesn't change with wounds, because that damage doesn't scale with stats. But for any damage bonus that does scale with stats, health damage and critical wounds should also be applied.

>One solution for now is create global script for bonus damage that will reduce current value bonuses after all other calcinations.
Why reduce damage after the calculations? Why not simply make it so that when a script reads unit's stats, it reads the penalized stats instead of the base stats?

>Question is what body parts wounds should apply penalty?
I'm not sure either. I guess the same way as it is for accuracy.

As I previously said some people would like raw stats data without any moddifers too, this is why I suggest do adjust it after other bonuses.
And if people would like interactions with wounds/missing health then it should affect maybe other stats too, not only "accuracy" ones.

Offline Yankes

  • Global Moderator
  • Commander
  • *****
  • Posts: 3435
    • View Profile
Re: Health damage doesn't reduce attack damage
« Reply #6 on: March 01, 2025, 01:30:47 pm »
I asked Warboy1982 and he confirm that wiki is inaccurate, OXC have correct formula based on original code.
I updated wiki to match correct formula.

Online Delian

  • Commander
  • *****
  • Posts: 657
    • View Profile
Re: Health damage doesn't reduce attack damage
« Reply #7 on: March 02, 2025, 11:30:53 am »

>someone complaint that I break his mod balance
I highly doubt anyone has made a mod that's balanced around how wounds are applied, or not applied, to accuracy and power. In fact, I don't think there exists a single modder that knows that the reduced stats that players are shown are fake. This is different than the heatVision, because in this case the players are actively presented stats information.

>to touch behaviors like this we need big modders majority
You can ask them, sure, but I can already tell you that anyone you ask "Hey, when your soldier is damaged, should the reduced stats, that you're shown, be applied to weapon power?", would answer with "What? The stat reduction isn't already being applied? We can see the stats are reduced tho?"

>we need provide "raw" stats too
I guess that does make sense. Altho I'm not sure of the practical applications. In what case would it be logical for the accuracy or power to be affected by base stat instead of current stat.

>your equation is not accurate
>return std::max(10, 25 * _health / getBaseStats()->health + 75 + -10 * wounds);
Code: [Select]
int __fastcall sub_35660(unsigned __int8 *unitPtr, int weaponPtr, __int16 hand)
{
  __int16 accuracy; // bx
  __int16 critWoundsCount; // dx
  __int16 woundsModifier; // ax

  accuracy = unitPtr[23];
  if ( (unitPtr[120] & 0x40) != 0 ) // if kneeling
    accuracy = (__int16)(115 * accuracy) / 100;
  if ( *(_BYTE *)(weaponPtr + 50) && unitPtr[54] != 0xFF && unitPtr[53] != 0xFF ) // if two-handed weapon and have both hands occupied
    accuracy = (__int16)(80 * accuracy) / 100;
  if ( *(_BYTE *)(weaponPtr + 50) ) // if two-handed weapon
    critWoundsCount = unitPtr[65] + unitPtr[66]; // add up wounds from both hands
  else
    critWoundsCount = unitPtr[66 - hand]; // add wounds from the currently used hand

  woundsModifier = (25 * unitPtr[13]) / unitPtr[26] + 75 - 10 * (unitPtr[63] + critWoundsCount); // currentHp = unitPtr[13]; maxHp = unitPtr[26]; headWounds = unitPtr[63];
  if ( woundsModifier < 10 )
    woundsModifier = 10;
  return accuracy * woundsModifier / 100;
}
I know my equation wasn't accurate. That's why I wrote "Let's assume...". If it was correct, then there wouldn't be any assumption hehe.
Anyway, this is the OG exe code and, we can see that it's equal to the current code. Altho it's a bit harder to extract "Current Firing Skill" from it.

>Probably half dead solders will have problems with providing this information correctly to weapon
In this game, half dead soldiers are still fully functional hehe. Uttering magic words is enough for the wand to shoot, and then the magic does the aiming!

>this is why I suggest do adjust it after other bonuses
Okay, but that's gonna be complicated~
« Last Edit: March 02, 2025, 11:33:02 am by Delian »

Offline Dioxine

  • Commander
  • *****
  • Posts: 5470
  • punk not dead
    • View Profile
    • Nocturnal Productions
Re: Health damage doesn't reduce attack damage
« Reply #8 on: March 02, 2025, 04:14:26 pm »
don't think there exists a single modder that knows that the reduced stats that players are shown are fake.

I do, however I also know there is accuracy reduction due to damage, so it's not entirelly fake.

>to touch behaviors like this we need big modders majority
You can ask them, sure, but I can already tell you that anyone you ask "Hey, when your soldier is damaged, should the reduced stats, that you're shown, be applied to weapon power?", would answer with "What? The stat reduction isn't already being applied? We can see the stats are reduced tho?"

I always assumed what turns out to be true: the damage bonus is derived from stats, without taking in the modifier for damage, which is fleeting, varies with stat and is already one step removed from the root. So, no, you're completely wrong on that. Please do not assume your opinion is the same as everyone else's.
My assumption was based on following logic: it's better to apply a separate debuff to final score, than to let stats modify other stats, because the latter will lead to formulas increasing their complexity exponentially.

In summary, I prefer the current behaviour, please do not remove it completely.
« Last Edit: March 02, 2025, 04:20:58 pm by Dioxine »

Offline Yankes

  • Global Moderator
  • Commander
  • *****
  • Posts: 3435
    • View Profile
Re: Health damage doesn't reduce attack damage
« Reply #9 on: March 02, 2025, 04:24:47 pm »
>someone complaint that I break his mod balance
I highly doubt anyone has made a mod that's balanced around how wounds are applied, or not applied, to accuracy and power. In fact, I don't think there exists a single modder that knows that the reduced stats that players are shown are fake. This is different than the heatVision, because in this case the players are actively presented stats information.

>to touch behaviors like this we need big modders majority
You can ask them, sure, but I can already tell you that anyone you ask "Hey, when your soldier is damaged, should the reduced stats, that you're shown, be applied to weapon power?", would answer with "What? The stat reduction isn't already being applied? We can see the stats are reduced tho?"
Whole history of OXCE have lot of cases when some changes that "should not break anything" it break many modes.
And I will not guess too what they think so about things because they many times have opposite option.
Only case when I go against them is when I believe change is required for long term maintainability of OXCE.

I pinged Dio and Sol to join this discussion (other modders are welcomed to), and if there is some consensus then we will go that way.





>we need provide "raw" stats too
I guess that does make sense. Altho I'm not sure of the practical applications. In what case would it be logical for the accuracy or power to be affected by base stat instead of current stat.

>your equation is not accurate
>return std::max(10, 25 * _health / getBaseStats()->health + 75 + -10 * wounds);
Code: [Select]
int __fastcall sub_35660(unsigned __int8 *unitPtr, int weaponPtr, __int16 hand)
{
  __int16 accuracy; // bx
  __int16 critWoundsCount; // dx
  __int16 woundsModifier; // ax

  accuracy = unitPtr[23];
  if ( (unitPtr[120] & 0x40) != 0 ) // if kneeling
    accuracy = (__int16)(115 * accuracy) / 100;
  if ( *(_BYTE *)(weaponPtr + 50) && unitPtr[54] != 0xFF && unitPtr[53] != 0xFF ) // if two-handed weapon and have both hands occupied
    accuracy = (__int16)(80 * accuracy) / 100;
  if ( *(_BYTE *)(weaponPtr + 50) ) // if two-handed weapon
    critWoundsCount = unitPtr[65] + unitPtr[66]; // add up wounds from both hands
  else
    critWoundsCount = unitPtr[66 - hand]; // add wounds from the currently used hand

  woundsModifier = (25 * unitPtr[13]) / unitPtr[26] + 75 - 10 * (unitPtr[63] + critWoundsCount); // currentHp = unitPtr[13]; maxHp = unitPtr[26]; headWounds = unitPtr[63];
  if ( woundsModifier < 10 )
    woundsModifier = 10;
  return accuracy * woundsModifier / 100;
}
I know my equation wasn't accurate. That's why I wrote "Let's assume...". If it was correct, then there wouldn't be any assumption hehe.
Anyway, this is the OG exe code and, we can see that it's equal to the current code. Altho it's a bit harder to extract "Current Firing Skill" from it.

>Probably half dead solders will have problems with providing this information correctly to weapon
In this game, half dead soldiers are still fully functional hehe. Uttering magic words is enough for the wand to shoot, and then the magic does the aiming!

>this is why I suggest do adjust it after other bonuses
Okay, but that's gonna be complicated~
This depend on "mental model" as even weapon is not "skill based" but it still be affected by overall health (image that magic drawn your stamina or mental focus).
As most of this is right now scriptable, this mean you can implement near any "damage penalty model" I do not have lot of desire to alter current default behavior without very compelling arguments.

If point out this over 10 years ago (when this code was added) I would be more eager to change it.


[ps]

As Dio answer faster than I write my reply.
This mean current behavior cannot change, now question is how we would add options (if desired) to easily have stats adjusted by unit damage penalty.
« Last Edit: March 02, 2025, 04:29:53 pm by Yankes »

Online Delian

  • Commander
  • *****
  • Posts: 657
    • View Profile
Re: Health damage doesn't reduce attack damage
« Reply #10 on: March 02, 2025, 04:42:37 pm »
it's better to apply a separate debuff to final score, than to let stats modify other stats

Ok so, what debuff should be applied then?


If you want it to be a per-item rule setting, then I guess what we need is "damageBonusPenalty" and "meleeBonusPenalty":
Code: [Select]
    damageBonus:
      strength: 0.25
      melee: 0.25
    damageBonusPenalty:
      health: 0.25
      healthCurrent: -0.25
Where the
finalDamageBonus = damageBonus * (1 - damageBonusPenalty);

Or would it be better to have it function as a multiplier?
Code: [Select]
    damageBonus:
      strength: 0.25
      melee: 0.25
    damageBonusModifier:
      flatOne: 75
      healthNormalized: 25
And the equation would be
finalDamageBonus = damageBonus * damageBonusModifier;



As most of this is right now scriptable, this mean you can implement near any "damage penalty model"

Are you sure it's scriptable? I think scripts don't have access to item's "bonusDamage".
« Last Edit: March 03, 2025, 04:45:50 pm by Delian »

Offline Yankes

  • Global Moderator
  • Commander
  • *****
  • Posts: 3435
    • View Profile
Re: Health damage doesn't reduce attack damage
« Reply #11 on: March 07, 2025, 03:04:20 pm »

Are you sure it's scriptable? I think scripts don't have access to item's "bonusDamage".

Yes, trick is that `damageBonus:` aside of map accept raw text and this text is parsed as script.
You can have any calculation there. This first place where you can have "fun".

Second is that all this bonus script have "global" hooks too, this mean you can define script that
will be called for every item/armor after or before evaluation of `damageBonus:`.


For simple version (only basic bonuses), I would see this would work like:
Code: [Select]
    damageBonus:
      throw: 0.75
      throwHealthNormalized: 0.25 #new stat that is `throw * health%`
This would equal `0.75 * throw + 0.25 * (throw * (current/max))` calculation.
Only problems I have is how it should be named and what value range it should have (normalized vs scaled vs nothing and what part should be this applied to).

Online Delian

  • Commander
  • *****
  • Posts: 657
    • View Profile
Re: Health damage doesn't reduce attack damage
« Reply #12 on: March 07, 2025, 08:57:20 pm »
Second is that all this bonus script have "global" hooks too, this mean you can define script that will be called for every item/armor after or before evaluation of `damageBonus:`.

I mean, if I try to hook the global hitUnit event, I only get "damage" as one of the parameters which already includes bonusDamage. I'm unable to tell what part of the damage is static and what dynamic.

throwHealthNormalized

I don't like this solution because it would require mod authors to rewrite every damage formula they already defined (because Find & Replace doesn't work). I don't think anyone would bother with that.

My solution allows to just define a single modifier, and then you can use yaml anchors to copy paste it to every item where damage scales with stats. It would be a lot less work, but still it wouldn't be super easy because copy-pasting stuff 1000 times is time-consuming. I wish there existed some sort of a global solution.

Offline Yankes

  • Global Moderator
  • Commander
  • *****
  • Posts: 3435
    • View Profile
Re: Health damage doesn't reduce attack damage
« Reply #13 on: March 07, 2025, 09:18:32 pm »
Because you look on wrong script, each script have specific name and bonuses have its own name like `damageBonusBonusStats`
simply you take name of `bonusDamage:` and add `BonusStats` and have name of global handler.