Files
EVEngine/docs/usr/modules/effects.md
T

81 lines
4.1 KiB
Markdown

# 通用效果模块
**脚本入口:** `eve.Effects()`
Effects 按 `subject` 保存临时或永久效果。效果具有类型、来源、优先级、持续时间、
强度、堆叠键、标签和 JSON 载荷;容器还保留 applied/refreshed/removed/expired
事件,适合状态效果、政策修正和临时增益。容器由模块拥有,脚本拿到的是带世代的
句柄,不要跨模块重载保存内部 `Effect`、`EffectEvent` 或 `EffectPayload` 引用。
## 创建容器并施加效果
```squirrel
local effectsResult = eve.Effects().newContainer();
if (!effectsResult.ok) throw effectsResult.status.summary;
local effects = effectsResult.value;
local idResult = effects.apply("hero:1", "buff.speed", "potion:7",
10, 8.0, "speed-buff", "refresh");
if (!idResult.ok) throw idResult.status.summary;
local effect = effects.find(idResult.value);
effect.addTag("positive");
effect.getPayload().setNumber("multiplier", 1.25);
```
`apply(subject, type, source, priority, duration, stackKey, policy)` 返回 Result。
`policy` 的可用值和堆叠行为由定义/运行时策略决定;不要把失败当作空 ID。
`applyCanonical(...)` 用已注册的效果定义创建效果。每帧调用 `update(dt)` 推进剩余
时间;消费完事件后调用 `clearEvents()`,否则事件会继续保留。
## 查询主体和标签
```squirrel
effects.update(dt);
for (local i = 0; i < effects.subjectCount("hero:1"); ++i) {
local e = effects.subjectAt("hero:1", i);
print(e.getType() + " remaining=" + e.getRemaining() + "\n");
}
for (local i = 0; i < effects.taggedCount("positive"); ++i)
print(effects.taggedAt("positive", i).getId() + "\n");
```
查询返回借用引用:容器发生 `apply`、`remove`、`clear`、`update` 或释放后重新查询,
不要长期缓存。`release()` 会主动释放容器;`isStale()` 可检查句柄是否已经失效。
## API 快查
### `Effects` 与拥有型容器
| API | 说明 |
|---|---|
| `getName()` | 返回模块名。 |
| `newContainer()` | 返回 `{ ok, value, status }`,其中 value 是模块拥有的容器。 |
| `ownership()` / `handle()` / `isStale()` / `release()` | 查询所有权和句柄、检测失效或提前释放。 |
| `apply(...)` / `applyCanonical(...)` | 施加临时效果或按 canonical 定义施加效果,返回 Result。 |
| `remove(id, reason)` / `clear()` / `update(dt)` | 删除、清空或推进效果时间。 |
| `find(id)` / `effectCount()` / `effectAt(i)` | 按 ID 或稳定的当前索引查询效果。 |
| `subjectCount(subject)` / `subjectAt(subject, i)` | 查询某主体的效果。 |
| `taggedCount(tag)` / `taggedAt(tag, i)` | 查询带指定标签的效果。 |
| `eventCount()` / `eventAt(i)` / `clearEvents()` | 读取并清空变更事件。 |
### `Effect`、载荷与事件
| API | 说明 |
|---|---|
| `getId()` / `getSubject()` / `getType()` / `getSource()` | 效果身份和来源。 |
| `getStackKey()` / `getPriority()` / `getDuration()` / `getRemaining()` | 堆叠和时间信息。 |
| `getMagnitude()` / `getStackCount()` / `getPayload()` | 强度、层数和结构化载荷。 |
| `addTag(tag)` / `removeTag(tag)` / `hasTag(tag)` | 修改或测试标签,修改操作返回 Result。 |
| `tagCount()` / `tagAt(i)` | 枚举标签。 |
| `setString()` / `setNumber()` / `setBool()` / `setNull()` | 设置载荷字段。 |
| `setJson()` / `getJson()` / `toJson()` | 写入规范 JSON、读取单字段或序列化整个载荷。 |
| `has()` / `erase()` / `clear()` | 测试、删除或清空载荷字段。 |
| `getSequence()` / `getKind()` / `getEffectId()` / `getReason()` | 事件序号、类型、效果 ID 和原因。事件也提供 `getSubject()`、`getType()`、`getSource()`。 |
## 生命周期与确定性
- 容器是 `owned` 对象;模块卸载、显式 `release()` 或世代变化后句柄 stale。
- `update(dt)` 的 `dt` 由游戏传入,回放时必须使用相同的模拟步长。
- 遍历事件或效果时不要在循环中结构性修改容器;先记录 ID,再统一修改。
- Payload 接受 JSON 值而不是任意 Squirrel 对象;持久化时保存 canonical JSON。