mirror of
https://github.com/motajs/template.git
synced 2026-10-21 23:00:29 +08:00
docs(10-03): write data-state-overview, hero-attribute, hero-items
- 数据端总览:state 入口、常用对象表与 L0-L3 分层标注 - 勇士属性:基础/最终属性、修饰器、save 语义、只读与试算 - 勇士道具:四种类别区分与 addItem/useItem/iterateItems 等接口
This commit is contained in:
parent
0348c30893
commit
627a40bc4b
64
docs/intermediate/data-state-overview.md
Normal file
64
docs/intermediate/data-state-overview.md
Normal file
@ -0,0 +1,64 @@
|
||||
# 数据端总览
|
||||
|
||||
数据端的一切都从主对象 `state` 开始。本篇列出作者最常需要的对象与接口,并说明如何从 `state` 拿到它们,作为中级教程其余篇章的查表入口。
|
||||
|
||||
## state:一切入口
|
||||
|
||||
`state` 是数据端的主对象(类型为 `ICoreState`),地图、勇士、怪物、战斗、Flag 等全部挂在它下面。在数据端代码里,它通常由框架传入——例如道具效果拿到 `(item, state)`、插件拿到 `state`;你也可以从任一数据端对象向外取得它。
|
||||
|
||||
```ts
|
||||
// 从 state 出发访问勇士、地图与 Flag
|
||||
const hp = state.hero.attribute.getFinalAttribute('hp');
|
||||
const floorId = state.hero.location.floorId;
|
||||
const cleared = state.flags.getFieldValue('cleared');
|
||||
```
|
||||
|
||||
## 常用对象与获取方式
|
||||
|
||||
下表把最常用的对象与接口列在一起:
|
||||
|
||||
| 对象 | 获取方式 | 用途 | 分层 |
|
||||
| --- | --- | --- | --- |
|
||||
| `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');
|
||||
state.emitTip('获得黄钥匙');
|
||||
```
|
||||
|
||||
## 分层标注(L0–L3)
|
||||
|
||||
上表的「分层」列标注了对象所属的模块层级:L0 公共层、L1 数据层、L2 系统层、L3 顶层。分层的意义在于区分「哪些内容会进存档」「哪些内容负责产生动作」,但**不影响你如何使用它们**——所有对象都能从 `state` 直接访问,调用方式完全一致。
|
||||
|
||||
```ts
|
||||
// 无论哪个分层,访问方式都相同
|
||||
state.flags.setFieldValue('door-open', true); // L1
|
||||
const map = state.maps.getActiveMap('floor-1'); // L1
|
||||
state.emitTip('获得黄钥匙'); // L0
|
||||
```
|
||||
|
||||
## 从这里继续
|
||||
|
||||
- 勇士的数值与加成:见[勇士属性](./hero-attribute.md);
|
||||
- 勇士的道具与装备:见[勇士道具](./hero-items.md);
|
||||
- 地图的层次结构:见[地图结构](./map-structure.md);
|
||||
- 全局可存档变量:见[Flag 变量](./flags.md);
|
||||
- 在关键动作上挂接处理:见[钩子](./hooks.md)。
|
||||
95
docs/intermediate/hero-attribute.md
Normal file
95
docs/intermediate/hero-attribute.md
Normal file
@ -0,0 +1,95 @@
|
||||
# 勇士属性
|
||||
|
||||
勇士属性决定战斗数值的最终结果。本篇讲解如何读取基础与最终属性、如何修改基础属性,以及如何用修饰器施加临时或永久的加成。访问勇士属性的入口见[数据端总览](./data-state-overview.md)。
|
||||
|
||||
## 基础属性与最终属性
|
||||
|
||||
勇士属性(`state.hero.attribute`)区分**基础值**与**最终值**:
|
||||
|
||||
- `getBaseAttribute(name)`:基础属性,即未经任何 Buff 或装备加成的原始值;
|
||||
- `getFinalAttribute(name)`:最终属性,即基础值经所有修饰器加成后的结果。
|
||||
|
||||
```ts
|
||||
const base = state.hero.attribute.getBaseAttribute('atk');
|
||||
const finalAtk = state.hero.attribute.getFinalAttribute('atk');
|
||||
```
|
||||
|
||||
属性名与勇士属性接口 `IHeroAttr` 的字段一致,常用的有 `hp`、`hpmax`、`atk`、`def`、`mdef`、`money`、`exp` 等。
|
||||
|
||||
## 修改基础属性
|
||||
|
||||
要修改勇士的基础属性,先取到可修改对象 `getModifiableAttribute()`,再调用:
|
||||
|
||||
- `set(name, value)`:直接设置;
|
||||
- `add(name, value)`:增减;
|
||||
- `mul(name, value)`:乘以某个数;
|
||||
- `div(name, value)`:除以某个数。
|
||||
|
||||
```ts
|
||||
const attr = state.hero.getModifiableAttribute();
|
||||
attr.add('atk', 10); // 攻击 +10
|
||||
attr.set('hp', 1000); // 生命值设为 1000
|
||||
attr.mul('money', 2); // 金币翻倍
|
||||
```
|
||||
|
||||
只读访问(只想读取、不加修改)可用 `state.hero.attribute`;需要修改时统一走 `getModifiableAttribute()`。
|
||||
|
||||
## 修饰器:临时的加减与百分比
|
||||
|
||||
直接改基础属性会永久改变勇士数值。如果只想施加一段**临时**的加成,应使用**修饰器**。属性包内置了两种:
|
||||
|
||||
- `ValueModifier`(type `@system/value`):数值加减,最终值 = 原值 + 修饰值;
|
||||
- `PercentageModifier`(type `@system/percentage`):按**基础值**计算百分比,最终值 = 原值 + 基础值 × 修饰值。
|
||||
|
||||
用 `addModifier(name, modifier, save?)` 挂上修饰器,用 `deleteModifier(name, modifier)` 移除:
|
||||
|
||||
```ts
|
||||
import { ValueModifier, PercentageModifier } from '@user/data-base';
|
||||
|
||||
const attr = state.hero.getModifiableAttribute();
|
||||
|
||||
// 攻击永久 +5:加一个数值修饰器
|
||||
attr.addModifier('atk', new ValueModifier(5));
|
||||
|
||||
// 防御临时 -30%:按基础防御算的百分比修饰器
|
||||
const defDown = new PercentageModifier(-0.3);
|
||||
attr.addModifier('def', defDown);
|
||||
|
||||
// 需要移除时,传回同一个修饰器对象
|
||||
attr.deleteModifier('def', defDown);
|
||||
```
|
||||
|
||||
`PercentageModifier` 的百分比以**基础值**为基数,而非当前最终值,因此多个百分比修饰器不会彼此叠乘。装备产生的加成走的也是同一套修饰器机制,见[勇士装备](./hero-equipment.md)。
|
||||
|
||||
## save 参数与读档一致性
|
||||
|
||||
`addModifier(name, modifier, save?)` 的 `save` 参数默认为 `true`,表示该修饰器会进入存档、读档后自动恢复;传 `false` 则表示**不进入存档**。
|
||||
|
||||
:::warning
|
||||
当修饰器不进入存档时,读档后它不会自动恢复。此时应由负责分配该修饰器的**外部系统**在读档后重新分配,否则会出现「存档前有加成、读档后消失」的不一致。仅在加成完全由外部系统掌控时才使用 `save: false`。
|
||||
:::
|
||||
|
||||
## 只读与试算
|
||||
|
||||
- `getAttribute()`:取只读属性对象,只能读、不能改;
|
||||
- `getIsolatedAttribute()`:取一份**独立的**属性副本,修改它不会影响勇士本身,适合在不改动实际数值的前提下试算某个效果。
|
||||
|
||||
```ts
|
||||
// 试算:把攻击 +999 后最终攻击会是多少
|
||||
const trial = state.hero.getIsolatedAttribute();
|
||||
trial.add('atk', 999);
|
||||
const preview = trial.getFinalAttribute('atk');
|
||||
```
|
||||
|
||||
## 示例
|
||||
|
||||
```ts
|
||||
// 攻击 +15 永久:直接改基础属性
|
||||
state.hero.getModifiableAttribute().add('atk', 15);
|
||||
|
||||
// 防御 -20% 临时:挂一个百分比修饰器,战斗结束后再删除
|
||||
const weaken = new PercentageModifier(-0.2);
|
||||
state.hero.getModifiableAttribute().addModifier('def', weaken);
|
||||
```
|
||||
|
||||
想在属性变化时收到通知,可以用属性钩子族的 `onUpdateAttribute`,见[钩子](./hooks.md)。
|
||||
65
docs/intermediate/hero-items.md
Normal file
65
docs/intermediate/hero-items.md
Normal file
@ -0,0 +1,65 @@
|
||||
# 勇士道具
|
||||
|
||||
勇士道具(`state.hero.items`)负责管理勇士拥有的除装备外的所有道具,并提供增加、查询、使用等接口。装备虽然也是道具,但归独立的装备系统,见[勇士装备](./hero-equipment.md)。
|
||||
|
||||
## 四种类别
|
||||
|
||||
道具的类别由 `ItemCategory` 定义,决定它被拾取或使用时的行为:
|
||||
|
||||
| 类别 | 含义 |
|
||||
| --- | --- |
|
||||
| `Constant` | 永久道具,使用后不消耗 |
|
||||
| `Consumable` | 一次性道具,使用后消耗一个 |
|
||||
| `Pick` | 即捡即用道具,拾取时立刻生效 |
|
||||
| `Equipment` | 装备类道具,走装备系统 |
|
||||
|
||||
`Unknown` 表示尚未归类。`Pick` 道具不会进入背包:`addItem` 到 `Pick` 道具时会直接触发它的效果。
|
||||
|
||||
## 常用接口
|
||||
|
||||
- `addItem(item, count?)`:增加道具数量,`count` 可以填负数以扣除道具,默认为 1;对 `Pick` 道具会立刻执行其效果。
|
||||
- `getItemState(item)`:获取指定道具的状态,不存在返回 `null`。
|
||||
- `iterateItems()`:迭代勇士拥有的所有道具。
|
||||
- `useItem(item)`:使用道具,**仅对 `Constant` 与 `Consumable` 生效**,`Consumable` 使用后数量减一。
|
||||
- `itemCount(item)`:获取指定道具的持有数量。
|
||||
|
||||
`item` 参数可以传道具的图块数字或字符串 id。
|
||||
|
||||
```ts
|
||||
// 发一把黄钥匙(+1)
|
||||
state.hero.items.addItem('yellow-key');
|
||||
|
||||
// 扣减道具(数量传负数)
|
||||
state.hero.items.addItem('yellow-key', -2);
|
||||
|
||||
// 使用道具
|
||||
state.hero.items.useItem('yellow-key');
|
||||
|
||||
// 查询数量
|
||||
const count = state.hero.items.itemCount('yellow-key');
|
||||
```
|
||||
|
||||
## 迭代背包
|
||||
|
||||
```ts
|
||||
for (const [num, item] of state.hero.items.iterateItems()) {
|
||||
// num 为道具图块数字,item 为道具状态
|
||||
state.emitTip(`${item.id}: ${item.count}`);
|
||||
}
|
||||
```
|
||||
|
||||
## 道具效果属内容层
|
||||
|
||||
道具的**使用效果本身**写在内容层的 `src/content/item.ts`,通过 `IItemEffect` 描述:`useEffect` 在 `Pick` 拾取或 `Constant`/`Consumable` 使用时触发,`canUse` 决定能否使用,`useEvent` 关联使用事件。道具效果可以调用 `state`(数据端主对象)与道具数据,因而能修改勇士属性、设置 Flag、发送提示等。
|
||||
|
||||
```ts
|
||||
// src/content/item.ts(内容层)
|
||||
export const item200: ItemEffect = {
|
||||
useEffect(item, state) {
|
||||
state.hero.getModifiableAttribute().add('atk', 5); // [!code ++]
|
||||
state.emitTip('攻击力提升!'); // [!code ++]
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
想了解从 `state` 能取到哪些对象,见[数据端总览](./data-state-overview.md)。
|
||||
Loading…
Reference in New Issue
Block a user