# 进阶机制扩展：召唤与环境蔓延 (Advanced Mechanics: Summons & Propagation)

> **⚠️ 实现现状 (2026-07-20 审计)**：召唤体系**只实现了 Stationary 炮台一种**；随从/卫星/镜像（含 hp / 碰撞体积 / 移动 / `behavior_state`）未实现，施法者死亡联动也无。`MinionManager` 用 `Array[Dictionary]`（§5.12，非 SoA），`MAX_MINIONS=20` FIFO 已实现。环境传导 / 反应地表 / 元素蔓延**未实现**。StatusID 常量 FREEZE/WET/OILY/STUN/VULNERABILITY 存在，但 `status_effects.json` 只定义 Burn/Poison/Combo。详见 [审计报告](../../docs_dev/doc_code_audit_2026-07-20.md)。

基于现有的 ECS 战斗系统，我们可以进一步拓展 **“召唤体系 (Summoning System)”** 和 **“环境传导 (Environmental Propagation)”** 维度。

## 1. 召唤体系 (Summoning Dimension)

召唤物不仅仅是“另一种子弹”，它们通常拥有独立的生命周期、AI 行为和属性继承规则。

### 1.1 召唤物类型 (Archetypes)
*   **Stationary (炮台型)**: 无法移动，持续对范围内敌人攻击。 (如：火舌图腾)
*   **Minion (随从型)**: 拥有碰撞体积，能阻挡敌人，有血量，会自动寻敌并攻击。 (如：骷髅兵、死灵狼)
*   **Satellite (卫星型/浮游炮)**: 围绕玩家旋转或跟随，不可被选中，辅助攻击。 (如：环绕飞剑)
*   **Clone (镜像型)**: 玩家的分身，继承完全相同的攻击行为，但伤害倍率较低。

### 1.2 属性继承 (Stat Inheritance)
召唤物的数据快照（Snapshot）机制至关重要：
*   **Inheritance Ratio**: 不同的召唤物继承玩家属性的比例不同（如：继承 50% 攻速，100% 暴击）。
*   **Dynamic vs Static**:
    *   **Static**: 召唤瞬间确定面板（大多数非光环类召唤）。
    *   **Dynamic**: 随玩家属性实时变化（如链接玩家的灵魂锁链）。

### 1.3 行为指令 (Command AI)
*   **Aggressive**: 搜寻屏幕内所有敌人。
*   **Defensive**: 只攻击攻击玩家的敌人。
*   **Focus Fire**: 攻击玩家当前瞄准的目标（光标指示）。

## 2. 环境传播与蔓延 (Propagation & Spreading)

“火焰范围蔓延”属于 **Cellular Automata (元胞自动机)** 或 **传染 (Contagion)** 机制的范畴。

### 2.1 实体间传导 (Entity-to-Entity Propagation)
不需要地块网格，直接基于实体距离的传播。
*   **Ignite Proliferation (点燃扩散)**:
    *   机制: 当一个敌人处于“燃烧”状态死亡时，将剩余的燃烧层数（或新的燃烧状态）复制给半径 R 内的所有敌人。
    *   扩展: “瘟疫”效果，在存活时通过 Tick 周期性传染周围。

### 2.2 区域场 (Field / Zone System)
引入 `ZoneManager` 来管理地面上的持久化效果区域。
*   **Pools (地面池)**: 毒液滩、岩浆、神圣地面。
    *   *实现*: 具有 Circle Collider 的 Trigger 节点。
    *   *逻辑*: `OnTriggerEnter` -> Apply Status; `OnTriggerExit` -> Remove Status (optional)。
*   **Reactive Ground (反应地表)**:
    *   向“毒液滩”发射“火箭”，引爆毒池造成瞬间高伤。
    *   向“水面”发射“冰箭”，冻结水面减慢经过敌人的速度或使其滑倒。

### 2.3 连锁反应示例 (Chain Reaction)
1.  **步骤 A**: 玩家投掷毒瓶，生成半径 200 的 `PoisonZone`。
2.  **步骤 B**: 怪物进入区域，获得 `Poisoned` 状态。
3.  **步骤 C**: 玩家使用“尸爆术”（Tag: Fire）。
4.  **步骤 D**: 尸爆击中带毒的怪物 -> 触发 `Catalyst: Fire + Poison` -> 产生 `GasExplosion` (毒气爆炸)，范围扩大至 400，并施加 `Blind` 致盲效果。

## 3. 开发实施建议

### 3.1 扩展 EnemyManager 支持友军
*   目前的 `EnemyManager` 是专门管理敌人的。为了支持 Minion：
    *   方案 A: 改造 `EnemyManager` 为 `UnitManager`，引入 `Faction` 字段（0=Friendly, 1=Hostile），统一管理所有生物。
    *   方案 B: 新增 `MinionManager`，逻辑类似但 AI 目标相反（Target=Enemy）。**推荐方案 B**，因为逻辑差异较大。

### 3.2 实现传播算法 (The Spread Algorithm)
在 `StatusManager` 中增加 `on_entity_died` 回调监听：
```gdscript
# 伪代码: 点燃扩散 (GDScript 风格)
# 状态类型系统为数据驱动的整数 ID，使用 StatusID Autoload 常量（见 architecture_design.md §8 ADR-R5-N2）。
# StatusID.BURN 等常量定义在 status_id.gd (Autoload: StatusID) 中。
# 禁止写法：StatusManager.has_status(victim_id, StatusType.BURN)  ← StatusType 枚举不存在
func on_enemy_died(victim_id: int) -> void:
    if StatusManager.has_status(victim_id, StatusID.BURN):  # ✅ 使用 StatusID 常量
        var neighbors: Array[int] = SpatialGrid.query_circle(
            EnemyManager.get_position(victim_id), 300.0)
        for n_id in neighbors:
            StatusManager.apply(n_id, StatusID.BURN, 0)    # ✅ 使用 StatusID 常量
        VFXManager.play("fire_spread", EnemyManager.get_position(victim_id))
```

> **StatusID Autoload 规范**：与 `CoreFeatureTag` 类比，所有状态类型必须通过
> `StatusID` Autoload 常量引用，禁止在业务代码中直接写整数字面量或自造枚举：
> ```gdscript
> # status_id.gd  (Autoload: StatusID)
> ## 状态效果 ID 常量表 — 所有系统通过此处引用，禁止裸整数
> const BURN:          int = 1   # 点燃（Fire DoT）
> const FREEZE:        int = 2   # 冻结（硬控）
> const POISON:        int = 3   # 中毒（Poison DoT，可叠层）
> const WET:           int = 4   # 潮湿（增幅雷电伤害）
> const OILY:          int = 5   # 油腻（增幅火焰伤害）
> const STUN:          int = 6   # 麻痹（雷电触发）
> const COMBO_MARK:    int = 7   # 连击标记（详见 consecutive_hits_stacking.md）
> const VULNERABILITY: int = 8   # 易伤标记（激光叠层增伤，详见 consecutive_hits_stacking.md）
> # 新增状态 ID 从 9 开始递增，并在此处登记
> ```

### 3.3 实现地面效果 (Zone Manager)
*   **ZoneManager 必须基于 `SpatialGrid` 进行空间索引（ADR-R5-N1 规范）**，
    **禁止使用 Area2D（Trigger 模式）**——Area2D 会为每个 Zone 创建 Godot 物理节点，
    1000 敌人 × 64 Zone 的碰撞检测开销完全无法接受，违反 ECS-Lite 架构原则。
    详见 `architecture_design.md §8 ADR-R5-N1`（ZoneManager 权威实现定义）。
*   每 `_physics_process` 帧对所有 Zone 调用 `SpatialGrid.query_circle(zone_center, zone_radius)`，
    批量获取范围内敌人 ID，然后通过 `StatusManager.apply()` 施加状态效果；
    使用 `tick_interval` 速率限制防止每帧过量触发（见 architecture_design.md §8 ADR-R5-N1）。
