From 4f4090d5c5f06892e55d5dbc8d4570ba5370f9ea Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Sat, 17 Oct 2026 22:22:37 +0800 Subject: [PATCH] =?UTF-8?q?style(10-11):=20prettier=20=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E5=8C=96=E4=B8=AD=E7=BA=A7=E6=95=99=E7=A8=8B=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/intermediate/combat-overview.md | 20 +++--- docs/intermediate/data-plugins.md | 14 ++--- docs/intermediate/data-state-overview.md | 42 ++++++------- docs/intermediate/enemy-aura.md | 34 ++++++----- docs/intermediate/enemy-calculator.md | 3 +- docs/intermediate/enemy-combat-script.md | 14 ++--- docs/intermediate/enemy-final.md | 10 +-- docs/intermediate/enemy-map-damage.md | 21 ++++--- docs/intermediate/enemy-query.md | 8 ++- docs/intermediate/enemy-specials.md | 78 ++++++++++++------------ docs/intermediate/enemy-status-hooks.md | 10 +-- docs/intermediate/events.md | 24 ++++---- docs/intermediate/flags.md | 22 +++---- docs/intermediate/hero-items.md | 12 ++-- docs/intermediate/hooks.md | 62 +++++++++---------- docs/intermediate/src-tour.md | 20 +++--- 16 files changed, 204 insertions(+), 190 deletions(-) diff --git a/docs/intermediate/combat-overview.md b/docs/intermediate/combat-overview.md index cd117a1..7254176 100644 --- a/docs/intermediate/combat-overview.md +++ b/docs/intermediate/combat-overview.md @@ -75,15 +75,15 @@ graph TD ## 流程步骤与对应文档 -| 步骤 | 做什么 | 对应文档 | -|------|--------|----------| -| 特殊属性 | 定义怪物的机制与参数 | [特殊属性](./enemy-specials.md) | -| 光环 | 影响周围怪物的基础属性或特殊属性 | [怪物光环](./enemy-aura.md) | -| 查询 | 读取上下文后调整自身 | [怪物查询](./enemy-query.md) | -| 最终效果 | 只调整自身基础属性 | [最终属性效果](./enemy-final.md) | -| 伤害计算 | 实现 `f(enemy, hero)` | [伤害计算](./enemy-calculator.md) | -| 地图伤害 | 勇士移动时按位置结算伤害 | [地图伤害](./enemy-map-damage.md) | -| 战前 / 战后脚本 | 拦截战斗、结算奖励 | [战斗脚本](./enemy-combat-script.md) | -| 状态钩子 | 处理中毒、衰弱、重生等状态 | [状态钩子](./enemy-status-hooks.md) | +| 步骤 | 做什么 | 对应文档 | +| --------------- | -------------------------------- | ------------------------------------ | +| 特殊属性 | 定义怪物的机制与参数 | [特殊属性](./enemy-specials.md) | +| 光环 | 影响周围怪物的基础属性或特殊属性 | [怪物光环](./enemy-aura.md) | +| 查询 | 读取上下文后调整自身 | [怪物查询](./enemy-query.md) | +| 最终效果 | 只调整自身基础属性 | [最终属性效果](./enemy-final.md) | +| 伤害计算 | 实现 `f(enemy, hero)` | [伤害计算](./enemy-calculator.md) | +| 地图伤害 | 勇士移动时按位置结算伤害 | [地图伤害](./enemy-map-damage.md) | +| 战前 / 战后脚本 | 拦截战斗、结算奖励 | [战斗脚本](./enemy-combat-script.md) | +| 状态钩子 | 处理中毒、衰弱、重生等状态 | [状态钩子](./enemy-status-hooks.md) | 勇士一侧的属性读写见[勇士属性](./hero-attribute.md)。 diff --git a/docs/intermediate/data-plugins.md b/docs/intermediate/data-plugins.md index 3866166..8d14a69 100644 --- a/docs/intermediate/data-plugins.md +++ b/docs/intermediate/data-plugins.md @@ -6,13 +6,13 @@ 一个插件实现 `IDataPluginDefine` 接口: -| 成员 | 说明 | -| --- | --- | -| `id` | 插件标识符,全局唯一 | -| `dependencies` | 依赖的其它插件 **id 字符串数组**,不允许循环依赖 | -| `awake(state, dependencies)` | 同步初始化 | -| `initialize(state, dependencies)` | 异步初始化 | -| `afterLoad(state, dependencies)` | 加载完成后初始化 | +| 成员 | 说明 | +| --------------------------------- | ------------------------------------------------ | +| `id` | 插件标识符,全局唯一 | +| `dependencies` | 依赖的其它插件 **id 字符串数组**,不允许循环依赖 | +| `awake(state, dependencies)` | 同步初始化 | +| `initialize(state, dependencies)` | 异步初始化 | +| `afterLoad(state, dependencies)` | 加载完成后初始化 | 三个时机方法都会收到数据端主对象 `state`,你对数据端的操作都从这里展开(`state` 的获取方式与含义见[数据端总览](./data-state-overview.md))。 diff --git a/docs/intermediate/data-state-overview.md b/docs/intermediate/data-state-overview.md index a2106ff..5f958e4 100644 --- a/docs/intermediate/data-state-overview.md +++ b/docs/intermediate/data-state-overview.md @@ -55,27 +55,27 @@ class MySystem { 下表把最常用的对象与接口列在一起——只要拿到了 `state`,就能按表中的方式访问它们: -| 对象 | 获取方式 | 用途 | 分层 | -| --- | --- | --- | --- | -| `hero` | `state.hero` | 勇士状态(属性、道具、装备、位置) | L1 | -| `maps` | `state.maps` | 楼层集合与楼层激活 | L1 | -| `flags` | `state.flags` | 全局可存档变量 | L1 | -| `enemyManager` | `state.enemyManager` | 怪物创建与查询 | L1 | -| `enemyContext` | `state.enemyContext` | 怪物属性构建与光环 | L2 | -| `combat` | `state.combat` | 战斗流程 | L2 | -| `eventSystem` | `state.eventSystem` | 地图事件执行 | L2 | -| `pathfinding` | `state.pathfinding` | 勇士寻路 | L2 | -| `tileStore` | `state.tileStore` | 图块定义存储 | L0 | -| `itemStore` | `state.itemStore` | 道具定义存储 | L0 | -| `mapStore` | `state.mapStore` | 地图定义存储 | L0 | -| `eventStore` | `state.eventStore` | 游戏事件存储 | L0 | -| `faceManager` | `state.faceManager` | 朝向管理 | L0 | -| `roleFace` | `state.roleFace` | 朝向绑定 | L0 | -| `replaySystem` | `state.replaySystem` | 录像系统 | L0 | -| `loader` | `state.loader` | 数据端加载对象 | L3 | -| `loadManager` | `state.loadManager` | 加载管理器 | L3 | -| `getDataPlugin(id)` | `state.getDataPlugin('xxx')` | 取得已加装的插件 | L3 | -| `emitTip(...)` | `state.emitTip('提示')` | 通知渲染端提示 | L0 | +| 对象 | 获取方式 | 用途 | 分层 | +| ------------------- | ---------------------------- | ---------------------------------- | ---- | +| `hero` | `state.hero` | 勇士状态(属性、道具、装备、位置) | L1 | +| `maps` | `state.maps` | 楼层集合与楼层激活 | L1 | +| `flags` | `state.flags` | 全局可存档变量 | L1 | +| `enemyManager` | `state.enemyManager` | 怪物创建与查询 | L1 | +| `enemyContext` | `state.enemyContext` | 怪物属性构建与光环 | L2 | +| `combat` | `state.combat` | 战斗流程 | L2 | +| `eventSystem` | `state.eventSystem` | 地图事件执行 | L2 | +| `pathfinding` | `state.pathfinding` | 勇士寻路 | L2 | +| `tileStore` | `state.tileStore` | 图块定义存储 | L0 | +| `itemStore` | `state.itemStore` | 道具定义存储 | L0 | +| `mapStore` | `state.mapStore` | 地图定义存储 | L0 | +| `eventStore` | `state.eventStore` | 游戏事件存储 | L0 | +| `faceManager` | `state.faceManager` | 朝向管理 | L0 | +| `roleFace` | `state.roleFace` | 朝向绑定 | L0 | +| `replaySystem` | `state.replaySystem` | 录像系统 | L0 | +| `loader` | `state.loader` | 数据端加载对象 | L3 | +| `loadManager` | `state.loadManager` | 加载管理器 | L3 | +| `getDataPlugin(id)` | `state.getDataPlugin('xxx')` | 取得已加装的插件 | L3 | +| `emitTip(...)` | `state.emitTip('提示')` | 通知渲染端提示 | L0 | ```ts const plugin = state.getDataPlugin('main'); diff --git a/docs/intermediate/enemy-aura.md b/docs/intermediate/enemy-aura.md index e0578d9..1a7030c 100644 --- a/docs/intermediate/enemy-aura.md +++ b/docs/intermediate/enemy-aura.md @@ -22,23 +22,23 @@ 引擎内置了三类光环,分别处理不同的需求: -| 光环 | code | 视图类 | priority | 行为 | -|------|------|--------|----------|------| -| 普通光环 | 23 | `CommonAura` | 10 | 按范围给怪物加 `hp` / `atk` / `def` 百分比 | -| 支援 | 24 | `GuardAura` | 5 | 把范围内的怪物登记为支援者,战斗时一起结算 | -| 特殊光环 | 26 | `SpecialAura` | 20 | 通过 `SpecialAuraModifier` 给目标添加或修改特殊属性 | +| 光环 | code | 视图类 | priority | 行为 | +| -------- | ---- | ------------- | -------- | --------------------------------------------------- | +| 普通光环 | 23 | `CommonAura` | 10 | 按范围给怪物加 `hp` / `atk` / `def` 百分比 | +| 支援 | 24 | `GuardAura` | 5 | 把范围内的怪物登记为支援者,战斗时一起结算 | +| 特殊光环 | 26 | `SpecialAura` | 20 | 通过 `SpecialAuraModifier` 给目标添加或修改特殊属性 | 这三类都在 `src/data/enemy/aura.ts` 中实现,并在 `initializeEnemy` 里通过 `ctx.registerAuraConverter(...)` 注册(`initializeEnemy` 是 `src/data/enemy/initialize.ts` 中集中注册内置怪物功能的入口函数;内置的光环转换器与你自己新增的转换器都从这里注册)。 普通光环(code 23)的参数接口是 `ISpecial23Value`,下文示例里 `setValue({...})` 传入的就是这几个字段: -| 字段 | 含义 | -|------|------| -| `range` | 光环范围值;为 0 时作用于同楼层所有怪物 | -| `square` | `true` 为矩形范围,`false` 为十字范围(范围大于 1 时按曼哈顿距离计算) | -| `hpBuff` | 目标生命值提升百分比 | -| `atkBuff` | 目标攻击力提升百分比 | -| `defBuff` | 目标防御力提升百分比 | +| 字段 | 含义 | +| --------- | ---------------------------------------------------------------------- | +| `range` | 光环范围值;为 0 时作用于同楼层所有怪物 | +| `square` | `true` 为矩形范围,`false` 为十字范围(范围大于 1 时按曼哈顿距离计算) | +| `hpBuff` | 目标生命值提升百分比 | +| `atkBuff` | 目标攻击力提升百分比 | +| `defBuff` | 目标防御力提升百分比 | ## 运作方式 @@ -120,7 +120,10 @@ import { ISpecial30Value } from './special'; const MANHATTAN_RANGE = new ManhattanRange(); const RECT_RANGE = new RectRange(); -export class WeakAuraConverter implements IAuraConverter { +export class WeakAuraConverter implements IAuraConverter< + IEnemyAttr, + IHeroAttr +> { shouldConvert(special: ISpecial): boolean { return special.code === 30; } @@ -251,7 +254,10 @@ export class ChainAuraModifier implements IEnemySpecialModifier { } } -export class ChainAuraConverter implements IAuraConverter { +export class ChainAuraConverter implements IAuraConverter< + IEnemyAttr, + IHeroAttr +> { shouldConvert(special: ISpecial): boolean { return special.code === 31; } diff --git a/docs/intermediate/enemy-calculator.md b/docs/intermediate/enemy-calculator.md index 188b436..2444eb7 100644 --- a/docs/intermediate/enemy-calculator.md +++ b/docs/intermediate/enemy-calculator.md @@ -78,7 +78,8 @@ export class ArithmeticCalculator implements IDamageCalculator< handler: IReadonlyEnemyHandler ): IEnemyDamageInfoBase { const { enemy, hero } = handler; - const heroPerDamage = hero.getFinalAttribute('atk') - enemy.getAttribute('def'); + const heroPerDamage = + hero.getFinalAttribute('atk') - enemy.getAttribute('def'); if (heroPerDamage <= 0) { return { damage: Infinity, turn: 0 }; } diff --git a/docs/intermediate/enemy-combat-script.md b/docs/intermediate/enemy-combat-script.md index bb7441b..9a7afe7 100644 --- a/docs/intermediate/enemy-combat-script.md +++ b/docs/intermediate/enemy-combat-script.md @@ -40,13 +40,13 @@ state.combat.addCombatScript(new MainCombatScript()); 战斗前后能做事的除了脚本,还有钩子。两者的区别主要在「能不能改变战斗的走向」和「多个监听者如何共存」: -| 需求 | 用脚本 | 用钩子 | -|------|--------|--------| -| 决定这场战斗是否发生 | 是,`before` 返回 `false` | 否,`onBeforeCombat` 不能阻止战斗 | -| 按固定顺序结算奖励或回血 | 是,用 `priority` 排序 | 顺序不由优先级控制 | -| 只响应战斗结果做副作用 | 可以,但不是必须 | 是,`onAfterCombat` 更直接 | -| 多个互不影响的监听者 | 不适合,同优先级会冲突 | 适合,多个钩子可以并存 | -| 需要和内置脚本一样参与战前拦截 | 是 | 否 | +| 需求 | 用脚本 | 用钩子 | +| ------------------------------ | ------------------------- | --------------------------------- | +| 决定这场战斗是否发生 | 是,`before` 返回 `false` | 否,`onBeforeCombat` 不能阻止战斗 | +| 按固定顺序结算奖励或回血 | 是,用 `priority` 排序 | 顺序不由优先级控制 | +| 只响应战斗结果做副作用 | 可以,但不是必须 | 是,`onAfterCombat` 更直接 | +| 多个互不影响的监听者 | 不适合,同优先级会冲突 | 适合,多个钩子可以并存 | +| 需要和内置脚本一样参与战前拦截 | 是 | 否 | 简单记:**要拦截或按顺序结算,用脚本;只想在战斗前后做附加动作,用钩子。** diff --git a/docs/intermediate/enemy-final.md b/docs/intermediate/enemy-final.md index cce55af..493d2f3 100644 --- a/docs/intermediate/enemy-final.md +++ b/docs/intermediate/enemy-final.md @@ -26,11 +26,11 @@ state.enemyContext.registerFinalEffect(effect); 光环、查询、最终效果都在构建计算后怪物时执行,但读取与影响的范围不同。把三者放在一起看,分工就清楚了: -| 效果 | 读取其他怪物/上下文 | 影响其他怪物 | 典型用途 | -|------|---------------------|--------------|----------| -| 光环 | 否(只按范围命中) | 是 | 给周围怪物加属性或特殊属性 | -| 查询 | 是 | 否(只改自身) | 抱团、同化、号角 | -| 最终 | 否 | 否 | 坚固、模仿、仿攻 | +| 效果 | 读取其他怪物/上下文 | 影响其他怪物 | 典型用途 | +| ---- | ------------------- | -------------- | -------------------------- | +| 光环 | 否(只按范围命中) | 是 | 给周围怪物加属性或特殊属性 | +| 查询 | 是 | 否(只改自身) | 抱团、同化、号角 | +| 最终 | 否 | 否 | 坚固、模仿、仿攻 | 最终效果可以读取勇士属性(模仿与仿攻都需要),但不会扫描周围怪物,也不会改变其他怪物。 diff --git a/docs/intermediate/enemy-map-damage.md b/docs/intermediate/enemy-map-damage.md index 8031927..069a465 100644 --- a/docs/intermediate/enemy-map-damage.md +++ b/docs/intermediate/enemy-map-damage.md @@ -34,13 +34,13 @@ mapDamage?.useConverter(new MainMapDamageConverter()); `MapDamageType` 定义了 `Unknown`、`Zone`、`Layer`、`Repulse`、`Between` 五种类型。内置视图与转换器在 `src/data/enemy/mapDamage.ts`: -| 类型 | 视图类 | 内置特殊属性 code | 说明 | -|------|--------|-------------------|------| -| 领域 | `ZoneDamageView` | 13(`ISpecial13Value`) | 范围内自动减血 | -| 夹击 | `BetweenDamageView` | 14 | 两只怪物夹住勇士时扣半血 | -| 阻击 | `RepulseDamageView` | 16 | 经过时怪物后退并造成伤害 | -| 激光 | `LaserDamageView` | 22 | 同行或同列时造成伤害 | -| 捕捉 | `AmbushDamageView` | 25 | 触发强制战斗,本身不造成伤害 | +| 类型 | 视图类 | 内置特殊属性 code | 说明 | +| ---- | ------------------- | ----------------------- | ---------------------------- | +| 领域 | `ZoneDamageView` | 13(`ISpecial13Value`) | 范围内自动减血 | +| 夹击 | `BetweenDamageView` | 14 | 两只怪物夹住勇士时扣半血 | +| 阻击 | `RepulseDamageView` | 16 | 经过时怪物后退并造成伤害 | +| 激光 | `LaserDamageView` | 22 | 同行或同列时造成伤害 | +| 捕捉 | `AmbushDamageView` | 25 | 触发强制战斗,本身不造成伤害 | 表中的 code 就是 `src/data/enemy/special.ts` 里同名内置属性注册的编号,转换器读取的也是同一组编号。要启用某类地图伤害,给怪物挂上对应的内置特殊属性即可,不需要再换算编号或修改转换器。 @@ -71,7 +71,8 @@ map.set( { damage: 50 }, { name: '遮挡激光', - desc: special => `同行或同列时造成${special.value.damage}点伤害,被地形遮挡则无效。`, + desc: special => + `同行或同列时造成${special.value.damage}点伤害,被地形遮挡则无效。`, color: '#D0A0DD' } ) @@ -182,7 +183,9 @@ export class BlockedLaserConverter implements IMapDamageConverter< const special = handler.enemy.getSpecial(43); if (!special) return []; const face = handler.state.faceManager.get(FaceGroup.Dir4)!; - return [new BlockedLaserDamageView(context, handler.locator, special, face)]; + return [ + new BlockedLaserDamageView(context, handler.locator, special, face) + ]; } } diff --git a/docs/intermediate/enemy-query.md b/docs/intermediate/enemy-query.md index e8514ff..2972bb7 100644 --- a/docs/intermediate/enemy-query.md +++ b/docs/intermediate/enemy-query.md @@ -121,14 +121,18 @@ const effect: IEnemySpecialQueryEffect = { add(handler) { const result: ISpecial[] = []; const others = [...ctx.iterateEnemy()] - .filter(([, view]) => view.getComputedEnemy() !== handler.enemy) + .filter( + ([, view]) => view.getComputedEnemy() !== handler.enemy + ) .sort( ([a], [b]) => ctx.indexer.index(a.x, a.y) - ctx.indexer.index(b.x, b.y) ); for (const [, view] of others) { - for (const special of view.getComputedEnemy().iterateSpecials()) { + for (const special of view + .getComputedEnemy() + .iterateSpecials()) { if (special.code === 41) continue; if (handler.enemy.hasSpecial(special.code)) continue; result.push(special.clone()); diff --git a/docs/intermediate/enemy-specials.md b/docs/intermediate/enemy-specials.md index 4cfb478..40ce2d0 100644 --- a/docs/intermediate/enemy-specials.md +++ b/docs/intermediate/enemy-specials.md @@ -12,35 +12,35 @@ 下表是 `src/data/enemy/special.ts` 里 `map.set(code, ...)` 当前注册的全部内置属性,code 与名称一一对应。判断「某个数字代表哪种机制」时以本表为准: -| code | 名称 | 参数 | -|------|------|------| -| 0 | 空 | 无 | -| 1 | 先攻 | 无 | -| 2 | 魔攻 | 无 | -| 3 | 坚固 | 无 | -| 4 | n连击 | 每回合攻击次数 | -| 5 | 破甲 | 附加伤害百分比 | -| 6 | 反击 | 附加伤害百分比 | -| 7 | 净化 | 附加伤害倍数 | -| 8 | 模仿 | 无 | -| 9 | 吸血 | `ISpecial9Value`(比例与是否加到自身) | -| 10 | 中毒 | 每步损失生命值 | -| 11 | 衰弱 | 攻防下降比例 | -| 12 | 诅咒 | 无 | -| 13 | 领域 | `ISpecial13Value` | -| 14 | 夹击 | 无 | -| 15 | 仇恨 | 无 | -| 16 | 阻击 | 伤害值 | -| 17 | 自爆 | 无 | -| 18 | 无敌 | 无 | -| 19 | 退化 | `ISpecial19Value`(攻防下降值) | -| 20 | 固伤 | 固定伤害值 | -| 21 | 重生 | 无 | -| 22 | 激光 | 伤害值 | -| 23 | 光环 | `ISpecial23Value` | -| 24 | 支援 | 无 | -| 25 | 捕捉 | 无 | -| 26 | 特殊光环 | `ISpecial26Value` | +| code | 名称 | 参数 | +| ---- | -------- | -------------------------------------- | +| 0 | 空 | 无 | +| 1 | 先攻 | 无 | +| 2 | 魔攻 | 无 | +| 3 | 坚固 | 无 | +| 4 | n连击 | 每回合攻击次数 | +| 5 | 破甲 | 附加伤害百分比 | +| 6 | 反击 | 附加伤害百分比 | +| 7 | 净化 | 附加伤害倍数 | +| 8 | 模仿 | 无 | +| 9 | 吸血 | `ISpecial9Value`(比例与是否加到自身) | +| 10 | 中毒 | 每步损失生命值 | +| 11 | 衰弱 | 攻防下降比例 | +| 12 | 诅咒 | 无 | +| 13 | 领域 | `ISpecial13Value` | +| 14 | 夹击 | 无 | +| 15 | 仇恨 | 无 | +| 16 | 阻击 | 伤害值 | +| 17 | 自爆 | 无 | +| 18 | 无敌 | 无 | +| 19 | 退化 | `ISpecial19Value`(攻防下降值) | +| 20 | 固伤 | 固定伤害值 | +| 21 | 重生 | 无 | +| 22 | 激光 | 伤害值 | +| 23 | 光环 | `ISpecial23Value` | +| 24 | 支援 | 无 | +| 25 | 捕捉 | 无 | +| 26 | 特殊光环 | `ISpecial26Value` | 地图伤害使用的也是上表的编号:转换器读取领域 13、夹击 14、阻击 16、激光 22、捕捉 25,挂上对应的内置属性就会生效(详见[地图伤害](./enemy-map-damage.md))。 @@ -154,16 +154,16 @@ map.set( 注册只是让引擎认识这条属性,真正让它生效的代码在别处。`special.ts` 顶部的注释给出了内置属性的实现分工。新增属性时按这张表找落点: -| 属性类型 | 实现位置 | 说明 | -|----------|----------|------| -| 调参类(先攻、魔攻、连击、破甲、反击、净化、固伤、仇恨、自爆等) | `src/data/enemy/calculator.ts` 的 `MainDamageCalculator.calculate` | 只改变伤害公式的结果 | -| 坚固、模仿 | `src/data/enemy/final.ts` 的 `MainEnemyFinalEffect.apply` | 只修改怪物自身基础属性 | -| 领域、夹击、阻击、激光、捕捉 | `src/data/enemy/mapDamage.ts` | 伤害视图 + 转换器 | -| 光环、支援、特殊光环 | `src/data/enemy/aura.ts` | 光环视图 + 转换器 | -| 中毒的每步效果 | `src/data/enemy/hook.ts` 的 `EnemyMoveHooks.handlePoison` | 移动钩子 | -| 中毒的瞬移效果 | `src/data/enemy/hook.ts` 的 `EnemyPathfindingHooks.handlePoison` | 寻路钩子 | -| 衰弱 | `src/data/enemy/hook.ts` 的 `EnemyCombatHooks.onAfterCombat` | 战后钩子 + 修饰器 | -| 重生 | `src/data/enemy/hook.ts` 的 `EnemyCombatHooks.onAfterCombat` 与 `EnemyChangeFloorHooks.onSetFloor` | 两个钩子协同 | +| 属性类型 | 实现位置 | 说明 | +| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | ---------------------- | +| 调参类(先攻、魔攻、连击、破甲、反击、净化、固伤、仇恨、自爆等) | `src/data/enemy/calculator.ts` 的 `MainDamageCalculator.calculate` | 只改变伤害公式的结果 | +| 坚固、模仿 | `src/data/enemy/final.ts` 的 `MainEnemyFinalEffect.apply` | 只修改怪物自身基础属性 | +| 领域、夹击、阻击、激光、捕捉 | `src/data/enemy/mapDamage.ts` | 伤害视图 + 转换器 | +| 光环、支援、特殊光环 | `src/data/enemy/aura.ts` | 光环视图 + 转换器 | +| 中毒的每步效果 | `src/data/enemy/hook.ts` 的 `EnemyMoveHooks.handlePoison` | 移动钩子 | +| 中毒的瞬移效果 | `src/data/enemy/hook.ts` 的 `EnemyPathfindingHooks.handlePoison` | 寻路钩子 | +| 衰弱 | `src/data/enemy/hook.ts` 的 `EnemyCombatHooks.onAfterCombat` | 战后钩子 + 修饰器 | +| 重生 | `src/data/enemy/hook.ts` 的 `EnemyCombatHooks.onAfterCombat` 与 `EnemyChangeFloorHooks.onSetFloor` | 两个钩子协同 | 具体实现方式分别见[怪物光环](./enemy-aura.md)、[伤害计算](./enemy-calculator.md)、[地图伤害](./enemy-map-damage.md)与[状态钩子](./enemy-status-hooks.md)。 diff --git a/docs/intermediate/enemy-status-hooks.md b/docs/intermediate/enemy-status-hooks.md index cd1044a..858145a 100644 --- a/docs/intermediate/enemy-status-hooks.md +++ b/docs/intermediate/enemy-status-hooks.md @@ -15,11 +15,11 @@ ## 三类内置状态 -| 状态 | 使用的钩子 | 实现位置 | 行为 | -|------|------------|----------|------| -| 中毒 | `onStepEnd` + `onAfterTeleportTo` | `EnemyMoveHooks` / `EnemyPathfindingHooks` | 读取 `poison` flag,按移动扣血;瞬移时按路径长度处理 | -| 衰弱 | `onAfterCombat` + 修饰器 | `EnemyCombatHooks` | 战后取最高虚弱值,用 `PercentageModifier` 降低攻防 | -| 重生 | `onAfterCombat` + `onSetFloor` | `EnemyCombatHooks` / `EnemyChangeFloorHooks` | 战后记录 `rebirth` flag;切层时把记录的事件块放回 | +| 状态 | 使用的钩子 | 实现位置 | 行为 | +| ---- | --------------------------------- | -------------------------------------------- | ---------------------------------------------------- | +| 中毒 | `onStepEnd` + `onAfterTeleportTo` | `EnemyMoveHooks` / `EnemyPathfindingHooks` | 读取 `poison` flag,按移动扣血;瞬移时按路径长度处理 | +| 衰弱 | `onAfterCombat` + 修饰器 | `EnemyCombatHooks` | 战后取最高虚弱值,用 `PercentageModifier` 降低攻防 | +| 重生 | `onAfterCombat` + `onSetFloor` | `EnemyCombatHooks` / `EnemyChangeFloorHooks` | 战后记录 `rebirth` flag;切层时把记录的事件块放回 | 补充说明: diff --git a/docs/intermediate/events.md b/docs/intermediate/events.md index 71203f3..d800af2 100644 --- a/docs/intermediate/events.md +++ b/docs/intermediate/events.md @@ -25,18 +25,18 @@ interface BuiltInFunction { `func` 的第二个参数是事件环境 `IBlockEventEnv`,里面放的是「这次事件在什么情况下被触发」。常用的字段: -| 字段 | 说明 | -| --- | --- | -| `state` | 数据端主对象,一切接口的入口 | -| `type` | 事件类型(普通事件 / 点事件 / 图块事件) | -| `trigger` | 本次事件的触发器类型 | -| `heroLocator` | 触发事件时勇士的位置 | -| `heroFloor` | 触发事件时勇士所在楼层 | -| `triggerLocator` | 触发者的位置,可能不存在 | -| `tile` | 触发事件的图块,可能不存在 | -| `layer` | 触发事件的图层,可能不存在 | -| `map` | 触发事件的地图,可能不存在 | -| `system` | 事件系统对象 | +| 字段 | 说明 | +| ---------------- | ---------------------------------------- | +| `state` | 数据端主对象,一切接口的入口 | +| `type` | 事件类型(普通事件 / 点事件 / 图块事件) | +| `trigger` | 本次事件的触发器类型 | +| `heroLocator` | 触发事件时勇士的位置 | +| `heroFloor` | 触发事件时勇士所在楼层 | +| `triggerLocator` | 触发者的位置,可能不存在 | +| `tile` | 触发事件的图块,可能不存在 | +| `layer` | 触发事件的图层,可能不存在 | +| `map` | 触发事件的地图,可能不存在 | +| `system` | 事件系统对象 | 其余字段见 API 参考。多数情况下你只需要 `state`:通过它能访问勇士、地图、Flag 等(见[数据端总览](./data-state-overview.md))。 diff --git a/docs/intermediate/flags.md b/docs/intermediate/flags.md index fb5e17e..20d3d33 100644 --- a/docs/intermediate/flags.md +++ b/docs/intermediate/flags.md @@ -10,17 +10,17 @@ Flag 中的每一项是一个**字段**(`IFlagCommonField`),字段名与 `IFlagSystem` 提供如下接口: -| 接口 | 说明 | -| --- | --- | -| `occupied(field)` | 判断字段是否被占用 | -| `setField(field, value)` | 以指定值插入字段,返回字段对象 | -| `getField(field)` | 取字段对象,不存在返回 `null` | -| `getOrInsert(field, defaultValue)` | 取字段,不存在则以默认值创建 | -| `getOrInsertComputed(field, defaultValue)` | 同上,但默认值由函数惰性计算 | -| `deleteField(field)` | 删除字段 | -| `setFieldValue(field, value)` | 设置字段的值 | -| `addFieldValue(field, value)` | 对数字字段增减 | -| `getFieldValue(field)` | 取字段的值,不存在返回 `undefined` | +| 接口 | 说明 | +| -------------------------------------------- | -------------------------------------- | +| `occupied(field)` | 判断字段是否被占用 | +| `setField(field, value)` | 以指定值插入字段,返回字段对象 | +| `getField(field)` | 取字段对象,不存在返回 `null` | +| `getOrInsert(field, defaultValue)` | 取字段,不存在则以默认值创建 | +| `getOrInsertComputed(field, defaultValue)` | 同上,但默认值由函数惰性计算 | +| `deleteField(field)` | 删除字段 | +| `setFieldValue(field, value)` | 设置字段的值 | +| `addFieldValue(field, value)` | 对数字字段增减 | +| `getFieldValue(field)` | 取字段的值,不存在返回 `undefined` | | `getFieldValueDefaults(field, defaultValue)` | 取字段的值,不存在则以默认值创建并返回 | `getOrInsertComputed` 只在字段确实不存在时才执行默认值函数,适合默认值计算量较大的场景。`getFieldValue` 没有默认值,需要默认值时用 `getFieldValueDefaults`。 diff --git a/docs/intermediate/hero-items.md b/docs/intermediate/hero-items.md index 2786edd..637c1f3 100644 --- a/docs/intermediate/hero-items.md +++ b/docs/intermediate/hero-items.md @@ -6,12 +6,12 @@ 一件道具被捡起或使用时会发生什么,取决于它属于哪一类。类别由 `ItemCategory` 定义: -| 类别 | 含义 | 典型行为 | -| --- | --- | --- | -| `Constant` | 永久道具 | 使用后不消耗,可以反复使用 | -| `Consumable` | 一次性道具 | 使用后消耗一个,用完即消失 | -| `Pick` | 即捡即用道具 | 拾取时立刻生效,不进入背包 | -| `Equipment` | 装备类道具 | 走装备系统,见[勇士装备](./hero-equipment.md) | +| 类别 | 含义 | 典型行为 | +| ------------ | ------------ | --------------------------------------------- | +| `Constant` | 永久道具 | 使用后不消耗,可以反复使用 | +| `Consumable` | 一次性道具 | 使用后消耗一个,用完即消失 | +| `Pick` | 即捡即用道具 | 拾取时立刻生效,不进入背包 | +| `Equipment` | 装备类道具 | 走装备系统,见[勇士装备](./hero-equipment.md) | `Unknown` 表示尚未归类。理解了这四类的差别,就能预判一件道具「什么时候、发生什么」:`Pick` 道具不会进入背包——`addItem` 到 `Pick` 道具时会直接触发它的效果。 diff --git a/docs/intermediate/hooks.md b/docs/intermediate/hooks.md index 8cbaa81..29cd513 100644 --- a/docs/intermediate/hooks.md +++ b/docs/intermediate/hooks.md @@ -20,43 +20,43 @@ const hook = { 「钩子族」是同一类钩子方法的集合(一个 `interface`)。常用的几族如下,方法名以源码为准: -| 钩子族 | 所属主对象 | 主要方法 | -| --- | --- | --- | -| `IDataCommonHooks` | 数据端公共对象 | `onTip` | -| `IHeroAttributeHooks` | 勇士属性 | `onUpdateAttribute` | -| `IHeroLocationHooks` | 勇士位置 | `onSetPos`、`onSetFloor` | -| `IHeroStateHooks` | 勇士状态 | `onBeforeChangeFloor`、`onAfterChangeFloor` | -| `IEquipmentStateHooks` | 装备 | `onChangeModifier` | -| `IHeroFollowersControllerHooks` | 勇士跟随者 | `onAddFollower`、`onRemoveFollower`、`onGatherFollowers` | -| `IObjectMoverHooks` | 移动器 | `onMoveStart`、`onMoveEnd`、`onStepStart`、`onStepEnd`、`onSetPos`、`onSetFaceDir`、`onSetMoveDir` | -| `ICombatFlowHooks` | 战斗流程 | `onBeforeCombat`、`onAfterCombat` | -| `IGameEventExecutorHooks` | 事件执行器 | `onBeforeExecuteEvent`、`onAfterExecuteEvent` | -| `IPathfindingSystemHooks` | 寻路系统 | `onBeforeTeleportTo`、`onAfterTeleportTo` | -| `IMapLayerHooks` | 地图图层 | `onResize`、`onUpdateArea`、`onUpdateBlock`、`onOpenDoor`、`onCloseDoor`、`onCreateDynamic`、`onDeleteDynamic`、`onUpdateDynamicPosition` | -| `IGameMapHooks` | 地图 | `onChangeBackground`、`onUpdateLayer`、`onResizeLayer` | -| `IReplaySystemHooks` | 录像系统 | `onCreateSandbox`、`onRecordCommand` | -| `IReplaySandboxHooks` | 录像沙盒 | `onStep`、`onSpeedSet`、`onStartReplay`、`onStopReplay`、`onPauseReplay`、`onResumeReplay` | +| 钩子族 | 所属主对象 | 主要方法 | +| ------------------------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | +| `IDataCommonHooks` | 数据端公共对象 | `onTip` | +| `IHeroAttributeHooks` | 勇士属性 | `onUpdateAttribute` | +| `IHeroLocationHooks` | 勇士位置 | `onSetPos`、`onSetFloor` | +| `IHeroStateHooks` | 勇士状态 | `onBeforeChangeFloor`、`onAfterChangeFloor` | +| `IEquipmentStateHooks` | 装备 | `onChangeModifier` | +| `IHeroFollowersControllerHooks` | 勇士跟随者 | `onAddFollower`、`onRemoveFollower`、`onGatherFollowers` | +| `IObjectMoverHooks` | 移动器 | `onMoveStart`、`onMoveEnd`、`onStepStart`、`onStepEnd`、`onSetPos`、`onSetFaceDir`、`onSetMoveDir` | +| `ICombatFlowHooks` | 战斗流程 | `onBeforeCombat`、`onAfterCombat` | +| `IGameEventExecutorHooks` | 事件执行器 | `onBeforeExecuteEvent`、`onAfterExecuteEvent` | +| `IPathfindingSystemHooks` | 寻路系统 | `onBeforeTeleportTo`、`onAfterTeleportTo` | +| `IMapLayerHooks` | 地图图层 | `onResize`、`onUpdateArea`、`onUpdateBlock`、`onOpenDoor`、`onCloseDoor`、`onCreateDynamic`、`onDeleteDynamic`、`onUpdateDynamicPosition` | +| `IGameMapHooks` | 地图 | `onChangeBackground`、`onUpdateLayer`、`onResizeLayer` | +| `IReplaySystemHooks` | 录像系统 | `onCreateSandbox`、`onRecordCommand` | +| `IReplaySandboxHooks` | 录像沙盒 | `onStep`、`onSpeedSet`、`onStartReplay`、`onStopReplay`、`onPauseReplay`、`onResumeReplay` | ## 需求 → 钩子对照表 真要动手时,多半是先有一个需求、再去找它对应哪个钩子。下表把常见需求和对应的钩子方法列在一起,照着找即可: -| 需求 | 对应钩子 | -| --- | --- | -| 勇士属性变化时做点事 | `IHeroAttributeHooks.onUpdateAttribute` | -| 勇士被设置坐标或切换楼层 | `IHeroLocationHooks.onSetPos` / `onSetFloor` | +| 需求 | 对应钩子 | +| ---------------------------- | --------------------------------------------------------------------------- | +| 勇士属性变化时做点事 | `IHeroAttributeHooks.onUpdateAttribute` | +| 勇士被设置坐标或切换楼层 | `IHeroLocationHooks.onSetPos` / `onSetFloor` | | 勇士移动开始、结束或每走一步 | `IObjectMoverHooks.onMoveStart` / `onMoveEnd` / `onStepStart` / `onStepEnd` | -| 切换楼层前后做过渡处理 | `IHeroStateHooks.onBeforeChangeFloor` / `onAfterChangeFloor` | -| 战斗前或战斗后介入 | `ICombatFlowHooks.onBeforeCombat` / `onAfterCombat` | -| 事件执行前后介入 | `IGameEventExecutorHooks.onBeforeExecuteEvent` / `onAfterExecuteEvent` | -| 地图图块被修改、区域被更新 | `IMapLayerHooks.onUpdateBlock` / `onUpdateArea` | -| 开门或关门时做点什么 | `IMapLayerHooks.onOpenDoor` / `onCloseDoor` | -| 动态图块被创建或删除 | `IMapLayerHooks.onCreateDynamic` / `onDeleteDynamic` | -| 装备的修饰器发生变化 | `IEquipmentStateHooks.onChangeModifier` | -| 瞬移寻路前后介入 | `IPathfindingSystemHooks.onBeforeTeleportTo` / `onAfterTeleportTo` | -| 录像播放到某一步 | `IReplaySandboxHooks.onStep` | -| 录像记录新指令 | `IReplaySystemHooks.onRecordCommand` | -| 通知渲染端进行一次提示 | `IDataCommonHooks.onTip` | +| 切换楼层前后做过渡处理 | `IHeroStateHooks.onBeforeChangeFloor` / `onAfterChangeFloor` | +| 战斗前或战斗后介入 | `ICombatFlowHooks.onBeforeCombat` / `onAfterCombat` | +| 事件执行前后介入 | `IGameEventExecutorHooks.onBeforeExecuteEvent` / `onAfterExecuteEvent` | +| 地图图块被修改、区域被更新 | `IMapLayerHooks.onUpdateBlock` / `onUpdateArea` | +| 开门或关门时做点什么 | `IMapLayerHooks.onOpenDoor` / `onCloseDoor` | +| 动态图块被创建或删除 | `IMapLayerHooks.onCreateDynamic` / `onDeleteDynamic` | +| 装备的修饰器发生变化 | `IEquipmentStateHooks.onChangeModifier` | +| 瞬移寻路前后介入 | `IPathfindingSystemHooks.onBeforeTeleportTo` / `onAfterTeleportTo` | +| 录像播放到某一步 | `IReplaySandboxHooks.onStep` | +| 录像记录新指令 | `IReplaySystemHooks.onRecordCommand` | +| 通知渲染端进行一次提示 | `IDataCommonHooks.onTip` | 注意区分「切换楼层」相关的两族钩子,它们挂在不同的主对象上:`onSetFloor` 属于 `IHeroLocationHooks`,挂在 `state.hero.location` 上;`onBeforeChangeFloor` / `onAfterChangeFloor` 属于 `IHeroStateHooks`,挂在 `state.hero` 上。 diff --git a/docs/intermediate/src-tour.md b/docs/intermediate/src-tour.md index 106e109..37d676a 100644 --- a/docs/intermediate/src-tour.md +++ b/docs/intermediate/src-tour.md @@ -63,15 +63,15 @@ 把上面几节收成一张表,动手前对照一下: -| 路径 | 用途 | 是否通常需要改动 | -| --- | --- | --- | -| `src/data/` | 数据端逻辑与结果 | 是,本教程重点 | -| `src/client/` | 渲染端画面与交互 | 视需求,交互类需求会改 | -| `src/content/` | 游戏内容数据 | 是,配置与内容 | -| `src/constant.ts` | 底层核心常量 | 否,一般不动 | -| `src/data.ts` | 数据端入口 | 否,一般不动 | -| `src/bootstrap.ts` | 启动入口 | 否,一般不动 | -| `src/package.json` | 入口包依赖声明 | 否,一般不动 | -| `src/styles.less` | 全局样式 | 否,一般不动 | +| 路径 | 用途 | 是否通常需要改动 | +| ------------------ | ---------------- | ---------------------- | +| `src/data/` | 数据端逻辑与结果 | 是,本教程重点 | +| `src/client/` | 渲染端画面与交互 | 视需求,交互类需求会改 | +| `src/content/` | 游戏内容数据 | 是,配置与内容 | +| `src/constant.ts` | 底层核心常量 | 否,一般不动 | +| `src/data.ts` | 数据端入口 | 否,一般不动 | +| `src/bootstrap.ts` | 启动入口 | 否,一般不动 | +| `src/package.json` | 入口包依赖声明 | 否,一般不动 | +| `src/styles.less` | 全局样式 | 否,一般不动 | 想先补齐读写这些文件所需的语法与类型知识,见[代码基础](./code-basics.md)。