Ejemplo n.º 1
0
        public static bool trySwapToMoreAccurateRangedWeapon(Pawn pawn, LocalTargetInfo target, bool dropCurrent, bool skipManualUse, bool skipDangerous = true, bool skipEMP = true)
        {
            CompSidearmMemory pawnMemory = CompSidearmMemory.GetMemoryCompForPawn(pawn);

            if (pawn == null || pawn.Dead || pawnMemory == null || pawn.equipment == null || pawn.inventory == null)
            {
                return(false);
            }

            if (pawnMemory.IsCurrentWeaponForced(false))
            {
                return(false);
            }

            (ThingWithComps weapon, float dps, float averageSpeed)bestWeapon = GettersFilters.findBestRangedWeapon(pawn, target, skipManualUse, skipDangerous, skipEMP, true);

            if (bestWeapon.weapon == null)
            {
                return(false);
            }

            CellRect cellRect   = (!target.HasThing) ? CellRect.SingleCell(target.Cell) : target.Thing.OccupiedRect();
            float    range      = cellRect.ClosestDistSquaredTo(pawn.Position);
            float    currentDPS = StatCalculator.RangedDPS(pawn.equipment.Primary, Settings.SpeedSelectionBiasRanged, bestWeapon.averageSpeed, range);

            if (bestWeapon.dps < currentDPS + MiscUtils.ANTI_OSCILLATION_FACTOR)
            {
                return(false);
            }

            equipSpecificWeaponFromInventory(pawn, bestWeapon.weapon, dropCurrent, false);
            return(true);
        }
Ejemplo n.º 2
0
        public static (ThingWithComps weapon, float dps, float averageSpeed) findBestRangedWeapon(Pawn pawn, LocalTargetInfo?target = null, bool skipManualUse = true, bool skipDangerous = true, bool skipEMP = true, bool includeEquipped = true)
        {
            if (pawn == null || pawn.Dead || pawn.equipment == null || pawn.inventory == null)
            {
                return(null, -1, 0);
            }

            IEnumerable <ThingWithComps> options = pawn.getCarriedWeapons(includeEquipped).Where(t => t.def.IsRangedWeapon);

            if (!Settings.AllowBlockedWeaponUse)
            {
                options = options.Where(t => StatCalculator.canUseSidearmInstance(t, pawn, out _));
            }

            options = options.Where(t => !pawn.IsColonistPlayerControlled || !isManualUse(t));

            if (skipManualUse)
            {
                options = options.Where(t => (!isManualUse(t)));
            }
            if (skipDangerous)
            {
                options = options.Where(t => (!isDangerousWeapon(t)));
            }
            if (skipEMP)
            {
                options = options.Where(t => !isEMPWeapon(t));
            }

            if (options.Count() == 0)
            {
                return(null, -1, 0);
            }

            float averageSpeed = AverageSpeedRanged(options);

            if (target.HasValue)
            {
                CellRect cellRect       = (!target.Value.HasThing) ? CellRect.SingleCell(target.Value.Cell) : target.Value.Thing.OccupiedRect();
                float    targetDistance = cellRect.ClosestDistSquaredTo(pawn.Position);

                options = options.Where(t =>
                {
                    VerbProperties atkProps = (t.GetComp <CompEquippable>())?.PrimaryVerb?.verbProps;
                    if (atkProps == null)
                    {
                        return(false);
                    }
                    return(atkProps.range >= targetDistance);
                });

                if (options.Count() == 0)
                {
                    return(null, -1, 0);
                }

                //TODO: handle DPS vs. armor?
                (ThingWithComps thing, float dps, float averageSpeed)best = (null, -1, averageSpeed);
                foreach (ThingWithComps candidate in options)
                {
                    float dps = StatCalculator.RangedDPS(candidate, Settings.SpeedSelectionBiasRanged, averageSpeed, targetDistance);
                    if (dps > best.dps)
                    {
                        best = (candidate, dps, averageSpeed);
                    }
                }
                return(best);
            }
            else
            {
                (ThingWithComps thing, float dps, float averageSpeed)best = (null, -1, averageSpeed);
                foreach (ThingWithComps candidate in options)
                {
                    float dps = StatCalculator.RangedDPSAverage(candidate, Settings.SpeedSelectionBiasRanged, averageSpeed);
                    if (dps > best.dps)
                    {
                        best = (candidate, dps, averageSpeed);
                    }
                }
                return(best);
            }
        }