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; }
private void Run() { ArrayList reflexes = new ArrayList(); foreach (Soldier s in Soldiers) { if (!reflexes.Contains(s.Reflexes)) { reflexes.Add(s.Reflexes); } } reflexes.Sort(); for (int turn = 1; turn <= 50; turn++) { bool shooters = (turn == 1 && ShootersPresent()); BattleReport.Add(""); BattleReport.Add(String.Format("Round {0}{1}|Раунд {0}{2}", turn.ToString(), (shooters ? " (ranged only)" : ""), (shooters ? " (только стрелки)" : "") )); // Process all soldiers in order of reflexes bool attackers_moved = false; bool defenders_moved = false; for (int i = reflexes.Count - 1; i >= 0; i--) { ArrayList acting = new ArrayList(); foreach (Soldier s in Soldiers) { if (s.Reflexes == (int)reflexes[i]) { acting.Add(s); } } while (acting.Count > 0) { int idx = Constants.Random(acting.Count); Soldier s = (Soldier)acting[idx]; if (!s.OutOfAction) { try { MoveSoldier(s, turn); if (s.Side == Side.Attacker) { attackers_moved = true; } else { defenders_moved = true; } } catch (NoTargetException) { BattleReport.Add(String.Format("{0}: can't attack anybody.|{1}: не может никого атаковать.", s.Person.ToString(Lang.En), s.Person.ToString(Lang.Ru))); } } acting.RemoveAt(idx); if (BattleEnded()) { return; } } } if (turn > 1) { if (!attackers_moved) { BattleReport.Add("Attackers panicked and ran away.|Атакующие запаниковали и убегают."); for (int i = 0; i < FirstDefender; i++) { ((Soldier)Soldiers[i]).Flee = true; } } if (!defenders_moved) { BattleReport.Add("Defenders panicked and ran away.|Защитники запаниковали и убегают."); for (int i = FirstDefender; i < Soldiers.Count; i++) { ((Soldier)Soldiers[i]).Flee = true; } } } } }
private void MoveSoldier(Soldier s, int round) { if (s.Weapon == null || s.SkillLevel == 0 || s.Person.Avoiding) { s.Flee = true; } if (s.Flee) { OOASoldier(s); s.FleedAway = true; BattleReport.Add(String.Format("{0} ran away from combat.|{1} убегает из боя.", s.Person.ToString(Lang.En), s.Person.ToString(Lang.Ru))); return; } // First turn is for ranged weapon only if shooters on field if (round == 1 && ShootersPresent() && !s.Weapon.Ranged) { return; } for (int i = 0; i < s.Weapon.Attacks; i++) { if (OutOfAmmo(s)) { break; } for (int j = 0; j < s.Weapon.Targets; j++) { MakeHit(s); if (BattleEnded()) { break; } } if (s.Ammo > 0) { s.Ammo--; } if (s.Weapon.Ammo != null) { if (s.Weapon.Ammo.Case != null) { Spoils.AddItems(s.Weapon.Ammo.Case, 1); } s.Person.Items.RemoveItems(s.Weapon.Ammo, 1); } if (OutOfAmmo(s)) { break; } if (BattleEnded()) { break; } } }
private void PrintSoldier(Soldier soldier) { // En string s = soldier.Person.ToString(Lang.En); if (!soldier.Person.HideFaction && soldier.Person.Faction != null) { s += ", " + soldier.Person.Faction.ToString(Lang.En); } if (soldier.Person.Avoiding) { s += ", avoiding"; } if (soldier.Weapon != null) { if (soldier.Weapon.IsMan) { s += ", unarmed"; } else { s += ", " + soldier.Weapon.ToString(1, Lang.En); } if (soldier.Weapon.Ammo != null) { s += " (ammo: " + soldier.Ammo.ToString() + ")"; } } if (soldier.Armor != null && !soldier.Armor.IsMan) { s += ", " + soldier.Armor.ToString(1, Lang.En); } s += ", skill " + soldier.SkillLevel.ToString(); s += ", reflexes " + soldier.Reflexes; if (soldier.Building != null) { s += ", inside " + soldier.Building.ToString(Lang.En) + " (" + Hits[soldier.Building].ToString() + " hp)"; } s += "."; // Ru s += "|" + soldier.Person.ToString(Lang.Ru); if (!soldier.Person.HideFaction && soldier.Person.Faction != null) { s += ", " + soldier.Person.Faction.ToString(Lang.Ru); } if (soldier.Person.Avoiding) { s += ", избегает боя"; } if (soldier.Weapon != null) { if (soldier.Weapon.IsMan) { s += ", без оружия"; } else { s += ", " + soldier.Weapon.ToString(1, Lang.Ru); } if (soldier.Weapon.Ammo != null) { s += " (заряды: " + soldier.Ammo.ToString() + ")"; } } if (soldier.Armor != null && !soldier.Armor.IsMan) { s += ", " + soldier.Armor.ToString(1, Lang.Ru); } s += ", навык " + soldier.SkillLevel.ToString(); s += ", рефлексы " + soldier.Reflexes; if (soldier.Building != null) { s += ", объект: " + soldier.Building.ToString(Lang.Ru) + " (" + Hits[soldier.Building].ToString() + " хитов)"; } s += "."; BattleReport.Add(s); }