Files
zeling_v2/Docs/DesignSpec/03_PlayerSystem.md
2026-05-08 11:04:00 +08:00

333 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 03 · 玩家系统规范
> **所属文档集** [← 返回索引](./README.md)
> **摘要**:玩家实体的构成、资源模型、状态机规范与对外行为契约。
> **关联**[04_CombatSystem](./04_CombatSystem.md) · [05_MovementSystem](./05_MovementSystem.md) · [06_FormSystem](./06_FormSystem.md)
---
## 目录
1. [玩家实体构成](#1-玩家实体构成)
2. [资源模型](#2-资源模型)
3. [玩家状态机](#3-玩家状态机)
4. [行为契约](#4-行为契约)
5. [能力解锁体系](#5-能力解锁体系)
6. [玩家配置参数](#6-玩家配置参数)
7. [发出的事件](#7-发出的事件)
---
## 1. 玩家实体构成
玩家实体是多个**职责分离的子系统**的协调器,自身不含具体业务逻辑:
```
PlayerEntity协调器
├── MovementController ← 物理移动(速度、跳跃、冲刺)
├── StatContainer ← 资源数值HP、灵力、魄元、灵泉、Geo
├── CombatHandler ← 攻击判定HitBox 开关、连击链)
├── FormController ← 形态管理(天魂/地魂/命魂切换)
├── WeaponSlot ← 当前武器(形态联动自动切换)
├── SkillExecutor ← 技能执行(魂技能/魄技能)
├── ParryHandler ← 弹反逻辑
├── HurtBox ← 受击判定(路由 DamagePacket
└── StateMachine ← 行为状态机(协调上述子系统)
```
**协调器原则**PlayerEntity 只负责:
1. 初始化子系统并维护引用
2. 维护状态机(决定当前行为)
3. 在受击时强制转换到受击状态
4. 在死亡时触发 `OnPlayerDied` 事件
---
## 2. 资源模型
### 2.1 资源总览
| 资源 | 类型 | 范围 | 特性 | 用途 |
|------|------|------|------|------|
| **HP** | Integer | 0 ~ MaxHP | 受击减少,存档点/灵泉恢复 | 生存指标 |
| **灵力SoulPower** | Integer | 0 ~ 100 | 近战命中积累,死亡清零 | 魂技能燃料 |
| **魄元SpiritPower** | Integer | 0 ~ 100 | 时间自动恢复,死亡恢复至上限 | 魄技能燃料 |
| **灵泉次数SpringCharges** | Integer | 0 ~ MaxCharges | 击杀积分驱动,存档点恢复 | 治疗次数 |
| **Geo灵晶** | Integer | 0 ~ ∞ | 击败敌人获得,死亡遗留遗骸 | 货币 |
### 2.2 灵力积累规则
> **设计目标**:鼓励玩家主动攻击,弹反作为高回报行为
| 来源 | 灵力增量 |
|------|---------|
| 近战命中普通敌人 | +10 |
| 近战命中 Boss | +5 |
| 弹反成功 | +33 |
- 死亡时归零
- 无自动恢复
### 2.3 魄元恢复规则
> **设计目标**:魄元是始终可用的"持续消耗"资源,不依赖风险操作
| 来源 | 魄元增量 |
|------|---------|
| 每秒自动恢复 | +`spiritRegenRate`(见配置参数)|
| 死亡复活 | 恢复至上限 |
| 存档点交互 | 恢复至上限 |
- 受伤不影响魄元
- 使用魄技能后扣除固定量
### 2.4 灵泉次数规则
> **设计目标**:治疗是"击杀驱动"而非"时间驱动",鼓励激进战斗风格
| 来源 | 变化 |
|------|------|
| 击杀普通敌人 | +1 积分 |
| 击杀精英怪 | +3 积分 |
| 击杀 Boss | +5 积分 |
| 积分达到阈值 | +1 次灵泉(积分清零)|
| 使用灵泉(治疗)| -1 次 |
| 与存档点交互 | 恢复至上限 |
| 死亡复活 | **不恢复**(死亡惩罚)|
> **设计决策**:死亡不恢复灵泉
> **原因**:保留一定死亡惩罚,让玩家珍惜治疗机会,但由于复活在存档点旁,玩家仍可快速通过激活存档点补满
### 2.5 Geo货币规则
| 来源 | 变化 |
|------|------|
| 击败敌人 | 掉落固定 + 随机范围 |
| 破坏场景容器 | 少量固定 |
| 任务奖励 | 固定量 |
| 死亡 | Geo 留在遗骸,不直接丢失 |
| 取回遗骸 | 遗骸的 Geo 归还玩家 |
| 再次死亡(未取回遗骸)| 遗骸 Geo **永久丢失** |
---
## 3. 玩家状态机
### 3.1 状态优先级
| 优先级 | 状态 | 说明 |
|--------|------|------|
| 100 | `DeathState` | 死亡,不可被任何状态打断 |
| 90 | `HurtState` | 受击硬直,仅死亡可打断 |
| 80 | `DashState` | 冲刺(含空中冲刺),受伤/死亡可打断 |
| 75 | `SoulSkillState` | 魂技能前摇,冲刺/受伤可打断 |
| 72 | `SpiritSkillState` | 魄技能前摇,冲刺/受伤可打断 |
| 70 | `ParryState` | 弹反等待,受伤可打断 |
| 60 | `AttackState` | 攻击,弹反/受伤可打断 |
| 55 | `SpringState` | 使用灵泉,前摇可被打断 |
| 40 | `InteractState` | 与 NPC/物件交互 |
| 35 | `WallGrabState` | 抓墙悬挂,冲刺/技能可打断 |
| 30 | `AirState` | 空中(含跳跃/下落)|
| 20 | `RunState` | 地面奔跑 |
| 10 | `SwimState` | 游泳(解锁后)|
| 0 | `IdleState` | 待机(最低优先级)|
### 3.2 状态转换规则
```
任意状态
══受击(HP>0)══► HurtState [强制,忽略优先级]
══受击(HP=0)══► DeathState [强制,不可被打断]
IdleState
──移动输入──────────► RunState
──跳跃输入──────────► AirState
──攻击输入──────────► AttackState
──弹反输入──────────► ParryState
──冲刺输入──────────► DashState
──魂技能+灵力充足───► SoulSkillState
──魄技能+魄元充足───► SpiritSkillState
──使用灵泉+次数≥1──► SpringState
──交互输入+目标存在─► InteractState
RunState
──无移动输入─────────► IdleState
──跳跃输入───────────► AirState
──攻击输入───────────► AttackState保持RunState上半身叠加
──弹反/冲刺/技能─────► 对应状态
AirState统一处理 跳跃/双跳/下落)
──落地───────────────► IdleState 或 RunState
──跳跃输入+双跳可用──► AirState内重置双跳不切状态
──贴墙+朝墙方向输入──► WallGrabState
──攻击/弹反/冲刺─────► 对应状态
WallGrabState
──跳跃输入───────────► AirState蹬墙跳
──反向输入或落地─────► AirState / IdleState
──冲刺/技能──────────► 对应状态
AttackState上半身叠加下半身保持原状态
~~动画结束~~──────────► 恢复原状态Idle/Run/Air
──连击窗口内攻击输入─► AttackState切换连击段
──弹反输入───────────► ParryState
ParryState
──弹反成功───────────► ParrySuccessState反击窗口
──攻击输入(窗口内)─► AttackStateParryCounter
~~反击窗口超时~~─────► IdleState/RunState
~~弹反超时~~──────────► IdleState/RunState
DashState
~~冲刺时长结束~~────── ► AirState 或 IdleState/RunState
SpringState
~~前摇完成~~──────────► 后摇 → IdleState
──被打断─────────────► IdleState灵泉次数已扣不返还
HurtState
~~硬直时长结束~~──────► IdleState
DeathState
(等待游戏管理器触发复活流程)
```
### 3.3 攻击连击链
| 连击段 | 触发方式 | 攻击方向 | 伤害倍率 | 备注 |
|--------|---------|---------|---------|------|
| `Attack1` | 第一次攻击输入 | 水平 | ×1.0 | 各形态动画不同 |
| `Attack2` | 连击窗口内再攻击 | 水平 | ×1.0 | |
| `Attack3` | 连击窗口内再攻击 | 水平 | ×2.0 | 重击,连击链结尾 |
| `AirAttack` | 空中攻击 | 水平 | ×1.0 | |
| `UpAttack` | 移动方向向上时攻击 | 向上 | ×1.0 | 角色轻微下移(反作用力)|
| `DownAttack` | 空中+移动方向向下时攻击 | 向下 | ×1.0 | 命中时产生弹起Pogo|
| `ParryCounter` | 弹反成功后攻击 | 水平 | ×3.0 | 不可被弹反,忽略无敌帧 |
> **设计决策**:第三击伤害 ×2弹反反击 ×3
> **原因**:鼓励打满连击,奖励弹反技巧。高倍率使玩家有显著的策略目标。
---
## 4. 行为契约
### 4.1 玩家实体对外接口
```
Interface IPlayerEntity {
// 只读属性
[readonly] position : Vector2
[readonly] facingDirection : Integer // +1 右 / -1 左
[readonly] currentState : StateID
[readonly] isInvincible : Boolean
// 强制状态切换(外部系统使用,如受击)
forceState(stateId: StateID, context: Optional<StateContext>) → void
// 查询
hasAbility(abilityId: ID) → Boolean
// 事件
[event] onDied : Event<void>
[event] onHit : Event<HitPayload>
[event] onStateChanged : Event<StateChangedPayload>
}
```
### 4.2 StatContainer 对外接口
```
Interface IStatContainer {
[readonly] currentHP : Integer
[readonly] maxHP : Integer
[readonly] currentSoulPower : Integer
[readonly] currentSpiritPower : Integer
[readonly] currentSpringCharges: Integer
[readonly] maxSpringCharges : Integer
[readonly] currentGeo : Integer
[readonly] isAlive : Boolean
takeDamage(amount: Integer) → void
heal(amount: Integer) → void
addSoulPower(amount: Integer) → void
consumeSoulPower(amount: Integer) → Result<Boolean>
consumeSpiritPower(amount: Integer) → Result<Boolean>
addKillCredit(creditType: KillType) → void // 驱动灵泉积分
useSpring() → Result<Boolean>
restoreSpringCharges() → void
addGeo(amount: Integer) → void
spendGeo(amount: Integer) → Result<Boolean>
beginInvincibility(duration: Duration)→ void
[event] onHPChanged : Event<{current, max}>
[event] onSoulPowerChanged : Event<{current, max}>
[event] onSpiritPowerChanged : Event<{current, max}>
[event] onSpringChargesChanged : Event<{current, max}>
[event] onGeoChanged : Event<{current, delta}>
[event] onDied : Event<void>
}
```
---
## 5. 能力解锁体系
### 5.1 能力定义
| 能力 ID | 默认状态 | 影响的状态/行为 | 解锁位置 |
|---------|---------|--------------|---------|
| `DoubleJump` | 锁定 | AirState 允许第二次跳跃 | 探索奖励 |
| `WallGrab` | **已解锁** | AirState → WallGrabState 允许 | 初始能力 |
| `AerialDash` | 锁定 | AirState → DashState 允许(消耗充能)| 探索奖励 |
| `Parry` | **已解锁** | ParryState 可进入 | 初始能力 |
| `Swim` | 锁定 | 液体区域不死亡SwimState 可进入 | 主线解锁 |
| `PlungeAttack` | 锁定 | 空中向下冲刺触发下冲 | 探索奖励 |
### 5.2 解锁流程
```
玩家触碰解锁物件AbilityUnlockItem
→ 世界系统发出 OnCollectiblePickedUptype=Ability, abilityId
→ 进程系统处理:将 abilityId 加入已解锁集合
→ 进程系统发出 OnAbilityUnlockedabilityId
→ 玩家系统接收:更新运行时能力标记
→ UI 系统显示能力获得动画
→ 存档系统:在下次存档时持久化
```
---
## 6. 玩家配置参数
以下参数在配置数据中定义,运行时只读:
| 参数 | 类型 | 推荐值 | 说明 |
|------|------|--------|------|
| `maxHP` | Integer | 5 | 初始最大生命值 |
| `maxSoulPower` | Integer | 100 | 灵力上限 |
| `maxSpiritPower` | Integer | 100 | 魄元上限 |
| `spiritRegenRate` | Number | 8.0/s | 魄元每秒自动回复量 |
| `maxSpringCharges` | Integer | 3 | 初始最大灵泉次数 |
| `springKillThreshold` | Integer | 5 | 增加 1 次灵泉所需积分 |
| `iFrameAfterHit` | Duration | 1.2s | 受击后无敌时长 |
| `comboWindowDuration` | Duration | 0.5s | 连击窗口时长 |
| `comboResetDelay` | Duration | 0.3s | 第三击后连击重置延迟 |
| `parryCounterDuration` | Duration | 0.6s | 弹反后反击窗口时长 |
---
## 7. 发出的事件
| 事件 | 触发时机 | 载荷 |
|------|---------|------|
| `OnPlayerDied` | HP 归零 | `void` |
| `OnHPChanged` | HP 任意变化 | `{current, max}` |
| `OnSoulPowerChanged` | 灵力变化 | `{current, max}` |
| `OnSpiritPowerChanged` | 魄元变化 | `{current, max}` |
| `OnSpringChargesChanged` | 灵泉次数变化 | `{current, max}` |
| `OnGeoChanged` | Geo 增减 | `{current, delta}` |
| `OnFormChanged` | 形态切换 | `{newFormId}` |
| `OnParrySuccess` | 弹反成功 | `{counterWindowDuration}` |
| `OnHitConfirmed` | 攻击命中有效目标 | `HitPayload` |
| `OnAbilityUnlocked` | 新能力获得 | `{abilityId}` |