From 8f090b73a5db0290e5c3d17ac7b70a118a182683 Mon Sep 17 00:00:00 2001 From: ManlyMarco <39247311+ManlyMarco@users.noreply.github.com> Date: Sat, 22 Jan 2022 02:15:54 +0100 Subject: [PATCH] [MSI] Add "Ero Detection App" store item --- src/KKS_MoreStoreItems/Extensions.cs | 6 ++ .../Features/EroDetectorFeat.cs | 76 +++++++++++++++++++ .../Features/TwinTalismanFeat.cs | 7 +- .../KKS_MoreShopItems.csproj | 26 +------ src/KKS_MoreStoreItems/MoreShopItemsPlugin.cs | 72 +++++++++--------- 5 files changed, 127 insertions(+), 60 deletions(-) create mode 100644 src/KKS_MoreStoreItems/Features/EroDetectorFeat.cs diff --git a/src/KKS_MoreStoreItems/Extensions.cs b/src/KKS_MoreStoreItems/Extensions.cs index c49d0aa..5734214 100644 --- a/src/KKS_MoreStoreItems/Extensions.cs +++ b/src/KKS_MoreStoreItems/Extensions.cs @@ -1,4 +1,5 @@ using System; +using HarmonyLib; using UniRx; namespace MoreShopItems @@ -10,5 +11,10 @@ public static void Add(this CompositeDisposable disp, UnityEngine.Object obj) if (disp == null) throw new ArgumentNullException(nameof(disp)); disp.Add(Disposable.Create(() => UnityEngine.Object.Destroy(obj))); } + public static void Add(this CompositeDisposable disp, Harmony hi) + { + if (disp == null) throw new ArgumentNullException(nameof(disp)); + disp.Add(Disposable.Create(() => hi?.UnpatchSelf())); + } } } diff --git a/src/KKS_MoreStoreItems/Features/EroDetectorFeat.cs b/src/KKS_MoreStoreItems/Features/EroDetectorFeat.cs new file mode 100644 index 0000000..ed52677 --- /dev/null +++ b/src/KKS_MoreStoreItems/Features/EroDetectorFeat.cs @@ -0,0 +1,76 @@ +using System; +using ActionGame; +using ActionGame.Chara; +using BepInEx.Configuration; +using Cysharp.Threading.Tasks; +using HarmonyLib; +using KKAPI.MainGame; +using KKAPI.Utilities; +using UniRx; + +namespace MoreShopItems.Features +{ + public class EroDetectorFeat : IFeature + { + private static ConfigEntry _notifyMast; + private static ConfigEntry _notifyLesb; + private static string _infoTextPrefix = "エロ活動:{0}"; + + public bool ApplyFeature(ref CompositeDisposable disp, MoreShopItemsPlugin inst) + { + const string itemName = "Ero Detection App"; + + disp.Add(StoreApi.RegisterShopItem( + itemId: MoreShopItemsPlugin.DetectorItemId, + itemName: itemName, + explaination: "A phone app that notifies you about erotic activities happening around the island. It's fully automatic and gives estimated locations.", + shopType: StoreApi.ShopType.NightOnly, + itemBackground: StoreApi.ShopBackground.Yellow, + itemCategory: 3, + stock: 1, + resetsDaily: false, + cost: 200, + sort: 500)); + + disp.Add(Harmony.CreateAndPatchAll(typeof(EroDetectorFeat))); + + _notifyMast = inst.Config.Bind(itemName, "Notification on masturbation", true, "If the item is purchased, show a notification whenever any NPC starts a masturbation action."); + _notifyLesb = inst.Config.Bind(itemName, "Notification on lesbian", true, "If the item is purchased, show a notification whenever any NPC starts a lesbian action."); + + TranslationHelper.TranslateAsync(_infoTextPrefix, s => _infoTextPrefix = s); + + return true; + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(Base), nameof(Base.wpData), MethodType.Setter)] + private static void WaitPointDataChangedHook(Base __instance, Base.WaitPointData value) + { + // wpData is null when the character is still walking to the current action location + if (value == null) return; + + if (__instance is NPC npc) + { + if (npc.isOnanism && _notifyMast.Value || npc.isLesbian && _notifyLesb.Value) + { + try + { + if (StoreApi.GetItemAmountBought(MoreShopItemsPlugin.DetectorItemId) > 0) + { + var mapNo = __instance.mapNo; + //if (ActionScene.initialized && ActionScene.instance.Player.mapNo != mapNo) + if (ActionScene.instance.Map.infoDic.TryGetValue(mapNo, out var param)) + { + InformationUI.SetAsync(string.Format(_infoTextPrefix, param.DisplayName), InformationUI.Mode.Normal).Forget(); + } + } + } + catch (Exception e) + { + UnityEngine.Debug.LogException(e); + } + } + } + } + } +} diff --git a/src/KKS_MoreStoreItems/Features/TwinTalismanFeat.cs b/src/KKS_MoreStoreItems/Features/TwinTalismanFeat.cs index 2a40719..41eef0a 100644 --- a/src/KKS_MoreStoreItems/Features/TwinTalismanFeat.cs +++ b/src/KKS_MoreStoreItems/Features/TwinTalismanFeat.cs @@ -16,10 +16,9 @@ public bool ApplyFeature(ref CompositeDisposable disp, MoreShopItemsPlugin inst) disp.Add(ico); - const int talismanItemId = 3456650; const int maxTalismansOwned = 2; disp.Add(StoreApi.RegisterShopItem( - itemId: talismanItemId, + itemId: MoreShopItemsPlugin.TalismanItemId, itemName: "Twin-making Talisman", explaination: "An old talisman that was allegedly used for conversing with spirits in the past. It can summon a fake twin of any living person that is experienced in sex. (One time use during H scenes)", shopType: StoreApi.ShopType.NightOnly, @@ -39,7 +38,7 @@ public bool ApplyFeature(ref CompositeDisposable disp, MoreShopItemsPlugin inst) && !flags.isFreeH // 3P is only available for experienced or horny && flags.lstHeroine[0].HExperience >= Heroine.HExperienceKind.慣れ - && StoreApi.GetItemAmountBought(talismanItemId) > 0 + && StoreApi.GetItemAmountBought(MoreShopItemsPlugin.TalismanItemId) > 0 // Only enable if not coming from a peeping H scene, because trying to start 3P in that state just ends the H scene && GameObject.FindObjectOfType().dataH.peepCategory.Count == 0; }, @@ -75,7 +74,7 @@ public bool ApplyFeature(ref CompositeDisposable disp, MoreShopItemsPlugin inst) if (asi) asi.ShortcutKeyEnable(false); // Eat one of the held items - StoreApi.DecreaseItemAmountBought(talismanItemId); + StoreApi.DecreaseItemAmountBought(MoreShopItemsPlugin.TalismanItemId); })); return true; diff --git a/src/KKS_MoreStoreItems/KKS_MoreShopItems.csproj b/src/KKS_MoreStoreItems/KKS_MoreShopItems.csproj index 7f0bc30..c8ed04d 100644 --- a/src/KKS_MoreStoreItems/KKS_MoreShopItems.csproj +++ b/src/KKS_MoreStoreItems/KKS_MoreShopItems.csproj @@ -19,7 +19,7 @@ true embedded false - ..\..\bin\BepInEx\plugins\ + F:\Games\KKS\BepInEx\scripts\ TRACE;DEBUG;KKS prompt 4 @@ -66,12 +66,6 @@ - - - - - - ..\packages\IllusionLibs.KoikatsuSunshine.UniRx.2021.9.17\lib\net46\UniRx.dll False @@ -80,22 +74,10 @@ ..\packages\IllusionLibs.KoikatsuSunshine.UniTask.2021.9.17\lib\net46\UniTask.dll False - - ..\packages\IllusionLibs.KoikatsuSunshine.UniTask.2021.9.17\lib\net46\UniTask.Addressables.dll - False - ..\packages\IllusionLibs.KoikatsuSunshine.UniTask.2021.9.17\lib\net46\UniTask.DOTween.dll False - - ..\packages\IllusionLibs.KoikatsuSunshine.UniTask.2021.9.17\lib\net46\UniTask.Linq.dll - False - - - ..\packages\IllusionLibs.KoikatsuSunshine.UniTask.2021.9.17\lib\net46\UniTask.TextMeshPro.dll - False - ..\packages\IllusionLibs.KoikatsuSunshine.UnityEngine.CoreModule.2019.4.9\lib\net46\UnityEngine.dll False @@ -123,17 +105,17 @@ + - + - - + diff --git a/src/KKS_MoreStoreItems/MoreShopItemsPlugin.cs b/src/KKS_MoreStoreItems/MoreShopItemsPlugin.cs index a367a6a..b3f14e8 100644 --- a/src/KKS_MoreStoreItems/MoreShopItemsPlugin.cs +++ b/src/KKS_MoreStoreItems/MoreShopItemsPlugin.cs @@ -17,15 +17,19 @@ public class MoreShopItemsPlugin : BaseUnityPlugin public const string GUID = "MoreShopItems"; public const string Version = "1.0"; - internal static new ManualLogSource Logger; + internal const int DetectorItemId = 3456651; + internal const int TalismanItemId = 3456650; - private static IDisposable _featureCleanup; + internal static new ManualLogSource Logger; private void Awake() { Logger = base.Logger; - _featureCleanup = LoadFeatures(); + var cleanup = LoadFeatures(); +#if DEBUG + cleanup.AddTo(this); +#endif } /// @@ -33,48 +37,48 @@ private void Awake() /// private IDisposable LoadFeatures() { - var loadedList = new StringBuilder("Loaded features: "); var cleanupList = new CompositeDisposable(); - var interfaceT = typeof(IFeature); - var ourAss = typeof(MoreShopItemsPlugin).Assembly; - foreach (var featType in ourAss.GetTypes().Where(x => !x.IsAbstract && x.IsClass && interfaceT.IsAssignableFrom(x))) + try { - var disp = new CompositeDisposable(); - try + var loadedList = new StringBuilder("Loaded features: "); + var interfaceT = typeof(IFeature); + var ourAss = typeof(MoreShopItemsPlugin).Assembly; + foreach (var featType in ourAss.GetTypes().Where(x => !x.IsAbstract && x.IsClass && interfaceT.IsAssignableFrom(x))) { - var i = (IFeature)Activator.CreateInstance(featType); - if (i.ApplyFeature(ref disp, this)) + var disp = new CompositeDisposable(); + try { - cleanupList.Add(disp); - disp = new CompositeDisposable(); - loadedList.Append(featType.Name); - loadedList.Append(" "); + var i = (IFeature)Activator.CreateInstance(featType); + if (i.ApplyFeature(ref disp, this)) + { + cleanupList.Add(disp); + disp = new CompositeDisposable(); + loadedList.Append(featType.Name); + loadedList.Append(" "); + } + else + { + disp.Clear(); + } } - else + catch (Exception e) { + disp.Dispose(); disp.Clear(); - } - } - catch (Exception e) - { - disp.Dispose(); - disp.Clear(); - Logger.LogWarning($"Failed to load feature {featType.FullName} with exception: " + e); + Logger.LogWarning($"Failed to load feature {featType.FullName} with exception: " + e); + } } - } - Logger.LogInfo(loadedList.ToString()); + Logger.LogInfo(loadedList.ToString()); - return cleanupList; - } - -#if DEBUG - private void OnDestroy() - { - _featureCleanup?.Dispose(); - _featureCleanup = null; + return cleanupList; + } + catch + { + cleanupList.Dispose(); + throw; + } } -#endif } }