public override IEnumerable <StatDrawEntry> SpecialDisplayStats(StatRequest req)
        {
            foreach (StatDrawEntry s in base.SpecialDisplayStats(req))
            {
                yield return(s);
            }
            if (DeepStorageCategory == null)
            {
                DeepStorageCategory = DefDatabase <StatCategoryDef> .GetNamed("LWM_DS_Stats");

                if (DeepStorageCategory == null)
                {
                    Log.Warning("LWM.DeepStorage: Stat Category FAILED to load.");
                    yield break;
                }
            }
            yield return(new StatDrawEntry(DeepStorageCategory, "LWM_DS_maxNumStacks".Translate(),
                                           size > 1?
                                           "LWM_DS_TotalAndPerCell".Translate(maxNumberStacks * size, maxNumberStacks)
                                           :maxNumberStacks.ToString(),
                                           10 /*display priority*/, "LWM_DS_maxNumStacksDesc".Translate()));

            if (maxTotalMass > 0f)
            {
                yield return(new StatDrawEntry(DeepStorageCategory, "LWM_DS_maxTotalMass".Translate(),
                                               size > 1?
                                               "LWM_DS_TotalAndPerCell".Translate(kg(maxTotalMass * size), kg(maxTotalMass))
                                       :kg(maxTotalMass),
                                               9, "LWM_DS_maxTotalMassDesc".Translate()));
            }
            if (maxMassOfStoredItem > 0f)
            {
                yield return(new StatDrawEntry(DeepStorageCategory, "LWM_DS_maxMassOfStoredItem".Translate(),
                                               kg(maxMassOfStoredItem),
                                               8, "LWM_DS_maxMassOfStoredItemDesc".Translate()));
            }
            if (AllowedCategoriesString != "")
            {
                yield return(new StatDrawEntry(DeepStorageCategory, "LWM_DS_allowedCategories".Translate(),
                                               AllowedCategoriesString,
                                               7, "LWM_DS_allowedCategoriesDesc".Translate()));
            }
            if (AllowedDefsString != "")
            {
                yield return(new StatDrawEntry(DeepStorageCategory, "LWM_DS_allowedDefs".Translate(),
                                               AllowedDefsString,
                                               6, "LWM_DS_allowedDefsDesc".Translate()));
            }
            if (DisallowedString != "")
            {
                yield return(new StatDrawEntry(DeepStorageCategory, "LWM_DS_disallowedStuff".Translate(),
                                               DisallowedString,
                                               5, "LWM_DS_disallowedStuffDesc".Translate()));
            }
//            if (parent?.building?.fixedStorageSettings?.filter
            yield break;
        }
        private static bool ShowForPawn(StatDef statDef)
        {
            StatCategoryDef category = statDef.category;

            return(category == StatCategoryDefOf.PawnCombat ||
                   category == StatCategoryDefOf.PawnMisc ||
                   category == StatCategoryDefOf.PawnSocial ||
                   category == StatCategoryDefOf.PawnWork);
        }
Esempio n. 3
0
 public StatDrawEntry(StatCategoryDef category, string label, string valueString, int displayPriorityWithinCategory = 0)
 {
     this.category                   = category;
     this.stat                       = null;
     this.labelInt                   = label;
     this.value                      = 0f;
     this.valueStringInt             = valueString;
     this.displayOrderWithinCategory = displayPriorityWithinCategory;
     this.numberSense                = ToStringNumberSense.Absolute;
 }
Esempio n. 4
0
 public static void Thing_PostfixSpecialDisplayStats(Thing __instance, ref IEnumerable <StatDrawEntry> __result)
 {
     if (Traverse.Create(__instance.def).Field("verbs").GetValue() is List <VerbProperties> verbs)
     {
         VerbProperties verb = verbs.First(x => x.isPrimary);
         if (verb.LaunchesProjectile && verb.defaultProjectile is ThingDef dP && dP.projectile is ProjectileProperties p)
         {
             StatCategoryDef c   = (__instance.def.category != ThingCategory.Pawn) ? StatCategoryDefOf.Weapon : StatCategoryDefOf.PawnCombat;
             string          vS  = GetAdjustedStoppingPower(p.StoppingPower, __instance).ToString("F2");
             string          oRT = "StoppingPowerExplanation".Translate();
             __result = __result.Add(new StatDrawEntry(c, "StoppingPower".Translate(), vS, overrideReportText: oRT));
         }
     }
 }
Esempio n. 5
0
        public StatDrawEntry CreateStacklimitStatEntry(ThingDef thingDef, int displayPriority)
        {
            StatCategoryDef stockingCat = StockingStatCategoryDefOf.Stocking;

            int   overstackLimit      = (int)((float)thingDef.stackLimit * OverstackLimitPerOverlay);
            int   overlays            = InRackMode ? OverlayLimit : 1;
            float allowedMassPerThing = MaxStockWeight / overlays;
            int   massLimit           = (int)(allowedMassPerThing / StockingUtility.cachedThingDefMasses[thingDef]);

            return(new StatDrawEntry(stockingCat, "StackLimitStat.Label".Translate(thingDef.label)
                                     , stackLimits[thingDef] + "/" + maxStackLimits[thingDef].ToString()
                                     , displayPriority, "MaxStackLimitStat.Text"
                                     .Translate(thingDef.label, thingDef.stackLimit, OverstackLimitPerOverlay, overstackLimit
                                                , allowedMassPerThing, massLimit, maxStackLimits[thingDef])));
        }
        // FIXME: Icons on the affix hyperlinks
        public override IEnumerable <StatDrawEntry> SpecialDisplayStats()
        {
            StatCategoryDef category =
                parent.def.IsApparel ? StatCategoryDefOf.Apparel :
                parent.def.IsWeapon  ? StatCategoryDefOf.Weapon  :
                StatCategoryDefOf.BasicsImportant
            ;

            string reportText = "RimLoot_LootAffixDescription".Translate() + "\n\n";
            var    affixDict  = AllAffixDefsByAffixes;

            foreach (string affixKey in AffixStrings)
            {
                LootAffixDef affix = affixDict[affixKey];
                reportText += affix.FullStatsReport(parent, affixKey) + "\n";
            }

            if (Prefs.DevMode)
            {
                reportText += "[DEV] Affix Rules:\n    " + string.Join("\n    ", affixRules) + "\n\n";
                reportText += "[DEV] Total Points: " + affixes.Select(lad => lad.GetRealAffixCost(parent)).Sum() +
                              "\n    " +
                              string.Join("\n    ", affixes.Select(lad => AllAffixesByAffixDefs[lad] + ": " + lad.GetRealAffixCost(parent))) +
                              "\n\n"
                ;
            }

            yield return(new StatDrawEntry(
                             category:    category,
                             label:       "RimLoot_LootAffixModifiers".Translate(),
                             valueString: GenText.ToCommaList(
                                 AllAffixDefsByAffixes.Select(kv => kv.Value.LabelWithStyle(parent, kv.Key)), false
                                 ),
                             reportText:  reportText,
                             hyperlinks:  affixes.SelectMany(lad => lad.GetHyperlinks(parent)),
                             displayPriorityWithinCategory: 1
                             ));

            // Add any additional entries from the defs or modifiers
            foreach (string affixKey in AffixStrings)
            {
                LootAffixDef affix = affixDict[affixKey];
                foreach (var statDrawEntry in affix.SpecialDisplayStatsForThing(parent, affixKey))
                {
                    yield return(statDrawEntry);
                }
            }
        }
Esempio n. 7
0
 public StatDrawEntry(StatCategoryDef category, StatDef stat, float value, StatRequest optionalReq, ToStringNumberSense numberSense = ToStringNumberSense.Undefined)
 {
     this.category                   = category;
     this.stat                       = stat;
     this.labelInt                   = null;
     this.value                      = value;
     this.valueStringInt             = null;
     this.displayOrderWithinCategory = 0;
     this.optionalReq                = optionalReq;
     this.hasOptionalReq             = true;
     if (numberSense == ToStringNumberSense.Undefined)
     {
         this.numberSense = stat.toStringNumberSense;
     }
     else
     {
         this.numberSense = numberSense;
     }
 }
Esempio n. 8
0
        public override IEnumerable <string> ConfigErrors(LootAffixDef parentDef)
        {
            foreach (string configError in base.ConfigErrors(parentDef))
            {
                yield return(configError);
            }

            StatCategoryDef        category             = affectedStat.category;
            List <StatCategoryDef> acceptableCategories = new List <StatCategoryDef>()
            {
                StatCategoryDefOf.Basics, StatCategoryDefOf.BasicsImportant, StatCategoryDefOf.BasicsNonPawn,
                StatCategoryDefOf.BasicsPawn, StatCategoryDefOf.BasicsPawnImportant, StatCategoryDefOf.PawnCombat,
                StatCategoryDefOf.PawnMisc, StatCategoryDefOf.PawnSocial, StatCategoryDefOf.PawnWork,
            };

            if (!acceptableCategories.Contains(category))
            {
                yield return("The affectedStat isn't in the typical stat categories: " + category);
            }
        }
Esempio n. 9
0
            static AnimalGeneticsAssemblyLoader()
            {
                var h = new Harmony("AnimalGenetics");

                h.PatchAll();

                DefDatabase <StatDef> .Add(AnimalGenetics.Damage);

                DefDatabase <StatDef> .Add(AnimalGenetics.Health);

                DefDatabase <StatDef> .Add(AnimalGenetics.GatherYield);

                var affectedStats = Constants.affectedStatsToInsert;

                foreach (var stat in affectedStats)
                {
                    try
                    {
                        stat.parts?.Insert(0, new StatPart(stat));
                    }
                    catch
                    {
                        Log.Error(stat + " is broken");
                    }
                }

                var category = new StatCategoryDef {
                    defName = "AnimalGenetics_Category", label = "Genetics", displayAllByDefault = true, displayOrder = 200
                };

                DefDatabase <StatCategoryDef> .Add(category);

                foreach (var stat in Constants.affectedStats)
                {
                    DefDatabase <StatDef> .Add(new StatDefWrapper { defName = "AnimalGenetics_" + stat.defName, label = Constants.GetLabel(stat), Underlying = stat, category = category, workerClass = typeof(StatWorker), toStringStyle = ToStringStyle.PercentZero });
                }

                StatDefOf.MarketValue.parts.Add(new MarketValueCalculator());

                gatherableTypes = new List <Type>()
                {
                    typeof(CompShearable),
                    typeof(CompMilkable)
                };

                // Compatibility patches
                try
                {
                    if (LoadedModManager.RunningModsListForReading.Any(x => x.PackageId == "sarg.alphaanimals" || x.Name == "Alpha Animals"))
                    {
                        Log.Message("Animal Genetics : Alpha Animals is loaded - Patching");
                        h.Patch(AccessTools.Method(AccessTools.TypeByName("AlphaBehavioursAndEvents.CompAnimalProduct"), "get_ResourceAmount"),
                                postfix: new HarmonyMethod(typeof(CompatibilityPatches), nameof(CompatibilityPatches.AlphaAnimals_get_ResourceAmount_Patch)));
                        gatherableTypes.Add(AccessTools.TypeByName("AlphaBehavioursAndEvents.CompAnimalProduct"));
                    }
                    if (LoadedModManager.RunningModsListForReading.Any(x => x.PackageId == "CETeam.CombatExtended" || x.Name == "Combat Extended"))
                    {
                        //gatherableTypes.Append(AccessTools.TypeByName("CombatExtended.CompMilkableRenameable")); //they all use shearable
                        gatherableTypes.Add(AccessTools.TypeByName("CombatExtended.CompShearableRenameable"));
                    }

                    if (LoadedModManager.RunningModsListForReading.Any(x => x.PackageId == "rim.job.world"))
                    {
                        Log.Message("Patched RJW");
                        h.Patch(AccessTools.Method(AccessTools.TypeByName("rjw.Hediff_BasePregnancy"), "GenerateBabies"),
                                prefix: new HarmonyMethod(typeof(CompatibilityPatches), nameof(CompatibilityPatches.RJW_GenerateBabies_Prefix)),
                                postfix: new HarmonyMethod(typeof(CompatibilityPatches), nameof(CompatibilityPatches.RJW_GenerateBabies_Postfix)));
                    }
                }
                catch { }

                if (ColonyManager.ModRunning && Settings.Integration.ColonyManagerIntegration)
                {
                    ColonyManager.Patch(h);
                }

                _DefaultAnimalsPawnTableDefColumns  = new List <PawnColumnDef>(PawnTableDefOf.Animals.columns);
                _DefaultWildlifePawnTableDefColumns = new List <PawnColumnDef>(PawnTableDefOf.Wildlife.columns);

                var placeholderPosition = MainTabWindow_AnimalGenetics.PawnTableDefs.Genetics.columns.FindIndex(def => def.defName == "AnimalGenetics_Placeholder");

                MainTabWindow_AnimalGenetics.PawnTableDefs.Genetics.columns.RemoveAt(placeholderPosition);
                MainTabWindow_AnimalGenetics.PawnTableDefs.Genetics.columns.InsertRange(placeholderPosition, PawnTableColumnsDefOf.Genetics.columns);

                PatchUI();
            }
        public static IEnumerable <StatDrawEntry> SpecialDisplayStats(HediffDef hediff, StatRequest req)
        {
            category = DefDatabase <StatCategoryDef> .GetNamed("Basics");

            yield return(HediffCategoryStat(hediff));

            if (hediff.isBad)
            {
                yield return(new StatDrawEntry(
                                 category:    category,
                                 label:       "Stat_Hediff_Tendable_Name".Translate(),
                                 reportText:  "Stat_Hediff_Tendable_Desc".Translate(),
                                 valueString: hediff.tendable.ToStringYesNo(),
                                 displayPriorityWithinCategory: 4975
                                 ));

                yield return(new StatDrawEntry(
                                 category:    category,
                                 label:       "Stat_Hediff_Immunizable_Name".Translate(),
                                 reportText:  "Stat_Hediff_Immunizable_Desc".Translate(),
                                 valueString: hediff.PossibleToDevelopImmunityNaturally().ToStringYesNo(),
                                 displayPriorityWithinCategory: 4970
                                 ));

                bool canBeLethal = hediff.lethalSeverity > 0 || (hediff.stages != null && hediff.stages.Any(s => s.lifeThreatening));

                yield return(new StatDrawEntry(
                                 category:    category,
                                 label:       "Stat_Hediff_Lethal_Name".Translate(),
                                 reportText:  "Stat_Hediff_Lethal_Desc".Translate(),
                                 valueString: canBeLethal.ToStringYesNo(),
                                 displayPriorityWithinCategory: 4965
                                 ));
            }

            if (hediff.addedPartProps != null)
            {
                StatCategoryDef implantCategory = DefDatabase <StatCategoryDef> .GetNamed("Implant");

                var props = hediff.addedPartProps;

                if (hediff.spawnThingOnRemoved != null)
                {
                    yield return(new StatDrawEntry(
                                     category:    implantCategory,
                                     label:       "Stat_Hediff_RelatedPart_Name".Translate(),
                                     reportText:  "Stat_Hediff_RelatedPart_Desc".Translate(),
                                     valueString: hediff.spawnThingOnRemoved.LabelCap,
                                     hyperlinks:  new[] { new Dialog_InfoCard.Hyperlink(hediff.spawnThingOnRemoved) },
                                     displayPriorityWithinCategory: 5000
                                     ));
                }
                yield return(new StatDrawEntry(
                                 category:    implantCategory,
                                 label:       "PartEfficiency".Translate(),
                                 reportText:  "Stat_Thing_BodyPartEfficiency_Desc".Translate(),
                                 valueString: props.partEfficiency.ToStringPercent(),
                                 displayPriorityWithinCategory: 4950
                                 ));

                yield return(new StatDrawEntry(
                                 category:    implantCategory,
                                 label:       "Stat_Hediff_BetterThanNatural_Name".Translate(),
                                 reportText:  "Stat_Hediff_BetterThanNatural_Desc".Translate(),
                                 valueString: props.betterThanNatural.ToStringYesNo(),
                                 displayPriorityWithinCategory: 4920
                                 ));

                yield return(new StatDrawEntry(
                                 category:    implantCategory,
                                 label:       "Stat_Hediff_Solid_Name".Translate(),
                                 reportText:  "Stat_Hediff_Solid_Desc".Translate(),
                                 valueString: props.solid.ToStringYesNo(),
                                 displayPriorityWithinCategory: 4900
                                 ));
            }

            if (hediff.priceImpact || hediff.priceOffset != 0)
            {
                float priceOffset = hediff.priceOffset;
                if (priceOffset == 0 && hediff.spawnThingOnRemoved != null)
                {
                    priceOffset = hediff.spawnThingOnRemoved.BaseMarketValue;
                }

                if (priceOffset >= 1.0 || priceOffset <= -1.0)
                {
                    yield return(new StatDrawEntry(
                                     category:    category,
                                     label:       "Stat_Hediff_PriceOffset_Name".Translate(),
                                     reportText:  "Stat_Hediff_PriceOffset_Desc".Translate(),
                                     valueString: priceOffset.ToStringMoneyOffset(),
                                     displayPriorityWithinCategory: 5500
                                     ));
                }
            }
        }
Esempio n. 11
0
        public static IEnumerable <StatDrawEntry> SpecialDisplayStats(BodyPartDef bodyPart, StatRequest req)
        {
            category = DefDatabase <StatCategoryDef> .GetNamed("Basics");

            yield return(new StatDrawEntry(
                             category:    category,
                             label:       "HitPointsBasic".Translate(),
                             reportText:  "Stat_HitPoints_Desc".Translate(),
                             valueString: bodyPart.hitPoints.ToString(),
                             displayPriorityWithinCategory: StatDisplayOrder.HitPointsBasic
                             ));

            if (bodyPart.spawnThingOnRemoved != null)
            {
                yield return(new StatDrawEntry(
                                 category:    category,
                                 label:       "Stat_BodyPart_RemovedPart_Name".Translate(),
                                 reportText:  "Stat_BodyPart_RemovedPart_Desc".Translate(),
                                 valueString: bodyPart.spawnThingOnRemoved.LabelCap,
                                 hyperlinks:  new[] { new Dialog_InfoCard.Hyperlink(bodyPart.spawnThingOnRemoved) },
                                 displayPriorityWithinCategory: 5000
                                 ));
            }

            string permanentInjuryChanceFactorString = bodyPart.permanentInjuryChanceFactor > 10000 ?
                                                       "Infinite".Translate().ToString() :
                                                       bodyPart.permanentInjuryChanceFactor.ToStringPercent()
            ;

            yield return(new StatDrawEntry(
                             category:    category,
                             label:       "Stat_BodyPart_PermanentInjuryChanceFactor_Name".Translate(),
                             reportText:  "Stat_BodyPart_PermanentInjuryChanceFactor_Desc".Translate(),
                             valueString: permanentInjuryChanceFactorString,
                             displayPriorityWithinCategory: 4890
                             ));

            yield return(new StatDrawEntry(
                             category:    category,
                             label:       "Stat_BodyPart_BleedRate_Name".Translate(),
                             reportText:  "Stat_BodyPart_BleedRate_Desc".Translate(),
                             valueString: bodyPart.bleedRate.ToStringPercent(),
                             displayPriorityWithinCategory: 4880
                             ));

            yield return(new StatDrawEntry(
                             category:    category,
                             label:       "Stat_BodyPart_FrostbiteVulnerability_Name".Translate(),
                             reportText:  "Stat_BodyPart_FrostbiteVulnerability_Desc".Translate(),
                             valueString: bodyPart.frostbiteVulnerability.ToStringPercent(),
                             hyperlinks:  new[] { new Dialog_InfoCard.Hyperlink(DefDatabase <HediffDef> .GetNamed("Frostbite")) },
                             displayPriorityWithinCategory: 4870
                             ));

            yield return(new StatDrawEntry(
                             category:    category,
                             label:       "Stat_BodyPart_Vital_Name".Translate(),
                             reportText:  "Stat_BodyPart_Vital_Desc".Translate(),
                             valueString: bodyPart.tags.Any(bptd => bptd.vital).ToStringYesNo(),
                             displayPriorityWithinCategory: 4795
                             ));

            yield return(new StatDrawEntry(
                             category:    category,
                             label:       "Stat_BodyPart_Alive_Name".Translate(),
                             reportText:  "Stat_BodyPart_Alive_Desc".Translate(),
                             valueString: bodyPart.alive.ToStringYesNo(),
                             displayPriorityWithinCategory: 4790
                             ));

            yield return(new StatDrawEntry(
                             category:    category,
                             label:       "Stat_BodyPart_SkinCovered_Name".Translate(),
                             reportText:  "Stat_BodyPart_SkinCovered_Desc".Translate(),
                             valueString: bodyPart.IsSkinCoveredInDefinition_Debug.ToStringYesNo(), // they really don't want you to use this property...
                             displayPriorityWithinCategory: 4780
                             ));

            yield return(new StatDrawEntry(
                             category:    category,
                             label:       "Stat_BodyPart_Solid_Name".Translate(),
                             reportText:  "Stat_BodyPart_Solid_Desc".Translate(),
                             valueString: bodyPart.IsSolidInDefinition_Debug.ToStringYesNo(), // they really don't want you to use this property...
                             displayPriorityWithinCategory: 4770
                             ));

            yield return(new StatDrawEntry(
                             category:    category,
                             label:       "Stat_BodyPart_Invulnerable_Name".Translate(),
                             reportText:  "Stat_BodyPart_Invulnerable_Desc".Translate(),
                             valueString: (!bodyPart.destroyableByDamage).ToStringYesNo(),
                             displayPriorityWithinCategory: 4765
                             ));

            yield return(new StatDrawEntry(
                             category:    category,
                             label:       "Stat_BodyPart_Delicate_Name".Translate(),
                             reportText:  "Stat_BodyPart_Delicate_Desc".Translate(),
                             valueString: bodyPart.delicate.ToStringYesNo(),
                             displayPriorityWithinCategory: 4760
                             ));

            yield return(new StatDrawEntry(
                             category:    category,
                             label:       "Stat_BodyPart_BeautyRelated_Name".Translate(),
                             reportText:  "Stat_BodyPart_BeautyRelated_Desc".Translate(),
                             valueString: bodyPart.delicate.ToStringYesNo(),
                             displayPriorityWithinCategory: 4750
                             ));

            yield return(new StatDrawEntry(
                             category:    category,
                             label:       "Stat_BodyPart_Amputatable_Name".Translate(),
                             reportText:  "Stat_BodyPart_Amputatable_Desc".Translate(),
                             valueString: bodyPart.canSuggestAmputation.ToStringYesNo(),
                             displayPriorityWithinCategory: 4690
                             ));

            string bodyPartProperties = string.Join("\n",
                                                    bodyPart.tags.Select(bptd => {
                string tagLangKey = "Stat_BodyPart_BodyPartProperties_" + bptd.defName;
                string backupText = GenText.SplitCamelCase(bptd.defName);

                // See big comment on SurgeryCategoryStat
                return(tagLangKey.CanTranslate() ? tagLangKey.Translate() : backupText.Translate());
            })
                                                    );

            if (!bodyPartProperties.NullOrEmpty())
            {
                yield return(new StatDrawEntry(
                                 category:    category,
                                 label:       "Stat_BodyPart_BodyPartProperties_Name".Translate(),
                                 reportText:  "Stat_BodyPart_BodyPartProperties_Desc".Translate(),
                                 valueString: bodyPartProperties,
                                 displayPriorityWithinCategory: 4500
                                 ));
            }

            List <Dialog_InfoCard.Hyperlink> bodyPartUsersHyperlinks =
                DefDatabase <PawnKindDef> .AllDefs.
                Where(pkd => pkd.race?.race != null).
                Select(pkd => pkd.race).Distinct().
                Where(race => race.race.body.AllParts.Any(bpr => bpr.def == bodyPart)).
                Select(race => new Dialog_InfoCard.Hyperlink(race)).
                ToList()
            ;

            yield return(new StatDrawEntry(
                             category:    category,
                             label:       "Stat_BodyPart_BodyPartUsers_Name".Translate(),
                             reportText:  "Stat_BodyPart_BodyPartUsers_Desc".Translate(),
                             valueString: "VariousLabel".Translate(),
                             hyperlinks:  bodyPartUsersHyperlinks,
                             displayPriorityWithinCategory: 4200
                             ));
        }
Esempio n. 12
0
        // TODO: Document ThoughtDefs
        public static StatDrawEntry FindHediffRisks(HediffDef hediff, string labelKey, StatCategoryDef category, int displayOffset = 0)
        {
            var riskKeys    = new List <string> {
            };
            var riskReports = new List <string> {
            };

            riskReports.Add(("Stat_Thing_Drug_" + labelKey + "_Desc").Translate());

            var hyperlinks = new List <Dialog_InfoCard.Hyperlink> {
                new Dialog_InfoCard.Hyperlink(hediff)
            };

            if (!hediff.everCurableByItem)
            {
                string incurable = "Incurable".Translate();
                riskKeys.Add(incurable);
                riskReports.Add(incurable);
            }

            if (hediff.stages != null)
            {
                foreach (HediffStage stage in hediff.stages)
                {
                    if (hediff.stages.Count > 1 && (stage.label.NullOrEmpty() || !stage.becomeVisible))
                    {
                        continue;
                    }

                    string label = stage.label.NullOrEmpty() ? hediff.label : stage.label;
                    label = label.CapitalizeFirst();

                    string report = "";  // keep it empty to check later
                    List <StatDrawEntry> statDrawEntries = stage.SpecialDisplayStats().ToList();
                    foreach (StatDrawEntry statDrawEntry in statDrawEntries.OrderBy(sde => sde.DisplayPriorityWithinCategory))
                    {
                        report += "    " + statDrawEntry.LabelCap + ": " + statDrawEntry.ValueString + "\n";
                    }

                    // Other stats not reported from stage.SpecialDisplayStats()
                    if (stage.vomitMtbDays > 0)
                    {
                        report += "    " + "Stat_MTBVomit".Translate() + ": " + ToStringDaysToPeriod(stage.vomitMtbDays) + "\n";
                    }
                    if (stage.forgetMemoryThoughtMtbDays > 0)
                    {
                        report += "    " + "Stat_MTBForget".Translate() + ": " + ToStringDaysToPeriod(stage.forgetMemoryThoughtMtbDays) + "\n";
                    }
                    if (stage.mentalBreakMtbDays > 0)
                    {
                        report += "    " + "Stat_MTBMentalBreak".Translate() + ": " + ToStringDaysToPeriod(stage.mentalBreakMtbDays) + "\n";
                    }
                    if (stage.deathMtbDays > 0)
                    {
                        report += "    " + "Stat_MTBDeath".Translate() + ": " + ToStringDaysToPeriod(stage.deathMtbDays) + "\n";
                    }

                    if (!stage.hediffGivers.NullOrEmpty())
                    {
                        foreach (HediffGiver hediffGiver in stage.hediffGivers)
                        {
                            report += "    " + ReadHediffGiver(hediffGiver) + "\n";
                        }
                    }

                    if (report.NullOrEmpty())
                    {
                        continue;
                    }

                    report = label + ":\n" + report.Trim('\n');
                    riskKeys.Add(label);
                    riskReports.Add(report);
                }
            }

            // Report on thoughts tied to the hediff
            string thoughtsReport = "";  // keep it empty to check later

            foreach (ThoughtDef thought in DefDatabase <ThoughtDef> .AllDefs.Where(td => td.hediff == hediff))
            {
                foreach (ThoughtStage stage in thought.stages)
                {
                    if (thought.stages.Count > 1 && (stage.label.NullOrEmpty() || !stage.visible))
                    {
                        continue;
                    }

                    string label = stage.label.NullOrEmpty() ? (string)thought.LabelCap : stage.LabelCap;

                    var effects = new List <string> {
                    };
                    if (stage.baseMoodEffect != 0)
                    {
                        effects.Add("Stat_Thought_MoodEffect".Translate(((int)stage.baseMoodEffect).ToStringWithSign()));
                    }
                    if (stage.baseOpinionOffset != 0)
                    {
                        effects.Add("Stat_Thought_OpinionOffset".Translate(((int)stage.baseOpinionOffset).ToStringWithSign()));
                    }

                    thoughtsReport += "    " + label + ": " + GenText.ToCommaList(effects) + "\n";
                }
            }

            if (!thoughtsReport.NullOrEmpty())
            {
                riskKeys.Add("Thoughts".Translate());
                thoughtsReport = "Thoughts".Translate() + ":\n" + thoughtsReport.Trim('\n');
                riskReports.Add(thoughtsReport);
            }

            if (!hediff.hediffGivers.NullOrEmpty())
            {
                string report = "";
                foreach (HediffGiver hediffGiver in hediff.hediffGivers)
                {
                    report += ReadHediffGiver(hediffGiver) + "\n";
                    riskKeys.Add(hediffGiver.hediff.LabelCap);
                }
                riskReports.Add(report.Trim('\n'));
            }

            if (hediff.lethalSeverity >= 0)
            {
                riskKeys.Add("Fatal".Translate());
                riskReports.Add("Stat_FatalAt".Translate(hediff.lethalSeverity.ToStringPercent()));
            }

            return(new StatDrawEntry(
                       category:    category,
                       label:       ("Stat_Thing_Drug_" + labelKey + "_Name").Translate(),
                       reportText:  string.Join("\n\n", riskReports),
                       valueString: riskKeys.Count == 0 ? (string)"None".Translate() : GenText.ToCommaList(riskKeys),
                       hyperlinks:  hyperlinks,
                       displayPriorityWithinCategory: displayOffset + 50
                       ));
        }
        public static void ProductionInfo(ref IEnumerable <StatDrawEntry> __result, RaceProperties __instance, ThingDef parentDef, StatRequest req)
        {
            if (!Settings.extra_display_stats)
            {
                return;
            }

            // Create a modifyable list
            List <StatDrawEntry> NewList = new List <StatDrawEntry>();

            // copy vanilla entries into the new list
            // since original method returns enumerator instead of collection, to actually get values iterator should be iterated; also this method should not be used for enumerators that change condition when called - it may be bad a idea for work givers / drivers
            foreach (StatDrawEntry entry in __result)
            {
                NewList.Add(entry);
            }

            int             startOrder   = 2150;
            StatCategoryDef StatCategory = StatCategoryDefOf.PawnMisc;

            Pawn pawn = null;

            if (req.HasThing && req.Thing is Pawn)
            {
                pawn = (req.Thing as Pawn);
            }

            if (pawn == null)
            {
                return;
            }

            foreach (ThingComp comp in pawn.AllComps)
            {
                CompProperties c = comp.props;
                if (c is CompProperties_Shearable shearable)
                {
                    NewList.Add(new StatDrawEntry(StatCategory, "WoolType".Translate(), shearable.woolDef.LabelCap, "Stat_Race_WoolType_Desc".Translate(), startOrder--, null, new Dialog_InfoCard.Hyperlink[1]
                    {
                        new Dialog_InfoCard.Hyperlink(shearable.woolDef)
                    }));
                    TaggedString woolStat = shearable.woolAmount + " / " + string.Format("{0:0.#}", shearable.shearIntervalDays) + "LetterDay".Translate();
                    if (shearable.shearIntervalDays != 1)
                    {
                        woolStat += " (" + string.Format("{0:0.#}", shearable.woolAmount / shearable.shearIntervalDays) + "/" + "LetterDay".Translate() + ")";
                    }
                    NewList.Add(new StatDrawEntry(StatCategory, "WoolAmount".Translate(), woolStat, "Stat_Race_WoolAmount_Desc".Translate(), startOrder--));
                }
                else if (c is CompProperties_Milkable milkable)
                {
                    NewList.Add(new StatDrawEntry(StatCategory, "MilkType".Translate(), milkable.milkDef.LabelCap, "Stat_Race_MilkType_Desc".Translate(), startOrder--, null, new Dialog_InfoCard.Hyperlink[1]
                    {
                        new Dialog_InfoCard.Hyperlink(milkable.milkDef)
                    }));
                    String milkStat = milkable.milkAmount + " / " + string.Format("{0:0.#}", milkable.milkIntervalDays) + "LetterDay".Translate();
                    if (milkable.milkIntervalDays != 1)
                    {
                        milkStat += " (" + string.Format("{0:0.#}", milkable.milkAmount / milkable.milkIntervalDays) + "/" + "LetterDay".Translate() + ")";
                    }
                    NewList.Add(new StatDrawEntry(StatCategory, "MilkAmount".Translate(), milkStat, "Stat_Race_MilkAmount_Desc".Translate(), startOrder--));
                    NewList.Add(new StatDrawEntry(StatCategory, "MilkFemale".Translate(), milkable.milkFemaleOnly ? "Yes".Translate() : "No".Translate(), "MilkFemaleExplanation".Translate(), startOrder--));
                }
                // catch all for custom comps based on CompHasGatherableBodyResource abstract
                else if (comp is CompHasGatherableBodyResource resource)
                {
                    ThingDef ResourceDef = (ThingDef)AccessTools.Method(comp.GetType(), "get_ResourceDef").Invoke(resource, null);
                    Log.Warning("AL: resource " + ResourceDef);
                    if (ResourceDef == null)
                    {
                        Log.Warning("Animals Logic: " + parentDef.defName + " has a custom comp for body resources but no resource def.");
                        continue;
                    }
                    NewList.Add(new StatDrawEntry(StatCategory, "AL_ResourceType".Translate(), ResourceDef.LabelCap, "AL_ResourceType_Desc".Translate(), startOrder--, null, new Dialog_InfoCard.Hyperlink[1]
                    {
                        new Dialog_InfoCard.Hyperlink(ResourceDef)
                    }));

                    int ResourceAmount = (int)AccessTools.Method(comp.GetType(), "get_ResourceAmount").Invoke(resource, null);
                    int GatherResourcesIntervalDays = (int)AccessTools.Method(comp.GetType(), "get_GatherResourcesIntervalDays").Invoke(resource, null);

                    String resourceStat = ResourceAmount + " / " + string.Format("{0:0.#}", GatherResourcesIntervalDays) + "LetterDay".Translate();
                    if (GatherResourcesIntervalDays != 1)
                    {
                        resourceStat += " (" + string.Format("{0:0.#}", ResourceAmount / GatherResourcesIntervalDays) + "/" + "LetterDay".Translate() + ")";
                    }
                    NewList.Add(new StatDrawEntry(StatCategory, "AL_ResourceAmount".Translate(), resourceStat, "AL_ResourceAmount_Desc".Translate(), startOrder--));
                }

                if (c is CompProperties_EggLayer layer)
                {
                    List <Dialog_InfoCard.Hyperlink> hyperlinks = new List <Dialog_InfoCard.Hyperlink>
                    {
                        new Dialog_InfoCard.Hyperlink(layer.eggFertilizedDef)
                    };
                    if (layer.eggUnfertilizedDef != null && layer.eggUnfertilizedDef != layer.eggFertilizedDef)
                    {
                        hyperlinks.Add(new Dialog_InfoCard.Hyperlink(layer.eggUnfertilizedDef));
                    }

                    NewList.Add(new StatDrawEntry(StatCategory, "EggType".Translate(), layer.eggFertilizedDef.LabelCap, "Stat_Race_EggType_Desc".Translate(), startOrder--, null, hyperlinks));
                    TaggedString eggsStat = (layer.eggCountRange.min == layer.eggCountRange.max ? layer.eggCountRange.max.ToString() : layer.eggCountRange.ToString())
                                            + " / " + string.Format("{0:0.#}", layer.eggLayIntervalDays) + "LetterDay".Translate();
                    if (layer.eggLayIntervalDays != 1 || layer.eggCountRange.min != layer.eggCountRange.max)
                    {
                        eggsStat += " (" + string.Format("{0:0.#}", layer.eggCountRange.Average / layer.eggLayIntervalDays) + "/" + "LetterDay".Translate() + ")";
                    }
                    NewList.Add(new StatDrawEntry(StatCategory, "EggAmount".Translate(), eggsStat, "Stat_Race_EggAmount_Desc".Translate(), startOrder--));
                    NewList.Add(new StatDrawEntry(StatCategory, "EggFemale".Translate(), layer.eggLayFemaleOnly ? "Yes".Translate() : "No".Translate(), "EggFemaleExplanation".Translate(), startOrder--));
                    NewList.Add(new StatDrawEntry(StatCategory, "EggNeedFertilization".Translate(), layer.eggProgressUnfertilizedMax < 1 ? "Yes".Translate() : "No".Translate(), "EggNeedFertilizationExplanation".Translate(), startOrder--));

                    CompProperties_Hatcher hatcher = layer.eggFertilizedDef.GetCompProperties <CompProperties_Hatcher>();
                    if (hatcher != null)
                    {
                        NewList.Add(new StatDrawEntry(StatCategory, "EggIncubation".Translate(), hatcher.hatcherDaystoHatch + "LetterDay".Translate(), "EggIncubationExplanation".Translate(), startOrder--));
                    }
                }
            }

            // TODO: break it down into explanation of each stage
            if (!__instance.lifeStageAges.NullOrEmpty())
            {
                LifeStageAge matureAge = __instance.lifeStageAges.FirstOrFallback(
                    p => p.def.reproductive || p.def.milkable || p.def.shearable,
                    __instance.lifeStageAges.Last()
                    );

                if (matureAge != null)
                {
                    float age   = matureAge.minAge; // contains number of years as float
                    int   years = (int)age;
                    age %= 1.0f;                    // now contains number of years that is less than 1
                    int days = (int)(age * 60);
                    age = (age * 60) % 1.0f;        // now contains number of days that is less than 1
                    int hours = (int)age * 24;

                    String matureAgeString      = ""; // unused now
                    String matureAgeStringShort = "";

                    if (years > 1)
                    {
                        matureAgeString      += "PeriodYears".Translate(years);
                        matureAgeStringShort += years + "LetterYear".Translate();
                    }
                    if (years == 1)
                    {
                        matureAgeString      += "Period1Year".Translate();
                        matureAgeStringShort += 1 + "LetterYear".Translate();
                    }

                    if (days > 1)
                    {
                        if (years > 0)
                        {
                            matureAgeString      += " ";
                            matureAgeStringShort += " ";
                        }
                        matureAgeString      += "PeriodDays".Translate(days);
                        matureAgeStringShort += days + "LetterDay".Translate();
                    }
                    if (days == 1)
                    {
                        if (years > 0)
                        {
                            matureAgeString      += " ";
                            matureAgeStringShort += " ";
                        }
                        matureAgeString      += "Period1Day".Translate();
                        matureAgeStringShort += 1 + "LetterDay".Translate();
                    }

                    if (hours > 1)
                    {
                        if (years + hours > 0)
                        {
                            matureAgeString      += " ";
                            matureAgeStringShort += " ";
                        }
                        matureAgeString      += "PeriodHours".Translate(hours);
                        matureAgeStringShort += hours + "LetterHour".Translate();
                    }
                    if (hours == 1)
                    {
                        if (years + hours > 0)
                        {
                            matureAgeString      += " ";
                            matureAgeStringShort += " ";
                        }
                        matureAgeString      += "Period1Hour".Translate();
                        matureAgeStringShort += 1 + "LetterHour".Translate();
                    }

                    NewList.Add(new StatDrawEntry(StatCategory, "TimeToMature".Translate(), matureAgeStringShort, "TimeToMatureExplanation".Translate(), startOrder--));
                }

                LifeStageAge reproductiveAge = __instance.lifeStageAges.Find(
                    p => p.def.reproductive
                    );

                if (__instance.hasGenders && reproductiveAge != null && !parentDef.HasComp(typeof(CompEggLayer)))
                {
                    NewList.Add(new StatDrawEntry(StatCategory, "GestationPeriod".Translate(), String.Format("{0:0.#}", __instance.gestationPeriodDays) + "LetterDay".Translate(), "GestationPeriodExplanation".Translate(), startOrder--));

                    float  litterAvg  = 1f;
                    String litterSize = "1";

                    if (__instance.litterSizeCurve != null && Math.Max(1, __instance.litterSizeCurve.First().x) != Math.Max(1, __instance.litterSizeCurve.Last().x))
                    {
                        litterAvg  = Rand.ByCurveAverage(__instance.litterSizeCurve);
                        litterAvg  = Math.Max(1, litterAvg);
                        litterSize = Math.Max(1, __instance.litterSizeCurve.First().x) + "~" + Math.Max(1, __instance.litterSizeCurve.Last().x) + " (" + String.Format("{0:0.#}", litterAvg) + ")";
                    }
                    NewList.Add(new StatDrawEntry(StatCategory, "LitterSize".Translate(), litterSize, "LitterSizeExplanation".Translate(), startOrder--));
                }
            }

            // convert list to IEnumerable to match the caller's expectations
            IEnumerable <StatDrawEntry> output = NewList;

            // make caller use the list
            __result = output;
        }
Esempio n. 14
0
        public override IEnumerable <StatDrawEntry> SpecialDisplayStats()
        {
            if (this.apparel != null)
            {
                string coveredParts = this.apparel.GetCoveredOuterPartsString(BodyDefOf.Human);
                yield return(new StatDrawEntry(StatCategoryDefOf.Apparel, "Covers".Translate(), coveredParts, 100, string.Empty));
            }
            if (this.IsMedicine && this.MedicineTendXpGainFactor != 1f)
            {
                yield return(new StatDrawEntry(StatCategoryDefOf.Basics, "MedicineXpGainFactor".Translate(), this.MedicineTendXpGainFactor.ToStringPercent(), 0, string.Empty));
            }
            if (this.fillPercent > 0f && this.fillPercent < 1f && (this.category == ThingCategory.Item || this.category == ThingCategory.Building || this.category == ThingCategory.Plant))
            {
                yield return(new StatDrawEntry(StatCategoryDefOf.Basics, "CoverEffectiveness".Translate(), this.BaseBlockChance().ToStringPercent(), 0, string.Empty)
                {
                    overrideReportText = "CoverEffectivenessExplanation".Translate()
                });
            }
            if (this.constructionSkillPrerequisite > 0)
            {
                StatCategoryDef basics             = StatCategoryDefOf.Basics;
                string          label              = "ConstructionSkillRequired".Translate();
                string          valueString        = this.constructionSkillPrerequisite.ToString();
                string          overrideReportText = "ConstructionSkillRequiredExplanation".Translate();
                yield return(new StatDrawEntry(basics, label, valueString, 0, overrideReportText));
            }
            if (!this.verbs.NullOrEmpty <VerbProperties>())
            {
                VerbProperties verb = (from x in this.verbs
                                       where x.isPrimary
                                       select x).First <VerbProperties>();
                StatCategoryDef verbStatCategory = (this.category != ThingCategory.Pawn) ? (verbStatCategory = StatCategoryDefOf.Weapon) : (verbStatCategory = StatCategoryDefOf.PawnCombat);
                float           warmup           = verb.warmupTime;
                if (warmup > 0f)
                {
                    string warmupLabel = (this.category != ThingCategory.Pawn) ? "WarmupTime".Translate() : "MeleeWarmupTime".Translate();
                    yield return(new StatDrawEntry(verbStatCategory, warmupLabel, warmup.ToString("0.##") + " s", 40, string.Empty));
                }
                if (verb.defaultProjectile != null)
                {
                    float dam = (float)verb.defaultProjectile.projectile.damageAmountBase;
                    yield return(new StatDrawEntry(verbStatCategory, "Damage".Translate(), dam.ToString(), 50, string.Empty));
                }
                if (verb.LaunchesProjectile)
                {
                    int   burstShotCount    = verb.burstShotCount;
                    float burstShotFireRate = 60f / verb.ticksBetweenBurstShots.TicksToSeconds();
                    float range             = verb.range;
                    if (burstShotCount > 1)
                    {
                        yield return(new StatDrawEntry(verbStatCategory, "BurstShotCount".Translate(), burstShotCount.ToString(), 20, string.Empty));

                        yield return(new StatDrawEntry(verbStatCategory, "BurstShotFireRate".Translate(), burstShotFireRate.ToString("0.##") + " rpm", 19, string.Empty));
                    }
                    yield return(new StatDrawEntry(verbStatCategory, "Range".Translate(), range.ToString("0.##"), 10, string.Empty));
                }
            }
            if (this.plant != null)
            {
                foreach (StatDrawEntry s in this.plant.SpecialDisplayStats())
                {
                    yield return(s);
                }
            }
            if (this.ingestible != null)
            {
                foreach (StatDrawEntry s2 in this.ingestible.SpecialDisplayStats(this))
                {
                    yield return(s2);
                }
            }
            if (this.race != null)
            {
                foreach (StatDrawEntry s3 in this.race.SpecialDisplayStats(this))
                {
                    yield return(s3);
                }
            }
            if (this.isBodyPartOrImplant)
            {
                foreach (RecipeDef def in from x in DefDatabase <RecipeDef> .AllDefs
                         where x.IsIngredient(this.$this)
                         select x)
                {
                    HediffDef diff = def.addsHediff;
                    if (diff != null)
                    {
                        if (diff.addedPartProps != null)
                        {
                            yield return(new StatDrawEntry(StatCategoryDefOf.Basics, "BodyPartEfficiency".Translate(), diff.addedPartProps.partEfficiency.ToStringByStyle(ToStringStyle.PercentZero, ToStringNumberSense.Absolute), 0, string.Empty));
                        }
                        foreach (StatDrawEntry s4 in diff.SpecialDisplayStats())
                        {
                            yield return(s4);
                        }
                        HediffCompProperties_VerbGiver vg = diff.CompProps <HediffCompProperties_VerbGiver>();
                        if (vg != null)
                        {
                            if (!vg.verbs.NullOrEmpty <VerbProperties>())
                            {
                                VerbProperties verb2 = vg.verbs[0];
                                if (!verb2.MeleeRange)
                                {
                                    if (verb2.defaultProjectile != null)
                                    {
                                        int projDamage = verb2.defaultProjectile.projectile.damageAmountBase;
                                        yield return(new StatDrawEntry(StatCategoryDefOf.Basics, "Damage".Translate(), projDamage.ToString(), 0, string.Empty));
                                    }
                                }
                                else
                                {
                                    int meleeDamage = verb2.meleeDamageBaseAmount;
                                    yield return(new StatDrawEntry(StatCategoryDefOf.Weapon, "Damage".Translate(), meleeDamage.ToString(), 0, string.Empty));
                                }
                            }
                            else if (!vg.tools.NullOrEmpty <Tool>())
                            {
                                Tool tool = vg.tools[0];
                                yield return(new StatDrawEntry(StatCategoryDefOf.Weapon, "Damage".Translate(), tool.power.ToString(), 0, string.Empty));
                            }
                        }
                        ThoughtDef thought = DefDatabase <ThoughtDef> .AllDefs.FirstOrDefault((ThoughtDef x) => x.hediff == diff);

                        if (thought != null && thought.stages != null && thought.stages.Any <ThoughtStage>())
                        {
                            yield return(new StatDrawEntry(StatCategoryDefOf.Basics, "MoodChange".Translate(), thought.stages.First <ThoughtStage>().baseMoodEffect.ToStringByStyle(ToStringStyle.Integer, ToStringNumberSense.Offset), 0, string.Empty));
                        }
                    }
                }
            }
            for (int i = 0; i < this.comps.Count; i++)
            {
                foreach (StatDrawEntry s5 in this.comps[i].SpecialDisplayStats())
                {
                    yield return(s5);
                }
            }
        }
        public static IEnumerable <StatDrawEntry> SpecialDisplayStats(RecipeDef surgery, StatRequest req)
        {
            category = DefDatabase <StatCategoryDef> .GetNamed("Surgery");

            yield return(SurgeryCategoryStat(surgery));

            StatDrawEntry workerModStat = WorkerModStat(surgery);

            if (workerModStat != null)
            {
                yield return(workerModStat);
            }

            yield return(new StatDrawEntry(
                             category:    category,
                             label:       "Stat_Recipe_Surgery_Anesthetize_Name".Translate(),
                             reportText:  "Stat_Recipe_Surgery_Anesthetize_Desc".Translate(),
                             valueString: surgery.anesthetize.ToStringYesNo(),
                             hyperlinks:  new[] { new Dialog_InfoCard.Hyperlink(HediffDefOf.Anesthetic) },
                             displayPriorityWithinCategory: 4950
                             ));

            if (!surgery.hideBodyPartNames)
            {
                yield return(AffectedBodyPartsStat(surgery));
            }
            if (!surgery.incompatibleWithHediffTags.NullOrEmpty())
            {
                yield return(IncompatibleWithHediffTagsStat(surgery));
            }

            if (surgery.addsHediff != null)
            {
                yield return(new StatDrawEntry(
                                 category:    category,
                                 label:       "Stat_Recipe_Surgery_AddsHediff_Name".Translate(),
                                 reportText:  "Stat_Recipe_Surgery_AddsHediff_Desc".Translate(),
                                 valueString: surgery.addsHediff.LabelCap,
                                 hyperlinks:  new[] { new Dialog_InfoCard.Hyperlink(surgery.addsHediff) },
                                 displayPriorityWithinCategory: 4859
                                 ));
            }
            if (surgery.removesHediff != null)
            {
                yield return(new StatDrawEntry(
                                 category:    category,
                                 label:       "Stat_Recipe_Surgery_RemovesHediff_Name".Translate(),
                                 reportText:  "Stat_Recipe_Surgery_RemovesHediff_Desc".Translate(),
                                 valueString: surgery.removesHediff.LabelCap,
                                 hyperlinks:  new[] { new Dialog_InfoCard.Hyperlink(surgery.removesHediff) },
                                 displayPriorityWithinCategory: 4858
                                 ));
            }
            if (surgery.changesHediffLevel != null)
            {
                yield return(new StatDrawEntry(
                                 category:    category,
                                 label:       "Stat_Recipe_Surgery_ChangesHediffLevel_Name".Translate(),
                                 reportText:  "Stat_Recipe_Surgery_ChangesHediffLevel_Desc".Translate(),
                                 valueString: surgery.changesHediffLevel.LabelCap,
                                 hyperlinks:  new[] { new Dialog_InfoCard.Hyperlink(surgery.changesHediffLevel) },
                                 displayPriorityWithinCategory: 4857
                                 ));
            }
        }