diff --git a/EdBPrepareCarefully.csproj b/EdBPrepareCarefully.csproj index 86f34b7..49e673d 100644 --- a/EdBPrepareCarefully.csproj +++ b/EdBPrepareCarefully.csproj @@ -216,7 +216,9 @@ - + + + diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index bb900ed..22d834a 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -17,7 +17,7 @@ // The form "{Major}.{Minor}.*" will automatically update the build and revision, // and "{Major}.{Minor}.{Build}.*" will update just the revision. -[assembly: AssemblyVersion("1.0.12")] +[assembly: AssemblyVersion("1.0.13")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. diff --git a/Resources/About/About.xml b/Resources/About/About.xml index 8d8aa6b..cd36dca 100644 --- a/Resources/About/About.xml +++ b/Resources/About/About.xml @@ -10,6 +10,6 @@ If you get a set of starting colonists that you like, save them as a preset so that you can start your game the same way next time. -[Version 1.0.12] +[Version 1.0.13] \ No newline at end of file diff --git a/Resources/About/Manifest.xml b/Resources/About/Manifest.xml new file mode 100644 index 0000000..656969c --- /dev/null +++ b/Resources/About/Manifest.xml @@ -0,0 +1,13 @@ + + + EdBPrepareCarefully + 1.0.13 + +
  • Core
  • +
  • HugsLib
  • +
  • JecsTools
  • +
    + false + https://github.com/edbmods/EdBPrepareCarefully/raw/master/Resources/About/Manifest.xml + https://github.com/edbmods/EdBPrepareCarefully/releases/latest +
    \ No newline at end of file diff --git a/Resources/CHANGELOG.txt b/Resources/CHANGELOG.txt index bc4d5e1..60cfca4 100644 --- a/Resources/CHANGELOG.txt +++ b/Resources/CHANGELOG.txt @@ -1,3 +1,16 @@ + _____________________________________________________________________________ + + Version 1.0.13 + _____________________________________________________________________________ + + - Bug-fix for item categories with multiple parent categories. + - Bug fix for choosing body parts for injuries that affect specific parts. + - Bug fix for races with no defined age generation curve. + - Updated the version of Harmony to 1.2.0.1. + - Added "manifest" file to support the Mod Manager mod. + - Ammunition equipment from Combat Extended is now classified under the + "Weapons" category. + _____________________________________________________________________________ Version 1.0.12 diff --git a/Source/Controller.cs b/Source/Controller.cs index 48ad881..e490d77 100644 --- a/Source/Controller.cs +++ b/Source/Controller.cs @@ -103,18 +103,6 @@ public void SavePreset(string name) { state.AddMessage("SavedAs".Translate(PrepareCarefully.Instance.Filename)); } - private Pawn ConvertPawn(CustomPawn customPawn) { - customPawn.Pawn.SetFactionDirect(Faction.OfPlayer); - if (customPawn.Type == CustomPawnType.Colonist) { - customPawn.Pawn.SetFactionDirect(Faction.OfPlayer); - } - if (customPawn.Pawn.workSettings == null) { - customPawn.Pawn.workSettings = new Pawn_WorkSettings(customPawn.Pawn); - } - customPawn.Pawn.workSettings.EnableAndInitialize(); - return customPawn.Pawn; - } - public void PrepareGame() { PrepareColonists(); PrepareWorldPawns(); diff --git a/Source/EquipmentDatabase.cs b/Source/EquipmentDatabase.cs index 4381569..84d07e0 100644 --- a/Source/EquipmentDatabase.cs +++ b/Source/EquipmentDatabase.cs @@ -124,7 +124,7 @@ protected void CountDefs() { protected void ProcessStuff() { for (int i = 0; i < LoadingProgress.stuffToProcessPerFrame; i++) { if (!LoadingProgress.enumerator.MoveNext()) { - Log.Message("Prepare Carefully loaded equipment database with " + LoadingProgress.stuffCount + " material(s)"); + Log.Message("Prepare Carefully :: Loaded equipment database with " + LoadingProgress.stuffCount + " material(s)"); NextPhase(); return; } @@ -138,7 +138,7 @@ protected void ProcessStuff() { protected void ProcessThings() { for (int i=0; i.AllDefs) { - try { - if (def != null) { - EquipmentType type = ClassifyThingDef(def); - if (type != null && type != TypeDiscard) { - AddThingDef(def, type); - } - } - } - catch (Exception e) { - Log.Warning("Prepare Carefully failed to classify thing definition while building equipment lists: " + def.defName); - Log.Message(" Exception: " + e.Message); - } - } - } - */ - private bool FoodTypeIsClassifiedAsFood(ThingDef def) { int foodTypes = (int)def.ingestible.foodType; if ((foodTypes & (int)FoodTypeFlags.Liquor) > 0) { @@ -242,10 +223,10 @@ public EquipmentType ClassifyThingDef(ThingDef def) { if (def.isUnfinishedThing) { return TypeDiscard; } - if (def.IsWithinCategory(ThingCategoryDefOf.Corpses)) { + if (BelongsToCategoryOrParentCategory(def, ThingCategoryDefOf.Corpses)) { return TypeDiscard; } - if (def.IsWithinCategory(ThingCategoryDefOf.Chunks)) { + if (BelongsToCategoryOrParentCategory(def, ThingCategoryDefOf.Chunks)) { return TypeDiscard; } if (def.IsBlueprint) { @@ -254,6 +235,9 @@ public EquipmentType ClassifyThingDef(ThingDef def) { if (def.IsFrame) { return TypeDiscard; } + if (BelongsToCategory(def, "Toy")) { + return TypeResources; + } if (def.weaponTags != null && def.weaponTags.Count > 0 && def.IsWeapon) { return TypeWeapons; } @@ -295,6 +279,10 @@ public EquipmentType ClassifyThingDef(ThingDef def) { } if (def.CountAsResource) { + // Ammunition should be counted under the weapons category + if (HasTradeTag(def, "CE_Ammo")) { + return TypeWeapons; + } if (def.IsShell) { return TypeWeapons; } @@ -334,6 +322,24 @@ public EquipmentType ClassifyThingDef(ThingDef def) { return null; } + private HashSet categoryLookup = new HashSet(); + // A duplicate of ThingDef.IsWithinCategory(), but with checks to prevent infinite recursion. + public bool BelongsToCategoryOrParentCategory(ThingDef def, ThingCategoryDef categoryDef) { + if (categoryDef == null || def.thingCategories == null) { + return false; + } + categoryLookup.Clear(); + for (int i = 0; i < def.thingCategories.Count; i++) { + for (ThingCategoryDef thingCategoryDef = def.thingCategories[i]; thingCategoryDef != null && !categoryLookup.Contains(thingCategoryDef.defName); thingCategoryDef = thingCategoryDef.parent) { + categoryLookup.Add(thingCategoryDef.defName); + if (thingCategoryDef.defName == categoryDef.defName) { + return true; + } + } + } + return false; + } + public bool BelongsToCategory(ThingDef def, ThingCategoryDef categoryDef) { if (categoryDef == null || def.thingCategories == null) { return false; @@ -379,6 +385,15 @@ public bool BelongsToCategory(ThingDef def, string categoryName) { }) != null; } + public bool HasTradeTag(ThingDef def, string tradeTag) { + if (tradeTag.NullOrEmpty() || def.tradeTags == null) { + return false; + } + return def.tradeTags.FirstOrDefault(t => { + return tradeTag == t; + }) != null; + } + public IEnumerable AllEquipmentOfType(EquipmentType type) { return entries.Values.Where((EquipmentRecord e) => { return e.type == type; diff --git a/Source/OptionsHealth.cs b/Source/OptionsHealth.cs index 1a6c7c4..dd65916 100644 --- a/Source/OptionsHealth.cs +++ b/Source/OptionsHealth.cs @@ -100,8 +100,7 @@ public UniqueBodyPart FindBodyPartByName(string name, int index) { return null; } public UniqueBodyPart FindBodyPartsForRecord(BodyPartRecord record) { - UniqueBodyPart result; - if (bodyPartRecordLookup.TryGetValue(record, out result)) { + if (bodyPartRecordLookup.TryGetValue(record, out UniqueBodyPart result)) { return result; } else { @@ -109,8 +108,7 @@ public UniqueBodyPart FindBodyPartsForRecord(BodyPartRecord record) { } } public List FindBodyPartsForDef(BodyPartDef def) { - List result; - if (bodyPartDefLookup.TryGetValue(def, out result)) { + if (bodyPartDefLookup.TryGetValue(def, out List result)) { return result; } else { @@ -187,7 +185,16 @@ public List InjuryOptions { } } public IEnumerable BodyPartsForInjury(InjuryOption option) { - return SkinCoveredBodyParts.Select((UniqueBodyPart p) => { return p.Record; }); + if (option.ValidParts == null || option.ValidParts.Count == 0) { + return SkinCoveredBodyParts.Select((UniqueBodyPart p) => { return p.Record; }); + } + else { + List records = new List(); + foreach (var part in option.ValidParts) { + records.AddRange(FindBodyPartsForDef(part).ConvertAll(p => p.Record)); + } + return records; + } } } } diff --git a/Source/PanelHealth.cs b/Source/PanelHealth.cs index 88a6dcb..b07609d 100644 --- a/Source/PanelHealth.cs +++ b/Source/PanelHealth.cs @@ -246,7 +246,7 @@ public void DrawAddButton() { }, ConfirmValidation = () => { if (selectedSeverity == null) { - return "EdB.PC.Error.MustSelectSeverity"; + return "EdB.PC.Panel.Health.Error.MustSelectSeverity"; } else { return null; @@ -314,6 +314,9 @@ public void DrawAddButton() { if (option.ValidParts == null && !option.WholeBody) { bodyPartSelectionRequired = true; } + else if (option.ValidParts != null && option.ValidParts.Count > 0) { + bodyPartSelectionRequired = true; + } else { bodyPartSelectionRequired = false; } @@ -333,10 +336,18 @@ public void DrawAddButton() { ResetSeverityOptions(selectedInjury); if (bodyPartSelectionRequired) { bodyPartDialog.Options = healthOptions.BodyPartsForInjury(selectedInjury); - ResetDisabledBodyParts(bodyPartDialog.Options, customPawn); - Find.WindowStack.Add(bodyPartDialog); + int count = bodyPartDialog.Options.Count(); + if (count > 1) { + ResetDisabledBodyParts(bodyPartDialog.Options, customPawn); + Find.WindowStack.Add(bodyPartDialog); + return; + } + else if (count == 1) { + selectedBodyPart = bodyPartDialog.Options.First(); + } } - else if (severityOptions.Count > 1) { + + if (severityOptions.Count > 1) { Find.WindowStack.Add(severityDialog); } else { diff --git a/Source/ProviderAgeLimits.cs b/Source/ProviderAgeLimits.cs index 59a2ade..98913f6 100644 --- a/Source/ProviderAgeLimits.cs +++ b/Source/ProviderAgeLimits.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using System.Text; using UnityEngine; using Verse; @@ -8,13 +9,29 @@ namespace EdB.PrepareCarefully { public class ProviderAgeLimits { + public static readonly int DEFAULT_MIN_AGE = 15; + public static readonly int DEFAULT_MAX_AGE = 100; private Dictionary minAgeLookup = new Dictionary(); private Dictionary maxAgeLookup = new Dictionary(); public int MinAgeForPawn(Pawn pawn) { if (!minAgeLookup.TryGetValue(pawn.def, out int age)) { - CurvePoint point = pawn.def.race.ageGenerationCurve.First(); - age = (int)point.x; + SimpleCurve simpleCurve = pawn.def.race.ageGenerationCurve; + if (simpleCurve == null) { + Log.Warning("Prepare Carefully :: No age generation curve defined for " + pawn.def.defName + ". Using default age generation curve to determine minimum age."); + simpleCurve = DefaultAgeGenerationCurve; + if (simpleCurve == null) { + Log.Warning("Prepare Carefully :: Failed to get default age generation curve. Using default minimum age of " + DEFAULT_MIN_AGE); + age = DEFAULT_MIN_AGE; + } + else { + age = Mathf.CeilToInt(pawn.def.race.lifeExpectancy * simpleCurve.First().x); + } + } + else { + CurvePoint point = simpleCurve.First(); + age = (int)point.x; + } minAgeLookup.Add(pawn.def, age); } return age; @@ -22,11 +39,37 @@ public int MinAgeForPawn(Pawn pawn) { public int MaxAgeForPawn(Pawn pawn) { if (!maxAgeLookup.TryGetValue(pawn.def, out int age)) { - CurvePoint point = pawn.def.race.ageGenerationCurve.Last(); - age = (int)(point.x * 1.2f); + SimpleCurve simpleCurve = pawn.def.race.ageGenerationCurve; + if (simpleCurve == null) { + Log.Warning("Prepare Carefully :: No age generation curve defined for " + pawn.def.defName + ". Using default age generation curve to determine maximum age."); + simpleCurve = DefaultAgeGenerationCurve; + if (simpleCurve == null) { + Log.Warning("Prepare Carefully :: Failed to get default age generation curve. Using default maximum age of " + DEFAULT_MAX_AGE); + age = DEFAULT_MAX_AGE; + } + else { + age = Mathf.CeilToInt(pawn.def.race.lifeExpectancy * simpleCurve.Last().x); + } + } + else { + CurvePoint point = simpleCurve.Last(); + age = (int)(point.x * 1.2f); + } maxAgeLookup.Add(pawn.def, age); } return age; } + + protected SimpleCurve DefaultAgeGenerationCurve { + get { + FieldInfo field = ReflectionUtil.GetNonPublicStaticField(typeof(Verse.PawnGenerator), "DefaultAgeGenerationCurve"); + if (field != null) { + return field.GetValue(null) as SimpleCurve; + } + else { + return null; + } + } + } } } diff --git a/Source/ProviderHealthOptions.cs b/Source/ProviderHealthOptions.cs index 7428da0..cbb6f96 100644 --- a/Source/ProviderHealthOptions.cs +++ b/Source/ProviderHealthOptions.cs @@ -110,7 +110,8 @@ protected void InitializeHediffGiverInjuries(OptionsHealth options, HediffGiver if (giver.partsToAffect != null && !giver.canAffectAnyLivePart) { List validParts = new List(); foreach (var def in giver.partsToAffect) { - if (options.FindBodyPartsForDef(def) != null) { + List parts = options.FindBodyPartsForDef(def); + if (parts != null) { validParts.Add(def); } } @@ -146,7 +147,7 @@ protected void InitializeInjuryOptions(OptionsHealth options, ThingDef pawnThing } } } - // Go though all of the chemical defs, looking for hediff givers. + // Go through all of the chemical defs, looking for hediff givers. foreach (var chemicalDef in DefDatabase.AllDefs) { if (chemicalDef.onGeneratedAddictedEvents != null) { foreach (var giver in chemicalDef.onGeneratedAddictedEvents) {