Пример #1
0
        private void BuildFireCone()
        {
            _fireCone = null;
            var pawn = Main.GetSelectedPawn();

            if (pawn == null)
            {
                return;
            }

            if (!HasValidWeapon(pawn))
            {
                return;
            }

            var targetCell = UI.MouseCell();
            var pawnCell   = pawn.Position;

            if (pawnCell.DistanceTo(targetCell) > GetEquippedWeaponRange(pawn))
            {
                return;
            }

            var fireProperties = new FireProperties(pawn, targetCell);

            _fireCone = FireCalculations.GetFireCone(fireProperties);
        }
Пример #2
0
        private HashSet <int> GetOrCreatedCachedFireConeFor(FireProperties fireProperties)
        {
            var originIndex = fireProperties.OriginIndex;
            var targetIndex = fireProperties.TargetIndex;

            if (_cachedFireCones.TryGetValue(originIndex, out var cachedFireConesFromOrigin))
            {
                if (cachedFireConesFromOrigin.TryGetValue(targetIndex, out var cachedFireCone))
                {
                    if (!cachedFireCone.IsExpired())
                    {
                        cachedFireCone.Prolong();
                        return(cachedFireCone.FireCone);
                    }
                }
            }

            // No cached firecone, create one
            var newFireCone = new CachedFireCone(FireCalculations.GetFireCone(fireProperties));

            if (!_cachedFireCones.ContainsKey(originIndex))
            {
                _cachedFireCones.Add(originIndex, new Dictionary <int, CachedFireCone>());
            }

            _cachedFireCones[originIndex][targetIndex] = newFireCone;

            return(newFireCone.FireCone);
        }
Пример #3
0
        public static HashSet <int> GetFireCone(FireProperties fireProperties)
        {
            if (!fireProperties.ArePointsVisibleAndValid())
            {
                return(null);
            }

            fireProperties.AdjustForLeaning();

            var missAreaDescriptor = fireProperties.GetMissAreaDescriptor();

            var result = new HashSet <int>();

            result.Clear();
            var map = Find.CurrentMap;

            for (var i = 0; i < missAreaDescriptor.AdjustmentCount; i++)
            {
                var splashTarget = fireProperties.Target + missAreaDescriptor.AdjustmentVector[i];
                result.UnionWith(GetShootablePointsBetween(fireProperties.Origin, splashTarget, map));
            }


            return(result);
        }
Пример #4
0
        public static bool HasValidWeapon(Pawn pawn)
        {
            var primaryWeaponVerb = FireProperties.GetEquippedWeaponVerb(pawn);

            if (primaryWeaponVerb?.verbProps?.defaultProjectile?.projectile == null)
            {
                return(false);
            }

            if (primaryWeaponVerb.verbProps.defaultProjectile.projectile.explosionRadius > 0.2f)
            {
                // Can't handle explosive projectiles yet
                return(false);
            }

            // TODO check if projectile is flyOverhead

            return(true);
        }
Пример #5
0
        public static float GetEquippedWeaponRange(Pawn pawn)
        {
            var primaryWeaponVerb = FireProperties.GetEquippedWeaponVerb(pawn);

            return(primaryWeaponVerb?.verbProps.range ?? 0);
        }
Пример #6
0
        public bool CanHitTargetSafely(FireProperties fireProperties)
        {
            if (SkipNextCheck)
            {
                SkipNextCheck = false;
                return(true);
            }

            Main.Instance.PawnStatusTracker.Remove(fireProperties.Caster);

            HashSet <int> fireCone = GetOrCreatedCachedFireConeFor(fireProperties);

            if (fireCone == null)
            {
                return(true);
            }

            var map = fireProperties.CasterMap;

            foreach (var pawn in map.mapPawns.AllPawns)
            {
                if (pawn?.RaceProps == null || pawn.Dead)
                {
                    continue;
                }

                if (pawn.Faction == null)
                {
                    continue;
                }

                if (pawn.RaceProps.Humanlike)
                {
                    if (pawn.IsPrisoner)
                    {
                        continue;
                    }

                    if (pawn.HostileTo(Faction.OfPlayer))
                    {
                        continue;
                    }
                }
                else if (!ShouldProtectAnimal(pawn))
                {
                    continue;
                }

                var pawnCell = pawn.Position;
                if (pawnCell == fireProperties.Origin || pawnCell == fireProperties.Target)
                {
                    continue;
                }

                var pawnIndex = map.cellIndices.CellToIndex(pawnCell);
                if (!fireCone.Contains(pawnIndex))
                {
                    continue;
                }

                if (IsPawnWearingUsefulShield(pawn))
                {
                    continue;
                }

                Main.Instance.PawnStatusTracker.AddBlockedShooter(fireProperties.Caster, pawn);

                return(false);
            }

            return(true);
        }