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) {