Last active
August 12, 2019 11:42
-
-
Save lbmaian/9dd0739c078105792e23c85a2e5cde36 to your computer and use it in GitHub Desktop.
Rimworld generic backstory def loading
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Reflection; | |
using System.Xml; | |
using UnityEngine; | |
using Verse; | |
namespace RimWorld | |
{ | |
// Allows loading of backstories defined via <BackstoryDef> with optional <defName> (and optional <bodyTypeMale>/<bodyTypeFemale>) | |
public class BackstoryDef : Def | |
{ | |
private Backstory backstory; | |
public void LoadDataFromXmlCustom(XmlNode xmlRoot) | |
{ | |
XmlNode defNameNode = xmlRoot.SelectSingleNode("defName"); | |
if (defNameNode != null) | |
{ | |
defName = defNameNode.InnerText; | |
xmlRoot.RemoveChild(defNameNode); // need to remove, since Backstory doesn't have a defName field | |
} | |
backstory = DirectXmlToObject.ObjectFromXml<Backstory>(xmlRoot, doPostLoad: true); | |
if (defName == Def.DefaultDefName && backstory != null) | |
{ | |
// The defName needs to default to backstory.identifier, but that is only calculated in Backstory.ResolveReferences(). | |
// Furthermore, defName cannot be Def.DefaultDefName, or else DefDatabase.AddAllInMods() will coerce it with a warning before ResolveReferences() is called. | |
// Copying the backstory.identifier calculation logic here, which doesn't depend on any references. | |
int num = Mathf.Abs(GenText.StableStringHash(backstory.baseDesc) % 100); | |
string s = backstory.title.Replace('-', ' '); | |
s = GenText.CapitalizedNoSpaces(s); | |
defName = GenText.RemoveNonAlphanumeric(s) + num.ToString(); | |
} | |
} | |
public override void ResolveReferences() | |
{ | |
if (backstory != null) | |
{ | |
if (backstory.slot == BackstorySlot.Adulthood && GetPrivateStringFieldValue(backstory, "bodyTypeGlobal").NullOrEmpty()) | |
{ | |
SetPrivateStringFieldValueIfNull(backstory, "bodyTypeMale", DefDatabase<BodyTypeDef>.GetNamedSilentFail("Male")?.defName ?? "Male"); | |
SetPrivateStringFieldValueIfNull(backstory, "bodyTypeFemale", DefDatabase<BodyTypeDef>.GetNamedSilentFail("Female")?.defName ?? "Female"); | |
} | |
backstory.ResolveReferences(); | |
backstory.identifier = defName; | |
BackstoryDatabase.AddBackstory(backstory); // like BackstoryDatabase.ReloadAllBackstories, add even if there are any config errors | |
//Log.Message("Added custom backstory: " + defName); | |
} | |
} | |
private static string GetPrivateStringFieldValue<T>(T obj, String fieldName) | |
{ | |
return (string)typeof(T).GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj); | |
} | |
private static void SetPrivateStringFieldValueIfNull<T>(T obj, String fieldName, object value) | |
{ | |
FieldInfo field = typeof(T).GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic); | |
if (((string)field.GetValue(obj)).NullOrEmpty()) | |
field.SetValue(obj, value); | |
} | |
public override IEnumerable<string> ConfigErrors() | |
{ | |
foreach (string error in base.ConfigErrors()) | |
yield return error; | |
if (backstory != null) | |
foreach (string error in backstory.ConfigErrors(ignoreNoSpawnCategories: false)) | |
yield return error; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment