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 readonly GUIStyleState fontstylestate = new GUIStyleState() { textColor = Color.white }; private static readonly GUIStyleState boxstylestate = GUI.skin.textArea.normal; private static readonly GUIStyleState buttonstylestate = GUI.skin.button.normal; private static readonly GUIStyle fontstylecenter = new GUIStyle() { alignment = TextAnchor.MiddleCenter, normal = fontstylestate }; private static readonly GUIStyle fontstyleright = new GUIStyle() { alignment = TextAnchor.MiddleRight, normal = fontstylestate }; private static readonly GUIStyle fontstyleleft = new GUIStyle() { alignment = TextAnchor.MiddleLeft, normal = fontstylestate }; private static readonly GUIStyle boxstyle = new GUIStyle(GUI.skin.textArea) { hover = boxstylestate, onHover = boxstylestate, onNormal = boxstylestate }; private static readonly GUIStyle buttonstyle = new GUIStyle(GUI.skin.button) { hover = buttonstylestate, onHover = buttonstylestate, onNormal = buttonstylestate }; private static Vector2 LastWindowPosition { get; set; } private Vector2 scroll; 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 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.parent as Pawn); //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 = !settings.SelectionLocked; } } 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.CapitalizeFirst() + ": {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.CapitalizeFirst() + ": {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.CapitalizeFirst() + ": {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.CapitalizeFirst() + ": {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.CapitalizeFirst()}: {pawn.GetSexStat():P2}", HistoryUtility.PassionBG[(int)(skill?.passion ?? 0)]); 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); } } } }