Files
2026-07-16 23:04:59 +08:00

666 lines
18 KiB
C#

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<GameObject> spawnedMaterialItems = new List<GameObject>();
private readonly List<equipmentSO.EquipmentSpecialEffectType> availableFinalBoostTypes = new List<equipmentSO.EquipmentSpecialEffectType>();
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<equipItemPrefab>();
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<equipItemPrefab>();
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<materialPrefab>();
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<Dropdown.OptionData>(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<Dropdown.OptionData> 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<equipItemPrefab>(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<equipBag>(FindObjectsInactive.Include, FindObjectsSortMode.None);
for (int i = 0; i < bags.Length; i++)
{
if (bags[i] != null)
{
bags[i].Rebuild();
}
}
}
}