Files
bansonic_beta_main/Assets/_eqpmtSys/eqpmtDesPrefab.cs
T
2026-03-27 08:02:55 +08:00

641 lines
18 KiB
C#

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class eqpmtDesPrefab : MonoBehaviour
{
[Header("so")]
public equipmentSO eSO;
[Header("display")]
public bool displayBasicAttributes = true;
public bool displaySpecialEffects = true;
public bool displayTypeSameEffects = true;
public bool displayIllusionEffects = true;
public bool displayMaxLevelEffects = true;
[Header("btm")]
public Image eqpmtBtm;
public Sprite[] eqpmtBtmSprites;
[Header("head")]
public Text eqpmtName;
public Text eqpmtID;
public Text eqpmtLevel;
public Image eqpmtIcon;
public Image eqpmtPbtm;
public Color[] profilebtmColor;
public Text eqpmtDescription;
[Header("body")]
public Text baTitle;
public Text baDetail;
public GameObject baSpace;
public Text saTitle;
public Text saDetail;
public GameObject saSpace;
public Text taTitle;
public Text taDetail;
public GameObject taSpace;
public Text iaTitle;
public Text iaDetail;
public GameObject iaSpace;
public Text mlTitle;
public Text mlDetail;
[Header("objs")]
public GameObject eqpmtSkillPrefab;
public Transform sasParent;
public Transform iasParent;
public Transform mlsParent;
private RectTransform rectTransform;
private Canvas rootCanvas;
private Camera uiCamera;
private bool ignoreCloseUntilClickReleased;
private void Awake()
{
rectTransform = transform as RectTransform;
rootCanvas = GetComponentInParent<Canvas>();
if (rootCanvas != null && rootCanvas.renderMode != RenderMode.ScreenSpaceOverlay)
{
uiCamera = rootCanvas.worldCamera;
}
}
public void Bind(equipmentSO so)
{
eSO = so;
RefreshView();
}
public void IgnoreCloseUntilClickReleased()
{
ignoreCloseUntilClickReleased = true;
}
private void Update()
{
if (eSO == null || rectTransform == null)
{
return;
}
if (ignoreCloseUntilClickReleased)
{
if (Input.GetMouseButton(0))
{
return;
}
ignoreCloseUntilClickReleased = false;
}
if (!Input.GetMouseButtonDown(0))
{
return;
}
if (RectTransformUtility.RectangleContainsScreenPoint(rectTransform, Input.mousePosition, uiCamera))
{
return;
}
if (IsClickInsidePopupHierarchy(Input.mousePosition))
{
return;
}
Destroy(gameObject);
}
private bool IsClickInsidePopupHierarchy(Vector2 screenPoint)
{
if (EventSystem.current == null)
{
return false;
}
PointerEventData pointer = new PointerEventData(EventSystem.current)
{
position = screenPoint
};
var results = new List<RaycastResult>();
EventSystem.current.RaycastAll(pointer, results);
for (int i = 0; i < results.Count; i++)
{
GameObject target = results[i].gameObject;
if (target != null && target.transform.IsChildOf(transform))
{
return true;
}
}
return false;
}
private void RefreshView()
{
ClearSkillPrefabs();
if (eSO == null)
{
ApplyHeader(string.Empty, null, 0, string.Empty);
ApplyBasicSection(string.Empty, false);
ApplyEffectSection(saTitle, saDetail, saSpace, sasParent, string.Empty, null, false);
ApplyEffectSection(taTitle, taDetail, taSpace, null, string.Empty, null, false);
ApplyEffectSection(iaTitle, iaDetail, iaSpace, iasParent, string.Empty, null, false);
ApplyEffectSection(mlTitle, mlDetail, null, mlsParent, string.Empty, null, false);
return;
}
equipmentSO.EquipmentTierPresentation presentation = ResolveTierPresentation(eSO);
string displayName = presentation != null && !string.IsNullOrWhiteSpace(presentation.tierName)
? presentation.tierName
: eSO.name;
Sprite displaySprite = presentation != null ? presentation.equipmentSprite : null;
string description = presentation != null ? presentation.tierDescription : string.Empty;
ApplyHeader(displayName, displaySprite, GetQualityVisualIndex(eSO.level), description);
string basicText = BuildBasicAttributesText(eSO);
ApplyBasicSection(basicText, displayBasicAttributes && !string.IsNullOrWhiteSpace(basicText));
string specialText = BuildEffectText(eSO.specialEffects, out int saSkillId);
bool hasSpecialSkill = HasSkillEffect(eSO.specialEffects);
ApplyEffectSection(
saTitle,
saDetail,
saSpace,
sasParent,
specialText,
hasSpecialSkill && saSkillId > 0 ? new[] { saSkillId } : null,
displaySpecialEffects && HasSectionContent(eSO.specialEffects, saSkillId));
string typeSameText = BuildEffectText(eSO.typeSameEffects, out _);
ApplyEffectSection(
taTitle,
taDetail,
taSpace,
null,
typeSameText,
null,
displayTypeSameEffects && HasSectionContent(eSO.typeSameEffects, 0));
string illusionText = BuildEffectText(eSO.illusionEffects, out int iaSkillId);
bool isTourPreview = IsTourPreviewEquipment(eSO);
if (isTourPreview)
{
illusionText = string.IsNullOrWhiteSpace(illusionText)
? "<color=#9DFF84>1个随机巡演特效</color>"
: $"{illusionText}\n<color=#9DFF84>1个随机巡演特效</color>";
}
bool hasIllusionSkill = iaSkillId > 0;
ApplyEffectSection(
iaTitle,
iaDetail,
iaSpace,
iasParent,
illusionText,
hasIllusionSkill ? new[] { iaSkillId } : null,
displayIllusionEffects && (isTourPreview || HasSectionContent(eSO.illusionEffects, iaSkillId)));
string maxLevelText = BuildEffectText(eSO.maxLevelEffects, out _);
ApplyEffectSection(
mlTitle,
mlDetail,
null,
mlsParent,
maxLevelText,
null,
displayMaxLevelEffects && HasSectionContent(eSO.maxLevelEffects, 0));
}
private equipmentSO.EquipmentTierPresentation ResolveTierPresentation(equipmentSO equipment)
{
if (equipment == null)
{
return null;
}
if (equipment.tierNameConfig != null &&
equipment.tierNameConfig.TryGetStagePresentation(equipment.skillType, equipment.GetTierStageIndex(), out equipmentTierNameConfigSO.StagePresentation stage) &&
stage != null)
{
return new equipmentSO.EquipmentTierPresentation
{
tierName = stage.tierName,
equipmentSprite = stage.equipmentSprite,
tierDescription = stage.tierDescription
};
}
return equipment.GetCurrentTierPresentation();
}
private void ApplyHeader(string displayName, Sprite displaySprite, int qualityIndex, string description)
{
if (eqpmtName != null)
{
eqpmtName.text = displayName;
eqpmtName.color = GetProfileColor(qualityIndex);
}
if (eqpmtID != null)
{
eqpmtID.text = BuildDisplayEquipmentId(eSO);
}
if (eqpmtLevel != null)
{
eqpmtLevel.text = eSO != null ? Mathf.Max(0, eSO.level).ToString() : string.Empty;
}
if (eqpmtDescription != null)
{
eqpmtDescription.text = description;
}
if (eqpmtIcon != null)
{
eqpmtIcon.sprite = displaySprite;
eqpmtIcon.enabled = displaySprite != null;
}
if (eqpmtBtm != null)
{
eqpmtBtm.sprite = GetBottomSprite(qualityIndex);
eqpmtBtm.enabled = eqpmtBtm.sprite != null;
}
if (eqpmtPbtm != null)
{
eqpmtPbtm.color = GetProfileColor(qualityIndex);
}
}
private void ApplyBasicSection(string text, bool active)
{
SetGroupActive(baTitle, baDetail, baSpace, null, active);
if (baDetail != null)
{
baDetail.supportRichText = true;
baDetail.text = text;
baDetail.gameObject.SetActive(active && !string.IsNullOrWhiteSpace(text));
}
}
private void ApplyEffectSection(
Text title,
Text detail,
GameObject space,
Transform skillParent,
string text,
int[] skillIds,
bool active)
{
bool hasText = !string.IsNullOrWhiteSpace(text);
bool hasSkills = skillParent != null && skillIds != null && skillIds.Length > 0;
bool showGroup = active && (hasText || hasSkills);
SetGroupActive(title, detail, space, null, showGroup);
if (detail != null)
{
detail.supportRichText = true;
detail.text = text;
detail.gameObject.SetActive(showGroup && hasText);
}
bool showSkillParent = showGroup && hasSkills;
if (skillParent != null)
{
skillParent.gameObject.SetActive(showSkillParent);
}
if (!showSkillParent)
{
return;
}
for (int i = 0; i < skillIds.Length; i++)
{
SpawnSkillPrefab(skillParent, skillIds[i]);
}
}
private void SpawnSkillPrefab(Transform parent, int skillId)
{
if (eqpmtSkillPrefab == null || parent == null || skillId <= 0)
{
return;
}
GameObject instance = Instantiate(eqpmtSkillPrefab, parent);
instance.name = $"eqpmtSkill_{skillId}";
eqpmtSkillPrefabItem item = instance.GetComponent<eqpmtSkillPrefabItem>();
if (item != null)
{
item.Bind(skillId);
return;
}
Text[] texts = instance.GetComponentsInChildren<Text>(true);
for (int i = 0; i < texts.Length; i++)
{
if (texts[i] != null)
{
texts[i].text = $"Skill {skillId}";
break;
}
}
}
private void ClearSkillPrefabs()
{
ClearChildren(sasParent);
ClearChildren(iasParent);
ClearChildren(mlsParent);
}
private static void ClearChildren(Transform parent)
{
if (parent == null)
{
return;
}
for (int i = parent.childCount - 1; i >= 0; i--)
{
Transform child = parent.GetChild(i);
if (Application.isPlaying)
{
Destroy(child.gameObject);
}
else
{
DestroyImmediate(child.gameObject);
}
}
}
private static void SetGroupActive(Text title, Text detail, GameObject space, Transform skillParent, bool active)
{
if (title != null)
{
title.gameObject.SetActive(active);
}
if (detail != null)
{
detail.gameObject.SetActive(active);
}
if (space != null)
{
space.SetActive(active);
}
if (skillParent != null)
{
skillParent.gameObject.SetActive(active);
}
}
private bool HasSectionContent(equipmentSO.EquipmentSpecialEffect[] effects, int skillId)
{
if (skillId > 0)
{
return true;
}
if (effects == null)
{
return false;
}
for (int i = 0; i < effects.Length; i++)
{
if (effects[i] != null &&
effects[i].effectType != equipmentSO.EquipmentSpecialEffectType.Skill &&
!Mathf.Approximately(effects[i].value, 0f))
{
return true;
}
}
return false;
}
private static bool HasSkillEffect(equipmentSO.EquipmentSpecialEffect[] effects)
{
if (effects == null)
{
return false;
}
for (int i = 0; i < effects.Length; i++)
{
if (effects[i] != null && effects[i].effectType == equipmentSO.EquipmentSpecialEffectType.Skill)
{
return true;
}
}
return false;
}
private string BuildBasicAttributesText(equipmentSO equipment)
{
if (equipment == null)
{
return string.Empty;
}
var lines = new List<string>();
AppendBasicLine(lines, "最大生命", equipment.maxHp);
AppendBasicLine(lines, "攻击力", equipment.attack);
AppendBasicLine(lines, "最大法力", equipment.maxMana);
AppendBasicLine(lines, "伤害减免", equipment.damageResistance);
AppendBasicLine(lines, "得分效率", equipment.scoreEfficiency);
return string.Join("\n", lines);
}
private void AppendBasicLine(List<string> lines, string label, equipmentSO.EquipmentStatTuning tuning)
{
if (lines == null || tuning == null)
{
return;
}
float baseValue = tuning.basicGain;
if (Mathf.Approximately(baseValue, 0f))
{
return;
}
float levelGain = eSO != null ? Mathf.Max(0, eSO.level) * tuning.cultivationInterval : 0f;
float total = baseValue + levelGain;
if (eSO == null || Mathf.Max(0, eSO.level) <= 0 || Mathf.Approximately(levelGain, 0f))
{
lines.Add($"{label}{FormatTotalPercent(baseValue)}");
return;
}
lines.Add(
$"{label}{FormatTotalPercent(total)} " +
$"(<color=#ADD8E6>{FormatComponentPercent(baseValue)}</color>+<color=#F0E68C>{FormatComponentPercent(levelGain)}</color>)");
}
private string BuildEffectText(equipmentSO.EquipmentSpecialEffect[] effects, out int skillId)
{
skillId = 0;
if (effects == eSO?.specialEffects)
{
skillId = eSO != null ? eSO.sa_skillID : 0;
}
else if (effects == eSO?.illusionEffects)
{
skillId = eSO != null ? eSO.ia_skillID : 0;
}
if (effects == null || effects.Length == 0)
{
return string.Empty;
}
var lines = new List<string>();
for (int i = 0; i < effects.Length; i++)
{
equipmentSO.EquipmentSpecialEffect effect = effects[i];
if (effect == null)
{
continue;
}
if (effect.effectType == equipmentSO.EquipmentSpecialEffectType.Skill)
{
continue;
}
if (Mathf.Approximately(effect.value, 0f))
{
continue;
}
lines.Add($"{GetEffectDisplayName(effect.effectType)}{FormatSignedValue(effect.value)}");
}
return string.Join("\n", lines);
}
private Sprite GetBottomSprite(int qualityIndex)
{
if (eqpmtBtmSprites == null || eqpmtBtmSprites.Length == 0)
{
return null;
}
int safeIndex = Mathf.Clamp(qualityIndex, 0, eqpmtBtmSprites.Length - 1);
return eqpmtBtmSprites[safeIndex];
}
private Color GetProfileColor(int qualityIndex)
{
if (profilebtmColor == null || profilebtmColor.Length == 0)
{
return Color.white;
}
int safeIndex = Mathf.Clamp(qualityIndex, 0, profilebtmColor.Length - 1);
return profilebtmColor[safeIndex];
}
private static int GetQualityVisualIndex(int level)
{
if (level >= 20)
{
return 5;
}
if (level >= 15)
{
return 4;
}
if (level >= 10)
{
return 3;
}
if (level >= 5)
{
return 2;
}
return 1;
}
private static string GetEffectDisplayName(equipmentSO.EquipmentSpecialEffectType effectType)
{
switch (effectType)
{
case equipmentSO.EquipmentSpecialEffectType.MaxHp: return "最大生命";
case equipmentSO.EquipmentSpecialEffectType.Attack: return "攻击力";
case equipmentSO.EquipmentSpecialEffectType.MaxMana: return "最大法力";
case equipmentSO.EquipmentSpecialEffectType.DamageResistance: return "伤害减免";
case equipmentSO.EquipmentSpecialEffectType.ScoreEfficiency: return "得分效率";
case equipmentSO.EquipmentSpecialEffectType.HitManaRecovery: return "hit法力恢复";
case equipmentSO.EquipmentSpecialEffectType.HitDamageMultiplier: return "hit伤害倍率";
case equipmentSO.EquipmentSpecialEffectType.HpLoseBase: return "hplosebase";
case equipmentSO.EquipmentSpecialEffectType.Skill: return "技能";
default: return effectType.ToString();
}
}
private static string FormatTotalPercent(float value)
{
float percent = value * 100f;
return $"{(percent >= 0f ? "+" : string.Empty)}{percent:0.0}%";
}
private static string FormatComponentPercent(float value)
{
float percent = value * 100f;
return $"{percent:0.0}%";
}
private static string FormatSignedValue(float value)
{
return $"{(value >= 0f ? "+" : string.Empty)}{value:0.####}";
}
private static string BuildDisplayEquipmentId(equipmentSO equipment)
{
if (equipment == null || string.IsNullOrWhiteSpace(equipment.name))
{
return string.Empty;
}
string raw = equipment.name;
bool isPreview = raw.Contains("(Clone)") || raw.Contains("(TourPreview)");
raw = raw.Replace("(Clone)", string.Empty).Replace("(TourPreview)", string.Empty).Trim();
if (raw.StartsWith("type"))
{
raw = raw.Substring(4);
}
return isPreview ? $"{raw}(Preview)" : raw;
}
private static bool IsTourPreviewEquipment(equipmentSO equipment)
{
return equipment != null &&
!string.IsNullOrWhiteSpace(equipment.name) &&
equipment.name.Contains("(TourPreview)");
}
}