private bool RollToHit(Soldier s, HitEvent evt) { int tohit_roll = Constants.Random(100); if (tohit_roll == 0) { evt.Results.Add(HitEvent.Code.CriticalHitFail); return(false); } if (tohit_roll == 99) { evt.Results.Add(HitEvent.Code.CriticalHit); } else { tohit_roll -= s.Weapon.HitModifier; if (tohit_roll >= s.SkillLevel) { evt.Results.Add(HitEvent.Code.NoHit); return(false); } } return(true); }
private void HitPerson(Soldier s) { // Pick target ArrayList targets = new ArrayList(); int st = 0; int en = Soldiers.Count - 1; if (s.Side == Side.Attacker) { st = FirstDefender; } else { en = FirstDefender - 1; } if (s.Weapon.Ranged) { // Ranged weapons for (int pass = 1; pass <= 3; pass++) { for (int j = st; j <= en; j++) { Soldier tg = (Soldier)Soldiers[j]; // Ranged weapons does not target units inside buildings if (tg.OutOfAction || tg.Building != null) { continue; } // Fleeing persons and chosen attacked last if (pass == 1 && (tg.Flee || tg.Person.Chosen)) { continue; } if (pass == 2 && tg.Person.Chosen) { continue; } targets.Add(tg); } if (targets.Count > 0) { break; } } } else { // Melee weapons // If soldier inside building, go out if (s.Building != null) { BattleReport.Add(String.Format("{0} goes out.|{1} выходит наружу.", s.Person.ToString(Lang.En), s.Person.ToString(Lang.Ru))); s.Building = null; } // Pick target for (int pass = 1; pass <= 2; pass++) { for (int j = st; j <= en; j++) { Soldier tg = (Soldier)Soldiers[j]; if (tg.OutOfAction) { continue; } if (pass == 1 && tg.Person.Chosen) { continue; } targets.Add(tg); } if (targets.Count > 0) { break; } } } // Noone to attack if (targets.Count == 0) { throw new NoTargetException(); } Soldier target = (Soldier)targets[Constants.Random(targets.Count)]; HitEvent evt = new HitEvent(s.Person, target.Person); BattleReport.Add(evt); // Roll to hit if (!RollToHit(s, evt)) { return; } if (!s.Weapon.Ranged && (target.Weapon != null && !target.Weapon.Ranged)) { // Roll to parry int parry_roll = Constants.Random(100); if (parry_roll == 99) { evt.Results.Add(HitEvent.Code.CriticalBlock); return; } if (parry_roll == 0) { evt.Results.Add(HitEvent.Code.CriticalBlockFail); } else { if (target.SkillLevel > parry_roll) { evt.Results.Add(HitEvent.Code.Block); return; } } } // Anti-tank weapons ignore wound rolls and armor save if (!s.Weapon.AntiTank) { // Armor save int save_roll = Constants.Random(100); if (save_roll == 99) { evt.Results.Add(HitEvent.Code.CriticalSave); return; } if (save_roll == 0) { evt.Results.Add(HitEvent.Code.CriticalSaveFail); } else { if (s.Weapon != null) { save_roll -= s.Weapon.ArmorModifier; } if (target.Armor != null && save_roll < target.Armor.ArmorSave) { evt.Results.Add(HitEvent.Code.ArmorSave); return; } } // Roll to wound if (!RollToWound(s, evt)) { return; } } // Target is hit KillTarget(s, target, evt); }
private void ExplodeTank(Soldier s) { // Pick target Building target = TargetBuilding(s); // If no buildings to attack, flee if (target == null) { s.Flee = true; throw new NoTargetException(); } HitEvent evt = new HitEvent(s.Person, target); BattleReport.Add(evt); // Roll to hit if (!RollToHit(s, evt)) { return; } // Target is hit, explode evt.Results.Add(HitEvent.Code.Exploded); target.Damage(); // Hit soldiers ArrayList targets = new ArrayList(); foreach (Soldier s2 in Soldiers) { if (s2.Building == target) { targets.Add(s2); } } int escape_roll = Constants.Random(100); if (escape_roll < s.SkillLevel) { targets.Add(s); } foreach (Soldier s2 in targets) { s2.Building = null; // Roll to wound int towound_roll = Constants.Random(100); if (towound_roll == 99) { continue; } if (towound_roll > 0 && towound_roll >= s.Weapon.ToWound) { continue; } // Incapacitate target KillTarget(s, s2, evt); } s.Person.Items.RemoveItems(s.Weapon, 1); s.Flee = true; }