Files
spellforge/docs/technical/boss_design.md
T
joywayerandClaude Opus 4.8 ad2f4c0bc6 docs: 整理文档目录并对齐代码现状
- 将开发过程/归档文档迁至 docs_dev/(development_plan、certification_checklist、
  已废弃的 Cocos 架构草案 archived_cocos_architecture_draft),并修正全部跨引用
- 新增根 README.md(项目介绍,暂定名 Spellforge)与 docs_dev/README.md 索引
- 新增 docs_dev/doc_code_audit_2026-07-20.md:文档 vs 代码交叉审计报告(经 6
  路对抗性复核,零证伪),含「代码更优 / 文档更优 / 中性」判定汇总
- 在 docs/ 各设计·技术·机制文档就地加「实现现状 (2026-07-20)」callout:
  追认代码更优实现(纯 JSON 数据驱动、SpatialGrid-only 碰撞、MultiMesh 单档、
  存档选最新槽等),订正陈旧/矛盾内容(.tres→JSON、Boss HP/阈值/波次、EventID、
  StatusManager.apply 签名等),标记未实现功能(C# 热路径、Mana、元进展、
  Boss 阶段/抗性、Tutorial、轨迹/连锁/催化等)与 latent bug(CoreFeatureTag 位运算、
  pierce 空操作、MAX_OPS 不读 cpu_limit)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 14:35:55 +08:00

222 lines
10 KiB
Markdown
Raw 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.
# Boss 系统架构设计
> **关联切片**S6 P0Mini Boss Wave 8 / Final Boss Wave 20
> **依赖系统**EnemyManager、StatusManager、EventBus、VFXManager、ZoneManager
---
> **⚠️ 实现现状 (2026-07-20 审计)**:本文档描述的整套 Boss 架构(`BossManager` Autoload、`BossDef`/`BossPhaseDef`/`.tres` 资源、`BossAttackRegistry` 攻击模式注册表、场地机制如冰墙/场地收缩、多阶段弹幕、状态机 `BossInstance`**均为设计蓝图,代码 0% 实现**。现状 Boss 只是 `EnemyManager` SoA 中 `type=4`Mini BossWave 8/`type=5`Final BossWave 20)的普通厚血实体;唯一的"阶段行为"是当血量跨越 66% / 33% 阈值时召唤一批 `FAST` 杂兵援军(`wave_manager.gd:94-117`)。以下 `BossManager`/`.tres`/攻击模式注册表/场地机制全部尚未落地,保留作为未来实现的目标设计。详见 [审计报告](../../docs_dev/doc_code_audit_2026-07-20.md)。
---
## 1. 设计原则
- **阶段驱动(Phase-Driven**Boss 行为由明确的阶段(Phase)枚举驱动,阶段切换在 `_physics_process` 中以血量阈值触发,不使用独立 Timer Node。
- **与 EnemyManager 解耦**Boss 不进入 EnemyManager SoA(避免 stride 污染和 AI 逻辑膨胀),由独立的 `BossManager` Autoload 管理;但向 SpatialGrid 注册自身坐标,使子弹归航与 ZoneManager 能命中 Boss。
- **数据驱动**:每个 Boss 的阶段配置存储于 `.tres` Resource`BossPhaseDef`),美术/策划可在不修改代码的情况下调整阈值与攻击模式。
- **EventBus 集成**:阶段切换、死亡均通过 EventBus 广播,HUD/BGM/成就系统订阅。
---
## 2. BossManager Autoload
```gdscript
# boss_manager.gd (Autoload: BossManager)
# Boss 实体数量极少(≤ 2 同屏),不使用 SoA,用 Array[BossInstance] 即可。
const MAX_BOSSES: int = 2 # 同屏 Boss 上限
var _active: Array[BossInstance] = []
func spawn_boss(boss_def_id: String, spawn_pos: Vector2) -> int:
# 从 BossRegistry 加载 BossDef,实例化 BossInstance,注册到 SpatialGrid
pass
func _physics_process(delta: float) -> void:
for boss in _active:
boss.tick(delta)
```
---
## 3. Phase 状态机模板
### 3.1 枚举与切换条件
每个 Boss 的阶段定义在 `BossPhaseDef` Resource 中:
```gdscript
# boss_phase_def.gd
class_name BossPhaseDef
extends Resource
@export var phase_id: int # 阶段编号(0 起始)
@export var hp_threshold: float # 进入此阶段的血量百分比(0.0~1.0),如 0.5 = 50% HP
@export var attack_patterns: Array[String] # 此阶段可用的攻击模式 ID 列表
@export var move_speed_mult: float = 1.0 # 移动速度倍率(狂暴阶段可设 1.5)
@export var enrage_vfx: String = "" # 阶段切换时触发的 VFX ID(空=无)
@export var phase_bgm_layer: int = 0 # 动态音乐层级(0=基础,1=紧张,2=狂暴)
```
### 3.2 BossInstance 状态机
```gdscript
# boss_instance.gd
class_name BossInstance
extends RefCounted
enum BossPhaseState {
PHASE_0, # 初始阶段(100% HP
PHASE_1, # 受伤阶段(阈值由 BossDef 配置,通常 70%
PHASE_2, # 危机阶段(通常 40%
PHASE_DYING # 死亡动画阶段(HP ≤ 0,播放死亡序列后才真正移除)
}
var boss_def: BossDef
var hp: float
var hp_max: float
var position: Vector2
var current_phase: BossPhaseState = BossPhaseState.PHASE_0
var _attack_cooldown: float = 0.0
var _pattern_index: int = 0 # 当前阶段攻击模式的轮询索引
var _phase_just_changed: bool = false # 本帧刚切换阶段的标志,用于触发 enrage VFX
func tick(delta: float) -> void:
_check_phase_transition()
if current_phase == BossPhaseState.PHASE_DYING:
_tick_dying(delta)
return
_tick_movement(delta)
_tick_attack(delta)
_sync_render()
# 血量阈值检查(每帧)
func _check_phase_transition() -> void:
var hp_pct: float = hp / hp_max
var phases: Array = boss_def.phases # Array[BossPhaseDef],按 hp_threshold 降序排列
for i in phases.size():
var phase_def: BossPhaseDef = phases[i]
if hp_pct <= phase_def.hp_threshold and int(current_phase) < i + 1:
_enter_phase(i + 1, phase_def)
break
func _enter_phase(new_phase: int, phase_def: BossPhaseDef) -> void:
current_phase = new_phase as BossPhaseState
_pattern_index = 0
_attack_cooldown = 0.0
# 阶段切换 VFX
if phase_def.enrage_vfx != "":
VFXManager.play(phase_def.enrage_vfx, position, 1.0)
# 通知 EventBusHUD 高亮、BGM 切换)
EventBus.emit(EventID.BOSS_PHASE_CHANGED, {
"boss_id": boss_def.id,
"phase": new_phase,
"bgm_layer": phase_def.phase_bgm_layer
})
```
---
## 4. 攻击模式系统 (Attack Pattern)
攻击模式以 ID 字符串存储,在 `BossAttackRegistry` 中注册(类比 `SpellRegistry`),运行时由 `_tick_attack` 调用:
```gdscript
# boss_instance.gd(续)
func _tick_attack(delta: float) -> void:
_attack_cooldown -= delta
if _attack_cooldown > 0.0:
return
var phase_def: BossPhaseDef = boss_def.phases[int(current_phase)]
if phase_def.attack_patterns.is_empty():
return
# 轮询攻击模式
var pattern_id: String = phase_def.attack_patterns[
_pattern_index % phase_def.attack_patterns.size()
]
_pattern_index += 1
var cooldown: float = BossAttackRegistry.execute(pattern_id, self)
_attack_cooldown = cooldown
```
`BossAttackRegistry.execute(id, boss)` 返回该攻击模式的冷却时间(秒)。每种攻击模式是一个独立的 GDScript 函数或 Resource,通过 SpellEvaluator 发射子弹(走标准 BulletManager 路径)。
---
## 5. 具体 Boss 设计模板
> **⚠️ 实现现状 (2026-07-20 审计)**:下表 HP 与阶段阈值均为**设计目标**,与代码现值不符。① **血量**:代码实取 `balance.json` 的 `boss_hp`Mini=**450** / Final=**1800**`balance.json:8-11`,疑为占位/待平衡值),并非本节的 2000 / 10000,也非 `numerical_design §3.2` 的 50000;三处数值互相矛盾。② **阶段阈值**:代码统一用 **66% / 33%** 两段(`wave_manager.gd:99-102`),并非本节 Mini 的 60%/30% 或 Final 的 70%/40%/15%。③ **攻击模式 / 场地机制 / move_speed / enrage_vfx** 字段全部未实现;每次"进阶"只是召唤 `4 + phase*2` 个 FAST 杂兵。详见 [审计报告](../../docs_dev/doc_code_audit_2026-07-20.md)。
### 5.1 Mini Boss — Wave 8(待策划填充)
| 字段 | 值 |
| :--- | :--- |
| `boss_id` | `"mini_boss_w8"` |
| `hp_max` | 2000(约为普通精英 6.6×) |
| `move_speed` | 120(比杂鱼慢,靠范围攻击弥补) |
| **Phase 0**100%→60% HP| 攻击模式:`"charge_slam"` + `"spread_shot_3"` |
| **Phase 1**60%→30% HP| 追加:`"summon_minion_x2"`move_speed_mult=1.2 |
| **Phase 2**30%→0% HP| 追加:`"zone_aoe_fire"`move_speed_mult=1.5enrage_vfx="boss_enrage" |
| 死亡事件 | `BOSS_KILLED`(**未实现**:该常量不存在;现状仅在生成时发 `BOSS_SPAWNED=19`,死亡走通用 `ENEMY_KILLED=7`|
| 战场机制 | 无(Mini Boss 不设场地机制,Final Boss 才有)|
### 5.2 Final Boss — Wave 20(待策划填充)
| 字段 | 值 |
| :--- | :--- |
| `boss_id` | `"final_boss_w20"` |
| `hp_max` | 10000 |
| `move_speed` | 80(极慢,靠弹幕覆盖)|
| **Phase 0**100%→70% HP| 攻击模式:`"spiral_shot_8"` + `"summon_turrets_x4"` |
| **Phase 1**70%→40% HP| 追加:`"zone_ice_wall"`;场地:随机生成 4 个冰墙障碍(`ZoneManager` 驱动)|
| **Phase 2**40%→15% HP| 追加:`"enrage_laser_sweep"`;场地收缩:边界每 10 秒向中心缩小 50px |
| **Phase 3**15%→0% HP| 全弹幕覆盖;`"phase3_barrage"`;恢复部分 HP 后进入死亡序列(演出用)|
| 死亡事件 | **未实现**`BOSS_KILLED` / `GAME_CLEARED` / `BOSS_PHASE_CHANGED` 三个常量均不存在(ID 15/16/17 实为 `SPELL_EQUIPPED`/`LEVEL_UP`/`SHOP_OPENED`)。现状:生成发 `BOSS_SPAWNED=19`,死亡走 `ENEMY_KILLED=7`,阶段切换发通用 `GAME_STATE_CHANGED=20`payload `to="BOSS_PHASE_N"`|
| 战场机制 | 场地收缩(Phase 2+)、冰墙障碍(Phase 1+)——**均未实现** |
---
## 6. EventBus 扩展(Boss 专用事件)
> **权威登记**:以下 ID 已并入 `technical/implementation_plan.md` §2.1 事件目录与 `event_ids.gd`,本节表为语义说明(勿改号)。
| 事件 ID | 常量名 | Payload | 订阅方 |
| :--- | :--- | :--- | :--- |
| 15 | `BOSS_PHASE_CHANGED` | `{boss_id, phase, bgm_layer}` | HUD(阶段提示)、AudioManagerBGM 切换)|
| 16 | `BOSS_KILLED` | `{boss_id, wave_num}` | WaveManager(进入结算)、AchievementManager |
| 17 | `GAME_CLEARED` | `{elapsed_sec, wave_num}` | GameCycleManager(结算屏)、排行榜 |
---
## 7. 与现有系统的接口约定
| 接口 | 调用方向 | 说明 |
| :--- | :--- | :--- |
| `SpatialGrid.register_boss(id, pos, radius)` | BossManager → SpatialGrid | Boss 作为可被子弹命中的实体,每帧更新坐标 |
| `BulletManager._on_bullet_hit(bullet_id, target_id)` | BulletManager → BossManager | `target_id` 前缀区分:`enemy_xxx` vs `boss_xxx`(或通过 faction 位掩码判断)|
| `ZoneManager.spawn_zone(...)` | BossAttackPattern → ZoneManager | Boss 攻击模式可生成 Zone(如冰墙、火圈)|
| `VFXManager.play(vfx_id, pos, scale)` | BossInstance → VFXManager | 阶段切换 + 死亡演出 VFX |
| `SpellEvaluator.execute_boss_pattern(pattern_id, origin)` | BossAttackRegistry → SpellEvaluator | Boss 弹幕走标准 SpellEvaluator 路径,复用子弹生成管线 |
---
## 8. 目录规范
```text
scripts/autoloads/
boss_manager.gd # Autoload BossManager
scripts/domain/boss/
boss_def.gd # class_name BossDef (Resource)
boss_phase_def.gd # class_name BossPhaseDef (Resource)
boss_instance.gd # class_name BossInstance (RefCounted)
boss_attack_registry.gd # BossAttackRegistry(类比 SpellRegistry
resources/bosses/
mini_boss_w8.tres
final_boss_w20.tres
resources/boss_patterns/
charge_slam.tres
spread_shot_3.tres
spiral_shot_8.tres
# ...
```