完成编队 增加多个细节和小功能

This commit is contained in:
FloatGaming
2025-12-10 19:12:27 +08:00
parent c0a822b958
commit edc2608f47
131 changed files with 11889 additions and 127 deletions
@@ -46,7 +46,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
@@ -138,7 +138,7 @@ TextureImporter:
customData:
physicsShape: []
bones: []
spriteID:
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
@@ -46,7 +46,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
@@ -138,7 +138,7 @@ TextureImporter:
customData:
physicsShape: []
bones: []
spriteID:
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
@@ -147,7 +147,8 @@ TextureImporter:
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
nameFileIdTable:
F@4x_0: 2696126732994276316
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
@@ -46,7 +46,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
@@ -138,7 +138,7 @@ TextureImporter:
customData:
physicsShape: []
bones: []
spriteID:
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
@@ -147,7 +147,8 @@ TextureImporter:
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
nameFileIdTable:
SS@4x_0: 8145665558145031127
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
@@ -46,7 +46,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
@@ -138,7 +138,7 @@ TextureImporter:
customData:
physicsShape: []
bones: []
spriteID:
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
@@ -147,7 +147,8 @@ TextureImporter:
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
nameFileIdTable:
"\u753B\u677F B@4x_0": -3477052224104452790
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
@@ -46,7 +46,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
@@ -138,7 +138,7 @@ TextureImporter:
customData:
physicsShape: []
bones: []
spriteID:
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
@@ -147,7 +147,8 @@ TextureImporter:
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
nameFileIdTable:
"\u753B\u677F C@4x_0": 753916413009869570
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
@@ -46,7 +46,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
@@ -138,7 +138,7 @@ TextureImporter:
customData:
physicsShape: []
bones: []
spriteID:
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
@@ -147,7 +147,8 @@ TextureImporter:
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
nameFileIdTable:
"\u753B\u677F D@4x_0": 5824227667964995878
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
@@ -46,7 +46,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
@@ -138,7 +138,7 @@ TextureImporter:
customData:
physicsShape: []
bones: []
spriteID:
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
@@ -147,7 +147,8 @@ TextureImporter:
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
nameFileIdTable:
"\u753B\u677F E@4x_0": 6528632934354270552
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
@@ -46,7 +46,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
@@ -138,7 +138,7 @@ TextureImporter:
customData:
physicsShape: []
bones: []
spriteID:
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
@@ -147,7 +147,8 @@ TextureImporter:
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
nameFileIdTable:
"\u753B\u677F EASE@4x_0": -1313005266698724572
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
@@ -46,7 +46,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
@@ -138,7 +138,7 @@ TextureImporter:
customData:
physicsShape: []
bones: []
spriteID:
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
@@ -147,7 +147,8 @@ TextureImporter:
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
nameFileIdTable:
"\u753B\u677F S@4x_0": -7571068170699483926
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
@@ -46,7 +46,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
@@ -138,7 +138,7 @@ TextureImporter:
customData:
physicsShape: []
bones: []
spriteID:
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
@@ -147,7 +147,8 @@ TextureImporter:
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
nameFileIdTable:
"\u753B\u677F UF@4x_0": 6470357825098895925
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
@@ -46,7 +46,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
@@ -138,7 +138,7 @@ TextureImporter:
customData:
physicsShape: []
bones: []
spriteID:
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
@@ -147,7 +147,8 @@ TextureImporter:
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
nameFileIdTable:
"\u753B\u677FA@4x_0": -6973214586806606383
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
@@ -0,0 +1,120 @@
using UnityEngine;
using UnityEngine.UI;
public class RatioBar : MonoBehaviour
{
[Header("子Image组件")]
public Image bar1; // 红色段
public Image bar2; // 橘色段
public Image bar3; // 黄色段
public Image bar4; // 第四段
[Header("分割点 (0-1)")]
[Range(0, 1)] public float ratio1 = 0.3f; // 颜色1结束位置
[Range(0, 1)] public float ratio2 = 0.6f; // 颜色2结束位置
[Range(0, 1)] public float ratio3 = 1.0f; // 颜色3结束位置,必须为1
[Header("长度控制")]
public float totalLength = 400f; // 前三个bar的总长度
public float bar4Length = 50f; // bar4的单独长度
[Header("高度控制")]
public float barHeight = 50f; // 四个bar的统一高度
[Header("颜色设置")]
public Color color1 = Color.red;
public Color color2 = new Color(1f, 0.5f, 0f); // 橘色
public Color color3 = Color.yellow;
public Color color4 = Color.green; // 第四段颜色
private float lastRatio1, lastRatio2, lastRatio3, lastTotalLength, lastBar4Length, lastBarHeight;
[Header("damageMulti")]
public Text damageMulti_miss;
public Text damageMulti_good;
public Text damageMulti_great;
public Text damageMulti_perfect;
[Header("manaGain")]
public Text manaGain_miss;
public Text manaGain_good;
public Text manaGain_great;
public Text manaGain_perfect;
void Update()
{
if (bar1 == null || bar2 == null || bar3 == null || bar4 == null) return;
// 检查值是否改变,避免不必要的更新
if (ratio1 == lastRatio1 && ratio2 == lastRatio2 && ratio3 == lastRatio3 && totalLength == lastTotalLength && bar4Length == lastBar4Length && barHeight == lastBarHeight) return;
lastRatio1 = ratio1;
lastRatio2 = ratio2;
lastRatio3 = ratio3;
lastTotalLength = totalLength;
lastBar4Length = bar4Length;
lastBarHeight = barHeight;
// 强制ratio3为1,确保三个颜色加起来正好是1
ratio3 = 1.0f;
// 确保顺序
ratio1 = Mathf.Clamp(ratio1, 0, ratio2);
ratio2 = Mathf.Clamp(ratio2, ratio1, 1);
// 获取父对象的RectTransform
RectTransform parentRect = GetComponent<RectTransform>();
// 设置父对象大小为totalLength + bar4Length 宽度,barHeight 高度
parentRect.sizeDelta = new Vector2(totalLength + bar4Length, barHeight);
// 计算段长(基于totalLength
float len1 = ratio1 * totalLength;
float len2 = (ratio2 - ratio1) * totalLength;
float len3 = (ratio3 - ratio2) * totalLength;
// 设置每个bar的大小和位置
bar1.rectTransform.sizeDelta = new Vector2(len1, barHeight);
bar2.rectTransform.sizeDelta = new Vector2(len2, barHeight);
bar3.rectTransform.sizeDelta = new Vector2(len3, barHeight);
bar4.rectTransform.sizeDelta = new Vector2(bar4Length, barHeight);
bar1.rectTransform.anchoredPosition = new Vector2(0, 0);
bar2.rectTransform.anchoredPosition = new Vector2(len1, 0);
bar3.rectTransform.anchoredPosition = new Vector2(len1 + len2, 0);
bar4.rectTransform.anchoredPosition = new Vector2(totalLength, 0);
// 设置颜色
bar1.color = color1;
bar2.color = color2;
bar3.color = color3;
bar4.color = color4;
}
// 设置manaGain和damageMulti文本
public void SetManaAndDamage(AllyHero_SO heroSO)
{
if (heroSO == null) return;
var levelInfo = heroSO.GetEffectiveLevelForCurrentEXP();
if (levelInfo == null) return;
// 设置manaGain
if (manaGain_miss != null) manaGain_miss.text = levelInfo.manaGainOnMiss.ToString();
if (manaGain_good != null) manaGain_good.text = levelInfo.manaGainGood.ToString();
if (manaGain_great != null) manaGain_great.text = levelInfo.manaGainGreat.ToString();
if (manaGain_perfect != null) manaGain_perfect.text = levelInfo.manaGainPerfect.ToString();
// 设置damageMulti
if (damageMulti_miss != null) damageMulti_miss.text = "0";
if (damageMulti_good != null) damageMulti_good.text = levelInfo.damageMultiplierGood.ToString();
if (damageMulti_great != null) damageMulti_great.text = levelInfo.damageMultiplierGreat.ToString();
if (damageMulti_perfect != null) damageMulti_perfect.text = levelInfo.damageMultiplierPerfect.ToString();
// 设置ratio
ratio1 = levelInfo.damageMultiplierGood;
ratio2 = levelInfo.damageMultiplierGreat;
ratio3 = levelInfo.damageMultiplierPerfect;
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 0e5edd01c661fd34db669441b899b370
@@ -0,0 +1,96 @@
using System.ComponentModel;
using UnityEngine;
using UnityEngine.UI;
public class basicInfoBars : MonoBehaviour
{
[SerializeField] protected int imageLength;
[SerializeField] protected int imageHeight;
[Header("images")]
public Image attackImage;
public Image maxHP_Image;
public Image damageResistanceImage;
public Image basicManaImage;
public Image scoreEffeciencyImage;
public Image missDamageImage;
[Header("maxValues")]
public int maxAttackValue = 999;
public int maxHP_Value = 9999;
public float maxDamageResistanceValue = 1f;
public int maxBasicManaValue = 999;
public float maxScoreEfficiencyValue = 1f;
public int maxMissDamageValue = 99;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
}
// Update is called once per frame
void Update()
{
}
// 设置攻击进度条
public void SetAttack(int value)
{
if (attackImage != null)
{
float clampedValue = Mathf.Clamp(value, 0, maxAttackValue);
attackImage.fillAmount = clampedValue / maxAttackValue;
}
}
// 设置最大HP进度条
public void SetMaxHP(int value)
{
if (maxHP_Image != null)
{
float clampedValue = Mathf.Clamp(value, 0, maxHP_Value);
maxHP_Image.fillAmount = clampedValue / maxHP_Value;
}
}
// 设置伤害抗性进度条
public void SetDamageResistance(float value)
{
if (damageResistanceImage != null)
{
float clampedValue = Mathf.Clamp(value, 0f, maxDamageResistanceValue);
damageResistanceImage.fillAmount = clampedValue / maxDamageResistanceValue;
}
}
// 设置基础法力进度条
public void SetBasicMana(int value)
{
if (basicManaImage != null)
{
float clampedValue = Mathf.Clamp(value, 0, maxBasicManaValue);
basicManaImage.fillAmount = clampedValue / maxBasicManaValue;
}
}
// 设置分数效率进度条
public void SetScoreEfficiency(float value)
{
if (scoreEffeciencyImage != null)
{
float clampedValue = Mathf.Clamp(value, 0f, maxScoreEfficiencyValue);
scoreEffeciencyImage.fillAmount = clampedValue / maxScoreEfficiencyValue;
}
}
// 设置Miss伤害进度条
public void SetMissDamage(int value)
{
if (missDamageImage != null)
{
float clampedValue = Mathf.Clamp(value, 0, maxMissDamageValue);
missDamageImage.fillAmount = clampedValue / maxMissDamageValue;
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 1e9aef44e3aada14282c7059a761695c
@@ -0,0 +1,106 @@
using UnityEngine;
using UnityEngine.UI;
public class character_detailInformation : MonoBehaviour
{
[Header("立绘HD")]
public Image character_HDImage;
public Image character_HDImage_shadow;
[Header("so")]
public ScriptableObject characterSO;
[Header("基础信息文本")]
public Text basic_infoText;
public Text designation_name_combination;
[Header("进度条控制器")]
public basicInfoBars infoBars;
[Header("等级条控制器")]
public levelBar_controller levelBar;
[Header("RatioBar控制器")]
public RatioBar ratioBar;
[Header("shutdown")]
public Button shut_button;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
// 添加关闭按钮监听器
if (shut_button != null)
{
shut_button.onClick.AddListener(ShutDown);
}
if (characterSO is AllyHero_SO heroSO)
{
// 设置HD图像
if (character_HDImage != null && heroSO.ally_hero_HD_image != null)
{
character_HDImage.sprite = heroSO.ally_hero_HD_image;
}
// 设置HD阴影图像
if (character_HDImage_shadow != null && heroSO.ally_hero_HD_image != null)
{
character_HDImage_shadow.sprite = heroSO.ally_hero_HD_image;
}
// 组合称号和名字
if (designation_name_combination != null)
{
designation_name_combination.text = $"{heroSO.ally_heroDesignation} {heroSO.ally_heroName}";
}
// 获取当前等级数据
var levelInfo = heroSO.GetEffectiveLevelForCurrentEXP();
if (levelInfo != null)
{
int attack = levelInfo.attack;
int maxHP = levelInfo.maxHP;
float damageResistance = levelInfo.damageResistance;
int maxMana = levelInfo.maxMana;
float scoreEfficiency = levelInfo.scoreEfficiency;
float missHpLoss = levelInfo.missHpLossBase;
// 输出到basic_infoText
if (basic_infoText != null)
{
basic_infoText.text = $"{attack}\n{maxHP}\n{damageResistance * 100}%\n{maxMana}\n{scoreEfficiency * 100}%\n\n{missHpLoss}";
}
// 交给basicInfoBars设置进度条
if (infoBars != null)
{
infoBars.SetAttack(attack);
infoBars.SetMaxHP(maxHP);
infoBars.SetDamageResistance(damageResistance);
infoBars.SetBasicMana(maxMana);
infoBars.SetScoreEfficiency(scoreEfficiency);
infoBars.SetMissDamage((int)missHpLoss); // 假设missDamage是int
}
// 设置等级条
if (levelBar != null)
{
levelBar.SetLevelBar(heroSO);
}
// 设置RatioBar
if (ratioBar != null)
{
ratioBar.SetManaAndDamage(heroSO);
}
}
}
}
// Update is called once per frame
void Update()
{
}
// 关闭按钮点击事件:销毁整个prefab
private void ShutDown()
{
Destroy(gameObject);
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 77e7e53dceb9d774aaa429aa23730b07
@@ -11,7 +11,7 @@ GameObject:
- component: {fileID: 6988326929107498435}
- component: {fileID: 8690290934256204690}
- component: {fileID: 9211739895151529780}
- component: {fileID: 9051471772868642912}
- component: {fileID: 478932237340675732}
m_Layer: 0
m_Name: columnText
m_TagString: Untagged
@@ -70,7 +70,7 @@ MonoBehaviour:
m_Font: {fileID: 12800000, guid: cc180dff846d13a4d88ddaed6f77e5cd, type: 3}
m_FontSize: 20
m_FontStyle: 0
m_BestFit: 0
m_BestFit: 1
m_MinSize: 2
m_MaxSize: 40
m_Alignment: 3
@@ -80,7 +80,7 @@ MonoBehaviour:
m_VerticalOverflow: 0
m_LineSpacing: 1
m_Text: columnText
--- !u!114 &9051471772868642912
--- !u!114 &478932237340675732
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 59dfd4ddf9533f644aefd71f3260a05c
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,223 @@
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
public class levelBar_controller : MonoBehaviour
{
[Header("前后等级图")]
public Image pre_levelIcon_image;
public Image post_levelIcon_image;
[Header("CBAS")]
public Sprite icon_c;
public Sprite icon_b;
public Sprite icon_a;
public Sprite icon_s;
[Header("控制fill amount")]
public Image C_image;
public Image B_image;
public Image A_image;
public Image S_image;
[Header("ratioText")]
public Text ratioText;
[Header("remainingExpText")]
public Text remainingExpText;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
// 初始化CBAS images的fillAmount为0
/* if (C_image != null) C_image.fillAmount = 0f;
if (B_image != null) B_image.fillAmount = 0f;
if (A_image != null) A_image.fillAmount = 0f;
if (S_image != null) S_image.fillAmount = 0f;*/
}
// Update is called once per frame
void Update()
{
}
// 设置等级条
public void SetLevelBar(AllyHero_SO heroSO)
{
if (heroSO == null || heroSO.levelStats == null || heroSO.levelStats.Count == 0) return;
var levelInfo = heroSO.GetEffectiveLevelForCurrentEXP();
if (levelInfo == null) return;
string currentLevel = GetRatingFromSO(heroSO);
int currentIndex = GetIndex(currentLevel);
// 设置前等级icon
if (pre_levelIcon_image != null)
{
pre_levelIcon_image.sprite = GetLevelSprite(currentLevel);
}
// 设置后等级icon
if (post_levelIcon_image != null)
{
if (currentIndex < 3)
{
string nextLevel = GetNextLevel(currentLevel);
post_levelIcon_image.sprite = GetLevelSprite(nextLevel);
post_levelIcon_image.color = Color.white;
}
else
{
post_levelIcon_image.sprite = null;
post_levelIcon_image.color = new Color(1f, 1f, 1f, 0f);
}
}
int currentEXP = heroSO.ally_currentEXP;
// 设置fill amount
for (int i = 0; i < 4; i++)
{
Image img = GetImage(i);
if (img == null) continue;
if (i < currentIndex)
{
img.fillAmount = 1f;
}
else if (i == currentIndex)
{
if (currentIndex == 3) // S级满级
{
img.fillAmount = 1f;
}
else
{
int nextRequired = heroSO.levelStats[currentIndex + 1].requiredEXP;
if (currentEXP == nextRequired)
{
img.fillAmount = 0f; // 相等但非满级,设为0
}
else
{
img.fillAmount = (float)currentEXP / nextRequired;
}
}
}
else
{
img.fillAmount = 0f;
}
}
// 设置ratioText
if (ratioText != null)
{
if (currentIndex < 3)
{
int nextRequired = heroSO.levelStats[currentIndex + 1].requiredEXP;
ratioText.text = $"{currentEXP}/{nextRequired}";
}
else
{
ratioText.text = "MAX";
}
}
// 设置remainingExpText
if (remainingExpText != null)
{
if (currentIndex < 3)
{
int nextRequired = heroSO.levelStats[currentIndex + 1].requiredEXP;
int remaining = nextRequired - currentEXP;
remainingExpText.text = $"还需{remaining}经验升级";
}
else
{
remainingExpText.text = "等级满";
}
}
}
// 获取等级对应的sprite
private Sprite GetLevelSprite(string level)
{
switch (level)
{
case "C": return icon_c;
case "B": return icon_b;
case "A": return icon_a;
case "S": return icon_s;
default: return null;
}
}
// 获取等级索引
private int GetIndex(string level)
{
switch (level)
{
case "C": return 0;
case "B": return 1;
case "A": return 2;
case "S": return 3;
default: return 0;
}
}
// 获取下一等级
private string GetNextLevel(string level)
{
switch (level)
{
case "C": return "B";
case "B": return "A";
case "A": return "S";
default: return "S";
}
}
// 获取对应等级的Image
private Image GetImage(int index)
{
switch (index)
{
case 0: return C_image;
case 1: return B_image;
case 2: return A_image;
case 3: return S_image;
default: return null;
}
}
// 获取角色等级字符串(与loadTeam_select.cs一致)
private string GetRatingFromSO(AllyHero_SO so)
{
if (so == null || so.levelStats == null || so.levelStats.Count == 0) return "C";
// Build a sorted copy by requiredEXP ascending
List<AllyHero_SO.AllyLevelInfo> sorted = new List<AllyHero_SO.AllyLevelInfo>();
foreach (var l in so.levelStats) if (l != null) sorted.Add(l);
sorted.Sort((a, b) => a.requiredEXP.CompareTo(b.requiredEXP));
int currentExp = so.ally_currentEXP;
int selectedIndex = 0;
for (int i = 0; i < sorted.Count; i++)
{
if (currentExp >= sorted[i].requiredEXP)
{
selectedIndex = i;
}
else
{
break;
}
}
// Map indices to ratings: index 0 -> C, 1 -> B, 2 -> A, 3+ -> S
if (selectedIndex <= 0) return "C";
if (selectedIndex == 1) return "B";
if (selectedIndex == 2) return "A";
// for selectedIndex >= 3 (including when there are more than 4 levels), treat as S
return "S";
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 3ed7ad820d56bab43bf4b22f620ab6f1
@@ -60,8 +60,16 @@ public class loadDetailsPrefab : MonoBehaviour
if (rt != null)
{
Vector3 pos = position;
pos.x += offset.x;
pos.y += offset.y;
// 获取Canvas的scaleFactor来调整偏移量
float scaleFactor = 1f;
Transform parentTransform = detailsParent != null ? detailsParent.transform : transform;
Canvas canvas = parentTransform.GetComponentInParent<Canvas>();
if (canvas != null)
{
scaleFactor = canvas.scaleFactor;
}
pos.x += offset.x / scaleFactor;
pos.y += offset.y / scaleFactor;
float width = rt.rect.width;
float height = rt.rect.height;
@@ -23,6 +23,15 @@ public class loadSkillsSelect : MonoBehaviour
public int columnPaddingBottom = 0; // Bottom padding for the column
public float columnVerticalSpacing = 10f; // Vertical spacing between header and skills in a column
[Header("Skill Card Layout Settings")]
public bool skillCardUseLayoutElement = true; // Whether to add LayoutElement to skill cards
public float skillCardPreferredWidth = -1f; // Preferred width for skill cards (-1 to ignore)
public float skillCardPreferredHeight = -1f; // Preferred height for skill cards (-1 to ignore)
public float skillCardFlexibleWidth = -1f; // Flexible width for skill cards (-1 to ignore)
public float skillCardFlexibleHeight = -1f; // Flexible height for skill cards (-1 to ignore)
public int skillCardMinWidth = -1; // Minimum width for skill cards (-1 to ignore)
public int skillCardMinHeight = -1; // Minimum height for skill cards (-1 to ignore)
// 当前加载的英雄SO,用于技能卡片更新equippedSkillGroupIDs
public AllyHero_SO currentHeroSO { get; private set; }
@@ -197,6 +206,21 @@ public class loadSkillsSelect : MonoBehaviour
s.isSelected = false;
s.ApplyState();
// set skill card to read-only mode
s.isReadOnly = true;
// Add or configure LayoutElement if enabled
if (skillCardUseLayoutElement)
{
var le = go.GetComponent<UnityEngine.UI.LayoutElement>() ?? go.AddComponent<UnityEngine.UI.LayoutElement>();
if (skillCardPreferredWidth >= 0) le.preferredWidth = skillCardPreferredWidth;
if (skillCardPreferredHeight >= 0) le.preferredHeight = skillCardPreferredHeight;
if (skillCardFlexibleWidth >= 0) le.flexibleWidth = skillCardFlexibleWidth;
if (skillCardFlexibleHeight >= 0) le.flexibleHeight = skillCardFlexibleHeight;
if (skillCardMinWidth >= 0) le.minWidth = skillCardMinWidth;
if (skillCardMinHeight >= 0) le.minHeight = skillCardMinHeight;
}
// use the existing Button component on the skill card
if (s.skillCard_button != null)
{
@@ -218,5 +242,23 @@ public class loadSkillsSelect : MonoBehaviour
}
Debug.Log($"loadSkillsSelect: instantiated {created} skill cards for heroId={heroId}");
// Update skill card selections based on equipped groups
UpdateSkillCardSelections();
}
public void UpdateSkillCardSelections()
{
if (currentHeroSO == null) return;
var equipped = new System.Collections.Generic.HashSet<int>(currentHeroSO.equippedSkillGroupIDs);
foreach (Transform child in contentParent)
{
var slot = child.GetComponentInChildren<slots_skillSlots>();
if (slot != null)
{
slot.isSelected = equipped.Contains(slot.skillCard_skillID);
slot.ApplyState();
}
}
}
}
@@ -24,7 +24,12 @@ public class roleCard_prefabController : MonoBehaviour, IDropHandler, IBeginDrag
private Canvas rootCanvas;
private CanvasGroup canvasGroup;
void Start() { rootCanvas = GetComponentInParent<Canvas>(); }
void Start() { rootCanvas = GetComponentInParent<Canvas>();
if (roleCard_heroID > 0 && heroSO == null)
{
heroSO = FindAllyHeroSOById(roleCard_heroID);
}
}
void Update() { }
// Handle drop from CharacterCardView or roleCard prefabs (we won't set poster here)
@@ -33,11 +38,18 @@ public class roleCard_prefabController : MonoBehaviour, IDropHandler, IBeginDrag
Debug.Log($"roleCard OnDrop called on {gameObject.name}, pointerDrag={eventData.pointerDrag?.name}");
if (eventData.pointerDrag == null) return;
// Do not allow drops from other roleCard prefabs to prevent overwriting each other
var sourceRole = eventData.pointerDrag.GetComponent<roleCard_prefabController>();
if (sourceRole != null)
{
Debug.Log("roleCard OnDrop: ignoring drop from another roleCard prefab");
return;
}
// find CharacterCardView or other roleCard source
var sourceCard = eventData.pointerDrag.GetComponent<CharacterCardView>() ?? eventData.pointerDrag.GetComponentInParent<CharacterCardView>();
var sourceRole = eventData.pointerDrag.GetComponent<roleCard_prefabController>() ?? eventData.pointerDrag.GetComponentInParent<roleCard_prefabController>();
if (sourceCard == null && sourceRole == null)
if (sourceCard == null)
{
Debug.LogWarning("roleCard OnDrop: dragged object has no recognized source component");
return;
@@ -50,11 +62,6 @@ public class roleCard_prefabController : MonoBehaviour, IDropHandler, IBeginDrag
sourceId = sourceCard.characterID;
boundary = sourceCard.currentBoundaryLevel;
}
else if (sourceRole != null)
{
sourceId = sourceRole.roleCard_heroID;
// role source may not have boundary
}
// Transfer info: update roleCard display (profile and name)
roleCard_heroID = sourceId;
@@ -117,7 +117,7 @@ RectTransform:
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 120, y: 40}
m_SizeDelta: {x: 120, y: 30}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &6783521660050107131
CanvasRenderer:
@@ -147,8 +147,8 @@ MonoBehaviour:
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: -7185773671606137197, guid: a2fd1502cdd90de4a9af7a05d3ba1610, type: 3}
m_Type: 0
m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
@@ -156,7 +156,7 @@ MonoBehaviour:
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1.82
m_PixelsPerUnitMultiplier: 1
--- !u!114 &6227919512305899592
MonoBehaviour:
m_ObjectHideFlags: 0
@@ -262,6 +262,7 @@ MonoBehaviour:
skillColor_locked: {r: 0.81886786, g: 0.5299465, b: 0.5299465, a: 1}
isSelected: 0
heroId: 0
isReadOnly: 0
--- !u!1 &7891944755686443198
GameObject:
m_ObjectHideFlags: 0
@@ -296,8 +297,8 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: -47.35, y: 0}
m_SizeDelta: {x: 20, y: 20}
m_AnchoredPosition: {x: -45, y: 0}
m_SizeDelta: {x: 30, y: 30}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &5651005210691825991
CanvasRenderer:
@@ -327,8 +328,8 @@ MonoBehaviour:
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
@@ -34,8 +34,8 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 200, y: 30}
m_AnchoredPosition: {x: 8.0421, y: 3.5}
m_SizeDelta: {x: 183.9157, y: 30.5529}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &6239950258831979156
CanvasRenderer:
@@ -58,7 +58,7 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.122641504, g: 0.122641504, b: 0.122641504, a: 1}
m_Color: {r: 0.9622642, g: 0.9622642, b: 0.9622642, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
@@ -67,12 +67,12 @@ MonoBehaviour:
m_Calls: []
m_FontData:
m_Font: {fileID: 12800000, guid: cc180dff846d13a4d88ddaed6f77e5cd, type: 3}
m_FontSize: 24
m_FontSize: 18
m_FontStyle: 0
m_BestFit: 0
m_MinSize: 2
m_MinSize: 1
m_MaxSize: 40
m_Alignment: 4
m_Alignment: 3
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 0
@@ -90,6 +90,7 @@ GameObject:
- component: {fileID: 3540761466598488858}
- component: {fileID: 7623010645365366267}
- component: {fileID: 1148509882617417704}
- component: {fileID: 8422361834202200019}
m_Layer: 0
m_Name: nameTextBottom
m_TagString: Untagged
@@ -106,16 +107,16 @@ RectTransform:
m_GameObject: {fileID: 1388826347110131287}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0.8, y: 0.8, z: 0.8}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 1
m_Children:
- {fileID: 1476567720918343532}
m_Father: {fileID: 505709450491090271}
m_Father: {fileID: 1069940504772234767}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: -206.39001}
m_SizeDelta: {x: 226, y: 62}
m_AnchoredPosition: {x: 98.19645, y: 13.335907}
m_SizeDelta: {x: 203.6091, y: 41.8408}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &7623010645365366267
CanvasRenderer:
@@ -138,15 +139,15 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_Color: {r: 0, g: 0, b: 0, a: 0.36078432}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: -7185773671606137197, guid: a2fd1502cdd90de4a9af7a05d3ba1610, type: 3}
m_Type: 0
m_Sprite: {fileID: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
@@ -154,7 +155,20 @@ MonoBehaviour:
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
m_PixelsPerUnitMultiplier: 2
--- !u!114 &8422361834202200019
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1388826347110131287}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 31a19414c41e5ae4aae2af33fee712f6, type: 3}
m_Name:
m_EditorClassIdentifier:
m_ShowMaskGraphic: 1
--- !u!1 &2696693463715882529
GameObject:
m_ObjectHideFlags: 0
@@ -308,7 +322,7 @@ RectTransform:
m_Children:
- {fileID: 1069940504772234767}
- {fileID: 2481977685806833048}
- {fileID: 3540761466598488858}
- {fileID: 5963241098399977379}
- {fileID: 6916506249471759434}
- {fileID: 6919908692958857229}
m_Father: {fileID: 0}
@@ -337,6 +351,7 @@ MonoBehaviour:
heroImage: {fileID: 6680939226128776059}
heroLevelImage: {fileID: 937097627106398845}
thisHero_detail_displayButton: {fileID: 1089004877857606799}
thisHero_detial_panelObject: {fileID: 3721889475878020754, guid: 59dfd4ddf9533f644aefd71f3260a05c, type: 3}
defaultHeroSprite: {fileID: 4831566642180743177, guid: 1d13657d89048be45a1165cba085b7dc, type: 3}
headerImage_colors:
- {r: 1, g: 1, b: 1, a: 1}
@@ -344,6 +359,12 @@ MonoBehaviour:
- {r: 1, g: 1, b: 1, a: 1}
- {r: 1, g: 1, b: 1, a: 1}
- {r: 1, g: 1, b: 1, a: 1}
skillContainer: {fileID: 3121310117852151690}
skillCardPrefab: {fileID: 6849663232819926772, guid: cd57e902147b2744ea30e7e412013adc, type: 3}
levelIcon_sprite_C: {fileID: 21300000, guid: a919404cd6477be4c878442426de1d13, type: 3}
levelIcon_sprite_B: {fileID: 21300000, guid: ff77da93eaa5bdd44966dad03e35f56b, type: 3}
levelIcon_sprite_A: {fileID: 21300000, guid: 61dd84e2a30a06a4b913933e34767f4b, type: 3}
levelIcon_sprite_S: {fileID: 21300000, guid: 8f6b0c65c13b1ed478dd3f37e989f2c5, type: 3}
--- !u!225 &3635589955459441602
CanvasGroup:
m_ObjectHideFlags: 0
@@ -356,6 +377,68 @@ CanvasGroup:
m_Interactable: 1
m_BlocksRaycasts: 1
m_IgnoreParentGroups: 0
--- !u!1 &3121310117852151690
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5963241098399977379}
- component: {fileID: 1481319262819956495}
m_Layer: 0
m_Name: selected_skillCards_List
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &5963241098399977379
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3121310117852151690}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: -2.9569368}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 505709450491090271}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: -50, y: -21.63324}
m_SizeDelta: {x: 100, y: 100}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1481319262819956495
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3121310117852151690}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Padding:
m_Left: 0
m_Right: 0
m_Top: 0
m_Bottom: 0
m_ChildAlignment: 1
m_Spacing: 40
m_ChildForceExpandWidth: 1
m_ChildForceExpandHeight: 0
m_ChildControlWidth: 0
m_ChildControlHeight: 0
m_ChildScaleWidth: 0
m_ChildScaleHeight: 0
m_ReverseArrangement: 0
--- !u!1 &4429112831358588495
GameObject:
m_ObjectHideFlags: 0
@@ -414,7 +497,7 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.554717, g: 0.003139862, b: 0.5047549, a: 1}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
@@ -442,6 +525,7 @@ GameObject:
- component: {fileID: 1069940504772234767}
- component: {fileID: 2067139795496260713}
- component: {fileID: 6680939226128776059}
- component: {fileID: 7272653038034623668}
m_Layer: 0
m_Name: Image
m_TagString: Untagged
@@ -460,7 +544,8 @@ RectTransform:
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 1
m_Children: []
m_Children:
- {fileID: 3540761466598488858}
m_Father: {fileID: 505709450491090271}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
@@ -506,6 +591,19 @@ MonoBehaviour:
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &7272653038034623668
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4690235293395520502}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 31a19414c41e5ae4aae2af33fee712f6, type: 3}
m_Name:
m_EditorClassIdentifier:
m_ShowMaskGraphic: 1
--- !u!1 &6379783019369532990
GameObject:
m_ObjectHideFlags: 0
@@ -1,6 +1,7 @@
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections.Generic;
public class slots_heroSlots : MonoBehaviour, IDropHandler, IBeginDragHandler, IDragHandler, IEndDragHandler, IPointerClickHandler
{
@@ -13,6 +14,8 @@ public class slots_heroSlots : MonoBehaviour, IDropHandler, IBeginDragHandler, I
public Image heroLevelImage;
public Button thisHero_detail_displayButton; // ?
public GameObject thisHero_detial_panelObject;
[Header("default Sprite")]
public Sprite defaultHeroSprite;
@@ -25,6 +28,17 @@ public class slots_heroSlots : MonoBehaviour, IDropHandler, IBeginDragHandler, I
Color.white
};
[Header("Skills Container")]
public GameObject skillContainer; // Container with Vertical Layout Group for displaying equipped skills
public GameObject skillCardPrefab; // Prefab for skill cards, should have slots_skillSlots component
[Header("等级图片CBAS")]
public Sprite levelIcon_sprite_C;
public Sprite levelIcon_sprite_B;
public Sprite levelIcon_sprite_A;
public Sprite levelIcon_sprite_S;
private Canvas rootCanvas;
private CanvasGroup canvasGroup;
@@ -67,6 +81,18 @@ public class slots_heroSlots : MonoBehaviour, IDropHandler, IBeginDragHandler, I
{
heroImage.color = new Color(heroImage.color.r, heroImage.color.g, heroImage.color.b, 0f);
}
// ensure hero level image transparent if not set
if (heroLevelImage != null && heroLevelImage.sprite == null)
{
heroLevelImage.color = new Color(heroLevelImage.color.r, heroLevelImage.color.g, heroLevelImage.color.b, 0f);
}
// Add listener for detail display button
if (thisHero_detail_displayButton != null)
{
thisHero_detail_displayButton.onClick.AddListener(OnDetailButtonClicked);
}
}
private void OnValidate()
@@ -88,6 +114,13 @@ public class slots_heroSlots : MonoBehaviour, IDropHandler, IBeginDragHandler, I
if (hc.a == 0f) hc.a = 1f;
heroSlot_colorImage.color = hc;
}
if (heroLevelImage != null)
{
Color lc = heroLevelImage.color;
if (lc.a == 0f) lc.a = 1f;
heroLevelImage.color = lc;
}
}
// Accept drops from CharacterCardView (role items) or roleCard_prefabController
@@ -167,6 +200,20 @@ public class slots_heroSlots : MonoBehaviour, IDropHandler, IBeginDragHandler, I
heroImage.sprite = sourceRole.roleCard_heroProfile.sprite;
heroImage.color = new Color(heroImage.color.r, heroImage.color.g, heroImage.color.b, 1f);
}
// 设置等级图标
var levelInfo = found.GetEffectiveLevelForCurrentEXP();
if (levelInfo != null && heroLevelImage != null)
{
string level = GetRatingFromSO(found);
heroLevelImage.sprite = GetLevelSprite(level);
heroLevelImage.color = heroLevelImage.sprite != null ? Color.white : new Color(1f, 1f, 1f, 0f);
}
else if (heroLevelImage != null)
{
heroLevelImage.sprite = null;
heroLevelImage.color = new Color(1f, 1f, 1f, 0f);
}
}
else
{
@@ -200,6 +247,15 @@ public class slots_heroSlots : MonoBehaviour, IDropHandler, IBeginDragHandler, I
}
Debug.Log($"slots_heroSlots OnDrop applied id={heroSlot_heroID} to {gameObject.name}");
// Update the skill list after setting the hero
UpdateSkillList();
// Update and save selected heroes
if (newTeamSelector.Instance != null)
{
newTeamSelector.Instance.UpdateAndSaveSelectedHeroes();
}
}
// Allow right-click to clear this slot
@@ -215,7 +271,7 @@ public class slots_heroSlots : MonoBehaviour, IDropHandler, IBeginDragHandler, I
{
int prevId = heroSlot_heroID; // remember previous id
heroSlot_heroID = 0;
if (heroSlot_heroName != null) heroSlot_heroName.text = string.Empty;
if (heroSlot_heroName != null) heroSlot_heroName.text = "空置";
if (heroImage != null)
{
// revert to default sprite if provided, otherwise keep transparent
@@ -230,12 +286,26 @@ public class slots_heroSlots : MonoBehaviour, IDropHandler, IBeginDragHandler, I
heroImage.color = new Color(heroImage.color.r, heroImage.color.g, heroImage.color.b, 0f);
}
}
if (heroLevelImage != null)
{
heroLevelImage.sprite = null;
heroLevelImage.color = new Color(1f, 1f, 1f, 0f);
}
if (TeamManager.Instance != null)
{
TeamManager.Instance.currentSelectedCharacterCard = null;
if (prevId != 0)
TeamManager.Instance.removeTeamCharacter(prevId);
}
// Clear the skill list
UpdateSkillList();
// Update and save selected heroes
if (newTeamSelector.Instance != null)
{
newTeamSelector.Instance.UpdateAndSaveSelectedHeroes();
}
}
// Drag between slots only
@@ -294,5 +364,173 @@ public class slots_heroSlots : MonoBehaviour, IDropHandler, IBeginDragHandler, I
if (heroSlot_heroName != null) heroSlot_heroName.text = name ?? string.Empty;
if (heroImage != null) heroImage.sprite = sprite;
if (heroImage != null) heroImage.color = sprite != null ? new Color(heroImage.color.r, heroImage.color.g, heroImage.color.b, 1f) : new Color(heroImage.color.r, heroImage.color.g, heroImage.color.b, 0f);
// 设置等级图标
if (id != 0)
{
var hero = FindHeroById(id);
if (hero != null)
{
var levelInfo = hero.GetEffectiveLevelForCurrentEXP();
if (levelInfo != null && heroLevelImage != null)
{
string level = GetRatingFromSO(hero);
heroLevelImage.sprite = GetLevelSprite(level);
heroLevelImage.color = heroLevelImage.sprite != null ? Color.white : new Color(1f, 1f, 1f, 0f);
}
}
}
else if (heroLevelImage != null)
{
heroLevelImage.sprite = null;
heroLevelImage.color = new Color(1f, 1f, 1f, 0f);
}
// Update skill list after setting slot
UpdateSkillList();
}
// Update the skill list in the container
public void UpdateSkillList()
{
if (skillContainer == null || skillCardPrefab == null) return;
// Clear existing skill cards
foreach (Transform child in skillContainer.transform)
{
Destroy(child.gameObject);
}
if (heroSlot_heroID == 0) return; // No hero, no skills
// Find the AllyHero_SO
AllyHero_SO hero = null;
try
{
var arr = Resources.LoadAll<AllyHero_SO>("");
foreach (var a in arr)
{
if (a != null && a.ally_heroID == heroSlot_heroID)
{
hero = a;
break;
}
}
}
catch { }
if (hero == null || hero.equippedSkillGroupIDs == null) return;
// Instantiate skill cards for equipped groups
foreach (int groupId in hero.equippedSkillGroupIDs)
{
if (groupId == 0) continue; // Skip empty
SkillGroup group = hero.GetSkillGroupByID(groupId);
if (group == null) continue;
GameObject skillGo = Instantiate(skillCardPrefab, skillContainer.transform);
slots_skillSlots skillSlot = skillGo.GetComponent<slots_skillSlots>();
if (skillSlot != null)
{
skillSlot.skillCard_skillName.text = group.groupName ?? string.Empty;
skillSlot.skillCard_skillID = group.skillGroupID;
if (skillSlot.skillCard_skillIconImage != null)
{
skillSlot.skillCard_skillIconImage.sprite = group.groupIcon;
skillSlot.skillCard_skillIconImage.color = group.groupIcon != null ? Color.white : new Color(1f, 1f, 1f, 0f);
}
skillSlot.skillCard_skillDescription = group.skillDescriptionsText ?? string.Empty;
skillSlot.heroId = heroSlot_heroID;
skillSlot.isSelected = true; // Since equipped
skillSlot.isReadOnly = true; // Set to read-only for display in hero slot
skillSlot.ApplyState();
}
}
}
// 辅助方法:根据ID查找英雄SO
private AllyHero_SO FindHeroById(int id)
{
var arr = Resources.LoadAll<AllyHero_SO>("");
foreach (var a in arr)
{
if (a != null && a.ally_heroID == id) return a;
}
return null;
}
// 获取等级对应的sprite
private Sprite GetLevelSprite(string level)
{
switch (level)
{
case "C": // C
return levelIcon_sprite_C;
case "B": // B
return levelIcon_sprite_B;
case "A": // A
return levelIcon_sprite_A;
case "S": // S
return levelIcon_sprite_S;
default:
Debug.LogWarning($"未找到对应等级贴图,当前等级为:{level}");
return null;
}
}
// 获取角色等级字符串(与loadTeam_select.cs一致)
private string GetRatingFromSO(AllyHero_SO so)
{
if (so == null || so.levelStats == null || so.levelStats.Count == 0) return "C";
// Build a sorted copy by requiredEXP ascending
List<AllyHero_SO.AllyLevelInfo> sorted = new List<AllyHero_SO.AllyLevelInfo>();
foreach (var l in so.levelStats) if (l != null) sorted.Add(l);
sorted.Sort((a, b) => a.requiredEXP.CompareTo(b.requiredEXP));
int currentExp = so.ally_currentEXP;
int selectedIndex = 0;
for (int i = 0; i < sorted.Count; i++)
{
if (currentExp >= sorted[i].requiredEXP)
{
selectedIndex = i;
}
else
{
break;
}
}
// Map indices to ratings: index 0 -> C, 1 -> B, 2 -> A, 3+ -> S
if (selectedIndex <= 0) return "C";
if (selectedIndex == 1) return "B";
if (selectedIndex == 2) return "A";
// for selectedIndex >= 3 (including when there are more than 4 levels), treat as S
return "S";
}
// Handle detail button click
private void OnDetailButtonClicked()
{
if (thisHero_detial_panelObject == null || heroSlot_heroID == 0) return;
// Find the parent for instantiation
Transform parent = loadDetailsPrefab.Instance != null ? loadDetailsPrefab.Instance.detailsParent.transform : transform;
// Instantiate the panel
GameObject panelInstance = Instantiate(thisHero_detial_panelObject, parent);
// Get the character_detailInformation script
character_detailInformation detailScript = panelInstance.GetComponentInChildren<character_detailInformation>();
if (detailScript != null)
{
// Set the character SO
AllyHero_SO heroSO = FindHeroById(heroSlot_heroID);
detailScript.characterSO = heroSO;
}
Debug.Log($"Displayed details for hero ID {heroSlot_heroID}");
}
}
@@ -1,6 +1,9 @@
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
#if UNITY_EDITOR
using UnityEditor;
#endif
public class slots_skillSlots : MonoBehaviour, IPointerClickHandler, IPointerEnterHandler, IPointerExitHandler
{
@@ -31,6 +34,9 @@ public class slots_skillSlots : MonoBehaviour, IPointerClickHandler, IPointerEnt
// hero ID to modify the corresponding SO
public int heroId;
// 是否只读模式(用于英雄槽位内的技能显示)
public bool isReadOnly = false;
void Start()
{
ApplyState();
@@ -95,11 +101,35 @@ public class slots_skillSlots : MonoBehaviour, IPointerClickHandler, IPointerEnt
}
}
}
// Notify all slots_heroSlots with matching heroId to update their skill lists
var allSlots = FindObjectsOfType<slots_heroSlots>();
foreach (var slot in allSlots)
{
if (slot.heroSlot_heroID == heroId)
{
slot.UpdateSkillList();
}
}
// Notify loadSkillsSelect to update skill card selections
loadSkillsSelect.Instance?.UpdateSkillCardSelections();
#if UNITY_EDITOR
// Save the SO changes to disk
if (so != null)
{
EditorUtility.SetDirty(so);
AssetDatabase.SaveAssets();
}
#endif
}
// 鼠标左/右键:左键选中(或切换),右键仅在选中时取消
public void OnPointerClick(PointerEventData eventData)
{
if (isReadOnly) return; // 只读模式下不允许点击切换
if (eventData.button == PointerEventData.InputButton.Left)
{
ToggleSelect();