RJW-Sexperience/Source/RJWSexperience/SexHistory/SexHistoryComp.cs

459 lines
12 KiB
C#
Raw Normal View History

using rjw;
2022-03-07 09:33:03 +00:00
using RJWSexperience.ExtensionMethods;
using System.Collections.Generic;
using System.Linq;
using Verse;
2022-06-13 05:51:09 +00:00
namespace RJWSexperience.SexHistory
2022-03-07 09:33:03 +00:00
{
public class SexHistoryComp : ThingComp
2022-03-07 09:33:03 +00:00
{
public const int ARRLEN = 20;
2022-03-26 18:11:59 +00:00
protected Dictionary<string, SexPartnerHistoryRecord> histories = new Dictionary<string, SexPartnerHistoryRecord>();
2022-03-07 09:33:03 +00:00
protected string first = "";
protected bool dirty = true;
2022-05-14 13:54:10 +00:00
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;
2022-03-07 09:33:03 +00:00
protected int incestuous = 0;
protected int bestiality = 0;
protected int corpsefuck = 0;
protected int interspecies = 0;
2022-05-14 13:54:10 +00:00
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 int recentSexTickAbsCache = 0;
protected int mostSexTickAbsCache = 0;
protected int bestSexTickAbsCache = 0;
2022-03-07 09:33:03 +00:00
2022-05-10 06:47:51 +00:00
public Gizmo Gizmo { get; private set; }
2022-05-06 15:54:49 +00:00
2022-05-14 13:54:10 +00:00
public SexPartnerHistoryRecord GetFirstPartnerHistory => histories.TryGetValue(first);
2022-03-26 18:11:59 +00:00
public SexPartnerHistoryRecord GetMostPartnerHistory
2022-03-07 09:33:03 +00:00
{
get
{
Update();
2022-05-14 13:54:10 +00:00
return histories.TryGetValue(mostPartnerCache);
2022-03-07 09:33:03 +00:00
}
}
public xxx.rjwSextype MostSextype
{
get
{
Update();
2022-05-14 13:54:10 +00:00
return mostSextypeCache;
2022-03-07 09:33:03 +00:00
}
}
public xxx.rjwSextype MostSatisfiedSex
{
get
{
Update();
2022-05-14 13:54:10 +00:00
return mostSatSextypeCache;
2022-03-07 09:33:03 +00:00
}
}
2022-05-14 13:54:10 +00:00
public SexPartnerHistoryRecord GetRecentPartnersHistory => histories.TryGetValue(recentPartner);
2022-03-26 18:11:59 +00:00
public SexPartnerHistoryRecord GetBestSexPartnerHistory
2022-03-07 09:33:03 +00:00
{
get
{
Update();
2022-05-14 13:54:10 +00:00
return histories.TryGetValue(bestPartnerCache);
2022-03-07 09:33:03 +00:00
}
}
public float TotalSexHad
{
get
{
Update();
2022-05-14 13:54:10 +00:00
return totalSexCache;
2022-03-07 09:33:03 +00:00
}
}
2022-05-14 13:54:10 +00:00
public int VirginsTaken => virginsTaken;
2022-03-26 18:11:59 +00:00
public List<SexPartnerHistoryRecord> PartnerList
2022-03-07 09:33:03 +00:00
{
get
{
2022-03-26 18:11:59 +00:00
List<SexPartnerHistoryRecord> res = null;
2022-03-07 09:33:03 +00:00
Update();
if (!histories.NullOrEmpty())
{
res = histories.Values.ToList();
}
return res;
}
}
public int PartnerCount
{
get
{
2022-03-26 18:11:59 +00:00
if (histories == null) histories = new Dictionary<string, SexPartnerHistoryRecord>();
2022-03-07 09:33:03 +00:00
return histories.Count;
}
}
public int IncestuousCount => incestuous;
public int RapedCount
{
get
{
Update();
2022-05-14 13:54:10 +00:00
return totalRapedCache;
2022-03-07 09:33:03 +00:00
}
}
public int BeenRapedCount
{
get
{
Update();
2022-05-14 13:54:10 +00:00
return totalBeenRapedCache;
2022-03-07 09:33:03 +00:00
}
}
public ThingDef PreferRace
{
get
{
Update();
2022-05-14 13:54:10 +00:00
return preferRaceCache;
2022-03-07 09:33:03 +00:00
}
}
public int PreferRaceSexCount
{
get
{
Update();
2022-05-14 13:54:10 +00:00
return preferRaceSexCountCache;
2022-03-07 09:33:03 +00:00
}
}
public int BestialityCount => bestiality;
public int CorpseFuckCount => corpsefuck;
public int InterspeciesCount => interspecies;
public float AVGSat
{
get
{
Update();
2022-05-14 13:54:10 +00:00
if (totalSexCache == 0) return 0;
return sextypeSat.Sum() / totalSexCache;
2022-03-07 09:33:03 +00:00
}
}
2022-05-14 13:54:10 +00:00
public int RecentSexTickAbs => recentSexTickAbsCache;
public int FirstSexTickAbs => firstSexTickAbs;
public int MostSexTickAbs => mostSexTickAbsCache;
public int BestSexTickAbs => bestSexTickAbsCache;
public Pawn PreferRacePawn
2022-03-07 09:33:03 +00:00
{
get
{
2022-05-14 13:54:10 +00:00
Update();
return preferRacePawnCache;
2022-03-07 09:33:03 +00:00
}
}
public float GetBestSextype(out xxx.rjwSextype sextype)
{
Update();
2022-05-14 13:54:10 +00:00
sextype = bestSextypeCache;
return bestSextypeSatCache;
2022-03-07 09:33:03 +00:00
}
public float GetRecentSextype(out xxx.rjwSextype sextype)
{
Update();
2022-05-14 13:54:10 +00:00
sextype = recentSex;
return recentSat;
2022-03-07 09:33:03 +00:00
}
2022-05-14 13:54:10 +00:00
public int GetSextypeRecentTickAbs(int sextype) => sextypeRecentTickAbs[sextype];
2022-03-07 09:33:03 +00:00
public float GetAVGSat(int index)
{
2022-05-14 13:54:10 +00:00
float res = sextypeSat[index] / sextypeCount[index];
2022-03-07 09:33:03 +00:00
return float.IsNaN(res) ? 0f : res;
}
2022-05-14 13:54:10 +00:00
public int GetSexCount(int sextype) => sextypeCount[sextype];
2022-03-07 09:33:03 +00:00
public override void PostExposeData()
{
List<int> sextypecountsave;
List<float> sextypesatsave;
List<int> sextyperecenttickabssave;
if (Scribe.mode == LoadSaveMode.Saving)
{
2022-05-14 13:54:10 +00:00
sextypecountsave = sextypeCount.ToList();
sextypesatsave = sextypeSat.ToList();
sextyperecenttickabssave = sextypeRecentTickAbs.ToList();
2022-03-07 09:33:03 +00:00
}
else
{
sextypecountsave = new List<int>();
sextypesatsave = new List<float>();
sextyperecenttickabssave = new List<int>();
}
Scribe_Collections.Look(ref histories, "histories", LookMode.Value, LookMode.Deep);
2022-05-06 16:17:45 +00:00
Scribe_Values.Look(ref first, "first", string.Empty);
2022-05-14 13:54:10 +00:00
Scribe_Values.Look(ref recentSex, "recentsex", xxx.rjwSextype.None);
Scribe_Values.Look(ref recentSat, "recentsat", 0);
Scribe_Values.Look(ref recentPartner, "recentpartner", string.Empty);
Scribe_Values.Look(ref virginsTaken, "virginstaken", 0);
2022-05-06 16:17:45 +00:00
Scribe_Values.Look(ref incestuous, "incestous", 0);
Scribe_Values.Look(ref bestiality, "bestiality", 0);
Scribe_Values.Look(ref corpsefuck, "corpsefuck", 0);
Scribe_Values.Look(ref interspecies, "interspecies", 0);
2022-05-14 13:54:10 +00:00
Scribe_Values.Look(ref firstSexTickAbs, "firstsextickabs", 0);
2022-03-07 09:33:03 +00:00
Scribe_Collections.Look(ref sextypecountsave, "sextypecountsave", LookMode.Value);
Scribe_Collections.Look(ref sextypesatsave, "sextypesatsave", LookMode.Value);
Scribe_Collections.Look(ref sextyperecenttickabssave, "sextyperecenttickabssave", LookMode.Value);
2022-05-06 16:17:45 +00:00
if (histories == null)
histories = new Dictionary<string, SexPartnerHistoryRecord>();
2022-03-07 09:33:03 +00:00
if (Scribe.mode == LoadSaveMode.LoadingVars)
{
2022-05-14 13:54:10 +00:00
sextypeCount = sextypecountsave?.ToArray() ?? new int[ARRLEN];
sextypeSat = sextypesatsave?.ToArray() ?? new float[ARRLEN];
sextypeRecentTickAbs = sextyperecenttickabssave?.ToArray() ?? new int[ARRLEN];
2022-03-07 09:33:03 +00:00
2022-03-26 18:11:59 +00:00
foreach (KeyValuePair<string, SexPartnerHistoryRecord> element in histories)
2022-03-07 09:33:03 +00:00
{
2022-04-03 17:20:14 +00:00
element.Value.PartnerID = element.Key;
2022-03-07 09:33:03 +00:00
}
}
base.PostExposeData();
}
2022-05-14 13:54:10 +00:00
public void RecordSex(Pawn partner, SexProps props)
2022-03-07 09:33:03 +00:00
{
Pawn pawn = parent as Pawn;
RecordFirst(partner, props);
2022-05-14 13:54:10 +00:00
GetPartnerRecord(partner)?.RecordSex(props);
recentPartner = partner.ThingID;
recentSex = props.sexType;
sextypeCount[(int)props.sexType]++;
sextypeRecentTickAbs[(int)props.sexType] = GenTicks.TicksAbs;
2022-03-07 09:33:03 +00:00
if (partner.IsIncest(pawn)) incestuous++;
if (partner.Dead) corpsefuck++;
if (props.IsBestiality()) bestiality++;
else if (pawn.def != partner.def) interspecies++;
dirty = true;
}
2022-05-14 13:54:10 +00:00
public void RecordSatisfaction(Pawn partner, SexProps props, float satisfaction)
2022-03-07 09:33:03 +00:00
{
RecordFirst(partner, props);
2022-05-14 13:54:10 +00:00
GetPartnerRecord(partner)?.RecordSatisfaction(props, satisfaction);
recentSat = satisfaction;
sextypeSat[(int)props.sexType] += satisfaction;
2022-03-07 09:33:03 +00:00
dirty = true;
}
2022-05-14 13:54:10 +00:00
public void RecordFirst(Pawn partner, SexProps props)
{
if (VirginCheck() && props.sexType == xxx.rjwSextype.Vaginal)
{
first = partner.ThingID;
SexHistoryComp history = partner.TryGetComp<SexHistoryComp>();
2022-05-14 13:54:10 +00:00
firstSexTickAbs = GenTicks.TicksAbs;
history?.TakeSomeonesVirgin(parent as Pawn);
}
}
2022-03-26 18:11:59 +00:00
protected SexPartnerHistoryRecord GetPartnerRecord(Pawn partner)
2022-03-07 09:33:03 +00:00
{
2022-03-26 18:11:59 +00:00
string partnerId = partner.ThingID;
if (histories.TryGetValue(partnerId, out SexPartnerHistoryRecord record))
2022-03-07 09:33:03 +00:00
{
2022-03-26 18:11:59 +00:00
return record;
}
SexPartnerHistoryRecord newRecord = new SexPartnerHistoryRecord(partner, partner.IsIncest(parent as Pawn));
histories.Add(partnerId, newRecord);
if (parent is Pawn pawn)
{
pawn.records.Increment(VariousDefOf.SexPartnerCount);
2022-03-07 09:33:03 +00:00
}
2022-03-26 18:11:59 +00:00
return newRecord;
2022-03-07 09:33:03 +00:00
}
public void TakeSomeonesVirgin(Pawn partner)
{
2022-05-14 13:54:10 +00:00
GetPartnerRecord(partner)?.TookVirgin();
virginsTaken++;
2022-03-07 09:33:03 +00:00
}
2022-05-14 13:54:10 +00:00
#region Cache update
2022-03-07 09:33:03 +00:00
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;
2022-05-14 13:54:10 +00:00
totalSexCache = 0;
totalRapedCache = 0;
totalBeenRapedCache = 0;
2022-03-07 09:33:03 +00:00
Dictionary<ThingDef, int> racetotalsat = new Dictionary<ThingDef, int>();
List<Pawn> allpartners = new List<Pawn>();
2022-03-26 18:11:59 +00:00
foreach (KeyValuePair<string, SexPartnerHistoryRecord> element in histories)
2022-03-07 09:33:03 +00:00
{
2022-03-26 18:11:59 +00:00
SexPartnerHistoryRecord h = element.Value;
2022-03-07 09:33:03 +00:00
//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);
}
}
2022-05-14 13:54:10 +00:00
totalSexCache += h.TotalSexCount;
totalRapedCache += h.Raped;
totalBeenRapedCache += h.RapedMe;
2022-03-07 09:33:03 +00:00
}
if (!racetotalsat.NullOrEmpty())
{
KeyValuePair<ThingDef, int> prefer = racetotalsat.MaxBy(x => x.Value);
2022-05-14 13:54:10 +00:00
preferRaceCache = prefer.Key;
preferRaceSexCountCache = prefer.Value;
preferRacePawnCache = allpartners.Find(x => x.def == preferRaceCache);
2022-03-07 09:33:03 +00:00
}
2022-05-14 13:54:10 +00:00
for (int i = 0; i < sextypeCount.Length; i++)
2022-03-07 09:33:03 +00:00
{
2022-05-14 13:54:10 +00:00
float avgsat = sextypeSat[i] / sextypeCount[i];
2022-03-07 09:33:03 +00:00
if (maxf < avgsat)
{
maxf = avgsat;
maxindex = i;
}
}
2022-05-14 13:54:10 +00:00
mostSatSextypeCache = (xxx.rjwSextype)maxindex;
mostSextypeCache = (xxx.rjwSextype)sextypeCount.FirstIndexOf(x => x == sextypeCount.Max());
mostPartnerCache = mostID;
bestPartnerCache = bestID;
2022-03-07 09:33:03 +00:00
2022-05-14 13:54:10 +00:00
recentSexTickAbsCache = histories.TryGetValue(recentPartner)?.RecentSexTickAbs ?? 0;
mostSexTickAbsCache = histories.TryGetValue(mostPartnerCache)?.RecentSexTickAbs ?? 0;
bestSexTickAbsCache = histories.TryGetValue(bestPartnerCache)?.BestSexTickAbs ?? 0;
2022-03-07 09:33:03 +00:00
racetotalsat.Clear();
allpartners.Clear();
}
protected void UpdateBestSex()
{
int bestindex = 0;
float bestsat = 0;
float avgsat;
2022-05-14 13:54:10 +00:00
for (int i = 0; i < sextypeCount.Length; i++)
2022-03-07 09:33:03 +00:00
{
2022-05-14 13:54:10 +00:00
avgsat = sextypeSat[i] / sextypeCount[i];
2022-03-07 09:33:03 +00:00
if (bestsat < avgsat)
{
bestindex = i;
bestsat = avgsat;
}
}
2022-05-14 13:54:10 +00:00
bestSextypeCache = (xxx.rjwSextype)bestindex;
bestSextypeSatCache = bestsat;
2022-03-07 09:33:03 +00:00
}
2022-05-14 13:54:10 +00:00
#endregion Cache update
2022-03-07 09:33:03 +00:00
protected bool VirginCheck()
{
if (histories.TryGetValue(first) != null) return false;
Pawn pawn = parent as Pawn;
return pawn?.IsVirgin() == true;
}
2022-05-06 15:54:49 +00:00
public override IEnumerable<Gizmo> CompGetGizmosExtra()
{
if (SexperienceMod.Settings.HideGizmoWhenDrafted && (parent as Pawn)?.Drafted == true)
yield break;
if (Find.Selector.NumSelected > 1)
yield break;
if (SexperienceMod.Settings.HideGizmoWithRJW && !RJWSettings.show_RJW_designation_box)
yield break;
yield return Gizmo;
}
2022-05-06 15:54:49 +00:00
public override void Initialize(CompProperties props)
{
base.Initialize(props);
2022-05-10 06:47:51 +00:00
Gizmo = new Command_Action
2022-05-06 15:54:49 +00:00
{
defaultLabel = Keyed.RS_Sex_History,
icon = HistoryUtility.HistoryIcon,
defaultIconColor = HistoryUtility.HistoryColor,
hotKey = VariousDefOf.OpenSexStatistics,
action = delegate
{
UI.SexStatusWindow.ToggleWindow(parent as Pawn, this);
}
};
}
2022-03-07 09:33:03 +00:00
}
}