using RimWorld; using rjw; using System.Collections.Generic; using System.Text; using System.Xml; using UnityEngine; using Verse; namespace RJW_Menstruation { public class PawnDNAModExtension : DefModExtension { public string fetusTexPath; public ColorInt cumColor; public Color CumColor => cumColor.ToColor; public float cumThickness = 0f; public List hybridExtension; public List ingestionOutcomeDoers; public HybridExtension GetHybridExtension(string race) { if (hybridExtension.NullOrEmpty()) return null; else return hybridExtension.Find(x => x.thingDef.defName.Equals(race)); } public PawnKindDef GetHybridWith(string race) { return GetHybridExtension(race)?.ChooseOne() ?? null; } } public class HybridExtension { public Dictionary hybridInfo = new Dictionary(); public ThingDef thingDef; public HybridExtension() { } public PawnKindDef ChooseOne() { if (hybridInfo.EnumerableNullOrEmpty()) return null; PawnKindDef res = null; do { string key = hybridInfo.RandomElementByWeight(x => x.Value).Key; res = DefDatabase.GetNamedSilentFail(key); if (res == null) res = DefDatabase.GetNamedSilentFail(key)?.race?.AnyPawnKind; if (res == null) { Log.Warning($"Could not find pawnKind or race {key}, removing hybrid definition"); hybridInfo.Remove(key); } } while (res == null && !hybridInfo.EnumerableNullOrEmpty()); return res; } public void LoadDataFromXmlCustom(XmlNode xmlRoot) { DirectXmlCrossRefLoader.RegisterObjectWantsCrossRef(this, "thingDef", xmlRoot.Name); XmlNodeList childNodes = xmlRoot.ChildNodes; if (childNodes.Count >= 1) foreach (XmlNode node in childNodes) { #if DEBUG Log.Message(xmlRoot.Name + "HybridInfo: " + node.Name + " " + node.InnerText); #endif hybridInfo.Add(node.Name, ParseHelper.FromString(node.InnerText)); } } } public class HybridInformations : IExposable { public List hybridExtension = new List(); private ThingDef thingDef; private string thingDefName; public string DefName { get { return thingDefName; } } public bool IsNull { get { return (thingDefName?.Length ?? 0) < 1; } } public ThingDef GetDef { get { if (thingDef != null) return thingDef; else { thingDef = DefDatabase.GetNamedSilentFail(thingDefName); return thingDef; } } } public HybridInformations() { } public HybridInformations(ThingDef def) { thingDef = def; thingDefName = def.defName; } public HybridExtensionExposable GetHybridExtension(string race) { if (hybridExtension.NullOrEmpty()) return null; else { return hybridExtension.Find(x => x.GetDef?.defName?.Equals(race) ?? false); } } public PawnKindDef GetHybridWith(string race) { return GetHybridExtension(race)?.ChooseOne() ?? null; } public void ExposeData() { Scribe_Values.Look(ref thingDefName, "thingDefName"); Scribe_Collections.Look(ref hybridExtension, "hybridExtension", LookMode.Deep, new object[0]); } } public class HybridExtensionExposable : HybridExtension, IExposable { private string thingDefName; public string DefName { get { return thingDefName; } } public bool IsNull { get { return (thingDefName?.Length ?? 0) < 1; } } public ThingDef GetDef { get { if (thingDef != null) return thingDef; else { thingDef = DefDatabase.GetNamedSilentFail(thingDefName); return thingDef; } } } public HybridExtensionExposable() { } public HybridExtensionExposable(ThingDef def) { thingDef = def; thingDefName = def.defName; hybridInfo = new Dictionary(); } public void ExposeData() { Scribe_Values.Look(ref thingDefName, "thingDefName"); Scribe_Collections.Look(ref hybridInfo, "hybridInfo", LookMode.Value, LookMode.Value); } } public class AbsorberModExtension : DefModExtension { public float passiveAbsorptionPerHour = 0.1f; public bool leakAfterDirty = false; public bool effectsAfterDirty = false; public ThingDef dirtyDef = null; public int minHourstoDirtyEffect = 0; } public class Absorber : Apparel { public float absorbedfluids = 0; public bool dirty = false; public int wearTicks = 0; public virtual float PassiveAbsorptionPerHour => def.GetModExtension().passiveAbsorptionPerHour; public virtual bool LeakAfterDirty => def.GetModExtension().leakAfterDirty; public virtual bool EffectAfterDirty => def.GetModExtension().effectsAfterDirty; public virtual ThingDef DirtyDef => def.GetModExtension().dirtyDef; public virtual int MinHrstoDirtyEffect => def.GetModExtension().minHourstoDirtyEffect; public Color fluidColor = Color.white; public virtual void DirtyEffect(int tickInterval) { } public virtual void WearEffect(int tickInterval) { absorbedfluids += PassiveAbsorptionPerHour * tickInterval / GenDate.TicksPerHour; CheckDirty(); if (dirty) wearTicks += tickInterval; } public void CheckDirty() { if (absorbedfluids > this.GetStatValue(VariousDefOf.MaxAbsorbable) && !(Wearer?.apparel?.IsLocked(this) ?? false) && DirtyDef != def && DirtyDef != null) { bool oldHasStats = !def.equippedStatOffsets.NullOrEmpty(); bool newHasStats = !DirtyDef.equippedStatOffsets.NullOrEmpty(); def = DirtyDef; dirty = true; Wearer.outfits?.forcedHandler?.SetForced(this, false); if (oldHasStats || newHasStats) Wearer.health.capacities.Notify_CapacityLevelsDirty(); Wearer.apparel.Notify_ApparelChanged(); } } public override Color DrawColorTwo => fluidColor; public override void ExposeData() { base.ExposeData(); if(Scribe.mode == LoadSaveMode.LoadingVars) { int wearhours = -1; Scribe_Values.Look(ref wearhours, "wearhours", wearhours, true); if (wearhours >= 0) wearTicks = wearhours * GenDate.TicksPerHour; } Scribe_Values.Look(ref absorbedfluids, "absorbedfluids", 0); Scribe_Values.Look(ref dirty, "dirty", false); Scribe_Values.Look(ref wearTicks, "wearTicks", 0); Scribe_Values.Look(ref fluidColor, "fluidColor", Color.white); } public override string DescriptionDetailed { get { StringBuilder text = new StringBuilder(base.DescriptionDetailed); text.AppendLine(); text.Append(Translations.Description_Absorbed); text.Append(": "); text.Append(absorbedfluids.ToStringDecimalIfSmall()); text.Append("/"); text.Append(this.GetStatValue(VariousDefOf.MaxAbsorbable).ToStringDecimalIfSmall()); text.Append("ml"); return text.ToString(); } } } public class Absorber_Tampon : Absorber { public override void DirtyEffect(int tickInterval) { if (wearTicks > MinHrstoDirtyEffect * GenDate.TicksPerHour && Rand.MTBEventOccurs(100.0f, GenDate.TicksPerHour, tickInterval) && !(Wearer.apparel?.IsLocked(this) ?? false)) { Wearer.health.AddHediff(HediffDefOf.WoundInfection, Genital_Helper.get_genitalsBPR(Wearer)); } } } public class Filth_Colored : Filth { private Color color = Color.white; public override void ExposeData() { base.ExposeData(); Scribe_Values.Look(ref color, "color", Color.white); } public override Color DrawColor { get { if (color != Color.white) { return color; } if (Stuff != null) { return def.GetColorForStuff(Stuff); } if (def.graphicData != null) { return def.graphicData.color; } return color; } set { color = value; } } } }