diff --git a/RJWSexperience/RJWSexperience/DebugAction.cs b/RJWSexperience/RJWSexperience/DebugAction.cs index c99fd27..61a253d 100644 --- a/RJWSexperience/RJWSexperience/DebugAction.cs +++ b/RJWSexperience/RJWSexperience/DebugAction.cs @@ -1,4 +1,5 @@ using RimWorld; +using rjw; using RJWSexperience.ExtensionMethods; using Verse; @@ -11,8 +12,8 @@ namespace RJWSexperience { Trait virgin = p.story?.traits?.GetTrait(VariousDefOf.Virgin); if (virgin != null) p.story.traits.RemoveTrait(virgin); - p.ResetRecord(true); - p.ResetRecord(false); + ResetRecord(p, true); + ResetRecord(p, false); p.AddVirginTrait(); MoteMaker.ThrowText(p.TrueCenter(), p.Map, "Records resetted!"); } @@ -20,7 +21,7 @@ namespace RJWSexperience [DebugAction("RJW Sexperience", "Reset pawn's record(virgin)", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.PlayingOnMap)] private static void ResetRecordsZero(Pawn p) { - p.ResetRecord(true); + ResetRecord(p, true); p.AddVirginTrait(); MoteMaker.ThrowText(p.TrueCenter(), p.Map, "Records resetted!\nVirginified!"); } @@ -55,5 +56,52 @@ namespace RJWSexperience MoteMaker.ThrowText(p.TrueCenter(), p.Map, "Lust: " + p.records.GetValue(VariousDefOf.Lust)); } + private static void ResetRecord(Pawn pawn, bool allzero) + { + if (!allzero) + { + if (Configurations.EnableRecordRandomizer && pawn != null && xxx.is_human(pawn)) + { + RecordRandomizer.Randomize(pawn); + } + } + else + { + 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); + pawn.records.SetTo(xxx.CountOfBeenRapedByOthers, 0); + pawn.records.SetTo(xxx.CountOfBirthAnimal, 0); + pawn.records.SetTo(xxx.CountOfBirthEgg, 0); + pawn.records.SetTo(xxx.CountOfBirthHuman, 0); + pawn.records.SetTo(xxx.CountOfFappin, 0); + pawn.records.SetTo(xxx.CountOfRapedAnimals, 0); + pawn.records.SetTo(xxx.CountOfRapedHumanlikes, 0); + pawn.records.SetTo(xxx.CountOfRapedInsects, 0); + pawn.records.SetTo(xxx.CountOfRapedOthers, 0); + pawn.records.SetTo(xxx.CountOfSex, 0); + pawn.records.SetTo(xxx.CountOfSexWithAnimals, 0); + pawn.records.SetTo(xxx.CountOfSexWithCorpse, 0); + pawn.records.SetTo(xxx.CountOfSexWithHumanlikes, 0); + pawn.records.SetTo(xxx.CountOfSexWithInsects, 0); + pawn.records.SetTo(xxx.CountOfSexWithOthers, 0); + pawn.records.SetTo(xxx.CountOfWhore, 0); + } + } } } diff --git a/RJWSexperience/RJWSexperience/ExtensionMethods/PawnExtensions.cs b/RJWSexperience/RJWSexperience/ExtensionMethods/PawnExtensions.cs index 7112fc4..eabef6d 100644 --- a/RJWSexperience/RJWSexperience/ExtensionMethods/PawnExtensions.cs +++ b/RJWSexperience/RJWSexperience/ExtensionMethods/PawnExtensions.cs @@ -194,53 +194,5 @@ namespace RJWSexperience.ExtensionMethods } } } - - public static void ResetRecord(this Pawn pawn, bool allzero) - { - if (!allzero) - { - if (Configurations.EnableRecordRandomizer && pawn != null && xxx.is_human(pawn)) - { - RecordRandomizer.Randomize(pawn); - } - } - else - { - 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); - pawn.records.SetTo(xxx.CountOfBeenRapedByOthers, 0); - pawn.records.SetTo(xxx.CountOfBirthAnimal, 0); - pawn.records.SetTo(xxx.CountOfBirthEgg, 0); - pawn.records.SetTo(xxx.CountOfBirthHuman, 0); - pawn.records.SetTo(xxx.CountOfFappin, 0); - pawn.records.SetTo(xxx.CountOfRapedAnimals, 0); - pawn.records.SetTo(xxx.CountOfRapedHumanlikes, 0); - pawn.records.SetTo(xxx.CountOfRapedInsects, 0); - pawn.records.SetTo(xxx.CountOfRapedOthers, 0); - pawn.records.SetTo(xxx.CountOfSex, 0); - pawn.records.SetTo(xxx.CountOfSexWithAnimals, 0); - pawn.records.SetTo(xxx.CountOfSexWithCorpse, 0); - pawn.records.SetTo(xxx.CountOfSexWithHumanlikes, 0); - pawn.records.SetTo(xxx.CountOfSexWithInsects, 0); - pawn.records.SetTo(xxx.CountOfSexWithOthers, 0); - pawn.records.SetTo(xxx.CountOfWhore, 0); - } - } } } diff --git a/RJWSexperience/RJWSexperience/RJWSexperience.csproj b/RJWSexperience/RJWSexperience/RJWSexperience.csproj index 9b79505..45a2126 100644 --- a/RJWSexperience/RJWSexperience/RJWSexperience.csproj +++ b/RJWSexperience/RJWSexperience/RJWSexperience.csproj @@ -79,6 +79,7 @@ + diff --git a/RJWSexperience/RJWSexperience/SexHistory/SexHistory.cs b/RJWSexperience/RJWSexperience/SexHistory/SexHistory.cs index b91ce12..2738e72 100644 --- a/RJWSexperience/RJWSexperience/SexHistory/SexHistory.cs +++ b/RJWSexperience/RJWSexperience/SexHistory/SexHistory.cs @@ -11,567 +11,6 @@ using RJWSexperience.ExtensionMethods; namespace RJWSexperience { - public class SexPartnerHistory : ThingComp - { - public SexPartnerHistory() { } - public const int ARRLEN = 20; - - //protected List histories = new List(); - protected Dictionary histories = new Dictionary(); - protected string first = ""; - protected bool dirty = true; - protected xxx.rjwSextype recentsex = xxx.rjwSextype.None; - protected float recentsat = 0; - protected string recentpartner = ""; - protected int[] sextypecount = new int[ARRLEN]; - protected float[] sextypesat = new float[ARRLEN]; - protected int[] sextyperecenttickabs = new int[ARRLEN]; - protected int virginstaken = 0; - protected int incestuous = 0; - protected int bestiality = 0; - protected int corpsefuck = 0; - protected int interspecies = 0; - protected int firstsextickabs = 0; - - protected string mostpartnercache = ""; - protected xxx.rjwSextype mostsextypecache = xxx.rjwSextype.None; - protected xxx.rjwSextype mostsatsextypecache = xxx.rjwSextype.None; - protected xxx.rjwSextype bestsextypecache = xxx.rjwSextype.None; - protected float bestsextypesatcache = 0; - protected string bestpartnercache = ""; - protected int totalsexcache = 0; - protected int totalrapedcache = 0; - protected int totalbeenrapedcache = 0; - protected ThingDef preferracecache = null; - protected int preferracesexcountcache = 0; - protected Pawn preferracepawncache = null; - protected float avtsatcache = 0; - protected int recentsextickabscache = 0; - protected int mostsextickabscache = 0; - protected int bestsextickabscache = 0; - - - - - public SexHistory GetFirstPartnerHistory - { - get - { - Update(); - return histories.TryGetValue(first); - } - } - public SexHistory GetMostPartnerHistory - { - get - { - Update(); - return histories.TryGetValue(mostpartnercache); - } - } - public xxx.rjwSextype MostSextype - { - get - { - Update(); - return mostsextypecache; - } - } - public xxx.rjwSextype MostSatisfiedSex - { - get - { - Update(); - return mostsatsextypecache; - } - } - public SexHistory GetRecentPartnersHistory - { - get - { - return histories.TryGetValue(recentpartner); - } - } - public SexHistory GetBestSexPartnerHistory - { - get - { - Update(); - SexHistory history = histories.TryGetValue(bestpartnercache); - return history; - } - } - public float TotalSexHad - { - get - { - Update(); - return totalsexcache; - } - } - public int VirginsTaken - { - get - { - return virginstaken; - } - } - public List PartnerList - { - get - { - List res = null; - Update(); - if (!histories.NullOrEmpty()) - { - res = histories.Values.ToList(); - } - return res; - } - } - public int PartnerCount - { - get - { - if (histories == null) histories = new Dictionary(); - return histories.Count; - } - } - public int IncestuousCount - { - get - { - return incestuous; - } - } - public int RapedCount - { - get - { - Update(); - return totalrapedcache; - } - } - public int BeenRapedCount - { - get - { - Update(); - return totalbeenrapedcache; - } - } - public ThingDef PreferRace - { - get - { - Update(); - return preferracecache; - } - } - public int PreferRaceSexCount - { - get - { - Update(); - return preferracesexcountcache; - } - } - public int BestialityCount - { - get - { - return bestiality; - } - } - public int CorpseFuckCount - { - get - { - return corpsefuck; - } - } - public int InterspeciesCount - { - get - { - return interspecies; - } - } - public float AVGSat - { - get - { - Update(); - if (totalsexcache == 0) return 0; - return sextypesat.Sum() / totalsexcache; - } - } - public int RecentSexElapsedTicks - { - get - { - return GenTicks.TicksAbs - recentsextickabscache; - } - } - public string RecentSexDays - { - get - { - if (recentsextickabscache != 0) return GenDate.ToStringTicksToDays(RecentSexElapsedTicks) + " " + Keyed.RS_Ago; - return ""; - } - } - public int FirstSexElapsedTicks - { - get - { - return GenTicks.TicksAbs - firstsextickabs; - } - } - public string FirstSexDays - { - get - { - if (firstsextickabs != 0) return GenDate.ToStringTicksToDays(FirstSexElapsedTicks) + " " + Keyed.RS_Ago; - return ""; - } - } - public int MostSexElapsedTicks - { - get - { - return GenTicks.TicksAbs - mostsextickabscache; - } - } - public string MostSexDays - { - get - { - if (mostsextickabscache != 0) return GenDate.ToStringTicksToDays(MostSexElapsedTicks) + " " + Keyed.RS_Ago; - return ""; - } - } - public int BestSexElapsedTicks - { - get - { - return GenTicks.TicksAbs - bestsextickabscache; - } - } - public string BestSexDays - { - get - { - if (bestsextickabscache != 0) return GenDate.ToStringTicksToDays(BestSexElapsedTicks) + " " + Keyed.RS_Ago; - return ""; - } - } - - - public Texture GetPreferRaceIcon(Vector2 size) - { - Update(); - if (preferracepawncache != null) return PortraitsCache.Get(preferracepawncache, size, Rot4.South, default, 1, true, true, false, false); - else return HistoryUtility.UnknownPawn; - - } - - public float GetBestSextype(out xxx.rjwSextype sextype) - { - if (dirty) Update(); - sextype = bestsextypecache; - return bestsextypesatcache; - } - - public float GetRecentSextype(out xxx.rjwSextype sextype) - { - if (dirty) Update(); - sextype = recentsex; - return recentsat; - } - - public string SextypeRecentDays(int sextype) - { - int index = (int)sextype; - if (sextyperecenttickabs[index] != 0) return GenDate.ToStringTicksToDays(GenTicks.TicksAbs - sextyperecenttickabs[index]) + " " + Keyed.RS_Ago; - return Keyed.Unknown; - } - - public SexHistory this[Pawn pawn] - { - get - { - return histories.TryGetValue(pawn.ThingID); - } - } - - public float GetAVGSat(xxx.rjwSextype sextype) - { - int index = (int)sextype; - return GetAVGSat(index); - } - - public float GetAVGSat(int index) - { - float res = sextypesat[index] / sextypecount[index]; - return float.IsNaN(res) ? 0f : res; - } - - public int GetSexCount(int index) - { - return sextypecount[index]; - } - - - - public override void PostExposeData() - { - List sextypecountsave; - List sextypesatsave; - List sextyperecenttickabssave; - - if (Scribe.mode == LoadSaveMode.Saving) - { - sextypecountsave = sextypecount.ToList(); - sextypesatsave = sextypesat.ToList(); - sextyperecenttickabssave = sextyperecenttickabs.ToList(); - } - else - { - sextypecountsave = new List(); - sextypesatsave = new List(); - sextyperecenttickabssave = new List(); - } - - Scribe_Collections.Look(ref histories, "histories", LookMode.Value, LookMode.Deep); - Scribe_Values.Look(ref first, "first", "", true); - Scribe_Values.Look(ref recentsex, "recentsex", recentsex, true); - Scribe_Values.Look(ref recentsat, "recentsat", recentsat, true); - Scribe_Values.Look(ref recentpartner, "recentpartner", recentpartner, true); - Scribe_Values.Look(ref virginstaken, "virginstaken", virginstaken, true); - Scribe_Values.Look(ref incestuous, "incestous", incestuous, true); - Scribe_Values.Look(ref bestiality, "bestiality", bestiality, true); - Scribe_Values.Look(ref corpsefuck, "corpsefuck", corpsefuck, true); - Scribe_Values.Look(ref interspecies, "interspecies", interspecies, true); - Scribe_Values.Look(ref firstsextickabs, "firstsextickabs", firstsextickabs, true); - Scribe_Collections.Look(ref sextypecountsave, "sextypecountsave", LookMode.Value); - Scribe_Collections.Look(ref sextypesatsave, "sextypesatsave", LookMode.Value); - Scribe_Collections.Look(ref sextyperecenttickabssave, "sextyperecenttickabssave", LookMode.Value); - //Scribe_Values.Look(ref sextypecount, "sextypecount", new int[ARRLEN], true); // not work - //Scribe_Values.Look(ref sextypesat, "sextypesat", new float[ARRLEN], true); - if (histories == null) histories = new Dictionary(); - - if (Scribe.mode == LoadSaveMode.LoadingVars) - { - sextypecount = sextypecountsave?.ToArray() ?? new int[ARRLEN]; - sextypesat = sextypesatsave?.ToArray() ?? new float[ARRLEN]; - sextyperecenttickabs = sextyperecenttickabssave?.ToArray() ?? new int[ARRLEN]; - - foreach (KeyValuePair element in histories) - { - element.Value.parent = this; - element.Value.partnerID = element.Key; - } - } - base.PostExposeData(); - } - - public void RecordHistory(Pawn partner, SexProps props) - { - Pawn pawn = parent as Pawn; - TryAddHistory(partner); - RecordFirst(partner, props); - recentpartner = partner.ThingID; - SexHistory history = histories[partner.ThingID]; - history?.RecordSex(props); - recentsex = props.sexType; - sextypecount[(int)props.sexType]++; - sextyperecenttickabs[(int)props.sexType] = GenTicks.TicksAbs; - if (partner.IsIncest(pawn)) incestuous++; - if (partner.Dead) corpsefuck++; - if (props.IsBestiality()) bestiality++; - else if (pawn.def != partner.def) interspecies++; - dirty = true; - } - - public void RecordSatisfactionHistory(Pawn partner, SexProps props, float satisfaction) - { - TryAddHistory(partner); - RecordFirst(partner, props); - SexHistory history = histories[partner.ThingID]; - history?.RecordSatisfaction(props, satisfaction); - recentsat = satisfaction; - sextypesat[(int)props.sexType] += satisfaction; - dirty = true; - } - - protected bool TryAddHistory(Pawn partner) - { - if (!histories.ContainsKey(partner.ThingID)) - { - SexHistory newhistory = new SexHistory(partner,partner.IsIncest(parent as Pawn)); - histories.Add(partner.ThingID, newhistory); - Pawn pawn = parent as Pawn; - if (pawn != null) - { - pawn.records.AddTo(VariousDefOf.SexPartnerCount, 1); - } - return true; - } - return false; - } - - public void RecordFirst(Pawn partner, SexProps props) - { - if (VirginCheck() && props.sexType == xxx.rjwSextype.Vaginal) - { - TryAddHistory(partner); - first = partner.ThingID; - SexPartnerHistory history = partner.GetPartnerHistory(); - firstsextickabs = GenTicks.TicksAbs; - if (history != null) - { - history.TakeSomeonesVirgin(parent as Pawn); - } - - } - } - - public void TakeSomeonesVirgin(Pawn partner) - { - TryAddHistory(partner); - SexHistory history = histories[partner.ThingID]; - if (history != null) history.TookVirgin(); - virginstaken++; - } - - protected void Update() - { - if (dirty) - { - UpdateStatistics(); - UpdateBestSex(); - dirty = false; - } - } - - protected void UpdateStatistics() - { - int max = 0; - float maxsat = 0; - float maxf = 0; - int maxindex = 0; - string mostID = Keyed.Unknown; - string bestID = Keyed.Unknown; - - totalsexcache = 0; - totalrapedcache = 0; - totalbeenrapedcache = 0; - Dictionary racetotalsat = new Dictionary(); - List allpartners = new List(); - - foreach (KeyValuePair element in histories) - { - SexHistory h = element.Value; - - //find most sex partner - if (max < h.TotalSexCount) - { - max = h.TotalSexCount; - mostID = element.Key; - } - if (maxsat < h.BestSatisfaction) - { - maxsat = h.BestSatisfaction; - bestID = element.Key; - } - - if (h.Partner != null) - { - Pawn partner = h.Partner; - allpartners.Add(partner); - if (racetotalsat.ContainsKey(h.Race)) - { - racetotalsat[h.Race] += h.TotalSexCount - h.RapedMe; - } - else - { - racetotalsat.Add(h.Race, h.TotalSexCount - h.RapedMe); - } - } - - totalsexcache += h.TotalSexCount; - totalrapedcache += h.Raped; - totalbeenrapedcache += h.RapedMe; - } - - if (!racetotalsat.NullOrEmpty()) - { - KeyValuePair prefer = racetotalsat.MaxBy(x => x.Value); - preferracecache = prefer.Key; - preferracesexcountcache = prefer.Value; - preferracepawncache = allpartners.FirstOrDefault(x => x.def == preferracecache); - } - - max = 0; - for (int i=0; i < sextypecount.Length; i++) - { - float avgsat = sextypesat[i] / sextypecount[i]; - if (maxf < avgsat) - { - maxf = avgsat; - maxindex = i; - } - } - - mostsatsextypecache = (xxx.rjwSextype)maxindex; - mostsextypecache = (xxx.rjwSextype)sextypecount.FirstIndexOf(x => x == sextypecount.Max()); - mostpartnercache = mostID; - bestpartnercache = bestID; - - recentsextickabscache = histories.TryGetValue(recentpartner)?.RecentSexTickAbs ?? 0; - mostsextickabscache = histories.TryGetValue(mostpartnercache)?.RecentSexTickAbs ?? 0; - bestsextickabscache = histories.TryGetValue(bestpartnercache)?.BestSexTickAbs ?? 0; - - racetotalsat.Clear(); - allpartners.Clear(); - } - - protected void UpdateBestSex() - { - int bestindex = 0; - float bestsat = 0; - float avgsat; - for(int i=0; i< sextypecount.Length; i++) - { - avgsat = sextypesat[i] / sextypecount[i]; - if (bestsat < avgsat) - { - bestindex = i; - bestsat = avgsat; - } - } - bestsextypecache = (xxx.rjwSextype)bestindex; - bestsextypesatcache = bestsat; - } - - protected bool VirginCheck() - { - if (histories.TryGetValue(first) != null) return false; - - Pawn pawn = parent as Pawn; - if (pawn != null) - { - if (pawn.IsVirgin()) return true; - } - return false; - } - - - - } - - public class SexHistory : IExposable { public SexPartnerHistory parent; @@ -592,7 +31,6 @@ namespace RJWSexperience protected bool cannotLoadPawnData = false; protected ThingDef race; - public string Label { get @@ -648,63 +86,15 @@ namespace RJWSexperience return res; } } - public int OrgasmCount - { - get - { - return orgasms; - } - } - public bool IamFirst - { - get - { - return itookvirgin; - } - } - public bool Incest - { - get - { - return incest; - } - } - public int Raped - { - get - { - return raped; - } - } - public int RapedMe - { - get - { - return rapedme; - } - } - public int RecentSexTickAbs - { - get - { - return recentsextickabs; - } - } - public int BestSexTickAbs - { - get - { - return bestsextickabs; - } - } - public int BestSexElapsedTicks - { - get - { - return GenTicks.TicksAbs - bestsextickabs; - } - } - public string BestSexDays + public int OrgasmCount => orgasms; + public bool IamFirst => itookvirgin; + public bool Incest => incest; + public int Raped => raped; + public int RapedMe => rapedme; + public int RecentSexTickAbs => recentsextickabs; + public int BestSexTickAbs => bestsextickabs; + public int BestSexElapsedTicks => GenTicks.TicksAbs - bestsextickabs; + public string BestSexDays { get { @@ -729,16 +119,14 @@ namespace RJWSexperience public SexHistory(Pawn pawn, bool incest = false) { - this.partner = pawn; + this.partner = pawn; this.namecache = pawn.Label; this.incest = incest; this.race = pawn.def; } - public void ExposeData() { - //Scribe_References.Look(ref partner, "partner", true); Scribe_Values.Look(ref namecache, "namecache", namecache, true); Scribe_Values.Look(ref totalsexhad, "totalsexhad", totalsexhad, true); Scribe_Values.Look(ref raped, "raped", raped, true); @@ -786,7 +174,7 @@ namespace RJWSexperience itookvirgin = true; } - public void LoadPartnerPawn(string partnerID) + protected void LoadPartnerPawn(string partnerID) { foreach (Map map in Find.Maps) { diff --git a/RJWSexperience/RJWSexperience/SexHistory/SexPartnerHistory.cs b/RJWSexperience/RJWSexperience/SexHistory/SexPartnerHistory.cs new file mode 100644 index 0000000..bb60dd2 --- /dev/null +++ b/RJWSexperience/RJWSexperience/SexHistory/SexPartnerHistory.cs @@ -0,0 +1,478 @@ +using RimWorld; +using rjw; +using RJWSexperience.ExtensionMethods; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using Verse; + +namespace RJWSexperience +{ + public class SexPartnerHistory : ThingComp + { + public SexPartnerHistory() { } + public const int ARRLEN = 20; + + protected Dictionary histories = new Dictionary(); + protected string first = ""; + protected bool dirty = true; + protected xxx.rjwSextype recentsex = xxx.rjwSextype.None; + protected float recentsat = 0; + protected string recentpartner = ""; + protected int[] sextypecount = new int[ARRLEN]; + protected float[] sextypesat = new float[ARRLEN]; + protected int[] sextyperecenttickabs = new int[ARRLEN]; + protected int virginstaken = 0; + protected int incestuous = 0; + protected int bestiality = 0; + protected int corpsefuck = 0; + protected int interspecies = 0; + protected int firstsextickabs = 0; + + protected string mostpartnercache = ""; + protected xxx.rjwSextype mostsextypecache = xxx.rjwSextype.None; + protected xxx.rjwSextype mostsatsextypecache = xxx.rjwSextype.None; + protected xxx.rjwSextype bestsextypecache = xxx.rjwSextype.None; + protected float bestsextypesatcache = 0; + protected string bestpartnercache = ""; + protected int totalsexcache = 0; + protected int totalrapedcache = 0; + protected int totalbeenrapedcache = 0; + protected ThingDef preferracecache = null; + protected int preferracesexcountcache = 0; + protected Pawn preferracepawncache = null; + protected float avtsatcache = 0; + protected int recentsextickabscache = 0; + protected int mostsextickabscache = 0; + protected int bestsextickabscache = 0; + + public SexHistory GetFirstPartnerHistory + { + get + { + Update(); + return histories.TryGetValue(first); + } + } + public SexHistory GetMostPartnerHistory + { + get + { + Update(); + return histories.TryGetValue(mostpartnercache); + } + } + public xxx.rjwSextype MostSextype + { + get + { + Update(); + return mostsextypecache; + } + } + public xxx.rjwSextype MostSatisfiedSex + { + get + { + Update(); + return mostsatsextypecache; + } + } + public SexHistory GetRecentPartnersHistory => histories.TryGetValue(recentpartner); + public SexHistory GetBestSexPartnerHistory + { + get + { + Update(); + return histories.TryGetValue(bestpartnercache); + } + } + public float TotalSexHad + { + get + { + Update(); + return totalsexcache; + } + } + public int VirginsTaken => virginstaken; + public List PartnerList + { + get + { + List res = null; + Update(); + if (!histories.NullOrEmpty()) + { + res = histories.Values.ToList(); + } + return res; + } + } + public int PartnerCount + { + get + { + if (histories == null) histories = new Dictionary(); + return histories.Count; + } + } + public int IncestuousCount => incestuous; + public int RapedCount + { + get + { + Update(); + return totalrapedcache; + } + } + public int BeenRapedCount + { + get + { + Update(); + return totalbeenrapedcache; + } + } + public ThingDef PreferRace + { + get + { + Update(); + return preferracecache; + } + } + public int PreferRaceSexCount + { + get + { + Update(); + return preferracesexcountcache; + } + } + public int BestialityCount => bestiality; + public int CorpseFuckCount => corpsefuck; + public int InterspeciesCount => interspecies; + public float AVGSat + { + get + { + Update(); + if (totalsexcache == 0) return 0; + return sextypesat.Sum() / totalsexcache; + } + } + public int RecentSexElapsedTicks => GenTicks.TicksAbs - recentsextickabscache; + public string RecentSexDays + { + get + { + if (recentsextickabscache != 0) return GenDate.ToStringTicksToDays(RecentSexElapsedTicks) + " " + Keyed.RS_Ago; + return ""; + } + } + public int FirstSexElapsedTicks => GenTicks.TicksAbs - firstsextickabs; + public string FirstSexDays + { + get + { + if (firstsextickabs != 0) return GenDate.ToStringTicksToDays(FirstSexElapsedTicks) + " " + Keyed.RS_Ago; + return ""; + } + } + public int MostSexElapsedTicks => GenTicks.TicksAbs - mostsextickabscache; + public string MostSexDays + { + get + { + if (mostsextickabscache != 0) return GenDate.ToStringTicksToDays(MostSexElapsedTicks) + " " + Keyed.RS_Ago; + return ""; + } + } + public int BestSexElapsedTicks => GenTicks.TicksAbs - bestsextickabscache; + public string BestSexDays + { + get + { + if (bestsextickabscache != 0) return GenDate.ToStringTicksToDays(BestSexElapsedTicks) + " " + Keyed.RS_Ago; + return ""; + } + } + + public Texture GetPreferRaceIcon(Vector2 size) + { + Update(); + if (preferracepawncache != null) return PortraitsCache.Get(preferracepawncache, size, Rot4.South, default, 1, true, true, false, false); + else return HistoryUtility.UnknownPawn; + } + + public float GetBestSextype(out xxx.rjwSextype sextype) + { + Update(); + sextype = bestsextypecache; + return bestsextypesatcache; + } + + public float GetRecentSextype(out xxx.rjwSextype sextype) + { + Update(); + sextype = recentsex; + return recentsat; + } + + public string SextypeRecentDays(int sextype) + { + int index = sextype; + if (sextyperecenttickabs[index] != 0) return GenDate.ToStringTicksToDays(GenTicks.TicksAbs - sextyperecenttickabs[index]) + " " + Keyed.RS_Ago; + return Keyed.Unknown; + } + + public float GetAVGSat(int index) + { + float res = sextypesat[index] / sextypecount[index]; + return float.IsNaN(res) ? 0f : res; + } + + public int GetSexCount(int index) + { + return sextypecount[index]; + } + + public override void PostExposeData() + { + List sextypecountsave; + List sextypesatsave; + List sextyperecenttickabssave; + + if (Scribe.mode == LoadSaveMode.Saving) + { + sextypecountsave = sextypecount.ToList(); + sextypesatsave = sextypesat.ToList(); + sextyperecenttickabssave = sextyperecenttickabs.ToList(); + } + else + { + sextypecountsave = new List(); + sextypesatsave = new List(); + sextyperecenttickabssave = new List(); + } + + Scribe_Collections.Look(ref histories, "histories", LookMode.Value, LookMode.Deep); + Scribe_Values.Look(ref first, "first", "", true); + Scribe_Values.Look(ref recentsex, "recentsex", recentsex, true); + Scribe_Values.Look(ref recentsat, "recentsat", recentsat, true); + Scribe_Values.Look(ref recentpartner, "recentpartner", recentpartner, true); + Scribe_Values.Look(ref virginstaken, "virginstaken", virginstaken, true); + Scribe_Values.Look(ref incestuous, "incestous", incestuous, true); + Scribe_Values.Look(ref bestiality, "bestiality", bestiality, true); + Scribe_Values.Look(ref corpsefuck, "corpsefuck", corpsefuck, true); + Scribe_Values.Look(ref interspecies, "interspecies", interspecies, true); + Scribe_Values.Look(ref firstsextickabs, "firstsextickabs", firstsextickabs, true); + Scribe_Collections.Look(ref sextypecountsave, "sextypecountsave", LookMode.Value); + Scribe_Collections.Look(ref sextypesatsave, "sextypesatsave", LookMode.Value); + Scribe_Collections.Look(ref sextyperecenttickabssave, "sextyperecenttickabssave", LookMode.Value); + + if (histories == null) histories = new Dictionary(); + + if (Scribe.mode == LoadSaveMode.LoadingVars) + { + sextypecount = sextypecountsave?.ToArray() ?? new int[ARRLEN]; + sextypesat = sextypesatsave?.ToArray() ?? new float[ARRLEN]; + sextyperecenttickabs = sextyperecenttickabssave?.ToArray() ?? new int[ARRLEN]; + + foreach (KeyValuePair element in histories) + { + element.Value.parent = this; + element.Value.partnerID = element.Key; + } + } + base.PostExposeData(); + } + + public void RecordHistory(Pawn partner, SexProps props) + { + Pawn pawn = parent as Pawn; + TryAddHistory(partner); + RecordFirst(partner, props); + recentpartner = partner.ThingID; + SexHistory history = histories[partner.ThingID]; + history?.RecordSex(props); + recentsex = props.sexType; + sextypecount[(int)props.sexType]++; + sextyperecenttickabs[(int)props.sexType] = GenTicks.TicksAbs; + if (partner.IsIncest(pawn)) incestuous++; + if (partner.Dead) corpsefuck++; + if (props.IsBestiality()) bestiality++; + else if (pawn.def != partner.def) interspecies++; + dirty = true; + } + + public void RecordSatisfactionHistory(Pawn partner, SexProps props, float satisfaction) + { + TryAddHistory(partner); + RecordFirst(partner, props); + SexHistory history = histories[partner.ThingID]; + history?.RecordSatisfaction(props, satisfaction); + recentsat = satisfaction; + sextypesat[(int)props.sexType] += satisfaction; + dirty = true; + } + + protected bool TryAddHistory(Pawn partner) + { + if (!histories.ContainsKey(partner.ThingID)) + { + SexHistory newhistory = new SexHistory(partner, partner.IsIncest(parent as Pawn)); + histories.Add(partner.ThingID, newhistory); + Pawn pawn = parent as Pawn; + if (pawn != null) + { + pawn.records.AddTo(VariousDefOf.SexPartnerCount, 1); + } + return true; + } + return false; + } + + public void RecordFirst(Pawn partner, SexProps props) + { + if (VirginCheck() && props.sexType == xxx.rjwSextype.Vaginal) + { + TryAddHistory(partner); + first = partner.ThingID; + SexPartnerHistory history = partner.GetPartnerHistory(); + firstsextickabs = GenTicks.TicksAbs; + if (history != null) + { + history.TakeSomeonesVirgin(parent as Pawn); + } + } + } + + public void TakeSomeonesVirgin(Pawn partner) + { + TryAddHistory(partner); + SexHistory history = histories[partner.ThingID]; + if (history != null) history.TookVirgin(); + virginstaken++; + } + + protected void Update() + { + if (dirty) + { + UpdateStatistics(); + UpdateBestSex(); + dirty = false; + } + } + + protected void UpdateStatistics() + { + int max = 0; + float maxsat = 0; + float maxf = 0; + int maxindex = 0; + string mostID = Keyed.Unknown; + string bestID = Keyed.Unknown; + + totalsexcache = 0; + totalrapedcache = 0; + totalbeenrapedcache = 0; + Dictionary racetotalsat = new Dictionary(); + List allpartners = new List(); + + foreach (KeyValuePair element in histories) + { + SexHistory h = element.Value; + + //find most sex partner + if (max < h.TotalSexCount) + { + max = h.TotalSexCount; + mostID = element.Key; + } + if (maxsat < h.BestSatisfaction) + { + maxsat = h.BestSatisfaction; + bestID = element.Key; + } + + if (h.Partner != null) + { + Pawn partner = h.Partner; + allpartners.Add(partner); + if (racetotalsat.ContainsKey(h.Race)) + { + racetotalsat[h.Race] += h.TotalSexCount - h.RapedMe; + } + else + { + racetotalsat.Add(h.Race, h.TotalSexCount - h.RapedMe); + } + } + + totalsexcache += h.TotalSexCount; + totalrapedcache += h.Raped; + totalbeenrapedcache += h.RapedMe; + } + + if (!racetotalsat.NullOrEmpty()) + { + KeyValuePair prefer = racetotalsat.MaxBy(x => x.Value); + preferracecache = prefer.Key; + preferracesexcountcache = prefer.Value; + preferracepawncache = allpartners.FirstOrDefault(x => x.def == preferracecache); + } + + max = 0; + for (int i = 0; i < sextypecount.Length; i++) + { + float avgsat = sextypesat[i] / sextypecount[i]; + if (maxf < avgsat) + { + maxf = avgsat; + maxindex = i; + } + } + + mostsatsextypecache = (xxx.rjwSextype)maxindex; + mostsextypecache = (xxx.rjwSextype)sextypecount.FirstIndexOf(x => x == sextypecount.Max()); + mostpartnercache = mostID; + bestpartnercache = bestID; + + recentsextickabscache = histories.TryGetValue(recentpartner)?.RecentSexTickAbs ?? 0; + mostsextickabscache = histories.TryGetValue(mostpartnercache)?.RecentSexTickAbs ?? 0; + bestsextickabscache = histories.TryGetValue(bestpartnercache)?.BestSexTickAbs ?? 0; + + racetotalsat.Clear(); + allpartners.Clear(); + } + + protected void UpdateBestSex() + { + int bestindex = 0; + float bestsat = 0; + float avgsat; + for (int i = 0; i < sextypecount.Length; i++) + { + avgsat = sextypesat[i] / sextypecount[i]; + if (bestsat < avgsat) + { + bestindex = i; + bestsat = avgsat; + } + } + bestsextypecache = (xxx.rjwSextype)bestindex; + bestsextypesatcache = bestsat; + } + + protected bool VirginCheck() + { + if (histories.TryGetValue(first) != null) return false; + + Pawn pawn = parent as Pawn; + return pawn?.IsVirgin() == true; + } + } +}