using System.Collections.Generic; using ShiroginSDK.Runtime.Modules.Data.Scripts; using ShiroginSDK.Runtime.Modules.Data.Scripts.Enums; using ShiroginSDK.Runtime.Modules.Events; using ShiroginSDK.Runtime.Modules.IAP.Enums; using ShiroginSDK.Runtime.Modules.IAP.Scripts.Definitions; using ShiroginSDK.Runtime.Services.Base; using ShiroginSDK.Runtime.Services.Interfaces; using UnityEngine; #if SHIROGIN_IAP using UnityEngine.Purchasing; #endif namespace ShiroginSDK.Runtime.Modules.IAP.Scripts.SO { #if SHIROGIN_IAP [CreateAssetMenu(fileName = "StoreItem", menuName = "ShiroginSDK/IAP/Store Item", order = 1)] public class StoreItem : ScriptableObject { [Header("๐Ÿงพ Product Info")] public string productId; public ProductType productType = ProductType.Consumable; public StoreCategory category = StoreCategory.UnknownPacks; public StoreItemLayoutType layoutType = StoreItemLayoutType.Default; [Header("๐Ÿ“‹ Display Info")] public string displayName; [TextArea] public string description; public Sprite icon; [Header("๐Ÿ’ฐ Purchase Settings")] public bool useCurrency; public CurrencyType currencyType = CurrencyType.Gems; public int price; public bool canBeRewardedAd; [Header("๐ŸŽ Reward Settings")] public List rewards = new(); public float adCooldownSeconds = 60f; public bool IsIAP => !useCurrency && !canBeRewardedAd; public bool IsCurrencyPurchase => useCurrency && price > 0; public bool IsRewardedAd => canBeRewardedAd; public void GiveReward(string source = "store") { foreach (var reward in rewards) { if (reward == null) continue; reward.Give(); } var dataService = ServiceLocator.Get(); var economy = dataService?.Get(); economy?.AddPurchase(); var eventService = ServiceLocator.Get(); eventService?.Invoke(new ShiroginEvents.Rewards.RewardGivenEvent(this)); Debug.Log($"[StoreItem] Rewards granted for '{productId}' via {source}"); } public void GiveRandomReward(int rewardCount = 3, string source = "store") { if (rewards == null || rewards.Count == 0) { Debug.LogWarning("[StoreItem] No rewards available."); return; } rewardCount = Mathf.Clamp(rewardCount, 1, rewards.Count); var randomRewards = new List(); var availableRewards = new List(rewards); for (var i = 0; i < rewardCount; i++) { if (availableRewards.Count == 0) break; var randomIndex = Random.Range(0, availableRewards.Count); var selected = availableRewards[randomIndex]; if (selected != null) { selected.Give(); randomRewards.Add(selected); } availableRewards.RemoveAt(randomIndex); } var dataService = ServiceLocator.Get(); var economy = dataService?.Get(); economy?.AddPurchase(); var eventService = ServiceLocator.Get(); eventService?.Invoke(new ShiroginEvents.Rewards.RewardGivenEvent(this)); eventService?.Invoke(new ShiroginEvents.Shop.Shop_UIStoreItem_Rewarded(randomRewards)); Debug.Log($"[StoreItem] {rewardCount} random rewards granted for '{productId}' via {source}"); foreach (var randomReward in randomRewards) Debug.Log($"[ehm] Given random reward: {randomReward.rewardType}"); } public List GetRewards() { return rewards; } public string GetDisplayPrice() { if (IsIAP) return "REAL MONEY"; if (IsCurrencyPurchase) return $"{price} {currencyType.ToString().ToUpper()}"; if (IsRewardedAd) return "WATCH AD"; return "FREE"; } public bool TryPurchaseWithCurrency() { if (!IsCurrencyPurchase) return false; var dataService = ServiceLocator.Get(); var economy = dataService?.Get(); if (economy == null) { Debug.LogError("[StoreItem] EconomyData not available."); return false; } if (!economy.HasEnough(currencyType, price)) { Debug.LogWarning($"[StoreItem] Not enough {currencyType} to buy '{displayName}'."); return false; } economy.SpendCurrency(currencyType, price); GiveReward("currency"); return true; } } #else [CreateAssetMenu(fileName = "StoreItem", menuName = "ShiroginSDK/IAP/Store Item", order = 1)] public class StoreItem : ScriptableObject { [Header("๐Ÿงพ Product Info")] public string productId; public DummyProductType productType = DummyProductType.Consumable; public StoreCategory category = StoreCategory.UnknownPacks; public StoreItemLayoutType layoutType = StoreItemLayoutType.Default; [Header("๐Ÿ“‹ Display Info")] public string displayName; [TextArea] public string description; public Sprite icon; [Header("๐Ÿ’ฐ Purchase Settings")] public bool useCurrency; public CurrencyType currencyType = CurrencyType.Gems; public int price; public bool canBeRewardedAd; [Header("๐ŸŽ Reward Settings")] public List rewards = new(); public float adCooldownSeconds = 60f; public bool IsIAP => !useCurrency && !canBeRewardedAd; public bool IsCurrencyPurchase => useCurrency && price > 0; public bool IsRewardedAd => canBeRewardedAd; public void GiveReward(string source = "store") { foreach (var reward in rewards) { if (reward == null) continue; reward.Give(); } var dataService = ServiceLocator.Get(); var economy = dataService?.Get(); economy?.AddPurchase(); var eventService = ServiceLocator.Get(); eventService?.Invoke(new ShiroginEvents.Rewards.RewardGivenEvent(this)); Debug.Log($"[StoreItem] Rewards granted for '{productId}' via {source}"); } public void GiveRandomReward(int rewardCount = 3, string source = "store") { if (rewards == null || rewards.Count == 0) { Debug.LogWarning("[StoreItem] No rewards available."); return; } rewardCount = Mathf.Clamp(rewardCount, 1, rewards.Count); var randomRewards = new List(); var availableRewards = new List(rewards); for (var i = 0; i < rewardCount; i++) { if (availableRewards.Count == 0) break; var randomIndex = Random.Range(0, availableRewards.Count); var selected = availableRewards[randomIndex]; if (selected != null) { selected.Give(); randomRewards.Add(selected); } availableRewards.RemoveAt(randomIndex); } var dataService = ServiceLocator.Get(); var economy = dataService?.Get(); economy?.AddPurchase(); var eventService = ServiceLocator.Get(); eventService?.Invoke(new ShiroginEvents.Rewards.RewardGivenEvent(this)); eventService?.Invoke(new ShiroginEvents.Shop.Shop_UIStoreItem_Rewarded(randomRewards)); Debug.Log($"[StoreItem] {rewardCount} random rewards granted for '{productId}' via {source}"); foreach (var randomReward in randomRewards) Debug.Log($"[ehm] Given random reward: {randomReward.rewardType}"); } public List GetRewards() { return rewards; } public string GetDisplayPrice() { if (IsIAP) return "REAL MONEY"; if (IsCurrencyPurchase) return $"{price} {currencyType.ToString().ToUpper()}"; if (IsRewardedAd) return "WATCH AD"; return "FREE"; } public bool TryPurchaseWithCurrency() { if (!IsCurrencyPurchase) return false; var dataService = ServiceLocator.Get(); var economy = dataService?.Get(); if (economy == null) { Debug.LogError("[StoreItem] EconomyData not available."); return false; } if (!economy.HasEnough(currencyType, price)) { Debug.LogWarning($"[StoreItem] Not enough {currencyType} to buy '{displayName}'."); return false; } economy.SpendCurrency(currencyType, price); GiveReward("currency"); return true; } } #endif }