diff --git a/1.4/Assemblies/RJWSexperience.dll b/1.4/Assemblies/RJWSexperience.dll index 938c28f..b494450 100644 Binary files a/1.4/Assemblies/RJWSexperience.dll and b/1.4/Assemblies/RJWSexperience.dll differ diff --git a/1.4/Defs/ThoughtDefs/Thoughts_ate.xml b/1.4/Defs/ThoughtDefs/Thoughts_ate.xml index b8e9d60..0bbeb15 100644 --- a/1.4/Defs/ThoughtDefs/Thoughts_ate.xml +++ b/1.4/Defs/ThoughtDefs/Thoughts_ate.xml @@ -15,12 +15,12 @@
  • - It's stinky and tastes bad. + Tastes bad and stinky. -2
  • - Tastes bad. But I liked it. + Tastes bad. But i liked it. 1
  • diff --git a/About/Manifest.xml b/About/Manifest.xml index 409b150..b412805 100644 --- a/About/Manifest.xml +++ b/About/Manifest.xml @@ -1,7 +1,7 @@ RJWSexperience - 1.1.4.0 + 1.1.3.0
  • RimJobWorld >= 5.3.0
  • diff --git a/Languages/English/Keyed/RJW_Sexperience.xml b/Languages/English/Keyed/RJW_Sexperience.xml index b093beb..daa7bc3 100644 --- a/Languages/English/Keyed/RJW_Sexperience.xml +++ b/Languages/English/Keyed/RJW_Sexperience.xml @@ -43,7 +43,6 @@ ago last sex Had best sex {0}. - Lock displayed pawn.\n\nWhen unlocked, window will automatically switch to a currently selected pawn. Main diff --git a/Source/RJWSexperience/Cum/Building_Cumbucket.cs b/Source/RJWSexperience/Cum/Building_Cumbucket.cs index 2cccea7..4598f5f 100644 --- a/Source/RJWSexperience/Cum/Building_Cumbucket.cs +++ b/Source/RJWSexperience/Cum/Building_Cumbucket.cs @@ -42,8 +42,8 @@ namespace RJWSexperience // Used in Menstruation with this namespace if (SexperienceMod.Settings.DevMode) { stringBuilder.AppendLine(); - stringBuilder.Append("[Debug] stored: ").Append(StoredStackCount).AppendLine(); - stringBuilder.Append("[Debug] storedDecimalRemainder: ").Append(storedDecimalRemainder); + stringBuilder.AppendLine($"[Debug] stored: {StoredStackCount}"); + stringBuilder.Append($"[Debug] storedDecimalRemainder: {storedDecimalRemainder}"); } return stringBuilder.ToString(); @@ -51,7 +51,7 @@ namespace RJWSexperience // Used in Menstruation with this namespace public void AddCum(float amount) { - AddCum(amount, RsDefOf.Thing.GatheredCum); + AddCum(amount, VariousDefOf.GatheredCum); } public void AddCum(float amount, ThingDef cumDef) @@ -69,7 +69,7 @@ namespace RJWSexperience // Used in Menstruation with this namespace cum.stackCount = num; if (cum.stackCount > 0 && !GenPlace.TryPlaceThing(cum, PositionHeld, Map, ThingPlaceMode.Direct, out Thing res)) { - FilthMaker.TryMakeFilth(PositionHeld, Map, RsDefOf.Thing.FilthCum, num); + FilthMaker.TryMakeFilth(PositionHeld, Map, VariousDefOf.FilthCum, num); } storedDecimalRemainder -= num; } diff --git a/Source/RJWSexperience/Cum/CumUtility.cs b/Source/RJWSexperience/Cum/CumUtility.cs index e3be0e9..988349d 100644 --- a/Source/RJWSexperience/Cum/CumUtility.cs +++ b/Source/RJWSexperience/Cum/CumUtility.cs @@ -125,7 +125,7 @@ namespace RJWSexperience.Cum const float allOf = 1000f; log.Message($"FeedCum({pawn.NameShortColored}, {amount})"); - Thing cum = ThingMaker.MakeThing(RsDefOf.Thing.GatheredCum); + Thing cum = ThingMaker.MakeThing(VariousDefOf.GatheredCum); cum.stackCount = (int)Math.Ceiling(amount); log.Message($"Created a stack of {cum.stackCount} cum"); cum.Ingested(pawn, allOf); diff --git a/Source/RJWSexperience/Cum/FilterWorkers/SpecialThingFilterWorker_Cum.cs b/Source/RJWSexperience/Cum/FilterWorkers/SpecialThingFilterWorker_Cum.cs index 2f89284..81ea225 100644 --- a/Source/RJWSexperience/Cum/FilterWorkers/SpecialThingFilterWorker_Cum.cs +++ b/Source/RJWSexperience/Cum/FilterWorkers/SpecialThingFilterWorker_Cum.cs @@ -6,7 +6,7 @@ namespace RJWSexperience.Cum.FilterWorkers { public override bool Matches(Thing t) { - return IsCum(t.def) || IsFoodWithCum(t); + return IsCum(t) || IsFoodWithCum(t); } } } diff --git a/Source/RJWSexperience/Cum/FilterWorkers/SpecialThingFilterWorker_CumBase.cs b/Source/RJWSexperience/Cum/FilterWorkers/SpecialThingFilterWorker_CumBase.cs index ce9fb03..d622aa0 100644 --- a/Source/RJWSexperience/Cum/FilterWorkers/SpecialThingFilterWorker_CumBase.cs +++ b/Source/RJWSexperience/Cum/FilterWorkers/SpecialThingFilterWorker_CumBase.cs @@ -10,18 +10,20 @@ namespace RJWSexperience.Cum.FilterWorkers return def.IsIngestible && def.IsProcessedFood; } - protected bool IsCum(ThingDef t) => t == RsDefOf.Thing.GatheredCum; + protected bool IsCum(Thing t) => IsCum(t.def); + + protected bool IsCum(ThingDef t) => t == VariousDefOf.GatheredCum; protected bool IsFoodWithCum(Thing food) { CompIngredients compIngredients = food.TryGetComp(); - if (compIngredients?.ingredients == null) + if (compIngredients == null) return false; - for (int i = 0; i < compIngredients.ingredients.Count; i++) + foreach (ThingDef ingredient in compIngredients.ingredients) { - if (IsCum(compIngredients.ingredients[i])) + if (IsCum(ingredient)) return true; } diff --git a/Source/RJWSexperience/Cum/FilterWorkers/SpecialThingFilterWorker_NoCum.cs b/Source/RJWSexperience/Cum/FilterWorkers/SpecialThingFilterWorker_NoCum.cs index b9b32e3..d288316 100644 --- a/Source/RJWSexperience/Cum/FilterWorkers/SpecialThingFilterWorker_NoCum.cs +++ b/Source/RJWSexperience/Cum/FilterWorkers/SpecialThingFilterWorker_NoCum.cs @@ -6,7 +6,7 @@ namespace RJWSexperience.Cum.FilterWorkers { public override bool Matches(Thing t) { - return !IsCum(t.def) && !IsFoodWithCum(t); + return !IsCum(t) && !IsFoodWithCum(t); } } } diff --git a/Source/RJWSexperience/Cum/IngestionOutcomeDoer_RecordEatenCum.cs b/Source/RJWSexperience/Cum/IngestionOutcomeDoer_RecordEatenCum.cs index 812abc5..29c9798 100644 --- a/Source/RJWSexperience/Cum/IngestionOutcomeDoer_RecordEatenCum.cs +++ b/Source/RJWSexperience/Cum/IngestionOutcomeDoer_RecordEatenCum.cs @@ -12,8 +12,8 @@ namespace RJWSexperience.Cum { int amount = ingested.stackCount * (int)unitAmount; Logs.LogManager.GetLogger().Message($"Record {pawn.NameShortColored} eating {amount} ml of cum"); - pawn.records.Increment(RsDefOf.Record.NumofEatenCum); - pawn.records.AddTo(RsDefOf.Record.AmountofEatenCum, amount); + pawn.records.Increment(VariousDefOf.NumofEatenCum); + pawn.records.AddTo(VariousDefOf.AmountofEatenCum, amount); } } } diff --git a/Source/RJWSexperience/Cum/Interactions/CumAddictPartKindUsageRule.cs b/Source/RJWSexperience/Cum/Interactions/CumAddictPartKindUsageRule.cs index 946dad7..bdd4762 100644 --- a/Source/RJWSexperience/Cum/Interactions/CumAddictPartKindUsageRule.cs +++ b/Source/RJWSexperience/Cum/Interactions/CumAddictPartKindUsageRule.cs @@ -17,7 +17,7 @@ namespace RJWSexperience.Cum.Interactions if (context.Internals.Submissive.Parts.Penises.Any()) return GetForCumAddict(context.Internals.Dominant.Pawn); - if (AddictionUtility.IsAddicted(context.Internals.Submissive.Pawn, RsDefOf.Chemical.Cum)) + if (AddictionUtility.IsAddicted(context.Internals.Submissive.Pawn, VariousDefOf.Cum)) return GetForPartner(); return Enumerable.Empty>(); @@ -28,7 +28,7 @@ namespace RJWSexperience.Cum.Interactions if (context.Internals.Dominant.Parts.Penises.Any()) return GetForCumAddict(context.Internals.Submissive.Pawn); - if (AddictionUtility.IsAddicted(context.Internals.Dominant.Pawn, RsDefOf.Chemical.Cum)) + if (AddictionUtility.IsAddicted(context.Internals.Dominant.Pawn, VariousDefOf.Cum)) return GetForPartner(); return Enumerable.Empty>(); @@ -42,7 +42,7 @@ namespace RJWSexperience.Cum.Interactions var log = LogManager.GetLogger(); log.Message($"Called for {pawn.NameShortColored}"); - if (!(pawn.needs?.TryGetNeed(RsDefOf.Need.Chemical_Cum) is Need_Chemical cumNeed)) + if (!(pawn.needs?.TryGetNeed(VariousDefOf.Chemical_Cum) is Need_Chemical cumNeed)) yield break; log.Message($"{pawn.NameShortColored} is cum addict, current desire level: {cumNeed.CurCategory}"); diff --git a/Source/RJWSexperience/Cum/Thought_AteCum.cs b/Source/RJWSexperience/Cum/Thought_AteCum.cs index fba55b2..d309521 100644 --- a/Source/RJWSexperience/Cum/Thought_AteCum.cs +++ b/Source/RJWSexperience/Cum/Thought_AteCum.cs @@ -1,17 +1,39 @@ -namespace RJWSexperience // Change in namespace will lead to save incompatibility +using RimWorld; + +namespace RJWSexperience // Change in namespace will lead to save incompatibility { public class Thought_AteCum : Thought_Recordbased { - protected override void UpdateCurStage() + public override int CurStageIndex { - if (pawn?.health?.hediffSet?.HasHediff(RsDefOf.Hediff.CumAddiction) ?? false) + get { - SetForcedStage(def.stages.Count - 1); + if (pawn?.health?.hediffSet?.HasHediff(VariousDefOf.CumAddiction) ?? false) + return def.stages.Count - 1; + return base.CurStageIndex; } - else + } + + public override bool TryMergeWithExistingMemory(out bool showBubble) + { + ThoughtHandler thoughts = pawn.needs.mood.thoughts; + if (thoughts.memories.NumMemoriesInGroup(this) >= def.stackLimit) { - base.UpdateCurStage(); + Thought_AteCum thought_Memory = (Thought_AteCum)thoughts.memories.OldestMemoryInGroup(this); + if (thought_Memory != null) + { + showBubble = thought_Memory.age > thought_Memory.def.DurationTicks / 2; + thought_Memory.Merged(); + return true; + } } + showBubble = true; + return false; + } + + protected virtual void Merged() + { + age = 0; } } } diff --git a/Source/RJWSexperience/DebugAction.cs b/Source/RJWSexperience/DebugAction.cs index 71a7a85..ca1b971 100644 --- a/Source/RJWSexperience/DebugAction.cs +++ b/Source/RJWSexperience/DebugAction.cs @@ -8,9 +8,9 @@ namespace RJWSexperience public static class DebugToolsSexperience { [DebugAction("RJW Sexperience", "Reset pawn's record", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.PlayingOnMap)] - public static void ResetRecords(Pawn p) + private static void ResetRecords(Pawn p) { - Trait virgin = p.story?.traits?.GetTrait(RsDefOf.Trait.Virgin); + Trait virgin = p.story?.traits?.GetTrait(VariousDefOf.Virgin); if (virgin != null) p.story.traits.RemoveTrait(virgin); ResetRecord(p, true); if (ResetRecord(p, false)) @@ -19,7 +19,7 @@ namespace RJWSexperience } [DebugAction("RJW Sexperience", "Reset pawn's record(virgin)", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.PlayingOnMap)] - public static void ResetRecordsZero(Pawn p) + private static void ResetRecordsZero(Pawn p) { ResetRecord(p, true); Virginity.TraitHandler.AddVirginTrait(p); @@ -27,31 +27,32 @@ namespace RJWSexperience } [DebugAction("RJW Sexperience", "Reset lust", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.PlayingOnMap)] - public static void ResetLust(Pawn p) + private static void ResetLust(Pawn p) { float lust = RecordRandomizer.RandomizeLust(p); MoteMaker.ThrowText(p.TrueCenter(), p.Map, "Lust: " + lust); } [DebugAction("RJW Sexperience", "Set lust to 0", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.PlayingOnMap)] - public static void SetLust(Pawn p) + private static void SetLust(Pawn p) { - p.records.SetTo(RsDefOf.Record.Lust, 0); + p.records.SetTo(VariousDefOf.Lust, 0); MoteMaker.ThrowText(p.TrueCenter(), p.Map, "Lust: 0"); } + [DebugAction("RJW Sexperience", "Add 10 to lust", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.PlayingOnMap)] - public static void AddLust(Pawn p) + private static void AddLust(Pawn p) { - p.records.AddTo(RsDefOf.Record.Lust, 10); - MoteMaker.ThrowText(p.TrueCenter(), p.Map, "Lust: " + p.records.GetValue(RsDefOf.Record.Lust)); + p.records.AddTo(VariousDefOf.Lust, 10); + MoteMaker.ThrowText(p.TrueCenter(), p.Map, "Lust: " + p.records.GetValue(VariousDefOf.Lust)); } [DebugAction("RJW Sexperience", "Subtract 10 to lust", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.PlayingOnMap)] - public static void SubtractLust(Pawn p) + private static void SubtractLust(Pawn p) { - p.records.AddTo(RsDefOf.Record.Lust, -10); - MoteMaker.ThrowText(p.TrueCenter(), p.Map, "Lust: " + p.records.GetValue(RsDefOf.Record.Lust)); + p.records.AddTo(VariousDefOf.Lust, -10); + MoteMaker.ThrowText(p.TrueCenter(), p.Map, "Lust: " + p.records.GetValue(VariousDefOf.Lust)); } private static bool ResetRecord(Pawn pawn, bool allzero) @@ -65,21 +66,21 @@ namespace RJWSexperience } else { - pawn.records.SetTo(RsDefOf.Record.Lust, 0); - pawn.records.SetTo(RsDefOf.Record.NumofEatenCum, 0); - pawn.records.SetTo(RsDefOf.Record.AmountofEatenCum, 0); - pawn.records.SetTo(RsDefOf.Record.VaginalSexCount, 0); - pawn.records.SetTo(RsDefOf.Record.AnalSexCount, 0); - pawn.records.SetTo(RsDefOf.Record.OralSexCount, 0); - pawn.records.SetTo(RsDefOf.Record.BlowjobCount, 0); - pawn.records.SetTo(RsDefOf.Record.CunnilingusCount, 0); - pawn.records.SetTo(RsDefOf.Record.GenitalCaressCount, 0); - pawn.records.SetTo(RsDefOf.Record.HandjobCount, 0); - pawn.records.SetTo(RsDefOf.Record.FingeringCount, 0); - pawn.records.SetTo(RsDefOf.Record.FootjobCount, 0); - pawn.records.SetTo(RsDefOf.Record.MiscSexualBehaviorCount, 0); - pawn.records.SetTo(RsDefOf.Record.SexPartnerCount, 0); - pawn.records.SetTo(RsDefOf.Record.OrgasmCount, 0); + pawn.records.SetTo(VariousDefOf.Lust, 0); + pawn.records.SetTo(VariousDefOf.NumofEatenCum, 0); + pawn.records.SetTo(VariousDefOf.AmountofEatenCum, 0); + pawn.records.SetTo(VariousDefOf.VaginalSexCount, 0); + pawn.records.SetTo(VariousDefOf.AnalSexCount, 0); + pawn.records.SetTo(VariousDefOf.OralSexCount, 0); + pawn.records.SetTo(VariousDefOf.BlowjobCount, 0); + pawn.records.SetTo(VariousDefOf.CunnilingusCount, 0); + pawn.records.SetTo(VariousDefOf.GenitalCaressCount, 0); + pawn.records.SetTo(VariousDefOf.HandjobCount, 0); + pawn.records.SetTo(VariousDefOf.FingeringCount, 0); + pawn.records.SetTo(VariousDefOf.FootjobCount, 0); + pawn.records.SetTo(VariousDefOf.MiscSexualBehaviorCount, 0); + pawn.records.SetTo(VariousDefOf.SexPartnerCount, 0); + pawn.records.SetTo(VariousDefOf.OrgasmCount, 0); pawn.records.SetTo(xxx.CountOfBeenRapedByAnimals, 0); pawn.records.SetTo(xxx.CountOfBeenRapedByHumanlikes, 0); pawn.records.SetTo(xxx.CountOfBeenRapedByInsects, 0); diff --git a/Source/RJWSexperience/ExtensionMethods/PawnExtensions.cs b/Source/RJWSexperience/ExtensionMethods/PawnExtensions.cs index aa40cfc..9e3a7f9 100644 --- a/Source/RJWSexperience/ExtensionMethods/PawnExtensions.cs +++ b/Source/RJWSexperience/ExtensionMethods/PawnExtensions.cs @@ -13,7 +13,7 @@ namespace RJWSexperience return false; IEnumerable relations = pawn.GetRelations(otherpawn); - if (relations == null) + if (relations.EnumerableNullOrEmpty()) return false; foreach (PawnRelationDef relation in relations) @@ -27,54 +27,71 @@ namespace RJWSexperience public static float GetSexStat(this Pawn pawn) { if (xxx.is_human(pawn) && !pawn.Dead) - return pawn.GetStatValue(RsDefOf.Stat.SexAbility); + return pawn.GetStatValue(VariousDefOf.SexAbility); return 1.0f; } - public static T GetAdjacentBuilding(this Pawn pawn) where T : Building => GetAdjacentBuildings(pawn).FirstOrFallback(); - - public static IEnumerable GetAdjacentBuildings(this Pawn pawn) where T : Building + public static T GetAdjacentBuilding(this Pawn pawn) where T : Building { if (!pawn.Spawned) - yield break; + return null; EdificeGrid edifice = pawn.Map.edificeGrid; if (edifice[pawn.Position] is T building) - yield return building; + return building; + foreach (IntVec3 pos in GenAdjFast.AdjacentCells8Way(pawn.Position)) + { + if (edifice[pos] is T adjBuilding) + return adjBuilding; + } + return null; + } + public static IEnumerable GetAdjacentBuildings(this Pawn pawn) where T : Building + { + var results = new List(); + + if (!pawn.Spawned) + return results; + + EdificeGrid edifice = pawn.Map.edificeGrid; + if (edifice[pawn.Position] is T building) + results.Add(building); foreach (IntVec3 pos in GenAdjFast.AdjacentCells8Way(pawn.Position)) { if (pos.InBounds(pawn.Map) && edifice[pos] is T adjBuilding) - yield return adjBuilding; + results.Add(adjBuilding); } + return results; } /// - /// Check if the pawn is virgin + /// If the pawn is virgin, return true. /// public static bool IsVirgin(this Pawn pawn) { - return pawn.records.GetValue(RsDefOf.Record.VaginalSexCount) == 0 || - pawn.relations?.ChildrenCount > 0; // Male is a virgins unless he stick into vagina? Not sure it should work this way + return pawn.records.GetValue(VariousDefOf.VaginalSexCount) == 0; } /// - /// Remove virginity if pawn is virgin and announce it + /// If pawn is virgin, lose his/her virginity. /// - public static void TryRemoveVirginity(this Pawn pawn, Pawn partner, SexProps props) + public static void PoptheCherry(this Pawn pawn, Pawn partner, SexProps props) { + if (props?.sexType != xxx.rjwSextype.Vaginal) + return; + int? removedDegree = Virginity.TraitHandler.RemoveVirginTrait(pawn); - if (SexperienceMod.Settings.EnableSexHistory && pawn.IsVirgin()) + if (pawn.IsVirgin()) { - pawn.TryGetComp()?.RecordFirst(partner); + pawn.TryGetComp()?.RecordFirst(partner, props); + if (removedDegree != null) + Messages.Message(Keyed.RS_LostVirgin(pawn.LabelShort, partner.LabelShort), MessageTypeDefOf.NeutralEvent, true); } - if (removedDegree != null && removedDegree != Virginity.TraitDegree.FemaleAfterSurgery) - { - Messages.Message(Keyed.RS_LostVirgin(pawn.LabelShort, partner.LabelShort), MessageTypeDefOf.NeutralEvent, true); + if (removedDegree != null) RJWUtility.ThrowVirginHistoryEvent(pawn, partner, props, (int)removedDegree); - } } } } diff --git a/Source/RJWSexperience/ExtensionMethods/SexPropsExtensions.cs b/Source/RJWSexperience/ExtensionMethods/SexPropsExtensions.cs index 185b1b3..6749c2b 100644 --- a/Source/RJWSexperience/ExtensionMethods/SexPropsExtensions.cs +++ b/Source/RJWSexperience/ExtensionMethods/SexPropsExtensions.cs @@ -19,22 +19,11 @@ namespace RJWSexperience.ExtensionMethods public static bool IsBestiality(this SexProps props) { - if (props.hasPartner()) + if (props.partner != null) { return props.pawn.IsAnimal() ^ props.partner.IsAnimal(); } return false; } - - /// - /// Get a not-so-unique ID. Same interaction between the same partners will return same ID - /// - public static int GetTempId(this SexProps props) - { - return props.pawn.GetHashCode() ^ - (props.partner?.GetHashCode() ?? 0) ^ - props.dictionaryKey.GetHashCode() ^ - (props.isReceiver ? 0 : 1); - } } } diff --git a/Source/RJWSexperience/Keyed.cs b/Source/RJWSexperience/Keyed.cs index ee3eb09..598ae22 100644 --- a/Source/RJWSexperience/Keyed.cs +++ b/Source/RJWSexperience/Keyed.cs @@ -9,14 +9,12 @@ namespace RJWSexperience public static class Keyed { public static string RS_LostVirgin(string pawn, string partner) => "RS_LostVirgin".Translate(pawn.Colorize(Color.yellow), partner.Colorize(Color.yellow)); - public static string RS_SexInfo(string sextype, int sexcount) => string.Format(RS_Sex_Info, sextype, sexcount); - public static string RS_SatAVG(float avgsat) => string.Format(RS_SAT_AVG, avgsat.ToStringPercent()); + public static string RS_Sex_Info(string sextype, string sexcount) => "RS_Sex_Info".Translate(sextype, sexcount); + public static string RS_SAT_AVG(string avgsat) => "RS_SAT_AVG".Translate(avgsat); public static string RS_HadBestSexDaysAgo(string days) => "RS_HadBestSexDaysAgo".Translate(days); public static readonly string Mod_Title = "RS_Mod_Title".Translate(); public static readonly string RSTotalGatheredCum = "RSTotalGatheredCum".Translate(); - public static readonly string RS_Sex_Info = "RS_Sex_Info".Translate(); - public static readonly string RS_SAT_AVG = "RS_SAT_AVG".Translate(); public static readonly string RS_Best_Sextype = "RS_Best_Sextype".Translate(); public static readonly string RS_Recent_Sextype = "RS_Recent_Sextype".Translate(); public static readonly string RS_Sex_Partners = "RS_Sex_Partners".Translate(); @@ -53,8 +51,7 @@ namespace RJWSexperience public static readonly string RS_SexSkill = "RS_SexSkill".Translate(); public static readonly string RS_NumofTimes = "RS_NumofTimes".Translate(); public static readonly string RS_Ago = "RS_Ago".Translate(); - public static readonly string RS_LastSex = "RS_LastSex".Translate().CapitalizeFirst(); - public static readonly string RS_PawnLockDesc = "RS_PawnLockDesc".Translate(); + public static readonly string RS_LastSex = "RS_LastSex".Translate(); [MayRequireRoyalty] public static readonly string Slave = "Slave".Translate(); public static readonly string TabLabelMain = "RSTabLabelMain".Translate(); diff --git a/Source/RJWSexperience/LustUtility.cs b/Source/RJWSexperience/LustUtility.cs index a89dd54..ba7aa8f 100644 --- a/Source/RJWSexperience/LustUtility.cs +++ b/Source/RJWSexperience/LustUtility.cs @@ -74,7 +74,7 @@ namespace RJWSexperience public static void UpdateLust(SexProps props, float satisfaction, float baseSatisfaction) { - float? lust = props.pawn.records?.GetValue(RsDefOf.Record.Lust); + float? lust = props.pawn.records?.GetValue(VariousDefOf.Lust); if (lust == null) return; @@ -97,7 +97,7 @@ namespace RJWSexperience return; LogManager.GetLogger("LustUtility").Message($"{props.pawn.NameShortColored}'s lust changed by {lustDelta} (from {lust})"); - props.pawn.records.AddTo(RsDefOf.Record.Lust, lustDelta); + props.pawn.records.AddTo(VariousDefOf.Lust, lustDelta); } private static float LustIncrementFactor(float lust) diff --git a/Source/RJWSexperience/Patches/RJW_Patch.cs b/Source/RJWSexperience/Patches/RJW_Patch.cs index cbb78f6..b3ccd7c 100644 --- a/Source/RJWSexperience/Patches/RJW_Patch.cs +++ b/Source/RJWSexperience/Patches/RJW_Patch.cs @@ -11,7 +11,7 @@ using Verse; namespace RJWSexperience { - [HarmonyPatch(typeof(JobDriver_Sex), "Orgasm")] // Despite the name, called every tick + [HarmonyPatch(typeof(JobDriver_Sex), "Orgasm")] public static class RJW_Patch_Orgasm { public static void Postfix(JobDriver_Sex __instance) @@ -20,17 +20,17 @@ namespace RJWSexperience { if (__instance.Sexprops.isRape && __instance.Sexprops.isReceiver) { - __instance.pawn?.skills?.Learn(RsDefOf.Skill.Sex, 0.05f, true); + __instance.pawn?.skills?.Learn(VariousDefOf.Sex, 0.05f, true); } else { - __instance.pawn?.skills?.Learn(RsDefOf.Skill.Sex, 0.35f, true); + __instance.pawn?.skills?.Learn(VariousDefOf.Sex, 0.35f, true); } } } } - [HarmonyPatch(typeof(SexUtility), nameof(SexUtility.SatisfyPersonal))] // Actual on orgasm method + [HarmonyPatch(typeof(SexUtility), nameof(SexUtility.SatisfyPersonal))] public static class RJW_Patch_SatisfyPersonal { private const float base_sat_per_fuck = 0.4f; @@ -44,9 +44,9 @@ namespace RJWSexperience { LustUtility.UpdateLust(props, satisfaction, base_sat_per_fuck); CumUtility.FillCumBuckets(props); - props.pawn.records?.Increment(RsDefOf.Record.OrgasmCount); + props.pawn.records?.Increment(VariousDefOf.OrgasmCount); if (SexperienceMod.Settings.EnableSexHistory && props.hasPartner()) - props.pawn.TryGetComp()?.RecordOrgasm(props.partner, props, satisfaction); + props.pawn.TryGetComp()?.RecordSatisfaction(props.partner, props, satisfaction); } } @@ -64,7 +64,7 @@ namespace RJWSexperience { public static void Postfix(Pawn pawn) { - SkillRecord sexskill = pawn.skills.GetSkill(RsDefOf.Skill.Sex); + SkillRecord sexskill = pawn.skills.GetSkill(VariousDefOf.Sex); if (sexskill != null) { sexskill.passion = Passion.Major; @@ -94,10 +94,10 @@ namespace RJWSexperience { public static void Postfix(JobDriver_SexBaseInitiator __instance) { - if (__instance.Sexprops.hasPartner() && __instance.Sexprops.sexType == xxx.rjwSextype.Vaginal) + if (__instance.Sexprops.hasPartner()) { - __instance.pawn.TryRemoveVirginity(__instance.Partner, __instance.Sexprops); - __instance.Partner.TryRemoveVirginity(__instance.pawn, __instance.Sexprops); + __instance.pawn.PoptheCherry(__instance.Partner, __instance.Sexprops); + __instance.Partner.PoptheCherry(__instance.pawn, __instance.Sexprops); } } } @@ -108,7 +108,9 @@ namespace RJWSexperience /// /// If masturbation and current map has a bucket, return location near the bucket /// - /// The place to stand near a bucket + /// + /// + /// /// Run original method public static bool Prefix(Pawn pawn, Pawn partner, ref IntVec3 __result) { diff --git a/Source/RJWSexperience/Patches/Rimworld_Patch.cs b/Source/RJWSexperience/Patches/Rimworld_Patch.cs index d00a943..0db6038 100644 --- a/Source/RJWSexperience/Patches/Rimworld_Patch.cs +++ b/Source/RJWSexperience/Patches/Rimworld_Patch.cs @@ -32,11 +32,11 @@ namespace RJWSexperience if (!pawn.relations.DirectRelationExists(PawnRelationDefOf.Parent, newMother)) return; - Trait virgin = newMother.story?.traits?.GetTrait(RsDefOf.Trait.Virgin, Virginity.TraitDegree.FemaleVirgin); + Trait virgin = newMother.story?.traits?.GetTrait(VariousDefOf.Virgin, Virginity.TraitDegree.FemaleVirgin); if (virgin != null) { newMother.story.traits.RemoveTrait(virgin); - newMother.story.traits.GainTrait(new Trait(RsDefOf.Trait.Virgin, Virginity.TraitDegree.FemaleAfterSurgery)); + newMother.story.traits.GainTrait(new Trait(VariousDefOf.Virgin, Virginity.TraitDegree.FemaleAfterSurgery)); } } } diff --git a/Source/RJWSexperience/RJWSexperience.csproj b/Source/RJWSexperience/RJWSexperience.csproj index 2aef4a8..6540f16 100644 --- a/Source/RJWSexperience/RJWSexperience.csproj +++ b/Source/RJWSexperience/RJWSexperience.csproj @@ -30,9 +30,6 @@ prompt 4 - - true - ..\..\..\rjw\1.4\Assemblies\RJW.dll @@ -67,12 +64,6 @@ - - - - - - @@ -95,10 +86,10 @@ - - + + - + diff --git a/Source/RJWSexperience/RJWUtility.cs b/Source/RJWSexperience/RJWUtility.cs index d980f0c..19d4160 100644 --- a/Source/RJWSexperience/RJWUtility.cs +++ b/Source/RJWSexperience/RJWUtility.cs @@ -58,52 +58,52 @@ namespace RJWSexperience { case xxx.rjwSextype.Vaginal: case xxx.rjwSextype.Scissoring: - IncreaseSameRecords(pawn, partner, RsDefOf.Record.VaginalSexCount); + IncreaseSameRecords(pawn, partner, VariousDefOf.VaginalSexCount); break; case xxx.rjwSextype.Anal: - IncreaseSameRecords(pawn, partner, RsDefOf.Record.AnalSexCount); + IncreaseSameRecords(pawn, partner, VariousDefOf.AnalSexCount); break; case xxx.rjwSextype.Oral: case xxx.rjwSextype.Fellatio: if (Genital_Helper.has_penis_fertile(giver) || Genital_Helper.has_penis_infertile(giver)) { - IncreaseRecords(giver, receiver, RsDefOf.Record.OralSexCount, RsDefOf.Record.BlowjobCount); + IncreaseRecords(giver, receiver, VariousDefOf.OralSexCount, VariousDefOf.BlowjobCount); } else if (Genital_Helper.has_penis_fertile(receiver) || Genital_Helper.has_penis_infertile(receiver)) { - IncreaseRecords(giver, receiver, RsDefOf.Record.BlowjobCount, RsDefOf.Record.OralSexCount); + IncreaseRecords(giver, receiver, VariousDefOf.BlowjobCount, VariousDefOf.OralSexCount); } break; case xxx.rjwSextype.Sixtynine: - IncreaseSameRecords(pawn, partner, RsDefOf.Record.OralSexCount); + IncreaseSameRecords(pawn, partner, VariousDefOf.OralSexCount); RecordDef recordpawn, recordpartner; if (Genital_Helper.has_penis_fertile(pawn) || Genital_Helper.has_penis_infertile(pawn)) { - recordpartner = RsDefOf.Record.BlowjobCount; + recordpartner = VariousDefOf.BlowjobCount; } else { - recordpartner = RsDefOf.Record.CunnilingusCount; + recordpartner = VariousDefOf.CunnilingusCount; } if (Genital_Helper.has_penis_fertile(partner) || Genital_Helper.has_penis_infertile(partner)) { - recordpawn = RsDefOf.Record.BlowjobCount; + recordpawn = VariousDefOf.BlowjobCount; } else { - recordpawn = RsDefOf.Record.CunnilingusCount; + recordpawn = VariousDefOf.CunnilingusCount; } IncreaseRecords(pawn, partner, recordpawn, recordpartner); break; case xxx.rjwSextype.Cunnilingus: if (Genital_Helper.has_vagina(giver)) { - IncreaseRecords(giver, receiver, RsDefOf.Record.OralSexCount, RsDefOf.Record.CunnilingusCount); + IncreaseRecords(giver, receiver, VariousDefOf.OralSexCount, VariousDefOf.CunnilingusCount); } else if (Genital_Helper.has_vagina(receiver)) { - IncreaseRecords(giver, receiver, RsDefOf.Record.CunnilingusCount, RsDefOf.Record.OralSexCount); + IncreaseRecords(giver, receiver, VariousDefOf.CunnilingusCount, VariousDefOf.OralSexCount); } break; case xxx.rjwSextype.Masturbation: @@ -111,29 +111,29 @@ namespace RJWSexperience case xxx.rjwSextype.Handjob: if (Genital_Helper.has_penis_fertile(giver) || Genital_Helper.has_penis_infertile(giver)) { - IncreaseRecords(giver, receiver, RsDefOf.Record.GenitalCaressCount, RsDefOf.Record.HandjobCount); + IncreaseRecords(giver, receiver, VariousDefOf.GenitalCaressCount, VariousDefOf.HandjobCount); } else { - IncreaseRecords(giver, receiver, RsDefOf.Record.HandjobCount, RsDefOf.Record.GenitalCaressCount); + IncreaseRecords(giver, receiver, VariousDefOf.HandjobCount, VariousDefOf.GenitalCaressCount); } break; case xxx.rjwSextype.Fingering: case xxx.rjwSextype.Fisting: if (Genital_Helper.has_vagina(giver)) { - IncreaseRecords(giver, receiver, RsDefOf.Record.GenitalCaressCount, RsDefOf.Record.FingeringCount); + IncreaseRecords(giver, receiver, VariousDefOf.GenitalCaressCount, VariousDefOf.FingeringCount); } else { - IncreaseRecords(giver, receiver, RsDefOf.Record.FingeringCount, RsDefOf.Record.GenitalCaressCount); + IncreaseRecords(giver, receiver, VariousDefOf.FingeringCount, VariousDefOf.GenitalCaressCount); } break; case xxx.rjwSextype.Footjob: - IncreaseSameRecords(pawn, partner, RsDefOf.Record.FootjobCount); + IncreaseSameRecords(pawn, partner, VariousDefOf.FootjobCount); break; default: - IncreaseSameRecords(pawn, partner, RsDefOf.Record.MiscSexualBehaviorCount); + IncreaseSameRecords(pawn, partner, VariousDefOf.MiscSexualBehaviorCount); break; } } @@ -154,7 +154,7 @@ namespace RJWSexperience // Moved this method back because of Menstruation public static Building_CumBucket FindClosestBucket(this Pawn pawn) { - List buckets = pawn.Map.listerBuildings.allBuildingsColonist.FindAll(x => x is Building_CumBucket bucket && bucket.StoredStackCount < RsDefOf.Thing.GatheredCum.stackLimit); + List buckets = pawn.Map.listerBuildings.allBuildingsColonist.FindAll(x => x is Building_CumBucket bucket && bucket.StoredStackCount < VariousDefOf.GatheredCum.stackLimit); if (buckets.NullOrEmpty()) return null; diff --git a/Source/RJWSexperience/RsDefOf.cs b/Source/RJWSexperience/RsDefOf.cs deleted file mode 100644 index d617947..0000000 --- a/Source/RJWSexperience/RsDefOf.cs +++ /dev/null @@ -1,78 +0,0 @@ -using RimWorld; -using Verse; - -namespace RJWSexperience -{ - public static class RsDefOf - { - [DefOf] - public static class Record - { - public static readonly RecordDef NumofEatenCum; - public static readonly RecordDef AmountofEatenCum; - public static readonly RecordDef Lust; - public static readonly RecordDef VaginalSexCount; - public static readonly RecordDef AnalSexCount; - public static readonly RecordDef OralSexCount; - public static readonly RecordDef BlowjobCount; - public static readonly RecordDef CunnilingusCount; - public static readonly RecordDef GenitalCaressCount; - public static readonly RecordDef HandjobCount; - public static readonly RecordDef FingeringCount; - public static readonly RecordDef FootjobCount; - public static readonly RecordDef MiscSexualBehaviorCount; - public static readonly RecordDef SexPartnerCount; - public static readonly RecordDef OrgasmCount; - } - - [DefOf] - public static class Skill - { - public static readonly SkillDef Sex; - } - - [DefOf] - public static class Thing - { - public static readonly ThingDef GatheredCum; - public static readonly ThingDef FilthCum; - } - - [DefOf] - public static class Chemical - { - public static readonly ChemicalDef Cum; - } - - [DefOf] - public static class Need - { - public static readonly NeedDef Chemical_Cum; - } - - [DefOf] - public static class Trait - { - public static readonly TraitDef Virgin; - } - - [DefOf] - public static class KeyBinding - { - public static readonly KeyBindingDef OpenSexStatistics; - } - - [DefOf] - public static class Stat - { - public static readonly StatDef SexAbility; - } - - [DefOf] - public static class Hediff - { - public static readonly HediffDef CumAddiction; - public static readonly HediffDef CumTolerance; - } - } -} diff --git a/Source/RJWSexperience/SexHistory/HistoryUtility.cs b/Source/RJWSexperience/SexHistory/HistoryUtility.cs index fede9bc..9e06c28 100644 --- a/Source/RJWSexperience/SexHistory/HistoryUtility.cs +++ b/Source/RJWSexperience/SexHistory/HistoryUtility.cs @@ -1,4 +1,5 @@ using RimWorld; +using System; using UnityEngine; using Verse; diff --git a/Source/RJWSexperience/SexHistory/RecordRandomizer.cs b/Source/RJWSexperience/SexHistory/RecordRandomizer.cs index b1c61f9..98d807b 100644 --- a/Source/RJWSexperience/SexHistory/RecordRandomizer.cs +++ b/Source/RJWSexperience/SexHistory/RecordRandomizer.cs @@ -95,8 +95,8 @@ namespace RJWSexperience.SexHistory minValue = float.MinValue; value = Mathf.Clamp(value, minValue, float.MaxValue); - float recordvalue = pawn.records.GetValue(RsDefOf.Record.Lust); - pawn.records.AddTo(RsDefOf.Record.Lust, value - recordvalue); + float recordvalue = pawn.records.GetValue(VariousDefOf.Lust); + pawn.records.AddTo(VariousDefOf.Lust, value - recordvalue); return value; } @@ -145,7 +145,7 @@ namespace RJWSexperience.SexHistory totalSexCount += RandomizeRecord(pawn, xxx.CountOfSexWithHumanlikes, avgsex, deviation); if (totalSexCount > 0) - pawn.records.AddTo(RsDefOf.Record.SexPartnerCount, Math.Max(1, Rand.Range(0, totalSexCount / 7))); + pawn.records.AddTo(VariousDefOf.SexPartnerCount, Math.Max(1, Rand.Range(0, totalSexCount / 7))); return totalSexCount; } @@ -170,67 +170,67 @@ namespace RJWSexperience.SexHistory Gender prefer = PreferredGender(pawn); int sex = (int)(totalsex * RJWPreferenceSettings.vaginal / totalweight); totalsex -= sex; - pawn.records.AddTo(RsDefOf.Record.VaginalSexCount, sex); + pawn.records.AddTo(VariousDefOf.VaginalSexCount, sex); sex = (int)(totalsex * RJWPreferenceSettings.anal / totalweight); totalsex -= sex; - pawn.records.AddTo(RsDefOf.Record.AnalSexCount, sex); + pawn.records.AddTo(VariousDefOf.AnalSexCount, sex); sex = (int)(totalsex * RJWPreferenceSettings.fellatio / totalweight); totalsex -= sex; - if (prefer == Gender.Male) pawn.records.AddTo(RsDefOf.Record.BlowjobCount, sex); - else pawn.records.AddTo(RsDefOf.Record.OralSexCount, sex); + if (prefer == Gender.Male) pawn.records.AddTo(VariousDefOf.BlowjobCount, sex); + else pawn.records.AddTo(VariousDefOf.OralSexCount, sex); sex = (int)(totalsex * RJWPreferenceSettings.cunnilingus / totalweight); totalsex -= sex; - if (prefer == Gender.Male) pawn.records.AddTo(RsDefOf.Record.OralSexCount, sex); - else pawn.records.AddTo(RsDefOf.Record.CunnilingusCount, sex); + if (prefer == Gender.Male) pawn.records.AddTo(VariousDefOf.OralSexCount, sex); + else pawn.records.AddTo(VariousDefOf.CunnilingusCount, sex); sex = (int)(totalsex * RJWPreferenceSettings.rimming / totalweight); totalsex -= sex; - pawn.records.AddTo(RsDefOf.Record.MiscSexualBehaviorCount, sex); + pawn.records.AddTo(VariousDefOf.MiscSexualBehaviorCount, sex); sex = (int)(totalsex * RJWPreferenceSettings.double_penetration / totalweight) / 2; totalsex -= sex; totalsex -= sex; - pawn.records.AddTo(RsDefOf.Record.VaginalSexCount, sex); - pawn.records.AddTo(RsDefOf.Record.AnalSexCount, sex); + pawn.records.AddTo(VariousDefOf.VaginalSexCount, sex); + pawn.records.AddTo(VariousDefOf.AnalSexCount, sex); sex = (int)(totalsex * RJWPreferenceSettings.breastjob / totalweight); totalsex -= sex; - pawn.records.AddTo(RsDefOf.Record.MiscSexualBehaviorCount, sex); + pawn.records.AddTo(VariousDefOf.MiscSexualBehaviorCount, sex); sex = (int)(totalsex * RJWPreferenceSettings.handjob / totalweight); totalsex -= sex; - if (prefer == Gender.Male) pawn.records.AddTo(RsDefOf.Record.HandjobCount, sex); - else pawn.records.AddTo(RsDefOf.Record.GenitalCaressCount, sex); + if (prefer == Gender.Male) pawn.records.AddTo(VariousDefOf.HandjobCount, sex); + else pawn.records.AddTo(VariousDefOf.GenitalCaressCount, sex); sex = (int)(totalsex * RJWPreferenceSettings.fingering / totalweight); totalsex -= sex; - if (prefer == Gender.Female) pawn.records.AddTo(RsDefOf.Record.FingeringCount, sex); - else pawn.records.AddTo(RsDefOf.Record.GenitalCaressCount, sex); + if (prefer == Gender.Female) pawn.records.AddTo(VariousDefOf.FingeringCount, sex); + else pawn.records.AddTo(VariousDefOf.GenitalCaressCount, sex); sex = (int)(totalsex * RJWPreferenceSettings.mutual_masturbation / totalweight); totalsex -= sex; - if (prefer == Gender.Male) pawn.records.AddTo(RsDefOf.Record.HandjobCount, sex); - else pawn.records.AddTo(RsDefOf.Record.FingeringCount, sex); - pawn.records.AddTo(RsDefOf.Record.GenitalCaressCount, sex); + if (prefer == Gender.Male) pawn.records.AddTo(VariousDefOf.HandjobCount, sex); + else pawn.records.AddTo(VariousDefOf.FingeringCount, sex); + pawn.records.AddTo(VariousDefOf.GenitalCaressCount, sex); sex = (int)(totalsex * RJWPreferenceSettings.footjob / totalweight); totalsex -= sex; - pawn.records.AddTo(RsDefOf.Record.FootjobCount, sex); + pawn.records.AddTo(VariousDefOf.FootjobCount, sex); sex = (int)(totalsex * RJWPreferenceSettings.scissoring / totalweight); totalsex -= sex; - pawn.records.AddTo(RsDefOf.Record.MiscSexualBehaviorCount, sex); + pawn.records.AddTo(VariousDefOf.MiscSexualBehaviorCount, sex); sex = (int)(totalsex * RJWPreferenceSettings.fisting / totalweight); totalsex -= sex; - pawn.records.AddTo(RsDefOf.Record.MiscSexualBehaviorCount, sex); + pawn.records.AddTo(VariousDefOf.MiscSexualBehaviorCount, sex); - pawn.records.AddTo(RsDefOf.Record.OralSexCount, totalsex); - if (prefer == Gender.Male) pawn.records.AddTo(RsDefOf.Record.BlowjobCount, totalsex); - else pawn.records.AddTo(RsDefOf.Record.CunnilingusCount, totalsex); + pawn.records.AddTo(VariousDefOf.OralSexCount, totalsex); + if (prefer == Gender.Male) pawn.records.AddTo(VariousDefOf.BlowjobCount, totalsex); + else pawn.records.AddTo(VariousDefOf.CunnilingusCount, totalsex); } private static Gender PreferredGender(Pawn pawn) diff --git a/Source/RJWSexperience/SexHistory/SexHistoryComp.cs b/Source/RJWSexperience/SexHistory/SexHistoryComp.cs index a78a904..65f7928 100644 --- a/Source/RJWSexperience/SexHistory/SexHistoryComp.cs +++ b/Source/RJWSexperience/SexHistory/SexHistoryComp.cs @@ -6,14 +6,11 @@ using Verse; namespace RJWSexperience.SexHistory { - /// - /// Stores pawn's sex history and handles its updates - /// public class SexHistoryComp : ThingComp { public const int ARRLEN = 20; - protected Dictionary partnerRecords = new Dictionary(); + protected Dictionary histories = new Dictionary(); protected string first = ""; protected bool dirty = true; protected xxx.rjwSextype recentSex = xxx.rjwSextype.None; @@ -46,14 +43,17 @@ namespace RJWSexperience.SexHistory protected int bestSexTickAbsCache = 0; public Gizmo Gizmo { get; private set; } + public Pawn ParentPawn => parent as Pawn; - public SexPartnerHistoryRecord FirstPartnerRecord => partnerRecords.TryGetValue(first); - public SexPartnerHistoryRecord MostPartnerRecord + + public SexPartnerHistoryRecord GetFirstPartnerHistory => histories.TryGetValue(first); + + public SexPartnerHistoryRecord GetMostPartnerHistory { get { Update(); - return partnerRecords.TryGetValue(mostPartnerCache); + return histories.TryGetValue(mostPartnerCache); } } public xxx.rjwSextype MostSextype @@ -72,13 +72,13 @@ namespace RJWSexperience.SexHistory return mostSatSextypeCache; } } - public SexPartnerHistoryRecord RecentPartnerRecord => partnerRecords.TryGetValue(recentPartner); - public SexPartnerHistoryRecord BestSexPartnerRecord + public SexPartnerHistoryRecord GetRecentPartnersHistory => histories.TryGetValue(recentPartner); + public SexPartnerHistoryRecord GetBestSexPartnerHistory { get { Update(); - return partnerRecords.TryGetValue(bestPartnerCache); + return histories.TryGetValue(bestPartnerCache); } } public float TotalSexHad @@ -90,20 +90,27 @@ namespace RJWSexperience.SexHistory } } public int VirginsTaken => virginsTaken; - public IEnumerable PartnerList + public List PartnerList { get { - IEnumerable res = Enumerable.Empty(); + List res = null; Update(); - if (!partnerRecords.NullOrEmpty()) + if (!histories.NullOrEmpty()) { - res = partnerRecords.Values; + res = histories.Values.ToList(); } return res; } } - public int PartnerCount => partnerRecords?.Count ?? 0; + public int PartnerCount + { + get + { + if (histories == null) histories = new Dictionary(); + return histories.Count; + } + } public int IncestuousCount => incestuous; public int RapedCount { @@ -153,6 +160,7 @@ namespace RJWSexperience.SexHistory public int FirstSexTickAbs => firstSexTickAbs; public int MostSexTickAbs => mostSexTickAbsCache; public int BestSexTickAbs => bestSexTickAbsCache; + public Pawn PreferRacePawn { get @@ -178,9 +186,9 @@ namespace RJWSexperience.SexHistory public int GetSextypeRecentTickAbs(int sextype) => sextypeRecentTickAbs[sextype]; - public float GetAVGSat(int sextype) + public float GetAVGSat(int index) { - float res = sextypeSat[sextype] / sextypeCount[sextype]; + float res = sextypeSat[index] / sextypeCount[index]; return float.IsNaN(res) ? 0f : res; } @@ -205,7 +213,7 @@ namespace RJWSexperience.SexHistory sextyperecenttickabssave = new List(); } - Scribe_Collections.Look(ref partnerRecords, "histories", LookMode.Value, LookMode.Deep); + Scribe_Collections.Look(ref histories, "histories", LookMode.Value, LookMode.Deep); Scribe_Values.Look(ref first, "first", string.Empty); Scribe_Values.Look(ref recentSex, "recentsex", xxx.rjwSextype.None); Scribe_Values.Look(ref recentSat, "recentsat", 0); @@ -220,8 +228,8 @@ namespace RJWSexperience.SexHistory Scribe_Collections.Look(ref sextypesatsave, "sextypesatsave", LookMode.Value); Scribe_Collections.Look(ref sextyperecenttickabssave, "sextyperecenttickabssave", LookMode.Value); - if (partnerRecords == null) - partnerRecords = new Dictionary(); + if (histories == null) + histories = new Dictionary(); if (Scribe.mode == LoadSaveMode.LoadingVars) { @@ -229,7 +237,7 @@ namespace RJWSexperience.SexHistory sextypeSat = sextypesatsave?.ToArray() ?? new float[ARRLEN]; sextypeRecentTickAbs = sextyperecenttickabssave?.ToArray() ?? new int[ARRLEN]; - foreach (KeyValuePair element in partnerRecords) + foreach (KeyValuePair element in histories) { element.Value.PartnerID = element.Key; } @@ -239,53 +247,51 @@ namespace RJWSexperience.SexHistory public void RecordSex(Pawn partner, SexProps props) { - SexPartnerHistoryRecord partnerRecord = GetPartnerRecord(partner); - partnerRecord.RecordSex(props); + RecordFirst(partner, props); + GetPartnerRecord(partner)?.RecordSex(props); recentPartner = partner.ThingID; recentSex = props.sexType; sextypeCount[(int)props.sexType]++; sextypeRecentTickAbs[(int)props.sexType] = GenTicks.TicksAbs; - if (partnerRecord.Incest) incestuous++; + if (partner.IsIncest(ParentPawn)) incestuous++; if (partner.Dead) corpsefuck++; if (props.IsBestiality()) bestiality++; else if (ParentPawn.def != partner.def) interspecies++; dirty = true; } - public void RecordOrgasm(Pawn partner, SexProps props, float satisfaction) + public void RecordSatisfaction(Pawn partner, SexProps props, float satisfaction) { - GetPartnerRecord(partner).RecordOrgasm(props.sexType, satisfaction); + RecordFirst(partner, props); + GetPartnerRecord(partner)?.RecordSatisfaction(props, satisfaction); recentSat = satisfaction; - sextypeSat[(int)props.sexType] += satisfaction; // Several orgasmsms in one sex are messing with this + sextypeSat[(int)props.sexType] += satisfaction; dirty = true; } - /// - /// Record first partner and time of sex. No checks are performed, the caller should make sure it is the first time. - /// - /// - public void RecordFirst(Pawn partner) + public void RecordFirst(Pawn partner, SexProps props) { - first = partner.ThingID; - firstSexTickAbs = GenTicks.TicksAbs; - partner.TryGetComp()?.TakeSomeonesVirgin(ParentPawn); + if (VirginCheck() && props.sexType == xxx.rjwSextype.Vaginal) + { + first = partner.ThingID; + SexHistoryComp history = partner.TryGetComp(); + firstSexTickAbs = GenTicks.TicksAbs; + history?.TakeSomeonesVirgin(ParentPawn); + } } - /// - /// Retrive an existing partner record or add a new one. Increments SexPartnerCount when new record is added - /// protected SexPartnerHistoryRecord GetPartnerRecord(Pawn partner) { string partnerId = partner.ThingID; - if (partnerRecords.TryGetValue(partnerId, out SexPartnerHistoryRecord record)) + if (histories.TryGetValue(partnerId, out SexPartnerHistoryRecord record)) { return record; } SexPartnerHistoryRecord newRecord = new SexPartnerHistoryRecord(partner, partner.IsIncest(ParentPawn)); - partnerRecords.Add(partnerId, newRecord); - ParentPawn.records.Increment(RsDefOf.Record.SexPartnerCount); + histories.Add(partnerId, newRecord); + ParentPawn.records.Increment(VariousDefOf.SexPartnerCount); return newRecord; } @@ -322,7 +328,7 @@ namespace RJWSexperience.SexHistory Dictionary racetotalsat = new Dictionary(); List allpartners = new List(); - foreach (KeyValuePair element in partnerRecords) + foreach (KeyValuePair element in histories) { SexPartnerHistoryRecord h = element.Value; @@ -380,9 +386,9 @@ namespace RJWSexperience.SexHistory mostPartnerCache = mostID; bestPartnerCache = bestID; - recentSexTickAbsCache = partnerRecords.TryGetValue(recentPartner)?.RecentSexTickAbs ?? 0; - mostSexTickAbsCache = partnerRecords.TryGetValue(mostPartnerCache)?.RecentSexTickAbs ?? 0; - bestSexTickAbsCache = partnerRecords.TryGetValue(bestPartnerCache)?.BestSexTickAbs ?? 0; + recentSexTickAbsCache = histories.TryGetValue(recentPartner)?.RecentSexTickAbs ?? 0; + mostSexTickAbsCache = histories.TryGetValue(mostPartnerCache)?.RecentSexTickAbs ?? 0; + bestSexTickAbsCache = histories.TryGetValue(bestPartnerCache)?.BestSexTickAbs ?? 0; racetotalsat.Clear(); allpartners.Clear(); @@ -408,6 +414,14 @@ namespace RJWSexperience.SexHistory #endregion Cache update + protected bool VirginCheck() + { + if (histories.TryGetValue(first) != null) + return false; + + return ParentPawn.IsVirgin(); + } + public override IEnumerable CompGetGizmosExtra() { if (SexperienceMod.Settings.HideGizmoWhenDrafted && ParentPawn.Drafted) @@ -428,8 +442,11 @@ namespace RJWSexperience.SexHistory defaultLabel = Keyed.RS_Sex_History, icon = HistoryUtility.HistoryIcon, defaultIconColor = HistoryUtility.HistoryColor, - hotKey = RsDefOf.KeyBinding.OpenSexStatistics, - action = () => UI.SexStatusWindow.ToggleWindow(this) + hotKey = VariousDefOf.OpenSexStatistics, + action = delegate + { + UI.SexStatusWindow.ToggleWindow(ParentPawn, this); + } }; } } diff --git a/Source/RJWSexperience/SexHistory/SexPartnerHistoryRecord.cs b/Source/RJWSexperience/SexHistory/SexPartnerHistoryRecord.cs index 9bcc832..cb17485 100644 --- a/Source/RJWSexperience/SexHistory/SexPartnerHistoryRecord.cs +++ b/Source/RJWSexperience/SexHistory/SexPartnerHistoryRecord.cs @@ -1,5 +1,6 @@ using rjw; using RJWSexperience.ExtensionMethods; +using System.Collections.Generic; using Verse; namespace RJWSexperience.SexHistory @@ -104,13 +105,13 @@ namespace RJWSexperience.SexHistory recentSexTickAbs = GenTicks.TicksAbs; } - public void RecordOrgasm(xxx.rjwSextype sextype, float satisfaction) + public void RecordSatisfaction(SexProps props, float satisfaction) { orgasms++; if (satisfaction > bestSatisfaction) { - bestSextype = sextype; + bestSextype = props.sexType; bestSatisfaction = satisfaction; bestSexTickAbs = GenTicks.TicksAbs; } @@ -130,5 +131,33 @@ namespace RJWSexperience.SexHistory } partner = Find.WorldPawns.AllPawnsAliveOrDead.Find(x => x.ThingID.Equals(partnerID)); } + + #region OrderComparers + + public class RecentOrderComparer : IComparer + { + public int Compare(SexPartnerHistoryRecord x, SexPartnerHistoryRecord y) + { + return y.RecentSexTickAbs.CompareTo(x.RecentSexTickAbs); + } + } + + public class MostOrderComparer : IComparer + { + public int Compare(SexPartnerHistoryRecord x, SexPartnerHistoryRecord y) + { + return y.TotalSexCount.CompareTo(x.TotalSexCount); + } + } + + public class NameOrderComparer : IComparer + { + public int Compare(SexPartnerHistoryRecord x, SexPartnerHistoryRecord y) + { + return x.Label.CompareTo(y.Label); + } + } + + #endregion OrderComparers } } diff --git a/Source/RJWSexperience/SexHistory/UI/BarInfo.cs b/Source/RJWSexperience/SexHistory/UI/BarInfo.cs deleted file mode 100644 index b03341b..0000000 --- a/Source/RJWSexperience/SexHistory/UI/BarInfo.cs +++ /dev/null @@ -1,35 +0,0 @@ -using UnityEngine; -using Verse; - -namespace RJWSexperience.SexHistory.UI -{ - public readonly struct BarInfo - { - public readonly string label; - public readonly float fillPercent; - public readonly Texture2D fillTexture; - public readonly TipSignal tooltip; - public readonly string labelRight; - public readonly Texture2D border; - - public BarInfo(string label, float fillPercent, Texture2D fillTexture, TipSignal tooltip, string labelRight = "", Texture2D border = null) - { - this.label = label.CapitalizeFirst(); - this.fillPercent = Mathf.Clamp01(fillPercent); - this.fillTexture = fillTexture; - this.tooltip = tooltip; - this.labelRight = labelRight.CapitalizeFirst(); - this.border = border; - } - - public BarInfo(string label, float fillPercent, Texture2D fillTexture, string labelRight = "") - { - this.label = label.CapitalizeFirst(); - this.fillPercent = Mathf.Clamp01(fillPercent); - this.fillTexture = fillTexture; - this.tooltip = default; - this.labelRight = labelRight.CapitalizeFirst(); - this.border = null; - } - } -} diff --git a/Source/RJWSexperience/SexHistory/UI/InfoCard.cs b/Source/RJWSexperience/SexHistory/UI/InfoCard.cs deleted file mode 100644 index 108305e..0000000 --- a/Source/RJWSexperience/SexHistory/UI/InfoCard.cs +++ /dev/null @@ -1,86 +0,0 @@ -using RimWorld; -using rjw; -using System; -using UnityEngine; -using Verse; - -namespace RJWSexperience.SexHistory.UI -{ - public readonly struct InfoCard - { - public readonly SexPartnerHistoryRecord partnerRecord; - public readonly string label; - public readonly string lastSexTime; - public readonly string name; - public readonly string sexCount; - public readonly string orgasms; - public readonly string relations; - public readonly BarInfo bestSextype; - public readonly PartnerPortraitInfo portraitInfo; - public readonly TipSignal tooltip; - - public InfoCard(Pawn pawn, SexPartnerHistoryRecord partnerRecord, string label, string tooltipLabel, int lastSexTimeTicks) - { - this.partnerRecord = partnerRecord; - this.label = label; - - lastSexTime = UIUtility.GetSexDays(lastSexTimeTicks); - portraitInfo = new PartnerPortraitInfo(pawn, partnerRecord); - - if (partnerRecord != null) - { - name = partnerRecord.Partner?.Name?.ToStringFull ?? partnerRecord.Label.CapitalizeFirst(); - sexCount = Keyed.RS_Sex_Count + partnerRecord.TotalSexCount; - - if (partnerRecord.Raped > 0) - { - sexCount += " " + Keyed.RS_Raped + partnerRecord.Raped; - } - if (partnerRecord.RapedMe > 0) - { - sexCount += " " + Keyed.RS_RapedMe + partnerRecord.RapedMe; - } - - orgasms = Keyed.RS_Orgasms + partnerRecord.OrgasmCount; - relations = pawn.GetRelationsString(partnerRecord.Partner); - tooltip = new TipSignal(() => - { - string completeTip = tooltipLabel; - - if (partnerRecord.Incest) - { - completeTip += " - " + Keyed.Incest; - } - if (partnerRecord.IamFirst) - { - completeTip += "\n" + Keyed.RS_LostVirgin(partnerRecord.Label, pawn.LabelShort); - } - if (partnerRecord.BestSexTickAbs != 0) - { - completeTip += "\n" + Keyed.RS_HadBestSexDaysAgo(partnerRecord.BestSexElapsedTicks.ToStringTicksToDays() + " " + Keyed.RS_Ago); - } - return completeTip; - }, tooltipLabel.GetHashCode()); - - float relativeBestSatisfaction = partnerRecord.BestSatisfaction / UIUtility.BASESAT; - bestSextype = new BarInfo( - label: Keyed.RS_Best_Sextype + ": " + Keyed.Sextype[(int)partnerRecord.BestSextype], - fillPercent: relativeBestSatisfaction / 2, - fillTexture: HistoryUtility.SextypeColor[(int)partnerRecord.BestSextype], - labelRight: relativeBestSatisfaction.ToStringPercent()); - } - else - { - name = Keyed.Unknown; - sexCount = Keyed.RS_Sex_Count + "?"; - orgasms = Keyed.RS_Orgasms + "?"; - relations = string.Empty; - tooltip = default; - bestSextype = new BarInfo( - label: String.Format(Keyed.RS_Best_Sextype + ": {0}", Keyed.Sextype[(int)xxx.rjwSextype.None]), - fillPercent: 0f, - fillTexture: Texture2D.linearGrayTexture); - } - } - } -} diff --git a/Source/RJWSexperience/SexHistory/UI/PartnerOrderMode.cs b/Source/RJWSexperience/SexHistory/UI/PartnerOrderMode.cs deleted file mode 100644 index 2fc7401..0000000 --- a/Source/RJWSexperience/SexHistory/UI/PartnerOrderMode.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace RJWSexperience.SexHistory.UI -{ - public enum PartnerOrderMode - { - Normal = 0, - Recent = 1, - Most = 2, - Name = 3 - }; - - public static class PartnerOrderModeExtension - { - public static PartnerOrderMode Next(this PartnerOrderMode mode) - { - return (PartnerOrderMode)(((int)mode + 1) % 4); - } - } -} diff --git a/Source/RJWSexperience/SexHistory/UI/PartnerPortraitInfo.cs b/Source/RJWSexperience/SexHistory/UI/PartnerPortraitInfo.cs deleted file mode 100644 index 2de32de..0000000 --- a/Source/RJWSexperience/SexHistory/UI/PartnerPortraitInfo.cs +++ /dev/null @@ -1,34 +0,0 @@ -using RimWorld; -using System; -using UnityEngine; -using Verse; - -namespace RJWSexperience.SexHistory.UI -{ - public readonly struct PartnerPortraitInfo - { - public readonly SexPartnerHistoryRecord partnerRecord; - public readonly bool lover; - public readonly Func portraitGetter; - - public PartnerPortraitInfo(Pawn pawn, SexPartnerHistoryRecord partnerRecord) - { - this.partnerRecord = partnerRecord; - lover = false; - - if (partnerRecord?.Partner != null) - { - portraitGetter = (size) => PortraitsCache.Get(partnerRecord.Partner, size, Rot4.South, default, 1, true, true, false, false); - lover = LovePartnerRelationUtility.LovePartnerRelationExists(pawn, partnerRecord.Partner); - } - else if (partnerRecord?.Race?.uiIcon != null) - { - portraitGetter = (_) => partnerRecord.Race.uiIcon; - } - else - { - portraitGetter = (_) => HistoryUtility.UnknownPawn; - } - } - } -} diff --git a/Source/RJWSexperience/SexHistory/UI/PreferedRaceCard.cs b/Source/RJWSexperience/SexHistory/UI/PreferedRaceCard.cs deleted file mode 100644 index 65d9e74..0000000 --- a/Source/RJWSexperience/SexHistory/UI/PreferedRaceCard.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using UnityEngine; - -namespace RJWSexperience.SexHistory.UI -{ - public readonly struct PreferedRaceCard - { - public readonly string preferRaceLabel; - public readonly string preferRaceTypeLabel; - public readonly string sexCount; - public readonly BarInfo? barInfo; - public readonly Func portraitGetter; - - public PreferedRaceCard(SexHistoryComp sexHistory) - { - if (sexHistory.PreferRace == null) - { - preferRaceLabel = Keyed.None; - preferRaceTypeLabel = null; - sexCount = null; - barInfo = null; - portraitGetter = (_) => HistoryUtility.UnknownPawn; - return; - } - - preferRaceLabel = sexHistory.PreferRace.LabelCap; - sexCount = Keyed.RS_Sex_Count + sexHistory.PreferRaceSexCount; - portraitGetter = (size) => UIUtility.GetRaceIcon(sexHistory.PreferRacePawn, size); - - if (sexHistory.PreferRace != sexHistory.ParentPawn.def) - { - if (sexHistory.PreferRace.race.Animal != sexHistory.ParentPawn.def.race.Animal) - { - preferRaceTypeLabel = Keyed.RS_Bestiality; - barInfo = new BarInfo( - label: Keyed.RS_SexInfo(Keyed.RS_Bestiality, sexHistory.BestialityCount), - fillPercent: sexHistory.BestialityCount / 100f, - fillTexture: Texture2D.linearGrayTexture); - } - else - { - preferRaceTypeLabel = Keyed.RS_Interspecies; - barInfo = new BarInfo( - label: Keyed.RS_SexInfo(Keyed.RS_Interspecies, sexHistory.InterspeciesCount), - fillPercent: sexHistory.InterspeciesCount / 100f, - fillTexture: Texture2D.linearGrayTexture); - } - } - else - { - preferRaceTypeLabel = null; - barInfo = null; - } - } - } -} diff --git a/Source/RJWSexperience/SexHistory/UI/RJWUIUtility.cs b/Source/RJWSexperience/SexHistory/UI/RJWUIUtility.cs new file mode 100644 index 0000000..f1e70de --- /dev/null +++ b/Source/RJWSexperience/SexHistory/UI/RJWUIUtility.cs @@ -0,0 +1,101 @@ +using RimWorld; +using rjw; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using UnityEngine; +using Verse; + +namespace RJWSexperience.SexHistory.UI +{ + public static class RJWUIUtility + { + public const float FONTHEIGHT = 22f; + public const float CARDHEIGHT = 110f; + public const float LISTPAWNSIZE = 100f; + public const float BASESAT = 0.40f; + public const float ICONSIZE = 30f; + + public static void DrawQuirk(this Rect rect, Pawn pawn) + { + List quirks = Quirk.All.FindAll(x => pawn.Has(x)); + string quirkstr = quirks.Select(x => x.Key).ToCommaList(); + string tooltip = ""; + + Widgets.Label(rect, "Quirks".Translate() + quirkstr); + + if (Mouse.IsOver(rect)) + { + if (quirks.NullOrEmpty()) + { + tooltip = "NoQuirks".Translate(); + } + else + { + StringBuilder stringBuilder = new StringBuilder(); + foreach (var q in quirks) + { + stringBuilder.AppendLine(q.Key.Colorize(Color.yellow)); + stringBuilder.AppendLine(q.LocaliztionKey.Translate(pawn.Named("pawn")).AdjustedFor(pawn).Resolve()); + stringBuilder.AppendLine(""); + } + tooltip = stringBuilder.ToString().TrimEndNewlines(); + } + Widgets.DrawHighlight(rect); + } + + TooltipHandler.TipRegion(rect, tooltip); + } + + public static void DrawSexuality(this Rect rect, CompRJW comp) + { + if (comp != null) + { + string sexuality = Keyed.Sexuality[(int)comp.orientation]; + Widgets.Label(rect, Keyed.RS_Sexuality + ": " + sexuality); + Widgets.DrawHighlightIfMouseover(rect); + } + } + + public static string GetRelationsString(this Pawn pawn, Pawn otherpawn) + { + if (otherpawn != null) + { + IEnumerable relations = pawn.GetRelations(otherpawn); + if (!relations.EnumerableNullOrEmpty()) return relations.Select(x => x.GetGenderSpecificLabel(otherpawn)).ToCommaList().CapitalizeFirst(); + } + return ""; + } + + public static void DrawBorder(this Rect rect, Texture border, float thickness = 1f) + { + GUI.DrawTexture(new Rect(rect.x, rect.y, rect.width, thickness), border); + GUI.DrawTexture(new Rect(rect.x + rect.width - thickness, rect.y, thickness, rect.height), border); + GUI.DrawTexture(new Rect(rect.x, rect.y + rect.height - thickness, rect.width, thickness), border); + GUI.DrawTexture(new Rect(rect.x, rect.y, thickness, rect.height), border); + } + + public static string GetStatExplanation(Pawn pawn, StatDef stat, float val) + { + if (!pawn.Dead) + return stat.description + "\n" + stat.Worker.GetExplanationFull(StatRequest.For(pawn), ToStringNumberSense.Undefined, val); + return "Dead".Translate(); + } + + public static string GetSexDays(int absticks, bool printUnknown = false) + { + if (absticks != 0) + return GenDate.ToStringTicksToDays(GenTicks.TicksAbs - absticks) + " " + Keyed.RS_Ago; + else if (printUnknown) + return Keyed.Unknown; + return ""; + } + + public static Texture GetRaceIcon(Pawn pawn, Vector2 size) + { + if (pawn != null) + return PortraitsCache.Get(pawn, size, Rot4.South, default, 1, true, true, false, false); + return HistoryUtility.UnknownPawn; + } + } +} diff --git a/Source/RJWSexperience/SexHistory/UI/SexStatus.cs b/Source/RJWSexperience/SexHistory/UI/SexStatus.cs new file mode 100644 index 0000000..880933b --- /dev/null +++ b/Source/RJWSexperience/SexHistory/UI/SexStatus.cs @@ -0,0 +1,654 @@ +using RimWorld; +using rjw; +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using Verse; +using Verse.Sound; + +namespace RJWSexperience.SexHistory.UI +{ + public enum PartnerOrderMode + { + Normal = 0, + Recent = 1, + Most = 2, + Name, MaxValue = 3 + }; + + public static class PartnerOrderModeExtension + { + public static PartnerOrderMode Next(this PartnerOrderMode mode) + { + return (PartnerOrderMode)(((int)mode + 1) % ((int)PartnerOrderMode.MaxValue + 1)); + } + } + + public class SexStatusWindow : Window + { + public const float WINDOW_WIDTH = 900f; + public const float WINDOW_HEIGHT = 600f; + public const float FONTHEIGHT = RJWUIUtility.FONTHEIGHT; + public const float CARDHEIGHT = RJWUIUtility.CARDHEIGHT; + public const float LISTPAWNSIZE = RJWUIUtility.LISTPAWNSIZE; + public const float BASESAT = RJWUIUtility.BASESAT; + public const float ICONSIZE = RJWUIUtility.ICONSIZE; + + public static readonly int[] Sextype = + { + (int)xxx.rjwSextype.Vaginal, + (int)xxx.rjwSextype.Anal, + (int)xxx.rjwSextype.Oral, + (int)xxx.rjwSextype.Fellatio, + (int)xxx.rjwSextype.Cunnilingus, + (int)xxx.rjwSextype.DoublePenetration, + (int)xxx.rjwSextype.Boobjob, + (int)xxx.rjwSextype.Handjob, + (int)xxx.rjwSextype.Footjob, + (int)xxx.rjwSextype.Fingering, + (int)xxx.rjwSextype.Scissoring, + (int)xxx.rjwSextype.MutualMasturbation, + (int)xxx.rjwSextype.Fisting, + (int)xxx.rjwSextype.Rimming, + (int)xxx.rjwSextype.Sixtynine + }; + + protected Pawn pawn; + protected SexPartnerHistoryRecord selectedPawn; + protected SexHistoryComp history; + protected CompRJW rjwcomp; + protected List partnerList; + protected PartnerOrderMode orderMode; + + private static GUIStyle fontStyleCenter; + private static GUIStyle fontStyleRight; + private static GUIStyle fontStyleLeft; + private static GUIStyle boxStyle; + private static GUIStyle buttonStyle; + + private static Vector2 LastWindowPosition { get; set; } + private Vector2 scroll; + + private static void InitStyles() + { + if (fontStyleCenter != null) + { + return; + } + + GUIStyleState fontStyleState = new GUIStyleState() { textColor = Color.white }; + GUIStyleState boxStyleState = GUI.skin.textArea.normal; + GUIStyleState buttonStyleState = GUI.skin.button.normal; + fontStyleCenter = new GUIStyle() { alignment = TextAnchor.MiddleCenter, normal = fontStyleState }; + fontStyleRight = new GUIStyle() { alignment = TextAnchor.MiddleRight, normal = fontStyleState }; + fontStyleLeft = new GUIStyle() { alignment = TextAnchor.MiddleLeft, normal = fontStyleState }; + boxStyle = new GUIStyle(GUI.skin.textArea) { hover = boxStyleState, onHover = boxStyleState, onNormal = boxStyleState }; + buttonStyle = new GUIStyle(GUI.skin.button) { hover = buttonStyleState, onHover = buttonStyleState, onNormal = buttonStyleState }; + } + + public SexStatusWindow(Pawn pawn, SexHistoryComp history) + { + this.pawn = pawn; + this.history = history; + this.selectedPawn = null; + this.rjwcomp = pawn.TryGetComp(); + this.partnerList = history?.PartnerList; + orderMode = PartnerOrderMode.Recent; + SortPartnerList(orderMode); + + soundClose = SoundDefOf.CommsWindow_Close; + absorbInputAroundWindow = false; + forcePause = false; + preventCameraMotion = false; + draggable = true; + doCloseX = true; + } + + protected override void SetInitialSizeAndPosition() + { + base.SetInitialSizeAndPosition(); + + if (LastWindowPosition == Vector2.zero) + return; + + windowRect.x = LastWindowPosition.x; + windowRect.y = LastWindowPosition.y; + } + + public override Vector2 InitialSize => new Vector2(WINDOW_WIDTH, WINDOW_HEIGHT); + + public override void PreOpen() + { + base.PreOpen(); + InitStyles(); + } + + public override void PreClose() + { + base.PreClose(); + LastWindowPosition = windowRect.position; + } + + public override void DoWindowContents(Rect inRect) + { + if (!SexperienceMod.Settings.SelectionLocked) + { + List selected = Find.Selector.SelectedPawns; + if (selected.Count == 1) + { + Pawn p = selected.First(); + if (p != pawn) + { + SexHistoryComp h = p.TryGetComp(); + if (h != null) ChangePawn(p, h); + } + } + } + + DrawSexStatus(inRect, history); + } + + public static void ToggleWindow(Pawn pawn, SexHistoryComp history) + { + SexStatusWindow window = (SexStatusWindow)Find.WindowStack.Windows.FirstOrDefault(x => x.GetType() == typeof(SexStatusWindow)); + if (window != null) + { + if (window.pawn != pawn) + { + SoundDefOf.TabOpen.PlayOneShotOnCamera(); + window.ChangePawn(pawn, history); + } + } + else + { + Find.WindowStack.Add(new SexStatusWindow(pawn, history)); + } + } + + public void ChangePawn(Pawn pawn, SexHistoryComp history) + { + List selected = Find.Selector.SelectedPawns; + if (!selected.NullOrEmpty()) + { + foreach (Pawn p in selected) + { + Find.Selector.Deselect(p); + } + } + + this.pawn = pawn; + this.history = history; + this.selectedPawn = null; + this.rjwcomp = pawn.TryGetComp(); + this.partnerList = history?.PartnerList; + if (!pawn.DestroyedOrNull() && Find.CurrentMap == pawn.Map) Find.Selector.Select(pawn); + SortPartnerList(orderMode); + } + + public void SortPartnerList(PartnerOrderMode mode) + { + if (partnerList.NullOrEmpty()) return; + switch (mode) + { + default: + partnerList = history?.PartnerList; + break; + case PartnerOrderMode.Recent: + partnerList.Sort(new SexPartnerHistoryRecord.RecentOrderComparer()); + break; + case PartnerOrderMode.Most: + partnerList.Sort(new SexPartnerHistoryRecord.MostOrderComparer()); + break; + case PartnerOrderMode.Name: + partnerList.Sort(new SexPartnerHistoryRecord.NameOrderComparer()); + break; + } + } + + /// + /// Main contents + /// + protected void DrawSexStatus(Rect mainrect, SexHistoryComp history) + { + float sectionwidth = mainrect.width / 3; + + Rect leftRect = new Rect(mainrect.x, mainrect.y, sectionwidth, mainrect.height); + Rect centerRect = new Rect(mainrect.x + sectionwidth, mainrect.y, sectionwidth, mainrect.height); + Rect rightRect = new Rect(mainrect.x + (sectionwidth * 2), mainrect.y, sectionwidth, mainrect.height); + + if (history != null) + { + //Left section + DrawBaseSexInfoLeft(leftRect.ContractedBy(4f)); + + //Center section + DrawBaseSexInfoCenter(centerRect.ContractedBy(4f), history.ParentPawn); + + //Right section + DrawBaseSexInfoRight(rightRect.ContractedBy(4f)); + } + } + + protected void DrawInfoWithPortrait(Rect rect, SexPartnerHistoryRecord history, string tooltip = "") + { + Widgets.DrawMenuSection(rect); + string str = tooltip; + Rect portraitRect = new Rect(rect.x, rect.y, rect.height - FONTHEIGHT, rect.height - FONTHEIGHT); + Rect nameRect = new Rect(rect.x + portraitRect.width, rect.y, rect.width - portraitRect.width, FONTHEIGHT); + Rect sexinfoRect = new Rect(rect.x + portraitRect.width, rect.y + FONTHEIGHT, rect.width - portraitRect.width, FONTHEIGHT); + Rect sexinfoRect2 = new Rect(rect.x + portraitRect.width, rect.y + (FONTHEIGHT * 2), rect.width - portraitRect.width, FONTHEIGHT); + Rect bestsexRect = new Rect(rect.x + 2f, rect.y + (FONTHEIGHT * 3), rect.width - 4f, FONTHEIGHT - 2f); + + if (history != null) + { + if (history.Incest) str += " - " + Keyed.Incest; + Pawn partner = history.Partner; + DrawPawn(portraitRect, history); + Widgets.DrawHighlightIfMouseover(portraitRect); + if (Widgets.ButtonInvisible(portraitRect)) + { + SexHistoryComp pawnhistory = partner?.TryGetComp(); + if (pawnhistory != null) + { + ChangePawn(partner, pawnhistory); + SoundDefOf.Click.PlayOneShotOnCamera(); + } + else + { + SoundDefOf.ClickReject.PlayOneShotOnCamera(); + } + } + + string rapeInfo = ""; + if (history.Raped > 0) rapeInfo += Keyed.RS_Raped + history.Raped + " "; + if (history.RapedMe > 0) rapeInfo += Keyed.RS_RapedMe + history.RapedMe; + + GUI.Label(nameRect, partner?.Name?.ToStringFull ?? history.Label.CapitalizeFirst(), fontStyleLeft); + GUI.Label(sexinfoRect, Keyed.RS_Sex_Count + history.TotalSexCount + " " + rapeInfo, fontStyleLeft); + GUI.Label(sexinfoRect2, Keyed.RS_Orgasms + history.OrgasmCount, fontStyleLeft); + GUI.Label(sexinfoRect2, pawn.GetRelationsString(partner) + " ", fontStyleRight); + float p = history.BestSatisfaction / BASESAT; + FillableBarLabeled(bestsexRect, String.Format(Keyed.RS_Best_Sextype + ": {0}", Keyed.Sextype[(int)history.BestSextype]), p / 2, HistoryUtility.SextypeColor[(int)history.BestSextype], Texture2D.blackTexture, null, String.Format("{0:P2}", p)); + + if (history.IamFirst) + str += "\n" + Keyed.RS_LostVirgin(history.Label, pawn.LabelShort); + if (history.BestSexTickAbs != 0) + str += "\n" + Keyed.RS_HadBestSexDaysAgo(history.BestSexElapsedTicks.ToStringTicksToDays() + " " + Keyed.RS_Ago); + + TooltipHandler.TipRegion(rect, str); + } + else + { + Widgets.DrawTextureFitted(portraitRect, HistoryUtility.UnknownPawn, 1.0f); + Widgets.Label(nameRect, Keyed.Unknown); + Widgets.Label(sexinfoRect, Keyed.RS_Sex_Count + "?"); + Widgets.Label(sexinfoRect2, Keyed.RS_Orgasms + "?"); + FillableBarLabeled(bestsexRect, String.Format(Keyed.RS_Best_Sextype + ": {0}", Keyed.Sextype[(int)xxx.rjwSextype.None]), 0, Texture2D.linearGrayTexture, Texture2D.blackTexture); + } + } + + protected void DrawSexInfoCard(Rect rect, SexPartnerHistoryRecord history, string label, string tooltip, string rightlabel = "") + { + Rect labelRect = new Rect(rect.x, rect.y, rect.width, FONTHEIGHT); + Rect infoRect = new Rect(rect.x, rect.y + FONTHEIGHT, rect.width, rect.height - FONTHEIGHT); + GUI.Label(labelRect, label, fontStyleLeft); + GUI.Label(labelRect, rightlabel, fontStyleRight); + DrawInfoWithPortrait(infoRect, history, tooltip); + } + + /// + /// Right section + /// + protected void DrawBaseSexInfoRight(Rect rect) + { + Listing_Standard listmain = new Listing_Standard(); + listmain.Begin(rect.ContractedBy(4f)); + DrawSexInfoCard(listmain.GetRect(CARDHEIGHT), history.GetRecentPartnersHistory, Keyed.RS_Recent_Sex_Partner, Keyed.RS_Recent_Sex_Partner_ToolTip, RJWUIUtility.GetSexDays(history.RecentSexTickAbs)); + DrawSexInfoCard(listmain.GetRect(CARDHEIGHT), history.GetFirstPartnerHistory, Keyed.RS_First_Sex_Partner, Keyed.RS_First_Sex_Partner_ToolTip, RJWUIUtility.GetSexDays(history.FirstSexTickAbs)); + DrawSexInfoCard(listmain.GetRect(CARDHEIGHT), history.GetMostPartnerHistory, Keyed.RS_Most_Sex_Partner, Keyed.RS_Most_Sex_Partner_ToolTip, RJWUIUtility.GetSexDays(history.MostSexTickAbs)); + DrawSexInfoCard(listmain.GetRect(CARDHEIGHT), history.GetBestSexPartnerHistory, Keyed.RS_Best_Sex_Partner, Keyed.RS_Best_Sex_Partner_ToolTip, RJWUIUtility.GetSexDays(history.BestSexTickAbs)); + GUI.Label(listmain.GetRect(FONTHEIGHT), Keyed.RS_PreferRace, fontStyleLeft); + DrawPreferRace(listmain.GetRect(66f + 15f)); + listmain.GetRect(15f); + listmain.End(); + } + + protected void DrawPreferRace(Rect rect) + { + Widgets.DrawMenuSection(rect); + Rect portraitRect = new Rect(rect.x, rect.y, rect.height - 15f, rect.height - 15f); + Rect infoRect1 = new Rect(rect.x + portraitRect.width, rect.y, rect.width - portraitRect.width, FONTHEIGHT); + Rect infoRect2 = new Rect(rect.x + portraitRect.width, rect.y + FONTHEIGHT, rect.width - portraitRect.width, FONTHEIGHT); + Rect infoRect3 = new Rect(rect.x + portraitRect.width, rect.y + (FONTHEIGHT * 2), rect.width - portraitRect.width - 2f, FONTHEIGHT); + + if (history.PreferRace != null) + { + Widgets.DrawTextureFitted(portraitRect, RJWUIUtility.GetRaceIcon(history.PreferRacePawn, portraitRect.size), 1.0f); + GUI.Label(infoRect1, history.PreferRace?.label.CapitalizeFirst() ?? Keyed.None, fontStyleLeft); + GUI.Label(infoRect2, Keyed.RS_Sex_Count + history.PreferRaceSexCount, fontStyleLeft); + if (history.PreferRace != pawn.def) + { + if (history.PreferRace.race.Animal ^ pawn.def.race.Animal) + { + GUI.Label(infoRect1, Keyed.RS_Bestiality + " ", fontStyleRight); + FillableBarLabeled(infoRect3, Keyed.RS_Sex_Info(Keyed.RS_Bestiality, history.BestialityCount.ToString()), history.BestialityCount / 100f, Texture2D.linearGrayTexture, Texture2D.blackTexture); + } + else + { + GUI.Label(infoRect1, Keyed.RS_Interspecies + " ", fontStyleRight); + FillableBarLabeled(infoRect3, Keyed.RS_Sex_Info(Keyed.RS_Interspecies, history.InterspeciesCount.ToString()), history.InterspeciesCount / 100f, Texture2D.linearGrayTexture, Texture2D.blackTexture); + } + } + } + else + { + Widgets.DrawTextureFitted(portraitRect, HistoryUtility.UnknownPawn, 1.0f); + GUI.Label(infoRect1, Keyed.None, fontStyleLeft); + } + } + + /// + /// Center section + /// + protected void DrawBaseSexInfoCenter(Rect rect, Pawn pawn) + { + Rect portraitRect = new Rect(rect.x + (rect.width / 4), rect.y, rect.width / 2, rect.width / 1.5f); + Rect nameRect = new Rect(portraitRect.x, portraitRect.yMax - (FONTHEIGHT * 2), portraitRect.width, FONTHEIGHT * 2); + Rect infoRect = new Rect(rect.x, rect.y + portraitRect.height, rect.width, rect.height - portraitRect.height); + Rect lockRect = new Rect(portraitRect.xMax - ICONSIZE, portraitRect.y, ICONSIZE, ICONSIZE); + Rect tmp; + + if (Mouse.IsOver(portraitRect)) + { + Configurations settings = SexperienceMod.Settings; + Texture lockicon = settings.SelectionLocked ? HistoryUtility.Locked : HistoryUtility.Unlocked; + Widgets.DrawTextureFitted(lockRect, lockicon, 1.0f); + if (Widgets.ButtonInvisible(lockRect)) + { + SoundDefOf.Click.PlayOneShotOnCamera(); + settings.SelectionLocked.Value = !settings.SelectionLocked.Value; + } + } + + GUI.Box(portraitRect, "", boxStyle); + Widgets.DrawTextureFitted(portraitRect, PortraitsCache.Get(pawn, portraitRect.size, Rot4.South, default, 1, true, true, false, false), 1.0f); + Widgets.DrawHighlightIfMouseover(portraitRect); + if (Widgets.ButtonInvisible(portraitRect)) + { + SoundDefOf.Click.PlayOneShotOnCamera(); + selectedPawn = null; + } + + GUI.Box(nameRect, "", boxStyle); + GUI.Label(nameRect.TopHalf(), pawn.Name?.ToStringFull ?? pawn.Label, fontStyleCenter); + if (pawn.story != null) GUI.Label(nameRect.BottomHalf(), pawn.ageTracker.AgeBiologicalYears + ", " + pawn.story.Title, fontStyleCenter); + else GUI.Label(nameRect.BottomHalf(), pawn.ageTracker.AgeBiologicalYears + ", " + pawn.def.label, fontStyleCenter); + + Listing_Standard listmain = new Listing_Standard(); + listmain.Begin(infoRect); + listmain.Gap(20f); + float p; + + Trait virginity = pawn.story?.traits?.GetTrait(VariousDefOf.Virgin); + if (virginity != null && virginity.Degree != Virginity.TraitDegree.FemaleAfterSurgery) + { + tmp = listmain.GetRect(FONTHEIGHT); + GUI.color = Color.red; + GUI.Box(tmp, "", boxStyle); + GUI.color = Color.white; + GUI.Label(tmp, virginity.Label, fontStyleCenter); + } + else + { + p = history.TotalSexHad; + FillableBarLabeled(listmain.GetRect(FONTHEIGHT), String.Format(Keyed.RS_TotalSexHad + ": {0:0} ({1:0})", p, pawn.records.GetValue(xxx.CountOfSex)), p / 100, HistoryUtility.TotalSex, Texture2D.blackTexture, null, Keyed.RS_SAT_AVG(String.Format("{0:P2}", history.AVGSat))); + } + listmain.Gap(1f); + + tmp = listmain.GetRect(FONTHEIGHT); + p = pawn.records.GetValue(VariousDefOf.Lust); + FillableBarLabeled(tmp, String.Format(Keyed.Lust + ": {0:0.00}", p), Mathf.Clamp01(p.Normalization(-SexperienceMod.Settings.LustLimit * 3, SexperienceMod.Settings.LustLimit * 3)), HistoryUtility.Slaanesh, Texture2D.blackTexture, null, String.Format(xxx.sex_drive_stat.LabelCap + ": {0:P2}", pawn.Dead ? 0 : pawn.GetStatValue(xxx.sex_drive_stat))); + listmain.Gap(1f); + if (Mouse.IsOver(tmp)) + { + TooltipHandler.TipRegion(tmp, RJWUIUtility.GetStatExplanation(pawn, xxx.sex_drive_stat, pawn.Dead ? 0 : pawn.GetStatValue(xxx.sex_drive_stat))); + } + + p = history.GetBestSextype(out xxx.rjwSextype sextype) / BASESAT; + FillableBarLabeled(listmain.GetRect(FONTHEIGHT), String.Format(Keyed.RS_Best_Sextype + ": {0}", Keyed.Sextype[(int)sextype]), p / 2, HistoryUtility.SextypeColor[(int)sextype], Texture2D.blackTexture, null, Keyed.RS_SAT_AVG(String.Format("{0:P2}", p))); + listmain.Gap(1f); + + p = history.GetRecentSextype(out sextype) / BASESAT; + FillableBarLabeled(listmain.GetRect(FONTHEIGHT), String.Format(Keyed.RS_Recent_Sextype + ": {0}", Keyed.Sextype[(int)sextype]), p / 2, HistoryUtility.SextypeColor[(int)sextype], Texture2D.blackTexture, null, String.Format("{0:P2}", p)); + listmain.Gap(1f); + + if (history.IncestuousCount < history.CorpseFuckCount) + { + p = history.CorpseFuckCount; + FillableBarLabeled(listmain.GetRect(FONTHEIGHT), String.Format(Keyed.RS_Necrophile + ": {0}", p), p / 50, HistoryUtility.Nurgle, Texture2D.blackTexture); + listmain.Gap(1f); + } + else + { + p = history.IncestuousCount; + FillableBarLabeled(listmain.GetRect(FONTHEIGHT), String.Format(Keyed.Incest + ": {0}", p), p / 50, HistoryUtility.Nurgle, Texture2D.blackTexture); + listmain.Gap(1f); + } + + p = pawn.records.GetValue(VariousDefOf.AmountofEatenCum); + FillableBarLabeled(listmain.GetRect(FONTHEIGHT), String.Format(Keyed.RS_Cum_Swallowed + ": {0} mL, {1} " + Keyed.RS_NumofTimes, p, pawn.records.GetValue(VariousDefOf.NumofEatenCum)), p / 1000, Texture2D.linearGrayTexture, Texture2D.blackTexture); + listmain.Gap(1f); + + Hediff addiction = pawn.health.hediffSet.GetFirstHediffOfDef(VariousDefOf.CumAddiction) + ?? pawn.health.hediffSet.GetFirstHediffOfDef(VariousDefOf.CumTolerance); + if (addiction != null) + { + p = addiction.Severity; + FillableBarLabeled(listmain.GetRect(FONTHEIGHT), $"{addiction.Label}: {p.ToStringPercent()}", p, Texture2D.linearGrayTexture, Texture2D.blackTexture, addiction.GetTooltip(pawn, false)); + } + else + { + listmain.GetRect(FONTHEIGHT); + } + listmain.Gap(1f); + + p = history.RapedCount; + tmp = listmain.GetRect(FONTHEIGHT); + if (p < history.BeenRapedCount) + { + p = history.BeenRapedCount; + FillableBarLabeled(tmp, String.Format(Keyed.RS_BeenRaped + ": {0}", p), p / 50, Texture2D.grayTexture, Texture2D.blackTexture, null, String.Format(xxx.vulnerability_stat.LabelCap + ": {0:P2}", pawn.Dead ? 0 : pawn.GetStatValue(xxx.vulnerability_stat))); + listmain.Gap(1f); + } + else + { + FillableBarLabeled(tmp, String.Format(Keyed.RS_RapedSomeone + ": {0}", p), p / 50, HistoryUtility.Khorne, Texture2D.blackTexture, null, String.Format(xxx.vulnerability_stat.LabelCap + ": {0:P2}", pawn.Dead ? 0 : pawn.GetStatValue(xxx.vulnerability_stat))); + listmain.Gap(1f); + } + if (Mouse.IsOver(tmp)) + { + TooltipHandler.TipRegion(tmp, RJWUIUtility.GetStatExplanation(pawn, xxx.vulnerability_stat, pawn.Dead ? 0 : pawn.GetStatValue(xxx.vulnerability_stat))); + } + + p = pawn.Dead ? 0 : pawn.GetStatValue(xxx.sex_satisfaction); + tmp = listmain.GetRect(FONTHEIGHT); + FillableBarLabeled(tmp, String.Format(xxx.sex_satisfaction.LabelCap + ": {0:P2}", p), p / 2, HistoryUtility.Satisfaction, Texture2D.blackTexture); + listmain.Gap(1f); + if (Mouse.IsOver(tmp)) + { + TooltipHandler.TipRegion(tmp, RJWUIUtility.GetStatExplanation(pawn, xxx.sex_satisfaction, pawn.Dead ? 0 : pawn.GetStatValue(xxx.sex_satisfaction))); + } + + SkillRecord skill = pawn.skills?.GetSkill(VariousDefOf.Sex); + p = skill?.Level ?? 0; + tmp = listmain.GetRect(FONTHEIGHT); + FillableBarLabeled(tmp, $"{Keyed.RS_SexSkill}: {p}, {skill?.xpSinceLastLevel / skill?.XpRequiredForLevelUp:P2}", p / 20, HistoryUtility.Tzeentch, Texture2D.blackTexture, null, $"{VariousDefOf.SexAbility.LabelCap}: {pawn.GetSexStat():P2}", HistoryUtility.GetPassionBG(skill?.passion)); + if (Mouse.IsOver(tmp)) + { + TooltipHandler.TipRegion(tmp, RJWUIUtility.GetStatExplanation(pawn, VariousDefOf.SexAbility, pawn.GetSexStat())); + } + + listmain.Gap(1f); + + if (selectedPawn != null) DrawSexInfoCard(listmain.GetRect(CARDHEIGHT), selectedPawn, Keyed.RS_Selected_Partner, Keyed.RS_Selected_Partner, RJWUIUtility.GetSexDays(selectedPawn.RecentSexTickAbs)); + else DrawExtraInfo(listmain.GetRect(CARDHEIGHT)); + + listmain.End(); + } + + protected void DrawExtraInfo(Rect rect) + { + Widgets.DrawMenuSection(rect); + Rect inRect = rect.ContractedBy(4f); + Listing_Standard listmain = new Listing_Standard(); + listmain.Begin(inRect); + listmain.Gap(4f); + listmain.GetRect(FONTHEIGHT).DrawSexuality(rjwcomp); + listmain.Gap(1f); + listmain.GetRect(FONTHEIGHT * 3f).DrawQuirk(pawn); + listmain.End(); + } + + /// + /// Left section + /// + protected void DrawBaseSexInfoLeft(Rect rect) + { + Listing_Standard listmain = new Listing_Standard(); + listmain.Begin(rect); + float p; + + //Sex statistics + GUI.Label(listmain.GetRect(FONTHEIGHT), " " + Keyed.RS_Statistics, fontStyleLeft); + listmain.Gap(1f); + float maxSatisfaction = history.GetBestSextype(out _); + if (maxSatisfaction == 0f) maxSatisfaction = BASESAT; + for (int i = 0; i < Sextype.Length; i++) + { + int sexindex = Sextype[i]; + float relativeSat = history.GetAVGSat(sexindex) / maxSatisfaction; + p = history.GetAVGSat(sexindex) / BASESAT; + string label = Keyed.RS_Sex_Info(Keyed.Sextype[sexindex], history.GetSexCount(sexindex).ToString()); + Rect tmpRect = listmain.GetRect(FONTHEIGHT); + FillableBarLabeled(tmpRect, label, relativeSat, HistoryUtility.SextypeColor[sexindex], Texture2D.blackTexture, null, Keyed.RS_SAT_AVG(String.Format("{0:P2}", p))); + if (Mouse.IsOver(tmpRect)) + { + TooltipHandler.TipRegion(tmpRect, Keyed.RS_LastSex.CapitalizeFirst() + ": " + RJWUIUtility.GetSexDays(history.GetSextypeRecentTickAbs(Sextype[i]), true)); + } + + listmain.Gap(1f); + } + + p = history.PartnerCount; + FillableBarLabeled(listmain.GetRect(FONTHEIGHT), String.Format(Keyed.RS_Sex_Partners + ": {0} ({1})", p, pawn.records.GetValue(VariousDefOf.SexPartnerCount)), p / 50, HistoryUtility.Partners, Texture2D.blackTexture); + listmain.Gap(1f); + + p = history.VirginsTaken; + FillableBarLabeled(listmain.GetRect(FONTHEIGHT), String.Format(Keyed.RS_VirginsTaken + ": {0:0}", p), p / 100, HistoryUtility.Partners, Texture2D.blackTexture); + listmain.Gap(1f); + + //Partner list + Rect listLabelRect = listmain.GetRect(FONTHEIGHT); + Rect sortbtnRect = new Rect(listLabelRect.xMax - 80f, listLabelRect.y, 80f, listLabelRect.height); + GUI.Label(listLabelRect, " " + Keyed.RS_PartnerList, fontStyleLeft); + if (Widgets.ButtonText(sortbtnRect, orderMode.Translate())) + { + SoundDefOf.Click.PlayOneShotOnCamera(); + orderMode = orderMode.Next(); + SortPartnerList(orderMode); + } + + listmain.Gap(1f); + + Rect scrollRect = listmain.GetRect(CARDHEIGHT + 1f); + GUI.Box(scrollRect, "", buttonStyle); + if (!partnerList.NullOrEmpty()) + { + Rect listRect = new Rect(scrollRect.x, scrollRect.y, LISTPAWNSIZE * partnerList.Count, scrollRect.height - 30f); + Widgets.ScrollHorizontal(scrollRect, ref scroll, listRect); + Widgets.BeginScrollView(scrollRect, ref scroll, listRect); + DrawPartnerList(listRect, partnerList); + Widgets.EndScrollView(); + } + + listmain.End(); + } + + protected void DrawPartnerList(Rect rect, List partnerList) + { + Rect pawnRect = new Rect(rect.x, rect.y, LISTPAWNSIZE, LISTPAWNSIZE); + for (int i = 0; i < partnerList.Count; i++) + { + Rect labelRect = new Rect(pawnRect.x, pawnRect.yMax - FONTHEIGHT, pawnRect.width, FONTHEIGHT); + + DrawPawn(pawnRect, partnerList[i]); + Widgets.DrawHighlightIfMouseover(pawnRect); + GUI.Label(labelRect, partnerList[i].Label, fontStyleCenter); + if (Widgets.ButtonInvisible(pawnRect)) + { + selectedPawn = partnerList[i]; + SoundDefOf.Click.PlayOneShotOnCamera(); + } + if (partnerList[i] == selectedPawn) + { + Widgets.DrawHighlightSelected(pawnRect); + } + + pawnRect.x += LISTPAWNSIZE; + } + } + + protected void DrawPawn(Rect rect, SexPartnerHistoryRecord history) + { + if (history != null) + { + bool drawheart = false; + Rect iconRect = new Rect(rect.x + (rect.width * 3 / 4), rect.y, rect.width / 4, rect.height / 4); + Texture img = HistoryUtility.UnknownPawn; + + if (history.IamFirst) + { + GUI.color = HistoryUtility.HistoryColor; + Widgets.DrawTextureFitted(rect, HistoryUtility.FirstOverlay, 1.0f); + GUI.color = Color.white; + } + + if (history.Partner != null) + { + img = PortraitsCache.Get(history.Partner, rect.size, Rot4.South, default, 1, true, true, false, false); + drawheart = LovePartnerRelationUtility.LovePartnerRelationExists(pawn, history.Partner); + } + else if (history.Race?.uiIcon != null) + { + img = history.Race.uiIcon; + } + + if (history.Incest) + { + Widgets.DrawTextureFitted(iconRect, HistoryUtility.Incest, 1.0f); + iconRect.x -= iconRect.width; + } + Widgets.DrawTextureFitted(rect, img, 1.0f); + if (drawheart) + { + Widgets.DrawTextureFitted(iconRect, HistoryUtility.Heart, 1.0f); + iconRect.x -= iconRect.width; + } + } + } + + public static void FillableBarLabeled(Rect rect, string label, float fillPercent, Texture2D filltexture, Texture2D bgtexture, string tooltip = null, string rightlabel = "", Texture2D border = null) + { + Widgets.FillableBar(rect, Math.Min(fillPercent, 1.0f), filltexture, bgtexture, true); + GUI.Label(rect, " " + label.CapitalizeFirst(), fontStyleLeft); + GUI.Label(rect, rightlabel.CapitalizeFirst() + " ", fontStyleRight); + Widgets.DrawHighlightIfMouseover(rect); + if (tooltip != null) TooltipHandler.TipRegion(rect, tooltip); + if (border != null) + { + rect.DrawBorder(border, 2f); + } + } + } +} diff --git a/Source/RJWSexperience/SexHistory/UI/SexStatusViewModel.cs b/Source/RJWSexperience/SexHistory/UI/SexStatusViewModel.cs deleted file mode 100644 index e7b3538..0000000 --- a/Source/RJWSexperience/SexHistory/UI/SexStatusViewModel.cs +++ /dev/null @@ -1,374 +0,0 @@ -using RimWorld; -using rjw; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using UnityEngine; -using Verse; - -namespace RJWSexperience.SexHistory.UI -{ - public sealed class SexStatusViewModel - { - private static readonly int[] Sextype = - { - (int)xxx.rjwSextype.Vaginal, - (int)xxx.rjwSextype.Anal, - (int)xxx.rjwSextype.Oral, - (int)xxx.rjwSextype.Fellatio, - (int)xxx.rjwSextype.Cunnilingus, - (int)xxx.rjwSextype.DoublePenetration, - (int)xxx.rjwSextype.Boobjob, - (int)xxx.rjwSextype.Handjob, - (int)xxx.rjwSextype.Footjob, - (int)xxx.rjwSextype.Fingering, - (int)xxx.rjwSextype.Scissoring, - (int)xxx.rjwSextype.MutualMasturbation, - (int)xxx.rjwSextype.Fisting, - (int)xxx.rjwSextype.Rimming, - (int)xxx.rjwSextype.Sixtynine - }; - - private readonly SexHistoryComp _history; - private readonly CompRJW _rjwComp; - private int _validUntilTick; - - public SexStatusViewModel(SexHistoryComp history, PartnerOrderMode mode) - { - _history = history; - _rjwComp = history.ParentPawn.TryGetComp(); - SetPartnerOrder(mode); - - Name = Pawn.Name?.ToStringFull ?? Pawn.Label; - if (Pawn.story != null) - { - AgeAndTitle = Pawn.ageTracker.AgeBiologicalYears + ", " + Pawn.story.Title; - } - else - { - AgeAndTitle = Pawn.ageTracker.AgeBiologicalYears + ", " + Pawn.def.label; - } - } - - public Pawn Pawn => _history.ParentPawn; - public string Name { get; } - public string AgeAndTitle { get; } - public List InfoCards { get; } = new List(); - public InfoCard SelectedPartnerCard { get; private set; } - public PreferedRaceCard PreferedRaceCard { get; private set; } - public List SexTypes { get; } = new List(); - public BarInfo TotalSex { get; private set; } - public BarInfo Lust { get; private set; } - public BarInfo BestSextype { get; private set; } - public BarInfo RecentSextype { get; private set; } - public BarInfo Necro { get; private set; } - public BarInfo Incest { get; private set; } - public BarInfo ConsumedCum { get; private set; } - public BarInfo? CumHediff { get; private set; } - public BarInfo BeenRaped { get; private set; } - public BarInfo Raped { get; private set; } - public BarInfo SexSatisfaction { get; private set; } - public BarInfo SexSkill { get; private set; } - public string VirginLabel { get; private set; } - public string SexualityLabel { get; private set; } - public string QuirksLabel { get; private set; } - public TipSignal QuirksTooltip { get; private set; } - public SexPartnerHistoryRecord SelectedPartner { get; private set; } - public IEnumerable Partners { get; private set; } - - public void Update() - { - if (Find.TickManager.TicksGame <= _validUntilTick) - { - return; - } - - UpdateInfoCards(); - UpdateBars(); - UpdateQuirks(); - UpdateVirginAndSexuality(); - PreferedRaceCard = new PreferedRaceCard(_history); - - int tickRateMultiplier = (int)Find.TickManager.TickRateMultiplier; - if (tickRateMultiplier == 0) // Paused - { - _validUntilTick = Find.TickManager.TicksGame; - return; - } - - _validUntilTick = Find.TickManager.TicksGame + (60 * tickRateMultiplier); - } - - private void UpdateInfoCards() - { - InfoCards.Clear(); - - InfoCards.Add(new InfoCard( - pawn: Pawn, - partnerRecord: _history.RecentPartnerRecord, - label: Keyed.RS_Recent_Sex_Partner, - tooltipLabel: Keyed.RS_Recent_Sex_Partner_ToolTip, - lastSexTimeTicks: _history.RecentSexTickAbs)); - - InfoCards.Add(new InfoCard( - pawn: Pawn, - partnerRecord: _history.FirstPartnerRecord, - label: Keyed.RS_First_Sex_Partner, - tooltipLabel: Keyed.RS_First_Sex_Partner_ToolTip, - lastSexTimeTicks: _history.FirstSexTickAbs)); - - InfoCards.Add(new InfoCard( - pawn: Pawn, - partnerRecord: _history.MostPartnerRecord, - label: Keyed.RS_Most_Sex_Partner, - tooltipLabel: Keyed.RS_Most_Sex_Partner_ToolTip, - lastSexTimeTicks: _history.MostSexTickAbs)); - - InfoCards.Add(new InfoCard( - pawn: Pawn, - partnerRecord: _history.BestSexPartnerRecord, - label: Keyed.RS_Best_Sex_Partner, - tooltipLabel: Keyed.RS_Best_Sex_Partner_ToolTip, - lastSexTimeTicks: _history.BestSexTickAbs)); - - if (SelectedPartner != null) - { - UpdateSelectedPartnerCard(); - } - } - - private void UpdateBars() - { - float maxSatisfaction = _history.GetBestSextype(out _); - if (maxSatisfaction == 0f) - { - maxSatisfaction = UIUtility.BASESAT; - } - - SexTypes.Clear(); - - for (int i = 0; i < Sextype.Length; i++) - { - int sexIndex = Sextype[i]; - float AverageSatisfaction = _history.GetAVGSat(sexIndex); - float relativeSat = AverageSatisfaction / maxSatisfaction; - float satisfactionRelativeToBase = AverageSatisfaction / UIUtility.BASESAT; - SexTypes.Add(new BarInfo( - label: Keyed.RS_SexInfo(Keyed.Sextype[sexIndex], _history.GetSexCount(sexIndex)), - fillPercent: relativeSat, - fillTexture: HistoryUtility.SextypeColor[sexIndex], - tooltip: Keyed.RS_LastSex + ": " + UIUtility.GetSexDays(_history.GetSextypeRecentTickAbs(sexIndex), true), - labelRight: Keyed.RS_SatAVG(satisfactionRelativeToBase))); - } - - SexTypes.Add(new BarInfo( - label: String.Format(Keyed.RS_Sex_Partners + ": {0} ({1})", _history.PartnerCount, Pawn.records.GetValue(RsDefOf.Record.SexPartnerCount)), - fillPercent: _history.PartnerCount / 50, - fillTexture: HistoryUtility.Partners)); - - SexTypes.Add(new BarInfo( - label: String.Format(Keyed.RS_VirginsTaken + ": {0:0}", _history.VirginsTaken), - fillPercent: _history.VirginsTaken / 100, - fillTexture: HistoryUtility.Partners)); - - TotalSex = new BarInfo( - label: String.Format(Keyed.RS_TotalSexHad + ": {0:0} ({1:0})", _history.TotalSexHad, Pawn.records.GetValue(xxx.CountOfSex)), - fillPercent: _history.TotalSexHad / 100, - fillTexture: HistoryUtility.TotalSex, - labelRight: Keyed.RS_SatAVG(_history.AVGSat)); - - float lust = Pawn.records.GetValue(RsDefOf.Record.Lust); - float sexDrive = GetStatValue(xxx.sex_drive_stat); - float lustLimit = SexperienceMod.Settings.LustLimit * 3f; - Lust = new BarInfo( - label: String.Format(Keyed.Lust + ": {0:0.00}", lust), - fillPercent: Mathf.Clamp01(lust.Normalization(-lustLimit, lustLimit)), - fillTexture: HistoryUtility.Slaanesh, - tooltip: GetStatTooltip(xxx.sex_drive_stat, sexDrive), - labelRight: xxx.sex_drive_stat.LabelCap + ": " + sexDrive.ToStringPercent()); - - float bestSextypeRelativeSatisfaction = _history.GetBestSextype(out xxx.rjwSextype bestSextype) / UIUtility.BASESAT; - BestSextype = new BarInfo( - label: String.Format(Keyed.RS_Best_Sextype + ": {0}", Keyed.Sextype[(int)bestSextype]), - fillPercent: bestSextypeRelativeSatisfaction / 2, - fillTexture: HistoryUtility.SextypeColor[(int)bestSextype], - labelRight: Keyed.RS_SatAVG(bestSextypeRelativeSatisfaction)); - - float recentSextypeRelativeSatisfaction = _history.GetRecentSextype(out xxx.rjwSextype recentSextype) / UIUtility.BASESAT; - RecentSextype = new BarInfo( - label: String.Format(Keyed.RS_Recent_Sextype + ": {0}", Keyed.Sextype[(int)recentSextype]), - fillPercent: recentSextypeRelativeSatisfaction / 2, - fillTexture: HistoryUtility.SextypeColor[(int)recentSextype], - labelRight: recentSextypeRelativeSatisfaction.ToStringPercent()); - - Necro = new BarInfo( - label: String.Format(Keyed.RS_Necrophile + ": {0}", _history.CorpseFuckCount), - fillPercent: _history.CorpseFuckCount / 50, - fillTexture: HistoryUtility.Nurgle); - - Incest = new BarInfo( - label: String.Format(Keyed.Incest + ": {0}", _history.IncestuousCount), - fillPercent: _history.IncestuousCount / 50, - fillTexture: HistoryUtility.Nurgle); - - float amountofEatenCum = Pawn.records.GetValue(RsDefOf.Record.AmountofEatenCum); - ConsumedCum = new BarInfo( - label: String.Format(Keyed.RS_Cum_Swallowed + ": {0} mL, {1} " + Keyed.RS_NumofTimes, amountofEatenCum, Pawn.records.GetValue(RsDefOf.Record.NumofEatenCum)), - fillPercent: amountofEatenCum / 1000, - fillTexture: Texture2D.linearGrayTexture); - - Hediff cumHediff = Pawn.health.hediffSet.GetFirstHediffOfDef(RsDefOf.Hediff.CumAddiction) - ?? Pawn.health.hediffSet.GetFirstHediffOfDef(RsDefOf.Hediff.CumTolerance); - if (cumHediff != null) - { - CumHediff = new BarInfo( - label: $"{cumHediff.Label}: {cumHediff.Severity.ToStringPercent()}", - fillPercent: cumHediff.Severity, - fillTexture: Texture2D.linearGrayTexture, - tooltip: new TipSignal(() => cumHediff.GetTooltip(Pawn, false), cumHediff.Label.GetHashCode())); - } - - float vulnerability = GetStatValue(xxx.vulnerability_stat); - string vulnerabilityLabel = xxx.vulnerability_stat.LabelCap + ": " + vulnerability.ToStringPercent(); - TipSignal vulnerabilityTip = GetStatTooltip(xxx.vulnerability_stat, vulnerability); - - Raped = new BarInfo( - label: String.Format(Keyed.RS_RapedSomeone + ": {0}", _history.RapedCount), - fillPercent: _history.RapedCount / 50, - fillTexture: HistoryUtility.Khorne, - tooltip: vulnerabilityTip, - labelRight: vulnerabilityLabel); - - BeenRaped = new BarInfo( - label: String.Format(Keyed.RS_BeenRaped + ": {0}", _history.BeenRapedCount), - fillPercent: _history.BeenRapedCount / 50, - fillTexture: Texture2D.grayTexture, - tooltip: vulnerabilityTip, - labelRight: vulnerabilityLabel); - - float sexSatisfaction = GetStatValue(xxx.sex_satisfaction); - SexSatisfaction = new BarInfo( - label: xxx.sex_satisfaction.LabelCap + ": " + sexSatisfaction.ToStringPercent(), - fillPercent: sexSatisfaction / 2, - fillTexture: HistoryUtility.Satisfaction, - tooltip: GetStatTooltip(xxx.sex_satisfaction, sexSatisfaction)); - - SkillRecord skill = Pawn.skills?.GetSkill(RsDefOf.Skill.Sex); - float sexSkillLevel = skill?.Level ?? 0f; - float sexStat = Pawn.GetSexStat(); - SexSkill = new BarInfo( - label: $"{Keyed.RS_SexSkill}: {sexSkillLevel}, {skill?.xpSinceLastLevel / skill?.XpRequiredForLevelUp:P2}", - fillPercent: sexSkillLevel / 20, - fillTexture: HistoryUtility.Tzeentch, - tooltip: GetStatTooltip(RsDefOf.Stat.SexAbility, sexStat), - labelRight: RsDefOf.Stat.SexAbility.LabelCap + ": " + sexStat.ToStringPercent(), - border: HistoryUtility.GetPassionBG(skill?.passion)); - } - - private void UpdateQuirks() - { - List quirks = Quirk.All.FindAll(x => Pawn.Has(x)); - string quirkstr = quirks.Select(x => x.Key).ToCommaList(); - QuirksLabel = "Quirks".Translate() + quirkstr; - - if (quirks.NullOrEmpty()) - { - QuirksTooltip = "NoQuirks".Translate(); - } - else - { - QuirksTooltip = new TipSignal(() => - { - StringBuilder stringBuilder = new StringBuilder(); - foreach (Quirk q in quirks) - { - stringBuilder.AppendLine(q.Key.Colorize(Color.yellow)); - stringBuilder.AppendLine(q.LocaliztionKey.Translate(Pawn.Named("pawn")).AdjustedFor(Pawn).Resolve()); - stringBuilder.AppendLine(""); - } - return stringBuilder.ToString().TrimEndNewlines(); - }, "Quirks".GetHashCode()); - } - } - - private void UpdateVirginAndSexuality() - { - Trait virginity = Pawn.story?.traits?.GetTrait(RsDefOf.Trait.Virgin); - if (virginity != null && virginity.Degree != Virginity.TraitDegree.FemaleAfterSurgery) - { - VirginLabel = virginity.Label; - } - else - { - VirginLabel = null; - } - - if (_rjwComp != null) - { - SexualityLabel = Keyed.RS_Sexuality + ": " + Keyed.Sexuality[(int)_rjwComp.orientation]; - } - } - - public void SetPartnerOrder(PartnerOrderMode mode) - { - if (_history == null) - { - return; - } - - var partners = _history.PartnerList.Select(x => new PartnerPortraitInfo(Pawn, x)); - - switch (mode) - { - default: - Partners = partners; - break; - case PartnerOrderMode.Recent: - Partners = partners.OrderBy(x => x.partnerRecord.RecentSexTickAbs); - break; - case PartnerOrderMode.Most: - Partners = partners.OrderBy(x => x.partnerRecord.TotalSexCount); - break; - case PartnerOrderMode.Name: - Partners = partners.OrderBy(x => x.partnerRecord.Label); - break; - } - } - - public void SetSelectedPartner(SexPartnerHistoryRecord sexPartner) - { - SelectedPartner = sexPartner; - UpdateSelectedPartnerCard(); - } - - private void UpdateSelectedPartnerCard() - { - if (SelectedPartner == null) - { - SelectedPartnerCard = default; - return; - } - - SelectedPartnerCard = new InfoCard( - pawn: Pawn, - partnerRecord: SelectedPartner, - label: Keyed.RS_Selected_Partner, - tooltipLabel: Keyed.RS_Selected_Partner, - lastSexTimeTicks: SelectedPartner.RecentSexTickAbs); - } - - private float GetStatValue(StatDef statDef) => Pawn.Dead ? 0f : Pawn.GetStatValue(statDef); - - private TipSignal GetStatTooltip(StatDef stat, float val) - { - if (!Pawn.Dead) - { - return new TipSignal( - textGetter: () => stat.description + "\n\n" + stat.Worker.GetExplanationFull(StatRequest.For(Pawn), ToStringNumberSense.Undefined, val), - uniqueId: stat.GetHashCode()); - } - return "Dead".Translate(); - } - } -} diff --git a/Source/RJWSexperience/SexHistory/UI/SexStatusWindow.cs b/Source/RJWSexperience/SexHistory/UI/SexStatusWindow.cs deleted file mode 100644 index f684891..0000000 --- a/Source/RJWSexperience/SexHistory/UI/SexStatusWindow.cs +++ /dev/null @@ -1,471 +0,0 @@ -using RimWorld; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using Verse; -using Verse.Sound; - -namespace RJWSexperience.SexHistory.UI -{ - public class SexStatusWindow : Window - { - public const float WINDOW_WIDTH = 900f; - public const float WINDOW_HEIGHT = 600f; - public const float FONTHEIGHT = UIUtility.FONTHEIGHT; - public const float CARDHEIGHT = UIUtility.CARDHEIGHT; - public const float LISTPAWNSIZE = UIUtility.LISTPAWNSIZE; - public const float BASESAT = UIUtility.BASESAT; - public const float ICONSIZE = UIUtility.ICONSIZE; - - private static GUIStyle fontStyleCenter; - private static GUIStyle fontStyleRight; - private static GUIStyle fontStyleLeft; - private static GUIStyle boxStyle; - private static GUIStyle buttonStyle; - - private SexStatusViewModel _context; - - protected PartnerOrderMode orderMode; - - private static Vector2 LastWindowPosition { get; set; } - private Vector2 scroll; - - private static void InitStyles() - { - if (fontStyleCenter != null) - { - return; - } - - GUIStyleState fontStyleState = new GUIStyleState() { textColor = Color.white }; - GUIStyleState boxStyleState = GUI.skin.textArea.normal; - GUIStyleState buttonStyleState = GUI.skin.button.normal; - fontStyleCenter = new GUIStyle() { alignment = TextAnchor.MiddleCenter, normal = fontStyleState }; - fontStyleRight = new GUIStyle() { alignment = TextAnchor.MiddleRight, normal = fontStyleState }; - fontStyleLeft = new GUIStyle() { alignment = TextAnchor.MiddleLeft, normal = fontStyleState }; - boxStyle = new GUIStyle(GUI.skin.textArea) { hover = boxStyleState, onHover = boxStyleState, onNormal = boxStyleState }; - buttonStyle = new GUIStyle(GUI.skin.button) { hover = buttonStyleState, onHover = buttonStyleState, onNormal = buttonStyleState }; - } - - public SexStatusWindow(SexHistoryComp history) - { - orderMode = PartnerOrderMode.Recent; - _context = new SexStatusViewModel(history, orderMode); - - soundClose = SoundDefOf.CommsWindow_Close; - absorbInputAroundWindow = false; - forcePause = false; - preventCameraMotion = false; - draggable = true; - doCloseX = true; - } - - protected override void SetInitialSizeAndPosition() - { - base.SetInitialSizeAndPosition(); - - if (LastWindowPosition == Vector2.zero) - return; - - windowRect.x = LastWindowPosition.x; - windowRect.y = LastWindowPosition.y; - } - - public override Vector2 InitialSize => new Vector2(WINDOW_WIDTH, WINDOW_HEIGHT); - - public override void PreOpen() - { - base.PreOpen(); - InitStyles(); - } - - public override void PreClose() - { - base.PreClose(); - LastWindowPosition = windowRect.position; - } - - public override void DoWindowContents(Rect inRect) - { - if (!SexperienceMod.Settings.SelectionLocked) - { - List selectedPawns = Find.Selector.SelectedPawns; - if (selectedPawns.Count == 1) - { - Pawn selectedPawn = selectedPawns[0]; - if (selectedPawn != _context.Pawn) - { - SexHistoryComp h = selectedPawn.TryGetComp(); - if (h != null) ChangePawn(h); - } - } - } - - _context.Update(); - DrawSexStatus(inRect); - } - - public static void ToggleWindow(SexHistoryComp history) - { - SexStatusWindow window = Find.WindowStack.WindowOfType(); - if (window != null) - { - if (window._context.Pawn != history.ParentPawn) - { - window.ChangePawn(history); - } - } - else - { - Find.WindowStack.Add(new SexStatusWindow(history)); - } - } - - public void ChangePawn(SexHistoryComp history) - { - Find.Selector.ClearSelection(); - _context = new SexStatusViewModel(history, orderMode); - if (!_context.Pawn.DestroyedOrNull() && Find.CurrentMap == _context.Pawn.Map) - { - Find.Selector.Select(_context.Pawn); - } - } - - /// - /// Main contents - /// - protected void DrawSexStatus(Rect mainrect) - { - float sectionwidth = mainrect.width / 3; - - Rect leftRect = new Rect(mainrect.x, mainrect.y, sectionwidth, mainrect.height); - Rect centerRect = new Rect(mainrect.x + sectionwidth, mainrect.y, sectionwidth, mainrect.height); - Rect rightRect = new Rect(mainrect.x + (sectionwidth * 2), mainrect.y, sectionwidth, mainrect.height); - - //Left section - DrawBaseSexInfoLeft(leftRect.ContractedBy(4f)); - - //Center section - DrawBaseSexInfoCenter(centerRect.ContractedBy(4f), _context.Pawn); - - //Right section - DrawBaseSexInfoRight(rightRect.ContractedBy(4f)); - } - - protected void DrawInfoWithPortrait(Rect rect, InfoCard context) - { - Widgets.DrawMenuSection(rect); - Rect portraitRect = new Rect(rect.x, rect.y, rect.height - FONTHEIGHT, rect.height - FONTHEIGHT); - Rect nameRect = new Rect(rect.x + portraitRect.width, rect.y, rect.width - portraitRect.width, FONTHEIGHT); - Rect sexinfoRect = new Rect(rect.x + portraitRect.width, rect.y + FONTHEIGHT, rect.width - portraitRect.width, FONTHEIGHT); - Rect sexinfoRect2 = new Rect(rect.x + portraitRect.width, rect.y + (FONTHEIGHT * 2), rect.width - portraitRect.width, FONTHEIGHT); - Rect bestsexRect = new Rect(rect.x + 2f, rect.y + (FONTHEIGHT * 3), rect.width - 4f, FONTHEIGHT - 2f); - - if (context.partnerRecord != null) - { - DrawPartnerPortrait(portraitRect, context.portraitInfo); - Widgets.DrawHighlightIfMouseover(portraitRect); - if (Widgets.ButtonInvisible(portraitRect)) - { - SexHistoryComp partnerHistory = context.partnerRecord.Partner?.TryGetComp(); - if (partnerHistory != null) - { - ChangePawn(partnerHistory); - SoundDefOf.Click.PlayOneShotOnCamera(); - } - else - { - SoundDefOf.ClickReject.PlayOneShotOnCamera(); - } - } - - GUI.Label(sexinfoRect2, context.relations + " ", fontStyleRight); - TooltipHandler.TipRegion(rect, context.tooltip); - } - else - { - Widgets.DrawTextureFitted(portraitRect, HistoryUtility.UnknownPawn, 1.0f); - } - Widgets.Label(nameRect, context.name); - Widgets.Label(sexinfoRect, context.sexCount); - Widgets.Label(sexinfoRect2, context.orgasms); - UIUtility.FillableBarLabeled(bestsexRect, context.bestSextype); - } - - protected void DrawSexInfoCard(Rect rect, InfoCard context) - { - rect.SplitHorizontally(FONTHEIGHT, out Rect labelRect, out Rect infoRect); - GUI.Label(labelRect, context.label, fontStyleLeft); - GUI.Label(labelRect, context.lastSexTime, fontStyleRight); - DrawInfoWithPortrait(infoRect, context); - } - - /// - /// Right section - /// - protected void DrawBaseSexInfoRight(Rect rect) - { - Listing_Standard listmain = new Listing_Standard(); - listmain.Begin(rect.ContractedBy(4f)); - foreach(InfoCard infoCard in _context.InfoCards) - { - DrawSexInfoCard(listmain.GetRect(CARDHEIGHT), infoCard); - } - GUI.Label(listmain.GetRect(FONTHEIGHT), Keyed.RS_PreferRace, fontStyleLeft); - DrawPreferRace(listmain.GetRect(66f + 15f), _context.PreferedRaceCard); - listmain.End(); - } - - protected void DrawPreferRace(Rect rect, PreferedRaceCard preferedRaceCard) - { - Widgets.DrawMenuSection(rect); - rect.SplitVertically(rect.height - 15f, out Rect portraitRect, out Rect infoRect); - portraitRect.height = portraitRect.width; - Rect infoRect1 = new Rect(infoRect.x, infoRect.y, infoRect.width, FONTHEIGHT); - Rect infoRect2 = new Rect(infoRect.x, infoRect.y + FONTHEIGHT, infoRect.width, FONTHEIGHT); - Rect infoRect3 = new Rect(infoRect.x, infoRect.y + (FONTHEIGHT * 2), infoRect.width - 2f, FONTHEIGHT); - - Widgets.DrawTextureFitted(portraitRect, preferedRaceCard.portraitGetter(portraitRect.size), 1.0f); - GUI.Label(infoRect1, preferedRaceCard.preferRaceLabel, fontStyleLeft); - - if (preferedRaceCard.preferRaceTypeLabel != null) - { - GUI.Label(infoRect1, preferedRaceCard.preferRaceTypeLabel + " ", fontStyleRight); - } - - if (preferedRaceCard.sexCount != null) - { - GUI.Label(infoRect2, preferedRaceCard.sexCount, fontStyleLeft); - } - - if (preferedRaceCard.barInfo != null) - { - UIUtility.FillableBarLabeled(infoRect3, (BarInfo)preferedRaceCard.barInfo); - } - } - - /// - /// Center section - /// - protected void DrawBaseSexInfoCenter(Rect rect, Pawn pawn) - { - Rect portraitRect = new Rect(rect.x + (rect.width / 4), rect.y, rect.width / 2, rect.width / 1.5f); - Rect nameRect = new Rect(portraitRect.x, portraitRect.yMax - (FONTHEIGHT * 2), portraitRect.width, FONTHEIGHT * 2); - Rect infoRect = rect.BottomPartPixels(rect.height - portraitRect.height - 20f); - - if (Mouse.IsOver(portraitRect)) - { - Rect lockRect = new Rect(portraitRect.xMax - ICONSIZE, portraitRect.y, ICONSIZE, ICONSIZE); - Configurations settings = SexperienceMod.Settings; - Texture lockIcon = settings.SelectionLocked ? HistoryUtility.Locked : HistoryUtility.Unlocked; - Widgets.DrawTextureFitted(lockRect, lockIcon, 1.0f); - TooltipHandler.TipRegion(lockRect, Keyed.RS_PawnLockDesc); - if (Widgets.ButtonInvisible(lockRect)) - { - SoundDefOf.Click.PlayOneShotOnCamera(); - settings.SelectionLocked.Value = !settings.SelectionLocked.Value; - } - } - - GUI.Box(portraitRect, "", boxStyle); - Widgets.DrawTextureFitted(portraitRect, PortraitsCache.Get(pawn, portraitRect.size, Rot4.South, default, 1, true, true, false, false), 1.0f); - if (_context.SelectedPartner != null) - { - Widgets.DrawHighlightIfMouseover(portraitRect); - if (Widgets.ButtonInvisible(portraitRect)) - { - SoundDefOf.Click.PlayOneShotOnCamera(); - _context.SetSelectedPartner(null); - } - } - - GUI.Box(nameRect, "", boxStyle); - GUI.Label(nameRect.TopHalf(), _context.Name, fontStyleCenter); - GUI.Label(nameRect.BottomHalf(), _context.AgeAndTitle, fontStyleCenter); - - Listing_Standard listmain = new Listing_Standard(); - listmain.Begin(infoRect); - - if (_context.VirginLabel != null) - { - Rect tmp = listmain.GetRect(FONTHEIGHT); - GUI.color = Color.red; - GUI.Box(tmp, "", boxStyle); - GUI.color = Color.white; - GUI.Label(tmp, _context.VirginLabel, fontStyleCenter); - listmain.Gap(1f); - } - else - { - listmain.FillableBarLabeled(_context.TotalSex); - } - - listmain.FillableBarLabeled(_context.Lust); - listmain.FillableBarLabeled(_context.BestSextype); - listmain.FillableBarLabeled(_context.RecentSextype); - - if (_context.Incest.fillPercent < _context.Necro.fillPercent) - { - listmain.FillableBarLabeled(_context.Necro); - } - else - { - listmain.FillableBarLabeled(_context.Incest); - } - - listmain.FillableBarLabeled(_context.ConsumedCum); - - if (_context.CumHediff != null) - { - listmain.FillableBarLabeled((BarInfo)_context.CumHediff); - } - else - { - listmain.Gap(FONTHEIGHT + 1f); - } - - if (_context.Raped.fillPercent < _context.BeenRaped.fillPercent) - { - listmain.FillableBarLabeled(_context.BeenRaped); - } - else - { - listmain.FillableBarLabeled(_context.Raped); - } - - listmain.FillableBarLabeled(_context.SexSatisfaction); - listmain.FillableBarLabeled(_context.SexSkill); - - if (_context.SelectedPartner != null) - { - DrawSexInfoCard(listmain.GetRect(CARDHEIGHT), _context.SelectedPartnerCard); - } - else - { - DrawExtraInfo(listmain.GetRect(CARDHEIGHT)); - } - listmain.End(); - } - - /// - /// Sexuality and quirks - /// - protected void DrawExtraInfo(Rect rect) - { - Widgets.DrawMenuSection(rect); - Rect inRect = rect.ContractedBy(4f); - Listing_Standard listmain = new Listing_Standard(); - listmain.Begin(inRect); - listmain.Gap(4f); - - Rect sexualityRect = listmain.GetRect(FONTHEIGHT); - if (_context.SexualityLabel != null) - { - Widgets.Label(sexualityRect, _context.SexualityLabel); - Widgets.DrawHighlightIfMouseover(sexualityRect); - } - listmain.Gap(1f); - - Rect quirkRect = listmain.GetRect(FONTHEIGHT * 3f); - Widgets.Label(quirkRect, _context.QuirksLabel); - Widgets.DrawHighlightIfMouseover(quirkRect); - TooltipHandler.TipRegion(quirkRect, _context.QuirksTooltip); - listmain.End(); - } - - /// - /// Left section - /// - protected void DrawBaseSexInfoLeft(Rect rect) - { - Listing_Standard listmain = new Listing_Standard(); - listmain.Begin(rect); - - //Sex statistics - GUI.Label(listmain.GetRect(FONTHEIGHT), " " + Keyed.RS_Statistics, fontStyleLeft); - listmain.Gap(1f); - - for (int i = 0; i < _context.SexTypes.Count; i++) - { - listmain.FillableBarLabeled(_context.SexTypes[i]); - } - - //Partner list - Rect listLabelRect = listmain.GetRect(FONTHEIGHT); - Rect sortbtnRect = new Rect(listLabelRect.xMax - 80f, listLabelRect.y, 80f, listLabelRect.height); - GUI.Label(listLabelRect, " " + Keyed.RS_PartnerList, fontStyleLeft); - if (Widgets.ButtonText(sortbtnRect, orderMode.Translate())) - { - SoundDefOf.Click.PlayOneShotOnCamera(); - orderMode = orderMode.Next(); - _context.SetPartnerOrder(orderMode); - } - - listmain.Gap(1f); - - Rect scrollRect = listmain.GetRect(CARDHEIGHT + 1f); - GUI.Box(scrollRect, "", buttonStyle); - if (!_context.Partners.EnumerableNullOrEmpty()) - { - Rect listRect = new Rect(scrollRect.x, scrollRect.y, LISTPAWNSIZE * _context.Partners.Count(), scrollRect.height - 30f); - Widgets.ScrollHorizontal(scrollRect, ref scroll, listRect); - Widgets.BeginScrollView(scrollRect, ref scroll, listRect); - DrawPartnerList(listRect, _context.Partners); - Widgets.EndScrollView(); - } - - listmain.End(); - } - - /// - /// Partners at the bottom of the left section - /// - protected void DrawPartnerList(Rect rect, IEnumerable partners) - { - Rect pawnRect = new Rect(rect.x, rect.y, LISTPAWNSIZE, LISTPAWNSIZE); - foreach (PartnerPortraitInfo partner in partners) - { - Rect labelRect = new Rect(pawnRect.x, pawnRect.yMax - FONTHEIGHT, pawnRect.width, FONTHEIGHT); - - DrawPartnerPortrait(pawnRect, partner); - Widgets.DrawHighlightIfMouseover(pawnRect); - GUI.Label(labelRect, partner.partnerRecord.Label, fontStyleCenter); - if (Widgets.ButtonInvisible(pawnRect)) - { - _context.SetSelectedPartner(partner.partnerRecord); - SoundDefOf.Click.PlayOneShotOnCamera(); - } - if (partner.partnerRecord == _context.SelectedPartner) - { - Widgets.DrawHighlightSelected(pawnRect); - } - - pawnRect.x += LISTPAWNSIZE; - } - } - - protected void DrawPartnerPortrait(Rect rect, PartnerPortraitInfo context) - { - Rect iconRect = new Rect(rect.x + (rect.width * 3 / 4), rect.y, rect.width / 4, rect.height / 4); - Texture img = context.portraitGetter(rect.size); - - if (context.partnerRecord.IamFirst) - { - GUI.color = HistoryUtility.HistoryColor; - Widgets.DrawTextureFitted(rect, HistoryUtility.FirstOverlay, 1.0f); - GUI.color = Color.white; - } - - if (context.partnerRecord.Incest) - { - Widgets.DrawTextureFitted(iconRect, HistoryUtility.Incest, 1.0f); - iconRect.x -= iconRect.width; - } - Widgets.DrawTextureFitted(rect, img, 1.0f); - if (context.lover) - { - Widgets.DrawTextureFitted(iconRect, HistoryUtility.Heart, 1.0f); - } - } - } -} diff --git a/Source/RJWSexperience/SexHistory/UI/UIUtility.cs b/Source/RJWSexperience/SexHistory/UI/UIUtility.cs deleted file mode 100644 index 29721d4..0000000 --- a/Source/RJWSexperience/SexHistory/UI/UIUtility.cs +++ /dev/null @@ -1,80 +0,0 @@ -using RimWorld; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Remoting.Contexts; -using UnityEngine; -using Verse; - -namespace RJWSexperience.SexHistory.UI -{ - public static class UIUtility - { - public const float FONTHEIGHT = 22f; - public const float CARDHEIGHT = 110f; - public const float LISTPAWNSIZE = 100f; - public const float BASESAT = 0.40f; - public const float ICONSIZE = 30f; - - public static string GetRelationsString(this Pawn pawn, Pawn otherpawn) - { - if (otherpawn != null) - { - IEnumerable relations = pawn.GetRelations(otherpawn); - if (!relations.EnumerableNullOrEmpty()) - return relations.Select(x => x.GetGenderSpecificLabel(otherpawn)).ToCommaList().CapitalizeFirst(); - } - return ""; - } - - public static void DrawBorder(this Rect rect, Texture border, float thickness = 1f) - { - GUI.DrawTexture(new Rect(rect.x, rect.y, rect.width, thickness), border); - GUI.DrawTexture(new Rect(rect.x + rect.width - thickness, rect.y, thickness, rect.height), border); - GUI.DrawTexture(new Rect(rect.x, rect.y + rect.height - thickness, rect.width, thickness), border); - GUI.DrawTexture(new Rect(rect.x, rect.y, thickness, rect.height), border); - } - - public static string GetSexDays(int absticks, bool printUnknown = false) - { - if (absticks != 0) - return GenDate.ToStringTicksToDays(GenTicks.TicksAbs - absticks) + " " + Keyed.RS_Ago; - else if (printUnknown) - return Keyed.Unknown; - return ""; - } - - public static Texture GetRaceIcon(Pawn pawn, Vector2 size) - { - if (pawn != null) - return PortraitsCache.Get(pawn, size, Rot4.South, default, 1, true, true, false, false); - return HistoryUtility.UnknownPawn; - } - - public static void FillableBarLabeled(Rect rect, BarInfo context) - { - Widgets.FillableBar(rect, context.fillPercent, context.fillTexture, null, true); - Rect labelRect = rect.ContractedBy(4f, 0f); - Text.Anchor = TextAnchor.MiddleLeft; - Widgets.Label(labelRect, context.label); - if (context.labelRight != "") - { - Text.Anchor = TextAnchor.MiddleRight; - Widgets.Label(labelRect, context.labelRight); - } - GenUI.ResetLabelAlign(); - Widgets.DrawHighlightIfMouseover(rect); - TooltipHandler.TipRegion(rect, context.tooltip); - - if (context.border != null) - { - rect.DrawBorder(context.border, 2f); - } - } - - public static void FillableBarLabeled(this Listing_Standard list, BarInfo context) - { - FillableBarLabeled(list.GetRect(FONTHEIGHT), context); - list.Gap(1f); - } - } -} diff --git a/Source/RJWSexperience/StatParts.cs b/Source/RJWSexperience/StatParts.cs index 206a296..eafdc43 100644 --- a/Source/RJWSexperience/StatParts.cs +++ b/Source/RJWSexperience/StatParts.cs @@ -24,7 +24,7 @@ namespace RJWSexperience val *= GetLustFactor(pawn); } - protected float GetLustFactor(Pawn pawn) => LustUtility.GetLustFactor(pawn.records.GetValue(RsDefOf.Record.Lust)); + protected float GetLustFactor(Pawn pawn) => LustUtility.GetLustFactor(pawn.records.GetValue(VariousDefOf.Lust)); } /// diff --git a/Source/RJWSexperience/Thoughts/ThoughtDefExtension_StageFromRecord.cs b/Source/RJWSexperience/Thoughts/ThoughtDefExtension_StageFromRecord.cs index cfa836e..6ff0001 100644 --- a/Source/RJWSexperience/Thoughts/ThoughtDefExtension_StageFromRecord.cs +++ b/Source/RJWSexperience/Thoughts/ThoughtDefExtension_StageFromRecord.cs @@ -5,51 +5,11 @@ using Verse; namespace RJWSexperience { - [SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Field value loaded from XML")] public class ThoughtDefExtension_StageFromRecord : DefModExtension { + [SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Field value loaded from XML")] public RecordDef recordDef; + [SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Field value loaded from XML")] public List minimumValueforStage = new List(); - - public int GetStageIndex(Pawn pawn) - { - float value = pawn?.records?.GetValue(recordDef) ?? 0f; - - for (int i = minimumValueforStage.Count - 1; i > 0; i--) - { - if (minimumValueforStage[i] < value) - { - return i; - } - } - - return 0; - } - - public override IEnumerable ConfigErrors() - { - foreach (string error in base.ConfigErrors()) - { - yield return error; - } - - if (recordDef == null) - { - yield return " is null"; - } - - if (minimumValueforStage.NullOrEmpty()) - { - yield return " should have an entry for every stage"; - } - - for (int i = 0; i < minimumValueforStage.Count - 1; i++) - { - if (minimumValueforStage[i] > minimumValueforStage[i + 1]) - { - yield return "Values in should be ordered from the lowest to the highest"; - } - } - } } } diff --git a/Source/RJWSexperience/Thoughts/Thought_Recordbased.cs b/Source/RJWSexperience/Thoughts/Thought_Recordbased.cs index dd79ab4..48dc19a 100644 --- a/Source/RJWSexperience/Thoughts/Thought_Recordbased.cs +++ b/Source/RJWSexperience/Thoughts/Thought_Recordbased.cs @@ -1,28 +1,39 @@ using RimWorld; -using Verse; +using System.Collections.Generic; namespace RJWSexperience { /// - /// Thought class that uses record to select active stage + /// Thought class using record. /// public class Thought_Recordbased : Thought_Memory { private ThoughtDefExtension_StageFromRecord extension; - protected ThoughtDefExtension_StageFromRecord Extension => extension ?? (extension = def.GetModExtension()); - /// - /// This method is called for every thought right after the pawn is assigned - /// - public override bool TryMergeWithExistingMemory(out bool showBubble) + protected ThoughtDefExtension_StageFromRecord Extension { - UpdateCurStage(); - return base.TryMergeWithExistingMemory(out showBubble); + get + { + if (extension == null) + extension = def.GetModExtension(); + return extension; + } } - protected virtual void UpdateCurStage() + protected RecordDef RecordDef => Extension.recordDef; + protected List MinimumValueforStage => Extension.minimumValueforStage; + + public override int CurStageIndex { - SetForcedStage(Extension.GetStageIndex(pawn)); + get + { + float value = pawn?.records?.GetValue(RecordDef) ?? 0f; + for (int i = MinimumValueforStage.Count - 1; i > 0; i--) + { + if (MinimumValueforStage[i] < value) return i; + } + return 0; + } } } } diff --git a/Source/RJWSexperience/VariousDefOf.cs b/Source/RJWSexperience/VariousDefOf.cs new file mode 100644 index 0000000..3f03d67 --- /dev/null +++ b/Source/RJWSexperience/VariousDefOf.cs @@ -0,0 +1,37 @@ +using RimWorld; +using Verse; + +namespace RJWSexperience +{ + [DefOf] + public static class VariousDefOf + { + public static readonly RecordDef NumofEatenCum; + public static readonly RecordDef AmountofEatenCum; + public static readonly RecordDef Lust; + public static readonly RecordDef VaginalSexCount; + public static readonly RecordDef AnalSexCount; + public static readonly RecordDef OralSexCount; + public static readonly RecordDef BlowjobCount; + public static readonly RecordDef CunnilingusCount; + public static readonly RecordDef GenitalCaressCount; + public static readonly RecordDef HandjobCount; + public static readonly RecordDef FingeringCount; + public static readonly RecordDef FootjobCount; + public static readonly RecordDef MiscSexualBehaviorCount; + public static readonly RecordDef SexPartnerCount; + public static readonly RecordDef OrgasmCount; + public static readonly SkillDef Sex; + public static readonly ThingDef CumBucket; + public static readonly ThingDef GatheredCum; + public static readonly ThingDef FilthCum; + public static readonly ChemicalDef Cum; + public static readonly NeedDef Chemical_Cum; + public static readonly TraitDef Virgin; + public static readonly KeyBindingDef OpenSexStatistics; + public static readonly StatDef SexAbility; + + public static readonly HediffDef CumAddiction; + public static readonly HediffDef CumTolerance; + } +} diff --git a/Source/RJWSexperience/Virginity/Recipe_HymenSurgery.cs b/Source/RJWSexperience/Virginity/Recipe_HymenSurgery.cs index c215696..f859e46 100644 --- a/Source/RJWSexperience/Virginity/Recipe_HymenSurgery.cs +++ b/Source/RJWSexperience/Virginity/Recipe_HymenSurgery.cs @@ -26,10 +26,14 @@ namespace RJWSexperience.Virginity if (billDoer == null) return; - TaleRecorder.RecordTale(TaleDefOf.DidSurgery, billDoer, pawn); + TaleRecorder.RecordTale(TaleDefOf.DidSurgery, new object[] + { + billDoer, + pawn + }); TraitHandler.AddVirginTrait(pawn); } - private static bool HasHymen(Pawn pawn) => pawn.story?.traits?.GetTrait(RsDefOf.Trait.Virgin)?.Degree > 0; + private static bool HasHymen(Pawn pawn) => pawn.story?.traits?.GetTrait(VariousDefOf.Virgin)?.Degree > 0; } } diff --git a/Source/RJWSexperience/Virginity/TraitHandler.cs b/Source/RJWSexperience/Virginity/TraitHandler.cs index 21cc148..40261d6 100644 --- a/Source/RJWSexperience/Virginity/TraitHandler.cs +++ b/Source/RJWSexperience/Virginity/TraitHandler.cs @@ -1,4 +1,5 @@ using RimWorld; +using rjw; using Verse; namespace RJWSexperience.Virginity @@ -16,7 +17,7 @@ namespace RJWSexperience.Virginity { if (Rand.Chance(hymenSurgeryChance)) { - Trait virgin = new Trait(RsDefOf.Trait.Virgin, TraitDegree.FemaleAfterSurgery, true); + Trait virgin = new Trait(VariousDefOf.Virgin, TraitDegree.FemaleAfterSurgery, true); pawn.story.traits.GainTrait(virgin); } return; @@ -35,23 +36,19 @@ namespace RJWSexperience.Virginity int degree = TraitDegree.MaleVirgin; if (pawn.gender == Gender.Female) degree = TraitDegree.FemaleVirgin; - Trait virgin = new Trait(RsDefOf.Trait.Virgin, degree, true); + Trait virgin = new Trait(VariousDefOf.Virgin, degree, true); pawn.story.traits.GainTrait(virgin); } else if (pawn.gender == Gender.Female) { - Trait virgin = new Trait(RsDefOf.Trait.Virgin, TraitDegree.FemaleAfterSurgery, true); + Trait virgin = new Trait(VariousDefOf.Virgin, TraitDegree.FemaleAfterSurgery, true); pawn.story.traits.GainTrait(virgin); } } - /// - /// Remove virginity trait and spawn blood filth if applicable - /// - /// Degree of the removed trait public static int? RemoveVirginTrait(Pawn pawn) { - Trait virgin = pawn.story?.traits?.GetTrait(RsDefOf.Trait.Virgin); + Trait virgin = pawn.story?.traits?.GetTrait(VariousDefOf.Virgin); if (virgin == null) return null; diff --git a/changelogs.txt b/changelogs.txt index eb12aa7..ff36265 100644 --- a/changelogs.txt +++ b/changelogs.txt @@ -1,10 +1,3 @@ -Version 1.1.4.0 - - Optimized SexStatusWindow - - Optimized Ate Cum thought - - Optimized? cum food filter - - Simplified virginity checks code - - Simplified bucket selection code - Version 1.1.3.0 - Removed "Hide Sex History button with RJW designators" setting - Fixed error with pawn masturbated on the map border