Seems like OG had a bad "RNG::percent" handling, so there are cases, which are correct in OG and wrong in OXC, wrong in OG and correct in OXC and also wrong in both.
Not sure yet, which cases should be fixed and which not... to be decided later.
For now I'll just paste some code from OG and OXC for reference.
xc_RandMod (100) returns a random number between 0 and 100 (i.e. 101 possible numbers), not between 0 and 99
//----- (0043D850) --------------------------------------------------------
unsigned __int16 __cdecl xc_RandMod(int a1)
{
unsigned __int16 result; // ax@2
if ( (unsigned __int16)a1 == -1 )
result = 0;
else
result = (unsigned __int16)rand() % ((unsigned __int16)a1 + 1);
return result;
}
freeze, run or berserk
//----- (0041F340) --------------------------------------------------------
void __cdecl xc_BF_Do_Morale_Checks(strucUnitPos *a1)
{
strucUnitRef *v1; // esi@1
v1 = a1->UnitRef_ptr;
if ( !v1->PanicMode ) // 0
{
if ( v1->curMorale < 50u )
{
if ( v1->curMorale >= xc_RandMod(50) )
{
if ( !a1->OwnerSide ) // xcom
++v1->Bravery_exp_cnt;
}
else
{
v1->PanicMode = xc_RandMod(2) + 1;
}
}
}
}
BattlescapeGame.cpp
int flee = RNG::generate(0,100);
BattleAction ba;
ba.actor = unit;
if (status == STATUS_PANICKING && flee <= 50) // 1/2 chance to freeze and 1/2 chance try to flee, STATUS_BERSERK is handled in the panic state.
{
BattleUnit.cpp
int chance = 100 - (2 * getMorale());
if (RNG::generate(1,100) <= chance)
{
int type = RNG::generate(0,100);
_status = (type<=33?STATUS_BERSERK:STATUS_PANICKING); // 33% chance of berserk, panic can mean freeze or flee, but that is determined later
}
OG has a 1:1:1 split
OXC has a 34:67 split and subsequent 51:50 split