From 316e43f85d6d1c864abda52968e7d303ea5581a2 Mon Sep 17 00:00:00 2001 From: Killface1980 Date: Sat, 18 Nov 2017 12:21:18 +0100 Subject: [PATCH] fixes + changes --- Assemblies/Outfitter.dll | Bin 74240 -> 75776 bytes Source/Outfitter/ApparelEntry.cs | 14 +- Source/Outfitter/ApparelStatCache.cs | 120 +++-- Source/Outfitter/ApparelStatsHelper.cs | 476 ++++++++---------- Source/Outfitter/Cache.cs | 26 +- Source/Outfitter/Extensions.cs | 11 +- Source/Outfitter/GameComponent_Outfitter.cs | 7 +- Source/Outfitter/HarmonyPatches.cs | 53 +- .../Outfitter/Helper/HelperThingFilterUI.cs | 117 ----- Source/Outfitter/ITab_Bills_Patch.cs | 108 ++-- .../InfusedStats/HarmonyPatchInfused.cs | 75 --- Source/Outfitter/InfusedStats/InfusedStats.cs | 83 --- .../JobGiver_OutfitterOptimizeApparel.cs | 44 +- .../Outfitter/Optional/Harmony_DDWorkTab.cs | 47 +- Source/Outfitter/Outfitter.csproj | 5 +- Source/Outfitter/Saveables/Saveable_Pawn.cs | 37 +- Source/Outfitter/StatDefOf2.cs | 1 - Source/Outfitter/StatPriority.cs | 2 - .../Window/Dialog_PawnApparelComparer.cs | 43 +- .../Outfitter/Window/ITab_Pawn_Outfitter.cs | 24 +- .../Window/Window_Pawn_ApparelDetail.cs | 38 +- Source/Outfitter_Infused/OutfitterInfused.cs | 11 +- 22 files changed, 550 insertions(+), 792 deletions(-) delete mode 100644 Source/Outfitter/Helper/HelperThingFilterUI.cs delete mode 100644 Source/Outfitter/InfusedStats/HarmonyPatchInfused.cs delete mode 100644 Source/Outfitter/InfusedStats/InfusedStats.cs diff --git a/Assemblies/Outfitter.dll b/Assemblies/Outfitter.dll index f521518449bd15eac775b9d3f1b65ebf7fb9e40e..374108cb8f4b00ecae23daf33755cc9a96841cb5 100644 GIT binary patch literal 75776 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 diff --git a/Source/Outfitter/ApparelEntry.cs b/Source/Outfitter/ApparelEntry.cs index 87413b1..e90c77b 100644 --- a/Source/Outfitter/ApparelEntry.cs +++ b/Source/Outfitter/ApparelEntry.cs @@ -8,7 +8,11 @@ namespace Outfitter public class ApparelEntry { - #region Public Fields + public HashSet equippedOffsets; + + public HashSet infusedOffsets; + + public HashSet statBases; public ApparelEntry() { @@ -16,13 +20,5 @@ public ApparelEntry() this.infusedOffsets = new HashSet(); this.statBases = new HashSet(); } - - public HashSet equippedOffsets; - - public HashSet infusedOffsets; - - public HashSet statBases; - - #endregion Public Fields } } \ No newline at end of file diff --git a/Source/Outfitter/ApparelStatCache.cs b/Source/Outfitter/ApparelStatCache.cs index 0bc1c04..5d4a0b5 100644 --- a/Source/Outfitter/ApparelStatCache.cs +++ b/Source/Outfitter/ApparelStatCache.cs @@ -20,13 +20,14 @@ namespace Outfitter using Verse; - public partial class ApparelStatCache + public class ApparelStatCache { - // public List recentApparel = new List(); + public const float MaxValue = 2.5f; + // public List recentApparel = new List(); public readonly List Cache; - public const float MaxValue = 2.5f; + public Dictionary ToDropList = new Dictionary(); private readonly Pawn pawn; @@ -75,8 +76,8 @@ public List StatCache get { // update auto stat priorities roughly between every vanilla gear check cycle - if (Find.TickManager.TicksGame - this.lastStatUpdate > JobGiver_OutfitterOptimizeApparel.ApparelStatCheck - || this.pawnSave.forceStatUpdate) + if (Find.TickManager.TicksGame - this.lastStatUpdate + > JobGiver_OutfitterOptimizeApparel.ApparelStatCheck || this.pawnSave.forceStatUpdate) { // list of auto stats if (this.Cache.Count < 1 && this.pawnSave.Stats.Count > 0) @@ -94,6 +95,7 @@ public List StatCache this.Cache.RemoveAll(stat => stat.Assignment == StatAssignment.Individual); // loop over each (new) stat + // Armor only used by the Battle beacon, no relevance to jobs etc. if (this.pawnSave.armorOnly) { Dictionary updateArmorStats = this.pawn.GetWeightedApparelArmorStats(); @@ -121,6 +123,12 @@ public List StatCache Dictionary updateIndividualPriorities = this.pawn.GetWeightedApparelIndividualStats(); + // updateAutoPriorities = updateAutoPriorities.OrderBy(x => x.Key.label).ToDictionary(x => x.Key, x => x.Value); + updateAutoPriorities = updateAutoPriorities.OrderByDescending(x => Mathf.Abs(x.Value)) + .ToDictionary(x => x.Key, x => x.Value); + updateIndividualPriorities = updateIndividualPriorities.OrderBy(x => x.Key.label) + .ToDictionary(x => x.Key, x => x.Value); + foreach (KeyValuePair pair in updateIndividualPriorities) { // find index of existing priority for this stat @@ -182,11 +190,11 @@ public List StatCache Saveable_Pawn_StatDef stats = new Saveable_Pawn_StatDef - { - Stat = statPriority.Stat, - Assignment = statPriority.Assignment, - Weight = statPriority.Weight - }; + { + Stat = statPriority.Stat, + Assignment = statPriority.Assignment, + Weight = statPriority.Weight + }; this.pawnSave.Stats.Add(stats); } } @@ -219,8 +227,6 @@ private FloatRange TemperatureWeight } } - public Dictionary ToDropList = new Dictionary(); - public static float ApparelScoreRaw_ProtectionBaseStat(Apparel ap) { float num = 1f; @@ -229,7 +235,10 @@ public static float ApparelScoreRaw_ProtectionBaseStat(Apparel ap) return num + num2 * 1.25f; } - public static void DoApparelScoreRaw_PawnStatsHandlers([NotNull] Apparel apparel, [NotNull] StatDef statDef, out float num) + public static void DoApparelScoreRaw_PawnStatsHandlers( + [NotNull] Apparel apparel, + [NotNull] StatDef statDef, + out float num) { num = 0f; ApparelScoreRaw_PawnStatsHandlers?.Invoke(apparel, statDef, out num); @@ -411,7 +420,6 @@ public float ApparelScoreRaw([NotNull] Apparel ap, [NotNull] Pawn pawn) if (infusedOffsets.Contains(statPriority.Stat)) { // float statInfused = StatInfused(infusionSet, statPriority, ref dontcare); - DoApparelScoreRaw_PawnStatsHandlers(ap, statPriority.Stat, out float statInfused); score += statInfused * statPriority.Weight; @@ -470,7 +478,6 @@ public float ApparelScoreRaw_Temperature([NotNull] Apparel apparel) // temperature FloatRange targetTemperatures = this.TargetTemperatures; - // offsets on apparel float insulationCold = apparel.GetStatValue(StatDefOf.Insulation_Cold); float insulationHeat = apparel.GetStatValue(StatDefOf.Insulation_Heat); @@ -479,15 +486,21 @@ public float ApparelScoreRaw_Temperature([NotNull] Apparel apparel) insulationHeat += apparel.def.equippedStatOffsets.GetStatOffsetFromList(StatDefOf.Insulation_Heat); { // offsets on apparel infusions - DoApparelScoreRaw_PawnStatsHandlers(apparel, StatDefOf.ComfyTemperatureMin, out float infInsulationCold); - DoApparelScoreRaw_PawnStatsHandlers(apparel, StatDefOf.ComfyTemperatureMax, out float infInsulationHeat); + DoApparelScoreRaw_PawnStatsHandlers( + apparel, + StatDefOf.ComfyTemperatureMin, + out float infInsulationCold); + DoApparelScoreRaw_PawnStatsHandlers( + apparel, + StatDefOf.ComfyTemperatureMax, + out float infInsulationHeat); insulationCold += infInsulationCold; insulationHeat += infInsulationHeat; } - // string log = apparel.LabelCap + " - InsCold: " + insulationCold + " - InsHeat: " + insulationHeat + " - TargTemp: " - // + targetTemperatures + "\nMinComfy: " + minComfyTemperature + " - MaxComfy: " - // + maxComfyTemperature; + // string log = apparel.LabelCap + " - InsCold: " + insulationCold + " - InsHeat: " + insulationHeat + " - TargTemp: " + // + targetTemperatures + "\nMinComfy: " + minComfyTemperature + " - MaxComfy: " + // + maxComfyTemperature; // if this gear is currently worn, we need to make sure the contribution to the pawn's comfy temps is removed so the gear is properly scored List wornApparel = this.pawn.apparel.WornApparel; @@ -495,7 +508,7 @@ public float ApparelScoreRaw_Temperature([NotNull] Apparel apparel) { if (wornApparel.Contains(apparel)) { - // log += "\nPawn is wearer of this apparel."; + // log += "\nPawn is wearer of this apparel."; minComfyTemperature -= insulationCold; maxComfyTemperature -= insulationHeat; } @@ -536,7 +549,7 @@ public float ApparelScoreRaw_Temperature([NotNull] Apparel apparel) } } - // log += "\nBasic stat - MinComfy: " + minComfyTemperature + " - MaxComfy: " + maxComfyTemperature; + // log += "\nBasic stat - MinComfy: " + minComfyTemperature + " - MaxComfy: " + maxComfyTemperature; // now for the interesting bit. FloatRange temperatureScoreOffset = new FloatRange(0f, 0f); @@ -548,14 +561,15 @@ public float ApparelScoreRaw_Temperature([NotNull] Apparel apparel) // isolation_warm is given as positive numbers. float neededInsulation_Warmth = targetTemperatures.max - maxComfyTemperature; - // log += "\nWeight: " + tempWeight + " - NeedInsCold: " + neededInsulation_Cold + " - NeedInsWarmth: " - // + neededInsulation_Warmth; + // log += "\nWeight: " + tempWeight + " - NeedInsCold: " + neededInsulation_Cold + " - NeedInsWarmth: " + // + neededInsulation_Warmth; // currently too cold if (neededInsulation_Cold < 0) { temperatureScoreOffset.min += -insulationCold * Math.Abs(tempWeight.min); } + // currently warm enough else { @@ -571,6 +585,7 @@ public float ApparelScoreRaw_Temperature([NotNull] Apparel apparel) { temperatureScoreOffset.max += insulationHeat * Math.Abs(tempWeight.max); } + // currently cool enough else { @@ -581,21 +596,36 @@ public float ApparelScoreRaw_Temperature([NotNull] Apparel apparel) * Math.Abs(tempWeight.max); } } + // Punish bad apparel temperatureScoreOffset.min *= temperatureScoreOffset.min < 0 ? 2f : 1f; temperatureScoreOffset.max *= temperatureScoreOffset.max < 0 ? 2f : 1f; - // log += "\nScoreOffsetMin: " + temperatureScoreOffset.min + " - ScoreOffsetMax: " - // + temperatureScoreOffset.max + " => " + 1 + (temperatureScoreOffset.min + temperatureScoreOffset.max) / 25; - // - // Log.Message(log); + // log += "\nScoreOffsetMin: " + temperatureScoreOffset.min + " - ScoreOffsetMax: " + // + temperatureScoreOffset.max + " => " + 1 + (temperatureScoreOffset.min + temperatureScoreOffset.max) / 25; + // Log.Message(log); + return 1 + (temperatureScoreOffset.min + temperatureScoreOffset.max) / 15; + } + + public ApparelEntry GetAllOffsets([NotNull] Apparel ap) + { + if (Outfitter.Cache.ApparelEntries.ContainsKey(ap)) + { + return Outfitter.Cache.ApparelEntries[ap]; + } + + ApparelEntry entry = new ApparelEntry(); + this.GetStatsOfApparel(ap, ref entry.equippedOffsets, ref entry.statBases); + this.GetStatsOfApparelInfused(ap, ref entry.infusedOffsets); - return 1 + (temperatureScoreOffset.min + temperatureScoreOffset.max) / 25; + Outfitter.Cache.ApparelEntries.Add(ap, entry); + return entry; } public void UpdateTemperatureIfNecessary(bool force = false, bool forceweight = false) { - if (Find.TickManager.TicksGame - this.lastTempUpdate > JobGiver_OutfitterOptimizeApparel.ApparelStatCheck || force) + if (Find.TickManager.TicksGame - this.lastTempUpdate > JobGiver_OutfitterOptimizeApparel.ApparelStatCheck + || force) { // get desired temperatures if (!this.pawnSave.TargetTemperaturesOverride) @@ -622,15 +652,13 @@ public void UpdateTemperatureIfNecessary(bool force = false, bool forceweight = { this.pawnSave.TargetTemperatures.min = Mathf.Min(this.pawnSave.TargetTemperatures.min, -3); } - } this.lastTempUpdate = Find.TickManager.TicksGame; } } - var RealComfyTemperatures = this.pawn.ComfortableTemperatureRange(); - + FloatRange RealComfyTemperatures = this.pawn.ComfortableTemperatureRange(); if (Find.TickManager.TicksGame - this.lastWeightUpdate > JobGiver_OutfitterOptimizeApparel.ApparelStatCheck || forceweight) @@ -639,14 +667,12 @@ public void UpdateTemperatureIfNecessary(bool force = false, bool forceweight = if (this.pawnSave.TargetTemperatures.min < RealComfyTemperatures.min) { - weight.min += Math.Abs( - (this.pawnSave.TargetTemperatures.min - RealComfyTemperatures.min) / 100); + weight.min += Math.Abs((this.pawnSave.TargetTemperatures.min - RealComfyTemperatures.min) / 100); } if (this.pawnSave.TargetTemperatures.max > RealComfyTemperatures.max) { - weight.max += Math.Abs( - (this.pawnSave.TargetTemperatures.max - RealComfyTemperatures.max) / 100); + weight.max += Math.Abs((this.pawnSave.TargetTemperatures.max - RealComfyTemperatures.max) / 100); } this.pawnSave.Temperatureweight = weight; @@ -662,22 +688,10 @@ private static void FillInfusionHashset_PawnStatsHandlers( ApparelScoreRaw_FillInfusedStat?.Invoke(apparel, parentStat, ref infusedOffsets); } - public ApparelEntry GetAllOffsets([NotNull] Apparel ap) - { - if (Outfitter.Cache.ApparelEntries.ContainsKey(ap)) - { - return Outfitter.Cache.ApparelEntries[ap]; - } - - ApparelEntry entry = new ApparelEntry(); - this.GetStatsOfApparel(ap, ref entry.equippedOffsets, ref entry.statBases); - this.GetStatsOfApparelInfused(ap, ref entry.infusedOffsets); - - Outfitter.Cache.ApparelEntries.Add(ap, entry); - return entry; - } - - private void GetStatsOfApparel([NotNull] Apparel ap, ref HashSet equippedOffsets, ref HashSet statBases) + private void GetStatsOfApparel( + [NotNull] Apparel ap, + ref HashSet equippedOffsets, + ref HashSet statBases) { if (ap.def.equippedStatOffsets != null) { diff --git a/Source/Outfitter/ApparelStatsHelper.cs b/Source/Outfitter/ApparelStatsHelper.cs index 6f6fd54..163a7fb 100644 --- a/Source/Outfitter/ApparelStatsHelper.cs +++ b/Source/Outfitter/ApparelStatsHelper.cs @@ -22,6 +22,36 @@ public static class ApparelStatsHelper { private const float ScoreFactorIfNotReplacing = 10f; + private static float NegMax(bool mainJob = false) + { + return mainJob ? -9f : -3f; + } + + private static float PosMax(bool mainJob = false) + { + return mainJob ? 9f : 3f; + } + + private static float NegMed(bool mainJob = false) + { + return mainJob ? -6f : -2f; + } + + private static float PosMed(bool mainJob = false) + { + return mainJob ? 6f : 2f; + } + + private static float PosMin(bool mainJob = false) + { + return mainJob ? 3f : 1f; + } + + private static float NegMin(bool mainJob = false) + { + return mainJob ? -3f : -1f; + } + // New curve public static readonly SimpleCurve HitPointsPercentScoreFactorCurve = new SimpleCurve { @@ -58,7 +88,6 @@ public static class ApparelStatsHelper private static List allApparelStats; - public static FloatRange MinMaxTemperatureRange => new FloatRange(-100, 100); private static List AllStatDefsModifiedByAnyApparel @@ -189,57 +218,50 @@ public static Dictionary GetWeightedApparelIndividualStats(this // dict.Add(StatDefOf.ArmorRating_Sharp, 0.25f); if (pawnSave.AddIndividualStats) { - bool activeDrone = false; - - PsychicDroneLevel psychicDroneLevel = PsychicDroneLevel.None; // ReSharper disable once InconsistentNaming - activeDrone = ExtantShipPart(pawn.Map); - - GameCondition_PsychicEmanation activeCondition = - pawn.Map.gameConditionManager.GetActiveCondition(); - if (activeCondition != null && activeCondition.gender == pawn.gender - && activeCondition.def.droneLevel > psychicDroneLevel) - { - activeDrone = true; - } - - if (activeDrone) + if (pawn.Map.gameConditionManager.ConditionIsActive(GameConditionDefOf.PsychicDrone)) { - switch (pawn.story.traits.DegreeOfTrait(TraitDef.Named("PsychicSensitivity"))) + GameCondition_PsychicEmanation activeCondition = + pawn.Map.gameConditionManager.GetActiveCondition(); + if (activeCondition.gender == pawn.gender && activeCondition.def.droneLevel > PsychicDroneLevel.None) { - case -1: - { - AddStatToDict(StatDefOf.PsychicSensitivity, -0.25f, ref dict); - break; - } + switch (pawn.story.traits.DegreeOfTrait(TraitDefOf.PsychicSensitivity)) + { + case -1: + { + AddStatToDict(StatDefOf.PsychicSensitivity, -0.25f, ref dict); + break; + } - case 0: - { - AddStatToDict(StatDefOf.PsychicSensitivity, -0.5f, ref dict); - break; - } + case 0: + { + AddStatToDict(StatDefOf.PsychicSensitivity, 0.5f, ref dict); + break; + } - case 1: - { - AddStatToDict(StatDefOf.PsychicSensitivity, -0.75f, ref dict); - break; - } + case 1: + { + AddStatToDict(StatDefOf.PsychicSensitivity, -0.75f, ref dict); + break; + } - case 2: - { - AddStatToDict(StatDefOf.PsychicSensitivity, -1f, ref dict); - break; - } + case 2: + { + AddStatToDict(StatDefOf.PsychicSensitivity, -1f, ref dict); + break; + } + } } } + if (pawn.Map.gameConditionManager.ConditionIsActive(GameConditionDefOf.PsychicSoothe)) { if (pawn.Map.gameConditionManager.GetActiveCondition().gender == pawn.gender) { - switch (pawn.story.traits.DegreeOfTrait(TraitDef.Named("PsychicSensitivity"))) + switch (pawn.story.traits.DegreeOfTrait(TraitDefOf.PsychicSensitivity)) { case -1: { @@ -304,10 +326,9 @@ public static Dictionary GetWeightedApparelIndividualStats(this // float v1 = pawn.GetStatValue(StatDefOf.MentalBreakThreshold); // float v2 = pawn.def.GetStatValueAbstract(StatDefOf.MentalBreakThreshold); - // // if (v1 > v2) // { - // AddStatToDict(StatDefOf.MentalBreakThreshold, (-v1 - v2) * 5, ref dict); + // AddStatToDict(StatDefOf.MentalBreakThreshold, (-v1 - v2) * 5, ref dict); // } } @@ -349,44 +370,56 @@ public static Dictionary GetWeightedApparelStats(this Pawn pawn) 1, (current, workType) => Mathf.Min(current, pawn.GetWorkPriority(workType))); - var log = "Outfitter Priorities, Pawn: " + pawn + " - Max: " + minPriority + "/" + maxPriority; + string log = "Outfitter Priorities, Pawn: " + pawn + " - Max: " + minPriority + "/" + maxPriority; foreach (WorkTypeDef workType in workTypes) { - foreach (KeyValuePair stat in GetStatsOfWorkType(pawn, workType)) + List> statsOfWorkType = GetStatsOfWorkType(pawn, workType).ToList(); + + foreach (KeyValuePair stat in statsOfWorkType) { int priority = Find.PlaySettings.useWorkPriorities ? pawn.GetWorkPriority(workType) : 3; float priorityAdjust = 1f / priority / maxPriority; - float weight = stat.Value * priorityAdjust; - for (int i = 0; i < workType.relevantSkills.Count; i++) + if (pawnSave.AddPersonalStats) { - var relSkill = workType.relevantSkills[i]; - SkillRecord record = pawn.skills.GetSkill(relSkill); - float skillMod = 1 + (record.Level / 20); - switch (record.passion) + for (int i = 0; i < workType.relevantSkills.Count; i++) { - case Passion.None: break; - case Passion.Minor: - skillMod *= 2; - break; - case Passion.Major: - skillMod *= 4; - break; + SkillDef relSkill = workType.relevantSkills[i]; + SkillRecord record = pawn.skills.GetSkill(relSkill); + float skillMod = 1 + (2f * record.Level / 20); + switch (record.passion) + { + case Passion.None: break; + case Passion.Minor: + skillMod *= 2f; + break; + + case Passion.Major: + skillMod *= 3f; + break; + } + priorityAdjust *= skillMod; } - priorityAdjust *= skillMod; } + float weight = stat.Value * priorityAdjust; + AddStatToDict(stat.Key, weight, ref dict); - log += "\n" + workType.defName + " - priority " + "-" + priority + " - adjusted " + priorityAdjust; + + log += "\n" + workType.defName + " - priority " + "-" + priority + " - adjusted " + + priorityAdjust; } } - Log.Message(log); + + // Log.Message(log); + // adjustments for traits AdjustStatsForTraits(pawn, ref dict); } - var num = ApparelStatCache.MaxValue / 8 * 5; + + float num = ApparelStatCache.MaxValue / 8 * 5; if (dict.Count > 0) { // normalize weights @@ -397,13 +430,10 @@ public static Dictionary GetWeightedApparelStats(this Pawn pawn) dict[key] /= max / num; } } - dict.OrderByDescending(x => x.Value); return dict; } - - [NotNull] public static List NotYetAssignedStatDefs([NotNull] this Pawn pawn) { @@ -473,12 +503,6 @@ private static void AdjustStatsForTraits(Pawn pawn, [NotNull] ref Dictionary list = map.listerThings.ThingsOfDef(ThingDefOf.CrashedPsychicEmanatorShipPart); - - return list.Any(); - } private static IEnumerable> GetStatsOfArmorMelee() { @@ -486,7 +510,7 @@ private static IEnumerable> GetStatsOfArmorMelee() yield return new KeyValuePair(StatDefOf.MeleeDodgeChance, 3f); yield return new KeyValuePair(StatDefOf.AccuracyTouch, 1.8f); yield return new KeyValuePair(StatDefOf.MeleeHitChance, 3f); - yield return new KeyValuePair(StatDefOf2.MeleeDPS, 2.4f); + yield return new KeyValuePair(StatDefOf.MeleeDPS, 2.4f); yield return new KeyValuePair(StatDefOf.MeleeWeapon_CooldownMultiplier, -2.4f); yield return new KeyValuePair(StatDefOf.MeleeWeapon_DamageMultiplier, 1.2f); yield return new KeyValuePair(StatDefOf.ArmorRating_Blunt, 2.5f); @@ -513,7 +537,7 @@ private static IEnumerable> GetStatsOfArmorRanged() yield return new KeyValuePair(StatDefOf.AccuracyMedium, 1.8f); yield return new KeyValuePair(StatDefOf.AccuracyLong, 1.8f); yield return new KeyValuePair(StatDefOf.MeleeHitChance, 1.8f); - yield return new KeyValuePair(StatDefOf2.MeleeDPS, 1f); + yield return new KeyValuePair(StatDefOf.MeleeDPS, 1f); yield return new KeyValuePair(StatDefOf.MeleeWeapon_CooldownMultiplier, -1f); yield return new KeyValuePair(StatDefOf.MeleeWeapon_DamageMultiplier, 1f); yield return new KeyValuePair(StatDefOf.ArmorRating_Blunt, 2.5f); @@ -522,39 +546,43 @@ private static IEnumerable> GetStatsOfArmorRanged() yield return new KeyValuePair(StatDefOf.ArmorRating_Electric, 1.5f); } - private static IEnumerable> GetStatsOfWorkType(Pawn pawn, WorkTypeDef worktype) + private static IEnumerable> GetStatsOfWorkType([NotNull] this Pawn pawn, + [NotNull] WorkTypeDef worktype) { SaveablePawn pawnSave = pawn.GetSaveablePawn(); - + bool mainJob = false; if (pawnSave.mainJob == MainJob.Soldier00Close_Combat) { - yield return new KeyValuePair(StatDefOf.MoveSpeed, 3f); - yield return new KeyValuePair(StatDefOf.AimingDelayFactor, -3f); - yield return new KeyValuePair(StatDefOf2.MeleeDPS, 2.4f); - yield return new KeyValuePair(StatDefOf.MeleeHitChance, 3f); - yield return new KeyValuePair(StatDefOf.MeleeDodgeChance, 3f); - yield return new KeyValuePair(StatDefOf.ArmorRating_Blunt, 1.8f); - yield return new KeyValuePair(StatDefOf.ArmorRating_Sharp, 1.8f); - yield return new KeyValuePair(StatDefOf.AccuracyTouch, 1.8f); - yield return new KeyValuePair(StatDefOf.MeleeWeapon_DamageMultiplier, 1.2f); - yield return new KeyValuePair(StatDefOf.MeleeWeapon_CooldownMultiplier, -2.4f); - yield return new KeyValuePair(StatDefOf.PainShockThreshold, 3f); + mainJob = true; + + yield return new KeyValuePair(StatDefOf.MoveSpeed, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.AimingDelayFactor, NegMax(mainJob)); + yield return new KeyValuePair(StatDefOf.MeleeDPS, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.MeleeHitChance, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.MeleeDodgeChance, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.ArmorRating_Blunt, PosMed(mainJob)); + yield return new KeyValuePair(StatDefOf.ArmorRating_Sharp, PosMed()); + yield return new KeyValuePair(StatDefOf.AccuracyTouch, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.MeleeWeapon_DamageMultiplier, PosMed(mainJob)); + yield return new KeyValuePair(StatDefOf.MeleeWeapon_CooldownMultiplier, NegMax(mainJob)); + yield return new KeyValuePair(StatDefOf.PainShockThreshold, PosMax(mainJob)); yield break; } if (pawnSave.mainJob == MainJob.Soldier00Ranged_Combat) { - yield return new KeyValuePair(StatDefOf.ShootingAccuracy, 3f); - yield return new KeyValuePair(StatDefOf.AccuracyShort, 1.8f); - yield return new KeyValuePair(StatDefOf.AccuracyMedium, 1.8f); - yield return new KeyValuePair(StatDefOf.AccuracyLong, 1.8f); - yield return new KeyValuePair(StatDefOf.MoveSpeed, 1.5f); - yield return new KeyValuePair(StatDefOf.ArmorRating_Blunt, 1.5f); - yield return new KeyValuePair(StatDefOf.ArmorRating_Sharp, 1.5f); - yield return new KeyValuePair(StatDefOf.MeleeDodgeChance, 0.5f); - yield return new KeyValuePair(StatDefOf.AimingDelayFactor, -3f); - yield return new KeyValuePair(StatDefOf.RangedWeapon_Cooldown, -3f); - yield return new KeyValuePair(StatDefOf.PainShockThreshold, 3f); + mainJob = true; + yield return new KeyValuePair(StatDefOf.ShootingAccuracy, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.AccuracyShort, PosMed(mainJob)); + yield return new KeyValuePair(StatDefOf.AccuracyMedium, PosMed(mainJob)); + yield return new KeyValuePair(StatDefOf.AccuracyLong, PosMed(mainJob)); + yield return new KeyValuePair(StatDefOf.MoveSpeed, PosMed(mainJob)); + yield return new KeyValuePair(StatDefOf.ArmorRating_Blunt, PosMed(mainJob)); + yield return new KeyValuePair(StatDefOf.ArmorRating_Sharp, PosMed(mainJob)); + yield return new KeyValuePair(StatDefOf.MeleeDodgeChance, PosMin()); + yield return new KeyValuePair(StatDefOf.AimingDelayFactor, NegMax(mainJob)); + yield return new KeyValuePair(StatDefOf.RangedWeapon_Cooldown, NegMax(mainJob)); + yield return new KeyValuePair(StatDefOf.PainShockThreshold, PosMax(mainJob)); yield break; } @@ -567,17 +595,13 @@ private static IEnumerable> GetStatsOfWorkType(Pawn case "Doctor": if (pawnSave.mainJob == MainJob.Doctor) { - yield return new KeyValuePair(StatDefOf2.MedicalOperationSpeed, 3f); - yield return new KeyValuePair(StatDefOf.MedicalSurgerySuccessChance, 3f); - yield return new KeyValuePair(StatDefOf.MedicalTendQuality, 3f); - yield return new KeyValuePair(StatDefOf.MedicalTendSpeed, 1.5f); - yield break; + mainJob = true; } - yield return new KeyValuePair(StatDefOf2.MedicalOperationSpeed, 1f); - yield return new KeyValuePair(StatDefOf.MedicalSurgerySuccessChance, 1f); - yield return new KeyValuePair(StatDefOf.MedicalTendQuality, 1f); - yield return new KeyValuePair(StatDefOf.MedicalTendSpeed, 0.5f); + yield return new KeyValuePair(StatDefOf2.MedicalOperationSpeed, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.MedicalSurgerySuccessChance, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.MedicalTendQuality, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.MedicalTendSpeed, PosMed(mainJob)); yield break; case "PatientBedRest": yield break; @@ -587,266 +611,202 @@ private static IEnumerable> GetStatsOfWorkType(Pawn case "Warden": if (pawnSave.mainJob == MainJob.Warden) { - yield return new KeyValuePair(StatDefOf.RecruitPrisonerChance, 3f); - yield return new KeyValuePair(StatDefOf.SocialImpact, 1.5f); - yield break; + mainJob = true; } - yield return new KeyValuePair(StatDefOf.RecruitPrisonerChance, 1f); - yield return new KeyValuePair(StatDefOf.SocialImpact, 0.5f); + yield return new KeyValuePair(StatDefOf.RecruitPrisonerChance, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.SocialImpact, PosMed(mainJob)); yield break; case "Handling": if (pawnSave.mainJob == MainJob.Handler) { - yield return new KeyValuePair(StatDefOf.TameAnimalChance, 3f); - yield return new KeyValuePair(StatDefOf.TrainAnimalChance, 3f); - yield return new KeyValuePair(StatDefOf.ArmorRating_Blunt, 1.25f); - yield return new KeyValuePair(StatDefOf.ArmorRating_Sharp, 1.25f); - yield return new KeyValuePair(StatDefOf.MeleeDodgeChance, 1f); - yield return new KeyValuePair(StatDefOf.MeleeHitChance, 0.6f); - yield return new KeyValuePair(StatDefOf.MoveSpeed, 0.9f); - yield return new KeyValuePair(StatDefOf.AnimalGatherYield, 1.2f); - yield return new KeyValuePair(StatDefOf.AnimalGatherSpeed, 0.6f); - yield return new KeyValuePair(StatDefOf.CarryingCapacity, 0.3f); - yield return new KeyValuePair(StatDefOf2.MeleeDPS, 0.6f); - yield return new KeyValuePair(StatDefOf.AccuracyTouch, 0.6f); - yield return new KeyValuePair(StatDefOf.MeleeWeapon_CooldownMultiplier, -0.6f); - yield return new KeyValuePair(StatDefOf.MeleeWeapon_DamageMultiplier, 0.6f); - yield break; + mainJob = true; } - yield return new KeyValuePair(StatDefOf.TameAnimalChance, 1f); - yield return new KeyValuePair(StatDefOf.TrainAnimalChance, 1f); - yield return new KeyValuePair(StatDefOf.ArmorRating_Blunt, 0.25f); - yield return new KeyValuePair(StatDefOf.ArmorRating_Sharp, 0.25f); - yield return new KeyValuePair(StatDefOf.MeleeDodgeChance, 0.5f); - yield return new KeyValuePair(StatDefOf.MeleeHitChance, 0.2f); - yield return new KeyValuePair(StatDefOf.MoveSpeed, 0.3f); - yield return new KeyValuePair(StatDefOf.AnimalGatherYield, 0.4f); - yield return new KeyValuePair(StatDefOf.AnimalGatherSpeed, 0.2f); - yield return new KeyValuePair(StatDefOf.CarryingCapacity, 0.1f); - yield return new KeyValuePair(StatDefOf2.MeleeDPS, 0.2f); - yield return new KeyValuePair(StatDefOf.AccuracyTouch, 0.2f); - yield return new KeyValuePair(StatDefOf.MeleeWeapon_CooldownMultiplier, -0.2f); - yield return new KeyValuePair(StatDefOf.MeleeWeapon_DamageMultiplier, 0.2f); + yield return new KeyValuePair(StatDefOf.TameAnimalChance, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.TrainAnimalChance, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.ArmorRating_Blunt, PosMin(mainJob)); + yield return new KeyValuePair(StatDefOf.ArmorRating_Sharp, PosMin(mainJob)); + yield return new KeyValuePair(StatDefOf.MeleeDodgeChance, PosMed(mainJob)); + yield return new KeyValuePair(StatDefOf.MeleeHitChance, PosMin(mainJob)); + yield return new KeyValuePair(StatDefOf.MoveSpeed, PosMin(mainJob)); + yield return new KeyValuePair(StatDefOf.AnimalGatherYield, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.AnimalGatherSpeed, PosMax(mainJob)); + // yield return new KeyValuePair(StatDefOf.CarryingCapacity, PosMin(mainJob)); + yield return new KeyValuePair(StatDefOf.MeleeDPS, PosMin(mainJob)); + yield return new KeyValuePair(StatDefOf.AccuracyTouch, PosMin(mainJob)); + yield return new KeyValuePair(StatDefOf.MeleeWeapon_CooldownMultiplier, NegMin(mainJob)); + yield return new KeyValuePair(StatDefOf.MeleeWeapon_DamageMultiplier, PosMin(mainJob)); yield break; case "Cooking": if (pawnSave.mainJob == MainJob.Cook) { - yield return new KeyValuePair(StatDefOf2.CookSpeed, 3f); - yield return new KeyValuePair(StatDefOf2.BrewingSpeed, 3f); - yield return new KeyValuePair(StatDefOf2.ButcheryFleshSpeed, 3f); - yield return new KeyValuePair(StatDefOf2.ButcheryFleshEfficiency, 3f); - yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, 0.6f); - yield return new KeyValuePair(StatDefOf.MoveSpeed, 0.3f); - yield return new KeyValuePair(StatDefOf.FoodPoisonChance, -1.5f); - yield break; + mainJob = true; } // yield return new KeyValuePair(StatDefOf.MoveSpeed, 0.05f); // yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, 0.2f); - yield return new KeyValuePair(StatDefOf2.CookSpeed, 1f); - yield return new KeyValuePair(StatDefOf2.BrewingSpeed, 1f); - yield return new KeyValuePair(StatDefOf2.ButcheryFleshSpeed, 1f); - yield return new KeyValuePair(StatDefOf2.ButcheryFleshEfficiency, 1f); - yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, 0.2f); - yield return new KeyValuePair(StatDefOf.MoveSpeed, 0.1f); - yield return new KeyValuePair(StatDefOf.FoodPoisonChance, -0.5f); + yield return new KeyValuePair(StatDefOf2.CookSpeed, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf2.BrewingSpeed, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf2.ButcheryFleshSpeed, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf2.ButcheryFleshEfficiency, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, PosMin(mainJob)); + yield return new KeyValuePair(StatDefOf.MoveSpeed, PosMin(mainJob)); + yield return new KeyValuePair(StatDefOf.FoodPoisonChance, NegMax(mainJob)); yield break; case "Hunting": if (pawnSave.mainJob == MainJob.Hunter) { - yield return new KeyValuePair(StatDefOf.ShootingAccuracy, 3f); - yield return new KeyValuePair(StatDefOf.MoveSpeed, 1.5f); - yield return new KeyValuePair(StatDefOf.AccuracyShort, 1.2f); - yield return new KeyValuePair(StatDefOf.AccuracyMedium, 1.2f); - yield return new KeyValuePair(StatDefOf.AccuracyLong, 1.2f); - yield return new KeyValuePair(StatDefOf2.MeleeDPS, 0.75f); - yield return new KeyValuePair(StatDefOf.MeleeHitChance, 0.75f); - yield return new KeyValuePair(StatDefOf.ArmorRating_Blunt, 0.75f); - yield return new KeyValuePair(StatDefOf.ArmorRating_Sharp, 0.75f); - yield return new KeyValuePair(StatDefOf.RangedWeapon_Cooldown, -2.4f); - yield return new KeyValuePair(StatDefOf.AimingDelayFactor, -3f); - yield return new KeyValuePair(StatDefOf.PainShockThreshold, 3f); - yield break; + mainJob = true; } - yield return new KeyValuePair(StatDefOf.ShootingAccuracy, 1f); - yield return new KeyValuePair(StatDefOf.MoveSpeed, 0.5f); - yield return new KeyValuePair(StatDefOf.AccuracyShort, 0.4f); - yield return new KeyValuePair(StatDefOf.AccuracyMedium, 0.4f); - yield return new KeyValuePair(StatDefOf.AccuracyLong, 0.4f); - yield return new KeyValuePair(StatDefOf2.MeleeDPS, 0.25f); - yield return new KeyValuePair(StatDefOf.MeleeHitChance, 0.25f); - yield return new KeyValuePair(StatDefOf.ArmorRating_Blunt, 0.25f); - yield return new KeyValuePair(StatDefOf.ArmorRating_Sharp, 0.25f); - yield return new KeyValuePair(StatDefOf.RangedWeapon_Cooldown, -0.8f); - yield return new KeyValuePair(StatDefOf.AimingDelayFactor, -1f); - yield return new KeyValuePair(StatDefOf.PainShockThreshold, 1f); + yield return new KeyValuePair(StatDefOf.ShootingAccuracy, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.MoveSpeed, PosMed(mainJob)); + yield return new KeyValuePair(StatDefOf.AccuracyShort, PosMed(mainJob)); + yield return new KeyValuePair(StatDefOf.AccuracyMedium, PosMed(mainJob)); + yield return new KeyValuePair(StatDefOf.AccuracyLong, PosMed(mainJob)); + yield return new KeyValuePair(StatDefOf.MeleeDPS, PosMin(mainJob)); + yield return new KeyValuePair(StatDefOf.MeleeHitChance, PosMin(mainJob)); + yield return new KeyValuePair(StatDefOf.ArmorRating_Blunt, PosMin(mainJob)); + yield return new KeyValuePair(StatDefOf.ArmorRating_Sharp, PosMin(mainJob)); + yield return new KeyValuePair(StatDefOf.RangedWeapon_Cooldown, NegMax(mainJob)); + yield return new KeyValuePair(StatDefOf.AimingDelayFactor, NegMax(mainJob)); + yield return new KeyValuePair(StatDefOf.PainShockThreshold, PosMax(mainJob)); yield break; case "Construction": if (pawnSave.mainJob == MainJob.Constructor) { - yield return new KeyValuePair(StatDefOf.ConstructionSpeed, 3f); - yield return new KeyValuePair(StatDefOf.ConstructSuccessChance, 3f); - yield return new KeyValuePair(StatDefOf.FixBrokenDownBuildingSuccessChance, 3f); - yield return new KeyValuePair(StatDefOf.SmoothingSpeed, 3f); - yield return new KeyValuePair(StatDefOf.CarryingCapacity, 0.75f); - yield return new KeyValuePair(StatDefOf.MoveSpeed, 0.6f); - yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, 0.6f); - yield break; + mainJob = true; } - yield return new KeyValuePair(StatDefOf.ConstructionSpeed, 1f); - yield return new KeyValuePair(StatDefOf.ConstructSuccessChance, 1f); - yield return new KeyValuePair(StatDefOf.FixBrokenDownBuildingSuccessChance, 1f); - yield return new KeyValuePair(StatDefOf.SmoothingSpeed, 1f); - yield return new KeyValuePair(StatDefOf.CarryingCapacity, 0.25f); - yield return new KeyValuePair(StatDefOf.MoveSpeed, 0.2f); - yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, 0.2f); + yield return new KeyValuePair(StatDefOf.ConstructionSpeed, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.ConstructSuccessChance, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.FixBrokenDownBuildingSuccessChance, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.SmoothingSpeed, PosMax(mainJob)); + // yield return new KeyValuePair(StatDefOf.CarryingCapacity, PosMin(mainJob)); + yield return new KeyValuePair(StatDefOf.MoveSpeed, PosMin(mainJob)); + yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, PosMin(mainJob)); yield break; case "Repair": - yield return new KeyValuePair(StatDefOf.FixBrokenDownBuildingSuccessChance, 1f); - yield return new KeyValuePair(StatDefOf.MoveSpeed, 0.2f); - yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, 0.2f); + yield return new KeyValuePair(StatDefOf.FixBrokenDownBuildingSuccessChance, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.MoveSpeed, PosMin(mainJob)); + yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, PosMin(mainJob)); yield break; case "Growing": if (pawnSave.mainJob == MainJob.Grower) { - yield return new KeyValuePair(StatDefOf.PlantHarvestYield, 3f); - yield return new KeyValuePair(StatDefOf.PlantWorkSpeed, 3f); - yield return new KeyValuePair(StatDefOf.MoveSpeed, 0.3f); - yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, 0.6f); - yield break; + mainJob = true; } - yield return new KeyValuePair(StatDefOf.PlantHarvestYield, 1f); - yield return new KeyValuePair(StatDefOf.PlantWorkSpeed, 1f); - yield return new KeyValuePair(StatDefOf.MoveSpeed, 0.1f); - yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, 0.2f); + yield return new KeyValuePair(StatDefOf.PlantHarvestYield, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.PlantWorkSpeed, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.MoveSpeed, PosMin(mainJob)); + yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, PosMin(mainJob)); yield break; case "Mining": if (pawnSave.mainJob == MainJob.Miner) { - yield return new KeyValuePair(StatDefOf.MiningYield, 3f); - yield return new KeyValuePair(StatDefOf.MiningSpeed, 3f); - yield return new KeyValuePair(StatDefOf.CarryingCapacity, 0.75f); - yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, 0.6f); - yield return new KeyValuePair(StatDefOf.MoveSpeed, 0.3f); - yield break; + mainJob = true; } - yield return new KeyValuePair(StatDefOf.MiningYield, 1f); - yield return new KeyValuePair(StatDefOf.MiningSpeed, 1f); - yield return new KeyValuePair(StatDefOf.CarryingCapacity, 0.25f); - yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, 0.2f); - yield return new KeyValuePair(StatDefOf.MoveSpeed, 0.1f); + yield return new KeyValuePair(StatDefOf.MiningYield, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.MiningSpeed, PosMax(mainJob)); + // yield return new KeyValuePair(StatDefOf.CarryingCapacity, PosMin(mainJob)); + yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, PosMin(mainJob)); + yield return new KeyValuePair(StatDefOf.MoveSpeed, PosMin(mainJob)); yield break; case "PlantCutting": - yield return new KeyValuePair(StatDefOf.PlantWorkSpeed, 0.5f); - yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, 0.2f); + yield return new KeyValuePair(StatDefOf.PlantWorkSpeed, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.PlantHarvestYield, PosMed(mainJob)); + yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, PosMin(mainJob)); yield break; case "Smithing": if (pawnSave.mainJob == MainJob.Smith) { - yield return new KeyValuePair(StatDefOf2.SmithingSpeed, 3f); - yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, 0.6f); - yield break; + mainJob = true; } - yield return new KeyValuePair(StatDefOf2.SmithingSpeed, 1f); - yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, 0.2f); + yield return new KeyValuePair(StatDefOf2.SmithingSpeed, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, PosMin(mainJob)); yield break; case "Tailoring": if (pawnSave.mainJob == MainJob.Tailor) { - yield return new KeyValuePair(StatDefOf2.TailoringSpeed, 3f); - yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, 0.6f); - yield break; + mainJob = true; } - yield return new KeyValuePair(StatDefOf2.TailoringSpeed, 1f); - yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, 0.2f); + yield return new KeyValuePair(StatDefOf2.TailoringSpeed, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, PosMin(mainJob)); yield break; case "Art": if (pawnSave.mainJob == MainJob.Artist) { - yield return new KeyValuePair(StatDefOf2.SculptingSpeed, 3f); - yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, 0.6f); - yield break; + mainJob = true; } - yield return new KeyValuePair(StatDefOf2.SculptingSpeed, 1f); - yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, 0.2f); + yield return new KeyValuePair(StatDefOf2.SculptingSpeed, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, PosMin(mainJob)); yield break; case "Crafting": if (pawnSave.mainJob == MainJob.Crafter) { - yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, 2.5f); - yield return new KeyValuePair(StatDefOf2.SmeltingSpeed, 3f); - yield return new KeyValuePair(StatDefOf2.ButcheryMechanoidSpeed, 1.5f); - yield return new KeyValuePair(StatDefOf2.ButcheryMechanoidEfficiency, 1.5f); - yield break; + mainJob = true; } - yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, 0.75f); - yield return new KeyValuePair(StatDefOf2.SmeltingSpeed, 1f); - yield return new KeyValuePair(StatDefOf2.ButcheryMechanoidSpeed, 0.5f); - yield return new KeyValuePair(StatDefOf2.ButcheryMechanoidEfficiency, 0.5f); + yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, PosMed(mainJob)); + yield return new KeyValuePair(StatDefOf2.SmeltingSpeed, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf2.ButcheryMechanoidSpeed, PosMed(mainJob)); + yield return new KeyValuePair(StatDefOf2.ButcheryMechanoidEfficiency, PosMed(mainJob)); yield break; case "Hauling": if (pawnSave.mainJob == MainJob.Hauler) { - yield return new KeyValuePair(StatDefOf.MoveSpeed, 3f); - yield return new KeyValuePair(StatDefOf.CarryingCapacity, 0.75f); - yield break; + mainJob = true; } - yield return new KeyValuePair(StatDefOf.MoveSpeed, 1f); - yield return new KeyValuePair(StatDefOf.CarryingCapacity, 0.25f); + yield return new KeyValuePair(StatDefOf.MoveSpeed, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.CarryingCapacity, PosMin(mainJob)); yield break; case "Cleaning": - yield return new KeyValuePair(StatDefOf.MoveSpeed, 0.5f); - yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, 0.25f); + yield return new KeyValuePair(StatDefOf.MoveSpeed, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, PosMax(mainJob)); yield break; case "Research": if (pawnSave.mainJob == MainJob.Researcher) { - yield return new KeyValuePair(StatDefOf.ResearchSpeed, 3f); - yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, 0.6f); - yield break; + mainJob = true; } - yield return new KeyValuePair(StatDefOf.ResearchSpeed, 1f); - yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, 0.2f); + yield return new KeyValuePair(StatDefOf.ResearchSpeed, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.WorkSpeedGlobal, PosMin(mainJob)); yield break; // Colony Manager case "Managing": - yield return new KeyValuePair(StatDefOf.SocialImpact, 0.25f); - yield return new KeyValuePair(DefDatabase.GetNamed("ManagingSpeed"), 0.5f); + yield return new KeyValuePair(StatDefOf.SocialImpact, PosMin(mainJob)); + yield return new KeyValuePair(DefDatabase.GetNamed("ManagingSpeed"), PosMed(mainJob)); yield break; // Hospitality case "Diplomat": - yield return new KeyValuePair(StatDefOf.SocialImpact, 0.5f); - yield return new KeyValuePair(StatDefOf.DiplomacyPower, 1f); - yield return new KeyValuePair(StatDefOf.TradePriceImprovement, 1f); + yield return new KeyValuePair(StatDefOf.SocialImpact, PosMed(mainJob)); + yield return new KeyValuePair(StatDefOf.DiplomacyPower, PosMax(mainJob)); + yield return new KeyValuePair(StatDefOf.TradePriceImprovement, PosMax(mainJob)); yield break; // Else @@ -859,7 +819,7 @@ private static IEnumerable> GetStatsOfWorkType(Pawn default: if (!IgnoredWorktypeDefs.Contains(worktype.defName)) { - Log.Warning("WorkTypeDef " + worktype.defName + " not handled."); + Log.Warning("Outfitter: WorkTypeDef " + worktype.defName + " not handled. \nThis is not a bug, just a notice for the mod author."); IgnoredWorktypeDefs.Add(worktype.defName); } diff --git a/Source/Outfitter/Cache.cs b/Source/Outfitter/Cache.cs index 1f45aa7..e76cf7c 100644 --- a/Source/Outfitter/Cache.cs +++ b/Source/Outfitter/Cache.cs @@ -6,8 +6,6 @@ using RimWorld; - using Verse; - public static class Cache { // ReSharper disable once FieldCanBeMadeReadOnly.Global @@ -18,25 +16,22 @@ public static float GetEquippedStatValue([NotNull] this Apparel apparel, StatDef float currentStat = apparel.def.equippedStatOffsets.GetStatOffsetFromList(stat); // { - // float baseStat = apparel.GetStatValue(stat, true); - // float currentStat = baseStat; - // currentStat += apparel.def.equippedStatOffsets.GetStatOffsetFromList(stat.); - // - // DoApparelScoreRaw_PawnStatsHandlers(apparel, StatDefOf.Insulation_Cold, out float infInsulationCold); - // DoApparelScoreRaw_PawnStatsHandlers(apparel, StatDefOf.Insulation_Heat, out float infInsulationHeat); - // - // if (baseStat == 0) - // return currentStat; - // else - // return currentStat / baseStat; + // float baseStat = apparel.GetStatValue(stat, true); + // float currentStat = baseStat; + // currentStat += apparel.def.equippedStatOffsets.GetStatOffsetFromList(stat.); + // DoApparelScoreRaw_PawnStatsHandlers(apparel, StatDefOf.Insulation_Cold, out float infInsulationCold); + // DoApparelScoreRaw_PawnStatsHandlers(apparel, StatDefOf.Insulation_Heat, out float infInsulationHeat); + // if (baseStat == 0) + // return currentStat; + // else + // return currentStat / baseStat; // } // float pawnStat = p.GetStatValue(stat); - // // var x = pawnStat; // if (!p.apparel.WornApparel.Contains(apparel)) // { - // x += currentStat; + // x += currentStat; // } // currentStat += apparel.def.equippedStatOffsets.GetStatOffsetFromList(stat.StatDef); @@ -44,7 +39,6 @@ public static float GetEquippedStatValue([NotNull] this Apparel apparel, StatDef // { // return apparel.def.equippedStatOffsets.GetStatOffsetFromList(stat.StatDef) - baseStat; // } - return currentStat; } } diff --git a/Source/Outfitter/Extensions.cs b/Source/Outfitter/Extensions.cs index 826a72f..b3cd024 100644 --- a/Source/Outfitter/Extensions.cs +++ b/Source/Outfitter/Extensions.cs @@ -1,10 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Outfitter +namespace Outfitter { + using System.Linq; + using Verse; public static class Extensions @@ -33,4 +30,4 @@ public static int GetWorkPriority(this Pawn pawn, WorkTypeDef workType) return pawn.workSettings.GetPriority(workType); } } -} +} \ No newline at end of file diff --git a/Source/Outfitter/GameComponent_Outfitter.cs b/Source/Outfitter/GameComponent_Outfitter.cs index c69fb8e..824a6d1 100644 --- a/Source/Outfitter/GameComponent_Outfitter.cs +++ b/Source/Outfitter/GameComponent_Outfitter.cs @@ -10,11 +10,11 @@ public class GameComponent_Outfitter : GameComponent { + public static bool updated; + [NotNull] public List _pawnCache = new List(); - public static bool updated; - public GameComponent_Outfitter() { } @@ -41,12 +41,11 @@ public GameComponent_Outfitter(Game game) } } - public override void ExposeData() { base.ExposeData(); - Scribe_Collections.Look(ref _pawnCache, "Pawns", LookMode.Deep); + Scribe_Collections.Look(ref this._pawnCache, "Pawns", LookMode.Deep); } } } \ No newline at end of file diff --git a/Source/Outfitter/HarmonyPatches.cs b/Source/Outfitter/HarmonyPatches.cs index 5343837..7ce8186 100644 --- a/Source/Outfitter/HarmonyPatches.cs +++ b/Source/Outfitter/HarmonyPatches.cs @@ -5,11 +5,13 @@ // public override string ModIdentifier { get { return "Outfitter"; } } // } -using Harmony; -using Outfitter; using System.Linq; using System.Reflection; +using Harmony; + +using Outfitter; + using RimWorld; using Verse; @@ -27,8 +29,10 @@ static HarmonyPatches() // new HarmonyMethod(typeof(TabsPatch), nameof(TabsPatch.DoTabs_Prefix)), // null); harmony.Patch( - AccessTools.Method(typeof(RimWorld.JobGiver_OptimizeApparel), "TryGiveJob"), - new HarmonyMethod(typeof(JobGiver_OutfitterOptimizeApparel), nameof(JobGiver_OutfitterOptimizeApparel.TryGiveJob_Prefix)), + AccessTools.Method(typeof(JobGiver_OptimizeApparel), "TryGiveJob"), + new HarmonyMethod( + typeof(JobGiver_OutfitterOptimizeApparel), + nameof(JobGiver_OutfitterOptimizeApparel.TryGiveJob_Prefix)), null); harmony.Patch( @@ -41,10 +45,20 @@ static HarmonyPatches() null, new HarmonyMethod(typeof(HarmonyPatches), nameof(UpdatePriorities))); - // harmony.Patch( - // AccessTools.Method(typeof(ThinkNode_JobGiver), nameof(ThinkNode_JobGiver.TryIssueJobPackage)), - // null, - // new HarmonyMethod(typeof(HarmonyPatches), nameof(LogJobActivities))); + harmony.Patch( + AccessTools.Method(typeof(ITab_Bills), "FillTab"), + new HarmonyMethod(typeof(ITab_Bills_Patch), nameof(ITab_Bills_Patch.FillTab_Prefix)), + null); + + harmony.Patch( + AccessTools.Method(typeof(ITab_Bills), "TabUpdate"), + new HarmonyMethod(typeof(ITab_Bills_Patch), nameof(ITab_Bills_Patch.TabUpdate_Prefix)), + null); + + // harmony.Patch( + // AccessTools.Method(typeof(ThinkNode_JobGiver), nameof(ThinkNode_JobGiver.TryIssueJobPackage)), + // null, + // new HarmonyMethod(typeof(HarmonyPatches), nameof(LogJobActivities))); // harmony.Patch( // AccessTools.Method(typeof(ITab_Bills), "FillTab"), @@ -56,18 +70,23 @@ static HarmonyPatches() "Outfitter successfully completed " + harmony.GetPatchedMethods().Count() + " patches with harmony."); } - private static void UpdatePriorities(Pawn_WorkSettings __instance) + private static void LogJobActivities( + ThinkNode_JobGiver __instance, + ThinkResult __result, + Pawn pawn, + JobIssueParams jobParams) { - FieldInfo fieldInfo = typeof(Pawn_WorkSettings).GetField("pawn", BindingFlags.NonPublic | BindingFlags.Instance); - Pawn pawn = (Pawn)fieldInfo?.GetValue(__instance); - pawn.GetSaveablePawn().forceStatUpdate = true; + // if (__result.Job.def.driverClass.) + // { + // __result.Job. + // } } - private static void LogJobActivities(ThinkNode_JobGiver __instance, ThinkResult __result, Pawn pawn, JobIssueParams jobParams) + private static void UpdatePriorities(Pawn_WorkSettings __instance) { - // if (__result.Job.def.driverClass.) - // { - // __result.Job. - // } + FieldInfo fieldInfo = + typeof(Pawn_WorkSettings).GetField("pawn", BindingFlags.NonPublic | BindingFlags.Instance); + Pawn pawn = (Pawn)fieldInfo?.GetValue(__instance); + pawn.GetSaveablePawn().forceStatUpdate = true; } } \ No newline at end of file diff --git a/Source/Outfitter/Helper/HelperThingFilterUI.cs b/Source/Outfitter/Helper/HelperThingFilterUI.cs deleted file mode 100644 index e45aa9c..0000000 --- a/Source/Outfitter/Helper/HelperThingFilterUI.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System.Linq; -using RimWorld; -using UnityEngine; -using Verse; - -namespace Outfitter.Helper -{ - public static class HelperThingFilterUI - { - private const float ExtraViewHeight = 90f; - - private const float RangeLabelTab = 10f; - - private const float RangeLabelHeight = 19f; - - private const float SliderHeight = 26f; - - private const float SliderTab = 20f; - - private static float viewHeight; - - // Verse.ThingFilterUI - public static void DoThingFilterConfigWindow(Rect rect, ref Vector2 scrollPosition, ThingFilter filter, ThingFilter parentFilter = null, int openMask = 1, string filterText = null) - { - Widgets.DrawMenuSection(rect, true); - Text.Font = GameFont.Tiny; - float num = rect.width - 2f; - Rect rect2 = new Rect(rect.x + 1f, rect.y + 1f, num / 2f, 24f); - if (Widgets.ButtonText(rect2, "ClearAll".Translate(), true, false, true)) - { - filter.SetDisallowAll(); - } - - Rect rect3 = new Rect(rect2.xMax + 1f, rect2.y, num / 2f, 24f); - if (Widgets.ButtonText(rect3, "AllowAll".Translate(), true, false, true)) - { - filter.SetAllowAll(parentFilter); - } - - Text.Font = GameFont.Small; - rect.yMin = rect2.yMax; - Rect viewRect = new Rect(0f, 0f, rect.width - 16f, HelperThingFilterUI.viewHeight); - Widgets.BeginScrollView(rect, ref scrollPosition, viewRect); - float num2 = 2f; - HelperThingFilterUI.DrawHitPointsFilterConfig(ref num2, viewRect.width, filter); - HelperThingFilterUI.DrawQualityFilterConfig(ref num2, viewRect.width, filter); - float num3 = num2; - Rect rect4 = new Rect(0f, num2, viewRect.width, 9999f); - Listing_TreeThingFilter listing_TreeThingFilter = new Listing_TreeThingFilter(rect4, filter, parentFilter); - TreeNode_ThingCategory node = ThingCategoryNodeDatabase.RootNode; - if (parentFilter != null) - { - if (parentFilter.DisplayRootCategory == null) - { - parentFilter.RecalculateDisplayRootCategory(); - } - - node = parentFilter.DisplayRootCategory; - } - - if (filterText != null && filterText.Length > 2) - { - TreeNode_ThingCategory rootNode = new TreeNode_ThingCategory(new ThingCategoryDef()); - - node.catDef.DescendantThingDefs.Where(td => td.label.ToLower().Contains(filterText.ToLower())); - - foreach (ThingDef currentThing in node.catDef.DescendantThingDefs.Where(td => td.label.ToLower().Contains(filterText.ToLower()))) - { - rootNode.catDef.childThingDefs.Add(currentThing); - } - - node = rootNode; - } - - listing_TreeThingFilter.DoCategoryChildren(node, 0, openMask, true); - listing_TreeThingFilter.End(); - if (Event.current.type == EventType.Layout) - { - HelperThingFilterUI.viewHeight = num3 + listing_TreeThingFilter.CurHeight + 90f; - } - - Widgets.EndScrollView(); - } - - private static void DrawHitPointsFilterConfig(ref float y, float width, ThingFilter filter) - { - if (!filter.allowedHitPointsConfigurable) - { - return; - } - - Rect rect = new Rect(20f, y, width - 20f, 26f); - FloatRange allowedHitPointsPercents = filter.AllowedHitPointsPercents; - Widgets.FloatRange(rect, 1, ref allowedHitPointsPercents, 0f, 1f, "HitPoints", ToStringStyle.PercentZero); - filter.AllowedHitPointsPercents = allowedHitPointsPercents; - y += 26f; - y += 5f; - Text.Font = GameFont.Small; - } - - private static void DrawQualityFilterConfig(ref float y, float width, ThingFilter filter) - { - if (!filter.allowedQualitiesConfigurable) - { - return; - } - - Rect rect = new Rect(20f, y, width - 20f, 26f); - QualityRange allowedQualityLevels = filter.AllowedQualityLevels; - Widgets.QualityRange(rect, 2, ref allowedQualityLevels); - filter.AllowedQualityLevels = allowedQualityLevels; - y += 26f; - y += 5f; - Text.Font = GameFont.Small; - } - } -} \ No newline at end of file diff --git a/Source/Outfitter/ITab_Bills_Patch.cs b/Source/Outfitter/ITab_Bills_Patch.cs index 12ecfa8..1e10932 100644 --- a/Source/Outfitter/ITab_Bills_Patch.cs +++ b/Source/Outfitter/ITab_Bills_Patch.cs @@ -1,77 +1,105 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Outfitter +namespace Outfitter { + using System; + using System.Collections.Generic; + using System.Linq; using System.Reflection; - using Harmony; - using RimWorld; using UnityEngine; using Verse; - using FloatMenuOption = Verse.FloatMenuOption; - public static class ITab_Bills_Patch { private static float viewHeight = 1000f; private static Vector2 scrollPosition = default(Vector2); - // RimWorld.ITab_Bills private static readonly Vector2 WinSize = new Vector2(420f, 480f); + private static Bill mouseoverBill; + + // RimWorld.ITab_Bills + public static bool FillTab_Prefix() { + Building_WorkTable selTable = (Building_WorkTable)Find.Selector.SingleSelectedThing; + PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.BillsTab, KnowledgeAmount.FrameDisplayed); - Rect rect = new Rect(0f, 0f, WinSize.x, WinSize.y).ContractedBy(10f); + float x = WinSize.x; + Vector2 winSize2 = WinSize; + Rect rect2 = new Rect(0f, 0f, x, winSize2.y).ContractedBy(10f); Func> recipeOptionsMaker = delegate { List list = new List(); - for (int i = 0; i < SelTable.def.AllRecipes.Count; i++) + for (int i = 0; i < selTable.def.AllRecipes.Count; i++) { - list.Add(new FloatMenuOption("LOL", null)); - - if (SelTable.def.AllRecipes[i].AvailableNow) + if (selTable.def.AllRecipes[i].AvailableNow) { - RecipeDef recipe = SelTable.def.AllRecipes[i]; - list.Add(new FloatMenuOption(recipe.LabelCap, delegate - { - if (!SelTable.Map.mapPawns.FreeColonists.Any((Pawn col) => recipe.PawnSatisfiesSkillRequirements(col))) - { - Bill.CreateNoPawnsWithSkillDialog(recipe); - } - Bill bill = recipe.MakeNewBill(); - SelTable.billStack.AddBill(bill); - if (recipe.conceptLearned != null) - { - PlayerKnowledgeDatabase.KnowledgeDemonstrated(recipe.conceptLearned, KnowledgeAmount.Total); - } - if (TutorSystem.TutorialMode) - { - TutorSystem.Notify_Event("AddBill-" + recipe.LabelCap); - } - })); + RecipeDef recipe = selTable.def.AllRecipes[i]; + list.Add( + new FloatMenuOption( + recipe.LabelCap, + delegate + { + if (!selTable.Map.mapPawns.FreeColonists.Any( + col => recipe.PawnSatisfiesSkillRequirements(col))) + { + Bill.CreateNoPawnsWithSkillDialog(recipe); + } + + Bill bill = recipe.MakeNewBill(); + selTable.billStack.AddBill(bill); + if (recipe.conceptLearned != null) + { + PlayerKnowledgeDatabase.KnowledgeDemonstrated( + recipe.conceptLearned, + KnowledgeAmount.Total); + } + + if (TutorSystem.TutorialMode) + { + TutorSystem.Notify_Event("AddBill-" + recipe.LabelCap); + } + }, + MenuOptionPriority.Default, + null, + null, + 29f, + rect => Widgets.InfoCardButton( + (float)(rect.x + 5.0), + (float)(rect.y + (rect.height - 24.0) / 2.0), + recipe))); } } - if (!Enumerable.Any(list)) + + if (!list.Any()) { - list.Add(new FloatMenuOption("NoneBrackets".Translate(), null)); + list.Add( + new FloatMenuOption( + "NoneBrackets".Translate(), + null)); } return list; }; - Bill mouseoverBill = SelTable.billStack.DoListing(rect, recipeOptionsMaker, ref scrollPosition, ref viewHeight); + mouseoverBill = selTable.billStack.DoListing(rect2, recipeOptionsMaker, ref scrollPosition, ref viewHeight); - typeof(Bill).GetField( - "mouseoverBill", - BindingFlags.Instance | BindingFlags.NonPublic).SetValue(typeof(Bill), mouseoverBill); + + return false; + + } + + public static bool TabUpdate_Prefix() + { + if (mouseoverBill != null) + { + mouseoverBill.TryDrawIngredientSearchRadiusOnMap(Find.Selector.SingleSelectedThing.Position); + mouseoverBill = null; + } return false; } } diff --git a/Source/Outfitter/InfusedStats/HarmonyPatchInfused.cs b/Source/Outfitter/InfusedStats/HarmonyPatchInfused.cs deleted file mode 100644 index 54120f5..0000000 --- a/Source/Outfitter/InfusedStats/HarmonyPatchInfused.cs +++ /dev/null @@ -1,75 +0,0 @@ -//namespace Outfitter -//{ -// public class Outfitter_ModBase : HugsLib.ModBase -// { -// public override string ModIdentifier { get { return "Outfitter"; } } -// } - -using System; - -using Harmony; - -using Outfitter; -using Outfitter.InfusedStats; - -using Verse; - -[StaticConstructorOnStartup] -internal class HarmonyPatchInfused -{ - #region Public Constructors - - static HarmonyPatchInfused() - { - HarmonyInstance harmony = HarmonyInstance.Create("com.outfitterinfused.rimworld.mod"); - - try - { - ((Action)(() => - { - if (AccessTools.Method(typeof(Infused.GenInfusion), nameof(Infused.GenInfusion.TryGetInfusions)) - == null) - { - return; - } - - harmony.Patch( - AccessTools.Method( - typeof(ApparelStatCache), - nameof(ApparelStatCache.ApparelScoreRaw_PawnStatsHandlers)), - null, - new HarmonyMethod( - typeof(InfusedStats), - nameof(InfusedStats.ApparelScoreRaw_PawnStatsHandlers))); - - harmony.Patch( - AccessTools.Method( - typeof(ApparelStatCache), - nameof(ApparelStatCache.ApparelScoreRaw_FillInfusedStat)), - null, - new HarmonyMethod( - typeof(InfusedStats), - nameof(InfusedStats.ApparelScoreRaw_FillInfusedStat))); - - harmony.Patch( - AccessTools.Method( - typeof(ApparelStatCache), - nameof(ApparelStatCache.Ignored_WTHandlers)), - null, - new HarmonyMethod( - typeof(InfusedStats), - nameof(InfusedStats.Ignored_WTHandlers))); - // ApparelStatCache.ApparelScoreRaw_PawnStatsHandlers += InfusedStats.ApparelScoreRaw_PawnStatsHandlers; - // ApparelStatCache.ApparelScoreRaw_FillInfusedStat += InfusedStats.ApparelScoreRaw_FillInfusedStat; - // ApparelStatCache.Ignored_WTHandlers += InfusedStats.Ignored_WTHandlers; - }))(); - } - catch (TypeLoadException) - { - } - - Log.Message("Outfitter successfully initialized Infused stats."); - } - - #endregion Public Constructors -} \ No newline at end of file diff --git a/Source/Outfitter/InfusedStats/InfusedStats.cs b/Source/Outfitter/InfusedStats/InfusedStats.cs deleted file mode 100644 index 9254595..0000000 --- a/Source/Outfitter/InfusedStats/InfusedStats.cs +++ /dev/null @@ -1,83 +0,0 @@ -namespace Outfitter.Infused -{ - using System.Collections.Generic; - using System.Linq; - - using RimWorld; - - using Verse; - - public static class InfusedStats - { - public static void ApparelScoreRaw_FillInfusedStat(Apparel apparel, StatDef parentStat, ref HashSet infusedOffsets) - { - if (apparel.TryGetInfusions(out InfusionSet inf)) - { - StatMod mod; - - Def prefix = inf.prefix; - Def suffix = inf.suffix; - - if (prefix != null && prefix.TryGetStatValue(parentStat, out mod)) - { - infusedOffsets.Add(parentStat); - } - - if (suffix != null && suffix.TryGetStatValue(parentStat, out mod)) - { - infusedOffsets.Add(parentStat); - } - - // if (!infusionSet.PassPre && prefix.GetStatValue(parentStat, out statMod)) - // { - // val += statMod.offset; - // val *= statMod.multiplier; - // } - // if (infusionSet.PassSuf || !suffix.GetStatValue(parentStat, out statMod)) - // return; - // val += statMod.offset; - // val *= statMod.multiplier; - } - } - - public static void ApparelScoreRaw_PawnStatsHandlers(Apparel apparel, StatDef statPriority, ref float val) - { - InfusionSet inf; - if (apparel.TryGetInfusions(out inf)) - { - Def prefix = inf.prefix; - Def suffix = inf.suffix; - - float statInfusedPrefix = 0f; - float statInfusedSuffix = 0f; - - if (prefix != null && prefix.TryGetStatValue(statPriority, out StatMod mod)) - { - statInfusedPrefix += mod.offset; - statInfusedPrefix += mod.multiplier - 1; - } - - if (suffix != null && suffix.TryGetStatValue(statPriority, out mod)) - { - statInfusedSuffix += mod.offset; - statInfusedSuffix += mod.multiplier - 1; - } - - val += statInfusedPrefix + statInfusedSuffix; - } - } - - public static void Ignored_WTHandlers(ref List allApparelStats) - { - // add all stat modifiers from all infusions - foreach (KeyValuePair mod in DefDatabase.AllDefsListForReading.SelectMany( - infusion => infusion.stats)) - { - if (!allApparelStats.Contains(mod.Key)) - { - allApparelStats.Add(mod.Key); - } - } - } - } -} \ No newline at end of file diff --git a/Source/Outfitter/JobGiver_OutfitterOptimizeApparel.cs b/Source/Outfitter/JobGiver_OutfitterOptimizeApparel.cs index fb14e82..dae7364 100644 --- a/Source/Outfitter/JobGiver_OutfitterOptimizeApparel.cs +++ b/Source/Outfitter/JobGiver_OutfitterOptimizeApparel.cs @@ -1,11 +1,15 @@ namespace Outfitter { - using JetBrains.Annotations; - using RimWorld; using System.Collections.Generic; using System.Linq; using System.Text; + + using JetBrains.Annotations; + + using RimWorld; + using UnityEngine; + using Verse; using Verse.AI; @@ -23,6 +27,15 @@ public static class JobGiver_OutfitterOptimizeApparel private static Apparel lastItem; + public static void SetNextOptimizeTick([NotNull] Pawn pawn) + { + pawn.mindState.nextApparelOptimizeTick = Find.TickManager.TicksGame + + Random.Range( + ApparelOptimizeCheckIntervalMin, + ApparelOptimizeCheckIntervalMax); + + // pawn.GetApparelStatCache().recentApparel.Clear(); + } // private static NeededWarmth neededWarmth; public static bool TryGiveJob_Prefix(ref Job __result, Pawn pawn) @@ -30,7 +43,9 @@ public static bool TryGiveJob_Prefix(ref Job __result, Pawn pawn) __result = null; if (pawn.outfits == null) { - Log.ErrorOnce(pawn + " tried to run JobGiver_OutfitterOptimizeApparel without an OutfitTracker", 5643897); + Log.ErrorOnce( + pawn + " tried to run JobGiver_OutfitterOptimizeApparel without an OutfitTracker", + 5643897); return false; } @@ -77,6 +92,7 @@ public static bool TryGiveJob_Prefix(ref Job __result, Pawn pawn) pawn.GetApparelStatCache().ToDropList[ap].mindState.Notify_OutfitChanged(); pawn.GetApparelStatCache().ToDropList.Remove(ap); } + return false; } } @@ -115,9 +131,8 @@ public static bool TryGiveJob_Prefix(ref Job __result, Pawn pawn) // not very elegant but working // if (pawn.GetApparelStatCache().recentApparel.Contains(apparel)) // { - // gain *= 0.01f; + // gain *= 0.01f; // } - if (DebugViewSettings.debugApparelOptimize) { debugSb.AppendLine(apparel.LabelCap + ": " + gain.ToString("F2")); @@ -144,15 +159,15 @@ public static bool TryGiveJob_Prefix(ref Job __result, Pawn pawn) } // New stuff - if (false) { - var list2 = pawn.Map.mapPawns.FreeColonistsSpawned.Where(x => x.IsColonistPlayerControlled); + IEnumerable list2 = pawn.Map.mapPawns.FreeColonistsSpawned.Where(x => x.IsColonistPlayerControlled); foreach (Apparel ap in wornApparel) { foreach (Pawn otherPawn in list2) { - foreach (Apparel otherAp in otherPawn.apparel.WornApparel.Where(x => !ApparelUtility.CanWearTogether(ap.def, x.def, pawn.RaceProps.body))) + foreach (Apparel otherAp in otherPawn.apparel.WornApparel.Where( + x => !ApparelUtility.CanWearTogether(ap.def, x.def, pawn.RaceProps.body))) { float gain = pawn.ApparelScoreGain(otherAp); float otherGain = otherPawn.ApparelScoreGain(ap); @@ -183,21 +198,10 @@ public static bool TryGiveJob_Prefix(ref Job __result, Pawn pawn) // foreach (Apparel apparel in wornApparel) // { - // pawn.GetApparelStatCache().recentApparel.Add(apparel); + // pawn.GetApparelStatCache().recentApparel.Add(apparel); // } - __result = new Job(JobDefOf.Wear, thing); return false; } - - public static void SetNextOptimizeTick([NotNull] Pawn pawn) - { - pawn.mindState.nextApparelOptimizeTick = Find.TickManager.TicksGame - + Random.Range( - ApparelOptimizeCheckIntervalMin, - ApparelOptimizeCheckIntervalMax); - // pawn.GetApparelStatCache().recentApparel.Clear(); - - } } } \ No newline at end of file diff --git a/Source/Outfitter/Optional/Harmony_DDWorkTab.cs b/Source/Outfitter/Optional/Harmony_DDWorkTab.cs index 499e19e..15a4a59 100644 --- a/Source/Outfitter/Optional/Harmony_DDWorkTab.cs +++ b/Source/Outfitter/Optional/Harmony_DDWorkTab.cs @@ -9,12 +9,8 @@ using Harmony; - using RimWorld; - using Verse; - using Extensions = Outfitter.Extensions; - // Blatantly stolen from "Psychology" [StaticConstructorOnStartup] internal static class Harmony_DDWorkTab @@ -26,14 +22,12 @@ static Harmony_DDWorkTab() { ((Action)(() => { - if (AccessTools.Method( - typeof(PawnSurface), - nameof(PawnSurface.EnableWorkType)) != null) + if (AccessTools.Method(typeof(PawnSurface), nameof(PawnSurface.EnableWorkType)) != null) { - harmony.Patch( - AccessTools.Method(typeof(PawnSurface), "UpdatePawnPriorities"), - null, - new HarmonyMethod(typeof(Harmony_DDWorkTab), nameof(UpdatePriorities))); + harmony.Patch( + AccessTools.Method(typeof(PawnSurface), "UpdatePawnPriorities"), + null, + new HarmonyMethod(typeof(Harmony_DDWorkTab), nameof(UpdatePriorities))); harmony.Patch( AccessTools.Method(typeof(ApparelStatsHelper), nameof(Extensions.GetWorkPriority)), @@ -66,27 +60,33 @@ static Harmony_DDWorkTab() } } - private static void UpdatePriorities(PawnSurface __instance) - { - __instance.pawn.GetSaveablePawn().forceStatUpdate = true; - } - private static bool GetWorkPriorityDD(Pawn pawn, WorkTypeDef workType, ref int __result) { __result = 20; - var GetManager = Current.Game.GetComponent(); + SurfaceManager GetManager = Current.Game.GetComponent(); PawnSurface surface = GetManager.GetPawnSurface(pawn); - var childrenFieldInfo = typeof(PawnSurface).GetField("children", BindingFlags.NonPublic | BindingFlags.Instance); + FieldInfo childrenFieldInfo = + typeof(PawnSurface).GetField("children", BindingFlags.NonPublic | BindingFlags.Instance); List children = (List)childrenFieldInfo?.GetValue(surface); if (children.NullOrEmpty()) { return true; } - List ignoreList = new List() { "Firefighter", "Patient", "PatientBedRest", "Flicker", "HaulingUrgent", "FinishingOff" }; - List filtered = children.Where(x => !x.Disabled && !ignoreList.Contains(x.Def.defName)).ToList(); + + List ignoreList = new List + { + "Firefighter", + "Patient", + "PatientBedRest", + "Flicker", + "HaulingUrgent", + "FinishingOff" + }; + List filtered = children.Where(x => !x.Disabled && !ignoreList.Contains(x.Def.defName)) + .ToList(); for (int i = 0; i < filtered.Count; i++) { @@ -96,11 +96,18 @@ private static bool GetWorkPriorityDD(Pawn pawn, WorkTypeDef workType, ref int _ { continue; } + int priority = i + 1; __result = priority; break; } + return false; } + + private static void UpdatePriorities(PawnSurface __instance) + { + __instance.pawn.GetSaveablePawn().forceStatUpdate = true; + } } } \ No newline at end of file diff --git a/Source/Outfitter/Outfitter.csproj b/Source/Outfitter/Outfitter.csproj index 6d50eb6..04c57ce 100644 --- a/Source/Outfitter/Outfitter.csproj +++ b/Source/Outfitter/Outfitter.csproj @@ -70,9 +70,7 @@ - - - + @@ -87,7 +85,6 @@ - diff --git a/Source/Outfitter/Saveables/Saveable_Pawn.cs b/Source/Outfitter/Saveables/Saveable_Pawn.cs index cc0036f..87769c3 100644 --- a/Source/Outfitter/Saveables/Saveable_Pawn.cs +++ b/Source/Outfitter/Saveables/Saveable_Pawn.cs @@ -4,12 +4,8 @@ using Verse; - public partial class SaveablePawn : IExposable + public class SaveablePawn : IExposable { - private bool addIndividualStats = true; - - private bool addWorkStats = true; - public List ApparelStats = new List(); public bool armorOnly = false; @@ -17,8 +13,7 @@ public partial class SaveablePawn : IExposable public bool AutoEquipWeapon; // public FloatRange RealComfyTemperatures; - public bool forceStatUpdate = false; - + public bool forceStatUpdate; public MainJob mainJob; // Exposed members @@ -32,28 +27,39 @@ public partial class SaveablePawn : IExposable public FloatRange Temperatureweight; - public bool AddWorkStats + private bool addIndividualStats = true; + private bool addPersonalStats = true; + + private bool addWorkStats = true; + + public bool AddIndividualStats { - get + get => this.addIndividualStats; + set { - return addWorkStats; + this.addIndividualStats = value; + this.forceStatUpdate = true; } + } + public bool AddPersonalStats + { + get => this.addPersonalStats; set { - addWorkStats = value; + this.addPersonalStats = value; this.forceStatUpdate = true; } } - public bool AddIndividualStats + public bool AddWorkStats { - get => this.addIndividualStats; + get => this.addWorkStats; + set { - this.addIndividualStats = value; + this.addWorkStats = value; this.forceStatUpdate = true; } - } // public SaveablePawn(Pawn pawn) @@ -76,6 +82,7 @@ public void ExposeData() Scribe_Collections.Look(ref this.ApparelStats, "WeaponStats", LookMode.Deep); Scribe_Values.Look(ref this.addWorkStats, "AddWorkStats", true); Scribe_Values.Look(ref this.addIndividualStats, "AddIndividualStats", true); + Scribe_Values.Look(ref this.addPersonalStats, "addPersonalStats", true); Scribe_Values.Look(ref this.mainJob, "mainJob"); } } diff --git a/Source/Outfitter/StatDefOf2.cs b/Source/Outfitter/StatDefOf2.cs index 5ad01de..015f199 100644 --- a/Source/Outfitter/StatDefOf2.cs +++ b/Source/Outfitter/StatDefOf2.cs @@ -20,7 +20,6 @@ public static class StatDefOf2 public static StatDef MedicalOperationSpeed; - public static StatDef MeleeDPS; public static StatDef SculptingSpeed; diff --git a/Source/Outfitter/StatPriority.cs b/Source/Outfitter/StatPriority.cs index 71f619a..451cf31 100644 --- a/Source/Outfitter/StatPriority.cs +++ b/Source/Outfitter/StatPriority.cs @@ -14,7 +14,6 @@ namespace Outfitter using Verse; - public class StatPriority { public StatPriority(StatDef stat, float priority, StatAssignment assignment = StatAssignment.Automatic) @@ -69,5 +68,4 @@ public void Reset(Pawn pawn) } // ReSharper disable once CollectionNeverUpdated.Global - } \ No newline at end of file diff --git a/Source/Outfitter/Window/Dialog_PawnApparelComparer.cs b/Source/Outfitter/Window/Dialog_PawnApparelComparer.cs index 442dc56..073b67d 100644 --- a/Source/Outfitter/Window/Dialog_PawnApparelComparer.cs +++ b/Source/Outfitter/Window/Dialog_PawnApparelComparer.cs @@ -1,10 +1,14 @@ namespace Outfitter.Window { - using JetBrains.Annotations; - using RimWorld; using System.Collections.Generic; using System.Linq; + + using JetBrains.Annotations; + + using RimWorld; + using UnityEngine; + using Verse; public class Dialog_PawnApparelComparer : Window @@ -15,6 +19,10 @@ public class Dialog_PawnApparelComparer : Window [NotNull] private readonly Pawn pawn; + private List _calculatedApparelItems; + + private List _calculatedApparelScore; + private Vector2 scrollPosition; public Dialog_PawnApparelComparer(Pawn p, Apparel apparel) @@ -29,9 +37,19 @@ public Dialog_PawnApparelComparer(Pawn p, Apparel apparel) public override Vector2 InitialSize => new Vector2(500f, 700f); + public void DIALOG_CalculateApparelScoreGain(Pawn pawn, Apparel apparel, out float gain) + { + if (this._calculatedApparelItems == null) + { + this.DIALOG_InitializeCalculatedApparelScoresFromWornApparel(); + } + + gain = pawn.ApparelScoreGain(apparel); + } + public override void DoWindowContents(Rect windowRect) { - ApparelStatCache apparelStatCache = new ApparelStatCache(pawn.GetSaveablePawn()); + ApparelStatCache apparelStatCache = new ApparelStatCache(this.pawn.GetSaveablePawn()); List allApparels = new List( this.pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.Apparel).OfType()); foreach (Pawn pawn in PawnsFinder.AllMaps_FreeColonists.Where(x => x.Map == this.pawn.Map)) @@ -99,7 +117,7 @@ public override void DoWindowContents(Rect windowRect) allApparels = allApparels.OrderByDescending( i => { - DIALOG_CalculateApparelScoreGain(this.pawn, i, out float g); + this.DIALOG_CalculateApparelScoreGain(this.pawn, i, out float g); return g; }).ToList(); @@ -138,7 +156,7 @@ public override void DoWindowContents(Rect windowRect) } } - DIALOG_CalculateApparelScoreGain(this.pawn, currentAppel, out float gain); + this.DIALOG_CalculateApparelScoreGain(this.pawn, currentAppel, out float gain); string gainString = this.pawn.outfits.forcedHandler.AllowedToAutomaticallyDrop(currentAppel) ? gain.ToString("N5") : "No Allow"; @@ -170,23 +188,10 @@ public override void DoWindowContents(Rect windowRect) Text.Anchor = TextAnchor.UpperLeft; GUI.EndGroup(); } - private List _calculatedApparelItems; - - private List _calculatedApparelScore; - - public void DIALOG_CalculateApparelScoreGain(Pawn pawn, Apparel apparel, out float gain) - { - if (this._calculatedApparelItems == null) - { - this.DIALOG_InitializeCalculatedApparelScoresFromWornApparel(); - } - - gain = pawn.ApparelScoreGain(apparel); - } private void DIALOG_InitializeCalculatedApparelScoresFromWornApparel() { - var conf = this.pawn.GetApparelStatCache(); + ApparelStatCache conf = this.pawn.GetApparelStatCache(); this._calculatedApparelItems = new List(); this._calculatedApparelScore = new List(); foreach (Apparel apparel in this.pawn.apparel.WornApparel) diff --git a/Source/Outfitter/Window/ITab_Pawn_Outfitter.cs b/Source/Outfitter/Window/ITab_Pawn_Outfitter.cs index 743bcab..d2c3fff 100644 --- a/Source/Outfitter/Window/ITab_Pawn_Outfitter.cs +++ b/Source/Outfitter/Window/ITab_Pawn_Outfitter.cs @@ -173,22 +173,25 @@ protected override void FillTab() } // Status checkboxes - Rect rectCheckboxes = new Rect(rectStatus.x, rectStatus.yMax + Margin, rectStatus.width, 48f); + Rect rectCheckboxes = new Rect(rectStatus.x, rectStatus.yMax + Margin, rectStatus.width, 72f); Rect check1 = new Rect(rectCheckboxes.x, rectCheckboxes.y, rectCheckboxes.width, 24f); Rect check2 = new Rect(rectCheckboxes.x, check1.yMax, rectCheckboxes.width, 24f); + Rect check3 = new Rect(rectCheckboxes.x, check2.yMax, rectCheckboxes.width, 24f); bool pawnSaveAddWorkStats = pawnSave.AddWorkStats; bool pawnSaveAddIndividualStats = pawnSave.AddIndividualStats; - DrawCheckBoxArea(check1, "AddWorkStats".Translate(), ref pawnSaveAddWorkStats); - DrawCheckBoxArea(check2, "AddIndividualStats".Translate(), ref pawnSaveAddIndividualStats); + bool pawnSaveAddPersonalStats = pawnSave.AddPersonalStats; + Widgets.CheckboxLabeled(check1, "AddWorkStats".Translate(), ref pawnSaveAddWorkStats); + Widgets.CheckboxLabeled(check2, "AddIndividualStats".Translate(), ref pawnSaveAddIndividualStats); + Widgets.CheckboxLabeled(check3, "AddPersonalStats".Translate(), ref pawnSaveAddPersonalStats); - if (pawnSaveAddWorkStats != pawnSave.AddWorkStats) + if (GUI.changed) { pawnSave.AddWorkStats = pawnSaveAddWorkStats; - } - if (pawnSaveAddIndividualStats != pawnSave.AddIndividualStats) - { + pawnSave.AddIndividualStats = pawnSaveAddIndividualStats; + + pawnSave.AddPersonalStats = pawnSaveAddPersonalStats; } // main canvas @@ -208,11 +211,6 @@ protected override void FillTab() Text.Anchor = TextAnchor.UpperLeft; } - private static void DrawCheckBoxArea(Rect rect, string name, ref bool stat) - { - Widgets.CheckboxLabeled(rect, name, ref stat); - } - private void DrawApparelList() { // main canvas @@ -345,7 +343,7 @@ private void DrawApparelStats(Vector2 cur, Rect canvas) Text.Font = GameFont.Tiny; GUI.color = Color.grey; Text.Anchor = TextAnchor.LowerLeft; - Widgets.Label(legendRect,"-"+ ApparelStatCache.MaxValue.ToString("N1")); + Widgets.Label(legendRect, "-" + ApparelStatCache.MaxValue.ToString("N1")); Text.Anchor = TextAnchor.LowerRight; Widgets.Label(legendRect, ApparelStatCache.MaxValue.ToString("N1")); Text.Anchor = TextAnchor.UpperLeft; diff --git a/Source/Outfitter/Window/Window_Pawn_ApparelDetail.cs b/Source/Outfitter/Window/Window_Pawn_ApparelDetail.cs index f374df2..f92fe09 100644 --- a/Source/Outfitter/Window/Window_Pawn_ApparelDetail.cs +++ b/Source/Outfitter/Window/Window_Pawn_ApparelDetail.cs @@ -18,24 +18,30 @@ namespace Outfitter public class Window_Pawn_ApparelDetail : Verse.Window { + private const float baseValue = 85f; + private readonly Apparel apparel; private readonly GUIStyle fontBold = new GUIStyle - { - fontStyle = FontStyle.Bold, - normal = { textColor = Color.white }, - padding = new RectOffset(0, 0, 12, 6) - }; + { + fontStyle = FontStyle.Bold, + normal = { + textColor = Color.white + }, + padding = new RectOffset(0, 0, 12, 6) + }; private readonly GUIStyle headline = new GUIStyle - { - fontStyle = FontStyle.Bold, - fontSize = 16, - normal = { textColor = Color.white }, - padding = new RectOffset(0, 0, 12, 6) - }; + { + fontStyle = FontStyle.Bold, + fontSize = 16, + normal = { + textColor = Color.white + }, + padding = new RectOffset(0, 0, 12, 6) + }; private readonly GUIStyle hoverBox = new GUIStyle { hover = { background = OutfitterTextures.BgColor } }; @@ -195,7 +201,6 @@ public override void DoWindowContents(Rect windowRect) if (infusedOffsets.Contains(statPriority.Stat)) { // float statInfused = StatCache.StatInfused(infusionSet, statPriority, ref dontcare); - ApparelStatCache.DoApparelScoreRaw_PawnStatsHandlers( this.apparel, statPriority.Stat, @@ -352,9 +357,14 @@ protected override void SetInitialSizeAndPosition() this.InitialSize.x, this.InitialSize.y).Rounded(); } - private const float baseValue = 85f; - private void DrawLine(string statDefLabelText, float statDefLabelWidth, string statDefValueText, string multiplierText, string finalValueText, GUIStyle style = null) + private void DrawLine( + string statDefLabelText, + float statDefLabelWidth, + string statDefValueText, + string multiplierText, + string finalValueText, + GUIStyle style = null) { if (style != null) { diff --git a/Source/Outfitter_Infused/OutfitterInfused.cs b/Source/Outfitter_Infused/OutfitterInfused.cs index fab9957..a348364 100644 --- a/Source/Outfitter_Infused/OutfitterInfused.cs +++ b/Source/Outfitter_Infused/OutfitterInfused.cs @@ -1,14 +1,16 @@ namespace OutfitterInfused { - using Infused; - using Outfitter; - using RimWorld; using System.Collections.Generic; using System.Linq; - using Harmony; + using Infused; + + using Outfitter; + + using RimWorld; using Verse; + using Def = Infused.Def; public class GameComponent_OutfitterInfused : GameComponent @@ -19,7 +21,6 @@ public GameComponent_OutfitterInfused(Game game) ApparelStatCache.ApparelScoreRaw_PawnStatsHandlers += ApparelScoreRaw_PawnStatsHandlers; ApparelStatCache.ApparelScoreRaw_FillInfusedStat += ApparelScoreRaw_FillInfusedStat; ApparelStatCache.Ignored_WTHandlers += Ignored_WTHandlers; - } private static void ApparelScoreRaw_FillInfusedStat(