Exemple #1
0
            public static void Postfix(Building_TurretGun __instance, TurretTop ___top)
            {
                // Determine which way the turret initially faces when spawned
                var turretFrameworkExtension = TurretFrameworkExtension.Get(__instance.def);

                switch (turretFrameworkExtension.gunFaceDirectionOnSpawn)
                {
                case TurretGunFaceDirection.North:
                    NonPublicProperties.TurretTop_set_CurRotation(___top, Rot4.North.AsAngle);
                    break;

                case TurretGunFaceDirection.East:
                    NonPublicProperties.TurretTop_set_CurRotation(___top, Rot4.East.AsAngle);
                    break;

                case TurretGunFaceDirection.South:
                    NonPublicProperties.TurretTop_set_CurRotation(___top, Rot4.South.AsAngle);
                    break;

                case TurretGunFaceDirection.West:
                    NonPublicProperties.TurretTop_set_CurRotation(___top, Rot4.West.AsAngle);
                    break;

                default:
                    NonPublicProperties.TurretTop_set_CurRotation(___top, __instance.Rotation.AsAngle);
                    break;
                }
            }
Exemple #2
0
        public static int AdjustedTurretBurstWarmupTicks(int warmupTicks, Building_Turret turret)
        {
            var   extensionValues  = TurretFrameworkExtension.Get(turret.def);
            float warmupTicksFloat = warmupTicks;

            // Multiply the burstWarmupTicksLeft by the manning pawn's aiming delay factor if applicable
            if (extensionValues.useManningPawnAimingDelayFactor)
            {
                var mannableComp = turret.TryGetComp <CompMannable>();
                if (mannableComp != null)
                {
                    var manningPawn = mannableComp.ManningPawn;
                    if (manningPawn != null)
                    {
                        float manningPawnAimingDelayFactor = manningPawn.GetStatValue(StatDefOf.AimingDelayFactor);
                        warmupTicksFloat *= manningPawnAimingDelayFactor;
                    }
                }
            }

            // Multiply based on upgrade
            if (turret.IsUpgraded(out CompUpgradable upgradableComp))
            {
                warmupTicksFloat *= upgradableComp.Props.turretBurstWarmupTimeFactor;
            }

            return(Mathf.RoundToInt(warmupTicksFloat));
        }
            public static void Postfix(Building_TurretGun __instance, ref bool __result)
            {
                // If the turret isn't mannable, is player-controlled and is set to be able to force target, do so
                if (__instance.Faction != Faction.OfPlayer)
                {
                    return;
                }

                var extensionValues = TurretFrameworkExtension.Get(__instance.def);
                var upgradableComp  = __instance.TryGetComp <CompUpgradable>();

                // Upgradable comp doesn't exist/isn't upgraded and can force attack, or exists and upgraded and can force attack
                if (upgradableComp == null || upgradableComp.Props.canForceAttack != null && (upgradableComp.upgraded || !extensionValues.canForceAttack) &&
                    (!upgradableComp.upgraded || !upgradableComp.Props.canForceAttack.Value))
                {
                    return;
                }

                if (!__instance.def.HasComp(typeof(CompMannable)))
                {
                    __result = true;
                }
                else
                {
                    Log.Warning($"Turret (defName={__instance.def.defName}) has canForceAttack set to true and CompMannable; canForceAttack is redundant in this case.");
                }
            }
 public override void TransformValue(StatRequest req, ref float val)
 {
     if (ShouldApply(req, out Building_Turret turret))
     {
         var extensionValues = TurretFrameworkExtension.Get(turret.def);
         val += turret.IsUpgraded(out var upgradableComp) ? upgradableComp.Props.manningPawnShootingAccuracyOffset : extensionValues.manningPawnShootingAccuracyOffset;
     }
 }
        private bool ShouldApply(StatRequest req, out CompMannable mannableComp)
        {
            mannableComp = null;
            if (req.Thing is Building_Turret turret && TurretFrameworkExtension.Get(turret.def).useManningPawnShootingAccuracy)
            {
                mannableComp = turret.GetComp <CompMannable>();
            }

            return(mannableComp != null);
        }
Exemple #6
0
        public static float FiringArcFor(Thing thing)
        {
            // Upgraded and defined firing arc
            if (thing.IsUpgraded(out CompUpgradable upgradableComp))
            {
                return(upgradableComp.Props.FiringArc);
            }

            // Defined firing arc
            return(TurretFrameworkExtension.Get(thing.def).FiringArc);
        }
Exemple #7
0
        public static bool AffectedByEMP(this Building_Turret turret)
        {
            // If turret is upgraded and affectedByEMP is defined, return upgradeComp' affectedByEMP
            if (turret.IsUpgraded(out var upgradableComp) && upgradableComp.Props.affectedByEMP.HasValue)
            {
                return(upgradableComp.Props.affectedByEMP.Value);
            }

            // Otherwise return the DefModExtension's value
            return(TurretFrameworkExtension.Get(turret.def).affectedByEMP);
        }
Exemple #8
0
        public override string ExplanationPart(StatRequest req)
        {
            if (!ShouldApply(req, out var turret))
            {
                return(null);
            }

            var extensionValues = TurretFrameworkExtension.Get(req.Def);
            var offset          = turret.IsUpgraded(out var upgradableComp) ? upgradableComp.Props.manningPawnShootingAccuracyOffset : extensionValues.manningPawnShootingAccuracyOffset;

            return(offset != 0 ? $"{turret.def.LabelCap}: {offset.ToStringByStyle(parentStat.ToStringStyleUnfinalized, ToStringNumberSense.Offset)}" : null);
        }
Exemple #9
0
        public override void ResolveReferences(ThingDef parentDef)
        {
            base.ResolveReferences(parentDef);
            var extensionValues = TurretFrameworkExtension.Get(parentDef);

            // If canForceAttack is unassigned, match it to DefModExtension
            if (!canForceAttack.HasValue)
            {
                canForceAttack = extensionValues.canForceAttack;
            }

            // If firing arc is unchanged, match it to DefModExtension
            if (firingArc == -1)
            {
                firingArc = extensionValues.FiringArc;
            }
        }
Exemple #10
0
            public static bool Prefix(BuildableDef checkingDef, IntVec3 loc, Rot4 rot, ref AcceptanceReport __result)
            {
                // Draw cones instead of circles if firing arc is limited
                float firingArc = TurretFrameworkExtension.Get(checkingDef).FiringArc;

                if (firingArc < 360)
                {
                    var verbProps = ((ThingDef)checkingDef).building.turretGunDef.Verbs.Find((VerbProperties v) => v.verbClass == typeof(Verb_Shoot));
                    if (verbProps.range > 0)
                    {
                        TurretExtensionsUtility.TryDrawFiringCone(loc, rot, verbProps.range, firingArc);
                    }
                    if (verbProps.minRange > 0)
                    {
                        TurretExtensionsUtility.TryDrawFiringCone(loc, rot, verbProps.minRange, firingArc);
                    }
                    __result = true;
                    return(false);
                }
                return(true);
            }
Exemple #11
0
            public static void Postfix(ThingDef __instance, StatRequest req, ref IEnumerable <StatDrawEntry> __result)
            {
                // Add mortar shell stats to the list of stat draw entries
                if (__instance.IsShell)
                {
                    var shellThing            = ThingMaker.MakeThing(__instance.projectileWhenLoaded);
                    var shellProps            = __instance.projectileWhenLoaded.projectile;
                    var shellDamage           = shellProps.GetDamageAmount(shellThing);
                    var shellArmorPenetration = shellProps.GetArmorPenetration(shellThing);
                    var shellStoppingPower    = shellProps.StoppingPower;
                    var shellDamageDef        = shellProps.damageDef.label.CapitalizeFirst();
                    var shellExplosionRadius  = shellProps.explosionRadius;

                    __result = __result.AddItem(new StatDrawEntry(StatCategoryDefOf.TurretAmmo, "Damage".Translate(), shellDamage.ToString(), "Stat_Thing_Damage_Desc".Translate(),
                                                                  20));
                    __result = __result.AddItem(new StatDrawEntry(StatCategoryDefOf.TurretAmmo, "TurretExtensions.ShellDamageType".Translate(), shellDamageDef,
                                                                  "TurretExtensions.ShellDamageType_Desc".Translate(), 19));
                    __result = __result.AddItem(new StatDrawEntry(StatCategoryDefOf.TurretAmmo, "ArmorPenetration".Translate(), shellArmorPenetration.ToStringPercent(),
                                                                  "ArmorPenetrationExplanation".Translate(), 18));
                    __result = __result.AddItem(new StatDrawEntry(StatCategoryDefOf.TurretAmmo, "StoppingPower".Translate(), shellStoppingPower.ToString(),
                                                                  "StoppingPowerExplanation".Translate(), 17));

                    if (shellExplosionRadius > 0)
                    {
                        __result = __result.AddItem(new StatDrawEntry(StatCategoryDefOf.TurretAmmo, "TurretExtensions.ShellExplosionRadius".Translate(),
                                                                      shellExplosionRadius.ToString(), "TurretExtensions.ShellExplosionRadius_Desc".Translate(), 16));
                    }
                }

                // Minimum range
                if (__instance.Verbs.FirstOrDefault(v => v.isPrimary) is VerbProperties verb)
                {
                    var verbStatCategory = __instance.category != ThingCategory.Pawn ? RimWorld.StatCategoryDefOf.Weapon : RimWorld.StatCategoryDefOf.PawnCombat;
                    if (verb.LaunchesProjectile)
                    {
                        if (verb.minRange > default(float))
                        {
                            __result = __result.AddItem(new StatDrawEntry(verbStatCategory, "MinimumRange".Translate(), verb.minRange.ToString("F0"),
                                                                          "TurretExtensions.MinimumRange_Desc".Translate(), 5385));
                        }
                    }
                }

                // Add turret weapons stats to the list of SpecialDisplayStats
                var buildingProps = __instance.building;

                if (buildingProps == null || !buildingProps.IsTurret)
                {
                    return;
                }

                var gunStatList = new List <StatDrawEntry>();

                if (req.Def is ThingDef tDef)
                {
                    // Add upgradability
                    string upgradableString;
                    CompProperties_Upgradable upgradableCompProps;
                    if (req.HasThing && req.Thing.IsUpgradable(out var upgradableComp))
                    {
                        upgradableString    = (upgradableComp.upgraded ? "TurretExtensions.NoAlreadyUpgraded" : "TurretExtensions.YesClickForDetails").Translate();
                        upgradableCompProps = upgradableComp.Props;
                    }
                    else
                    {
                        upgradableString = (tDef.IsUpgradable(out upgradableCompProps) ? "TurretExtensions.YesClickForDetails" : "No").Translate();
                    }

                    var upgradeHyperlinks = new List <Dialog_InfoCard.Hyperlink>();
                    if (upgradableCompProps?.turretGunDef != null)
                    {
                        upgradeHyperlinks.Add(new Dialog_InfoCard.Hyperlink(upgradableCompProps.turretGunDef));
                    }

                    gunStatList.Add(new StatDrawEntry(RimWorld.StatCategoryDefOf.BasicsNonPawn, "TurretExtensions.Upgradable".Translate(), upgradableString,
                                                      TurretExtensionsUtility.UpgradeReadoutReportText(req), 999, hyperlinks: upgradeHyperlinks));

                    // Add firing arc
                    var firingArc = req.HasThing ? TurretExtensionsUtility.FiringArcFor(req.Thing) : TurretFrameworkExtension.Get(tDef).FiringArc;
                    gunStatList.Add(new StatDrawEntry(RimWorld.StatCategoryDefOf.Weapon, "TurretExtensions.FiringArc".Translate(), firingArc.ToStringDegrees(),
                                                      "TurretExtensions.FiringArc_Desc".Translate(), 5380));
                }

                // Replace cooldown
                __result = __result.Where(s => s.stat != StatDefOf.RangedWeapon_Cooldown);
                var cooldownStat = StatDefOf.RangedWeapon_Cooldown;

                gunStatList.Add(new StatDrawEntry(cooldownStat.category, cooldownStat, TurretCooldown(req, buildingProps), StatRequest.ForEmpty(),
                                                  cooldownStat.toStringNumberSense));

                // Replace warmup
                __result = __result.Where(s => s.LabelCap != "WarmupTime".Translate().CapitalizeFirst());
                gunStatList.Add(new StatDrawEntry(RimWorld.StatCategoryDefOf.Weapon, "WarmupTime".Translate(), $"{TurretWarmup(req, buildingProps).ToString("0.##")} s",
                                                  "Stat_Thing_Weapon_MeleeWarmupTime_Desc".Translate(), StatDisplayOrder.Thing_Weapon_MeleeWarmupTime));

                __result = __result.Concat(gunStatList);
            }
Exemple #12
0
        public static string UpgradeReadoutReportText(StatRequest req)
        {
            var tDef         = (ThingDef)req.Def;
            var upgradeProps = tDef.GetCompProperties <CompProperties_Upgradable>();

            // First paragraph
            var reportBuilder = new StringBuilder();

            reportBuilder.AppendLine("TurretExtensions.TurretUpgradeBenefitsMain".Translate());
            reportBuilder.AppendLine();

            // Upgradable
            if (upgradeProps != null)
            {
                var  upgradeComp     = req.Thing?.TryGetComp <CompUpgradable>();
                var  extensionValues = TurretFrameworkExtension.Get(tDef);
                var  defaultStuff    = GenStuff.DefaultStuffFor(tDef);
                bool hasThing        = req.HasThing;

                // Description
                reportBuilder.AppendLine($"{"Description".Translate()}: {upgradeProps.description}");

                // Resource requirements
                if (upgradeProps.costStuffCount > 0 || !upgradeProps.costList.NullOrEmpty())
                {
                    reportBuilder.AppendLine();
                    reportBuilder.AppendLine($"{"TurretExtensions.TurretResourceRequirements".Translate()}:");

                    var usedCostList = upgradeComp != null ? upgradeComp.finalCostList : upgradeProps.costList;
                    for (int i = 0; i < usedCostList.Count; i++)
                    {
                        var curCost = usedCostList[i];
                        reportBuilder.AppendLine($"- {curCost.count}x {curCost.thingDef.LabelCap}");
                    }

                    if (!hasThing && upgradeProps.costStuffCount > 0)
                    {
                        reportBuilder.AppendLine($"- {upgradeProps.costStuffCount}x {"StatsReport_Material".Translate()}");
                    }
                }

                // Construction skill requirement
                if (upgradeProps.constructionSkillPrerequisite > 0)
                {
                    reportBuilder.AppendLine();
                    reportBuilder.AppendLine($"{"ConstructionNeeded".Translate()}: {upgradeProps.constructionSkillPrerequisite}");
                }

                // Research requirements
                if (!upgradeProps.researchPrerequisites.NullOrEmpty())
                {
                    reportBuilder.AppendLine();
                    reportBuilder.AppendLine($"{"ResearchPrerequisites".Translate()}:");

                    for (int i = 0; i < upgradeProps.researchPrerequisites.Count; i++)
                    {
                        reportBuilder.AppendLine($"- {upgradeProps.researchPrerequisites[i].LabelCap}");
                    }
                }

                // Upgrade bonuses
                reportBuilder.AppendLine();
                reportBuilder.AppendLine($"{"TurretExtensions.TurretUpgradeBenefitsUpgradable".Translate()}:");

                // Weapon
                if (upgradeProps.turretGunDef != null)
                {
                    reportBuilder.AppendLine($"- {"Stat_Weapon_Name".Translate()}: {tDef.building.turretGunDef.LabelCap} => {upgradeProps.turretGunDef.LabelCap}");
                }

                // Stat modifiers
                var statsModified = new List <StatDef>();
                if (!upgradeProps.statOffsets.NullOrEmpty())
                {
                    statsModified.AddRange(upgradeProps.statOffsets.Select(s => s.stat));
                }
                if (!upgradeProps.statFactors.NullOrEmpty())
                {
                    statsModified.AddRange(upgradeProps.statFactors.Select(s => s.stat));
                }
                if (statsModified.Any())
                {
                    statsModified = statsModified.Distinct().ToList();
                    statsModified.SortBy(s => s.LabelCap.RawText);
                    for (int i = 0; i < statsModified.Count; i++)
                    {
                        var   curStat       = statsModified[i];
                        var   stringStyle   = curStat.toStringStyle;
                        var   numberSense   = curStat.toStringNumberSense;
                        var   preStatValue  = hasThing ? req.Thing.GetStatValue(curStat) : tDef.GetStatValueAbstract(curStat, defaultStuff);
                        float postStatValue = preStatValue;
                        if (upgradeProps.statOffsets?.StatListContains(curStat) == true)
                        {
                            postStatValue += upgradeProps.statOffsets.GetStatOffsetFromList(curStat);
                        }
                        if (upgradeProps.statFactors?.StatListContains(curStat) == true)
                        {
                            postStatValue *= upgradeProps.statFactors.GetStatFactorFromList(curStat);
                        }
                        reportBuilder.AppendLine($"- {curStat.LabelCap}: {preStatValue.ToStringByStyle(stringStyle, numberSense)} => {postStatValue.ToStringByStyle(stringStyle, numberSense)}");
                    }
                }

                // Fuel capacity
                if (upgradeProps.fuelCapacityFactor != 1 && tDef.GetCompProperties <CompProperties_Refuelable>() is CompProperties_Refuelable refuelProps)
                {
                    reportBuilder.AppendLine($"- {refuelProps.FuelGizmoLabel}: {refuelProps.fuelCapacity} => {Mathf.Round(refuelProps.fuelCapacity * upgradeProps.fuelCapacityFactor)}");
                }

                // Power consumption
                if (upgradeProps.basePowerConsumptionFactor != 1 && tDef.GetCompProperties <CompProperties_Power>() is CompProperties_Power powerProps)
                {
                    reportBuilder.AppendLine($"- {"PowerConsumption".Translate()}: {powerProps.basePowerConsumption.ToString("F0")} =>" +
                                             $" {Mathf.Round(powerProps.basePowerConsumption * upgradeProps.basePowerConsumptionFactor)}");
                }

                // Warmup
                if (upgradeProps.turretBurstWarmupTimeFactor != 1)
                {
                    reportBuilder.AppendLine($"- {"WarmupTime".Translate()}: {upgradeProps.turretBurstWarmupTimeFactor.ToStringByStyle(ToStringStyle.PercentZero, ToStringNumberSense.Factor)}");
                }

                // Cooldown
                if (upgradeProps.turretBurstCooldownTimeFactor != 1)
                {
                    reportBuilder.AppendLine($"- {"StatsReport_Cooldown".Translate()}: {upgradeProps.turretBurstCooldownTimeFactor.ToStringByStyle(ToStringStyle.PercentZero, ToStringNumberSense.Factor)}");
                }

                // Firing arc
                if (upgradeProps.FiringArc != extensionValues.FiringArc)
                {
                    reportBuilder.AppendLine($"- {"TurretExtensions.FiringArc".Translate()}: {extensionValues.FiringArc.ToStringDegrees()} => {upgradeProps.FiringArc.ToStringDegrees()}");
                }

                // User accuracy modifier
                if ((extensionValues.manningPawnShootingAccuracyOffset != 0 || upgradeProps.manningPawnShootingAccuracyOffset != 0) && tDef.HasComp(typeof(CompMannable)))
                {
                    reportBuilder.AppendLine($"- {"TurretExtensions.UserShootingAccuracyModifier".Translate()}: " +
                                             $"{extensionValues.manningPawnShootingAccuracyOffset.ToStringByStyle(ToStringStyle.FloatOne, ToStringNumberSense.Offset)} => " +
                                             $"{(upgradeProps.manningPawnShootingAccuracyOffset).ToStringByStyle(ToStringStyle.FloatOne, ToStringNumberSense.Offset)}");
                }

                // Manually controllable
                if (extensionValues.canForceAttack != upgradeProps.canForceAttack && !tDef.HasComp(typeof(CompMannable)))
                {
                    if (upgradeProps.canForceAttack.Value)
                    {
                        reportBuilder.AppendLine($"- {"TurretExtensions.TurretManuallyControllable".Translate()}");
                    }
                    else
                    {
                        reportBuilder.AppendLine($"- {"TurretExtensions.TurretNotManuallyControllable".Translate()}");
                    }
                }
            }

            // Not upgradable :(
            else
            {
                reportBuilder.AppendLine("TurretExtensions.TurretUpgradeBenefitsNotUpgradable".Translate());
            }

            // Return report text
            return(reportBuilder.ToString());
        }
Exemple #13
0
 public static float FiringArcFor(Thing thing)
 {
     // Upgraded and defined firing arc
     return(thing.IsUpgraded(out var upgradableComp) ? upgradableComp.Props.FiringArc : TurretFrameworkExtension.Get(thing.def).FiringArc);
 }