using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.0")] namespace PregnancyMods; [BepInPlugin("com.lousan114.pregnancy_mods", "Pregnancy Mods", "1.3.0")] public class PregnancyModsPlugin : BaseUnityPlugin { private struct Target { public string Name; public int Age; public string PregValue; public int Shijia; public int MemberClass; public int Index; public string Note; } private class Notice { public string Text; public float Until; } public const string GUID = "com.lousan114.pregnancy_mods"; public const string NAME = "Pregnancy Mods"; public const string VERSION = "1.3.0"; internal static PregnancyModsPlugin Instance; internal static ManualLogSource Log; internal static ConfigEntry ModEnabled; internal static ConfigEntry FamilyFertilityMultiplier; internal static ConfigEntry FamilyAlwaysPregnant; internal static ConfigEntry OtherClanFertilityMultiplier; internal static ConfigEntry AffairAlwaysPregnant; internal static ConfigEntry MenuKey; internal static ConfigEntry FixRoyalPanelCrash; internal static ConfigEntry BloodlineEnabled; internal static ConfigEntry Language; internal static ConfigEntry BirthNotify; internal static ConfigEntry InheritTalent; internal static ConfigEntry GenderSelect; internal static ConfigEntry BoyPercent; internal static ConfigEntry TwinsPercent; internal static ConfigEntry TripletsPercent; internal static ConfigEntry PregnancyMonths; internal static ConfigEntry NoPostpartumCooldown; internal static int RandDepth; internal static bool RandCtxFamily; internal static int TouQingDepth; internal static bool ForceNext; private bool _showMenu; private Rect _win = new Rect(60f, 40f, 700f, 780f); private string _searchWomen = ""; private string _searchFather = ""; private Vector2 _scroll; private int _tab; private string _toast = ""; private float _toastUntil; private GUIStyle _rowStyle; private GUIStyle _headStyle; private GUIStyle _toastStyle; private float _nextBloodTick; private static readonly List s_notices = new List(); private GUIStyle _noticeStyle; private int _fatherPick = -1; private void Awake() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Expected O, but got Unknown //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Expected O, but got Unknown //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Expected O, but got Unknown //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Expected O, but got Unknown //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Expected O, but got Unknown //IL_03bc: Unknown result type (might be due to invalid IL or missing references) //IL_03c1: Unknown result type (might be due to invalid IL or missing references) Instance = this; Log = ((BaseUnityPlugin)this).Logger; ModEnabled = ((BaseUnityPlugin)this).Config.Bind("1. General", "Enabled", true, "Master switch for all features of this mod."); FamilyFertilityMultiplier = ((BaseUnityPlugin)this).Config.Bind("1. General", "FamilyFertilityMultiplier", 10f, new ConfigDescription("Multiplies the monthly pregnancy chance for your own family (wives, consorts, female members) and the royal palace. 1 = vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 100f), Array.Empty())); FamilyAlwaysPregnant = ((BaseUnityPlugin)this).Config.Bind("1. General", "FamilyAlwaysPregnant", false, "If true, every eligible spouse/female member of your family conceives on the next monthly tick (eligibility = married, not already pregnant, not on postpartum cooldown)."); OtherClanFertilityMultiplier = ((BaseUnityPlugin)this).Config.Bind("1. General", "OtherClanFertilityMultiplier", 1f, new ConfigDescription("Multiplies the monthly pregnancy chance for OTHER clans' members and wives. 1 = vanilla. Raising this grows rival clans faster too!", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 100f), Array.Empty())); AffairAlwaysPregnant = ((BaseUnityPlugin)this).Config.Bind("1. General", "AffairAlwaysPregnant", true, "Affairs / secret liaisons (the game's HuaiYun_TouQing events) ALWAYS cause pregnancy - including women of other clans - as long as the target is an adult and not already pregnant."); MenuKey = ((BaseUnityPlugin)this).Config.Bind("2. Menu", "MenuKey", (KeyCode)287, "Key that opens the Pregnancy menu (click a person to make them pregnant instantly)."); Language = ((BaseUnityPlugin)this).Config.Bind("2. Menu", "Language", Lang.VI, "Menu language / Ngon ngu giao dien: EN = English, VI = Tieng Viet."); BirthNotify = ((BaseUnityPlugin)this).Config.Bind("4. Bloodline", "BirthNotify", true, "Show an on-screen notification when a secret bloodline child is born."); InheritTalent = ((BaseUnityPlugin)this).Config.Bind("4. Bloodline", "InheritTalent", true, "Children in the Bloodline ledger inherit the REAL father's talent (and sometimes skill) at birth, when the father is known."); BloodlineEnabled = ((BaseUnityPlugin)this).Config.Bind("4. Bloodline", "BloodlineEnabled", true, "Track every affair conception in a hidden Bloodline ledger: which children across rival clans (and inside your own house) were secretly fathered outside the marriage. View in the F6 menu -> Bloodline tab."); GenderSelect = ((BaseUnityPlugin)this).Config.Bind("5. Births", "GenderSelect", GenderMode.Natural, "Sex of newborn children in your family: Natural = vanilla random, Boy/Girl = always, Custom = roll with BoyPercent."); BoyPercent = ((BaseUnityPlugin)this).Config.Bind("5. Births", "BoyPercent", 50, new ConfigDescription("Chance (%) that a newborn is a BOY when GenderSelect = Custom.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); TwinsPercent = ((BaseUnityPlugin)this).Config.Bind("5. Births", "TwinsPercent", 20, new ConfigDescription("Chance (%) that a birth in your family delivers TWINS (one extra baby).", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); TripletsPercent = ((BaseUnityPlugin)this).Config.Bind("5. Births", "TripletsPercent", 5, new ConfigDescription("When the twins roll hits: chance (%) of a THIRD baby.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); PregnancyMonths = ((BaseUnityPlugin)this).Config.Bind("5. Births", "PregnancyMonths", 10, new ConfigDescription("Length of every pregnancy in months (10 = vanilla). Applies to ongoing pregnancies too, in every pool: family, palace, other clans.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 10), Array.Empty())); NoPostpartumCooldown = ((BaseUnityPlugin)this).Config.Bind("5. Births", "NoPostpartumCooldown", true, "Remove the postpartum rest period of your family's wives/consorts so they can conceive again immediately."); FixRoyalPanelCrash = ((BaseUnityPlugin)this).Config.Bind("3. Fixes", "FixRoyalPanelCrash", true, "Guards a vanilla bug: the royal palace panels (PerMemberKingPanel / PerMemberKingQuPanel) read Member_King / Member_King_qu with a stale click index and throw ArgumentOutOfRangeException when that list shrank. This blocks the crash and logs a warning instead."); Harmony val = new Harmony("com.lousan114.pregnancy_mods"); int num = 0; Type[] array = new Type[9] { typeof(Patch_Rand_HuaiYun), typeof(Patch_HuaiYun_TouQing), typeof(Patch_GetRanom), typeof(Patch_KingQuPanel_DataGuard), typeof(Patch_KingQuPanel_ShowGuard), typeof(Patch_KingPanel_DataGuard), typeof(Patch_KingPanel_ShowGuard), typeof(Patch_PerKMShow_ClickFix), typeof(Patch_NewMemberNow) }; foreach (Type type in array) { try { val.PatchAll(type); num++; } catch (Exception ex) { Log.LogError((object)("Patch " + type.Name + " failed - game version may have changed: " + ex.Message)); } } Log.LogInfo((object)("Pregnancy Mods 1.3.0 loaded, " + num + "/9 patch sets applied. Press " + ((object)MenuKey.Value/*cast due to .constrained prefix*/).ToString() + " in game to open the menu.")); } private void Update() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown(MenuKey.Value)) { _showMenu = !_showMenu; } if (Time.unscaledTime >= _nextBloodTick) { _nextBloodTick = Time.unscaledTime + 5f; try { Bloodline.Tick(); } catch (Exception ex) { Log.LogWarning((object)("Bloodline tick: " + ex.Message)); } try { FastBirthTick(); } catch (Exception ex2) { Log.LogWarning((object)("Fast-birth tick: " + ex2.Message)); } } } internal static void FastBirthTick() { if (ModEnabled == null || !ModEnabled.Value || !GameLoaded()) { return; } int num = ((PregnancyMonths != null) ? PregnancyMonths.Value : 10); bool flag = num < 10; bool flag2 = NoPostpartumCooldown != null && NoPostpartumCooldown.Value; if (!flag && !flag2) { return; } if (flag) { ClampPool(Mainload.Member_now, 25, num); ClampPool(Mainload.Member_qu, 18, num); ClampPool(Mainload.MenKe_Now, 17, num); ClampPool(Mainload.Member_King, 11, num); ClampPool(Mainload.Member_King_qu, 13, num); List>> member_other = Mainload.Member_other; if (member_other != null) { foreach (List> item in member_other) { ClampPool(item, 12, num); } } List>> member_Other_qu = Mainload.Member_Other_qu; if (member_Other_qu != null) { foreach (List> item2 in member_Other_qu) { ClampPool(item2, 13, num); } } } if (!flag2) { return; } List> member_qu = Mainload.Member_qu; if (member_qu == null) { return; } foreach (List item3 in member_qu) { if (item3 != null && item3.Count > 24 && SexOf(item3, 2) == "0" && ParseInt(F(item3, 24), 0) > 0) { item3[24] = "0"; } } } private static void ClampPool(List> pool, int pregIdx, int months) { if (pool == null) { return; } foreach (List item in pool) { if (item != null && item.Count > pregIdx && ParseInt(F(item, pregIdx), -1) > months) { item[pregIdx] = months.ToString(); } } } internal static bool SetPregValue(int shijia, int cls, int index, string val) { try { List> list = Bloodline.PoolList(shijia, cls); int num = Bloodline.PregIdx(shijia, cls); if (list == null || index < 0 || index >= list.Count) { return false; } List list2 = list[index]; if (list2 == null || list2.Count <= num) { return false; } if (ParseInt(F(list2, num), -1) <= 0) { return false; } list2[num] = val; return true; } catch { return false; } } internal static string F(List row, int idx) { if (row == null || idx < 0 || idx >= row.Count) { return ""; } return row[idx] ?? ""; } internal static string Tok(string s, int i) { if (string.IsNullOrEmpty(s)) { return ""; } string[] array = s.Split(new char[1] { '|' }); if (i < 0 || i >= array.Length) { return ""; } return array[i]; } internal static int ParseInt(string s, int fallback) { if (!int.TryParse(s, out var result)) { return fallback; } return result; } internal static string Fold(string s) { if (string.IsNullOrEmpty(s)) { return ""; } StringBuilder stringBuilder = new StringBuilder(s.Length); string text = s.Normalize(NormalizationForm.FormD); foreach (char c in text) { if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark) { switch (c) { case 'đ': stringBuilder.Append('d'); break; case 'Đ': stringBuilder.Append('D'); break; default: stringBuilder.Append(c); break; } } } return stringBuilder.ToString().ToLowerInvariant(); } internal static bool SearchMatch(string name, string query) { if (string.IsNullOrEmpty(query)) { return true; } return Fold(name).Contains(Fold(query)); } internal static int AdultAge() { try { if (Mainload.OldFenjie != null && Mainload.OldFenjie.Count > 1) { return Mainload.OldFenjie[1]; } } catch { } return 18; } internal static bool GameLoaded() { try { return Mainload.Member_now != null && Mainload.Member_now.Count > 0; } catch { return false; } } private static string SexOf(List row, int infoField) { return Tok(F(row, infoField), 4); } private static void CollectFamily(List outList) { List> member_qu = Mainload.Member_qu; if (member_qu != null) { for (int i = 0; i < member_qu.Count; i++) { List row = member_qu[i]; if (!(SexOf(row, 2) != "0")) { Target item = new Target { Name = Tok(F(row, 2), 0), Age = ParseInt(F(row, 5), -1), PregValue = F(row, 18), Shijia = -1, MemberClass = 1, Index = i, Note = L.T("spouse") }; int num = ParseInt(F(row, 24), 0); if (item.PregValue == "-1" && num > 0) { item.Note = L.T("spouse") + L.T("cooldown") + num + "m"; } outList.Add(item); } } } List> member_now = Mainload.Member_now; if (member_now == null) { return; } for (int j = 0; j < member_now.Count; j++) { List row2 = member_now[j]; if (!(SexOf(row2, 4) != "0")) { outList.Add(new Target { Name = Tok(F(row2, 4), 0), Age = ParseInt(F(row2, 6), -1), PregValue = F(row2, 25), Shijia = -1, MemberClass = 0, Index = j, Note = L.T("family_member") }); } } } private static void CollectRoyal(List outList) { List> member_King = Mainload.Member_King; if (member_King != null) { for (int i = 0; i < member_King.Count; i++) { List row = member_King[i]; if (!(SexOf(row, 2) != "0")) { outList.Add(new Target { Name = Tok(F(row, 2), 0), Age = ParseInt(F(row, 3), -1), PregValue = F(row, 11), Shijia = -2, MemberClass = 0, Index = i, Note = L.T("royal") }); } } } List> member_King_qu = Mainload.Member_King_qu; if (member_King_qu == null) { return; } for (int j = 0; j < member_King_qu.Count; j++) { List row2 = member_King_qu[j]; if (!(SexOf(row2, 2) == "1")) { outList.Add(new Target { Name = Tok(F(row2, 2), 0), Age = ParseInt(F(row2, 3), -1), PregValue = F(row2, 13), Shijia = -2, MemberClass = 1, Index = j, Note = L.T("royal_consort") }); } } } private static void CollectOtherClan(int s, List outList) { List>> member_other = Mainload.Member_other; if (member_other != null && s < member_other.Count && member_other[s] != null) { for (int i = 0; i < member_other[s].Count; i++) { List row = member_other[s][i]; if (!(SexOf(row, 2) != "0") && !(F(row, 21) == "3")) { outList.Add(new Target { Name = Tok(F(row, 2), 0), Age = ParseInt(F(row, 3), -1), PregValue = F(row, 12), Shijia = s, MemberClass = 0, Index = i, Note = L.T("clan_member") }); } } } List>> member_Other_qu = Mainload.Member_Other_qu; if (member_Other_qu == null || s >= member_Other_qu.Count || member_Other_qu[s] == null) { return; } for (int j = 0; j < member_Other_qu[s].Count; j++) { List row2 = member_Other_qu[s][j]; if (!(SexOf(row2, 2) == "1")) { outList.Add(new Target { Name = Tok(F(row2, 2), 0), Age = ParseInt(F(row2, 3), -1), PregValue = F(row2, 13), Shijia = s, MemberClass = 1, Index = j, Note = L.T("clan_wife") }); } } } private static string ReadPregValue(int shijia, int memberClass, int index) { try { if (shijia == -1 && memberClass == 0) { return F(Mainload.Member_now[index], 25); } if (shijia == -1 && memberClass == 1) { return F(Mainload.Member_qu[index], 18); } if (shijia == -2 && memberClass == 0) { return F(Mainload.Member_King[index], 11); } if (shijia == -2 && memberClass == 1) { return F(Mainload.Member_King_qu[index], 13); } if (shijia >= 0 && memberClass == 0) { return F(Mainload.Member_other[shijia][index], 12); } if (shijia >= 0 && memberClass == 1) { return F(Mainload.Member_Other_qu[shijia][index], 13); } } catch { } return ""; } internal static bool MakePregnant(int shijia, int memberClass, int index, string fatherId = "null") { if (!GameLoaded()) { return false; } if (ReadPregValue(shijia, memberClass, index) != "-1") { return false; } if (string.IsNullOrEmpty(fatherId)) { fatherId = "null"; } ForceNext = true; try { FormulaData.HuaiYun_TouQing(shijia, memberClass, index, fatherId); } catch (Exception ex) { Log.LogError((object)("MakePregnant failed: " + ex)); } finally { ForceNext = false; } return ReadPregValue(shijia, memberClass, index) != "-1"; } internal static string PlaceName(BloodEntry e) { if (e.Dir == "PALACE") { return L.T("palace"); } if (e.Dir == "IN") { return L.T("your_house"); } if (e.Dir == "MENKE") { return L.T("retainer"); } string text = ""; try { text = Bloodline.RowName(Mainload.Member_other[e.Shijia][0], 2); } catch { } return L.T("clan_n") + (e.Shijia + 1) + ((text != "") ? (" (" + text + ")") : ""); } internal static void PushNotice(string msg) { try { s_notices.Add(new Notice { Text = msg, Until = Time.unscaledTime + 8f }); if (s_notices.Count > 4) { s_notices.RemoveAt(0); } if (Log != null) { Log.LogInfo((object)("[Notice] " + msg)); } } catch { } } private void DrawNotices() { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown //IL_00fa: Unknown result type (might be due to invalid IL or missing references) if (s_notices.Count == 0) { return; } s_notices.RemoveAll((Notice n) => Time.unscaledTime > n.Until); if (s_notices.Count == 0) { return; } if (_noticeStyle == null) { _noticeStyle = new GUIStyle(GUI.skin.box) { fontSize = 15, fontStyle = (FontStyle)1, alignment = (TextAnchor)4, wordWrap = true }; _noticeStyle.normal.textColor = new Color(1f, 0.92f, 0.7f); } float num = 560f; float num2 = 60f; foreach (Notice s_notice in s_notices) { GUIContent val = new GUIContent(s_notice.Text); float num3 = _noticeStyle.CalcHeight(val, num - 20f) + 14f; GUI.Box(new Rect(((float)Screen.width - num) / 2f, num2, num, num3), val, _noticeStyle); num2 += num3 + 6f; } } private List FatherCandidates() { List list = new List(); try { List> member_now = Mainload.Member_now; int num = AdultAge(); int num2 = 0; while (member_now != null && num2 < member_now.Count) { if (Tok(F(member_now[num2], 4), 4) == "1" && ParseInt(F(member_now[num2], 6), 0) >= num) { list.Add(num2); } num2++; } } catch { } return list; } private string SelectedFatherId(List cands) { if (_fatherPick < 0 || _fatherPick >= cands.Count) { return "null"; } try { return F(Mainload.Member_now[cands[_fatherPick]], 0); } catch { return "null"; } } private List FilterFathers(List cands) { if (string.IsNullOrEmpty(_searchFather)) { return cands; } List list = new List(); foreach (int cand in cands) { string name = ""; try { name = Bloodline.RowName(Mainload.Member_now[cand], 4); } catch { } if (SearchMatch(name, _searchFather)) { list.Add(cand); } } return list; } private void DrawFatherPicker(List cands) { GUILayout.BeginHorizontal(GUI.skin.box, Array.Empty()); string text = L.T("father_none"); if (_fatherPick >= 0 && _fatherPick < cands.Count) { try { text = Bloodline.RowName(Mainload.Member_now[cands[_fatherPick]], 4); } catch { } } GUILayout.Label(L.T("father") + text + ((cands.Count > 0) ? (" (" + (_fatherPick + 1) + "/" + cands.Count + ")") : ""), _rowStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(300f) }); if (GUILayout.Button("<", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(30f) })) { _fatherPick = ((_fatherPick <= -1) ? (cands.Count - 1) : (_fatherPick - 1)); } if (GUILayout.Button(">", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(30f) })) { _fatherPick = ((_fatherPick >= cands.Count - 1) ? (-1) : (_fatherPick + 1)); } GUILayout.Space(10f); GUILayout.Label(L.T("search"), _rowStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(46f) }); string text2 = GUILayout.TextField(_searchFather, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) }); if (text2 != _searchFather) { _searchFather = text2; _fatherPick = -1; } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); } private void DrawBloodlineRows() { //IL_04c0: Unknown result type (might be due to invalid IL or missing references) //IL_04ea: Expected O, but got Unknown List entries = Bloodline.Entries; int num = 0; int num2 = 0; int num3 = 0; HashSet hashSet = new HashSet(); foreach (BloodEntry item in entries) { if (item.Status == "B" || item.Status == "C") { num++; } else if (item.Status == "P") { num2++; } else { num3++; } if (item.Shijia >= 0) { hashSet.Add(item.Shijia); } } GUILayout.Label(L.F("blood_sum", num, num2) + ((hashSet.Count > 0) ? L.F("blood_clans", hashSet.Count) : "") + ((num3 > 0) ? L.F("blood_lost", num3) : ""), _headStyle, Array.Empty()); GUILayout.Label(L.T("blood_hint"), _rowStyle, Array.Empty()); GUILayout.Space(4f); if (entries.Count == 0) { GUILayout.Label(L.T("blood_empty"), _rowStyle, Array.Empty()); return; } BloodEntry bloodEntry = null; foreach (BloodEntry item2 in entries) { GUILayout.BeginHorizontal(GUI.skin.box, Array.Empty()); string text; if (item2.Status == "C") { text = L.T("claimed") + item2.ChildName; } else if (item2.Status == "B") { text = L.T("born") + ((item2.ChildName != "") ? item2.ChildName : ((item2.ChildId != "") ? item2.ChildId : L.T("child_untracked"))); } else if (item2.Status == "P") { string text2 = ""; try { List> list = Bloodline.PoolList(item2.Shijia, item2.MemberClass); int num4 = 0; while (list != null && num4 < list.Count) { if (F(list[num4], 0) == item2.MotherId) { text2 = F(list[num4], Bloodline.PregIdx(item2.Shijia, item2.MemberClass)); break; } num4++; } } catch { } text = L.T("pregnant") + ((text2 != "" && text2 != "-1") ? L.F("months_left", text2) : ""); } else { text = L.T("lost"); } GUILayout.Label(text + "\n" + L.T("mother") + item2.MotherName + " | " + PlaceName(item2) + "\n" + L.T("father") + ((item2.FatherName != "") ? item2.FatherName : "?") + ((item2.Date != "") ? (" | " + item2.Date) : "") + (ShowVia(item2.Via) ? (L.T("via") + item2.Via) : ""), _rowStyle, Array.Empty()); GUILayout.FlexibleSpace(); if (item2.Status == "B" && item2.Shijia >= 0 && item2.ChildId != "" && GUILayout.Button(L.T("claim"), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(110f), GUILayout.Height(30f) })) { int num5 = ResolveFatherIndex(item2); if (num5 < 0) { Toast(L.T("claim_need_father")); } else { Bloodline.ClaimChild(item2, num5, out var message); Toast(message); } } if (GUILayout.Button(new GUIContent(L.T("untrack"), L.T("untrack_tip")), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(100f), GUILayout.Height(30f) })) { bloodEntry = item2; } GUILayout.EndHorizontal(); } if (bloodEntry != null) { entries.Remove(bloodEntry); Bloodline.Save(); } } private static bool ShowVia(string via) { if (string.IsNullOrEmpty(via)) { return false; } string text = via.ToLowerInvariant(); string[] array = new string[11] { "huaiyun", "touqing", "tou_qing", "hui_tou", "you_hui", "dmd", "formu", "harmony", "patch", "bloodline", "pregnancy" }; foreach (string value in array) { if (text.Contains(value)) { return false; } } return true; } private int ResolveFatherIndex(BloodEntry e) { try { List> member_now = Mainload.Member_now; if (member_now != null && !string.IsNullOrEmpty(e.FatherId) && e.FatherId != "null") { for (int i = 0; i < member_now.Count; i++) { if (F(member_now[i], 0) == e.FatherId) { return i; } } } List list = FatherCandidates(); if (_fatherPick >= 0 && _fatherPick < list.Count) { return list[_fatherPick]; } } catch { } return -1; } private void OnGUI() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Expected O, but got Unknown //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) if (_rowStyle == null) { _rowStyle = new GUIStyle(GUI.skin.label) { fontSize = 14, alignment = (TextAnchor)3 }; _headStyle = new GUIStyle(GUI.skin.label) { fontSize = 15, fontStyle = (FontStyle)1 }; _toastStyle = new GUIStyle(GUI.skin.label) { fontSize = 14, fontStyle = (FontStyle)1 }; } DrawNotices(); if (_showMenu) { _win = GUI.Window(1347568967, _win, new WindowFunction(DrawWindow), "Pregnancy Mods v1.3.0 (" + ((object)MenuKey.Value/*cast due to .constrained prefix*/).ToString() + L.T("close")); } } private void Toast(string msg) { _toast = msg; _toastUntil = Time.unscaledTime + 4f; } private void DrawWindow(int id) { //IL_0805: Unknown result type (might be due to invalid IL or missing references) //IL_080f: Unknown result type (might be due to invalid IL or missing references) //IL_0814: Unknown result type (might be due to invalid IL or missing references) //IL_0c1e: Unknown result type (might be due to invalid IL or missing references) if (!GameLoaded()) { GUILayout.Space(20f); GUILayout.Label(L.T("load_first"), _headStyle, Array.Empty()); GUI.DragWindow(); return; } GUILayout.BeginVertical(GUI.skin.box, Array.Empty()); GUILayout.BeginHorizontal(Array.Empty()); ModEnabled.Value = GUILayout.Toggle(ModEnabled.Value, L.T("enabled"), Array.Empty()); GUILayout.FlexibleSpace(); FamilyAlwaysPregnant.Value = GUILayout.Toggle(FamilyAlwaysPregnant.Value, L.T("fam_always"), Array.Empty()); GUILayout.FlexibleSpace(); AffairAlwaysPregnant.Value = GUILayout.Toggle(AffairAlwaysPregnant.Value, L.T("affair_always"), Array.Empty()); GUILayout.FlexibleSpace(); if (GUILayout.Button((Language.Value == Lang.VI) ? "EN" : "VI", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(44f) })) { Language.Value = ((Language.Value != Lang.VI) ? Lang.VI : Lang.EN); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label(L.T("fam_mult") + FamilyFertilityMultiplier.Value.ToString("0"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(190f) }); FamilyFertilityMultiplier.Value = Mathf.Round(GUILayout.HorizontalSlider(FamilyFertilityMultiplier.Value, 1f, 100f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(140f) })); GUILayout.Space(16f); GUILayout.Label(L.T("other_mult") + OtherClanFertilityMultiplier.Value.ToString("0"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) }); OtherClanFertilityMultiplier.Value = Mathf.Round(GUILayout.HorizontalSlider(OtherClanFertilityMultiplier.Value, 1f, 100f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(140f) })); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label(L.T("gender"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(118f) }); int value = (int)GenderSelect.Value; int num = GUILayout.Toolbar(value, new string[4] { L.T("g_nat"), L.T("g_boy"), L.T("g_girl"), L.T("g_pct") }, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(300f) }); if (num != value) { GenderSelect.Value = (GenderMode)num; } if (GenderSelect.Value == GenderMode.Custom) { GUILayout.Space(10f); GUILayout.Label(L.T("boy_pct") + BoyPercent.Value + "%", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(88f) }); BoyPercent.Value = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)BoyPercent.Value, 0f, 100f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) })); } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label(L.T("twins") + TwinsPercent.Value + "%", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(140f) }); TwinsPercent.Value = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)TwinsPercent.Value, 0f, 100f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) })); GUILayout.Space(14f); GUILayout.Label(L.T("triplets") + TripletsPercent.Value + "%", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(130f) }); TripletsPercent.Value = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)TripletsPercent.Value, 0f, 100f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) })); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label(L.T("preg_months") + PregnancyMonths.Value, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(140f) }); PregnancyMonths.Value = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)PregnancyMonths.Value, 1f, 10f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) })); GUILayout.Space(14f); NoPostpartumCooldown.Value = GUILayout.Toggle(NoPostpartumCooldown.Value, L.T("no_cooldown"), Array.Empty()); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.EndVertical(); _tab = GUILayout.Toolbar(_tab, new string[4] { L.T("tab_family"), L.T("tab_royal"), L.T("tab_others"), L.T("tab_blood") }, Array.Empty()); List cands = FilterFathers(FatherCandidates()); if (_tab <= 2) { DrawFatherPicker(cands); } List list = new List(); try { if (_tab == 0) { CollectFamily(list); } else if (_tab == 1) { CollectRoyal(list); } else if (_tab == 2) { int num2 = Mainload.Member_other?.Count ?? 0; for (int i = 0; i < num2; i++) { CollectOtherClan(i, list); } } } catch (Exception ex) { Log.LogError((object)("Menu list error: " + ex)); } if (_tab == 0 && GUILayout.Button(L.T("make_all"), Array.Empty())) { int num3 = 0; int num4 = 0; foreach (Target item in list) { if (item.PregValue == "-1" && (item.MemberClass == 1 || item.Age >= AdultAge())) { if (MakePregnant(item.Shijia, item.MemberClass, item.Index, SelectedFatherId(cands))) { num3++; } else { num4++; } } } Toast(num3 + L.T("now_pregnant") + ((num4 > 0) ? (", " + num4 + L.T("not_eligible_n")) : "")); } if (_tab <= 2) { GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label(L.T("search"), _rowStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(46f) }); _searchWomen = GUILayout.TextField(_searchWomen, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(220f) }); if (_searchWomen != "" && GUILayout.Button("x", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(26f) })) { _searchWomen = ""; } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); if (_searchWomen != "") { list = list.FindAll((Target t) => SearchMatch(t.Name, _searchWomen)); } } _scroll = GUILayout.BeginScrollView(_scroll, Array.Empty()); int num5 = AdultAge(); string text = null; foreach (Target item2 in list) { if (_tab == 2) { string text2 = "Clan #" + (item2.Shijia + 1); if (text2 != text) { text = text2; string text3 = ""; try { text3 = Tok(F(Mainload.Member_other[item2.Shijia][0], 2), 0); } catch { } GUILayout.Space(6f); GUILayout.Label(L.T("clan_n") + (item2.Shijia + 1) + ((text3 != "") ? (" - " + text3) : ""), _headStyle, Array.Empty()); } } GUILayout.BeginHorizontal(GUI.skin.box, Array.Empty()); object obj2; if (item2.Age < 0) { obj2 = "?"; } else { int age = item2.Age; obj2 = age.ToString(); } string text4 = (string)obj2; GUILayout.Label(item2.Name + " (" + L.T("age") + text4 + ", " + item2.Note + ")", _rowStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(330f) }); GUILayout.FlexibleSpace(); if (item2.PregValue != "-1" && item2.PregValue != "") { GUILayout.Label(L.F("pregnant_left", item2.PregValue), _rowStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(165f) }); if (ParseInt(item2.PregValue, 0) > 1 && GUILayout.Button(L.T("birth_now"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) })) { bool flag = SetPregValue(item2.Shijia, item2.MemberClass, item2.Index, "1"); Toast(flag ? (item2.Name + L.T("birth_next_month")) : (item2.Name + L.T("not_eligible"))); } } else if (item2.MemberClass == 0 && item2.Age >= 0 && item2.Age < num5) { GUILayout.Label(L.T("too_young"), _rowStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(190f) }); } else if (GUILayout.Button(L.T("make_pregnant"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) })) { bool flag2 = MakePregnant(item2.Shijia, item2.MemberClass, item2.Index, SelectedFatherId(cands)); Toast(flag2 ? (item2.Name + L.T("is_now_pregnant")) : (item2.Name + L.T("not_eligible"))); } GUILayout.EndHorizontal(); } if (_tab == 3) { DrawBloodlineRows(); } else if (list.Count == 0) { GUILayout.Label(L.T("nobody"), _rowStyle, Array.Empty()); } GUILayout.EndScrollView(); if (Time.unscaledTime < _toastUntil) { GUILayout.Label(_toast, _toastStyle, Array.Empty()); } if (GUI.tooltip != "") { GUILayout.Label(GUI.tooltip, _rowStyle, Array.Empty()); } GUI.DragWindow(new Rect(0f, 0f, 10000f, 24f)); } } [HarmonyPatch(typeof(FormulaData), "Rand_HuaiYun")] internal static class Patch_Rand_HuaiYun { [HarmonyPrefix] private static void Prefix(int shijiaIndex) { PregnancyModsPlugin.RandDepth++; PregnancyModsPlugin.RandCtxFamily = shijiaIndex < 0; } [HarmonyFinalizer] private static void Finalizer() { if (PregnancyModsPlugin.RandDepth > 0) { PregnancyModsPlugin.RandDepth--; } } [HarmonyPostfix] private static void Postfix(ref int __result, int shijiaIndex) { if (!PregnancyModsPlugin.ModEnabled.Value) { return; } if (PregnancyModsPlugin.ForceNext || (PregnancyModsPlugin.TouQingDepth > 0 && PregnancyModsPlugin.AffairAlwaysPregnant.Value)) { __result = 99999; } else { if (__result <= 0) { return; } if (shijiaIndex < 0) { if (PregnancyModsPlugin.FamilyAlwaysPregnant.Value) { __result = 99999; } else { __result = Mathf.Max(1, Mathf.RoundToInt((float)__result * PregnancyModsPlugin.FamilyFertilityMultiplier.Value)); } } else { __result = Mathf.Max(1, Mathf.RoundToInt((float)__result * PregnancyModsPlugin.OtherClanFertilityMultiplier.Value)); } } } } [HarmonyPatch(typeof(FormulaData), "HuaiYun_TouQing")] internal static class Patch_HuaiYun_TouQing { private static string s_pregBefore; [HarmonyPrefix] private static void Prefix(int __0, int __1, int __2) { PregnancyModsPlugin.TouQingDepth++; s_pregBefore = null; try { List> list = Bloodline.PoolList(__0, __1); if (list != null && __2 >= 0 && __2 < list.Count) { s_pregBefore = PregnancyModsPlugin.F(list[__2], Bloodline.PregIdx(__0, __1)); } } catch { } } [HarmonyPostfix] private static void Postfix(int __0, int __1, int __2, string __3) { try { if (s_pregBefore != "-1") { return; } List> list = Bloodline.PoolList(__0, __1); if (list != null && __2 >= 0 && __2 < list.Count) { string text = PregnancyModsPlugin.F(list[__2], Bloodline.PregIdx(__0, __1)); if (text != "-1" && text != "") { Bloodline.RecordConception(__0, __1, __2, __3, PregnancyModsPlugin.ForceNext); } } } catch { } } [HarmonyFinalizer] private static void Finalizer() { if (PregnancyModsPlugin.TouQingDepth > 0) { PregnancyModsPlugin.TouQingDepth--; } } } [HarmonyPatch(typeof(TrueRandom), "GetRanom")] internal static class Patch_GetRanom { [HarmonyPrefix] private static bool Prefix(ref int __result) { if (!PregnancyModsPlugin.ModEnabled.Value) { return true; } if (PregnancyModsPlugin.ForceNext) { __result = 0; return false; } if (PregnancyModsPlugin.TouQingDepth > 0 && PregnancyModsPlugin.AffairAlwaysPregnant.Value) { __result = 0; return false; } if (PregnancyModsPlugin.RandDepth > 0) { bool num; if (!PregnancyModsPlugin.RandCtxFamily) { num = PregnancyModsPlugin.OtherClanFertilityMultiplier.Value > 1f; } else { if (PregnancyModsPlugin.FamilyAlwaysPregnant.Value) { goto IL_0077; } num = PregnancyModsPlugin.FamilyFertilityMultiplier.Value > 1f; } if (num) { goto IL_0077; } } return true; IL_0077: __result = 0; return false; } } public enum Lang { EN, VI } public enum GenderMode { Natural, Boy, Girl, Custom } internal static class L { private static readonly Dictionary S = new Dictionary { { "close", new string[2] { " to close)", " để đóng)" } }, { "load_first", new string[2] { "Load a save first - no family data found.", "Hãy vào một save trước - chưa thấy dữ liệu gia tộc." } }, { "enabled", new string[2] { " Mod enabled", " Bật mod" } }, { "fam_always", new string[2] { " Family: always pregnant", " Gia tộc: luôn đậu thai" } }, { "affair_always", new string[2] { " Affairs: always pregnant", " Tư thông: luôn đậu thai" } }, { "fam_mult", new string[2] { "Family fertility x", "Mắn đẻ gia tộc x" } }, { "other_mult", new string[2] { "Other clans x", "Gia tộc khác x" } }, { "tab_family", new string[2] { "My family", "Gia tộc" } }, { "tab_royal", new string[2] { "Royal palace", "Hoàng cung" } }, { "tab_others", new string[2] { "Other clans", "Tộc khác" } }, { "tab_blood", new string[2] { "Bloodline", "Huyết mạch" } }, { "make_all", new string[2] { "Make ALL eligible family spouses pregnant now", "Cho TẤT CẢ thê thiếp đủ điều kiện mang thai ngay" } }, { "now_pregnant", new string[2] { " now pregnant", " người vừa đậu thai" } }, { "not_eligible_n", new string[2] { " not eligible", " không đủ điều kiện" } }, { "father", new string[2] { "Father: ", "Cha: " } }, { "father_none", new string[2] { "(random/none)", "(ngẫu nhiên/không chọn)" } }, { "age", new string[2] { "age ", "tuổi " } }, { "spouse", new string[2] { "spouse", "thê thiếp" } }, { "family_member", new string[2] { "family member", "người trong tộc" } }, { "royal", new string[2] { "royal", "hoàng thân" } }, { "royal_consort", new string[2] { "royal consort", "phi tần" } }, { "clan_member", new string[2] { "clan member", "nữ nhân trong tộc" } }, { "clan_wife", new string[2] { "clan wife", "vợ người trong tộc" } }, { "cooldown", new string[2] { ", cooldown ", ", nghỉ sau sinh " } }, { "pregnant_left", new string[2] { "Pregnant - {0} months left", "Mang thai - còn {0} tháng" } }, { "too_young", new string[2] { "Too young", "Chưa trưởng thành" } }, { "make_pregnant", new string[2] { "Make pregnant", "Cho mang thai" } }, { "is_now_pregnant", new string[2] { " is now pregnant!", " đã mang thai!" } }, { "not_eligible", new string[2] { ": not eligible (age/status)", ": không đủ điều kiện (tuổi/trạng thái)" } }, { "nobody", new string[2] { "Nobody found in this category.", "Không có ai trong mục này." } }, { "blood_sum", new string[2] { "Secret bloodline: {0} born, {1} on the way", "Huyết mạch bí mật: {0} đã sinh, {1} đang mang thai" } }, { "blood_clans", new string[2] { " - your blood runs in {0} rival clan(s)", " - dòng máu của bạn ở {0} gia tộc khác" } }, { "blood_lost", new string[2] { " ({0} lost)", " ({0} thất lạc)" } }, { "blood_empty", new string[2] { "No secret conceptions recorded yet. Affairs and F6-menu pregnancies will appear here.", "Chưa ghi nhận lần thụ thai bí mật nào. Tư thông và bấm nút trong menu F6 sẽ hiện ở đây." } }, { "born", new string[2] { "Born: ", "Đã sinh: " } }, { "child_untracked", new string[2] { "child untracked", "chưa xác định được đứa trẻ" } }, { "pregnant", new string[2] { "Pregnant", "Đang mang thai" } }, { "months_left", new string[2] { " - {0}m left", " - còn {0} tháng" } }, { "lost", new string[2] { "Lost", "Thất lạc" } }, { "claimed", new string[2] { "CLAIMED: ", "ĐÃ NHẬN VỀ: " } }, { "mother", new string[2] { "Mother: ", "Mẹ: " } }, { "via", new string[2] { " | via ", " | qua " } }, { "your_house", new string[2] { "YOUR house - outside blood!", "NHÀ BẠN - dòng máu bên ngoài!" } }, { "palace", new string[2] { "Royal palace", "Hoàng cung" } }, { "retainer", new string[2] { "Retainer quarters", "Môn khách" } }, { "clan_n", new string[2] { "Clan #", "Tộc #" } }, { "claim", new string[2] { "Claim", "Nhận về tộc" } }, { "claim_ok", new string[2] { "{0} has joined your family as {1}!", "{0} đã về với gia tộc, tên mới: {1}!" } }, { "claim_need_father", new string[2] { "Select a father first (header of the family tabs).", "Hãy chọn Cha trước (đầu các tab gia tộc)." } }, { "claim_adult", new string[2] { "Only children below adult age can be claimed (v1).", "Chỉ nhận được con chưa trưởng thành (v1)." } }, { "claim_missing", new string[2] { "Child not found in that clan anymore.", "Không còn tìm thấy đứa trẻ trong gia tộc đó." } }, { "claim_fail", new string[2] { "Claim failed - nothing was changed.", "Nhận về thất bại - chưa thay đổi gì." } }, { "notify_born_out", new string[2] { "Secret child born in {0}: {1} (mother {2})", "Đứa con bí mật vừa chào đời ở {0}: {1} (mẹ: {2})" } }, { "notify_born_in", new string[2] { "A child of outside blood was born in YOUR house: {0}", "Một đứa trẻ mang dòng máu bên ngoài vừa ra đời trong NHÀ BẠN: {0}" } }, { "inherited", new string[2] { " - talent inherited from {0}", " - thừa hưởng thiên phú từ {0}" } }, { "untrack", new string[2] { "Untrack", "Bỏ theo dõi" } }, { "untrack_tip", new string[2] { "Removes only this tracking row from the ledger - the game itself is not affected.", "Chỉ xoá dòng theo dõi này khỏi sổ - không ảnh hưởng gì tới game." } }, { "blood_hint", new string[2] { "\"Untrack\" only deletes the ledger row (game unaffected). \"Claim\" brings the child home to your clan.", "\"Bỏ theo dõi\" chỉ xoá dòng trong sổ (không ảnh hưởng game). \"Nhận về tộc\" đưa đứa trẻ về gia tộc bạn." } }, { "search", new string[2] { "Search: ", "Tìm: " } }, { "gender", new string[2] { "Newborn sex: ", "Giới tính con: " } }, { "g_nat", new string[2] { "Natural", "Tự nhiên" } }, { "g_boy", new string[2] { "Boy", "Trai" } }, { "g_girl", new string[2] { "Girl", "Gái" } }, { "g_pct", new string[2] { "Custom %", "Tỉ lệ %" } }, { "boy_pct", new string[2] { "boys ", "trai " } }, { "twins", new string[2] { "Twins ", "Song thai " } }, { "triplets", new string[2] { "+3rd baby ", "Sinh ba " } }, { "preg_months", new string[2] { "Pregnancy (months): ", "Thai kỳ (tháng): " } }, { "no_cooldown", new string[2] { " No postpartum rest", " Bỏ ở cữ (thụ thai lại ngay)" } }, { "birth_now", new string[2] { "Give birth now", "Sinh ngay" } }, { "birth_next_month", new string[2] { " will give birth when the month turns!", " sẽ sinh khi sang tháng!" } }, { "notify_twins", new string[2] { "TWINS! {0} delivered a second baby", "SONG THAI! {0} vừa sinh thêm một bé" } }, { "notify_triplets", new string[2] { "TRIPLETS! {0} delivered two more babies", "SINH BA! {0} vừa sinh thêm hai bé" } } }; internal static string T(string key) { if (!S.TryGetValue(key, out var value)) { return key; } if (PregnancyModsPlugin.Language == null || PregnancyModsPlugin.Language.Value != Lang.VI) { return value[0]; } return value[1]; } internal static string F(string key, params object[] args) { try { return string.Format(T(key), args); } catch { return T(key); } } } internal class BloodEntry { public string Status = "P"; public string Dir = "OUT"; public int Shijia; public int MemberClass; public string MotherId = ""; public string MotherName = ""; public string FatherId = ""; public string FatherName = ""; public string Via = ""; public string Date = ""; public string ChildId = ""; public string ChildName = ""; public string ChildrenSnapshot = ""; } internal static class Bloodline { internal static readonly List Entries = new List(); private static string _loadedSlot; internal static List> PoolList(int shijia, int cls) { try { if (shijia == -1) { switch (cls) { case 0: return Mainload.Member_now; case 1: return Mainload.Member_qu; case 2: return Mainload.MenKe_Now; } } else { if (shijia == -2) { return (cls == 0) ? Mainload.Member_King : Mainload.Member_King_qu; } if (shijia >= 0) { List>> list = ((cls == 0) ? Mainload.Member_other : Mainload.Member_Other_qu); if (list != null && shijia < list.Count) { return list[shijia]; } } } } catch { } return null; } internal static int PregIdx(int shijia, int cls) { switch (shijia) { case -1: return cls switch { 1 => 18, 0 => 25, _ => 17, }; case -2: if (cls != 0) { return 13; } return 11; default: if (cls != 0) { return 13; } return 12; } } internal static int ChildrenIdx(int shijia, int cls) { switch (shijia) { case -1: return cls switch { 1 => 3, 0 => 2, _ => -1, }; case -2: if (cls != 0) { return 23; } return 13; default: if (cls != 0) { return 23; } return 14; } } internal static int NameField(int shijia, int cls) { if (shijia != -1 || cls != 0) { return 2; } return 4; } private static List> ChildSearchPool(BloodEntry e) { if (e.Shijia >= 0) { return PoolList(e.Shijia, 0); } if (e.Shijia == -2) { return Mainload.Member_King; } return Mainload.Member_now; } private static int ChildNameField(BloodEntry e) { if (e.Shijia != -1) { return 2; } return 4; } internal static string RowName(List row, int nameField) { string text = PregnancyModsPlugin.Tok(PregnancyModsPlugin.F(row, nameField), 0); if (!(text == "")) { return text; } return "?"; } private static List FindById(List> pool, string id) { if (pool == null || string.IsNullOrEmpty(id)) { return null; } for (int i = 0; i < pool.Count; i++) { if (pool[i] != null && pool[i].Count > 0 && pool[i][0] == id) { return pool[i]; } } return null; } internal static string GameDate() { try { List time_now = Mainload.Time_now; if (time_now != null && time_now.Count >= 2) { return "Y" + time_now[0] + " M" + time_now[1]; } if (time_now != null && time_now.Count == 1) { return "Y" + time_now[0]; } } catch { } return ""; } private static string CallerHint() { try { StackTrace stackTrace = new StackTrace(fNeedFileInfo: false); for (int i = 2; i < stackTrace.FrameCount && i < 10; i++) { MethodBase method = stackTrace.GetFrame(i).GetMethod(); if (method == null) { continue; } string text = ((method.DeclaringType != null) ? method.DeclaringType.Name : "") + "." + method.Name; string text2 = text.ToLowerInvariant(); bool flag = false; string[] array = new string[12] { "huaiyun", "touqing", "tou_qing", "hui_tou", "you_hui", "dmd", "formu", "harmony", "patch", "bloodline", "pregnancy", "makepregnant" }; foreach (string value in array) { if (text2.Contains(value)) { flag = true; break; } } if (!flag && !(method.DeclaringType == null) && !(method.DeclaringType.Assembly == null) && !(method.DeclaringType.Assembly.GetName().Name != "Assembly-CSharp")) { return text; } } } catch { } return ""; } internal static void RecordConception(int shijia, int cls, int index, string fuId, bool viaMenu) { if (PregnancyModsPlugin.BloodlineEnabled != null && !PregnancyModsPlugin.BloodlineEnabled.Value) { return; } List> list = PoolList(shijia, cls); if (list != null && index >= 0 && index < list.Count) { List row = list[index]; BloodEntry bloodEntry = new BloodEntry { Shijia = shijia, MemberClass = cls, MotherId = PregnancyModsPlugin.F(row, 0), MotherName = RowName(row, NameField(shijia, cls)), Date = GameDate(), Via = (viaMenu ? "F6 menu" : CallerHint()) }; int num = ChildrenIdx(shijia, cls); bloodEntry.ChildrenSnapshot = ((num >= 0) ? PregnancyModsPlugin.F(row, num) : ""); if (shijia >= 0) { bloodEntry.Dir = "OUT"; } else if (shijia == -2) { bloodEntry.Dir = "PALACE"; } else { bloodEntry.Dir = ((cls == 2) ? "MENKE" : "IN"); } if (!string.IsNullOrEmpty(fuId) && fuId != "null") { bloodEntry.FatherId = fuId; List list2 = FindById(Mainload.Member_now, fuId); bloodEntry.FatherName = ((list2 != null) ? RowName(list2, 4) : fuId); } else if (viaMenu) { bloodEntry.FatherName = "(menu)"; } Entries.Add(bloodEntry); Save(); if (PregnancyModsPlugin.Log != null) { PregnancyModsPlugin.Log.LogInfo((object)("Bloodline: recorded conception - " + bloodEntry.MotherName + " (" + bloodEntry.Dir + ")")); } } } internal static void Tick() { if ((PregnancyModsPlugin.BloodlineEnabled != null && !PregnancyModsPlugin.BloodlineEnabled.Value) || !PregnancyModsPlugin.GameLoaded()) { return; } SyncSlot(); bool flag = false; foreach (BloodEntry entry in Entries) { if (entry.Status != "P") { continue; } List list = FindById(PoolList(entry.Shijia, entry.MemberClass), entry.MotherId); if (list == null) { entry.Status = "L"; flag = true; continue; } string text = PregnancyModsPlugin.F(list, PregIdx(entry.Shijia, entry.MemberClass)); if (text != "-1" && text != "") { continue; } entry.Status = "B"; flag = true; int num = ChildrenIdx(entry.Shijia, entry.MemberClass); if (num >= 0) { HashSet hashSet = new HashSet((entry.ChildrenSnapshot ?? "").Split(new char[1] { '|' })); string[] array = (PregnancyModsPlugin.F(list, num) ?? "").Split(new char[1] { '|' }); foreach (string text2 in array) { if (!(text2 == "") && !(text2 == "null") && !hashSet.Contains(text2)) { entry.ChildId = text2; List list2 = FindById(ChildSearchPool(entry), text2); entry.ChildName = ((list2 != null) ? RowName(list2, ChildNameField(entry)) : ""); break; } } } OnBirthCompleted(entry); } if (flag) { Save(); } } internal static void OnBirthCompleted(BloodEntry e) { string text = ""; try { if (PregnancyModsPlugin.InheritTalent != null && PregnancyModsPlugin.InheritTalent.Value && e.ChildId != "" && ApplyInheritance(e)) { text = L.F("inherited", e.FatherName); } } catch { } try { if (PregnancyModsPlugin.BirthNotify != null && PregnancyModsPlugin.BirthNotify.Value) { string text2 = ((e.ChildName != "") ? e.ChildName : L.T("child_untracked")); PregnancyModsPlugin.PushNotice(((e.Dir == "IN") ? L.F("notify_born_in", text2) : L.F("notify_born_out", PregnancyModsPlugin.PlaceName(e), text2, e.MotherName)) + text); } } catch { } } internal static bool ApplyInheritance(BloodEntry e) { List list = FindById(Mainload.Member_now, e.FatherId); if (list == null) { return false; } List list2 = FindById(ChildSearchPool(e), e.ChildId); if (list2 == null) { return false; } int num = ChildNameField(e); string[] array = PregnancyModsPlugin.F(list2, num).Split(new char[1] { '|' }); string[] array2 = PregnancyModsPlugin.F(list, 4).Split(new char[1] { '|' }); if (array.Length < 8 || array2.Length < 8) { return false; } bool flag = false; if (array2[2] != "0" && array2[2] != "") { array[2] = array2[2]; int val = PregnancyModsPlugin.ParseInt(array[3], 0); int num2 = PregnancyModsPlugin.ParseInt(array2[3], 0); array[3] = Math.Max(val, Math.Max(0, num2 - 10)).ToString(); flag = true; } if (array2[6] != "0" && array2[6] != "" && (array[6] == "0" || array[6] == "")) { array[6] = array2[6]; int num3 = PregnancyModsPlugin.ParseInt(array2[7], 0); array[7] = Math.Max(PregnancyModsPlugin.ParseInt(array[7], 0), Math.Max(0, num3 - 20)).ToString(); flag = true; } if (flag) { list2[num] = string.Join("|", array); } return flag; } internal static void OnNewMemberCreated(int showId, int memberIndex, int countBefore) { if ((PregnancyModsPlugin.BloodlineEnabled != null && !PregnancyModsPlugin.BloodlineEnabled.Value) || showId != 2) { return; } try { List> menKe_Now = Mainload.MenKe_Now; if (menKe_Now == null || memberIndex < 0 || memberIndex >= menKe_Now.Count) { return; } string text = PregnancyModsPlugin.F(menKe_Now[memberIndex], 0); foreach (BloodEntry entry in Entries) { if (!(entry.Status != "P") && entry.MemberClass == 2 && entry.Shijia == -1 && !(entry.MotherId != text)) { entry.Status = "B"; List> member_now = Mainload.Member_now; if (member_now != null && member_now.Count > countBefore) { List row = member_now[member_now.Count - 1]; entry.ChildId = PregnancyModsPlugin.F(row, 0); entry.ChildName = RowName(row, 4); } OnBirthCompleted(entry); Save(); break; } } } catch { } } internal static string StripChild(string childrenList, string childId) { if (string.IsNullOrEmpty(childrenList) || childrenList == "null") { return childrenList; } List list = new List(); string[] array = childrenList.Split(new char[1] { '|' }); foreach (string text in array) { if (text != childId && text != "") { list.Add(text); } } if (list.Count != 0) { return string.Join("|", list); } return "null"; } internal static bool ClaimChild(BloodEntry e, int fatherNowIndex, out string message) { message = ""; try { if (e.Status != "B" || e.Shijia < 0 || string.IsNullOrEmpty(e.ChildId)) { message = L.T("claim_missing"); return false; } List> list = ((Mainload.Member_other != null && e.Shijia < Mainload.Member_other.Count) ? Mainload.Member_other[e.Shijia] : null); List list2 = FindById(list, e.ChildId); if (list2 == null) { message = L.T("claim_missing"); return false; } int num = PregnancyModsPlugin.ParseInt(PregnancyModsPlugin.F(list2, 3), 99); if (num >= PregnancyModsPlugin.AdultAge()) { message = L.T("claim_adult"); return false; } List> member_now = Mainload.Member_now; if (member_now == null || fatherNowIndex < 0 || fatherNowIndex >= member_now.Count) { message = L.T("claim_need_father"); return false; } int num2 = ((PregnancyModsPlugin.Tok(PregnancyModsPlugin.F(list2, 2), 4) == "1") ? 1 : 0); string text = RowName(list2, 2); int count = member_now.Count; FormulaData.New_MemberNow(1, fatherNowIndex, num2, Math.Max(1, num), "null", "null", "null"); if (member_now.Count <= count) { message = L.T("claim_fail"); return false; } List list3 = member_now[member_now.Count - 1]; string[] array = PregnancyModsPlugin.F(list2, 2).Split(new char[1] { '|' }); string[] array2 = PregnancyModsPlugin.F(list3, 4).Split(new char[1] { '|' }); if (array.Length >= 8 && array2.Length >= 8) { array2[2] = array[2]; array2[3] = array[3]; array2[6] = array[6]; array2[7] = array[7]; list3[4] = string.Join("|", array2); } list.Remove(list2); List list4 = FindById(PoolList(e.Shijia, e.MemberClass), e.MotherId); if (list4 != null) { int num3 = ChildrenIdx(e.Shijia, e.MemberClass); if (num3 >= 0) { list4[num3] = StripChild(PregnancyModsPlugin.F(list4, num3), e.ChildId); } if (e.MemberClass == 1) { string id = PregnancyModsPlugin.Tok(PregnancyModsPlugin.F(list4, 2), 9); List list5 = FindById(list, id); if (list5 != null) { list5[14] = StripChild(PregnancyModsPlugin.F(list5, 14), e.ChildId); } } } string text2 = RowName(list3, 4); e.Status = "C"; e.ChildId = PregnancyModsPlugin.F(list3, 0); e.ChildName = text + " -> " + text2; Save(); message = L.F("claim_ok", text, text2); if (PregnancyModsPlugin.Log != null) { PregnancyModsPlugin.Log.LogInfo((object)("Bloodline claim: " + message)); } return true; } catch (Exception ex) { message = L.T("claim_fail"); if (PregnancyModsPlugin.Log != null) { PregnancyModsPlugin.Log.LogError((object)("ClaimChild: " + ex)); } return false; } } private static string Slot() { try { string text = Mainload.CunDangIndex_now; if (!string.IsNullOrEmpty(text)) { char[] invalidFileNameChars = Path.GetInvalidFileNameChars(); foreach (char oldChar in invalidFileNameChars) { text = text.Replace(oldChar, '_'); } return text; } } catch { } return "default"; } private static string FilePath(string slot) { return Path.Combine(Paths.ConfigPath, "PregnancyMods.Bloodline." + slot + ".txt"); } private static void SyncSlot() { string text = Slot(); if (!(text == _loadedSlot)) { if (_loadedSlot != null) { SaveTo(_loadedSlot); } Entries.Clear(); _loadedSlot = text; LoadFrom(text); } } private static string Esc(string s) { return (s ?? "").Replace('\t', ' ').Replace('\n', ' ').Replace('\r', ' '); } internal static void Save() { if (_loadedSlot == null) { _loadedSlot = Slot(); } SaveTo(_loadedSlot); } private static void SaveTo(string slot) { try { StringBuilder stringBuilder = new StringBuilder(); foreach (BloodEntry entry in Entries) { stringBuilder.AppendLine(string.Join("\t", "v1", entry.Status, entry.Dir, entry.Shijia.ToString(), entry.MemberClass.ToString(), Esc(entry.MotherId), Esc(entry.MotherName), Esc(entry.FatherId), Esc(entry.FatherName), Esc(entry.Via), Esc(entry.Date), Esc(entry.ChildId), Esc(entry.ChildName), Esc(entry.ChildrenSnapshot))); } File.WriteAllText(FilePath(slot), stringBuilder.ToString()); } catch (Exception ex) { if (PregnancyModsPlugin.Log != null) { PregnancyModsPlugin.Log.LogWarning((object)("Bloodline save failed: " + ex.Message)); } } } internal static void LoadFrom(string slot) { try { string path = FilePath(slot); if (!File.Exists(path)) { return; } string[] array = File.ReadAllLines(path); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { '\t' }); if (array2.Length >= 14 && !(array2[0] != "v1") && int.TryParse(array2[3], out var result) && int.TryParse(array2[4], out var result2)) { Entries.Add(new BloodEntry { Status = array2[1], Dir = array2[2], Shijia = result, MemberClass = result2, MotherId = array2[5], MotherName = array2[6], FatherId = array2[7], FatherName = array2[8], Via = array2[9], Date = array2[10], ChildId = array2[11], ChildName = array2[12], ChildrenSnapshot = array2[13] }); } } } catch (Exception ex) { if (PregnancyModsPlugin.Log != null) { PregnancyModsPlugin.Log.LogWarning((object)("Bloodline load failed: " + ex.Message)); } } } } internal static class RoyalGuard { internal static string RepairKingClick(int memberClass, int cachedIndex, string memberId) { if (string.IsNullOrEmpty(memberId) || memberId == "null") { return null; } List> list; switch (memberClass) { case 0: list = Mainload.Member_King; break; case 1: list = Mainload.Member_King_qu; break; default: return null; } if (list == null) { return null; } if (cachedIndex >= 0 && cachedIndex < list.Count && list[cachedIndex] != null && list[cachedIndex].Count > 0 && list[cachedIndex][0] == memberId) { return null; } for (int i = 0; i < list.Count; i++) { if (list[i] != null && list[i].Count > 0 && list[i][0] == memberId) { return memberClass + "|" + i; } } return null; } internal static bool RowValid(int index, bool quList) { if (PregnancyModsPlugin.FixRoyalPanelCrash == null || !PregnancyModsPlugin.FixRoyalPanelCrash.Value) { return true; } try { List> list = (quList ? Mainload.Member_King_qu : Mainload.Member_King); if (list != null && index >= 0 && index < list.Count) { return true; } if (PregnancyModsPlugin.Log != null) { PregnancyModsPlugin.Log.LogWarning((object)("Blocked royal panel crash: stale index " + index + " into Member_King" + (quList ? "_qu" : "") + " (count " + (list?.Count ?? (-1)) + ")")); } return false; } catch { return true; } } } [HarmonyPatch(typeof(PerMemberKingQuPanel), "OnEnableData")] internal static class Patch_KingQuPanel_DataGuard { [HarmonyPrefix] private static bool Prefix(PerMemberKingQuPanel __instance) { return RoyalGuard.RowValid(__instance.MemberIndex, quList: true); } } [HarmonyPatch(typeof(PerMemberKingQuPanel), "OnEnableShow")] internal static class Patch_KingQuPanel_ShowGuard { [HarmonyPrefix] private static bool Prefix(PerMemberKingQuPanel __instance) { return RoyalGuard.RowValid(__instance.MemberIndex, quList: true); } } [HarmonyPatch(typeof(PerMemberKingPanel), "OnEnableData")] internal static class Patch_KingPanel_DataGuard { [HarmonyPrefix] private static bool Prefix(PerMemberKingPanel __instance) { return RoyalGuard.RowValid(__instance.MemberIndex, quList: false); } } [HarmonyPatch(typeof(PerMemberKingPanel), "OnEnableShow")] internal static class Patch_KingPanel_ShowGuard { [HarmonyPrefix] private static bool Prefix(PerMemberKingPanel __instance) { return RoyalGuard.RowValid(__instance.MemberIndex, quList: false); } } [HarmonyPatch(typeof(PerKMShow), "ClickBT")] internal static class Patch_PerKMShow_ClickFix { private static readonly FieldRef MemberIDRef = AccessTools.FieldRefAccess("MemberID"); [HarmonyPostfix] private static void Postfix(PerKMShow __instance) { try { if (PregnancyModsPlugin.FixRoyalPanelCrash == null || !PregnancyModsPlugin.FixRoyalPanelCrash.Value) { return; } string text = RoyalGuard.RepairKingClick(__instance.MemberClass, __instance.MemberIndex, MemberIDRef.Invoke(__instance)); if (text != null) { Mainload.KingClick = text; __instance.MemberIndex = int.Parse(text.Split(new char[1] { '|' })[1]); if (PregnancyModsPlugin.Log != null) { PregnancyModsPlugin.Log.LogInfo((object)("Repaired stale palace click -> KingClick=" + text)); } } } catch (Exception ex) { if (PregnancyModsPlugin.Log != null) { PregnancyModsPlugin.Log.LogWarning((object)("Palace click repair skipped: " + ex.Message)); } } } } [HarmonyPatch(typeof(FormulaData), "New_MemberNow")] internal static class Patch_NewMemberNow { private static int s_countBefore; internal static int Depth; private static readonly Random Rng = new Random(); [HarmonyPrefix] private static void Prefix(int __0, ref int __2) { Depth++; try { s_countBefore = ((Mainload.Member_now != null) ? Mainload.Member_now.Count : 0); } catch { s_countBefore = 0; } try { if (__2 == -1 && PregnancyModsPlugin.ModEnabled != null && PregnancyModsPlugin.ModEnabled.Value && PregnancyModsPlugin.GenderSelect != null) { switch (PregnancyModsPlugin.GenderSelect.Value) { case GenderMode.Boy: __2 = 1; break; case GenderMode.Girl: __2 = 0; break; case GenderMode.Custom: __2 = ((Rng.Next(100) < PregnancyModsPlugin.BoyPercent.Value) ? 1 : 0); break; } } } catch { } } [HarmonyPostfix] private static void Postfix(int __0, int __1, int __3) { int num = s_countBefore; try { Bloodline.OnNewMemberCreated(__0, __1, num); } catch { } try { if (Depth != 1 || (__0 != 0 && __0 != 2) || PregnancyModsPlugin.ModEnabled == null || !PregnancyModsPlugin.ModEnabled.Value || PregnancyModsPlugin.TwinsPercent == null) { return; } int value = PregnancyModsPlugin.TwinsPercent.Value; if (value <= 0) { return; } List> member_now = Mainload.Member_now; if (member_now == null || member_now.Count <= num || Rng.Next(100) >= value) { return; } int num2 = ((Rng.Next(100) >= PregnancyModsPlugin.TripletsPercent.Value) ? 1 : 2); for (int i = 0; i < num2; i++) { FormulaData.New_MemberNow(__0, __1, -1, Math.Max(1, __3), "null", "null", "null"); } if (PregnancyModsPlugin.BirthNotify != null && !PregnancyModsPlugin.BirthNotify.Value) { return; } string text = "?"; try { List> list = ((__0 == 2) ? Mainload.MenKe_Now : Mainload.Member_qu); if (list != null && __1 >= 0 && __1 < list.Count) { text = Bloodline.RowName(list[__1], 2); } } catch { } PregnancyModsPlugin.PushNotice(L.F((num2 == 2) ? "notify_triplets" : "notify_twins", text)); } catch (Exception ex) { if (PregnancyModsPlugin.Log != null) { PregnancyModsPlugin.Log.LogWarning((object)("Twins roll failed: " + ex.Message)); } } } [HarmonyFinalizer] private static void Finalizer() { if (Depth > 0) { Depth--; } } }