private static void CombatTurn(CombatStats attacker, CombatStats defender) { const int critMargin = 10; const int attackDiceSides = 16; var attackScore = attacker.Attack + MathF.Rnd.Next(1, attackDiceSides + 1); var result = AttackResult.Defended; var damage = 0; if (attackScore > defender.Defense) { var isCrit = attackScore - defender.Defense > critMargin; result = AttackResult.Hit; damage = attacker.Damage.Roll(); if (isCrit) { damage *= 2; result = AttackResult.CriticalHit; } damage = Math.Max(damage - defender.DamageReduction, 0); if (damage == 0) { result = AttackResult.ArmorZeroed; } } defender.ChangeHealth(-damage); //Log.Game.Write($"{attacker.GameObj.Name} (score: {attackScore}) attacks {defender.GameObj.Name} (score: {defender.Defense}) and damages {damage}"); var isPlayerAttack = attacker.GameObj.GetComponent <PlayerMovement>() != null; Scene.Current.FindComponent <UiRenderer>().RequestCombatUi(new CombatUiData(isPlayerAttack, attackScore, defender.Defense, damage, defender.MaxHealth, defender.currentHealth, result)); switch (result) { case AttackResult.Defended: AudioPlayer.PlaySfx(Sfx.Blocked); break; case AttackResult.Hit: case AttackResult.CriticalHit: if (defender.currentHealth == 0) { AudioPlayer.PlaySfx(Sfx.Kill); } else { AudioPlayer.PlaySfx(Sfx.Hit); } break; case AttackResult.ArmorZeroed: AudioPlayer.PlaySfx(Sfx.ArmorBlocked); break; default: throw new ArgumentOutOfRangeException(); } }
public void FightWith(CombatStats other) { CombatTurn(this, other); }