Advertisement
Guest User

XCOM 2 Crit chance calc

a guest
Feb 8th, 2016
234
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //In X2AbilityToHitCalc.uc
  2.  
  3. protected function FinalizeHitChance()
  4. {
  5.     local int i;
  6.     local EAbilityHitResult HitResult;
  7.     local float GrazeScale;
  8.     local int FinalGraze;
  9.  
  10.     `log("==" $ GetFuncName() $ "==\n", m_bDebugModifiers, 'XCom_HitRolls');
  11.     `log("Starting values...", m_bDebugModifiers, 'XCom_HitRolls');
  12.     for (i = 0; i < eHit_MAX; ++i)
  13.     {
  14.         HitResult = EAbilityHitResult(i);
  15.         `log(HitResult $ ":" @ m_ShotBreakdown.ResultTable[i], m_bDebugModifiers, 'XCom_HitRolls');
  16.     }
  17.  
  18.     m_ShotBreakdown.FinalHitChance = m_ShotBreakdown.ResultTable[eHit_Success];
  19.     //  if crit goes negative, hit would get a boost, so restrict it to 0
  20.     if (m_ShotBreakdown.ResultTable[eHit_Crit] < 0)
  21.         m_ShotBreakdown.ResultTable[eHit_Crit] = 0;
  22.     //  Crit is folded into the chance to hit, so lower accordingly
  23.     m_ShotBreakdown.ResultTable[eHit_Success] -= m_ShotBreakdown.ResultTable[eHit_Crit];
  24.     //  Graze is scaled against Success
  25.     if (m_ShotBreakdown.ResultTable[eHit_Graze] > 0)
  26.     {
  27.         GrazeScale = float(m_ShotBreakdown.ResultTable[eHit_Graze]) / 100.0f;
  28.         GrazeScale *= float(m_ShotBreakdown.FinalHitChance);
  29.         FinalGraze = Round(GrazeScale);
  30.         m_ShotBreakdown.ResultTable[eHit_Success] -= FinalGraze;
  31.         m_ShotBreakdown.ResultTable[eHit_Graze] = FinalGraze;
  32.     }
  33.  
  34.     if (m_ShotBreakdown.FinalHitChance >= 100)
  35.     {
  36.         m_ShotBreakdown.ResultTable[eHit_Miss] = 0;
  37.     }
  38.     else
  39.     {
  40.         m_ShotBreakdown.ResultTable[eHit_Miss] = 100 - m_ShotBreakdown.FinalHitChance;
  41.     }
  42.    
  43.     `log("Calculated values...", m_bDebugModifiers, 'XCom_HitRolls');
  44.     for (i = 0; i < eHit_MAX; ++i)
  45.     {
  46.         HitResult = EAbilityHitResult(i);
  47.         `log(HitResult $ ":" @ m_ShotBreakdown.ResultTable[i], m_bDebugModifiers, 'XCom_HitRolls');
  48.     }
  49.     `log("Final hit chance (success + crit + graze) =" @ m_ShotBreakdown.FinalHitChance, m_bDebugModifiers, 'XCom_HitRolls');
  50.  
  51.     //"Negative chance to hit" is used as a token in UI code - don't ever report that.
  52.     if (m_ShotBreakdown.FinalHitChance < 0)
  53.     {
  54.         `log("FinalHitChance was less than 0 (" $ m_ShotBreakdown.FinalHitChance $ ") and was clamped to avoid confusing the UI (@btopp).", m_bDebugModifiers, 'XCom_HitRolls');
  55.         m_ShotBreakdown.FinalHitChance = 0;
  56.     }
  57. }
  58.  
  59. //The code you're currently using is above, if for instance, a shot has a 65% to-hit and a 65% crit chance, that's actually a 100% chance to crit IF you hit, in short, that just ain't right.
  60.  
  61. //This happens because resultTable gives the chance that a shot is a hit AND a crit, a shot is a hit AND isn't a graze or a crit, a shot is a hit AND is a graze or a shot is a miss, ignoring stuff like lightning reflexes etc, that's applied after, if I'm not mistaken.
  62. //You're prepping the table badly for the purposes of InternalRollForAbilityHit and GetHitChance.
  63.  
  64. //You may want to decouple your resultTable from UI chance to crit, or have a translation function, or don't call finalizehitchance for //purely UI data.
  65.  
  66. //Anyway, here's fixed code, it should also fix how dodge is ignored by crits, currently it's only lowering the chance for a normal hit, so a crit would never be affected by dodge, 100% crit completely ignores dodge, if you want it to do that, it's easy enough to fiddle around, but it doesn't seem like that's desired.
  67.  
  68. protected function FinalizeHitChance()
  69. {
  70.     local int i;
  71.     local EAbilityHitResult HitResult;
  72.     local float GrazeScale;
  73.  
  74.     `log("==" $ GetFuncName() $ "==\n", m_bDebugModifiers, 'XCom_HitRolls');
  75.     `log("Starting values...", m_bDebugModifiers, 'XCom_HitRolls');
  76.     for (i = 0; i < eHit_MAX; ++i)
  77.     {
  78.         HitResult = EAbilityHitResult(i);
  79.         //  Clamp values, optional, but generally a good idea for the final leg of hit calc
  80.         m_ShotBreakdown.ResultTable[i] = Clamp(m_ShotBreakdown.ResultTable[i], 0, 100);
  81.         `log(HitResult $ ":" @ m_ShotBreakdown.ResultTable[i], m_bDebugModifiers, 'XCom_HitRolls');
  82.     }
  83.  
  84.     m_ShotBreakdown.FinalHitChance = m_ShotBreakdown.ResultTable[eHit_Success];
  85.  
  86.     //  Graze is scaled against chance to hit
  87.     if (m_ShotBreakdown.ResultTable[eHit_Graze] > 0)
  88.     {
  89.         GrazeScale = float(m_ShotBreakdown.ResultTable[eHit_Graze]) / 100.0f;
  90.         m_ShotBreakdown.ResultTable[eHit_Graze] = Round(GrazeScale * float(m_ShotBreakdown.ResultTable[eHit_Success]));
  91.         m_ShotBreakdown.ResultTable[eHit_Success] -= m_ShotBreakdown.ResultTable[eHit_Graze];
  92.     }
  93.  
  94.     // Here's an idea, add a new eHit_Type for display purposes
  95.     m_ShotBreakdown.ResultTable[eHit_DisplayedCrit] = m_ShotBreakdown.ResultTable[eHit_Crit];
  96.  
  97.     m_ShotBreakdown.ResultTable[eHit_Crit] = Round(float(m_ShotBreakdown.ResultTable[eHit_Crit]) / 100.0f * float(m_ShotBreakdown.ResultTable[eHit_Success]));
  98.     m_ShotBreakdown.ResultTable[eHit_Success] -= m_ShotBreakdown.ResultTable[eHit_Crit];
  99.     m_ShotBreakdown.FinalHitChance = m_ShotBreakdown.ResultTable[eHit_Graze] + m_ShotBreakdown.ResultTable[eHit_Success] + m_ShotBreakdown.ResultTable[eHit_Crit]
  100.     m_ShotBreakdown.ResultTable[eHit_Miss] = 100 - m_ShotBreakdown.FinalHitChance;
  101.  
  102.     `log("Calculated values...", m_bDebugModifiers, 'XCom_HitRolls');
  103.     for (i = 0; i < eHit_MAX; ++i)
  104.     {
  105.         HitResult = EAbilityHitResult(i);
  106.         `log(HitResult $ ":" @ m_ShotBreakdown.ResultTable[i], m_bDebugModifiers, 'XCom_HitRolls');
  107.     }
  108.     `log("Final hit chance (success + crit + graze) =" @ m_ShotBreakdown.FinalHitChance, m_bDebugModifiers, 'XCom_HitRolls');
  109. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement