private static void ApplyToAllDatas(Func<AgentData, PregnancyData, bool> action)
        {
            void ApplyToDatas(AgentData character)
                {
                    var chafiles = character.GetRelatedChaFiles();
                    if (chafiles == null) return;

                    foreach (var chaFile in chafiles)
                    {
                        var data = ExtendedSave.GetExtendedDataById(chaFile, PregnancyPlugin.GUID);
                        var pd = PregnancyData.Load(data) ?? new PregnancyData();
                        if (action(character, pd))
                            ExtendedSave.SetExtendedDataById(chaFile, PregnancyPlugin.GUID, pd.Save());
                    }
                }

                var heroineList = GetHeroineList();
                if (heroineList == null) return;

                foreach (var heroine in heroineList)
                {
                    ApplyToDatas(heroine);
                }
                // ApplyToDatas(Singleton<Map>.Instance.Player.AgentPartner.AgentData);  TODO find male AgentData, if we want to match what KK is now doing

                // If controller exists then update its state so it gets any pregnancy week updates
                foreach (var controller in FindObjectsOfType<PregnancyCharaController>())
                    controller.ReadData();
        }
            internal static void ExtendedCardLoad(ChaFile file)
            {
                Sideloader.Logger.LogDebug($"Loading card [{file.charaFileName}]");

                var extData = ExtendedSave.GetExtendedDataById(file, UARExtIDOld) ?? ExtendedSave.GetExtendedDataById(file, UARExtID);
                List <ResolveInfo> extInfo;

                if (extData == null || !extData.data.ContainsKey("info"))
                {
                    Sideloader.Logger.LogDebug("No sideloader marker found");
                    extInfo = null;
                }
                else
                {
                    var tmpExtInfo = (object[])extData.data["info"];
                    extInfo = tmpExtInfo.Select(x => ResolveInfo.Deserialize((byte[])x)).ToList();

                    Sideloader.Logger.LogDebug($"Sideloader marker found, external info count: {extInfo.Count}");

                    if (Sideloader.DebugLogging.Value)
                    {
                        foreach (ResolveInfo info in extInfo)
                        {
                            Sideloader.Logger.LogDebug($"External info: {info.GUID} : {info.Property} : {info.Slot}");
                        }
                    }
                }

                IterateCardPrefixes(ResolveStructure, file, extInfo);
            }
Beispiel #3
0
        public static void ChaFileCoordinateSaveFilePostHook(ChaFileCoordinate __instance, string path)
        {
            Logger.Log(LogLevel.Debug, $"Reloading coordinate [{path}]");

            var extData = ExtendedSave.GetExtendedDataById(__instance, UniversalAutoResolver.UARExtID);

            var tmpExtInfo = (List <byte[]>)extData.data["info"];
            var extInfo    = tmpExtInfo.Select(ResolveInfo.Unserialize);

            Logger.Log(LogLevel.Debug, $"External info count: {extInfo.Count()}");
            foreach (ResolveInfo info in extInfo)
            {
                Logger.Log(LogLevel.Debug, $"External info: {info.GUID} : {info.Property} : {info.Slot}");
            }

            void ResetStructResolveStructure(Dictionary <CategoryProperty, StructValue <int> > propertyDict, object structure, IEnumerable <ResolveInfo> extInfo2, string propertyPrefix = "")
            {
                foreach (var kv in propertyDict)
                {
                    var extResolve = extInfo.FirstOrDefault(x => x.Property == $"{propertyPrefix}{kv.Key.ToString()}");

                    if (extResolve != null)
                    {
                        kv.Value.SetMethod(structure, extResolve.LocalSlot);

                        Logger.Log(LogLevel.Debug, $"[UAR] Resetting {extResolve.GUID}:{extResolve.Property} to internal slot {extResolve.LocalSlot}");
                    }
                }
            }

            IterateCoordinatePrefixes(ResetStructResolveStructure, __instance, extInfo);
        }
        private static void AddPregnancyWeek(ChaFileControl chaFile)
        {
            var data = ExtendedSave.GetExtendedDataById(chaFile, PregnancyPlugin.GUID);

            if (data == null)
            {
                return;
            }

            PregnancyDataUtils.DeserializeData(data, out var week, out var gameplayEnabled, out var fertility, out var schedule);
            // Advance the week of pregnancy. If week is 0 the character is not pregnant
            if (gameplayEnabled && week > 0)
            {
                if (week < PregnancyDataUtils.LeaveSchoolWeek)
                {
                    // Advance through in-school at full configured speed
                    var weekChange = PregnancyPlugin.PregnancyProgressionSpeed.Value;
                    week = Mathf.Min(PregnancyDataUtils.LeaveSchoolWeek, week + weekChange);
                }
                else if (week < PregnancyDataUtils.ReturnToSchoolWeek)
                {
                    // Make sure at least one week is spent out of school
                    var weekChange = Mathf.Min(PregnancyDataUtils.ReturnToSchoolWeek - PregnancyDataUtils.LeaveSchoolWeek - 1, PregnancyPlugin.PregnancyProgressionSpeed.Value);
                    week = week + weekChange;
                }

                if (week >= PregnancyDataUtils.ReturnToSchoolWeek)
                {
                    week = 0;
                }

                //Logger.Log(LogLevel.Debug, $"Preg - pregnancy week for {chaFile.parameter.fullname} is now {week}");
                ExtendedSave.SetExtendedDataById(chaFile, PregnancyPlugin.GUID, PregnancyDataUtils.SerializeData(week, true, fertility, schedule));
            }
        }
Beispiel #5
0
        /// <summary>
        /// Attempt to import old KK_CharaOverlaysBasedOnCoordinate data.
        /// Based on code from https://github.com/jim60105/KK/blob/99dd9a055679cea8bf2c7d85a357ca53c4233636/KK_CharaOverlaysBasedOnCoordinate/KK_CharaOverlaysBasedOnCoordinate.cs
        /// </summary>
        private bool TryImportCOBOC()
        {
#if KK || KKS
            var data = ExtendedSave.GetExtendedDataById(ChaFileControl, "com.jim60105.kk.charaoverlaysbasedoncoordinate");
            if (data == null)
            {
                return(false);
            }

            KoiSkinOverlayMgr.Logger.LogInfo("[Import] Trying to import KK_CharaOverlaysBasedOnCoordinate data.");

            Dictionary <TKey, TValue> ToDictionary <TKey, TValue>(object self)
            {
                if (!(self is IDictionary dictionary))
                {
                    KoiSkinOverlayMgr.Logger.LogWarning($"[Import] Failed to cast to Dictionary! Likely invalid data.");
                    return(null);
                }

                return(CastDict(dictionary).ToDictionary(entry => (TKey)entry.Key, entry => (TValue)entry.Value));

                IEnumerable <DictionaryEntry> CastDict(IDictionary dic)
                {
                    foreach (DictionaryEntry entry in dic)
                    {
                        yield return(entry);
                    }
                }
            }

            if ((!data.data.TryGetValue("AllCharaOverlayTable", out var tmpOverlayTable) || tmpOverlayTable == null) ||
                (!data.data.TryGetValue("AllCharaResources", out var tmpResources) || null == tmpResources))
            {
                KoiSkinOverlayMgr.Logger.LogWarning("[Import] Wrong PluginData version, can't import.");
            }
        private static void ApplyToAllDatas(Func <SaveData.CharaData, PregnancyData, bool> action)
        {
            void ApplyToDatas(SaveData.CharaData character)
            {
                var chafiles = character.GetRelatedChaFiles();

                if (chafiles == null)
                {
                    return;
                }
                foreach (var chaFile in chafiles)
                {
                    var data = ExtendedSave.GetExtendedDataById(chaFile, PregnancyPlugin.GUID);
                    var pd   = PregnancyData.Load(data) ?? new PregnancyData();
                    if (action(character, pd))
                    {
                        ExtendedSave.SetExtendedDataById(chaFile, PregnancyPlugin.GUID, pd.Save());
                    }
                }
            }

            foreach (var heroine in Game.Instance.HeroineList)
            {
                ApplyToDatas(heroine);
            }
            ApplyToDatas(Game.Instance.Player);

            // If controller exists then update its state so it gets any pregnancy week updates
            foreach (var controller in FindObjectsOfType <PregnancyCharaController>())
            {
                controller.ReadData();
            }
        }
Beispiel #7
0
        /// <summary>
        /// Method to retrieve a list of BoneModifiers from a selected card in the maker, without loading a character.
        /// </summary>
        public static List <BoneModifier> GetBoneModifiersFromCard()
        {
            ChaFile             file      = Utilities.GetSelectedCharacter();
            PluginData          bonedata  = ExtendedSave.GetExtendedDataById(file, "KKABMPlugin.ABMData");
            List <BoneModifier> modifiers = new List <BoneModifier>();

            if (bonedata != null)
            {
                try
                {
                    switch (bonedata.version)
                    {
                    // Only support for version 2
                    case 2:
                        modifiers = LZ4MessagePackSerializer.Deserialize <List <BoneModifier> >((byte[])bonedata.data["boneData"]);
                        break;

                    default:
                        throw new NotSupportedException($"Save version {bonedata.version} is not supported");
                    }
                }
                catch (Exception ex)
                {
                    Logger.Log(LogLevel.Error, "[KK_Archetypes] Failed to load KKABMX extended data - " + ex);
                }
            }
            return(modifiers);
        }
Beispiel #8
0
            internal static void ExtendedHousingLoad(CraftInfo info)
            {
                if (info == null)
                {
                    return; // TODO: check if this case needs debug logging message.
                }
                if (Sideloader.DebugLoggingResolveInfo.Value)
                {
                    Sideloader.Logger.LogInfo($"Resolving Extended Save Game");
                }

                PluginData ExtendedData = ExtendedSave.GetExtendedDataById(info, UARExtID);

                if (ExtendedData != null)
                {
                    var ResolvedInfo = ((Dictionary <int, byte[]>)ExtendedData.data[mapItemInfoKey]);
                    int index        = 0;
                    HousingObjectIteration(info.ObjectInfos, ref index, (item, i) =>
                    {
                        if (!ResolvedInfo.TryGetValue(i, out byte[] bytes))
                        {
                            return;
                        }
                        var extResolve = AIGameResolveInfo.Deserialize(bytes);
                        if (extResolve == null)
                        {
                            return;
                        }
                        item.ID = extResolve.Slot;
                        ResolveHousingFurniture(extResolve, item);
                    });
Beispiel #9
0
        /// <summary>
        /// Card saving
        /// </summary>
        private void ExtendedCardSave(ChaFile file)
        {
            PluginData ExtendedData = ExtendedSave.GetExtendedDataById(file, "KK_FutaMod");

            if (ExtendedData != null && ExtendedData.data.ContainsKey("Futa"))
            {
                if (Singleton <CustomBase> .IsInstance() && Singleton <CustomBase> .Instance.chaCtrl != null)
                {
                    //Saving card from chara maker, get the status from the character
                    ExtendedData.data["Futa"] = file.status.visibleSonAlways;
                    ExtendedSave.SetExtendedDataById(file, "KK_FutaMod", ExtendedData);
                }
                else
                {
                    //Not in chara maker, keep the existing extended data
                    ExtendedSave.SetExtendedDataById(file, "KK_FutaMod", ExtendedData);
                }
            }
            else
            {
                if (Singleton <CustomBase> .IsInstance() && Singleton <CustomBase> .Instance.chaCtrl != null)
                {
                    //Saving a character in chara maker that doesn't have extended data
                    ExtendedData      = new PluginData();
                    ExtendedData.data = new Dictionary <string, object> {
                        { "Futa", file.status.visibleSonAlways }
                    };
                    ExtendedSave.SetExtendedDataById(file, "KK_FutaMod", ExtendedData);
                }
            }
        }
            internal static void ChaFileCoordinateSaveFilePostHook(ChaFileCoordinate __instance, string path)
            {
                if (DoingImport)
                {
                    return;
                }

                Sideloader.Logger.LogDebug($"Reloading coordinate [{path}]");

                var extData = ExtendedSave.GetExtendedDataById(__instance, UARExtIDOld) ?? ExtendedSave.GetExtendedDataById(__instance, UARExtID);

                var tmpExtInfo = (List <byte[]>)extData.data["info"];
                var extInfo    = tmpExtInfo.Select(ResolveInfo.Deserialize).ToList();

                Sideloader.Logger.LogDebug($"External info count: {extInfo.Count}");

                if (Sideloader.DebugLogging.Value)
                {
                    foreach (ResolveInfo info in extInfo)
                    {
                        Sideloader.Logger.LogDebug($"External info: {info.GUID} : {info.Property} : {info.Slot}");
                    }
                }

                void ResetStructResolveStructure(Dictionary <CategoryProperty, StructValue <int> > propertyDict, object structure, IEnumerable <ResolveInfo> extInfo2, string propertyPrefix = "")
                {
                    foreach (var kv in propertyDict)
                    {
                        var extResolve = extInfo.FirstOrDefault(x => x.Property == $"{propertyPrefix}{kv.Key.ToString()}");

                        if (extResolve != null)
                            kv.Value.SetMethod(structure, extResolve.LocalSlot); }
                    }
                }
Beispiel #11
0
            private static void ExtendedWorldLoad(WorldData worldData)
            {
                if (worldData == null)
                {
                    return;
                }

                var extResolve = ExtendedSave.GetExtendedDataById(worldData, UARExtID);

                if (extResolve == null)
                {
                    return;
                }

                foreach (var dataPair in extResolve.data)
                {
                    if (int.TryParse(dataPair.Key, out int id) &&
                        worldData.HousingData.CraftInfos.TryGetValue(id, out var craftInfo) &&
                        dataPair.Value is Dictionary <string, object> extData)
                    {
                        ExtendedSave.SetExtendedDataById(craftInfo, UARExtID, new PluginData()
                        {
                            data = extData
                        });
                        ExtendedHousingLoad(craftInfo);
                    }
                }
            }
Beispiel #12
0
        private static void ExtendedCardLoad(ChaFile file)
        {
            Logger.Log(LogLevel.Debug, $"Loading card [{file.charaFileName}]");

            var extData = ExtendedSave.GetExtendedDataById(file, UniversalAutoResolver.UARExtID);
            List <ResolveInfo> extInfo;

            if (extData == null || !extData.data.ContainsKey("info"))
            {
                Logger.Log(LogLevel.Debug, "No sideloader marker found");
                extInfo = null;
            }
            else
            {
                var tmpExtInfo = (object[])extData.data["info"];
                extInfo = tmpExtInfo.Select(x => ResolveInfo.Unserialize((byte[])x)).ToList();

                Logger.Log(LogLevel.Debug, "Sideloader marker found");
                Logger.Log(LogLevel.Debug, $"External info count: {extInfo.Count}");
                foreach (ResolveInfo info in extInfo)
                {
                    Logger.Log(LogLevel.Debug, $"External info: {info.GUID} : {info.Property} : {info.Slot}");
                }
            }

            IterateCardPrefixes(UniversalAutoResolver.ResolveStructure, file, extInfo);
        }
 /// <summary>
 /// Get extended data based on supplied ExtendedDataId. When in chara maker loads data from character that's being loaded.
 /// </summary>
 public PluginData GetExtendedData()
 {
     if (ExtendedDataId == null)
     {
         throw new ArgumentException(nameof(ExtendedDataId));
     }
     return(ExtendedSave.GetExtendedDataById(Manager.Game.Instance.saveData, ExtendedDataId));
 }
Beispiel #14
0
        public static void CopyChaFile(ChaFile dst, ChaFile src)
        {
            PluginData ExtendedData = ExtendedSave.GetExtendedDataById(src, "KK_FutaMod");

            if (ExtendedData != null && ExtendedData.data.ContainsKey("Futa"))
            {
                ExtendedSave.SetExtendedDataById(dst, "KK_FutaMod", ExtendedData);
            }
        }
Beispiel #15
0
        /// <summary>
        /// Get extended data of the current character by using the ID you specified when registering this controller.
        /// </summary>
        /// <param name="getFromLoadedChara">If true, when in chara maker load data from character that's being loaded.
        /// When outside maker or false, always grab current character's data.</param>
        public PluginData GetExtendedData(bool getFromLoadedChara)
        {
            if (ExtendedDataId == null)
            {
                throw new ArgumentException(nameof(ExtendedDataId));
            }
            var customParameter = getFromLoadedChara ? MakerAPI.LastLoadedChaFile ?? CustomParameterControl : CustomParameterControl; //todo

            return(ExtendedSave.GetExtendedDataById(customParameter, ExtendedDataId));
        }
        /// <summary>
        /// Get extended data of the current character by using the ID you specified when registering this controller.
        /// This should be used inside the <see cref="OnReload(KKAPI.GameMode,bool)"/> event.
        /// Consider using one of the other "Get___ExtData" and "Set___ExtData" methods instead since they are more reliable and handle copying and transferring outfits and they conform to built in maker load toggles.
        /// </summary>
        /// <param name="getFromLoadedChara">If true, when in chara maker load data from character that's being loaded.
        /// When outside maker or false, always grab current character's data.</param>
        public PluginData GetExtendedData(bool getFromLoadedChara)
        {
            if (ExtendedDataId == null)
            {
                throw new ArgumentException(nameof(ExtendedDataId));
            }
            var chaFile = getFromLoadedChara ? MakerAPI.LastLoadedChaFile ?? ChaFileControl : ChaFileControl;

            return(ExtendedSave.GetExtendedDataById(chaFile, ExtendedDataId));
        }
Beispiel #17
0
        public static void ChangeCharaPrefix(OCIChar __instance)
        {
            ChangeCharaVisibleState = true;
            PluginData ExtendedData = ExtendedSave.GetExtendedDataById(__instance.charInfo.chaFile, "KK_InvisibleBody");

            if (ExtendedData != null && (bool)ExtendedData.data["Visible"] == false)
            {
                //character is invisible, set it back to visible before the character is changed out
                ChangeCharaVisibleState = false;
                SetVisibleState(__instance.charInfo, forceVisible: true, forceVisibleState: true, saveVisibleState: false);
            }
        }
 /// <summary>
 /// Get extended data of the specified coordinate by using the ID you specified when registering this controller.
 /// This should be used inside the <see cref="OnCoordinateBeingLoaded(ChaFileCoordinate,bool)"/> event.
 /// Consider using one of the other "Get___ExtData" and "Set___ExtData" methods instead since they are more reliable and handle copying and transferring outfits and they conform to built in maker load toggles.
 /// </summary>
 /// <param name="coordinate">Coordinate you want to get the data from</param>
 public PluginData GetCoordinateExtendedData(ChaFileCoordinate coordinate)
 {
     if (coordinate == null)
     {
         throw new ArgumentNullException(nameof(coordinate));
     }
     if (ExtendedDataId == null)
     {
         throw new ArgumentException(nameof(ExtendedDataId));
     }
     return(ExtendedSave.GetExtendedDataById(coordinate, ExtendedDataId));
 }
        /// <summary>
        /// Register new functionality that will be automatically added to all characters (where applicable).
        /// Offers easy API for saving and loading extended data, and for running logic to apply it to the characters.
        /// All necessary hooking and event subscribing is done for you. All you have to do is create a type
        /// that inherits from <code>CharaExtraBehaviour</code> (don't make instances, the API will make them for you).
        /// </summary>
        /// <typeparam name="T">Type with your custom logic to add to a character</typeparam>
        /// <param name="extendedDataId">Extended data ID used by this behaviour. Set to null if not used. Needed to copy the data in some situations.</param>
        public static void RegisterExtraBehaviour <T>(string extendedDataId) where T : CharaCustomFunctionController, new()
        {
            void BasicCopier(ChaFile dst, ChaFile src)
            {
                var extendedData = ExtendedSave.GetExtendedDataById(src, extendedDataId);

                ExtendedSave.SetExtendedDataById(dst, extendedDataId, extendedData);
            }

            var copier = extendedDataId == null ? (CopyExtendedDataFunc)null : BasicCopier;

            RegisterExtraBehaviour <T>(extendedDataId, copier);
        }
            private static void GetMenstruationOverridePrefix()
            {
                if (_lastHeroine != null)
                {
                    // Get a schedule directly this way since the controller is not spawned in class roster
                    var schedule = _lastHeroine.GetRelatedChaFiles()
                                   .Select(c => PregnancyData.Load(ExtendedSave.GetExtendedDataById(c, GUID))?.MenstruationSchedule ?? MenstruationSchedule.Default)
                                   .FirstOrDefault(x => x != MenstruationSchedule.Default);

                    _menstruationsBackup = HFlag.menstruations;
                    HFlag.menstruations  = PregnancyCharaController.GetMenstruationsArr(schedule);
                }
            }
Beispiel #21
0
        public static void CreateChara(ChaControl __result, ChaFileControl _chaFile, byte _sex)
        {
            if (_sex == 0 || _chaFile == null)
            {
                return;
            }

            PluginData ExtendedData = ExtendedSave.GetExtendedDataById(_chaFile, "KK_FutaMod");

            if (ExtendedData != null && ExtendedData.data.ContainsKey("Futa"))
            {
                __result.chaFile.status.visibleSonAlways = (bool)ExtendedData.data["Futa"];
            }
        }
        private static void StartPregnancy(ChaFileControl chaFile)
        {
            var data = ExtendedSave.GetExtendedDataById(chaFile, PregnancyPlugin.GUID);

            PregnancyDataUtils.DeserializeData(data, out var week, out var gameplayEnabled, out var fertility, out var schedule);

            // If week is 0 the character is not pregnant
            if (gameplayEnabled && week <= 0)
            {
                //Logger.Log(LogLevel.Debug, "Preg - starting pregnancy on " + chaFile.parameter.fullname + ", new week is " + 1);

                ExtendedSave.SetExtendedDataById(chaFile, PregnancyPlugin.GUID, PregnancyDataUtils.SerializeData(1, true, fertility, schedule));
            }
        }
Beispiel #23
0
            private static bool CanGetSpawned(AgentActor heroine)
            {
                var isOnLeave = heroine.GetRelatedChaFiles()
                                .Any(c =>
                {
                    var pd = PregnancyData.Load(ExtendedSave.GetExtendedDataById(heroine.ChaControl.chaFile, GUID));
                    if (pd == null)
                    {
                        return(false);
                    }
                    return(pd.GameplayEnabled && pd.Week >= PregnancyData.LeaveSchoolWeek);
                });

                return(!isOnLeave);
            }
        private static bool LoadExtendedData_ver1(ParamCharaController controller)
        {
#if DEBUG
            BreastPhysicsController.Logger.LogDebug("Call LoadExtendedData_ver1");
#endif
            var chaFile  = MakerAPI.LastLoadedChaFile ?? controller.ChaFileControl;
            var dataVer1 = ExtendedSave.GetExtendedDataById(chaFile, ExtendedDataID_ver1);

            if (dataVer1 != null)
            {
#if DEBUG
                BreastPhysicsController.Logger.LogDebug("Found ver1 ExtendedData.");
#endif
                Compatibility.BreastDynamicBoneParameter paramVer1 = new Compatibility.BreastDynamicBoneParameter();
                var byteDBParams = new object();
                if (dataVer1.data.TryGetValue(ExtendedDataKey_ver1, out byteDBParams) && byteDBParams is byte[])
                {
                    if (paramVer1.SetParamByte((byte[])byteDBParams))
                    {
                        BreastPhysicsController.Logger.LogInfo("Loaded ver1 parameters from ExtendedData.");
                        if (paramVer1.CopyParamsTo(controller.paramCustom))
                        {
                            foreach (ParamBustCustom bust in controller.paramCustom.GetAllBustParameters())
                            {
                                bust.enabled = true;
                            }
                            controller.Enabled = true;

                            return(true);
                        }
                        else
                        {
#if DEBUG
                            BreastPhysicsController.Logger.LogDebug("Failed copy ver1 parameters to controller");
#endif
                        }
                    }
                    else
                    {
                        BreastPhysicsController.Logger.LogError("Loaded ver1 parameters from ExtendedData is invalid.");
                    }
                }
            }
#if DEBUG
            BreastPhysicsController.Logger.LogDebug("Not found ver1 plugin data.");
#endif
            return(false);
        }
        /// <param name="c">ChaFile to test</param>
        ///// <param name="afterWasDiscovered">The girl knows about it / tested it</param>
        public static PregnancyData GetPregnancyData(this ChaFileControl c)
        {
            if (c == null)
            {
                return(null);
            }

            var d = ExtendedSave.GetExtendedDataById(c, PregnancyPlugin.GUID);

            if (d == null)
            {
                return(null);
            }

            return(PregnancyData.Load(d));
        }
Beispiel #26
0
            internal static void ExtendedCardLoad(ChaFile file)
            {
                string cardName = file.charaFileName;

                if (cardName.IsNullOrEmpty())
                {
                    cardName = file.parameter?.fullname?.Trim();
                }
                Sideloader.Logger.LogDebug($"Loading card [{cardName}]");

                var extData = ExtendedSave.GetExtendedDataById(file, UARExtIDOld) ?? ExtendedSave.GetExtendedDataById(file, UARExtID);
                List <ResolveInfo> extInfo;

                if (extData == null || !extData.data.ContainsKey("info"))
                {
                    Sideloader.Logger.LogDebug("No sideloader marker found");
                    extInfo = null;
                }
                else
                {
                    var tmpExtInfo = (object[])extData.data["info"];
                    extInfo = tmpExtInfo.Select(x => ResolveInfo.Deserialize((byte[])x)).ToList();

                    Sideloader.Logger.LogDebug($"Sideloader marker found, external info count: {extInfo.Count}");

                    if (Sideloader.DebugLogging.Value)
                    {
                        foreach (ResolveInfo info in extInfo)
                        {
                            Sideloader.Logger.LogDebug($"External info: {info.GUID} : {info.Property} : {info.Slot}");
                        }
                    }
                }

                IterateCardPrefixes(ResolveStructure, file, extInfo);

#if AI || HS2
                //Resolve the bundleID to the same ID as the hair
                foreach (var hairPart in file.custom.hair.parts)
                {
                    if (hairPart.id > BaseSlotID)
                    {
                        hairPart.bundleId = hairPart.id;
                    }
                }
#endif
            }
Beispiel #27
0
        /// <param name="c">ChaFile to test</param>
        /// <param name="afterWasDiscovered">The girl knows about it / tested it</param>
        public static bool IsChaFilePregnant(this ChaFileControl c, bool afterWasDiscovered)
        {
            if (c == null)
            {
                return(false);
            }

            var d = ExtendedSave.GetExtendedDataById(c, PregnancyPlugin.GUID);

            if (d == null)
            {
                return(false);
            }

            DeserializeData(d, out var week, out _, out _, out _);
            return(afterWasDiscovered ? week > 1 : week > 0);
        }
Beispiel #28
0
        /// <summary>
        /// 從ExtendedData取得給定ChaControl的HairAccessories和單一hairAccessoryInfo
        /// </summary>
        /// <param name="chaCtrl">要查詢的ChaControl</param>
        /// <param name="nowcoordinateExtData">nowCoordinate的hairAccessoryInfo</param>
        /// <returns>整個HairAccessories</returns>
        public static Dictionary <int, object> GetDataFromCoordinate(ChaFileCoordinate coordinate)
        {
            Dictionary <int, object> nowcoordinateExtData;
            PluginData data = ExtendedSave.GetExtendedDataById(coordinate, GUID);

            if (data != null && data.data.TryGetValue("CoordinateHairAccessories", out object loadedHairAccessories) && loadedHairAccessories != null)
            {
                nowcoordinateExtData = MessagePackSerializer.Deserialize <Dictionary <int, object> >((byte[])loadedHairAccessories);
                if (null == nowcoordinateExtData)
                {
                    nowcoordinateExtData = new Dictionary <int, object>();
                }
                Logger.LogDebug($"Get Hair Accessories from coordinate {coordinate.coordinateName}: {nowcoordinateExtData.Count} (1)");
                Logger.LogDebug($"->{string.Join(",", nowcoordinateExtData.Select(x => x.Key.ToString()).ToArray())}");
                return(nowcoordinateExtData);
            }
            Logger.LogDebug($"No Hair Accessories get from coordinate {coordinate.coordinateFileName}");
            return(null);
        }
            private static void GetMenstruationOverridePrefix()
            {
                if (_lastHeroine != null)
                {
                    // Get a schedule directly this way since the controller is not spawned in class roster
                    var schedule = _lastHeroine.GetRelatedChaFiles().Select(control =>
                    {
                        var d = ExtendedSave.GetExtendedDataById(control, GUID);
                        if (d == null)
                        {
                            return(PregnancyDataUtils.MenstruationSchedule.Default);
                        }
                        PregnancyDataUtils.DeserializeData(d, out _, out _, out _, out var s);
                        return(s);
                    }).FirstOrDefault(x => x != PregnancyDataUtils.MenstruationSchedule.Default);

                    _menstruationsBackup = HFlag.menstruations;
                    HFlag.menstruations  = PregnancyCharaController.GetMenstruationsArr(schedule);
                }
            }
Beispiel #30
0
        public static void ResolveStructure(Dictionary <CategoryProperty, StructValue <int> > propertyDict, object structure, ChaFile save)
        {
            //BepInLogger.Log($"Tried to resolve structure: {structure.GetType().Name}");

            var extData = ExtendedSave.GetExtendedDataById(save, UARExtID);

            if (extData == null || !extData.data.ContainsKey("info"))
            {
                //BepInLogger.Log($"No info to load!");
                return;
            }

            var tmpExtInfo = (object[])extData.data["info"];
            var extInfo    = tmpExtInfo.Select(x => ResolveInfo.Unserialize((byte[])x));

            //BepInLogger.Log($"Internal info count: {LoadedResolutionInfo.Count}");
            //foreach (ResolveInfo info in LoadedResolutionInfo)
            //    BepInLogger.Log($"Internal info: {info.ModID} : {info.Property} : {info.Slot}");

            //BepInLogger.Log($"External info count: {extInfo.Count()}");
            //foreach (ResolveInfo info in extInfo)
            //    BepInLogger.Log($"External info: {info.ModID} : {info.Property} : {info.Slot}");


            foreach (var kv in propertyDict)
            {
                var extResolve = extInfo.FirstOrDefault(x => x.Property == kv.Key.ToString());

                if (extResolve != null)
                {
                    var intResolve = LoadedResolutionInfo.FirstOrDefault(x => x.CanResolve(extResolve));

                    if (intResolve != null)
                    {
                        BepInLogger.Log($"[UAR] Resolving {extResolve.ModID}:{extResolve.Property} from slot {extResolve.Slot} to slot {intResolve.LocalSlot}");

                        kv.Value.SetMethod(structure, intResolve.LocalSlot);
                    }
                }
            }
        }