From 4b541f66256ef545bfb827d9349124be16cd9b5c Mon Sep 17 00:00:00 2001 From: XeonSquared Date: Sun, 15 Jan 2023 10:55:51 +1100 Subject: [PATCH] import source --- .gitignore | 1 + 1.4/Defs/GeneDefs/LitteredBirths.xml | 15 ++ 1.4/Defs/LetterDefs/AnotherBaby.xml | 11 ++ 1.4/Languages/English/Keyed/SettingsKeys.xml | 8 + .../Icons/Genes/Gene_LitteredBirths.png | Bin 0 -> 9576 bytes About/About.xml | 25 +++ LitterBiotech.sln | 22 +++ Source/DefOf/GeneDefOf.cs | 11 ++ Source/DefOf/HediffDefOf.cs | 14 ++ Source/DefOf/LetterDefOf.cs | 11 ++ Source/Hediffs/Infatuo.cs | 57 +++++++ Source/Helpers/LBTLogger.cs | 35 ++++ Source/Helpers/LaborState.cs | 28 +++ Source/LitterBiotech.cs | 161 ++++++++++++++++++ Source/LitterBiotech.csproj | 70 ++++++++ Source/Properties/AssemblyInfo.cs | 36 ++++ Source/Settings/LBTSettings.cs | 54 ++++++ 17 files changed, 559 insertions(+) create mode 100644 1.4/Defs/GeneDefs/LitteredBirths.xml create mode 100644 1.4/Defs/LetterDefs/AnotherBaby.xml create mode 100644 1.4/Languages/English/Keyed/SettingsKeys.xml create mode 100644 1.4/Textures/Icons/Genes/Gene_LitteredBirths.png create mode 100644 About/About.xml create mode 100644 LitterBiotech.sln create mode 100644 Source/DefOf/GeneDefOf.cs create mode 100644 Source/DefOf/HediffDefOf.cs create mode 100644 Source/DefOf/LetterDefOf.cs create mode 100644 Source/Hediffs/Infatuo.cs create mode 100644 Source/Helpers/LBTLogger.cs create mode 100644 Source/Helpers/LaborState.cs create mode 100644 Source/LitterBiotech.cs create mode 100644 Source/LitterBiotech.csproj create mode 100644 Source/Properties/AssemblyInfo.cs create mode 100644 Source/Settings/LBTSettings.cs diff --git a/.gitignore b/.gitignore index 9e4e587..7dce504 100644 --- a/.gitignore +++ b/.gitignore @@ -259,3 +259,4 @@ __pycache__/ /1.4/Assemblies/HarmonyMod.dll /1.4/Assemblies/0MultiplayerAPI.dll /1.4/Assemblies/0Harmony.dll +/1.4/Assemblies/LitterBiotech.dll diff --git a/1.4/Defs/GeneDefs/LitteredBirths.xml b/1.4/Defs/GeneDefs/LitteredBirths.xml new file mode 100644 index 0000000..8f8e5a0 --- /dev/null +++ b/1.4/Defs/GeneDefs/LitteredBirths.xml @@ -0,0 +1,15 @@ + + + + + LitteredBirths + + Female carriers of this gene birth litters instead of just one baby, with a chance of having two to four babies per pregnancy. + Icons/Genes/Gene_LitteredBirths + + 110 + 1.25 + 0 + 1 + + diff --git a/1.4/Defs/LetterDefs/AnotherBaby.xml b/1.4/Defs/LetterDefs/AnotherBaby.xml new file mode 100644 index 0000000..d8f7c17 --- /dev/null +++ b/1.4/Defs/LetterDefs/AnotherBaby.xml @@ -0,0 +1,11 @@ + + + + AnotherBaby + (120, 176, 216) + (106, 179, 231) + 40 + LetterArrive_Good + MajorThreat + + \ No newline at end of file diff --git a/1.4/Languages/English/Keyed/SettingsKeys.xml b/1.4/Languages/English/Keyed/SettingsKeys.xml new file mode 100644 index 0000000..f5de00e --- /dev/null +++ b/1.4/Languages/English/Keyed/SettingsKeys.xml @@ -0,0 +1,8 @@ + + + Litter Biotech + Enable development logging + When enabled, this setting provides additional Litter Biotech related logging in the development mode log. + Disable "Regrets stealing lovin'" thought + By default, the limbic stimulator implant allows for pawns without the Rapist trait to steal lovin'. When this occurs, the non-rapist pawn will receive a -5 mood negative thought that stacks up to 3 times. When enabled, this setting disables generation of that thought. + \ No newline at end of file diff --git a/1.4/Textures/Icons/Genes/Gene_LitteredBirths.png b/1.4/Textures/Icons/Genes/Gene_LitteredBirths.png new file mode 100644 index 0000000000000000000000000000000000000000..5b5a09eaf5f2a1e5cafc2b942f6edb6fdea4e862 GIT binary patch literal 9576 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 + Litters for Biotech + leboeuf +leboeuf.litters + +
  • 1.4
  • +
    + + +
  • rim.job.world
  • +
    + +Litter Biotech is a small RimWorld: Biotech expansion for RimJobWorld. + +Features: + + • Biotech pregnancy compatible multibirth system, allowing + pawns to have random twins with a default 1-in-100 chance. + • Littered births gene, where pawns can have guaranteed + litters of multiple babies. + +For all feature requests and bugs/issues: + https://gitgud.io/leboeuf/litter-biotech/-/issues + + diff --git a/LitterBiotech.sln b/LitterBiotech.sln new file mode 100644 index 0000000..c6e2ef0 --- /dev/null +++ b/LitterBiotech.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31205.134 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LitterBiotech", "Source\LitterBiotech.csproj", "{D7D21B4A-1DA7-41D8-B202-C58CA8FA62AA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D7D21B4A-1DA7-41D8-B202-C58CA8FA62AA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D7D21B4A-1DA7-41D8-B202-C58CA8FA62AA}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {28CF9A73-5333-4EB3-BFCC-3FBEDDA19200} + EndGlobalSection +EndGlobal diff --git a/Source/DefOf/GeneDefOf.cs b/Source/DefOf/GeneDefOf.cs new file mode 100644 index 0000000..c5e2720 --- /dev/null +++ b/Source/DefOf/GeneDefOf.cs @@ -0,0 +1,11 @@ +using RimWorld; +using Verse; + +namespace LitterBiotech +{ + [RimWorld.DefOf] + public static class GeneDefOf + { + public static GeneDef LitteredBirths; + } +} \ No newline at end of file diff --git a/Source/DefOf/HediffDefOf.cs b/Source/DefOf/HediffDefOf.cs new file mode 100644 index 0000000..b1c4dfb --- /dev/null +++ b/Source/DefOf/HediffDefOf.cs @@ -0,0 +1,14 @@ +using RimWorld; +using Verse; + +namespace LitterBiotech +{ + [RimWorld.DefOf] + public static class HediffDefOf + { + // public static HediffDef Infatuo; + // public static HediffDef InfatuoCalibrating; + public static HediffDef OvaryAgitator; + public static HediffDef Bioscaffold; + } +} \ No newline at end of file diff --git a/Source/DefOf/LetterDefOf.cs b/Source/DefOf/LetterDefOf.cs new file mode 100644 index 0000000..d3f72e9 --- /dev/null +++ b/Source/DefOf/LetterDefOf.cs @@ -0,0 +1,11 @@ +using RimWorld; +using Verse; + +namespace LitterBiotech +{ + [RimWorld.DefOf] + public static class LetterDefOf + { + public static LetterDef AnotherBaby; + } +} diff --git a/Source/Hediffs/Infatuo.cs b/Source/Hediffs/Infatuo.cs new file mode 100644 index 0000000..d2aa986 --- /dev/null +++ b/Source/Hediffs/Infatuo.cs @@ -0,0 +1,57 @@ +// FOR ANYONE (THAT ISN"T ME (BOEUF)) THAT CARES +// ===================== +// This is an idea for an implant that I had that basically forces a pawn to romantically obsess about another pawn, but I'm taking a break from working on it +// because I'm too smoothbrain to work out relation defs and making custom relations, and the multibirth stuff was taking up my time as is +// If you want to mess with it, this code is here for shits and gigs - modify it, throw it out, make something new, idgaf + +/*using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LitterBiotech.Hediffs +{ + class Infatuo + { + public class PawnRelationWorker_InfatuoInfatuated : PawnRelationWorker + { + // BaseGenerationChanceFactor - should NEVER autogenerate on pawns (for now, anyway) + new public float BaseGenerationChanceFactor(Pawn generated, Pawn other, PawnGenerationRequest request) + { + return 0.0f; + } + + // CreateRelation - shouldn't be needed for now since we're not autogenerating infatuo relations, but may be used in future + public override void CreateRelation(Pawn generated, Pawn other, ref PawnGenerationRequest request) + { + return; + } + + // GenerationChance - should NEVER autogenerate on pawns (for now, anyway) + public override float GenerationChance(Pawn generated, Pawn other, PawnGenerationRequest request) + { + return 0.0f; + } + + public override bool InRelation(Pawn me, Pawn other) + { + return (me.health.hediffSet.GetFirstHediff().target == other); + } + } + + public class Hediff_Infatuo : Hediff + { + public Hediff_Infatuo(Pawn intTarget) + { + target = intTarget; + } + public Pawn target; + } + + public class Hediff_InfatuoCalibrating : Hediff + { + + } + } +}*/ diff --git a/Source/Helpers/LBTLogger.cs b/Source/Helpers/LBTLogger.cs new file mode 100644 index 0000000..9f03551 --- /dev/null +++ b/Source/Helpers/LBTLogger.cs @@ -0,0 +1,35 @@ +using Verse; + +namespace LitterBiotech.Helpers +{ + public static class LBTLogger + { + public static void Message(string message) + { + Log.Message("[INFO][LitterBT] - " + message); + } + + public static void Warning(string message) + { + Log.Message("[WARN][LitterBT] - " + message); + } + + public static void Error(string message) + { + Log.Message("[ ERR][LitterBT] - " + message); + } + + public static void MessageGroupHead(string message) + { + Log.Message("[INFO][LitterBT]╦═ " + message); + } + public static void MessageGroupBody(string message) + { + Log.Message("[INFO][LitterBT]╠═══ " + message); + } + public static void MessageGroupFoot(string message) + { + Log.Message("[INFO][LitterBT]╚═══ " + message); + } + } +} diff --git a/Source/Helpers/LaborState.cs b/Source/Helpers/LaborState.cs new file mode 100644 index 0000000..9a99f12 --- /dev/null +++ b/Source/Helpers/LaborState.cs @@ -0,0 +1,28 @@ +using System; +using RimWorld; +using Verse; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LitterBiotech +{ + class LaborState + { + public Pawn pawn; + public int birthTotal = 0; + public int birthCount = 1; + public bool hasOvaryAgitator = false; + public bool hasBioscaffold = false; + + public LaborState(Pawn pawn, int birthTotal) + { + this.pawn = pawn; + this.birthTotal = birthTotal; + this.birthCount = 0; + this.hasOvaryAgitator = pawn.health.hediffSet.HasHediff(HediffDef.Named("OvaryAgitator")); + this.hasBioscaffold = pawn.health.hediffSet.HasHediff(HediffDef.Named("OvaryAgitator")); + } + } +} diff --git a/Source/LitterBiotech.cs b/Source/LitterBiotech.cs new file mode 100644 index 0000000..c127eed --- /dev/null +++ b/Source/LitterBiotech.cs @@ -0,0 +1,161 @@ +using HarmonyLib; +using RimWorld; +using LitterBiotech.Helpers; +using System.Collections.Generic; +using Verse; + +namespace LitterBiotech +{ + [StaticConstructorOnStartup] + public class LitterBiotechMod + { + static Dictionary laborStateMap = new Dictionary(); + + static LitterBiotechMod() + { + Harmony harmony = new Harmony(id: "rimworld.leboeuf.litterbiotech"); + // Hediff_Labor state capture + harmony.Patch(AccessTools.Method(typeof(Hediff_Labor), nameof(Hediff_Labor.PostRemoved)), + postfix: new HarmonyMethod(typeof(LitterBiotechMod), nameof(Hediff_Labor_PostRemovedPostFix))); + + // Gene_LitteredBirths multibirth logic + harmony.Patch(AccessTools.Method(typeof(Hediff_LaborPushing), nameof(Hediff_LaborPushing.PostRemoved)), + postfix: new HarmonyMethod(typeof(LitterBiotechMod), nameof(Hediff_LaborPushing_PostRemovedPostFix))); + + LBTLogger.Message("Litter Biotech started successfully."); + + if (LBTSettings.devMode) + { + LBTLogger.Message("Notice: Developer logging for Litter Biotech is currently active - it can be disabled in the mod settings."); + } + } + + // Notes about Hediff_Labor_PostRemovedPostFix + // =========================================== + // Alright, didn't really want to make a patch for Labor as well as LaborPushing, but I have to because otherwise there's + // no way to assign a doctor on second/third/etc births if I only use LaborPushing, which can disproportionately cause + // more stillbirths than you might normally have + // + // I TRIED to modify the ChildBirth lord job and ritual code to allow the first doctor that was assigned and any childbirth + // attendees to just autoreassign themselves to the next births, but it wasn't working - for now, I'm not happy with how I'm + // doing this because multiple births now require: + // 1. (potentially several) forced pauses with letters telling the player to reassign a doctor to the mother who's giving birth to another child + // 2. A LOT of state carrying (that I likely overengineered :v) ) between hediff removes and adds + // + // I've got a dictionary now for storing state across hediffs and on multiple pawns, instead of what I was originally doing, which was using + // severity as a way of tracking state. LaborState class should help keep things a little more organized. + // + // I'll revisit this in the future (probably). Thanks for coming to my TED talk + static void Hediff_Labor_PostRemovedPostFix(ref Hediff_Labor __instance) + { + bool randomTwinsRoll; + int totalBirths; + bool laborStateIsNull = !laborStateMap.ContainsKey(__instance.pawn.ThingID); + bool hasLitteredBirthsGene = __instance.pawn.genes.HasGene(LitterBiotech.GeneDefOf.LitteredBirths); + + // we'll never do additional processing if this is the guaranteed last birth (eg birth #4) + if (!laborStateIsNull && laborStateMap.TryGetValue(__instance.pawn.ThingID).birthCount == 4) + { + return; + } + + // For now, littered birth overrides twin calculations, so if a LaborState already exists + // with littered births gene, move on + if (!laborStateIsNull && hasLitteredBirthsGene) + { + if (LBTSettings.devMode) + { + LBTLogger.MessageGroupHead("Found active LaborState and LitteredBirths gene - skipping additional Hediff_Labor_PostRemovedPostFix work"); + LBTLogger.MessageGroupBody("Pawn: " + __instance.pawn.NameShortColored + " (" + __instance.pawn.ThingID + ")"); + LBTLogger.MessageGroupFoot("birthCount: " + laborStateMap.TryGetValue(__instance.pawn.ThingID).birthCount); + } + + return; + } + + // Make a new LaborState for the null case with littered births + if (laborStateIsNull && hasLitteredBirthsGene) + { + LBTLogger.Message("Found littered births gene"); + int litteredBirthsTotalRoll = Rand.RangeInclusive(2, 4); + laborStateMap.SetOrAdd(__instance.pawn.ThingID, new LaborState(__instance.pawn, litteredBirthsTotalRoll)); + return; + } + + // Finally, regardless of littered births gene, we only want new state creation on + // pawns that don't already have state, so return if state is !null (STATE SHOULD ALWAYS BE CLEANED IN LABORPUSHING POSTFIX) + if (!laborStateIsNull) + { + if (LBTSettings.devMode) + { + LBTLogger.Warning("Labor state for pawn " + __instance.pawn.NameShortColored + " (" + __instance.pawn.ThingID + ") is not null despite all checks passing for determining first instance of Hediff_Labor - this warning should never occur, and may indicate a bug in Hediff_LaborPushing of lingering labor state from a previous pregnancy"); + } + return; + } + + // For everything else, we do random twin handling + // ------- + // If we fail a base chance twins roll, return without any additional processing and proceed with vanilla childbirth + // Notes on rolls: + // -> Chance with Littered Births gene: random between 2 and 4 (inclusive) + randomTwinsRoll = Rand.Chance(0.01f); + if (!randomTwinsRoll) + { + // We failed rolls - no additional processing, do vanilla single baby birth + if (LBTSettings.devMode) + { + LBTLogger.MessageGroupHead("Inside Hediff_Labor_PostRemovedPostFix random twins check fail"); + LBTLogger.MessageGroupBody("Pawn: " + __instance.pawn.NameShortColored); + LBTLogger.MessageGroupBody("Random twins roll outcome: " + randomTwinsRoll); + } + return; + } + + totalBirths = 2; + bool doTriplets = Rand.Chance(0.5f); + bool doQuadruplets = Rand.Chance(0.1f); + if (doTriplets) totalBirths = 3; + if (doTriplets && doQuadruplets) totalBirths = 4; + + // Set new LaborState + laborStateMap.Add(__instance.pawn.ThingID, new LaborState(__instance.pawn, totalBirths)); + } + + static void Hediff_LaborPushing_PostRemovedPostFix(ref Hediff_LaborPushing __instance) + { + bool hasLitteredBirthsGene = __instance.pawn.genes.HasGene(LitterBiotech.GeneDefOf.LitteredBirths); + bool laborStateIsNull = !laborStateMap.ContainsKey(__instance.pawn.ThingID); + LaborState currentLaborState; + laborStateMap.TryGetValue(__instance.pawn.ThingID, out currentLaborState); + + if (laborStateIsNull) + { + return; + } + + if (currentLaborState.birthTotal == currentLaborState.birthCount) + { + laborStateMap.Remove(__instance.pawn.ThingID); + if (__instance.pawn.health.hediffSet.HasHediff(HediffDef.Named("Bioscaffold"))) { + __instance.pawn.health.RemoveHediff(__instance.pawn.health.hediffSet.GetFirstHediffOfDef(LitterBiotech.HediffDefOf.Bioscaffold)); + } + return; + } + + ((Hediff_Labor)__instance.pawn.health.AddHediff(RimWorld.HediffDefOf.PregnancyLabor)).SetParents(__instance.pawn, __instance.Father, PregnancyUtility.GetInheritedGeneSet(__instance.Father, __instance.pawn)); + currentLaborState.birthCount++; + + if (!hasLitteredBirthsGene) + { + if (LBTSettings.devMode) + { + LBTLogger.Message("Pawn " + __instance.pawn.NameShortColored + " (" + __instance.pawn.ThingID + ") is having random twins"); + } + Find.LetterStack.ReceiveLetter("Twins!", __instance.pawn.NameShortColored + " is still in labor and is having twins!\n\nBe sure to gather your doctor and additional friends and family to ensure the other baby is also born healthy!", LitterBiotech.LetterDefOf.AnotherBaby, __instance.pawn); + return; + } + + Find.LetterStack.ReceiveLetter("Another baby!", __instance.pawn.NameShortColored + " is still in labor and is having another baby!\n\nBe sure to gather your doctor and additional friends and family to ensure the next baby is also born healthy!", LitterBiotech.LetterDefOf.AnotherBaby, __instance.pawn); + } + } +} diff --git a/Source/LitterBiotech.csproj b/Source/LitterBiotech.csproj new file mode 100644 index 0000000..b8c97c2 --- /dev/null +++ b/Source/LitterBiotech.csproj @@ -0,0 +1,70 @@ + + + + + Debug + AnyCPU + {D7D21B4A-1DA7-41D8-B202-C58CA8FA62AA} + Library + Properties + LitterBiotech + LitterBiotech + v4.7.2 + 512 + + + + none + true + ..\1.4\Assemblies\ + prompt + 4 + false + + + Always + + + + ..\..\..\..\..\workshop\content\294100\2009463077\Current\Assemblies\0Harmony.dll + + + ..\..\..\RimWorldLinux_Data\Managed\Assembly-CSharp.dll + False + + + ..\..\..\..\..\workshop\content\294100\2009463077\Current\Assemblies\HarmonyMod.dll + + + + + + + + + ..\..\..\RimWorldLinux_Data\Managed\UnityEngine.CoreModule.dll + False + + + + + + + + + + + + + + + + + + + + + cp "$(SolutionDir)Source/obj/Release/$(SolutionName).dll" "$(SolutionDir)1.4/Assemblies" + + + diff --git a/Source/Properties/AssemblyInfo.cs b/Source/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..ffc8925 --- /dev/null +++ b/Source/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("LitterBiotech")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("LitterBiotech")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("d7d21b4a-1da7-41d8-b202-c58ca8fa62aa")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Source/Settings/LBTSettings.cs b/Source/Settings/LBTSettings.cs new file mode 100644 index 0000000..f6243b1 --- /dev/null +++ b/Source/Settings/LBTSettings.cs @@ -0,0 +1,54 @@ +using UnityEngine; +using Verse; + +// If it isn't blatantly obvious, I unabashedly ripped this settings template from RJW, minus the fact that +// I won't be (personally) supporting multiplayer, and it's all in one file - but I digress ... +namespace LitterBiotech +{ + class LBTSettingsController : Mod + { + public LBTSettingsController(ModContentPack content) : base(content) + { + GetSettings(); + } + + public override string SettingsCategory() + { + return "LBTSettings".Translate(); + } + + public override void DoSettingsWindowContents(Rect inRect) + { + LBTSettings.DoWindowContents(inRect); + } + } + + public class LBTSettings : ModSettings + { + // For my own sanity, all now and future settings will have a default disabled/false state (at least, that's the plan), and + // the settings name and description should reflect that (not that I'm going to add that many settings, mind you) + public static bool devMode = false; + public static bool regretStealingLovinThoughtDisabled = false; + + public static void DoWindowContents(Rect inRect) + { + // Shrink the settings window a bit - don't need to be that w i d e + inRect.width = inRect.width - 400; + inRect.x = inRect.x + 200; + Listing_Standard listingStandard = new Listing_Standard(); + listingStandard.Begin(inRect); + listingStandard.Gap(4f); + listingStandard.CheckboxLabeled("EnableLBTDevLogging".Translate(), ref devMode, "EnableLBTDevLoggingDesc".Translate()); + listingStandard.Gap(4f); + listingStandard.CheckboxLabeled("RegretStealingLovinThoughtDisabled".Translate(), ref regretStealingLovinThoughtDisabled, "RegretStealingLovinThoughtDisabledDesc".Translate()); + listingStandard.End(); + } + + public override void ExposeData() + { + base.ExposeData(); + Scribe_Values.Look(ref devMode, "EnableLBTDevLogging", devMode, true); + Scribe_Values.Look(ref regretStealingLovinThoughtDisabled, "regretStealingLovinThoughtDisabled", regretStealingLovinThoughtDisabled, true); + } + } +}