internal static void SaveDataCallNormalizePostfix(ref SaveData.CharaData charaData) { var orig = charaData.callName; try { if (Instance == null || Instance._matched.Contains(orig) || !TryGetReplacementsByPersonality(charaData.personality, out var replacements)) { return; } var nickParam = SaveData.WorldData.GetCallName(charaData); var key = Instance.TextResourceHelper.GetSpecializedKey(nickParam, nickParam.Name); if (!replacements.TryGetValue(key, out var translatedName)) { return; } charaData.callName = translatedName; Instance._matched.Add(translatedName); } catch (Exception err) { Logger.LogWarning($"{nameof(SaveDataCallNormalizePostfix)}: {err.Message}"); UnityEngine.Debug.LogException(err); } }
public static GameDialogHelperCharaController GetGameDialogHelperController(this SaveData.CharaData charaData) { GameDialogHelperCharaController controller = null; charaData.SafeProc(cd => cd.chaCtrl.SafeProcObject(cc => controller = cc.GetGameDialogHelperController())); return(controller); }
/// <summary> /// Mark character to reload next time their assigned ChaControl changes, so that any changes in function /// controller on previous chara can get propagated to controller on new chara /// todo limit this better to avoid unnecessary reloads? might not be an issue /// </summary> internal static bool SetDirty(SaveData.CharaData chara, bool dirty) { if (dirty && KKAPI.MainGame.GameAPI.GameBeingSaved) { return(false); } return(dirty ? _dirtyCharas.Add(chara) : _dirtyCharas.Remove(chara)); }
internal static IEnumerable <ChaFileControl> GetRelatedChaFiles(this SaveData.CharaData character) { var chafiles = character is SaveData.Heroine h ? KKAPI.MainGame.GameExtensions.GetRelatedChaFiles(h) : character is SaveData.Player p ? KKAPI.MainGame.GameExtensions.GetRelatedChaFiles(p) : null; return(chafiles); }
private static void OnChaCtrlChangePre(ChaControl value, SaveData.CharaData __instance, bool __state) { // Only reload if the chactrl actually changes. Reload in postfix just in case any plugin expects CharaData.chaCtrl to already be set if (__state) { if (_dirtyCharas.Remove(__instance)) { CharacterApi.ReloadChara(value); } } }
private static Exception CatchGetCallNameCrash(Exception __exception, SaveData.CharaData charaData, int id) { if (__exception != null) { if (!CheckPersonalityAndOverride(charaData.charFile)) { // If the personality does exist, the id will get auto reset even if we don't do anything Utilities.Logger.Log(LogLevel.Warning, $"Failed to get CallName for personality={charaData.personality} id={id}. Resetting it to default."); Utilities.Logger.LogWarning(__exception); } } return(null); }
public static void DenialOverride(SaveData.CharaData __instance, ref ChaFileParameter.Denial __result) { var currentCrest = (__instance as SaveData.Heroine)?.GetCurrentCrest(); if (currentCrest == CrestType.command) { __result = _noDenial; } else if (currentCrest == CrestType.suffer) { var newResult = new ChaFileParameter.Denial(); newResult.Copy(__result); newResult.aibu = true; newResult.anal = true; newResult.massage = true; __result = newResult; } }
public static PregnancyData GetPregnancyData(this SaveData.CharaData chara) { if (chara == null) { return(new PregnancyData()); } // Figure out which data to take if there are multiple // probably not necessary? null check should be enough? return(chara.GetRelatedChaFiles() .Select(GetPregnancyData) .Where(x => x != null) .OrderByDescending(x => x.PregnancyCount) .ThenByDescending(x => x.WeeksSinceLastPregnancy) .ThenByDescending(x => x.Week) .ThenByDescending(x => x.MenstruationSchedule) .ThenByDescending(x => x.GameplayEnabled) .FirstOrDefault() ?? new PregnancyData()); }
private static void PassportSetPostfix(Passport __instance, SaveData.CharaData charaData) { if (_instance == null || !_instance.Enabled) { return; } try { if (_instance.TryNameLookup(__instance._activity.text, out var tmpResult)) { __instance._activity.text = tmpResult; } } catch (Exception err) { TextResourceRedirector.Logger?.LogWarning( $"{nameof(PassportSetPostfix)}: Unexpected error: {err.Message}"); UnityEngine.Debug.LogException(err); } }
/// <summary> /// Enable/disable pregnancy icon /// </summary> private static void SetHeart(GameObject rootObj, SaveData.CharaData chara, bool classRoster) { var pregIconTr = rootObj.transform.Find(ICON_NAME); if (chara == null) { if (pregIconTr != null) { Destroy(pregIconTr.gameObject); } } else { if (pregIconTr == null) { pregIconTr = new GameObject(ICON_NAME, typeof(RectTransform), typeof(CanvasRenderer), typeof(Image)).transform; pregIconTr.SetParent(rootObj.transform, false); var rt = pregIconTr.GetComponent <RectTransform>(); if (classRoster) { rt.anchorMax = rt.anchorMin = rt.pivot = new Vector2(0, 1); rt.offsetMin = Vector2.zero; rt.offsetMax = new Vector2(48, 48); rt.localScale = Vector3.one; rt.localPosition = new Vector3(4, -115, 0); } else // status screen during roaming mode { rt.anchorMax = rt.anchorMin = rt.pivot = new Vector2(0.5f, 0.5f); rt.offsetMin = Vector2.zero; rt.offsetMax = new Vector2(48, 48); rt.localScale = Vector3.one; rt.localPosition = new Vector3(-273, -85, 0); } } AddPregIcon(pregIconTr, chara); } }
private static void AddPregIcon(Transform pregIconTransform, SaveData.CharaData chara) { var image = pregIconTransform.GetComponent <Image>(); _currentHeroine.Add(new KeyValuePair <SaveData.CharaData, RectTransform>(chara, image.GetComponent <RectTransform>())); var status = chara.GetCharaStatus(chara.GetPregnancyData()); switch (status) { case HeroineStatus.Unknown: image.sprite = _unknownSprite; break; case HeroineStatus.OnLeave: image.sprite = _leaveSprite; break; case HeroineStatus.Safe: image.sprite = _safeSprite; break; case HeroineStatus.Risky: image.sprite = _riskySprite; break; case HeroineStatus.Pregnant: image.sprite = _pregSprite; break; default: throw new ArgumentOutOfRangeException(); } pregIconTransform.gameObject.SetActiveIfDifferent(chara is SaveData.Heroine || status == HeroineStatus.Pregnant); }
public static Guid GetCharaGuid(this SaveData.CharaData charaData, int guidVersion = PluginDataInfo.CurrentCharaGuidVersion) { if (guidVersion > PluginDataInfo.MaxCharaGuidVersion) { throw new ArgumentOutOfRangeException(nameof(guidVersion), $"Unknown guidVersion ({guidVersion})"); } if (guidVersion < PluginDataInfo.MinimumSupportedCharaGuidVersion || charaData == null || !charaData.charFileInitialized) { return(Guid.Empty); } var guidKeyBuilder = StringBuilderPool.Get(); var intFmt = "{0:04}"; try { switch (guidVersion) { case 5: guidKeyBuilder .AppendFormat(intFmt, charaData is SaveData.Heroine heroine5 ? heroine5.FixCharaIDOrPersonality : charaData.personality) .Append('/') .AppendFormat(intFmt, charaData.schoolClass) .Append('/') .AppendFormat(intFmt, charaData.schoolClassIndex) .Append('/') .Append(charaData.Name); break; case 6: guidKeyBuilder .AppendFormat(intFmt, charaData is SaveData.Heroine heroine6 ? heroine6.FixCharaIDOrPersonality : charaData.personality) .Append('/') .AppendFormat(intFmt, charaData.schoolClass) .Append('/') .AppendFormat(intFmt, charaData.schoolClassIndex) .Append('/') .Append(charaData.firstname) .Append('/') .Append(charaData.lastname) .Append('/') .Append(charaData.parameter.sex); break; default: throw new ArgumentOutOfRangeException(nameof(guidVersion), $"Unsupported guidVersion ({guidVersion})"); } if (guidKeyBuilder.Length == 0) { return(Guid.Empty); } var guidKey = guidKeyBuilder.ToString(); var result = GuidCache.Get(guidKey); Logger?.DebugLogDebug( $"{nameof(GetCharaGuid)} (version={guidVersion}): guidKey={guidKey}, result={result}"); return(result); } finally { StringBuilderPool.Release(guidKeyBuilder); } }
public static void PersistData(this SaveData.CharaData charaData) { charaData.SafeProc(cd => cd.GetGameDialogHelperController().SafeProcObject(dhc => dhc.PersistToCard())); }
public static void StopPregnancy(SaveData.CharaData heroine) { _stoppedPregnancies.Add(heroine); }
private static void OnChaCtrlChangePre(ChaControl value, SaveData.CharaData __instance, out bool __state) { __state = value != __instance.chaCtrl; }
internal static void SetClassChara(SaveData.CharaData charaData) => CheckPersonalityAndOverride(charaData.charFile);
public static HeroineStatus GetHeroineStatus(this SaveData.CharaData chara, PregnancyData pregData = null) => GetCharaStatus(chara, pregData);
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); }
public CharaDialogMemory(SaveData.CharaData charaData) : this(charaData.GetCharaGuid()) { }