using System; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.UI; using Bansonic; #if UNITY_EDITOR using UnityEditor; #endif public class equipSmelt : MonoBehaviour { private static readonly List SmeltPoolEquipments = new List(); private static readonly HashSet SmeltPoolLookup = new HashSet(); private static readonly HashSet ConsumedSmeltEquipmentIds = new HashSet(StringComparer.Ordinal); private static readonly HashSet ConsumedSmeltEquipments = new HashSet(); private const string SmeltStatePrefsKey = "equip_smelt_state_v1"; private static bool persistenceLoaded; private static readonly List Instances = new List(); private static bool isSmeltingState; private static bool smeltCompletedState; private static int gamesRequiredForCurrentBatchState; private static int gamesCompletedForCurrentBatchState; private static int pendingDirectFragmentsState; private static int pendingStoredFragmentsState; private static int storedSmeltEnergyState; [Serializable] private sealed class SmeltPersistentState { public bool isSmelting; public bool smeltCompleted; public int gamesRequired; public int gamesCompleted; public int pendingDirectFragments; public int pendingStoredFragments; public int storedSmeltEnergy; public string[] consumedEquipmentIds; } [Header("so")] public smeltStageRewardSO ssrso; [Header("sprites")] public Sprite memoryFragment; public Sprite coins; [Header("selection and progress")] public GameObject smeltPool; public GameObject smeltProgress; [Header("drag")] public GameObject dragObj; [Header("smeltPool")] public GameObject smeltPoolItemPrefab; public Transform smeltPoolContent; [Header("smeltTimeProgress")] public Slider stpSlider; public Text smeltStatusText; public Button quickFinishButton; public Text qf_cost_text; [Header("smelt Rewards")] public Text rewardGenProgress; public Image rewardProgressImage; public Dropdown selectAReward; public Button getReward; [Header("smelt notice")] public Image d_mf_img; public Text d_mf_Amount; public Image s_mf_img; public Text s_mf_Amount; public Text smeltNoticeText; [Header("cost and start")] public Text costText; public Text reasonWhy; public Button startSmeltButton; [Header("choose type and skill")] public GameObject ctasPrefab; public Transform ctasParent; private readonly List spawnedPoolItems = new List(); private GameObject activeCtasInstance; private void Awake() { EnsurePersistentStateLoaded(); RegisterInstance(); BindButtons(); RefreshAllUi(); } private void OnEnable() { RegisterInstance(); BindButtons(); RefreshAllUi(); } private void OnDisable() { CloseActiveCtas(); Instances.Remove(this); } private void OnDestroy() { CloseActiveCtas(); Instances.Remove(this); } public static bool IsEquipmentAssignedToSmeltPool(equipmentSO equipment) { EnsurePersistentStateLoaded(); return equipment != null && SmeltPoolLookup.Contains(equipment); } public static bool IsEquipmentConsumedBySmelt(equipmentSO equipment) { EnsurePersistentStateLoaded(); return equipment != null && ConsumedSmeltEquipments.Contains(equipment); } public static bool ShouldHideConsumedEquipment(equipmentSO equipment) { EnsurePersistentStateLoaded(); return equipment != null && (ConsumedSmeltEquipments.Contains(equipment) || (!string.IsNullOrWhiteSpace(equipment.name) && ConsumedSmeltEquipmentIds.Contains(equipment.name))); } public static bool RemoveEquipmentFromSmeltPool(equipmentSO equipment) { EnsurePersistentStateLoaded(); if (equipment == null) { return false; } if (!SmeltPoolLookup.Remove(equipment)) { return false; } SmeltPoolEquipments.Remove(equipment); SavePersistentState(); RefreshAllSmeltPools(); RefreshAllEquipBags(); return true; } public static bool TryHandleQuickTransfer(equipmentSO equipment) { EnsurePersistentStateLoaded(); if (equipment == null || IsEquipmentConsumedBySmelt(equipment)) { return false; } equipSmelt activeSmelt = GetActivePoolInstance(); if (activeSmelt == null) { return false; } if (IsEquipmentAssignedToSmeltPool(equipment)) { return RemoveEquipmentFromSmeltPool(equipment); } activeSmelt.AcceptDraggedEquipment(equipment); return IsEquipmentAssignedToSmeltPool(equipment); } public static void ReinstateRewardEquipment(equipmentSO equipment) { EnsurePersistentStateLoaded(); if (equipment == null) { return; } ConsumedSmeltEquipments.Remove(equipment); if (!string.IsNullOrWhiteSpace(equipment.name)) { ConsumedSmeltEquipmentIds.Remove(equipment.name); } SavePersistentState(); } public void RefreshPlayerSkillAdjustedUi() { RefreshAllUi(); } public void SetDragPreviewVisible(bool visible) { if (dragObj == null) { return; } if (!IsPoolOpenForTransfers()) { dragObj.SetActive(false); return; } bool shouldShow = visible || SmeltPoolEquipments.Count == 0; dragObj.SetActive(shouldShow); } public bool IsPointerOverDropArea(Vector2 screenPoint, Camera eventCamera) { if (dragObj == null || !dragObj.activeInHierarchy || !IsPoolOpenForTransfers()) { return false; } RectTransform[] rects = dragObj.GetComponentsInChildren(true); if (rects == null || rects.Length == 0) { return false; } for (int i = 0; i < rects.Length; i++) { RectTransform rect = rects[i]; if (rect == null || !rect.gameObject.activeInHierarchy) { continue; } if (RectTransformUtility.RectangleContainsScreenPoint(rect, screenPoint, eventCamera)) { return true; } } return false; } public void AcceptDraggedEquipment(equipmentSO equipment) { EnsurePersistentStateLoaded(); if (equipment == null || IsEquipmentConsumedBySmelt(equipment) || !IsPoolOpenForTransfers()) { return; } int capacity = GetSmeltEquipmentCapacity(); if (capacity <= 0 || SmeltPoolEquipments.Count >= capacity) { return; } if (SmeltPoolLookup.Add(equipment)) { SmeltPoolEquipments.Add(equipment); SavePersistentState(); RefreshAllUi(); RefreshAllEquipBags(); } } private void BindButtons() { if (startSmeltButton != null) { startSmeltButton.onClick.RemoveListener(HandleStartSmeltClicked); startSmeltButton.onClick.AddListener(HandleStartSmeltClicked); } if (quickFinishButton != null) { quickFinishButton.onClick.RemoveListener(HandleQuickFinishClicked); quickFinishButton.onClick.AddListener(HandleQuickFinishClicked); } if (getReward != null) { getReward.onClick.RemoveListener(HandleGetRewardClicked); getReward.onClick.AddListener(HandleGetRewardClicked); } if (selectAReward != null) { selectAReward.onValueChanged.RemoveListener(HandleRewardSelectionChanged); selectAReward.onValueChanged.AddListener(HandleRewardSelectionChanged); } } private void HandleStartSmeltClicked() { if (smeltCompletedState) { ClaimCurrentBatchRewards(); return; } if (isSmeltingState || SmeltPoolEquipments.Count <= 0) { return; } int startCost = GetStartSmeltCost(); if (!PlayerEconomyLedger.EnsureInstance().TrySpendCoins(startCost)) { RefreshAllUi(); return; } isSmeltingState = true; smeltCompletedState = false; gamesCompletedForCurrentBatchState = 0; gamesRequiredForCurrentBatchState = Mathf.Max(1, Mathf.CeilToInt(SmeltPoolEquipments.Count / 20f)); int totalFragments = CalculateTotalFragmentsForCurrentPool(); pendingDirectFragmentsState = Mathf.FloorToInt(totalFragments * 0.7f); pendingStoredFragmentsState = Mathf.Max(0, totalFragments - pendingDirectFragmentsState); ConsumeCurrentPoolEquipments(); SavePersistentState(); RefreshAllUi(); RefreshAllEquipBags(); } private void HandleQuickFinishClicked() { if (!isSmeltingState || smeltCompletedState) { return; } int cost = GetQuickFinishCost(); if (!PlayerEconomyLedger.EnsureInstance().TrySpendCoins(cost)) { return; } gamesCompletedForCurrentBatchState = gamesRequiredForCurrentBatchState; smeltCompletedState = true; SavePersistentState(); RefreshAllUi(); } public static void NotifySettlementCompleted() { if (!isSmeltingState || smeltCompletedState) { return; } if (GameConfig.autoPlayEnabled) { return; } gamesCompletedForCurrentBatchState = Mathf.Min(gamesRequiredForCurrentBatchState, gamesCompletedForCurrentBatchState + 1); if (gamesCompletedForCurrentBatchState >= gamesRequiredForCurrentBatchState) { smeltCompletedState = true; ClaimCurrentBatchRewardsStatic(); return; } SavePersistentState(); RefreshAllSmeltPools(); } private void ClaimCurrentBatchRewards() { ClaimCurrentBatchRewardsStatic(); } private static void ClaimCurrentBatchRewardsStatic() { if (!smeltCompletedState) { return; } int grantedFragments = Mathf.Max(0, pendingDirectFragmentsState); if (pendingDirectFragmentsState > 0) { PlayerEconomyLedger.EnsureInstance().AddMaterial(pendingDirectFragmentsState); } storedSmeltEnergyState = Mathf.Clamp(storedSmeltEnergyState + pendingStoredFragmentsState, 0, GetSmeltStorageCapacityStatic()); pendingDirectFragmentsState = 0; pendingStoredFragmentsState = 0; gamesRequiredForCurrentBatchState = 0; gamesCompletedForCurrentBatchState = 0; isSmeltingState = false; smeltCompletedState = false; SavePersistentState(); RefreshAllSmeltPools(); RefreshAllEquipBags(); if (grantedFragments > 0) { gItemGet.display(gItemGet.Create("记忆碎片", ResolveMemoryFragmentSprite(), grantedFragments, ItemRarity.Uncommon)); } } private void HandleGetRewardClicked() { smeltStageRewardSO.SmeltStageRewardRequirement requirement = GetSelectedRewardRequirement(); if (requirement == null) { return; } int requiredAmount = Mathf.Max(0, requirement.requiredAmount); if (requiredAmount > storedSmeltEnergyState) { return; } if (RequiresRewardSelection(requirement)) { OpenRewardSelector(requirement); return; } GrantReward(requirement, null, 0); } private void HandleRewardSelectionChanged(int _) { RefreshButtons(); } private bool RequiresRewardSelection(smeltStageRewardSO.SmeltStageRewardRequirement requirement) { if (requirement == null) { return false; } return RequiresTypeSelection(requirement) || RequiresSkillSelection(requirement); } private bool RequiresTypeSelection(smeltStageRewardSO.SmeltStageRewardRequirement requirement) { if (requirement == null) { return false; } if (requirement.equipmentType == smeltStageRewardSO.equipType.selfChosenType) { return true; } return !string.IsNullOrWhiteSpace(requirement.equipRewardName) && requirement.equipRewardName.Contains("自选", StringComparison.Ordinal); } private bool RequiresSkillSelection(smeltStageRewardSO.SmeltStageRewardRequirement requirement) { return requirement != null && requirement.skillRequirement == smeltStageRewardSO.skillOwned.selfChosen; } private void OpenRewardSelector(smeltStageRewardSO.SmeltStageRewardRequirement requirement) { if (ctasPrefab == null || ctasParent == null || ssrso == null || ssrso.rewardRandomConfig == null) { return; } CloseActiveCtas(); GameObject instance = Instantiate(ctasPrefab, ctasParent); activeCtasInstance = instance; global::ctasPrefab selector = instance.GetComponent(); if (selector == null) { return; } equipmentSO selectionTemplate = ssrso.rewardTemplate != null ? UnityEngine.Object.Instantiate(ssrso.rewardTemplate) : ScriptableObject.CreateInstance(); selectionTemplate.hideFlags = HideFlags.DontSave; selectionTemplate.sa_skillID = 0; selectionTemplate.ia_skillID = 0; bool requireTypeSelection = RequiresTypeSelection(requirement); bool requireSkillSelection = RequiresSkillSelection(requirement); if (requireTypeSelection) { selectionTemplate.skillType = requirement.chosenSkillType; } selector.Initialize( selectionTemplate, ssrso.rewardRandomConfig, requireTypeSelection, requireSkillSelection, (selectedType, selectedSkillGroupId) => HandleRewardSelectionConfirmed(requirement, selectedType, selectedSkillGroupId), HandleRewardSelectorClosed); } private void HandleRewardSelectionConfirmed(smeltStageRewardSO.SmeltStageRewardRequirement requirement, equipmentSO.EquipmentSkillType selectedType, int selectedSkillGroupId) { activeCtasInstance = null; GrantReward(requirement, selectedType, selectedSkillGroupId); } private void GrantReward(smeltStageRewardSO.SmeltStageRewardRequirement requirement, equipmentSO.EquipmentSkillType? selectedTypeOverride, int selectedSkillGroupId) { if (requirement == null) { return; } int requiredAmount = Mathf.Max(0, requirement.requiredAmount); if (requiredAmount > storedSmeltEnergyState) { return; } equipmentSO generated = equipmentGenerator.GenerateFromSmeltReward(ssrso, requirement, selectedTypeOverride, selectedSkillGroupId); if (generated == null) { return; } ReinstateRewardEquipment(generated); storedSmeltEnergyState = Mathf.Max(0, storedSmeltEnergyState - requiredAmount); SavePersistentState(); gItemGet.display(gItemGet.FromEquipment(generated, 1)); RefreshAllUi(); RefreshAllEquipBags(); } private static Sprite ResolveMemoryFragmentSprite() { equipSmelt[] instances = FindObjectsByType(FindObjectsInactive.Include, FindObjectsSortMode.None); if (instances == null) { return null; } for (int i = 0; i < instances.Length; i++) { if (instances[i] != null && instances[i].memoryFragment != null) { return instances[i].memoryFragment; } } return null; } private void HandleRewardSelectorClosed() { activeCtasInstance = null; RefreshButtons(); } private void CloseActiveCtas() { if (activeCtasInstance != null) { Destroy(activeCtasInstance); activeCtasInstance = null; } } private void ConsumeCurrentPoolEquipments() { if (SmeltPoolEquipments.Count == 0) { return; } for (int i = 0; i < SmeltPoolEquipments.Count; i++) { equipmentSO equipment = SmeltPoolEquipments[i]; if (equipment == null) { continue; } ConsumedSmeltEquipments.Add(equipment); if (!string.IsNullOrWhiteSpace(equipment.name)) { ConsumedSmeltEquipmentIds.Add(equipment.name); } #if UNITY_EDITOR string assetPath = AssetDatabase.GetAssetPath(equipment); if (!string.IsNullOrWhiteSpace(assetPath) && assetPath.StartsWith("Assets/Resources/so/uEquip/", StringComparison.OrdinalIgnoreCase)) { AssetDatabase.DeleteAsset(assetPath); } #endif } SmeltPoolEquipments.Clear(); SmeltPoolLookup.Clear(); #if UNITY_EDITOR AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); #endif SavePersistentState(); } private void RefreshAllUi() { ApplySmeltViewState(); RebuildSmeltPool(); RefreshRewardPreview(); RefreshStoredEnergyDisplay(); RefreshRewardDropdown(); RefreshProgressDisplay(); RefreshButtons(); RefreshReasonWhy(); } private void ApplySmeltViewState() { if (smeltPool != null) { smeltPool.SetActive(!isSmeltingState); } if (smeltProgress != null) { smeltProgress.SetActive(isSmeltingState); } SetDragPreviewVisible(false); } private bool IsPoolOpenForTransfers() { return gameObject.activeInHierarchy && smeltPool != null && smeltPool.activeInHierarchy && !isSmeltingState; } private void RebuildSmeltPool() { ClearSmeltPoolItems(); if (smeltPoolItemPrefab == null || smeltPoolContent == null) { SetDragPreviewVisible(false); return; } for (int i = 0; i < SmeltPoolEquipments.Count; i++) { equipmentSO equipment = SmeltPoolEquipments[i]; if (equipment == null) { continue; } GameObject instance = Instantiate(smeltPoolItemPrefab, smeltPoolContent); instance.name = string.IsNullOrWhiteSpace(equipment.GetCurrentTierDisplayName()) ? equipment.name : equipment.GetCurrentTierDisplayName(); instance.SetActive(true); spawnedPoolItems.Add(instance); equipItemPrefab item = instance.GetComponent(); if (item != null) { item.Bind(equipment); } } int placeholderToSpawn = Mathf.Max(0, GetSmeltEquipmentCapacity() - SmeltPoolEquipments.Count); for (int i = 0; i < placeholderToSpawn; i++) { GameObject instance = Instantiate(smeltPoolItemPrefab, smeltPoolContent); instance.name = $"SmeltPlaceholder_{i:00}"; instance.SetActive(true); spawnedPoolItems.Add(instance); equipItemPrefab item = instance.GetComponent(); if (item != null) { item.Bind(null); if (item.itemButton != null) { item.itemButton.interactable = false; } } } SetDragPreviewVisible(false); } private void RefreshRewardPreview() { bool useLockedBatchReward = isSmeltingState || smeltCompletedState; int directReward; int savedReward; if (useLockedBatchReward) { directReward = Mathf.Max(0, pendingDirectFragmentsState); savedReward = Mathf.Max(0, pendingStoredFragmentsState); } else { int totalFragments = CalculateTotalFragmentsForCurrentPool(); directReward = Mathf.FloorToInt(totalFragments * 0.7f); savedReward = Mathf.Max(0, totalFragments - directReward); } if (d_mf_Amount != null) { d_mf_Amount.text = directReward.ToString(); } if (s_mf_Amount != null) { s_mf_Amount.text = savedReward.ToString(); } } private void RefreshProgressDisplay() { if (costText != null) { costText.text = GetStartSmeltCost().ToString(); } if (qf_cost_text != null) { qf_cost_text.text = GetQuickFinishCost().ToString(); } if (stpSlider != null) { int required = Mathf.Max(1, gamesRequiredForCurrentBatchState); stpSlider.minValue = 0f; stpSlider.maxValue = required; stpSlider.value = Mathf.Clamp(gamesCompletedForCurrentBatchState, 0, required); Text sliderText = stpSlider.GetComponentInChildren(true); if (sliderText != null) { sliderText.text = $"融合进度{Mathf.Clamp(gamesCompletedForCurrentBatchState, 0, required)}/{required}"; } } if (smeltStatusText != null) { if (!isSmeltingState) { smeltStatusText.text = string.Empty; } else if (smeltCompletedState) { smeltStatusText.text = "融合完毕,可以收获结果"; } else { int remain = Mathf.Max(0, gamesRequiredForCurrentBatchState - gamesCompletedForCurrentBatchState); smeltStatusText.text = $"正在融合,还需{remain}场比赛"; } } } private void RefreshStoredEnergyDisplay() { int capacity = GetSmeltStorageCapacity(); if (rewardGenProgress != null) { rewardGenProgress.text = $"{storedSmeltEnergyState}/{capacity}"; } if (rewardProgressImage != null) { rewardProgressImage.fillAmount = capacity <= 0 ? 0f : Mathf.Clamp01((float)storedSmeltEnergyState / capacity); } } private void RefreshRewardDropdown() { if (selectAReward == null) { return; } int previousValue = selectAReward.options != null && selectAReward.options.Count > 0 ? Mathf.Max(0, selectAReward.value) : 0; selectAReward.ClearOptions(); if (selectAReward.captionText != null) { selectAReward.captionText.supportRichText = true; } if (selectAReward.itemText != null) { selectAReward.itemText.supportRichText = true; } var options = new List(); if (ssrso != null && ssrso.rewardRequirements != null) { for (int i = 0; i < ssrso.rewardRequirements.Length; i++) { smeltStageRewardSO.SmeltStageRewardRequirement requirement = ssrso.rewardRequirements[i]; string optionName = requirement != null ? requirement.equipRewardName : string.Empty; int requiredAmount = requirement != null ? Mathf.Max(0, requirement.requiredAmount) : 0; string color = string.IsNullOrWhiteSpace(optionName) ? "#808080" : (requiredAmount > storedSmeltEnergyState ? "#FF0000" : "#FFFFFF"); options.Add(new Dropdown.OptionData($"{(string.IsNullOrWhiteSpace(optionName) ? "未命名奖励" : optionName)}")); } } if (options.Count == 0) { options.Add(new Dropdown.OptionData("暂无奖励")); } selectAReward.AddOptions(options); selectAReward.value = Mathf.Clamp(previousValue, 0, options.Count - 1); selectAReward.RefreshShownValue(); } private void RefreshButtons() { if (startSmeltButton != null) { bool canStart = !isSmeltingState && SmeltPoolEquipments.Count > 0 && PlayerEconomyLedger.EnsureInstance().HasEnoughCoins(GetStartSmeltCost()); startSmeltButton.interactable = smeltCompletedState || canStart; Text startButtonText = startSmeltButton.GetComponentInChildren(true); if (startButtonText != null) { startButtonText.text = smeltCompletedState ? "领取碎片" : "开始融合"; } } if (quickFinishButton != null) { quickFinishButton.interactable = isSmeltingState && !smeltCompletedState && PlayerEconomyLedger.EnsureInstance().HasEnoughCoins(GetQuickFinishCost()); } if (getReward != null) { smeltStageRewardSO.SmeltStageRewardRequirement requirement = GetSelectedRewardRequirement(); getReward.interactable = (activeCtasInstance == null) && requirement != null && Mathf.Max(0, requirement.requiredAmount) <= storedSmeltEnergyState; } } private void RefreshReasonWhy() { if (reasonWhy == null) { return; } if (smeltCompletedState) { reasonWhy.text = string.Empty; return; } if (isSmeltingState) { reasonWhy.text = "正在融合中"; return; } if (GetSmeltEquipmentCapacity() <= 0) { reasonWhy.text = "熔炉容量为0"; return; } if (SmeltPoolEquipments.Count <= 0) { reasonWhy.text = "需要投入记忆"; return; } reasonWhy.text = string.Empty; if (!PlayerEconomyLedger.EnsureInstance().HasEnoughCoins(GetStartSmeltCost())) { reasonWhy.text = "硬币不足"; return; } } private int CalculateTotalFragmentsForCurrentPool() { int totalFragments = 0; for (int i = 0; i < SmeltPoolEquipments.Count; i++) { equipmentSO equipment = SmeltPoolEquipments[i]; if (equipment == null) { continue; } totalFragments += GetFragmentReward(equipment); } return totalFragments; } private int GetFragmentReward(equipmentSO equipment) { if (equipment == null) { return 0; } int skillCount = 0; if (equipment.sa_skillID > 0) { skillCount++; } if (equipment.ia_skillID > 0) { skillCount++; } int simpleReward = ssrso != null ? ssrso.simpleRewardAmount : 40; int oneSkillReward = ssrso != null ? ssrso._1skillRewardAmount : 100; int twoSkillReward = ssrso != null ? ssrso._2skillRewardAmount : 300; switch (skillCount) { case 0: return simpleReward; case 1: return oneSkillReward; default: return twoSkillReward; } } private int GetSmeltEquipmentCapacity() { if (ssrso == null) { return 60; } return Mathf.Clamp(ssrso.smeltEquipmentCapacity, 0, 100); } private int GetSmeltStorageCapacity() { if (ssrso == null) { return 5000; } return Mathf.Clamp(ssrso.smeltStorageCapacity, 0, 5000); } private static int GetSmeltStorageCapacityStatic() { for (int i = 0; i < Instances.Count; i++) { equipSmelt instance = Instances[i]; if (instance != null && instance.ssrso != null) { return Mathf.Clamp(instance.ssrso.smeltStorageCapacity, 0, 5000); } } return 5000; } private int GetQuickFinishCost() { int baseCost = ssrso != null ? Mathf.Max(0, ssrso.quickFinishCost) : 0; return PlayerSkillService.ModifySmeltCoinCost(baseCost); } private int GetStartSmeltCost() { int baseCost = ssrso != null ? Mathf.Max(0, ssrso.startSmeltCost) : 0; return PlayerSkillService.ModifySmeltCoinCost(baseCost); } private smeltStageRewardSO.SmeltStageRewardRequirement GetSelectedRewardRequirement() { if (ssrso == null || ssrso.rewardRequirements == null || ssrso.rewardRequirements.Length == 0) { return null; } int selectedIndex = selectAReward != null ? Mathf.Clamp(selectAReward.value, 0, ssrso.rewardRequirements.Length - 1) : 0; return ssrso.rewardRequirements[selectedIndex]; } private static equipSmelt GetActivePoolInstance() { for (int i = 0; i < Instances.Count; i++) { equipSmelt instance = Instances[i]; if (instance != null && instance.IsPoolOpenForTransfers()) { return instance; } } return null; } private void ClearSmeltPoolItems() { for (int i = smeltPoolContent != null ? smeltPoolContent.childCount - 1 : -1; i >= 0; i--) { Transform child = smeltPoolContent.GetChild(i); if (child == null) { continue; } #if UNITY_EDITOR if (!Application.isPlaying) { DestroyImmediate(child.gameObject); } else #endif { Destroy(child.gameObject); } } spawnedPoolItems.Clear(); } private void RegisterInstance() { if (!Instances.Contains(this)) { Instances.Add(this); } } private void OnApplicationPause(bool pauseStatus) { if (pauseStatus) { SavePersistentState(); } } private void OnApplicationQuit() { SavePersistentState(); } private static void EnsurePersistentStateLoaded() { if (persistenceLoaded) { return; } persistenceLoaded = true; ConsumedSmeltEquipmentIds.Clear(); if (!PlayerPrefs.HasKey(SmeltStatePrefsKey)) { return; } string json = PlayerPrefs.GetString(SmeltStatePrefsKey, string.Empty); if (string.IsNullOrWhiteSpace(json)) { return; } SmeltPersistentState state = null; try { state = JsonUtility.FromJson(json); } catch (Exception ex) { Debug.LogWarning($"[equipSmelt] Failed to parse persistent state: {ex.Message}"); } if (state == null) { return; } isSmeltingState = state.isSmelting; smeltCompletedState = state.smeltCompleted; gamesRequiredForCurrentBatchState = Mathf.Max(0, state.gamesRequired); gamesCompletedForCurrentBatchState = Mathf.Clamp(state.gamesCompleted, 0, gamesRequiredForCurrentBatchState); pendingDirectFragmentsState = Mathf.Max(0, state.pendingDirectFragments); pendingStoredFragmentsState = Mathf.Max(0, state.pendingStoredFragments); storedSmeltEnergyState = Mathf.Max(0, state.storedSmeltEnergy); if (state.consumedEquipmentIds != null) { for (int i = 0; i < state.consumedEquipmentIds.Length; i++) { string id = state.consumedEquipmentIds[i]; if (!string.IsNullOrWhiteSpace(id)) { ConsumedSmeltEquipmentIds.Add(id); } } } } private static void SavePersistentState() { if (!persistenceLoaded) { return; } var state = new SmeltPersistentState { isSmelting = isSmeltingState, smeltCompleted = smeltCompletedState, gamesRequired = gamesRequiredForCurrentBatchState, gamesCompleted = gamesCompletedForCurrentBatchState, pendingDirectFragments = pendingDirectFragmentsState, pendingStoredFragments = pendingStoredFragmentsState, storedSmeltEnergy = storedSmeltEnergyState, consumedEquipmentIds = ConsumedSmeltEquipmentIds.Count > 0 ? ConsumedSmeltEquipmentIds.ToArray() : Array.Empty() }; PlayerPrefs.SetString(SmeltStatePrefsKey, JsonUtility.ToJson(state)); PlayerPrefs.Save(); } public static void ClearPersistentState() { SmeltPoolEquipments.Clear(); SmeltPoolLookup.Clear(); ConsumedSmeltEquipments.Clear(); ConsumedSmeltEquipmentIds.Clear(); isSmeltingState = false; smeltCompletedState = false; gamesRequiredForCurrentBatchState = 0; gamesCompletedForCurrentBatchState = 0; pendingDirectFragmentsState = 0; pendingStoredFragmentsState = 0; storedSmeltEnergyState = 0; persistenceLoaded = true; PlayerPrefs.DeleteKey(SmeltStatePrefsKey); PlayerPrefs.Save(); RefreshAllSmeltPools(); RefreshAllEquipBags(); } private static void RefreshAllSmeltPools() { for (int i = 0; i < Instances.Count; i++) { if (Instances[i] != null) { Instances[i].RefreshAllUi(); } } } private static void RefreshAllEquipBags() { equipBag[] bags = FindObjectsOfType(true); if (bags == null) { return; } for (int i = 0; i < bags.Length; i++) { if (bags[i] != null) { bags[i].Rebuild(); } } } }