using UnityEngine; using System.Collections.Generic; [CreateAssetMenu(fileName = "NewAllyHero", menuName = "SO_Data/AllyHero")] public class AllyHero_SO : ScriptableObject { [Header("友方英雄基本信息")] public string ally_heroName; public int ally_heroID; [Header("英雄立绘")] public Sprite ally_heroImage; [Header("英雄局内头像")] public Sprite ally_heroProfile; [Header("英雄轨道icon")] public Sprite ally_heroIcon; [Header("等级属性列表")] public List levelStats = new List(); [System.Serializable] public class AllyLevelInfo { [Tooltip("等级名称或标识")] public string levelName; public int levelID; [Tooltip("基础攻击力")] public int attack = 0; [Tooltip("最大生命值")] public int maxHP = 100; [Tooltip("伤害抗性 (0..1), 用于减少所受伤害")] public float damageResistance = 0f; [Tooltip("最大法力值")] public int maxMana = 100; [Tooltip("得分效率")] public float scoreEfficiency = 1f; [Tooltip("升到本等级所需经验")] public int requiredEXP; // --- 新增:每等级的共享音符击中参数(用于将来调整) --- [Header("Note-hit shared parameters")] [Tooltip("Good 判定时获得的法力值(整数)")] public int manaGainGood = 1; [Tooltip("Great 判定时获得的法力值(整数)")] public int manaGainGreat = 2; [Tooltip("Perfect 判定时获得的法力值(整数)")] public int manaGainPerfect = 3; [Tooltip("Miss 判定时获得的法力值(整数)")] public int manaGainOnMiss = 5; [Tooltip("Good 判定时基于英雄攻击力的伤害倍率,例如 0.5 表示造成 50% 的基础攻击力伤害")] public float damageMultiplierGood = 0.5f; [Tooltip("Great 判定时基于英雄攻击力的伤害倍率,例如 0.75 表示造成 75% 的基础攻击力伤害")] public float damageMultiplierGreat = 0.75f; [Tooltip("Perfect 判定时基于英雄攻击力的伤害倍率,例如 1.0 表示造成 100% 的基础攻击力伤害")] public float damageMultiplierPerfect = 1f; [Tooltip("Miss 时造成的基础生命损失基数。最终扣血将按 (missHpLossBase * (1 - damageResistance)) 计算,以考虑抗性")] public float missHpLossBase = 10f; } [Header("当前经验")] public int ally_currentEXP; [Header("Skills")] public SkillDefinition[] availableSkills; [Tooltip("Indexes into availableSkills for preselected skills; empty means none selected")] public int[] selectedSkillIndices = new int[0]; [Tooltip("Primary selected skill index into availableSkills (-1 = none)")] public int primarySkillIndex = -1; public SkillDefinition GetPrimarySkill() { if (availableSkills == null || primarySkillIndex < 0 || primarySkillIndex >= availableSkills.Length) return null; return availableSkills[primarySkillIndex]; } // Return the AllyLevelInfo that corresponds to the current ally_currentEXP. // Picks the highest level whose requiredEXP <= ally_currentEXP. If none match, returns levelStats[0] if present, otherwise null. public AllyLevelInfo GetEffectiveLevelForCurrentEXP() { if (levelStats == null || levelStats.Count == 0) return null; AllyLevelInfo best = null; int currentExp = ally_currentEXP; foreach (var lvl in levelStats) { if (lvl == null) continue; if (best == null) { if (currentExp >= lvl.requiredEXP) best = lvl; } else { if (currentExp >= lvl.requiredEXP && lvl.requiredEXP >= best.requiredEXP) best = lvl; } } if (best == null) return levelStats[0]; return best; } }