# 54 · 霸体系统(Poise / Superarmor System)
> **命名空间** `BaseGames.Combat`
> **所属文档集** [← 返回索引](./README.md) · [总览](./00_Overview.md)
> **依赖** `BaseGames.Combat`(DamageInfo / HitBox / HurtBox)· `BaseGames.Skills`(FormSkillSO)· `BaseGames.Enemies.Boss.Skills`(BossSkillSO)
---
## 目录
1. [系统总览](#1-系统总览)
2. [核心枚举定义](#2-核心枚举定义)
3. [霸体窗口配置(PoiseWindowConfig)](#3-霸体窗口配置poiseswindowconfig)
4. [IPoiseSource — 霸体来源接口](#4-ipoisesource--霸体来源接口)
5. [HurtBox 打断判定流水线](#5-hurtbox-打断判定流水线)
6. [DamageInfo / DamageSourceSO 扩展](#6-damageinfo--damagesourceso-扩展)
7. [玩家霸体配置](#7-玩家霸体配置)
- [7.1 攻击状态霸体](#71-攻击状态霸体)
- [7.2 技能施放霸体(FormSkillSO)](#72-技能施放霸体formskillso)
- [7.3 能力状态霸体](#73-能力状态霸体)
8. [敌人 / Boss 霸体配置(BossSkillSO)](#8-敌人--boss-霸体配置bossskillso)
9. [显式打断关系表(PoiseOverrideTableSO)](#9-显式打断关系表poiseoverridetableso)
10. [全动作霸体参考表](#10-全动作霸体参考表)
11. [平衡设计准则](#11-平衡设计准则)
12. [编辑器友好设计](#12-编辑器友好设计)
---
## 1. 系统总览
**霸体(Poise)** 是动作游戏中"受击时不被打断"的能力。本系统将霸体和打断能力拆解为两个对立等级,并通过 SO 数据驱动实现对**所有技能、攻击、能力**的精细配置。
### 核心概念
| 概念 | 说明 |
|------|------|
| **霸体等级(PoiseLevel)** | 当前动作抵抗被打断的强度。等级越高,越难被打断。 |
| **打断等级(BreakLevel)** | 攻击/技能的打断能力。等级越高,能打断越强的霸体。 |
| **霸体窗口(Poise Window)** | 某个动作在哪段时间内拥有霸体(可以是整个状态,也可以是特定动画帧区间)。 |
| **霸体 vs 无敌帧(IFrame)** | 无敌帧 = 不受任何伤害;霸体 = 受伤但不被打断,两者独立,可同时生效。 |
### 打断判定规则
```
受击时:
1. 检查无敌帧(IFrame) → 若活跃,直接跳过所有伤害处理
2. 检查打断逻辑:
a. 查询 PoiseOverrideTable 是否有该攻击 vs 该状态的显式规则
→ 若有 AlwaysInterrupt: 强制打断(Unbreakable 除外)
→ 若有 NeverInterrupt: 绝不打断(保留伤害)
b. 默认规则:(int)incomingBreakLevel >= (int)currentPoiseLevel → 打断
3. 若打断:进入 HurtState / 施加击退 / 技能 / 动作被取消
若不打断:仅扣血 + 播放受击闪烁,不进入 HurtState
```
```
装备系统
职责图:
├─ PoiseLevel / BreakLevel → 两个对立枚举(等级比较核心)
├─ PoiseWindowConfig → 结构体(哪段时间有霸体,霸体等级)
├─ IPoiseSource → 接口(状态/技能/动作暴露当前霸体等级)
├─ DamageSourceSO → 增加 breakLevel 字段
├─ DamageInfo → 增加 BreakLevel 字段
├─ HurtBox → 打断判定逻辑
├─ FormSkillSO → 技能施放期间的霸体窗口
├─ BossSkillSO → Boss 技能执行期间的霸体配置
├─ PlayerStateBase → 玩家状态暴露 CurrentPoise
└─ PoiseOverrideTableSO → 显式打断关系配置(可选精细控制)
```
---
## 2. 核心枚举定义
```csharp
namespace BaseGames.Combat
{
///
/// 霸体等级:当前动作抵抗被打断的强度。
/// Unbreakable = 100,任何 BreakLevel 均无法打断(BOSS 阶段转换技、玩家特定能力专用)。
///
public enum PoiseLevel
{
None = 0, // 无霸体:任何攻击均可打断(普通状态、普通敌人站立)
Light = 1, // 轻霸体:可被中级以上攻击打断(普通攻击第3段可打断)
Medium = 2, // 中霸体:只有重型攻击或技能可打断(精英怪冲刺、玩家技能施放)
Heavy = 3, // 重霸体:只有破甲攻击可打断(Boss 核心攻击前摇)
Unbreakable = 100, // 霸体:完全不可打断(Boss 阶段过渡、剧情硬直)
}
///
/// 打断等级:攻击/技能打断对手霸体的能力。
/// 判定规则:(int)breakLevel >= (int)targetPoiseLevel 时发生打断(Unbreakable 例外)。
///
public enum BreakLevel
{
None = 0, // 无打断力(弱攻击,只能打断 PoiseLevel.None)
Light = 1, // 轻打断(可打断 Light 及以下霸体)
Medium = 2, // 中打断(可打断 Medium 及以下霸体)
Heavy = 3, // 重打断(可打断 Heavy 及以下霸体)
Breaker = 4, // 破甲(可打断 Heavy 及以下,不能打断 Unbreakable)
}
}
```
### 打断关系速查矩阵
| **BreakLevel →** | None(0) | Light(1) | Medium(2) | Heavy(3) | Breaker(4) |
|:---:|:---:|:---:|:---:|:---:|:---:|
| **PoiseLevel.None(0)** | ✅打断 | ✅打断 | ✅打断 | ✅打断 | ✅打断 |
| **PoiseLevel.Light(1)** | ❌ | ✅打断 | ✅打断 | ✅打断 | ✅打断 |
| **PoiseLevel.Medium(2)** | ❌ | ❌ | ✅打断 | ✅打断 | ✅打断 |
| **PoiseLevel.Heavy(3)** | ❌ | ❌ | ❌ | ✅打断 | ✅打断 |
| **PoiseLevel.Unbreakable** | ❌ | ❌ | ❌ | ❌ | ❌ |
> 所有 ❌ 情况:仍扣血,但**不进入 HurtState,不施加击退**。
---
## 3. 霸体窗口配置(PoiseWindowConfig)
```csharp
///
/// 霸体窗口配置。定义某动作在哪段时间内(以动画时间轴为基准)拥有霸体。
/// - 若 windowStart = windowEnd = 0,则整个动作期间均拥有霸体。
/// - windowStart/End 使用归一化时间(0.0 = 动画起始,1.0 = 动画结束)。
///
[Serializable]
public struct PoiseWindowConfig
{
[Tooltip("霸体等级(None = 无霸体,Unbreakable = 完全不可打断)")]
public PoiseLevel level;
[Tooltip("霸体生效起始时间(归一化,0 = 动画开始)。0+0 = 全程霸体。")]
[Range(0f, 1f)]
public float windowStart;
[Tooltip("霸体生效结束时间(归一化,0 = 动画结束 = 1.0 等价)。0+0 = 全程霸体。")]
[Range(0f, 1f)]
public float windowEnd;
/// 是否在整个动作期间都有霸体(windowStart = windowEnd = 0 时视为全程)
public bool IsFullDuration => windowStart == 0f && windowEnd == 0f;
/// 检查指定归一化时间是否在霸体窗口内
public bool IsActiveAt(float normalizedTime)
{
if (level == PoiseLevel.None) return false;
if (IsFullDuration) return true;
return normalizedTime >= windowStart && normalizedTime <= windowEnd;
}
/// 预设:全程轻霸体
public static PoiseWindowConfig LightFull
=> new() { level = PoiseLevel.Light, windowStart = 0, windowEnd = 0 };
/// 预设:全程中霸体
public static PoiseWindowConfig MediumFull
=> new() { level = PoiseLevel.Medium, windowStart = 0, windowEnd = 0 };
/// 预设:全程重霸体
public static PoiseWindowConfig HeavyFull
=> new() { level = PoiseLevel.Heavy, windowStart = 0, windowEnd = 0 };
/// 预设:无霸体
public static PoiseWindowConfig None
=> new() { level = PoiseLevel.None, windowStart = 0, windowEnd = 0 };
}
```
---
## 4. IPoiseSource — 霸体来源接口
所有可以提供霸体的对象(玩家状态、技能执行器、Boss 技能执行器)实现此接口:
```csharp
///
/// 霸体来源接口。HurtBox 在打断判定时调用此接口查询当前霸体等级。
///
public interface IPoiseSource
{
/// 当前霸体等级(实时,随动画帧变化)
PoiseLevel CurrentPoise { get; }
}
```
**玩家端实现**:`PlayerController` 汇总多个 `IPoiseSource`(当前状态 + 技能执行器)并对外暴露最高霸体等级:
```csharp
public class PlayerController : MonoBehaviour, IPoiseSource
{
// 汇总当前所有霸体来源,取最高等级
public PoiseLevel CurrentPoise
{
get
{
PoiseLevel best = _currentState?.CurrentPoise ?? PoiseLevel.None;
PoiseLevel skill = _skillManager.CurrentPoise;
return (int)skill > (int)best ? skill : best;
}
}
}
```
---
## 5. HurtBox 打断判定流水线
`HurtBox.ReceiveDamage(DamageInfo)` 新增霸体检查步骤:
```csharp
public void ReceiveDamage(DamageInfo info)
{
// ── Step 1: 无敌帧检查 ──────────────────────────────────────────────────
if (_owner is IInvincible inv && inv.IsInvincible && !info.Flags.HasFlag(DamageFlags.IgnoreIFrame))
return;
// ── Step 2: 计算最终伤害 ─────────────────────────────────────────────────
int finalDamage = info.DamageType == DamageType.True
? info.RawDamage
: Mathf.Max(1, info.RawDamage - _defenseStat);
// ── Step 3: 霸体打断检查 ─────────────────────────────────────────────────
bool interrupted = ShouldInterrupt(info);
// ── Step 4: 应用伤害 ─────────────────────────────────────────────────────
_owner.TakeDamage(finalDamage);
OnHitConfirmedChannel.Raise(info);
OnHurt.Invoke(info);
// ── Step 5: 条件性打断 ────────────────────────────────────────────────────
if (interrupted)
{
_owner.ApplyKnockback(info);
_owner.ForceState(HurtState); // 取消当前动作,进入硬直
}
else
{
// 仅播放受击闪烁/震屏,不打断动作
_owner.PlayHitFlash();
}
}
/// 综合三层规则判断是否发生打断
bool ShouldInterrupt(DamageInfo info)
{
// 获取当前霸体等级
PoiseLevel poise = (_owner as IPoiseSource)?.CurrentPoise ?? PoiseLevel.None;
// Unbreakable 不可打断(即使有 ForceBreak 标记)
if (poise == PoiseLevel.Unbreakable) return false;
// Layer 1: 显式 PoiseOverrideTable 查询
if (_overrideTable != null)
{
PoiseOverrideResult? ov = _overrideTable.Query(info.SourceId, _owner.StateId);
if (ov == PoiseOverrideResult.AlwaysInterrupt) return true;
if (ov == PoiseOverrideResult.NeverInterrupt) return false;
}
// Layer 2: DamageFlags.ForceBreak — 无视霸体等级(Unbreakable 已在上面拦截)
if (info.Flags.HasFlag(DamageFlags.ForceBreak)) return true;
// Layer 3: 默认数值比较
return (int)info.BreakLevel >= (int)poise;
}
```
### 新增 DamageFlags
```csharp
public enum DamageFlags
{
// ... 原有 flags ...
CanBeParried = 1 << 0,
Unblockable = 1 << 1,
IgnoreIFrame = 1 << 2,
PerfectParryOnly = 1 << 3,
IsProjectile = 1 << 4,
CanClash = 1 << 5,
// 新增
ForceBreak = 1 << 6, // 强制打断目标当前动作(忽略霸体等级,Unbreakable 除外)
NoKnockback = 1 << 7, // 打断时不施加击退(仅进入 HurtState 硬直)
}
```
---
## 6. DamageInfo / DamageSourceSO 扩展
### DamageInfo 新增字段
```csharp
public struct DamageInfo
{
// ... 原有字段 ...
///
/// 此次攻击的打断等级。由 DamageSourceSO.breakLevel 赋值,
/// 弹射物等特殊攻击由创建者手动指定。
///
public BreakLevel BreakLevel;
///
/// 攻击来源标识(用于 PoiseOverrideTable 查询)。
/// 格式:DamageSourceSO.sourceId 或 SkillSO.skillId。
///
public string SourceId;
}
```
### DamageSourceSO 新增字段
```csharp
public class DamageSourceSO : ScriptableObject
{
// ... 原有字段 ...
[Header("霸体系统")]
[Tooltip("此攻击的打断等级(决定能打断多高的霸体)")]
public BreakLevel breakLevel = BreakLevel.None;
[Tooltip("是否强制打断(ForceBreak)—— 无视目标霸体等级,Unbreakable 除外")]
public bool forceBreak = false;
}
```
`HitBox` 构建 `DamageInfo` 时:
```csharp
var info = new DamageInfo
{
// ... 原有赋值 ...
BreakLevel = _damageSource.breakLevel,
SourceId = _damageSource.sourceId,
// ForceBreak 标记
DamageFlags = _damageSource.forceBreak
? _damageSource.DamageFlags | DamageFlags.ForceBreak
: _damageSource.DamageFlags,
};
```
---
## 7. 玩家霸体配置
### 7.1 攻击状态霸体
`PlayerStateBase` 提供默认实现;`AttackState` 根据当前武器动画帧动态更新霸体等级:
```csharp
public abstract class PlayerStateBase : StateObject, IPoiseSource
{
/// 此状态的默认霸体等级(子类可覆盖)
public virtual PoiseLevel CurrentPoise => PoiseLevel.None;
/// 外部查询时使用的状态 ID(用于 PoiseOverrideTable)
public virtual string StateId => GetType().Name;
}
public class AttackState : PlayerStateBase
{
// 从当前武器 SO 读取当前段的霸体配置
public override PoiseLevel CurrentPoise
{
get
{
WeaponSO w = _weaponManager.ActiveWeapon;
PoiseWindowConfig cfg = _comboState switch
{
ComboState.Attack1 => w.attack1PoiseWindow,
ComboState.Attack2 => w.attack2PoiseWindow,
ComboState.Attack3 => w.attack3PoiseWindow,
ComboState.AirAttack => w.airAttackPoiseWindow,
ComboState.UpAttack => w.upAttackPoiseWindow,
ComboState.DownAttack => w.downAttackPoiseWindow,
_ => PoiseWindowConfig.None,
};
float t = _animancer.Layers[0].CurrentState?.NormalizedTime ?? 0f;
return cfg.IsActiveAt(t) ? cfg.level : PoiseLevel.None;
}
}
}
```
`WeaponSO` 新增攻击霸体窗口字段(见 [53_WeaponSystem §2](./53_WeaponSystem.md)):
```csharp
[Header("霸体配置(每段攻击)")]
public PoiseWindowConfig attack1PoiseWindow; // 默认 None(普通轻击无霸体)
public PoiseWindowConfig attack2PoiseWindow;
public PoiseWindowConfig attack3PoiseWindow; // 通常配置 Light 霸体(重击前摇)
public PoiseWindowConfig airAttackPoiseWindow;
public PoiseWindowConfig upAttackPoiseWindow;
public PoiseWindowConfig downAttackPoiseWindow;
```
### 三形态武器攻击霸体预设
| 动作 | 天魂(SkyBlade)| 地魂(EarthHammer)| 命魂(LifeScythe)|
|------|:-----------:|:-----------:|:-----------:|
| Attack1 | None | None | None |
| Attack2 | None | None | None |
| Attack3 | Light(0.0-0.5 前摇)| Medium(全程)| Light(全程)|
| AirAttack | None | None | None |
| UpAttack | None | None | None |
| DownAttack | None | None | None |
### 7.2 技能施放霸体(FormSkillSO)
`FormSkillSO` 新增 `poiseWindow` 字段:
```csharp
[Header("霸体配置")]
[Tooltip("技能施放期间的霸体窗口。None = 可被任何攻击打断。")]
public PoiseWindowConfig poiseWindow;
```
`SkillManager` 在技能施放期间作为 `IPoiseSource`:
```csharp
public class SkillManager : MonoBehaviour, IPoiseSource
{
FormSkillSO _activeCastingSkill;
float _castStartTime;
public PoiseLevel CurrentPoise
{
get
{
if (_activeCastingSkill == null) return PoiseLevel.None;
float elapsed = Time.time - _castStartTime;
float duration = _activeCastingSkill.castLockDuration;
float normalized = Mathf.Clamp01(duration > 0 ? elapsed / duration : 1f);
return _activeCastingSkill.poiseWindow.IsActiveAt(normalized)
? _activeCastingSkill.poiseWindow.level
: PoiseLevel.None;
}
}
}
```
**九种技能施放霸体预设**:
| 技能 | 形态 | 效果类型 | poiseWindow |
|------|------|---------|------------|
| 裂空掌 | 天魂 | MeleeAoE | `Light(0.0-0.6)` — 出手前摇有轻霸体 |
| 漩灵击 | 天魂 | BarrierAura | `Medium(全程)` — 护盾持续期间中霸体 |
| 灵踪弹 | 天魂 | Projectile | `None` — 远程技能无前摇霸体 |
| 地行术 | 地魂 | GroundDive | `Unbreakable(全程)` — 入地期间完全无敌 |
| 霸山拳 | 地魂 | MeleeAoE | `Heavy(0.0-0.4)` — 蓄力起手重霸体 |
| 魂元爆 | 地魂 | DelayedExplosion | `Light(0.0-0.3)` — 放置前摇轻霸体 |
| 登龙蹴 | 命魂 | DragonKick | `Heavy(全程)` — 升龙整段重霸体 |
| 太虚斩 | 命魂 | WraithDash | `Medium(全程)` — 冲刺中霸体 |
| 残阴术 | 命魂 | ShadowDecoy | `None` — 残影技能无霸体 |
### 7.3 能力状态霸体
| 状态类 | `CurrentPoise` 返回值 | 说明 |
|--------|---------------------|------|
| `IdleState` | `None` | 站立无霸体 |
| `RunState` | `None` | 跑动无霸体 |
| `AttackState` | 见 §7.1(动态) | 武器 SO 配置 |
| `DashState` | `None`(使用 IFrame 代替)| 冲刺靠无敌帧保护 |
| `AirState` | `None` | 空中无霸体 |
| `SpringState` | `Heavy` | 灵泉治疗全程重霸体(不可轻易打断)|
| `WallGrabState` | `Light` | 墙壁悬挂轻霸体(强击可推下)|
| `ParryState` | `Medium` | 弹反动作中霸体(弹反窗口内)|
| `HurtState` | `None` | 受击硬直无霸体 |
| `DeathState` | `Unbreakable` | 死亡动画完整播放 |
---
## 8. 敌人 / Boss 霸体配置(BossSkillSO)
`BossSkillSO` 新增霸体配置:
```csharp
// ─────────────────────────────
// 8. 霸体配置(新增)
// ─────────────────────────────
[Header("霸体配置")]
[Tooltip("此技能执行期间的霸体窗口(None = 可被玩家攻击打断)")]
public PoiseWindowConfig poiseWindow;
```
`AttackPatternSO`(`19_BossPatternLibrary`)也添加打断等级,以描述**单次动作模式**的打断能力:
```csharp
[Header("打断能力")]
[Tooltip("此攻击动作对玩家霸体的打断等级")]
public BreakLevel breakLevel = BreakLevel.Light;
```
### Boss 技能霸体分类建议
| Boss 技能类型 | 推荐 poiseWindow |
|-------------|----------------|
| `Melee` 近战普通攻击 | `Light(全程)` |
| `Charge` 冲刺突进 | `Medium(全程)` |
| `AoE` 大范围爆炸 | `Heavy(0.0-0.5 蓄力段)` |
| `Phase` 阶段转换 | `Unbreakable(全程)` |
| `Reactive` 反制技 | `Medium(全程)` |
| `Buff` 自身增益 | `Heavy(全程)` |
| `Summon` 召唤技 | `Light(全程)` |
### 普通敌人霸体(EnemyBase 扩展)
普通敌人通过 `EnemyConfigSO` 配置站立/攻击状态的霸体等级:
```csharp
[Header("霸体配置")]
public PoiseLevel idlePoise = PoiseLevel.None; // 站立/游荡时
public PoiseLevel attackPoise = PoiseLevel.Light; // 攻击动作时
public PoiseLevel staggerThreshold = PoiseLevel.None; // 受到同级霸体时触发僵直动画
```
---
## 9. 显式打断关系表(PoiseOverrideTableSO)
当默认数值规则不满足精细设计需求时,`PoiseOverrideTableSO` 允许指定**特定攻击 vs 特定状态**的强制规则:
```csharp
namespace BaseGames.Combat
{
///
/// 显式打断关系配置表。HurtBox 在数值比较前优先查询此表。
/// 用于设计"某 Boss 技能无论玩家霸体多高都必须打断"等特殊场合。
///
[CreateAssetMenu(menuName = "Combat/PoiseOverrideTable")]
public class PoiseOverrideTableSO : ScriptableObject
{
public List entries;
public PoiseOverrideResult? Query(string attackSourceId, string targetStateId)
{
foreach (var e in entries)
{
bool matchAtk = string.IsNullOrEmpty(e.attackSourceId)
|| e.attackSourceId == attackSourceId;
bool matchTarget = string.IsNullOrEmpty(e.targetStateId)
|| e.targetStateId == targetStateId;
if (matchAtk && matchTarget)
return e.alwaysInterrupt
? PoiseOverrideResult.AlwaysInterrupt
: PoiseOverrideResult.NeverInterrupt;
}
return null; // 无显式规则,走默认数值逻辑
}
}
[Serializable]
public class PoiseOverrideEntry
{
[Tooltip("攻击来源 ID(DamageSourceSO.sourceId 或 skillId)。留空 = 匹配所有攻击来源。")]
public string attackSourceId;
[Tooltip("被打断状态 ID(PlayerStateBase.StateId 或 BossSkillSO.skillId)。留空 = 匹配所有状态。")]
public string targetStateId;
[Tooltip("true = 强制打断(无视目标霸体等级,Unbreakable 除外)")]
public bool alwaysInterrupt;
[Tooltip("true = 永不打断(无视打断等级,受击仅扣血)")]
public bool neverInterrupt;
[TextArea(1, 2)]
[Tooltip("记录此规则的设计原因")]
public string designNote;
}
public enum PoiseOverrideResult { AlwaysInterrupt, NeverInterrupt }
}
```
**资产存放**:`Assets/ScriptableObjects/Combat/PoiseOverrideTable.asset`
**配置示例**:
```
// 规则 1: Boss"虚空起源"的阶段2核心技能"星陨重压"强制打断玩家地行术(即使地行术是 Unbreakable)
attackSourceId = "VoidOrigin_StarCrash"
targetStateId = "GroundDiveState"
alwaysInterrupt = true ← 注意:此处会覆盖 Unbreakable(慎用)
designNote = "设计意图:玩家不能通过地行术无伤躲过阶段技"
// 规则 2: 玩家弹反成功后的反击(ParryCounter)永不被任何敌人打断
attackSourceId = "" // 空 = 所有攻击来源
targetStateId = "ParryCounterState"
neverInterrupt = true
designNote = "弹反反击动作不应被打断,维护弹反奖励感"
// 规则 3: 精英敌人"石甲虫"的普通攻击对玩家施放天魂所有技能均无法打断
attackSourceId = "StoneArmadillo_Attack"
targetStateId = "" // 空 = 所有玩家状态
neverInterrupt = true
designNote = "石甲虫攻击较弱,不应打断任何玩家行动"
```
---
## 10. 全动作霸体参考表
### 玩家攻击打断等级
| 动作 | 天魂 BreakLevel | 地魂 BreakLevel | 命魂 BreakLevel |
|------|:-----------:|:-----------:|:-----------:|
| Attack1 | Light | Medium | Light |
| Attack2 | Light | Medium | Light |
| Attack3 | Medium | Heavy | Medium |
| AirAttack | Light | Medium | Light |
| UpAttack | Light | Medium | Light |
| DownAttack(Pogo)| Light | Medium | Light |
| ParryCounter | Heavy | Heavy | Heavy |
> 地魂武器整体打断等级高一级,体现"重击"特性。
### 玩家技能打断等级
| 技能 | BreakLevel | 说明 |
|------|:----------:|------|
| 裂空掌 | Heavy | 近战 AoE,高打断 |
| 漩灵击 | Medium | 护体,打断中等 |
| 灵踪弹 | Light | 弹射物,轻打断 |
| 地行术 | None | 入地,无接触打断 |
| 霸山拳 | Breaker | 破甲重拳 |
| 魂元爆 | Medium | 爆炸,中等打断 |
| 登龙蹴 | Heavy | 升龙,高打断 |
| 太虚斩 | Medium | 冲刺斩,中打断 |
| 残阴术(残影攻击)| Light | 残影,轻打断 |
### 能力状态打断等级(玩家被击时视角)
(参见 §7.3 能力状态霸体表)
---
## 11. 平衡设计准则
### 玩家侧
1. **普通连击段(Attack1/2)** 一般不给霸体,保持高风险高收益的近身博弈感
2. **第三段(Attack3)** 给 `Light` 或 `Medium` 霸体,奖励打完完整连击的玩家
3. **重要技能施放**(霸山拳、登龙蹴)给 `Medium`–`Heavy` 霸体,让技能"值得放"
4. **灵泉治疗** 给 `Heavy` 霸体,保证玩家有机会用完一个治疗不被打断
5. **冲刺** 使用 IFrame 而非霸体(短距离无敌,不受霸体系统管辖)
### 敌人侧
1. **普通敌人攻击** BreakLevel 统一为 `Light`(只能打断无霸体动作)
2. **精英怪攻击** BreakLevel 可到 `Medium`(能打断玩家轻霸体)
3. **Boss 核心技能** BreakLevel 可到 `Heavy` 或 `Breaker`(压制玩家大部分动作)
4. **Boss 蓄力/前摇** poiseWindow 给 `Heavy`,让玩家意识到"这招不能被随意取消"
### 禁止事项
| 禁止 | 原因 |
|------|------|
| 给 `Unbreakable` 的攻击设置 `PoiseOverrideEntry.alwaysInterrupt` | 会破坏设计安全感,须经负责人审核 |
| 玩家普通攻击 BreakLevel ≥ Heavy | 普通攻击打断 Boss 重霸体会让 Boss 失去压迫感 |
| BreakLevel = Breaker 的弹射物 | 远程破甲会使近战霸体设计失去意义 |
---
## 12. 编辑器友好设计
### HurtBox Gizmo 可视化
运行时暂停时,HurtBox 的 Gizmo 显示:
```
受击对象: Player
当前状态: AttackState (Attack3)
当前霸体: Medium [窗口 0.0 ~ 1.0 全程]
最近受击: DS_Boss_Charge (BreakLevel: Heavy)
打断结果: ✅ Interrupted (Heavy >= Medium)
```
### PoiseOverrideTable 编辑器窗口
`Tools → Zeling → Poise Override Table`:
```
┌─ Poise Override Table ─────────────────────────────────────┐
│ [自动验证:检查 attackSourceId / targetStateId 是否存在] │
│ │
│ # | 攻击来源 | 目标状态 | 类型 │
│ 1 | VoidOrigin_Star | GroundDiveState | AlwaysBreak │
│ 2 | (全部) | ParryCounterState | NeverBreak │
│ ... │
│ [+ 添加规则] [导出 CSV] [验证全部] │
└────────────────────────────────────────────────────────────┘
```
自动验证会检查:
- `attackSourceId` 对应的 `DamageSourceSO` / `FormSkillSO` / `BossSkillSO` 是否存在
- `targetStateId` 对应的 `PlayerStateBase` 子类或 `BossSkillSO.skillId` 是否存在
- 是否同时勾选 `alwaysInterrupt` 和 `neverInterrupt`(互斥,报错)