예제 #1
0
        private void ShootIfReasonable(BattleSoldier soldier, bool isMoving)
        {
            if (soldier.RangedWeapons.Count == 0)
            {
                return;
            }
            float         range    = _grid.GetNearestEnemy(soldier.Soldier.Id, out int closestEnemyId);
            BattleSquad   oppSquad = _opposingSoldierIdSquadMap[closestEnemyId];
            BattleSoldier target   = oppSquad.GetRandomSquadMember();

            range = _grid.GetDistanceBetweenSoldiers(soldier.Soldier.Id, target.Soldier.Id);
            // decide whether to shoot or aim
            Tuple <float, float, RangedWeapon> weaponProfile = ShouldShootAtRange(soldier, target, range, isMoving);

            if (weaponProfile.Item3 != null)
            {
                int shotsToFire = CalculateShotsToFire(weaponProfile.Item3, weaponProfile.Item1, weaponProfile.Item2);
                _shootActionBag.Add(new ShootAction(soldier, weaponProfile.Item3, target, range, shotsToFire, isMoving, _woundResolutionBag, _log));
            }
            else if (!isMoving)
            {
                // aim with longest ranged weapon
                _shootActionBag.Add(new AimAction(soldier, target, soldier.EquippedRangedWeapons.OrderByDescending(w => w.Template.MaximumRange).First(), _log));
            }
        }
예제 #2
0
        public void PrepareActions(BattleSquad squad)
        {
            int retreatVotes = 0;
            int advanceVotes = 0;
            int standVotes   = 0;
            int chargeVotes  = 0;

            // need some concept of squad disposition... stance, whether they're actively aiming
            // determine closest enemy
            // determine our optimal range
            // determine closest enemy optimal range
            // if the enemy wants to advance, we want to stay put, and vice versa
            // if we both want to get closer or both want to stay put, it's more interesting
            if (squad.IsInMelee)
            {
                // it doesn't really matter what the soldiers want to do, it's time to fight
                foreach (BattleSoldier soldier in squad.Soldiers)
                {
                    if (_grid.IsAdjacentToEnemy(soldier.Soldier.Id))
                    {
                        AddMeleeActionsToBag(soldier);
                    }
                    else
                    {
                        AddChargeActionsToBag(soldier);
                    }
                }
            }
            else
            {
                foreach (BattleSoldier soldier in squad.Soldiers)
                {
                    float       distance             = _grid.GetNearestEnemy(soldier.Soldier.Id, out int closestSoldierId);
                    BattleSquad closestSquad         = _opposingSoldierIdSquadMap[closestSoldierId];
                    float       targetSize           = closestSquad.GetAverageSize();
                    float       targetArmor          = closestSquad.GetAverageArmor();
                    float       targetCon            = closestSquad.GetAverageConstitution();
                    float       preferredHitDistance = CalculateOptimalDistance(soldier, targetSize, targetArmor, targetCon);
                    if (preferredHitDistance == -1)
                    {
                        // this soldier wants to run
                        retreatVotes++;
                    }
                    else if (preferredHitDistance == 0)
                    {
                        if (soldier.EquippedRangedWeapons.Count >= 1)
                        {
                            float desperateHitDistance = EstimateArmorPenDistance(soldier.EquippedRangedWeapons[0], targetArmor);
                            desperateHitDistance = Mathf.Min(desperateHitDistance, EstimateHitDistance(soldier.Soldier, soldier.EquippedRangedWeapons[0], targetSize, soldier.HandsFree));
                            if (desperateHitDistance > 0)
                            {
                                float targetPreferredDistance = CalculateOptimalDistance(closestSquad.GetRandomSquadMember(),
                                                                                         soldier.Soldier.Size,
                                                                                         soldier.Armor.Template.ArmorProvided,
                                                                                         soldier.Soldier.Constitution);

                                if (desperateHitDistance < targetPreferredDistance)
                                {
                                    // advance
                                    advanceVotes++;
                                }
                                else
                                {
                                    // don't advance
                                    standVotes++;
                                }
                            }
                            else
                            {
                                advanceVotes++;
                                chargeVotes++;
                            }
                        }
                        else
                        {
                            advanceVotes++;
                            chargeVotes++;
                        }
                    }
                    else if (distance > preferredHitDistance * 3)
                    {
                        advanceVotes++;
                    }
                    else
                    {
                        float targetPreferredDistance = CalculateOptimalDistance(closestSquad.GetRandomSquadMember(),
                                                                                 soldier.Soldier.Size,
                                                                                 soldier.Armor.Template.ArmorProvided,
                                                                                 soldier.Soldier.Constitution);

                        if (preferredHitDistance < targetPreferredDistance)
                        {
                            // advance
                            advanceVotes++;
                        }
                        else
                        {
                            // don't advance
                            standVotes++;
                        }
                    }
                }

                if (advanceVotes > standVotes && advanceVotes > retreatVotes)
                {
                    _log.Enqueue(squad.Name + " advances");
                    if (chargeVotes >= advanceVotes / 2)
                    {
                        foreach (BattleSoldier soldier in squad.Soldiers)
                        {
                            AddChargeActionsToBag(soldier);
                        }
                    }
                    else
                    {
                        foreach (BattleSoldier soldier in squad.Soldiers)
                        {
                            AddAdvanceActionsToBag(soldier);
                        }
                    }
                }
                else if (retreatVotes > standVotes && retreatVotes > advanceVotes)
                {
                    foreach (BattleSoldier soldier in squad.Soldiers)
                    {
                        AddRetreatingActionsToBag(soldier, squad);
                    }
                }
                else
                {
                    foreach (BattleSoldier soldier in squad.Soldiers)
                    {
                        AddStandingActionsToBag(soldier);
                    }
                }
            }
        }