using System; using System.Collections.Generic; 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 ConsumedSmeltEquipments = new HashSet(); 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; [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 void Awake() { RegisterInstance(); BindButtons(); RefreshAllUi(); } private void OnEnable() { RegisterInstance(); BindButtons(); settlementController.OnSettlementCompleted -= HandleSettlementCompleted; settlementController.OnSettlementCompleted += HandleSettlementCompleted; RefreshAllUi(); } private void OnDisable() { settlementController.OnSettlementCompleted -= HandleSettlementCompleted; Instances.Remove(this); } private void OnDestroy() { settlementController.OnSettlementCompleted -= HandleSettlementCompleted; Instances.Remove(this); } public static bool IsEquipmentAssignedToSmeltPool(equipmentSO equipment) { return equipment != null && SmeltPoolLookup.Contains(equipment); } public static bool IsEquipmentConsumedBySmelt(equipmentSO equipment) { return equipment != null && ConsumedSmeltEquipments.Contains(equipment); } public static bool RemoveEquipmentFromSmeltPool(equipmentSO equipment) { if (equipment == null) { return false; } if (!SmeltPoolLookup.Remove(equipment)) { return false; } SmeltPoolEquipments.Remove(equipment); RefreshAllSmeltPools(); RefreshAllEquipBags(); return true; } public static bool TryHandleQuickTransfer(equipmentSO equipment) { 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 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) { if (equipment == null || IsEquipmentConsumedBySmelt(equipment) || !IsPoolOpenForTransfers()) { return; } int capacity = GetSmeltEquipmentCapacity(); if (capacity <= 0 || SmeltPoolEquipments.Count >= capacity) { return; } if (SmeltPoolLookup.Add(equipment)) { SmeltPoolEquipments.Add(equipment); 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; } 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(); RefreshAllUi(); RefreshAllEquipBags(); } private void HandleQuickFinishClicked() { if (!isSmeltingState || smeltCompletedState) { return; } int cost = GetQuickFinishCost(); if (!PlayerEconomyLedger.EnsureInstance().TrySpendCoins(cost)) { return; } gamesCompletedForCurrentBatchState = gamesRequiredForCurrentBatchState; smeltCompletedState = true; RefreshAllUi(); } private void HandleSettlementCompleted() { if (!isSmeltingState || smeltCompletedState) { return; } gamesCompletedForCurrentBatchState = Mathf.Min(gamesRequiredForCurrentBatchState, gamesCompletedForCurrentBatchState + 1); if (gamesCompletedForCurrentBatchState >= gamesRequiredForCurrentBatchState) { smeltCompletedState = true; } RefreshAllUi(); } private void ClaimCurrentBatchRewards() { if (!smeltCompletedState) { return; } if (pendingDirectFragmentsState > 0) { PlayerEconomyLedger.EnsureInstance().AddMaterial(pendingDirectFragmentsState); } storedSmeltEnergyState = Mathf.Clamp(storedSmeltEnergyState + pendingStoredFragmentsState, 0, GetSmeltStorageCapacity()); pendingDirectFragmentsState = 0; pendingStoredFragmentsState = 0; gamesRequiredForCurrentBatchState = 0; gamesCompletedForCurrentBatchState = 0; isSmeltingState = false; smeltCompletedState = false; if (d_mf_Amount != null) { d_mf_Amount.text = "0"; } if (s_mf_Amount != null) { s_mf_Amount.text = "0"; } RefreshAllUi(); RefreshAllEquipBags(); } private void HandleGetRewardClicked() { smeltStageRewardSO.SmeltStageRewardRequirement requirement = GetSelectedRewardRequirement(); if (requirement == null) { return; } int requiredAmount = Mathf.Max(0, requirement.requiredAmount); if (requiredAmount > storedSmeltEnergyState) { return; } equipmentSO generated = equipmentGenerator.GenerateFromSmeltReward(ssrso, requirement); if (generated == null) { return; } storedSmeltEnergyState = Mathf.Max(0, storedSmeltEnergyState - requiredAmount); RefreshAllUi(); RefreshAllEquipBags(); } private void HandleRewardSelectionChanged(int _) { RefreshButtons(); } 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 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 } 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 (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; } 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 = 0; selectAReward.RefreshShownValue(); } private void RefreshButtons() { if (startSmeltButton != null) { startSmeltButton.interactable = smeltCompletedState || (!isSmeltingState && SmeltPoolEquipments.Count > 0); 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 = 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; } 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 int GetQuickFinishCost() { return ssrso != null ? Mathf.Max(0, ssrso.quickFinishCost) : 0; } 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 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(); } } } }