14 KiB
地图回合实现进度(台账)
本文档记录代码已落地内容与待接线任务,便于在对话上下文变长时单独查阅。规则、伪代码与冻结优先级以 map-turn-spec.md 为唯一口径;本文不写新规则,只写状态与文件指针。patch / rebuild / performEnemyAction 等与实现对齐的契约说明见规范 §6.2、§6.3、§6.7。
1. 已完成(截至当前仓库)
1.1 数据表(timeCost 默认 null)
| 区域 | 说明 |
|---|---|
| project/items.js | 每条道具在 "cls" 下一行含 "timeCost": null;需消耗地图时间时改为正整数。样例(已接):bigKey(tools)timeCost: 3,见 §1.3。 |
| project/enemys.js | 每条怪物在 point 与 special 之间含 "timeCost": null。 |
enemy48 |
与 enemys 共用 core.material.enemys 数值,无独立 libs/enemys48.js 数据表。 |
1.2 引擎初始化缺省补全
| 文件 | 行为 |
|---|---|
libs/items.js items.prototype._init |
若道具 timeCost === undefined,补 timeCost: null(含编辑器新注册道具漏字段)。 |
libs/enemys.js enemys.prototype._init |
若怪物 timeCost === undefined,补 timeCost: null。 |
1.3 使用道具推进地图时间
| 文件 | 行为 |
|---|---|
libs/items.js items.prototype.useItem |
在 _useItemEffect(含 eval useItemEffect、并入队 useItemEvent)之后立即结算:若 typeof timeCost === "number" 且 > 0,且存在 core.plugin.mapTurn.consumeTime,则 consumeTime(_tc, "item:" + itemId)(如 item:bigKey → 3 tick)。例外:cls 为 skillbattle / skillupdate,或 mapTurnSkillRole 为 battle / update 时不走本条即时扣时(与规范 §3.1 对齐;工程上可用 cls:"tools" + mapTurnSkillRole 代替未注册的 skill cls),地图时间语义见 §1.4 / map-turn-spec.md §3.1。null 或非正数不推进;与异步开门动画无关(规范 §4 tools)。总开关关则 consumeTime 内早退。 |
1.4 插件:core.plugin.mapTurn
| 文件 | 说明 |
|---|---|
project/plugins.js 插件键 "mapTurn" |
挂载 this.mapTurn = { ... },对外即 core.plugin.mapTurn.*。 |
已实现的 API(名称与 map-turn-spec.md §3.4 / §6 对齐):
isEnabled/setEnabled(v):总开关读写flags.mapTurnEnabled(随存档);为真时consumeTime/advanceMapTurnOne才会推进状态。setEnabled(true)或bootstrapPersistedState()在开关为真时会补齐mapTurnState/skillState缺省结构。consumeTime(deltaTime, reason):clock += floor(delta),再循环deltaTime次advanceMapTurnOne(§2.1)。advanceMapTurnOne(reason):mapTurn += 1,调用resolveEnemyActionsForSingleTick。resolveEnemyActionsForSingleTick(reason):已按 §6.2 遍历activeEnemiesByFloor[currentFloor],维护enemyActionGauge[floorId][runtimeId],达阈调用performEnemyAction;本函数路径内不调用extractBlocks。performEnemyAction(enemyRef, def, floorId, reason):已挂载;特殊 29【庇护】(测试):hasSpecial(..., 29)时本层所有怪enemyOnPoint.hp += 1,不经改图块;否则初版actType === idle无操作;chase/patrol/skill占位(同步改图块会经引擎removeBlock触发全表扫描,故不在此 tick 内实现)。rebuildActiveEnemies(floorId):对该层extractBlocks一次 后遍历map.blocks,收录cls以enemy开头 且enemys[id].timeCost为正数 的实例(runtimeId/x/y/enemyId/def),写回activeEnemiesByFloor[floorId],activeEnemiesVersion++,并修剪enemyActionGauge[floorId]。换层由 project/plugins.js 对afterChangeFloor的包装调用。patchActiveEnemiesForBlockChange(floorId, hint):hint.op为removeCell/syncCell/migratePoint/rebuild(默认全量rebuildActiveEnemies)。已在maps.removeBlock/setBlock/hideBlock/showBlock/removeBlockByIndexes与events.moveEnemyOnPoint挂钩;moveBlock/jumpBlock用深度计数抑制中途removeBlock/setBlock的重复同步,keep===false结束时补removeCell起点格;migratePoint在moveEnemyOnPoint后迁移runtimeId与enemyActionGauge。- 战后成功路径(同文件内 「序章追击」 等对
events.prototype.afterBattle的包装):先调用原afterBattle;若勇士仍存活且存在mapTurn,则consumeTime(settleBattleTimeCost(), "battle"),再applyStatusAfterBattle("success")。 settleBattleTimeCost:返回max(1, M)(§6.4)。M =activeStatusSkills各条battleTimeCost中的最大值,与activeBattleSkillId对应道具在cls === "skillbattle"或mapTurnSkillRole === "battle"时的timeCost取较大(二者仅取一层 max,再与基础 1 取 max)。syncBattleSkillItemState/resyncBattleSkillItemStates:战斗技能道具与flag:skill、activeBattleSkillId对齐(约定skillN型 id);useItem末尾与读档bootstrapPersistedState内resync调用。migrateSkillItemBuckets:读档开头将constants或旧skillbattle/skillremote/skillrecover/skillupdate桶中、但material已改为cls:"tools"且带mapTurnSkillRole的条目迁入tools;仍保留从constants迁往skill*桶的旧逻辑以兼容旧表。applyStatusAfterBattle:§6.5,按remainBattles等扣减activeStatusSkills(战后成功路径已调用)。clearOnDeath:§6.6 清理skillState等逻辑已实现;调用侧仍缺:需在lose/ 战斗失败 出口调用(当前仓库未接,见 §3)。- 道具栏:libs/ui.js
getToolboxItems("tools")与getToolboxPermanentItems(constants+ 四类技能cls)分两行;地图回合技能线若暂用cls:"tools",走 消耗道具行 显示(与bigKey同区)。
1.5 编辑器 / 新素材注册
| 文件 | 说明 |
|---|---|
| _server/table/comment.js | 道具表、怪物表 timeCost 列说明;items_template / enemys_template 含 timeCost: null。道具 cls 可选 skillbattle / skillremote / skillrecover / skillupdate(与 map-turn-spec.md §3.1 一致)。工程临时:未在编辑器注册 skill cls 时,可用 cls:"tools" + mapTurnSkillRole(battle/remote/recover/update)+ mapTurnKeepAfterUse: true(使用后不占消耗、addItem 上限 1),与 libs/items.js useItem / _afterUseItem 对齐。 |
1.6 当前接线口径补充(2026-04)
- 总开关开启时机:已在 project/data.js 的
startText前两条:setValue写入flag:mapTurnEnabled为真,再bootstrapPersistedState()补齐结构。开关存于存档,读档后随存档恢复。 - 首次触发路径约束:新开局统一经过
startText写入总开关;读档后由 project/functions.jsloadData调用bootstrapPersistedState()与存档中的mapTurnEnabled对齐。 - 演出移动与地图回合:事件编辑器「地图处理」中在「无视地形移动勇士」下增加图块 「移动勇者」(JSON
type:moveHeroMapTurn)。运行时由 libs/events.js_action_moveHeroMapTurn将路径拆成每格一次eventMoveHero,每格落点后consumeTime(1, "event:moveHeroMapTurn")(speed:与:0段不扣时)。语法见 _server/MotaAction.g4moveHeroMapTurn_s。 - 分层相对回合约定:
mapTurn以楼层相对值使用;普通切层后当前层回合计数按0起算。读档导致的换层(__fromLoad__为真)不归零,以保持与存档一致。clock可继续作为全局累计观测值。
2. 待完成(接线清单,对齐 map-turn-spec §4 / §6 / §8)
核心调度接线见 §1(含 §1.4、§1.6)。下表 §2 为大块任务勾选;细项与「仍缺」见 §2.1、§3。
-
resolveEnemyActionsForSingleTick:已在 project/plugins.jsmapTurn中实现 §2 该条所列 1–4 步(含performEnemyAction,idle已实现,其余actType占位)。 -
rebuildActiveEnemies:已在mapTurn.rebuildActiveEnemies实现 §2 该条 1–4 步;afterChangeFloor中已调用rebuildActiveEnemies(core.status.floorId || floorId)。 -
patchActiveEnemiesForBlockChange:已在mapTurn.patchActiveEnemiesForBlockChange实现removeCell/syncCell/migratePoint/rebuild;project/plugins.js 在mapTurn插件末尾对core.maps/core.events安装挂钩(含moveBlock/jumpBlock与keep===false补清)。
2.1 后续扩展接线备忘
对应 map-turn-spec.md 中已有字段或流程的操作指向;已接与仍缺分列如下。
已接(当前仓库)
- 战斗技能(
skillbattle或mapTurnSkillRole:"battle"):样例skill1(project/items.js,当前cls:"tools"+mapTurnSkillRole:"battle"+mapTurnKeepAfterUse,timeCost: 3,idskill1↔flag:skill === 1);libs/items.jsuseItem对battle/update角色跳过即时consumeTime;战后settleBattleTimeCost、syncBattleSkillItemState/resyncBattleSkillItemStates、migrateSkillItemBuckets(§1.4);道具栏走tools行(§1.4)。 bigKey:tools+timeCost: 3,§1.3 即时consumeTime(已验证)。
仍待扩展
skillremote/skillrecover/skillupdate(规范 cls):编辑器注册与activeStatusSkills战后路径仍可按规范扩展;仓库内示例I347/I348/I350已用tools+mapTurnSkillRole实现拾取/使用时轴与道具栏(I350仍为mapTestAtkLayers+ tick 衰减,非activeStatusSkills)。contactBattleOnly与多怪捕捉:在战斗触发逻辑(如beforeBattle或等价入口)读取怪物字段分支;多怪连续战斗时每场成功需调用applyStatusAfterBattle("success")(普通单场已接,见 §1.4 战后路径)。actType/actArgs:在performEnemyAction(或由resolveEnemyActionsForSingleTick内联)按怪物表字段分支执行移动/技能等行为(chase/patrol/skill等仍占位,§1.4)。
3. 验收清单映射(对应 map-turn-spec §10)
| §10 条目 | 依赖 / 当前状态(台账口径) |
|---|---|
状态技能不立即推进时间;战后层数 -1 |
applyStatusAfterBattle 已在单场战后成功路径调用(§1.4)。规范路径仍缺:cls:"skillupdate" 写入 activeStatusSkills(含 remainBattles / battleTimeCost)的配置与开关脚本。I350 为测试向 mapTestAtkLayers + tick 衰减,不覆盖 activeStatusSkills 验收。 |
| 远程/恢复立即推进;怪物按时间响应 | useItem 对 remote/recover 角色(或规范 skillremote/skillrecover)与普通 tools 一样按正数 timeCost consumeTime(§1.3)。示例 I347/I348(§2.1)。敌调度:resolveEnemyActionsForSingleTick + activeEnemies 已实装(§1.4)。 |
战斗耗时 max |
afterBattle 成功路径已 consumeTime(settleBattleTimeCost(), "battle")(§1.4);含 skill1(battle 角色)与 activeStatusSkills。回归:全场战斗均走该 afterBattle 包装即可确认。 |
| 多怪捕捉逐场扣层 | 单场 afterBattle 已链 applyStatusAfterBattle。仍缺:多怪连战的 afterBattle 触发次数 / 事件链是否每场独立成功分支(见 §2.1)。 |
Boss contactBattleOnly |
仍缺:战斗触发层读取 contactBattleOnly 与单场结算分支(§2.1)。 |
| 死亡清理 | clearOnDeath 已实现;仍缺:在 events.lose 或等价失败出口调用(§1.4)。 |
| 存档读档连续 | flags.mapTurnState / skillState 等随档;读档后 bootstrapPersistedState + afterChangeFloor 侧 rebuildActiveEnemies(§1.6)。 |
timeCost=0 不参与调度 |
rebuildActiveEnemies 仅收录 timeCost > 0;resolveEnemyActionsForSingleTick 只扫缓存列表(§1.4)。 |
consumeTime(3) 恰好 3 tick |
consumeTime 内循环 advanceMapTurnOne 已实现;建议:对 bigKey 或脚本 consumeTime(3) 做日志/计数断言回归(§1.3)。 |
activeEnemies 路径无每 tick 全图扫描 |
resolveEnemyActionsForSingleTick 不 extractBlocks;地图变更走 patch/rebuild(§1.4)。例外:庇护 29 每次行动 extractBlocks 一次(测试专用,§1.4)。 |
4. 相关路径速查
| 用途 | 路径 |
|---|---|
| 规范全文 | docs/map-turn-spec.md |
| 样板 API | _docs/api.md |
| 地图回合插件 | project/plugins.js 搜索 "mapTurn" |