852 lines
25 KiB
C#
852 lines
25 KiB
C#
using System.Collections.Generic;
|
|
using Spine.Unity;
|
|
using UnityEngine;
|
|
using UnityEngine.EventSystems;
|
|
using UnityEngine.UI;
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
#endif
|
|
|
|
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("spine particles")]
|
|
public GameObject golden_particle;
|
|
public GameObject red_particle;
|
|
public GameObject pink_particle;
|
|
|
|
[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 eqpmtType;
|
|
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;
|
|
public GameObject eqpSpace;
|
|
public GameObject whoEquipping;
|
|
public Image equipperProfile;
|
|
public Text equipperName;
|
|
|
|
[Header("objs")]
|
|
public GameObject eqpmtSkillPrefab;
|
|
public Transform sasParent;
|
|
public Transform iasParent;
|
|
public Transform mlsParent;
|
|
[Header("es description")]
|
|
public GameObject esDesPrefab;
|
|
public Vector2 esDesPrefabOffset = new Vector2(20f, 30f);
|
|
|
|
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)
|
|
{
|
|
ApplySpineParticles(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);
|
|
ApplyEquipperInfo(null);
|
|
return;
|
|
}
|
|
|
|
equipmentSO.EquipmentTierPresentation presentation = ResolveTierPresentation(eSO);
|
|
string displayName = eSO.GetDisplayTierName();
|
|
if (string.IsNullOrWhiteSpace(displayName))
|
|
{
|
|
displayName = eSO.name;
|
|
}
|
|
Sprite displaySprite = presentation != null ? presentation.equipmentSprite : null;
|
|
string description = eSO.GetDisplayTierDescription();
|
|
|
|
ApplySpineParticles(eSO);
|
|
ApplyHeader(displayName, displaySprite, GetQualityVisualIndex(eSO), description);
|
|
ApplyEquipperInfo(eSO);
|
|
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 void ApplySpineParticles(equipmentSO equipment)
|
|
{
|
|
bool showGolden = false;
|
|
bool showRed = false;
|
|
bool showPink = false;
|
|
|
|
if (equipment != null)
|
|
{
|
|
int level = Mathf.Max(0, equipment.level);
|
|
bool hasFinalDreamEffect = equipment.HasFinalDreamEffect();
|
|
|
|
if (level >= 20 && hasFinalDreamEffect)
|
|
{
|
|
showPink = true;
|
|
}
|
|
else if (level >= 15)
|
|
{
|
|
showRed = true;
|
|
}
|
|
else if (level >= 10)
|
|
{
|
|
showGolden = true;
|
|
}
|
|
}
|
|
|
|
if (golden_particle != null)
|
|
{
|
|
golden_particle.SetActive(showGolden);
|
|
}
|
|
|
|
if (red_particle != null)
|
|
{
|
|
red_particle.SetActive(showRed);
|
|
}
|
|
|
|
if (pink_particle != null)
|
|
{
|
|
pink_particle.SetActive(showPink);
|
|
}
|
|
}
|
|
|
|
|
|
private static void ConfigureSpineParticleRenderers(GameObject target)
|
|
{
|
|
if (target == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
SkeletonGraphic[] skeletonGraphics = target.GetComponentsInChildren<SkeletonGraphic>(true);
|
|
for (int i = 0; i < skeletonGraphics.Length; i++)
|
|
{
|
|
SkeletonGraphic skeletonGraphic = skeletonGraphics[i];
|
|
if (skeletonGraphic == null || skeletonGraphic.allowMultipleCanvasRenderers)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
skeletonGraphic.allowMultipleCanvasRenderers = true;
|
|
skeletonGraphic.Initialize(true);
|
|
skeletonGraphic.SetMaterialDirty();
|
|
skeletonGraphic.SetVerticesDirty();
|
|
}
|
|
}
|
|
private void ApplyEquipperInfo(equipmentSO equipment)
|
|
{
|
|
AllyHero_SO equipper = FindEquipper(equipment);
|
|
bool hasEquipper = equipper != null;
|
|
|
|
if (whoEquipping != null)
|
|
{
|
|
whoEquipping.SetActive(hasEquipper);
|
|
}
|
|
|
|
if (eqpSpace != null)
|
|
{
|
|
eqpSpace.SetActive(hasEquipper);
|
|
}
|
|
|
|
if (equipperProfile != null)
|
|
{
|
|
equipperProfile.sprite = hasEquipper ? equipper.ally_hero_squareProfile : null;
|
|
equipperProfile.color = hasEquipper && equipper.ally_hero_squareProfile != null ? Color.white : new Color(1f, 1f, 1f, 0f);
|
|
}
|
|
|
|
if (equipperName != null)
|
|
{
|
|
equipperName.text = hasEquipper ? equipper.ally_heroName : string.Empty;
|
|
}
|
|
}
|
|
|
|
private AllyHero_SO FindEquipper(equipmentSO equipment)
|
|
{
|
|
if (equipment == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
AllyHero_SO[] heroes = LoadHeroAssets();
|
|
for (int i = 0; i < heroes.Length; i++)
|
|
{
|
|
AllyHero_SO hero = heroes[i];
|
|
if (hero == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
hero.LoadEquippedEquipmentFromLocal();
|
|
equipmentSO equipped = hero.GetEquippedEquipmentResolved();
|
|
if (equipped == equipment || (!string.IsNullOrWhiteSpace(equipped?.name) && equipped.name == equipment.name))
|
|
{
|
|
return hero;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private AllyHero_SO[] LoadHeroAssets()
|
|
{
|
|
#if UNITY_EDITOR
|
|
if (!Application.isPlaying)
|
|
{
|
|
string[] guids = AssetDatabase.FindAssets("t:AllyHero_SO", new[] { "Assets/Resources/so/ally" });
|
|
var heroes = new List<AllyHero_SO>(guids.Length);
|
|
for (int i = 0; i < guids.Length; i++)
|
|
{
|
|
string path = AssetDatabase.GUIDToAssetPath(guids[i]);
|
|
AllyHero_SO hero = AssetDatabase.LoadAssetAtPath<AllyHero_SO>(path);
|
|
if (hero != null)
|
|
{
|
|
heroes.Add(hero);
|
|
}
|
|
}
|
|
|
|
return heroes.ToArray();
|
|
}
|
|
#endif
|
|
|
|
return RuntimeResourcesCache.LoadAllAllyHeroes();
|
|
}
|
|
|
|
private equipmentSO.EquipmentTierPresentation ResolveTierPresentation(equipmentSO equipment)
|
|
{
|
|
if (equipment == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (equipment.tierNameConfig != null &&
|
|
equipment.tierNameConfig.TryGetStagePresentation(equipment.skillType, equipment.GetVisualTierStageIndex(), out equipmentTierNameConfigSO.StagePresentation stage) &&
|
|
stage != null)
|
|
{
|
|
return new equipmentSO.EquipmentTierPresentation
|
|
{
|
|
tierName = stage.tierName,
|
|
equipmentSprite = stage.equipmentSprite,
|
|
tierDescription = stage.tierDescription
|
|
};
|
|
}
|
|
|
|
return equipment.GetVisualTierPresentation();
|
|
}
|
|
|
|
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 (eqpmtType != null)
|
|
{
|
|
eqpmtType.text = eSO != null ? eSO.skillType.ToString() : string.Empty;
|
|
}
|
|
|
|
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}";
|
|
SkillGroup skillGroup = EquipmentSkillGroupLibrary.ResolveSkillGroup(skillId);
|
|
string displayName = skillGroup != null && !string.IsNullOrWhiteSpace(skillGroup.groupName)
|
|
? skillGroup.groupName
|
|
: $"Skill {skillId}";
|
|
Sprite displayIcon = skillGroup != null ? skillGroup.groupIcon : null;
|
|
|
|
esPrefab legacyItem = instance.GetComponent<esPrefab>();
|
|
if (legacyItem != null)
|
|
{
|
|
legacyItem.BindSkillGroup(skillId, displayName, displayIcon, esDesPrefab, transform as RectTransform, esDesPrefabOffset);
|
|
|
|
return;
|
|
}
|
|
|
|
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 = displayName;
|
|
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, equipmentSO.EquipmentSpecialEffectType.MaxHp);
|
|
AppendBasicLine(lines, "攻击力", equipment.attack, equipmentSO.EquipmentSpecialEffectType.Attack);
|
|
AppendBasicLine(lines, "最大法力", equipment.maxMana, equipmentSO.EquipmentSpecialEffectType.MaxMana);
|
|
AppendBasicLine(lines, "伤害减免", equipment.damageResistance, equipmentSO.EquipmentSpecialEffectType.DamageResistance);
|
|
AppendBasicLine(lines, "得分效率", equipment.scoreEfficiency, equipmentSO.EquipmentSpecialEffectType.ScoreEfficiency);
|
|
return string.Join("\n", lines);
|
|
}
|
|
|
|
private void AppendBasicLine(List<string> lines, string label, equipmentSO.EquipmentStatTuning tuning, equipmentSO.EquipmentSpecialEffectType effectType)
|
|
{
|
|
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 finalDreamGain = GetMaxLevelBoost(effectType);
|
|
float total = baseValue + levelGain + finalDreamGain;
|
|
|
|
if (eSO == null || (Mathf.Max(0, eSO.level) <= 0 && Mathf.Approximately(finalDreamGain, 0f)))
|
|
{
|
|
lines.Add($"{label}{FormatTotalPercent(baseValue + finalDreamGain)}");
|
|
return;
|
|
}
|
|
|
|
string componentText = $"<color=#ADD8E6>{FormatComponentPercent(baseValue)}</color>";
|
|
if (!Mathf.Approximately(levelGain, 0f))
|
|
{
|
|
componentText += $"+<color=#F0E68C>{FormatComponentPercent(levelGain)}</color>";
|
|
}
|
|
|
|
if (!Mathf.Approximately(finalDreamGain, 0f))
|
|
{
|
|
componentText += $"+<color=#FF67A4>{FormatComponentPercent(finalDreamGain)}</color>";
|
|
}
|
|
|
|
lines.Add($"{label}{FormatTotalPercent(total)} ({componentText})");
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
bool isTypeSameEffectSection = effects == eSO?.typeSameEffects;
|
|
bool isMaxLevelEffectSection = effects == eSO?.maxLevelEffects;
|
|
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;
|
|
}
|
|
|
|
string valueText = (isTypeSameEffectSection || isMaxLevelEffectSection)
|
|
? FormatSignedPercent(effect.value)
|
|
: FormatSignedValue(effect.value);
|
|
lines.Add($"{GetEffectDisplayName(effect.effectType)}{valueText}");
|
|
}
|
|
|
|
return string.Join("\n", lines);
|
|
}
|
|
|
|
private float GetMaxLevelBoost(equipmentSO.EquipmentSpecialEffectType effectType)
|
|
{
|
|
if (eSO == null || eSO.maxLevelEffects == null)
|
|
{
|
|
return 0f;
|
|
}
|
|
|
|
for (int i = 0; i < eSO.maxLevelEffects.Length; i++)
|
|
{
|
|
equipmentSO.EquipmentSpecialEffect effect = eSO.maxLevelEffects[i];
|
|
if (effect == null || effect.effectType != effectType)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
return effect.value;
|
|
}
|
|
|
|
return 0f;
|
|
}
|
|
|
|
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(equipmentSO equipment)
|
|
{
|
|
if (equipment == null)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return equipment.GetVisualQualityColorIndex();
|
|
}
|
|
|
|
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 FormatSignedPercent(float value)
|
|
{
|
|
float percent = value * 100f;
|
|
return $"{(percent >= 0f ? "+" : string.Empty)}{percent: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)");
|
|
}
|
|
}
|
|
|
|
|