Skip to content

Commit

Permalink
Merge pull request #94 from edbmods/develop
Browse files Browse the repository at this point in the history
Merge v0.16.1.2 to master
  • Loading branch information
edbmods committed Dec 22, 2016
2 parents b7e5619 + 4a0aab2 commit bd28421
Show file tree
Hide file tree
Showing 15 changed files with 371 additions and 181 deletions.
3 changes: 2 additions & 1 deletion EdBPrepareCarefully.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<OutputType>Library</OutputType>
<RootNamespace>EdB.PrepareCarefully</RootNamespace>
<AssemblyName>EdBPrepareCarefully</AssemblyName>
<ReleaseVersion>0.16.1.1</ReleaseVersion>
<ReleaseVersion>0.16.1.2</ReleaseVersion>
<UseMSBuildEngine>False</UseMSBuildEngine>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<ApplicationManifest>Dialog_Confirm.cs.manifest</ApplicationManifest>
Expand Down Expand Up @@ -108,6 +108,7 @@
<Compile Include="Source\GenStep_ScenParts.cs" />
<Compile Include="Source\Dialog_Confirm.cs" />
<Compile Include="Source\ThingCache.cs" />
<Compile Include="Source\BodyPartDictionary.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup />
Expand Down
6 changes: 3 additions & 3 deletions EdBPrepareCarefully.sln
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ Global
$0.TextStylePolicy = $2
$2.FileWidth = 120
$2.TabsToSpaces = False
$2.inheritsSet = null
$2.inheritsSet = VisualStudio
$2.inheritsScope = text/plain
$2.scope = application/xml
$2.scope = text/plain
$0.CSharpFormattingPolicy = $3
$3.IndentSwitchBody = True
$3.ElseNewLinePlacement = NewLine
Expand Down Expand Up @@ -194,6 +194,6 @@ Global
$29.IncludeStaticEntities = True
$0.VersionControlPolicy = $31
$31.inheritsSet = Mono
version = 0.16.1.1
version = 0.16.1.2
EndGlobalSection
EndGlobal
2 changes: 1 addition & 1 deletion Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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("0.16.1.1")]
[assembly: AssemblyVersion("0.16.1.2")]

// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.
Expand Down
2 changes: 1 addition & 1 deletion Resources/About/About.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,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 0.16.1.1]
[Version 0.16.1.2]
</description>
</ModMetaData>
7 changes: 7 additions & 0 deletions Resources/CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
_____________________________________________________________________________

Version 0.16.1.2
_____________________________________________________________________________

- Compatibility fixes to avoid some errors when running with other mods.

_____________________________________________________________________________

Version 0.16.1.1
_____________________________________________________________________________

Expand Down
184 changes: 184 additions & 0 deletions Source/BodyPartDictionary.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
using RimWorld;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
using Verse;
using Verse.Sound;

namespace EdB.PrepareCarefully
{
public class BodyPartDictionary
{
protected Dictionary<BodyPartDef, List<BodyPartRecord>> bodyPartListLookup = new Dictionary<BodyPartDef, List<BodyPartRecord>>();
protected List<RecipeDef> recipes = new List<RecipeDef>();
protected Dictionary<RecipeDef, List<BodyPartRecord>> recipeBodyParts = new Dictionary<RecipeDef, List<BodyPartRecord>>();
protected HashSet<BodyPartRecord> replaceableParts = new HashSet<BodyPartRecord>();
protected Dictionary<BodyPartRecord, HashSet<BodyPartRecord>> bodyPartAncestors = new Dictionary<BodyPartRecord, HashSet<BodyPartRecord>>();
protected List<BodyPartRecord> allBodyParts = new List<BodyPartRecord>();
protected List<BodyPartRecord> allOutsideBodyParts = new List<BodyPartRecord>();
protected List<BodyPartRecord> allSkinCoveredBodyParts = new List<BodyPartRecord>();
private BodyDef bodyDef;

public BodyDef BodyDef {
get {
return bodyDef;
}
}

public List<RecipeDef> ImplantRecipes {
get {
return recipes;
}
}

public IEnumerable<BodyPartRecord> AllBodyParts {
get { return allBodyParts; }
}

public IEnumerable<BodyPartRecord> AllOutsideBodyParts {
get { return allOutsideBodyParts; }
}

public IEnumerable<BodyPartRecord> AllSkinCoveredBodyParts {
get { return allSkinCoveredBodyParts; }
}

public BodyPartDictionary(ThingDef pawnThingDef)
{
this.bodyDef = pawnThingDef.race.body;

// Go through all of the body part records for the race. Each record is an individual body part, and you
// will see more than one instance of each record. For example, you'll see 12 "Rib" records, one for each
// of the 12 rib bones. For each body part type (i.e. "Rib"), we store a list of each body part record
// in a dictionary, so that we can get a list of all records that match a given type/definition.
foreach (BodyPartRecord record in bodyDef.AllParts) {
List<BodyPartRecord> records;
if (!bodyPartListLookup.TryGetValue(record.def, out records)) {
records = new List<BodyPartRecord>();
bodyPartListLookup[record.def] = records;
}
records.Add(record);
AddAncestors(record);
}

// Find all recipes that replace a body part.
recipes.AddRange(pawnThingDef.recipes.Where((RecipeDef def) => {
if (def.addsHediff != null && def.appliedOnFixedBodyParts != null && def.appliedOnFixedBodyParts.Count > 0) {
return true;
}
else {
return false;
}
}));

// De-dupe the list.
HashSet<RecipeDef> recipeSet = new HashSet<RecipeDef>();
foreach (var r in recipes) {
recipeSet.Add(r);
}
recipes = new List<RecipeDef>(recipeSet);

// Iterate the recipes. Populate a lookup with all of the body parts that apply to a given recipe.
foreach (var r in recipes) {

// Get the list of recipe body parts from the dictionary or create it if it doesn't exist.
List<BodyPartRecord> bodyPartRecords;
if (!recipeBodyParts.TryGetValue(r, out bodyPartRecords)) {
bodyPartRecords = new List<BodyPartRecord>();
recipeBodyParts.Add(r, bodyPartRecords);
}
// Add all of the body part records for that recipe to the list.
foreach (var bodyPartDef in r.appliedOnFixedBodyParts) {
if (bodyPartListLookup.ContainsKey(bodyPartDef)) {
List<BodyPartRecord> records = bodyPartListLookup[bodyPartDef];
bodyPartRecords.AddRange(records);
foreach (var record in records) {
replaceableParts.Add(record);
}
}
}
}

// Sort the recipes.
recipes.Sort((RecipeDef a, RecipeDef b) => {
return a.LabelCap.CompareTo(b.LabelCap);
});

// Classify body parts into all, outside and skin-covered lists.
foreach (BodyPartRecord record in bodyDef.AllParts) {
allBodyParts.Add(record);
if (record.depth == BodyPartDepth.Outside) {
allOutsideBodyParts.Add(record);
}
FieldInfo skinCoveredField = typeof(BodyPartDef).GetField("skinCovered", BindingFlags.Instance | BindingFlags.NonPublic);
Boolean value = (Boolean)skinCoveredField.GetValue(record.def);
if (value == true) {
allSkinCoveredBodyParts.Add(record);
}
}
}

public List<BodyPartRecord> PartsForRecipe(RecipeDef recipe)
{
return this.recipeBodyParts[recipe];
}

public IEnumerable<BodyPartRecord> PartAncestors(BodyPartRecord part)
{
return bodyPartAncestors[part];
}

public bool AncestorIsImplant(BodyPartRecord record, CustomPawn pawn)
{
foreach (BodyPartRecord ancestor in bodyPartAncestors[record]) {
if (pawn.IsImplantedPart(ancestor)) {
return true;
}
}
return false;
}

protected void AddAncestors(BodyPartRecord record)
{
if (bodyPartAncestors.ContainsKey(record)) {
return;
}
else {
bodyPartAncestors.Add(record, new HashSet<BodyPartRecord>());
}
for (BodyPartRecord parentRecord = record.parent; parentRecord != null; parentRecord = parentRecord.parent) {
bodyPartAncestors[record].Add(parentRecord);
}
}

// TODO: This is problematic for body parts that appear multiple times in a body (i.e. ribs).
// Calling this will return the first one that it finds. There's no distinguishing between multiple
// parts of the same type.
public BodyPartRecord FindReplaceableBodyPartByName(string name)
{
foreach (var record in replaceableParts) {
if (record.def.defName == name) {
return record;
}
}
return null;
}

public BodyPartRecord FirstBodyPartRecord(string bodyPartDefName)
{
foreach (BodyPartRecord record in bodyDef.AllParts) {
if (record.def.defName == bodyPartDefName) {
return record;
}
}
return null;
}

public BodyPartRecord FirstBodyPartRecord(BodyPartDef def)
{
return FirstBodyPartRecord(def.defName);
}
}
}
2 changes: 1 addition & 1 deletion Source/CostCalculator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ public void CalculatePawnCost(ColonistCostDetails cost, CustomPawn pawn)
foreach (Implant option in pawn.Implants) {

// Check if there are any ancestor parts that override the selection.
if (PrepareCarefully.Instance.HealthManager.ImplantManager.AncestorIsImplant(option.BodyPartRecord, pawn)) {
if (PrepareCarefully.Instance.HealthManager.ImplantManager.AncestorIsImplant(pawn, option.BodyPartRecord)) {
continue;
}

Expand Down

0 comments on commit bd28421

Please sign in to comment.