using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using Bansonic; #if UNITY_EDITOR using UnityEditor; #endif public class eFinalDream : MonoBehaviour { [Header("so")] public Player_SO playerSO; public equipmentSO eqp_p_SO; public eUpdate_mtrSO need_mtrSO; [Header("status")] public GameObject beforeObj; public GameObject toObj; public GameObject nextObj; [Header("dropdown")] public Dropdown selectFinalBoost; [Header("dragging")] public GameObject dragPrev; [Header("transforms")] public Transform prevEquip; public Transform nextLevelEquip; public GameObject eip; [Header("texts")] public Text prevText; public Text nextText; public Text reasonWhy; [Header("materials")] public GameObject mtrPrefab; public Transform mtrParent; public Text mtrInfo; [Header("sprites")] public Sprite memoryFragmentSprite; public Sprite coinSprite; [Header("button")] public Button yesDreamUpButton; private GameObject spawnedPrevInstance; private GameObject spawnedNextInstance; private equipmentSO previewSO; private readonly List spawnedMaterialItems = new List(); private readonly List availableFinalBoostTypes = new List(); private equipmentSO cachedFinalBoostEquipment; private bool suppressFinalBoostCallback; private void Awake() { InitializeBindings(); SetDragPreviewVisible(false); RefreshAll(); } private void OnEnable() { InitializeBindings(); SetDragPreviewVisible(false); RefreshAll(); } private void OnDisable() { if (yesDreamUpButton != null) { yesDreamUpButton.onClick.RemoveListener(HandleYesDreamClicked); } if (selectFinalBoost != null) { selectFinalBoost.onValueChanged.RemoveListener(HandleFinalBoostChanged); } } private void InitializeBindings() { if (playerSO != null) { PlayerEconomyLedger.EnsureInstance().AttachPlayerData(playerSO); } if (selectFinalBoost != null) { selectFinalBoost.onValueChanged.RemoveListener(HandleFinalBoostChanged); selectFinalBoost.onValueChanged.AddListener(HandleFinalBoostChanged); } if (yesDreamUpButton != null) { yesDreamUpButton.onClick.RemoveListener(HandleYesDreamClicked); yesDreamUpButton.onClick.AddListener(HandleYesDreamClicked); } } public void SetDragPreviewVisible(bool visible) { if (dragPrev == null) { return; } if (!gameObject.activeInHierarchy) { dragPrev.SetActive(false); return; } dragPrev.SetActive(visible); } public bool IsPointerOverDropArea(Vector2 screenPoint, Camera eventCamera) { if (dragPrev == null || !dragPrev.activeInHierarchy) { return false; } RectTransform rectTransform = dragPrev.transform as RectTransform; if (rectTransform == null) { return false; } return RectTransformUtility.RectangleContainsScreenPoint(rectTransform, screenPoint, eventCamera); } public void AcceptDraggedEquipment(equipmentSO equipment) { if (equipment == null) { return; } eqp_p_SO = equipment; cachedFinalBoostEquipment = null; RefreshAll(); } private void HandleFinalBoostChanged(int _) { if (suppressFinalBoostCallback) { return; } RefreshPreviewStateOnly(); } private void RefreshAll() { EnsureFinalBoostOptions(); RefreshPrevPreview(); RefreshNextPreview(); RefreshStateObjects(); RefreshTexts(); RefreshMaterials(); RefreshReasonWhy(); RefreshActionState(); } private void RefreshPreviewStateOnly() { RefreshNextPreview(); RefreshStateObjects(); RefreshTexts(); RefreshReasonWhy(); RefreshActionState(); } private void RefreshPrevPreview() { DestroySpawned(ref spawnedPrevInstance); if (eqp_p_SO == null || eip == null || prevEquip == null) { return; } spawnedPrevInstance = Instantiate(eip, prevEquip); spawnedPrevInstance.name = $"{eqp_p_SO.name}_FinalDreamPrev"; spawnedPrevInstance.SetActive(true); equipItemPrefab item = spawnedPrevInstance.GetComponent(); if (item != null) { item.Bind(eqp_p_SO); item.SetInteractionOptions(false, false); } } private void RefreshNextPreview() { DestroySpawned(ref spawnedNextInstance); DestroyPreviewEquipment(); if (!CanPreview()) { return; } previewSO = Instantiate(eqp_p_SO); previewSO.name = $"{eqp_p_SO.name}(FinalPreview)"; ApplyFinalBoost(previewSO, GetSelectedBoostType(), 0.01f); spawnedNextInstance = Instantiate(eip, nextLevelEquip); spawnedNextInstance.name = $"{eqp_p_SO.name}_FinalDreamNext"; spawnedNextInstance.SetActive(true); equipItemPrefab item = spawnedNextInstance.GetComponent(); if (item != null) { item.Bind(previewSO); item.SetInteractionOptions(false, false); } } private void RefreshStateObjects() { if (beforeObj != null) { beforeObj.SetActive(true); } bool canPreview = CanPreview(); if (toObj != null) { toObj.SetActive(canPreview); } if (nextObj != null) { nextObj.SetActive(canPreview); } } private void RefreshTexts() { if (prevText != null) { prevText.text = eqp_p_SO != null ? ResolveEquipmentName(eqp_p_SO) : string.Empty; prevText.color = eqp_p_SO != null ? ResolveEquipmentColor(eqp_p_SO.GetVisualQualityColorIndex()) : Color.black; } if (nextText != null) { nextText.text = previewSO != null ? ResolveEquipmentName(previewSO) : string.Empty; nextText.color = previewSO != null ? ResolveEquipmentColor(previewSO.GetVisualQualityColorIndex()) : Color.black; } } private void RefreshMaterials() { ClearSpawnedMaterialItems(); if (mtrInfo == null) { return; } string structuralReason = GetStructuralFailureReason(); if (!string.IsNullOrEmpty(structuralReason)) { mtrInfo.text = structuralReason; return; } mtrInfo.text = string.Empty; SpawnMaterialItems(); } private void SpawnMaterialItems() { if (mtrPrefab == null || mtrParent == null || need_mtrSO == null) { return; } int materialRequired = need_mtrSO.GetFinalDreamMaterialRequired(); int coinRequired = need_mtrSO.GetFinalDreamCoinsRequired(); int memoryRequired = need_mtrSO.GetFinalDreamMemoryFragmentRequired(); if (materialRequired > 0 && need_mtrSO.finalDreamMaterial != null) { SpawnMaterialItem( need_mtrSO.finalDreamMaterial.consumableSprite, need_mtrSO.finalDreamMaterial.consumableName, EquipmentConsumableLedger.EnsureInstance().GetCount(need_mtrSO.finalDreamMaterial.consumableKind), materialRequired); } if (coinRequired > 0) { SpawnMaterialItem(coinSprite, "算力", PlayerEconomyLedger.EnsureInstance().GetCoins(), coinRequired); } if (memoryRequired > 0) { SpawnMaterialItem(memoryFragmentSprite, "记忆碎片", PlayerEconomyLedger.EnsureInstance().GetMaterial(), memoryRequired); } } private void SpawnMaterialItem(Sprite sprite, string displayName, int ownedAmount, int requiredAmount) { GameObject instance = Instantiate(mtrPrefab, mtrParent); instance.SetActive(true); spawnedMaterialItems.Add(instance); materialPrefab item = instance.GetComponent(); if (item != null) { item.BindOwnedRequired(sprite, displayName, ownedAmount, requiredAmount, true, false, null); item.SetSelected(true); if (item.materialButton != null) { item.materialButton.interactable = false; } } } private void RefreshReasonWhy() { if (reasonWhy != null) { reasonWhy.text = GetActionFailureReason(); } } private void RefreshActionState() { if (yesDreamUpButton != null) { yesDreamUpButton.interactable = string.IsNullOrEmpty(GetActionFailureReason()); } } private string GetStructuralFailureReason() { if (eqp_p_SO == null) { return "需要选择一个记忆"; } if (eqp_p_SO.level < 0 || eqp_p_SO.level > 20) { return "非法等级"; } if (eqp_p_SO.level != 20) { return "要求20追忆等级"; } if (need_mtrSO == null) { return "未配置登顶强化规则"; } if (need_mtrSO.finalDreamMaterial == null) { return "未配置登顶材料"; } if (availableFinalBoostTypes.Count == 0) { return "当前记忆没有可登顶的基础属性"; } return string.Empty; } private string GetActionFailureReason() { string structuralReason = GetStructuralFailureReason(); if (!string.IsNullOrEmpty(structuralReason)) { return structuralReason; } int materialRequired = need_mtrSO.GetFinalDreamMaterialRequired(); int coinRequired = need_mtrSO.GetFinalDreamCoinsRequired(); int memoryRequired = need_mtrSO.GetFinalDreamMemoryFragmentRequired(); if (materialRequired > 0 && EquipmentConsumableLedger.EnsureInstance().GetCount(need_mtrSO.finalDreamMaterial.consumableKind) < materialRequired) { return "登顶材料不足"; } if (!PlayerEconomyLedger.EnsureInstance().HasEnoughCoins(coinRequired)) { return "算力不足"; } if (!PlayerEconomyLedger.EnsureInstance().HasEnoughMaterial(memoryRequired)) { return "记忆碎片不足"; } return string.Empty; } private void HandleYesDreamClicked() { string failureReason = GetActionFailureReason(); if (!string.IsNullOrEmpty(failureReason)) { RefreshAll(); return; } int materialRequired = need_mtrSO.GetFinalDreamMaterialRequired(); int coinRequired = need_mtrSO.GetFinalDreamCoinsRequired(); int memoryRequired = need_mtrSO.GetFinalDreamMemoryFragmentRequired(); if (materialRequired > 0 && !EquipmentConsumableLedger.EnsureInstance().TryConsume(need_mtrSO.finalDreamMaterial.consumableKind, materialRequired)) { RefreshAll(); return; } if (coinRequired > 0 && !PlayerEconomyLedger.EnsureInstance().TrySpendCoins(coinRequired)) { if (materialRequired > 0) { EquipmentConsumableLedger.EnsureInstance().Add(need_mtrSO.finalDreamMaterial.consumableKind, materialRequired); } RefreshAll(); return; } if (memoryRequired > 0 && !PlayerEconomyLedger.EnsureInstance().TrySpendMaterial(memoryRequired)) { if (coinRequired > 0) { PlayerEconomyLedger.EnsureInstance().AddCoins(coinRequired); } if (materialRequired > 0) { EquipmentConsumableLedger.EnsureInstance().Add(need_mtrSO.finalDreamMaterial.consumableKind, materialRequired); } RefreshAll(); return; } ApplyFinalBoost(eqp_p_SO, GetSelectedBoostType(), 0.01f); PersistEquipment(eqp_p_SO); RefreshAllEquipBags(); RefreshAll(); } private bool CanPreview() { return string.IsNullOrEmpty(GetStructuralFailureReason()) && availableFinalBoostTypes.Count > 0 && eip != null && nextLevelEquip != null; } private equipmentSO.EquipmentSpecialEffectType GetSelectedBoostType() { if (availableFinalBoostTypes.Count == 0) { return equipmentSO.EquipmentSpecialEffectType.MaxHp; } int index = selectFinalBoost != null ? Mathf.Clamp(selectFinalBoost.value, 0, availableFinalBoostTypes.Count - 1) : 0; return availableFinalBoostTypes[index]; } private void EnsureFinalBoostOptions() { if (selectFinalBoost == null) { return; } if (cachedFinalBoostEquipment == eqp_p_SO && selectFinalBoost.options != null && selectFinalBoost.options.Count == availableFinalBoostTypes.Count) { return; } int currentValue = selectFinalBoost.value; availableFinalBoostTypes.Clear(); var options = new List(5); AppendFinalBoostOption(eqp_p_SO != null && !Mathf.Approximately(eqp_p_SO.maxHp.basicGain, 0f), equipmentSO.EquipmentSpecialEffectType.MaxHp, "最大生命值", options); AppendFinalBoostOption(eqp_p_SO != null && !Mathf.Approximately(eqp_p_SO.attack.basicGain, 0f), equipmentSO.EquipmentSpecialEffectType.Attack, "攻击力", options); AppendFinalBoostOption(eqp_p_SO != null && !Mathf.Approximately(eqp_p_SO.maxMana.basicGain, 0f), equipmentSO.EquipmentSpecialEffectType.MaxMana, "最大法力值", options); AppendFinalBoostOption(eqp_p_SO != null && !Mathf.Approximately(eqp_p_SO.damageResistance.basicGain, 0f), equipmentSO.EquipmentSpecialEffectType.DamageResistance, "伤害减免", options); AppendFinalBoostOption(eqp_p_SO != null && !Mathf.Approximately(eqp_p_SO.scoreEfficiency.basicGain, 0f), equipmentSO.EquipmentSpecialEffectType.ScoreEfficiency, "得分效率", options); suppressFinalBoostCallback = true; selectFinalBoost.ClearOptions(); selectFinalBoost.AddOptions(options); if (options.Count > 0) { selectFinalBoost.value = Mathf.Clamp(currentValue, 0, options.Count - 1); } selectFinalBoost.RefreshShownValue(); suppressFinalBoostCallback = false; cachedFinalBoostEquipment = eqp_p_SO; } private void AppendFinalBoostOption(bool include, equipmentSO.EquipmentSpecialEffectType effectType, string displayName, List options) { if (!include) { return; } availableFinalBoostTypes.Add(effectType); options.Add(new Dropdown.OptionData(displayName)); } private static void ApplyFinalBoost(equipmentSO equipment, equipmentSO.EquipmentSpecialEffectType effectType, float boostValue) { equipment.maxLevelEffects = new[] { new equipmentSO.EquipmentSpecialEffect { effectType = effectType, value = boostValue } }; } private static bool HasMaxLevelEffect(equipmentSO equipment) { return equipment != null && equipment.maxLevelEffects != null && equipment.maxLevelEffects.Length > 0; } private static string ResolveEquipmentName(equipmentSO equipment) { if (equipment == null) { return string.Empty; } string displayName = equipment.GetDisplayTierName(); return string.IsNullOrWhiteSpace(displayName) ? equipment.name : displayName; } private static Color ResolveEquipmentColor(int colorIndex) { equipItemPrefab reference = Object.FindFirstObjectByType(FindObjectsInactive.Include); if (reference == null) { return Color.white; } return reference.GetAccentColorByVisualIndex(colorIndex); } private void ClearSpawnedMaterialItems() { if (mtrParent != null) { for (int i = mtrParent.childCount - 1; i >= 0; i--) { Transform child = mtrParent.GetChild(i); if (child == null) { continue; } #if UNITY_EDITOR if (!Application.isPlaying) { DestroyImmediate(child.gameObject); } else #endif { Destroy(child.gameObject); } } } spawnedMaterialItems.Clear(); } private void DestroySpawned(ref GameObject instance) { if (instance == null) { return; } #if UNITY_EDITOR if (!Application.isPlaying) { DestroyImmediate(instance); } else #endif { Destroy(instance); } instance = null; } private void DestroyPreviewEquipment() { if (previewSO == null) { return; } #if UNITY_EDITOR if (!Application.isPlaying) { DestroyImmediate(previewSO); } else #endif { Destroy(previewSO); } previewSO = null; } private static void PersistEquipment(equipmentSO equipment) { if (equipment == null) { return; } if (Application.isPlaying) { equipmentGenerator.SaveRuntimeEquipmentState(equipment); return; } #if UNITY_EDITOR EditorUtility.SetDirty(equipment); AssetDatabase.SaveAssets(); #endif } private static void RefreshAllEquipBags() { equipBag[] bags = UnityEngine.Object.FindObjectsByType(FindObjectsInactive.Include, FindObjectsSortMode.None); for (int i = 0; i < bags.Length; i++) { if (bags[i] != null) { bags[i].Rebuild(); } } } }