Ejemplo n.º 1
0
        protected override void OnEndH(MonoBehaviour proc, HFlag hFlag, bool vr)
        {
            InsideHScene = false;
            Destroy(proc.GetComponent <LactationController>());

            // Figure out if conception happened at end of h scene
            // bug Don't know which character is which
            if (hFlag.mode == HFlag.EMode.houshi3P || hFlag.mode == HFlag.EMode.sonyu3P)
            {
                return;
            }

            var heroine        = hFlag.lstHeroine.First(x => x != null);
            var isDangerousDay = HFlag.GetMenstruation(heroine.MenstruationDay) == HFlag.MenstruationType.危険日;

            if (!isDangerousDay)
            {
                return;
            }

            var cameInside     = PregnancyPlugin.ConceptionEnabled.Value && hFlag.count.sonyuInside > 0;
            var cameInsideAnal = PregnancyPlugin.AnalConceptionEnabled.Value && hFlag.count.sonyuAnalInside > 0;

            if (cameInside || cameInsideAnal)
            {
                //var c = heroine.chaCtrl.GetComponent<PregnancyCharaController>();
                var pd = heroine.GetPregnancyData();

                var fertility = Mathf.Max(PregnancyPlugin.FertilityOverride.Value, pd.Fertility);

                var winThreshold = Mathf.RoundToInt(fertility * 100);
                var childLottery = Random.Range(1, 100);

                var wonAChild = winThreshold >= childLottery;
                PregnancyPlugin.Logger.LogDebug($"OnEndH -> lottery: heroine={heroine.parameter.fullname} winThreshold={winThreshold} won={wonAChild}");
                if (wonAChild)
                {
                    StartPregnancyDelayed(heroine, true);
                }

                ApplyToAllDatas((chara, data) =>
                {
                    if (chara == heroine && !data.IsPregnant && !data.CanAskForAfterpill)
                    {
                        data.CanAskForAfterpill = true;
                        return(true);
                    }
                    return(false);
                });
            }
        }
        protected override void OnEndH(HSceneProc proc, bool freeH)
        {
            InsideHScene = false;
            Destroy(proc.GetComponent <LactationController>());

            // Figure out if conception happened at end of h scene
            // bug Don't know which character is which
            if (proc.flags.mode == HFlag.EMode.houshi3P || proc.flags.mode == HFlag.EMode.sonyu3P)
            {
                return;
            }

            var heroine        = proc.flags.lstHeroine.First(x => x != null);
            var isDangerousDay = HFlag.GetMenstruation(heroine.MenstruationDay) == HFlag.MenstruationType.危険日;

            if (!isDangerousDay)
            {
                return;
            }

            var cameInside     = PregnancyPlugin.ConceptionEnabled.Value && proc.flags.count.sonyuInside > 0;
            var cameInsideAnal = PregnancyPlugin.AnalConceptionEnabled.Value && proc.flags.count.sonyuAnalInside > 0;

            if (cameInside || cameInsideAnal)
            {
                var controller = heroine.chaCtrl.GetComponent <PregnancyCharaController>();
                if (controller == null)
                {
                    throw new ArgumentNullException(nameof(controller));
                }

                //Allow pregnancy if enabled, or overridden, and is not currently pregnant
                if (!controller.Data.GameplayEnabled || controller.Data.IsPregnant)
                {
                    return;
                }

                var fertility = Mathf.Max(PregnancyPlugin.FertilityOverride.Value, controller.Data.Fertility);

                var winThreshold = Mathf.RoundToInt(fertility * 100);
                var childLottery = Random.Range(1, 100);
                //Logger.Log(LogLevel.Debug, $"Preg - OnEndH calc pregnancy chance {childLottery} to {winThreshold}");
                var wonAChild = winThreshold >= childLottery;
                if (wonAChild)
                {
                    //Logger.Log(LogLevel.Debug, "Preg - child lottery won, pregnancy will start");
                    _startedPregnancies.Add(heroine);
                }
            }
        }
        // Figure out if conception happened at end of h scene
        protected override void OnEndH(HSceneProc proc, bool freeH)
        {
            // Don't know which girl player came inside
            if (proc.flags.mode == HFlag.EMode.houshi3P || proc.flags.mode == HFlag.EMode.sonyu3P)
            {
                return;
            }

            var heroine        = proc.flags.lstHeroine.First(x => x != null);
            var isDangerousDay = HFlag.GetMenstruation(heroine.MenstruationDay) == HFlag.MenstruationType.危険日;

            if (!isDangerousDay)
            {
                return;
            }

            var cameInside     = PregnancyPlugin.ConceptionEnabled.Value && proc.flags.count.sonyuInside > 0;
            var cameInsideAnal = PregnancyPlugin.AnalConceptionEnabled.Value && proc.flags.count.sonyuAnalInside > 0;

            if (cameInside || cameInsideAnal)
            {
                var controller = heroine.chaCtrl.GetComponent <PregnancyCharaController>();
                if (controller == null)
                {
                    throw new ArgumentNullException(nameof(controller));
                }

                if (!controller.GameplayEnabled || controller.IsDuringPregnancy())
                {
                    return;
                }

                var winThreshold = Mathf.RoundToInt(controller.Fertility * 100);
                var childLottery = Random.Range(1, 100);
                //Logger.Log(LogLevel.Debug, $"Preg - OnEndH calc pregnancy chance {childLottery} to {winThreshold}");
                var wonAChild = winThreshold >= childLottery;
                if (wonAChild)
                {
                    //Logger.Log(LogLevel.Debug, "Preg - child lottery won, pregnancy will start");
                    _startedPregnancies.Add(heroine);
                }
            }
        }
Ejemplo n.º 4
0
        private static void ApplyGirlAnger(object sender, EventArgs e)
        {
            if (!_forceInsertAnger.Value)
            {
                return;
            }

            var hflag = GameObject.FindObjectOfType <HFlag>();

            var heroine = hflag.GetLeadingHeroine();

            if (heroine == null)
            {
                return;
            }

            if (!hflag.isInsertOK[hflag.GetLeadingHeroineId()])
            {
                if (hflag.count.sonyuInside > 0)
                {
                    if (HFlag.GetMenstruation(heroine.MenstruationDay) == HFlag.MenstruationType.危険日)
                    {
                        // If it's dangerous always make her angry
                        heroine.anger   = Math.Min(100, heroine.anger + hflag.count.sonyuInside * 45);
                        heroine.isAnger = true;
                    }
                    else
                    {
                        heroine.anger = Math.Min(100, heroine.anger + hflag.count.sonyuInside * 25);
                    }
                }
                else if (hflag.count.sonyuOutside > 0)
                {
                    heroine.anger = Math.Max(0, heroine.anger - hflag.count.sonyuOutside * 10);
                }
            }

            if (heroine.anger >= 100)
            {
                heroine.isAnger = true;
            }
        }
            private static HeroineStatus GetHeroineStatus(SaveData.Heroine heroine)
            {
                // Check if she wants to tell
                if (heroine.intimacy >= 80 ||
                    heroine.hCount >= 5 ||
                    heroine.parameter.attribute.bitch && heroine.favor > 50 ||
                    (heroine.isGirlfriend || heroine.favor >= 90) && (!heroine.isVirgin || heroine.hCount >= 2 || heroine.intimacy >= 40))
                {
                    if (heroine.IsHeroinePregnant(!PregnancyPlugin.ShowPregnancyIconEarly.Value))
                    {
                        return(HeroineStatus.Pregnant);
                    }

                    return(HFlag.GetMenstruation(heroine.MenstruationDay) == HFlag.MenstruationType.安全日
                        ? HeroineStatus.Safe
                        : HeroineStatus.Risky);
                }

                return(HeroineStatus.Unknown);
            }
Ejemplo n.º 6
0
        [HarmonyWrapSafe] // Ignore crashes
        private static void OnFinishInside(HFlag __instance)
        {
            if (!IsEffectActive())
            {
                return;
            }

            var heroine    = __instance.GetLeadingHeroine();
            var controller = PregnancyPlugin.GetEffectController(heroine);

            if (controller.Data.GameplayEnabled && !controller.Data.IsPregnant && controller.Data.Fertility > 0.001f)
            {
                var isDangerousDay = HFlag.GetMenstruation(heroine.MenstruationDay) == HFlag.MenstruationType.危険日;
                if (UnityEngine.Random.RandomRangeInt(0, 100) < (isDangerousDay ? 95 : 30))
                {
                    PregnancyPlugin.Logger.LogInfo("Through the power of a pin hole, pregnancy");
                    PregnancyGameController.StartPregnancyDelayed(heroine, true);
                }
            }
        }
Ejemplo n.º 7
0
        private static void ApplyGirlAnger(HSprite __instance)
        {
            if (!KoikatuGameplayMod.ForceInsertAnger.Value)
            {
                return;
            }

            var heroine = Utilities.GetTargetHeroine(__instance);

            if (heroine == null)
            {
                return;
            }

            if (!__instance.flags.isInsertOK[Utilities.GetTargetHeroineId(__instance)])
            {
                if (__instance.flags.count.sonyuInside > 0)
                {
                    if (HFlag.GetMenstruation(heroine.MenstruationDay) == HFlag.MenstruationType.危険日)
                    {
                        // If it's dangerous always make her angry
                        heroine.anger   = Math.Min(100, heroine.anger + __instance.flags.count.sonyuInside * 45);
                        heroine.isAnger = true;
                    }
                    else
                    {
                        heroine.anger = Math.Min(100, heroine.anger + __instance.flags.count.sonyuInside * 25);
                    }
                }
                else if (__instance.flags.count.sonyuOutside > 0)
                {
                    heroine.anger = Math.Max(0, heroine.anger - __instance.flags.count.sonyuOutside * 10);
                }
            }

            if (heroine.anger >= 100)
            {
                heroine.isAnger = true;
            }
        }
Ejemplo n.º 8
0
            private void OnGUI()
            {
                if (_currentHeroine.Count == 0)
                {
                    return;
                }

                var pos         = new Vector2(Input.mousePosition.x, -(Input.mousePosition.y - Screen.height));
                var heroineRect = _currentHeroine.FirstOrDefault(x =>
                {
                    if (x.Value == null)
                    {
                        return(false);
                    }
                    return(GetOccupiedScreenRect(x).Contains(pos));
                });
                var chara = heroineRect.Key;

                if (chara == null)
                {
                    return;
                }

                var pregData = chara.GetPregnancyData();

                var status  = chara.GetCharaStatus(pregData);
                var heroine = chara as SaveData.Heroine;

                var windowHeight = status == HeroineStatus.Unknown ? 100 : status == HeroineStatus.Pregnant || status == HeroineStatus.OnLeave ? 180 : 370;
                var screenRect   = new Rect((int)pos.x + 30, (int)pos.y - windowHeight / 2, 180, windowHeight);

                IMGUIUtils.DrawSolidBox(screenRect);
                GUILayout.BeginArea(screenRect, GUI.skin.box);
                {
                    GUILayout.BeginVertical();
                    {
                        GUILayout.FlexibleSpace();

                        switch (status)
                        {
                        case HeroineStatus.Unknown:
                            GUILayout.Label("This character didn't tell you their risky day schedule yet.");
                            GUILayout.FlexibleSpace();
                            GUILayout.Label("Become closer to learn it!");
                            break;

                        case HeroineStatus.OnLeave:
                            GUILayout.Label("This character is on a maternal leave and will not appear until it is over.");
                            GUILayout.FlexibleSpace();
                            GUILayout.Label("Consider using a rubber next time!");
                            break;

                        case HeroineStatus.Pregnant:
                            GUILayout.Label($"This character is pregnant (on week {pregData.Week} / 40).");
                            GUILayout.FlexibleSpace();
                            if (pregData.GameplayEnabled)
                            {
                                GUILayout.Label(heroine != null ? "The character's body will slowly change, and at the end they will temporarily leave." : "The character's body will slowly change.");
                            }

                            GUILayout.FlexibleSpace();
                            var previousPregcount = Mathf.Max(0, pregData.PregnancyCount - 1);
                            GUILayout.Label($"This character was pregnant {previousPregcount} times before.");
                            break;

                        case HeroineStatus.Safe:
                        case HeroineStatus.Risky:
                            if (heroine == null)
                            {
                                break;
                            }

                            GUILayout.Label(status == HeroineStatus.Safe
                                    ? "This character is on a safe day, have fun!"
                                    : "This character is on a risky day, be careful!");
                            //GUILayout.Space(5);
                            GUILayout.FlexibleSpace();

                            var day = Singleton <Cycle> .Instance.nowWeek;

                            GUILayout.Label("Forecast for this week:");

                            switch (pregData.MenstruationSchedule)
                            {
                            case MenstruationSchedule.AlwaysSafe:
                                GUILayout.Label("It's always safe!");
                                break;

                            case MenstruationSchedule.AlwaysRisky:
                                GUILayout.Label("It's always risky!");
                                break;

                            default:
                                GUILayout.Label($"Today ({day}): {status}");

                                for (var dayOffset = 1; dayOffset < 7; dayOffset++)
                                {
                                    var adjustedDay  = (Cycle.Week)((int)(day + dayOffset) % Enum.GetValues(typeof(Cycle.Week)).Length);
                                    var adjustedSafe = HFlag.GetMenstruation((byte)((heroine.MenstruationDay + dayOffset) % HFlag.menstruations.Length)) == HFlag.MenstruationType.安全日;
                                    GUILayout.Label($"{adjustedDay}: {(adjustedSafe ? "Safe" : "Risky")}");
                                }
                                break;
                            }

                            var pregnancyCount = pregData.IsPregnant ? pregData.PregnancyCount - 1 : pregData.PregnancyCount;
                            if (pregnancyCount > 0)
                            {
                                GUILayout.FlexibleSpace();
                                GUILayout.Label($"This character was pregnant {pregnancyCount} times.");
                            }

                            if (pregData.WeeksSinceLastPregnancy > 0)
                            {
                                GUILayout.FlexibleSpace();
                                GUILayout.Label($"Last pregnancy was {pregData.WeeksSinceLastPregnancy} weeks ago.");
                            }
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }

                        GUILayout.FlexibleSpace();
                    }
                    GUILayout.EndVertical();
                }
                GUILayout.EndArea();
            }
            private void OnGUI()
            {
                if (_currentHeroine.Count == 0)
                {
                    return;
                }

                var pos     = new Vector2(Input.mousePosition.x, -(Input.mousePosition.y - Screen.height));
                var heroine = _currentHeroine.FirstOrDefault(x => x.Value.Contains(pos)).Key;

                if (heroine == null)
                {
                    return;
                }

                var status = GetHeroineStatus(heroine);

                var windowHeight = status == HeroineStatus.Unknown || status == HeroineStatus.Pregnant ? 110 : 270;
                var screenRect   = new Rect(pos.x + 30, pos.y - windowHeight / 2, 180, windowHeight);

                IMGUIUtils.DrawSolidBox(screenRect);
                GUILayout.BeginArea(screenRect, GUI.skin.box);
                {
                    GUILayout.BeginVertical();
                    {
                        GUILayout.FlexibleSpace();

                        switch (status)
                        {
                        case HeroineStatus.Unknown:
                            GUILayout.Label("This character didn't tell you their risky day schedule yet.\n\nBecome closer to learn it!");
                            break;

                        case HeroineStatus.Pregnant:
                            GUILayout.Label("This character is pregnant.\n\nOver time the character's belly will grow, and at the end they will leave school temporarily.");
                            break;

                        case HeroineStatus.Safe:
                        case HeroineStatus.Risky:
                            GUILayout.Label(status == HeroineStatus.Safe
                                    ? "This character is on a safe day, have fun!"
                                    : "This character is on a risky day, be careful!");
                            GUILayout.Space(5);

                            var day = Singleton <Cycle> .Instance.nowWeek;

                            GUILayout.Label("Forecast for this week:");
                            GUILayout.Label($"Today ({day}): {status}");

                            for (var dayOffset = 1; dayOffset < 7; dayOffset++)
                            {
                                var adjustedDay =
                                    (Cycle.Week)((int)(day + dayOffset) % Enum.GetValues(typeof(Cycle.Week)).Length);
                                var adjustedSafe =
                                    HFlag.GetMenstruation(
                                        (byte)((heroine.MenstruationDay + dayOffset) % HFlag.menstruations.Length)) ==
                                    HFlag.MenstruationType.安全日;
                                GUILayout.Label($"{adjustedDay}: {(adjustedSafe ? "Safe" : "Risky")}");
                            }
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }

                        GUILayout.FlexibleSpace();
                    }
                    GUILayout.EndVertical();
                }
                GUILayout.EndArea();
            }
        public static HeroineStatus GetCharaStatus(this SaveData.CharaData chara, PregnancyData pregData = null)
        {
            if (chara is SaveData.Heroine heroine)
            {
                if (pregData == null)
                {
                    pregData = heroine.GetPregnancyData();
                }

                // Check if she wants to tell
                if (heroine.intimacy >= 80 ||
                    heroine.hCount >= 5 ||
                    heroine.parameter.attribute.bitch && heroine.favor > 50 ||
                    (heroine.isGirlfriend || heroine.favor >= 90) &&
                    (!heroine.isVirgin || heroine.hCount >= 2 || heroine.intimacy >= 40))
                {
                    var pregnancyWeek = pregData.Week;
                    if (pregnancyWeek > 0)
                    {
                        if (pregnancyWeek >= PregnancyData.LeaveSchoolWeek)
                        {
                            return(HeroineStatus.OnLeave);
                        }
                        if (PregnancyPlugin.ShowPregnancyIconEarly.Value)
                        {
                            return(HeroineStatus.Pregnant);
                        }
                        // Different personalities notice at different times
                        if (_earlyDetectPersonalities.Contains(heroine.personality))
                        {
                            if (pregnancyWeek > 1)
                            {
                                return(HeroineStatus.Pregnant);
                            }
                        }
                        else if (_lateDetectPersonalities.Contains(heroine.personality))
                        {
                            if (pregnancyWeek > 11)
                            {
                                return(HeroineStatus.Pregnant);
                            }
                        }
                        else
                        {
                            if (pregnancyWeek > 5)
                            {
                                return(HeroineStatus.Pregnant);
                            }
                        }
                    }

                    return(HFlag.GetMenstruation(heroine.MenstruationDay) == HFlag.MenstruationType.安全日
                            ? HeroineStatus.Safe
                            : HeroineStatus.Risky);
                }
            }
            else if (chara is SaveData.Player player)
            {
                if (pregData == null)
                {
                    pregData = player.GetPregnancyData();
                }
                return(pregData.IsPregnant ? HeroineStatus.Pregnant : HeroineStatus.Safe);
            }
            return(HeroineStatus.Unknown);
        }
Ejemplo n.º 11
0
        private static void DrawHeroineCheats(SaveData.Heroine currentAdvGirl, CheatToolsWindow cheatToolsWindow)
        {
            GUILayout.BeginVertical();
            {
                GUILayout.Label("Selected girl name: " + currentAdvGirl.Name);

                GUILayout.BeginVertical();
                {
                    GUILayout.BeginHorizontal();
                    {
                        GUILayout.Label("Favor: " + currentAdvGirl.favor, GUILayout.Width(60));
                        currentAdvGirl.favor = (int)GUILayout.HorizontalSlider(currentAdvGirl.favor, 0, 100);
                    }
                    GUILayout.EndHorizontal();
                    GUILayout.BeginHorizontal();
                    {
                        GUILayout.Label("Lewd: " + currentAdvGirl.lewdness, GUILayout.Width(60));
                        currentAdvGirl.lewdness = (int)GUILayout.HorizontalSlider(currentAdvGirl.lewdness, 0, 100);
                    }
                    GUILayout.EndHorizontal();
                    GUILayout.BeginHorizontal();
                    {
                        GUILayout.Label("Anger: " + currentAdvGirl.anger, GUILayout.Width(60));
                        currentAdvGirl.anger = (int)GUILayout.HorizontalSlider(currentAdvGirl.anger, 0, 100);
                    }
                    GUILayout.EndHorizontal();
                    GUILayout.BeginHorizontal();
                    {
                        GUILayout.Label("Intimacy: " + currentAdvGirl.intimacy, GUILayout.Width(60));
                        currentAdvGirl.intimacy = (int)GUILayout.HorizontalSlider(currentAdvGirl.intimacy, 0, 100);
                    }
                    GUILayout.EndHorizontal();
                }
                GUILayout.EndVertical();

                GUILayout.Space(4);

                GUILayout.Label("Sex experience: " + GetHExpText(currentAdvGirl));
                GUILayout.Label("Set to: (changes multiple stats)");
                GUILayout.BeginHorizontal();
                {
                    if (GUILayout.Button("Virgin"))
                    {
                        MakeVirgin(currentAdvGirl);
                    }
                    if (GUILayout.Button("Inexp"))
                    {
                        MakeInexperienced(currentAdvGirl);
                    }
                    if (GUILayout.Button("Exp"))
                    {
                        MakeExperienced(currentAdvGirl);
                    }
                    if (GUILayout.Button("Horny"))
                    {
                        MakeHorny(currentAdvGirl);
                    }
                }
                GUILayout.EndHorizontal();

                GUILayout.Space(4);

                GUILayout.Label("Set all touch experience");
                GUILayout.BeginHorizontal();
                {
                    if (GUILayout.Button("0%"))
                    {
                        SetGirlHExp(currentAdvGirl, 0f);
                    }
                    if (GUILayout.Button("50%"))
                    {
                        SetGirlHExp(currentAdvGirl, 50f);
                    }
                    if (GUILayout.Button("100%"))
                    {
                        SetGirlHExp(currentAdvGirl, 100f);
                    }
                }
                GUILayout.EndHorizontal();

                GUILayout.Space(8);

                if (GUILayout.Button("Reset conversation time"))
                {
                    currentAdvGirl.talkTime = currentAdvGirl.talkTimeMax;
                }

                var actCtrl = _gameMgr?.actScene?.actCtrl;
                if (actCtrl != null)
                {
                    var sortedDesires = Enum.GetValues(typeof(DesireEng)).Cast <DesireEng>()
                                        .Select(i => new { id = i, value = actCtrl.GetDesire((int)i, currentAdvGirl) })
                                        .Where(x => x.value > 5)
                                        .OrderByDescending(x => x.value)
                                        .Take(8);

                    var any = false;
                    foreach (var desire in sortedDesires)
                    {
                        if (!any)
                        {
                            GUILayout.Label("Desires (and their strengths):\n");
                            any = true;
                        }
                        GUILayout.BeginHorizontal();
                        {
                            GUILayout.Label((int)desire.id + " " + desire.id);
                            GUILayout.FlexibleSpace();
                            GUILayout.Label(desire.value + "%");
                            if (GUILayout.Button("X", GUILayout.ExpandWidth(false)))
                            {
                                actCtrl.SetDesire((int)desire.id, currentAdvGirl, 0);
                            }
                        }
                        GUILayout.EndHorizontal();
                    }
                    if (!any)
                    {
                        GUILayout.Label("Has no desires");
                    }

                    if (GUILayout.Button("Clear all desires"))
                    {
                        for (int i = 0; i < 31; i++)
                        {
                            actCtrl.SetDesire(i, currentAdvGirl, 0);
                        }
                    }

                    GUILayout.BeginHorizontal();
                    {
                        GUILayout.Label("Set desire ", GUILayout.ExpandWidth(false));
                        _setdesireId = GUILayout.TextField(_setdesireId ?? "");
                        GUILayout.Label(" to value ", GUILayout.ExpandWidth(false));
                        _setdesireValue = GUILayout.TextField(_setdesireValue ?? "");
                        if (GUILayout.Button("OK", GUILayout.ExpandWidth(false)))
                        {
                            try
                            {
                                actCtrl.SetDesire((int)Enum.Parse(typeof(DesireEng), _setdesireId), currentAdvGirl, int.Parse(_setdesireValue));
                            }
                            catch (Exception e)
                            {
                                CheatToolsPlugin.Logger.LogMessage("Invalid desire ID (0-30) or value (0-100) - " + e.Message);
                            }
                        }
                    }
                    GUILayout.EndHorizontal();

                    var wantsMast = actCtrl.GetDesire(4, currentAdvGirl) > 80;
                    if (!wantsMast)
                    {
                        if (GUILayout.Button("Make desire to m********e"))
                        {
                            actCtrl.SetDesire(4, currentAdvGirl, 100);
                        }
                    }

                    var wantsLes = actCtrl.GetDesire(26, currentAdvGirl) > 80;
                    if (!wantsLes)
                    {
                        if (GUILayout.Button("Make desire to lesbian"))
                        {
                            actCtrl.SetDesire(26, currentAdvGirl, 100);
                            actCtrl.SetDesire(27, currentAdvGirl, 100);
                        }
                    }
                }

                GUILayout.Space(8);

                // 危険日 is risky, 安全日 is safe. Only change when user clicks to avoid messing with the value unnecessarily
                GUI.changed = false;
                var isDangerousDay = GUILayout.Toggle(HFlag.GetMenstruation(currentAdvGirl.MenstruationDay) == HFlag.MenstruationType.危険日, "Is on a risky day");
                if (GUI.changed)
                {
                    HFlag.SetMenstruation(currentAdvGirl, isDangerousDay ? HFlag.MenstruationType.危険日 : HFlag.MenstruationType.安全日);
                }

                currentAdvGirl.isVirgin     = GUILayout.Toggle(currentAdvGirl.isVirgin, "isVirgin");
                currentAdvGirl.isAnalVirgin = GUILayout.Toggle(currentAdvGirl.isAnalVirgin, "isAnalVirgin");

                GUILayout.BeginHorizontal();
                {
                    GUILayout.Label("Sex count: ", GUILayout.ExpandWidth(false));
                    GUI.changed = false;
                    var newCount = GUILayout.TextField(currentAdvGirl.hCount.ToString(), GUILayout.ExpandWidth(true));
                    if (GUI.changed && int.TryParse(newCount, out var newCountInt))
                    {
                        currentAdvGirl.hCount = Mathf.Max(newCountInt, 0);
                    }
                }
                GUILayout.EndHorizontal();

                currentAdvGirl.isAnger = GUILayout.Toggle(currentAdvGirl.isAnger, "Is angry");
                currentAdvGirl.isDate  = GUILayout.Toggle(currentAdvGirl.isDate, "Date promised");
                //currentAdvGirl.isFirstGirlfriend = GUILayout.Toggle(currentAdvGirl.isFirstGirlfriend, "isFirstGirlfriend");

                GUI.changed = false;
                var newVal = GUILayout.Toggle(currentAdvGirl.talkEvent.Contains(0) || currentAdvGirl.talkEvent.Contains(1), "Had first meeting");
                if (GUI.changed)
                {
                    if (newVal)
                    {
                        currentAdvGirl.talkEvent.Add(0);
                        currentAdvGirl.talkEvent.Add(1);
                    }
                    else
                    {
                        currentAdvGirl.talkEvent.Remove(0);
                        currentAdvGirl.talkEvent.Remove(1);
                    }
                }

                GUI.changed = false;
                newVal      = GUILayout.Toggle(currentAdvGirl.talkEvent.Contains(2), "Is a friend");
                if (GUI.changed)
                {
                    if (newVal)
                    {
                        currentAdvGirl.talkEvent.Add(2);
                    }
                    else
                    {
                        currentAdvGirl.talkEvent.Remove(2);
                    }
                }

                currentAdvGirl.isGirlfriend = GUILayout.Toggle(currentAdvGirl.isGirlfriend, "Is a girlfriend");
                currentAdvGirl.isStaff      = GUILayout.Toggle(currentAdvGirl.isStaff, "Is a club member");

                currentAdvGirl.denial.kiss      = GUILayout.Toggle(currentAdvGirl.denial.kiss, "Won't refuse kiss");
                currentAdvGirl.denial.massage   = GUILayout.Toggle(currentAdvGirl.denial.massage, "Won't refuse strong massage");
                currentAdvGirl.denial.anal      = GUILayout.Toggle(currentAdvGirl.denial.anal, "Won't refuse anal");
                currentAdvGirl.denial.aibu      = GUILayout.Toggle(currentAdvGirl.denial.aibu, "Won't refuse vibrator");
                currentAdvGirl.denial.notCondom = GUILayout.Toggle(currentAdvGirl.denial.notCondom, "Insert w/o condom OK");

                if (_gameMgr?.actScene != null && currentAdvGirl.transform != null && GUILayout.Button("Follow me"))
                {
                    var npc = currentAdvGirl.transform.GetComponent <NPC>();
                    if (npc)
                    {
                        _gameMgr.actScene.Player.ChaserSet(npc);
                    }
                    else
                    {
                        CheatToolsPlugin.Logger.Log(LogLevel.Warning | LogLevel.Message, "Could not make heroine follow - NPC component not found");
                    }
                }

                if (GUILayout.Button("Navigate to heroine's GameObject"))
                {
                    if (currentAdvGirl.transform != null)
                    {
                        cheatToolsWindow.Editor.TreeViewer.SelectAndShowObject(currentAdvGirl.transform);
                    }
                    else
                    {
                        CheatToolsPlugin.Logger.Log(LogLevel.Warning | LogLevel.Message, "Heroine has no body assigned");
                    }
                }

                if (GUILayout.Button("Open Heroine in inspector"))
                {
                    cheatToolsWindow.Editor.Inspector.Push(new InstanceStackEntry(currentAdvGirl, "Heroine " + currentAdvGirl.Name), true);
                }

                if (GUILayout.Button("Inspect extended data"))
                {
                    cheatToolsWindow.Editor.Inspector.Push(new InstanceStackEntry(ExtensibleSaveFormat.ExtendedSave.GetAllExtendedData(currentAdvGirl.charFile), "ExtData for " + currentAdvGirl.Name), true);
                }
            }
            GUILayout.EndVertical();
        }