多轮审查和修复

This commit is contained in:
2026-05-12 15:34:08 +08:00
parent f55d2a57c3
commit ebbbb7332e
805 changed files with 838724 additions and 1905 deletions

View File

@@ -0,0 +1,167 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using Animancer;
using BaseGames.Player;
namespace BaseGames.Skills
{
/// <summary>
/// 技能数值修改维度(架构 09_ProgressionModule §10
/// </summary>
public enum SkillStat { Damage, Cost, Cooldown, Range, Duration }
/// <summary>
/// 插槽覆盖描述符:某护符将指定形态的某个技能槽替换为另一技能。
/// </summary>
[Serializable]
public struct SkillSlotOverride
{
public FormSO targetForm; // null = 所有形态
public string targetSlot; // 使用 SkillSlotNames 中的常量SoulSkill / SpiritSkill1 / SpiritSkill2
public FormSkillSO replacementSkill; // 替换目标技能
public int priority; // 高优先级覆盖低优先级
}
/// <summary>
/// 所有数值修改器叠加后的运行时参数快照(架构 09_ProgressionModule §10
/// 由 SkillModifierRegistry.GetEffectiveParams() 生成,传入 SkillManager 使用。
/// </summary>
public struct EffectiveSkillParams
{
public FormSkillSO baseSkill; // 原始 SO 引用(不变)
public int effectiveCost; // 修改后消耗
public float effectiveCooldown; // 修改后冷却(秒)
public float damageMult; // 伤害倍率1.0 = 无增益)
public float rangeMult; // 范围倍率
public FeedbackPresetSO effectiveFeedback; // 最终特效预设null = 回退原始)
public ClipTransition effectiveAnimation; // 最终施法动画null = 回退原始)
/// <summary>以技能 SO 默认值初始化,无任何修改器加成。</summary>
public static EffectiveSkillParams FromBase(FormSkillSO skill) => new()
{
baseSkill = skill,
effectiveCost = skill.baseCost,
effectiveCooldown = skill.cooldown,
damageMult = 1f,
rangeMult = 1f,
effectiveFeedback = null,
effectiveAnimation = default,
};
}
// 内部记录结构,存储单条数值修改
internal struct SkillStatEntry
{
public SkillStat stat;
public float delta;
public bool isPercent;
}
/// <summary>
/// 技能修改器注册表(架构 09_ProgressionModule §10
/// 挂在 Player 上,收集所有护符对技能数值的修改。
/// SkillManager 在施放技能时调用 GetEffectiveParams() 获取最终参数。
/// </summary>
public class SkillModifierRegistry : MonoBehaviour
{
// skillId → 一组数值修改
private readonly Dictionary<string, List<SkillStatEntry>> _modifiers = new();
// 插槽覆盖列表(按 priority 降序排列)
private readonly List<SkillSlotOverride> _slotOverrides = new();
// ── 数值修改 ────────────────────────────────────────────────────────
public void Register(string skillId, SkillStat stat, float delta, bool isPercent)
{
if (!_modifiers.TryGetValue(skillId, out var list))
{
list = new List<SkillStatEntry>();
_modifiers[skillId] = list;
}
list.Add(new SkillStatEntry { stat = stat, delta = delta, isPercent = isPercent });
}
public void Unregister(string skillId, SkillStat stat, float delta, bool isPercent)
{
if (!_modifiers.TryGetValue(skillId, out var list)) return;
list.RemoveAll(e => e.stat == stat &&
Mathf.Approximately(e.delta, delta) &&
e.isPercent == isPercent);
}
/// <summary>
/// 对给定技能叠加所有已注册修改器,返回一次性快照供 SkillManager 使用。
/// </summary>
public EffectiveSkillParams GetEffectiveParams(FormSkillSO skill)
{
var p = EffectiveSkillParams.FromBase(skill);
if (!_modifiers.TryGetValue(skill.skillId, out var entries)) return p;
float flatCost = 0, pctCost = 1f;
float flatCooldown = 0, pctCooldown = 1f;
float flatDamage = 0, pctDamage = 1f;
float flatRange = 0, pctRange = 1f;
foreach (var e in entries)
{
switch (e.stat)
{
case SkillStat.Cost:
if (e.isPercent) pctCost += e.delta;
else flatCost += e.delta;
break;
case SkillStat.Cooldown:
if (e.isPercent) pctCooldown += e.delta;
else flatCooldown += e.delta;
break;
case SkillStat.Damage:
if (e.isPercent) pctDamage += e.delta;
else flatDamage += e.delta;
break;
case SkillStat.Range:
if (e.isPercent) pctRange += e.delta;
else flatRange += e.delta;
break;
}
}
p.effectiveCost = Mathf.Max(0, Mathf.RoundToInt(skill.baseCost * pctCost + flatCost));
p.effectiveCooldown = Mathf.Max(0, skill.cooldown * pctCooldown + flatCooldown);
p.damageMult = 1f + (pctDamage - 1f) + flatDamage;
p.rangeMult = 1f + (pctRange - 1f) + flatRange;
return p;
}
// ── 插槽覆盖 ────────────────────────────────────────────────────────
public void AddSlotOverride(SkillSlotOverride data)
{
_slotOverrides.Add(data);
_slotOverrides.Sort((a, b) => b.priority.CompareTo(a.priority));
}
public void RemoveSlotOverride(SkillSlotOverride data)
{
_slotOverrides.RemoveAll(o =>
o.targetForm == data.targetForm &&
o.targetSlot == data.targetSlot &&
o.replacementSkill == data.replacementSkill);
}
/// <summary>
/// 获取当前形态某槽位的实际技能(考虑插槽覆盖)。
/// 没有覆盖时返回 null调用方保留原始技能
/// </summary>
public FormSkillSO GetOverriddenSkill(FormSO form, string slotName)
{
foreach (var o in _slotOverrides)
{
bool formMatch = o.targetForm == null || o.targetForm == form;
if (formMatch && o.targetSlot == slotName)
return o.replacementSkill;
}
return null;
}
}
}