MoraleDamageFromCloseCombat
MoraleDamageFromCloseCombat
Hallo! How does the game calculate "MoraleDamageFromCloseCombat"?
See MoraleTools.bsf => if (GetAttribArray(me, "MoraleDamageFromCloseCombat", notional_turn) > FIRST_CT_THRESHOLD) // See Macros.bsf. Roughly 5% losses (but allowing for morale damage not being rounded down like actual casualties are.).
The FIRST_CT_THRESHOLD is not exactly % losses. For example the FIRST_CT_THRESHOLD of "550" doesn't mean 5,5 % casualties of the current number of men. Thus if a unit with current number of men 300/480 suffers 18 losses (300*0,055+1 = 17,5 rounded to 18) in doesn't mean reaching this FIRST_CT_THRESHOLD.
Moreover I changed "550" into "250", "500" or "1000" points in Macros.bsf but still can't get the exact number of casualties a unit should suffer to start this calculation.
Using Notepad++ I have found out that maybe the function "ConvertLossFactorToMoraleDamage" is a key. I managed to understand how to get the LossFactor, but how can I convert the LossFactor to MoraleDamage?
Or maybe there is something more than % of casualties suffered by the unit that contributes to the MoraleDamage?
Thanks in advance for any advice!
See MoraleTools.bsf => if (GetAttribArray(me, "MoraleDamageFromCloseCombat", notional_turn) > FIRST_CT_THRESHOLD) // See Macros.bsf. Roughly 5% losses (but allowing for morale damage not being rounded down like actual casualties are.).
The FIRST_CT_THRESHOLD is not exactly % losses. For example the FIRST_CT_THRESHOLD of "550" doesn't mean 5,5 % casualties of the current number of men. Thus if a unit with current number of men 300/480 suffers 18 losses (300*0,055+1 = 17,5 rounded to 18) in doesn't mean reaching this FIRST_CT_THRESHOLD.
Moreover I changed "550" into "250", "500" or "1000" points in Macros.bsf but still can't get the exact number of casualties a unit should suffer to start this calculation.
Using Notepad++ I have found out that maybe the function "ConvertLossFactorToMoraleDamage" is a key. I managed to understand how to get the LossFactor, but how can I convert the LossFactor to MoraleDamage?
Or maybe there is something more than % of casualties suffered by the unit that contributes to the MoraleDamage?
Thanks in advance for any advice!

 Field of Glory 2
 Posts: 22425
 Joined: Sun Dec 04, 2005 6:25 pm
Re: MoraleDamageFromCloseCombat
I don’t have access to the source code today so I cannot give you a specific answer just now.
What exactly are you trying to achieve?
What exactly are you trying to achieve?
Richard Bodley Scott
Re: MoraleDamageFromCloseCombat
Dear RbodleyScott, thank you very much for your answer!rbodleyscott wrote: ↑Sat Sep 28, 2019 5:47 pmI don’t have access to the source code today so I cannot give you a specific answer just now.
What exactly are you trying to achieve?
From Macros.bsf line 1 we know: // "#define FIRST_CT_THRESHOLD...This is meant to represent ...% losses, but takes into account the fact that morale damage is not rounded down, so is somewhat higher than actual losses in "men". //
I would like to know "How much actual losses in "men" (casualties) should a unit exactly get to trigger this calculation?"

 Field of Glory 2
 Posts: 22425
 Joined: Sun Dec 04, 2005 6:25 pm
Re: MoraleDamageFromCloseCombat
IIRC 5% but it is only approximate for several reasons, one of which being that it is 5% of the first three ranks of models, so it is actually a lower percentage of deeper units.Spiret3z wrote: ↑Sat Sep 28, 2019 5:57 pmDear RbodleyScott, thank you very much for your answer!rbodleyscott wrote: ↑Sat Sep 28, 2019 5:47 pmI don’t have access to the source code today so I cannot give you a specific answer just now.
What exactly are you trying to achieve?
From Macros.bsf line 1 we know: // "#define FIRST_CT_THRESHOLD...This is meant to represent ...% losses, but takes into account the fact that morale damage is not rounded down, so is somewhat higher than actual losses in "men". //
I would like to know "How much actual losses in "men" (casualties) should a unit exactly get to trigger this calculation?"
But the way the code works is a lot more complicated than simply looking at the number of casualties, because it doesn’t actually work using the casualties directly. I can’t explain properly without sight of the source code, which I do not have access to today.
However, once again it would be helpful if you could say what you are attempting to achieve by your intended mod, as I may be able to suggest a simpler method than trying to fully understand the complex way the calculations work.
Richard Bodley Scott
Re: MoraleDamageFromCloseCombat
Dear RbodleyScott, thank you very much for your answer!rbodleyscott wrote: ↑Sat Sep 28, 2019 6:50 pmIIRC 5% but it is only approximate for several reasons, one of which being that it is 5% of the first three ranks of models, so it is actually a lower percentage of deeper units.Spiret3z wrote: ↑Sat Sep 28, 2019 5:57 pmDear RbodleyScott, thank you very much for your answer!rbodleyscott wrote: ↑Sat Sep 28, 2019 5:47 pmI don’t have access to the source code today so I cannot give you a specific answer just now.
What exactly are you trying to achieve?
From Macros.bsf line 1 we know: // "#define FIRST_CT_THRESHOLD...This is meant to represent ...% losses, but takes into account the fact that morale damage is not rounded down, so is somewhat higher than actual losses in "men". //
I would like to know "How much actual losses in "men" (casualties) should a unit exactly get to trigger this calculation?"
But the way the code works is a lot more complicated than simply looking at the number of casualties, because it doesn’t actually work using the casualties directly. I can’t explain properly without sight of the source code, which I do not have access to today.
However, once again it would be helpful if you could say what you are attempting to achieve by your intended mod, as I may be able to suggest a simpler method than trying to fully understand the complex way the calculations work.
 do you mean lines 871878 in MoraleTools.bsf?:rbodleyscott wrote: ↑Sat Sep 28, 2019 6:50 pm// IIRC 5% but it is only approximate for several reasons, one of which being that it is 5% of the first three ranks of models, so it is actually a lower percentage of deeper units.//
// Calculate 100 x % morale damage from 100 x % actual damage to unit. (Ignore rear ranks of very big units). (Use 100 x to avoid rounding errors).
FUNCTION ConvertLossFactorToMoraleDamage(me, damage)
{
damage = damage * GetAttrib(me, "UnitSize");
damage /= Min(GetAttrib(me, "UnitSize"), 900);
return damage;
}
It is not relevant to my question as both units have unitsizes 600 (max. 480 men, 2 ranks deep 4*2).
After having already played in FoGII 500+ hours, I think it's time for me to understand what is written in Combat Log during the battle.rbodleyscott wrote: ↑Sat Sep 28, 2019 6:50 pmBut the way the code works is a lot more complicated than simply looking at the number of casualties, because it doesn’t actually work using the casualties directly. I can’t explain properly without sight of the source code, which I do not have access to today.
However, once again it would be helpful if you could say what you are attempting to achieve by your intended mod, as I may be able to suggest a simpler method than trying to fully understand the complex way the calculations work.
My unit got a message "Significant melee casualties received this turn: 1". => IDS_CT_SIGNIF_MELEE => // Modifier if significant melee morale damage received
if (GetAttribArray(me, "MoraleDamageFromCloseCombat", notional_turn) > FIRST_CT_THRESHOLD) =>...
But then no information how to calculate MoraleDamageFromCloseCombat.
And thus would like to know "How much actual losses in "men" (casualties) should a unit exactly get to trigger this calculation?"

 Field of Glory 2
 Posts: 22425
 Joined: Sun Dec 04, 2005 6:25 pm
Re: MoraleDamageFromCloseCombat
The answer is that it isn't the actual losses in "men" that trigger it, it is a surrogate damage value which approximates to that percentage of men. So it isn't possible to answer the question exactly  except by looking at the code  see below.Spiret3z wrote: ↑Sat Sep 28, 2019 8:20 pmAfter having already played in FoGII 500+ hours, I think it's time for me to understand what is written in Combat Log during the battle.
My unit got a message "Significant melee casualties received this turn: 1". => IDS_CT_SIGNIF_MELEE => // Modifier if significant melee morale damage received
if (GetAttribArray(me, "MoraleDamageFromCloseCombat", notional_turn) > FIRST_CT_THRESHOLD) =>...
But then no information how to calculate MoraleDamageFromCloseCombat.
And thus would like to know "How much actual losses in "men" (casualties) should a unit exactly get to trigger this calculation?"
Code: Select all
lossFactor = RemoveCasualties(me, enemy, enemyDamageInflicted, 1, red);
moraleDamage = ConvertLossFactorToMoraleDamage(me, lossFactor); // Remove part of the moraleDamage diluting effect of very large units
SetAttribArray(me, "MoraleDamageFromCloseCombat", notional_turn, GetAttribArray(me, "MoraleDamageFromCloseCombat", notional_turn) + moraleDamage);
Code: Select all
// Removes losses and returns 100 times the % of current strength just lost. Any randomization of damage needs to be done before calling this function.
// Note that it returns 100 x % lost so as to minimise rounding errors.
// if combatLog = 1 then also writes to combat log
// Uses Work Array 0. Note that it calls GetCloseCombatFacingsAndRank() which uses Work Arrays 0 and 1, but this function does not use Work Array 0 till after that function has resolved.
FUNCTION RemoveCasualties(me, enemy, damage, combatLog, red)
{
int current_strength;
int men_lost;
int lossFactor;
int new_strength;
int id;
int impact;
current_strength = GetAttrib(me, "TotalMen");
men_lost = GetLosses(me, damage);
DisplayCasualties(me, men_lost, combatLog, red);
lossFactor = GetLossFactor(me, damage); // Avoid 0 casualties on elephants reducing lossFactor to 0.
Log ("Unit, Damage Factor, Men Lost, lossFactor (100 times % damage)", me, damage, men_lost, lossFactor);
new_strength = current_strength  men_lost;
//DebugLogX("unit, base man count, men_lost, killed", me, manCount, men_lost, killed);
SetAttrib(me, "TotalMen", new_strength);
impact = 0;
if (GetAttrib(me, "AnimSituation") == 1)
{
impact = 1;
}
if (enemy != 1)
{
if (GetAttrib(enemy, "AnimSituation") == 1)
{
impact = 1;
}
}
if (impact == 1)
{
AddVizFunctionCall("CasualtiesDie", me); // Called in VizQ so that (hopefully) it won't get enacted before units move
}
else
{
CasualtiesDie(me);
}
SetUnitStatusFlag(me);
// Also apply proportional losses to carried unit  currently none in FOG2.
id = GetLoadedUnit(me);
if (id != 1)
{
current_strength = GetAttrib(id, "TotalMen");
men_lost = GetLosses(id, damage);
new_strength = current_strength  men_lost;
SetAttrib(id, "TotalMen", new_strength);
AddVizFunctionCall("CasualtiesDie", id); // Uncertain whether this code will have the correct result.
SetUnitStatusFlag(id);
}
return lossFactor;
}
Code: Select all
FUNCTION GetLossFactor(me, damage)
{
int lossFactor;
int unitSize;
unitSize = GetAttrib(me, "UnitSize");
// lossFactor is calculated from original strength of unit, as incoming fire/close combat damage is not reduced by unit's losses,
// and the divisor is based on the unitSize of the unit  with a minimum unitSize of 300 (or double actual unitSize if lower) to stop small units being too vulnerable.
lossFactor = StartingStrength(me) * damage * 100;
lossFactor /= Max(unitSize, Min(300, unitSize * 2));
lossFactor *= 100;
lossFactor /= GetAttrib(me, "TotalMen");
return lossFactor;
}
Code: Select all
// Calculate 100 x % morale damage from 100 x % actual damage to unit. (Ignore rear ranks of very big units). (Use 100 x to avoid rounding errors).
FUNCTION ConvertLossFactorToMoraleDamage(me, damage)
{
damage = damage * GetAttrib(me, "UnitSize");
damage /= Min(GetAttrib(me, "UnitSize"), 900);
return damage;
}
Also, the shooting % to trigger a cohesion test is complicated by the fact that when (during development) we switched from having units shooting in both players' turns, to having shooting only in the player's own turn, we did not simply double the casualties. Instead each unit actually shoots twice, a separate record is kept for each unit for shooting casualties in the first and second shooting volley, and a cohesion test can be triggered by either one of these, taking in account only first or second volley casualties.
This is to simulate the unit shooting in each turn separately. Although it is convoluted for anyone looking at the code to follow, this was simpler for us than having to completely rebalance the cohesion tests around the higher casualties.
So the shooting casualties for triggering a cohesion test is (approximately) 5% per test, but this corresponds to very approximately 10% over the two volleys. However, as the two volleys are an entirely behindthescenes internal mechanism, with only one volley being animated, and the casualties from the two volleys added together before the casualties are reported, you will never be able to correlate the % losses used to determine whether a cohesion test is triggered against the reported losses. For example, the unit might only lose 7% casualties overall, but if this was 5% on the first volley and 2% on the second volley, a cohesion test would be triggered by the first volley. If both volleys caused over 5% casualties each, a cohesion test would only be taken for the first volley. If the casualties were 2% and 5% respectively, a cohesion test would only be taken for the second volley.
Richard Bodley Scott
Re: MoraleDamageFromCloseCombat
Dear Rbodleyscott, thank you very much for your answer!
Your explanation with shooting % is very useful, but my topic is about melee engagement between 2 infantry units (480 men, 600 unitsize each).
As I have written, we can get the LossFactor. There are 2 ways to get it, both in the file CombatTools.bsf.
Either lines 470472
Or lines 67216737 (as you have already mentioned above)
But then there is the question, how we can get this (lines 404405 in MoraleTools.bsf)?
?
The only function I can see is this one (lines 871878 in MoraleTools.bsf),, but it is not relevant to units with 600 unitsize 2*4 ranks deep each.
And therefore I get the LossFactor, but it isn't the morale damage and thus cannot be compared with the FIRST_CT_THRESHOLD. The LossFactor tends to be much higher than the required number of points of the FIRST_CT_THRESHOLD (See Macros.bsf).
So, how does the game transform the LossFactor into the MoraleDamage in melee engagement?
Your explanation with shooting % is very useful, but my topic is about melee engagement between 2 infantry units (480 men, 600 unitsize each).
As I have written, we can get the LossFactor. There are 2 ways to get it, both in the file CombatTools.bsf.
Either lines 470472
Code: Select all
// lossFactor = men_lost * 10000;
// lossFactor /= current_strength;
lossFactor = GetLossFactor(me, damage); // Avoid 0 casualties on elephants reducing lossFactor to 0.//
Code: Select all
// FUNCTION GetLossFactor(me, damage)
{
int lossFactor;
int unitSize;
unitSize = GetAttrib(me, "UnitSize");
// lossFactor is calculated from original strength of unit, as incoming fire/close combat damage is not reduced by unit's losses,
// and the divisor is based on the unitSize of the unit  with a minimum unitSize of 300 (or double actual unitSize if lower) to stop small units being too vulnerable.
lossFactor = StartingStrength(me) * damage * 100;
lossFactor /= Max(unitSize, Min(300, unitSize * 2));
lossFactor *= 100;
lossFactor /= GetAttrib(me, "TotalMen");
return lossFactor;
}
Code: Select all
// Modifier if significant melee morale damage received
if (GetAttribArray(me, "MoraleDamageFromCloseCombat", notional_turn) > FIRST_CT_THRESHOLD) //
The only function I can see is this one (lines 871878 in MoraleTools.bsf),
Code: Select all
// Calculate 100 x % morale damage from 100 x % actual damage to unit. (Ignore rear ranks of very big units). (Use 100 x to avoid rounding errors).
FUNCTION ConvertLossFactorToMoraleDamage(me, damage)
{
damage = damage * GetAttrib(me, "UnitSize");
damage /= Min(GetAttrib(me, "UnitSize"), 900);
return damage;
}
And therefore I get the LossFactor, but it isn't the morale damage and thus cannot be compared with the FIRST_CT_THRESHOLD. The LossFactor tends to be much higher than the required number of points of the FIRST_CT_THRESHOLD (See Macros.bsf).
So, how does the game transform the LossFactor into the MoraleDamage in melee engagement?

 Field of Glory 2
 Posts: 22425
 Joined: Sun Dec 04, 2005 6:25 pm
Re: MoraleDamageFromCloseCombat
The top two lines are commented out, so the parser ignores them. It is the third line that gets the lossFactor.Spiret3z wrote: ↑Mon Sep 30, 2019 10:56 pmDear Rbodleyscott, thank you very much for your answer!
Your explanation with shooting % is very useful, but my topic is about melee engagement between 2 infantry units (480 men, 600 unitsize each).
As I have written, we can get the LossFactor. There are 2 ways to get it, both in the file CombatTools.bsf.
Either lines 470472
Code: Select all
// lossFactor = men_lost * 10000; // lossFactor /= current_strength; lossFactor = GetLossFactor(me, damage); // Avoid 0 casualties on elephants reducing lossFactor to 0.//
So, how does the game transform the LossFactor into the MoraleDamage in melee engagement?
Code: Select all
moraleDamage = ConvertLossFactorToMoraleDamage(me, lossFactor); // Remove part of the moraleDamage diluting effect of very large units
SetAttribArray(me, "MoraleDamageFromCloseCombat", notional_turn, GetAttribArray(me, "MoraleDamageFromCloseCombat", notional_turn) + moraleDamage);
Richard Bodley Scott