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?"
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.
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 behind-the-scenes 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.