Merge branch 'main' of https://gitea.mota.press/click/if
This commit is contained in:
parent
728c4af327
commit
32fcdef57b
File diff suppressed because one or more lines are too long
@ -26,11 +26,15 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
|
|||||||
"items",
|
"items",
|
||||||
"constants",
|
"constants",
|
||||||
"tools",
|
"tools",
|
||||||
"equips"
|
"equips",
|
||||||
|
"skillbattle",
|
||||||
|
"skillremote",
|
||||||
|
"skillrecover",
|
||||||
|
"skillupdate"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"_docs": "道具类别",
|
"_docs": "道具类别",
|
||||||
"_data": "items(宝石、血瓶) constants(永久物品) tools(消耗道具) equips(装备)"
|
"_data": "items(宝石、血瓶) constants(永久物品) tools(消耗道具) equips(装备);skillbattle/skillremote/skillrecover/skillupdate 为地图回合技能四类 cls,见 docs/map-turn-spec.md §3.1"
|
||||||
},
|
},
|
||||||
"name": {
|
"name": {
|
||||||
"_leaf": true,
|
"_leaf": true,
|
||||||
@ -90,7 +94,7 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
|
|||||||
"_string": true,
|
"_string": true,
|
||||||
"_lint": true,
|
"_lint": true,
|
||||||
"_docs": "使用效果",
|
"_docs": "使用效果",
|
||||||
"_data": "道具效果,仅对cls为tools或constants有效。"
|
"_data": "道具效果,对 cls 为 tools、constants 或技能四类(skillbattle 等)有效。"
|
||||||
},
|
},
|
||||||
"canUseItemEffect": {
|
"canUseItemEffect": {
|
||||||
"_leaf": true,
|
"_leaf": true,
|
||||||
@ -225,7 +229,7 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
|
|||||||
"_leaf": true,
|
"_leaf": true,
|
||||||
"_type": "textarea",
|
"_type": "textarea",
|
||||||
"_docs": "特殊属性数值",
|
"_docs": "特殊属性数值",
|
||||||
"_data": "特殊属性的数值\n如:领域/阻激/激光怪的伤害值;光环怪增加生命的比例"
|
"_data": "特殊属性的数值(与「特殊属性」勾选配套)"
|
||||||
},
|
},
|
||||||
"zone": {
|
"zone": {
|
||||||
"_leaf": true,
|
"_leaf": true,
|
||||||
@ -233,35 +237,18 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
|
|||||||
"_docs": "领域伤害",
|
"_docs": "领域伤害",
|
||||||
"_data": "领域怪的伤害值"
|
"_data": "领域怪的伤害值"
|
||||||
},
|
},
|
||||||
"repulse": {
|
"range": {
|
||||||
"_leaf": true,
|
"_leaf": true,
|
||||||
"_type": "textarea",
|
"_type": "textarea",
|
||||||
"_docs": "阻击伤害",
|
"_range": "(thiseval==~~thiseval && thiseval>0)||thiseval==null",
|
||||||
"_data": "阻击怪的伤害值"
|
"_docs": "领域范围",
|
||||||
|
"_data": "领域的范围;不加默认为1"
|
||||||
},
|
},
|
||||||
"laser": {
|
"zoneSquare": {
|
||||||
"_leaf": true,
|
"_leaf": true,
|
||||||
"_type": "textarea",
|
"_type": "checkbox",
|
||||||
"_docs": "激光伤害",
|
"_docs": "九宫格",
|
||||||
"_data": "激光怪的伤害值"
|
"_data": "领域怪是否九宫格伤害(与领域范围配合)"
|
||||||
},
|
|
||||||
"breakArmor": {
|
|
||||||
"_leaf": true,
|
|
||||||
"_type": "textarea",
|
|
||||||
"_docs": "破甲比例",
|
|
||||||
"_data": "破甲百分比"
|
|
||||||
},
|
|
||||||
"counterAttack": {
|
|
||||||
"_leaf": true,
|
|
||||||
"_type": "textarea",
|
|
||||||
"_docs": "反击比例",
|
|
||||||
"_data": "反击百分比"
|
|
||||||
},
|
|
||||||
"vampire": {
|
|
||||||
"_leaf": true,
|
|
||||||
"_type": "textarea",
|
|
||||||
"_docs": "吸血比例",
|
|
||||||
"_data": "吸血怪的吸血百分比"
|
|
||||||
},
|
},
|
||||||
"hpBuff": {
|
"hpBuff": {
|
||||||
"_leaf": true,
|
"_leaf": true,
|
||||||
@ -281,25 +268,6 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
|
|||||||
"_docs": "光环加防",
|
"_docs": "光环加防",
|
||||||
"_data": "光环怪增加防御的比例"
|
"_data": "光环怪增加防御的比例"
|
||||||
},
|
},
|
||||||
"zoneSquare": {
|
|
||||||
"_leaf": true,
|
|
||||||
"_type": "checkbox",
|
|
||||||
"_docs": "九宫格",
|
|
||||||
"_data": "领域、阻击或捕捉怪是否九宫格"
|
|
||||||
},
|
|
||||||
"haloSquare": {
|
|
||||||
"_leaf": true,
|
|
||||||
"_type": "checkbox",
|
|
||||||
"_docs": "九宫格",
|
|
||||||
"_data": "光环怪是否九宫格"
|
|
||||||
},
|
|
||||||
"range": {
|
|
||||||
"_leaf": true,
|
|
||||||
"_type": "textarea",
|
|
||||||
"_range": "(thiseval==~~thiseval && thiseval>0)||thiseval==null",
|
|
||||||
"_docs": "领域范围",
|
|
||||||
"_data": "领域的范围;不加默认为1"
|
|
||||||
},
|
|
||||||
"haloRange": {
|
"haloRange": {
|
||||||
"_leaf": true,
|
"_leaf": true,
|
||||||
"_type": "textarea",
|
"_type": "textarea",
|
||||||
@ -311,54 +279,14 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
|
|||||||
"_leaf": true,
|
"_leaf": true,
|
||||||
"_type": "checkbox",
|
"_type": "checkbox",
|
||||||
"_docs": "不可炸",
|
"_docs": "不可炸",
|
||||||
"_data": "该怪物不可被炸"
|
"_data": "勾选后该怪不可被炸弹消灭"
|
||||||
},
|
},
|
||||||
"n": {
|
"n": {
|
||||||
"_leaf": true,
|
"_leaf": true,
|
||||||
"_type": "textarea",
|
"_type": "textarea",
|
||||||
"_range": "(thiseval==~~thiseval && thiseval>0)||thiseval==null",
|
"_range": "(thiseval==~~thiseval && thiseval>0)||thiseval==null",
|
||||||
"_docs": "连击数",
|
"_docs": "连击数",
|
||||||
"_data": "多连击的连击数,净化怪的净化倍率"
|
"_data": "多连击次数;部分特殊怪作净化倍率等,见文档"
|
||||||
},
|
|
||||||
"purify": {
|
|
||||||
"_leaf": true,
|
|
||||||
"_type": "textarea",
|
|
||||||
"_range": "(thiseval==~~thiseval && thiseval>0)||thiseval==null",
|
|
||||||
"_docs": "净化倍率",
|
|
||||||
"_data": "净化百分比"
|
|
||||||
},
|
|
||||||
"add": {
|
|
||||||
"_leaf": true,
|
|
||||||
"_type": "checkbox",
|
|
||||||
"_docs": "吸血加到自身",
|
|
||||||
"_data": "吸血后是否加到自身"
|
|
||||||
},
|
|
||||||
"haloAdd": {
|
|
||||||
"_leaf": true,
|
|
||||||
"_type": "checkbox",
|
|
||||||
"_docs": "光环是否叠加",
|
|
||||||
"_data": "光环是否叠加"
|
|
||||||
},
|
|
||||||
"atkValue": {
|
|
||||||
"_leaf": true,
|
|
||||||
"_type": "textarea",
|
|
||||||
"_range": "thiseval==~~thiseval||thiseval==null",
|
|
||||||
"_docs": "退化扣攻",
|
|
||||||
"_data": "退化时勇士下降的攻击力点数"
|
|
||||||
},
|
|
||||||
"defValue": {
|
|
||||||
"_leaf": true,
|
|
||||||
"_type": "textarea",
|
|
||||||
"_range": "thiseval==~~thiseval||thiseval==null",
|
|
||||||
"_docs": "退化扣防",
|
|
||||||
"_data": "退化时勇士下降的防御力点数"
|
|
||||||
},
|
|
||||||
"damage": {
|
|
||||||
"_leaf": true,
|
|
||||||
"_type": "textarea",
|
|
||||||
"_range": "thiseval==~~thiseval||thiseval==null",
|
|
||||||
"_docs": "固伤",
|
|
||||||
"_data": "战前扣血的点数"
|
|
||||||
},
|
},
|
||||||
"beforeBattle": {
|
"beforeBattle": {
|
||||||
"_leaf": true,
|
"_leaf": true,
|
||||||
@ -373,7 +301,13 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
|
|||||||
"_event": "afterBattle",
|
"_event": "afterBattle",
|
||||||
"_docs": "战后事件",
|
"_docs": "战后事件",
|
||||||
"_data": "和该怪物战斗后触发的事件列表"
|
"_data": "和该怪物战斗后触发的事件列表"
|
||||||
}
|
},
|
||||||
|
/*
|
||||||
|
下列字段不在面板列出;可在 project/enemys.js 手写。字段名:
|
||||||
|
repulse, laser, breakArmor, counterAttack, vampire, haloSquare,
|
||||||
|
purify, haloAdd, atkValue, defValue, damage
|
||||||
|
(add「吸血加到自身」已废弃不在表中出现;旧存档若有手写需自行删除键)
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"enemys_template": { 'name': '新敌人', 'hp': 0, 'atk': 0, 'def': 0, 'money': 0, 'exp': 0, 'point': 0, 'timeCost': null, 'special': [] },
|
"enemys_template": { 'name': '新敌人', 'hp': 0, 'atk': 0, 'def': 0, 'money': 0, 'exp': 0, 'point': 0, 'timeCost': null, 'special': [] },
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
| 区域 | 说明 |
|
| 区域 | 说明 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| [project/items.js](../project/items.js) | 每条道具在 `"cls"` 下一行含 **`"timeCost": null`**;需消耗地图时间时改为正整数。 |
|
| [project/items.js](../project/items.js) | 每条道具在 `"cls"` 下一行含 **`"timeCost": null`**;需消耗地图时间时改为正整数。**样例(已接)**:`bigKey`(`tools`)**`timeCost: 3`**,见 §1.3。 |
|
||||||
| [project/enemys.js](../project/enemys.js) | 每条怪物在 **`point` 与 `special` 之间**含 **`"timeCost": null`**。 |
|
| [project/enemys.js](../project/enemys.js) | 每条怪物在 **`point` 与 `special` 之间**含 **`"timeCost": null`**。 |
|
||||||
| `enemy48` | 与 `enemys` 共用 **`core.material.enemys`** 数值,**无**独立 `libs/enemys48.js` 数据表。 |
|
| `enemy48` | 与 `enemys` 共用 **`core.material.enemys`** 数值,**无**独立 `libs/enemys48.js` 数据表。 |
|
||||||
|
|
||||||
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
| 文件 | 行为 |
|
| 文件 | 行为 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| [libs/items.js](../libs/items.js) `items.prototype.useItem` | 在 **`_useItemEffect`** 之后:若 **`typeof timeCost === "number"` 且 `> 0`**,且存在 **`core.plugin.mapTurn.consumeTime`**,则调用 **`consumeTime(_tc, "item:" + itemId)`**。`null` 或非正数不推进。 |
|
| [libs/items.js](../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](map-turn-spec.md) §3.1。`null` 或非正数不推进;**与异步开门动画无关**(规范 §4 tools)。总开关关则 **`consumeTime`** 内早退。 |
|
||||||
|
|
||||||
### 1.4 插件:`core.plugin.mapTurn`
|
### 1.4 插件:`core.plugin.mapTurn`
|
||||||
|
|
||||||
@ -39,17 +39,21 @@
|
|||||||
- **`consumeTime(deltaTime, reason)`**:`clock += floor(delta)`,再循环 **`deltaTime` 次** **`advanceMapTurnOne`**(§2.1)。
|
- **`consumeTime(deltaTime, reason)`**:`clock += floor(delta)`,再循环 **`deltaTime` 次** **`advanceMapTurnOne`**(§2.1)。
|
||||||
- **`advanceMapTurnOne(reason)`**:`mapTurn += 1`,调用 **`resolveEnemyActionsForSingleTick`**。
|
- **`advanceMapTurnOne(reason)`**:`mapTurn += 1`,调用 **`resolveEnemyActionsForSingleTick`**。
|
||||||
- **`resolveEnemyActionsForSingleTick(reason)`**:已按 §6.2 遍历 **`activeEnemiesByFloor[currentFloor]`**,维护 **`enemyActionGauge[floorId][runtimeId]`**,达阈调用 **`performEnemyAction`**;本函数路径内不调用 **`extractBlocks`**。
|
- **`resolveEnemyActionsForSingleTick(reason)`**:已按 §6.2 遍历 **`activeEnemiesByFloor[currentFloor]`**,维护 **`enemyActionGauge[floorId][runtimeId]`**,达阈调用 **`performEnemyAction`**;本函数路径内不调用 **`extractBlocks`**。
|
||||||
- **`performEnemyAction(enemyRef, def, floorId, reason)`**:已挂载;初版 **`actType === idle`** 无操作;`chase`/`patrol`/`skill` 占位(同步改图块会经引擎 `removeBlock` 触发全表扫描,故不在此 tick 内实现)。
|
- **`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](../project/plugins.js) 对 **`afterChangeFloor`** 的包装调用。
|
- **`rebuildActiveEnemies(floorId)`**:对该层 **`extractBlocks` 一次** 后遍历 **`map.blocks`**,收录 **`cls` 以 `enemy` 开头** 且 **`enemys[id].timeCost` 为正数** 的实例(**`runtimeId` / `x` / `y` / `enemyId` / `def`**),写回 **`activeEnemiesByFloor[floorId]`**,**`activeEnemiesVersion++`**,并修剪 **`enemyActionGauge[floorId]`**。换层由 [project/plugins.js](../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`**。
|
- **`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`**。
|
||||||
- **`settleBattleTimeCost`**:已实现 **`max(1, 状态技能 battleTimeCost 最大值)`**(§6.4)。
|
- **战后成功路径**(同文件内 **「序章追击」** 等对 **`events.prototype.afterBattle`** 的包装):先调用原 **`afterBattle`**;若勇士仍存活且存在 **`mapTurn`**,则 **`consumeTime(settleBattleTimeCost(), "battle")`**,再 **`applyStatusAfterBattle("success")`**。
|
||||||
- **`applyStatusAfterBattle` / `clearOnDeath`**:已按规范 §6.5–6.6 操作 **`flags.skillState`**(经 **`core.getFlag` / `core.setFlag`** 维护的 **`mapTurnState` / `skillState`** 结构)。
|
- **`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](../libs/ui.js) **`getToolboxItems("tools")`** 与 **`getToolboxPermanentItems`**(**`constants`** + 四类技能 **`cls`**)分两行;**地图回合技能线若暂用 `cls:"tools"`**,走 **消耗道具行** 显示(与 **`bigKey`** 同区)。
|
||||||
|
|
||||||
### 1.5 编辑器 / 新素材注册
|
### 1.5 编辑器 / 新素材注册
|
||||||
|
|
||||||
| 文件 | 说明 |
|
| 文件 | 说明 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| [_server/table/comment.js](../_server/table/comment.js) | 道具表、怪物表增加 **`timeCost`** 列说明;**`items_template`** / **`enemys_template`** 含 **`timeCost: null`**,新建行时带该字段。 |
|
| [_server/table/comment.js](../_server/table/comment.js) | 道具表、怪物表 **`timeCost`** 列说明;**`items_template`** / **`enemys_template`** 含 **`timeCost: null`**。道具 **`cls`** 可选 **`skillbattle` / `skillremote` / `skillrecover` / `skillupdate`**(与 [map-turn-spec.md](map-turn-spec.md) §3.1 一致)。**工程临时**:未在编辑器注册 skill cls 时,可用 **`cls:"tools"`** + **`mapTurnSkillRole`**(`battle`/`remote`/`recover`/`update`)+ **`mapTurnKeepAfterUse: true`**(使用后不占消耗、**`addItem` 上限 1**),与 [libs/items.js](../libs/items.js) **`useItem`** / **`_afterUseItem`** 对齐。 |
|
||||||
|
|
||||||
### 1.6 当前接线口径补充(2026-04)
|
### 1.6 当前接线口径补充(2026-04)
|
||||||
|
|
||||||
@ -62,7 +66,7 @@
|
|||||||
|
|
||||||
## 2. 待完成(接线清单,对齐 map-turn-spec §4 / §6 / §8)
|
## 2. 待完成(接线清单,对齐 map-turn-spec §4 / §6 / §8)
|
||||||
|
|
||||||
已完成接线见 **§1**(含 §1.4、§1.6)。以下为尚未实现的步骤说明;完成后在 §3 验收表对应行打勾。
|
核心调度接线见 **§1**(含 §1.4、§1.6)。下表 **§2** 为大块任务勾选;细项与「仍缺」见 **§2.1**、**§3**。
|
||||||
|
|
||||||
- [x] **`resolveEnemyActionsForSingleTick`**:已在 [project/plugins.js](../project/plugins.js) **`mapTurn`** 中实现 §2 该条所列 1–4 步(含 **`performEnemyAction`**,`idle` 已实现,其余 `actType` 占位)。
|
- [x] **`resolveEnemyActionsForSingleTick`**:已在 [project/plugins.js](../project/plugins.js) **`mapTurn`** 中实现 §2 该条所列 1–4 步(含 **`performEnemyAction`**,`idle` 已实现,其余 `actType` 占位)。
|
||||||
|
|
||||||
@ -72,28 +76,35 @@
|
|||||||
|
|
||||||
### 2.1 后续扩展接线备忘
|
### 2.1 后续扩展接线备忘
|
||||||
|
|
||||||
对应 [map-turn-spec.md](map-turn-spec.md) 中已有字段或流程、尚未在工程中专项接线时的操作指向:
|
对应 [map-turn-spec.md](map-turn-spec.md) 中已有字段或流程的操作指向;**已接与仍缺分列如下**。
|
||||||
|
|
||||||
- **四类技能与 `items`**:在 [project/items.js](../project/items.js) 为道具补 **`skillType` / `timeCost` 等**后,在道具使用效果与 **`flags.skillState`** 写入处接线;状态技能保持 **`timeCost === 0`** 且不调用 **`consumeTime`**;战斗耗时仍走 **`settleBattleTimeCost`** 与战后 **`applyStatusAfterBattle`** 调用链。
|
**已接(当前仓库)**
|
||||||
- **`contactBattleOnly` 与多怪捕捉**:在战斗触发逻辑(如 **`beforeBattle`** 或等价入口)读取怪物字段分支;多怪连续战斗时每场成功后调用 **`applyStatusAfterBattle("success")`**。
|
|
||||||
- **`actType` / `actArgs`**:在 **`performEnemyAction`**(或由 **`resolveEnemyActionsForSingleTick`** 内联)按怪物表字段分支执行移动/技能等行为。
|
- **战斗技能(`skillbattle` 或 `mapTurnSkillRole:"battle"`)**:样例 **`skill1`**([project/items.js](../project/items.js),当前 **`cls:"tools"`** + **`mapTurnSkillRole:"battle"`** + **`mapTurnKeepAfterUse`**,**`timeCost: 3`**,id **`skill1`** ↔ **`flag:skill === 1`**);[libs/items.js](../libs/items.js) **`useItem`** 对 **`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)
|
## 3. 验收清单映射(对应 map-turn-spec §10)
|
||||||
|
|
||||||
| §10 条目 | 依赖的待办小节 |
|
| §10 条目 | 依赖 / 当前状态(台账口径) |
|
||||||
|----------|----------------|
|
|----------|----------------|
|
||||||
| 状态技能不立即推进时间;战后层数 `-1` | 战斗胜利接线 + **`skillState`** 数据与 **`applyStatusAfterBattle`** 调用时机 |
|
| 状态技能不立即推进时间;战后层数 `-1` | **`applyStatusAfterBattle`** 已在单场战后成功路径调用(§1.4)。**规范路径仍缺**:**`cls:"skillupdate"`** 写入 **`activeStatusSkills`**(含 **`remainBattles`** / **`battleTimeCost`**)的配置与开关脚本。**`I350`** 为测试向 **`mapTestAtkLayers` + tick 衰减**,不覆盖 **`activeStatusSkills`** 验收。 |
|
||||||
| 远程/恢复立即推进;怪物按时间响应 | 道具 **`timeCost`**(已有 `useItem` 钩子)+ **`resolveEnemyActions` / `activeEnemies`** 实装 |
|
| 远程/恢复立即推进;怪物按时间响应 | **`useItem`** 对 **`remote`/`recover` 角色**(或规范 **`skillremote`/`skillrecover`**)与普通 **`tools`** 一样按正数 **`timeCost`** **`consumeTime`**(§1.3)。示例 **`I347`/`I348`**(§2.1)。**敌调度**:**`resolveEnemyActionsForSingleTick`** + **`activeEnemies`** 已实装(§1.4)。 |
|
||||||
| 战斗耗时 **`max`** | **`settleBattleTimeCost`** 已在插件中;需战斗路径实际调用 |
|
| 战斗耗时 **`max`** | **`afterBattle`** 成功路径已 **`consumeTime(settleBattleTimeCost(), "battle")`**(§1.4);含 **`skill1`**(**`battle` 角色**)与 **`activeStatusSkills`**。回归:全场战斗均走该 **`afterBattle`** 包装即可确认。 |
|
||||||
| 多怪捕捉逐场扣层 | **`afterBattle`** 多场链路与每场成功分支 |
|
| 多怪捕捉逐场扣层 | **单场** **`afterBattle`** 已链 **`applyStatusAfterBattle`**。**仍缺**:多怪连战的 **`afterBattle`** 触发次数 / 事件链是否每场独立成功分支(见 §2.1)。 |
|
||||||
| Boss **`contactBattleOnly`** | 战斗触发层逻辑 + 怪物字段 |
|
| Boss **`contactBattleOnly`** | **仍缺**:战斗触发层读取 **`contactBattleOnly`** 与单场结算分支(§2.1)。 |
|
||||||
| 死亡清理 | **`clearOnDeath`** 接入 **`lose` / 失败** |
|
| 死亡清理 | **`clearOnDeath`** 已实现;**仍缺**:在 **`events.lose`** 或等价失败出口调用(§1.4)。 |
|
||||||
| 存档读档连续 | **`flags`** 持久化已有方向;读档后 **`rebuildActiveEnemies`** |
|
| 存档读档连续 | **`flags.mapTurnState` / `skillState`** 等随档;读档后 **`bootstrapPersistedState`** + **`afterChangeFloor`** 侧 **`rebuildActiveEnemies`**(§1.6)。 |
|
||||||
| **`timeCost=0`** 不参与调度 | **`rebuildActiveEnemies`** 过滤 + **`resolveEnemyActions`** 只扫缓存 |
|
| **`timeCost=0`** 不参与调度 | **`rebuildActiveEnemies`** 仅收录 **`timeCost > 0`**;**`resolveEnemyActionsForSingleTick`** 只扫缓存列表(§1.4)。 |
|
||||||
| **`consumeTime(3)`** 恰好 3 tick | **`consumeTime`** 已实现循环;需集成测试断言 |
|
| **`consumeTime(3)`** 恰好 3 tick | **`consumeTime`** 内循环 **`advanceMapTurnOne`** 已实现;**建议**:对 **`bigKey`** 或脚本 **`consumeTime(3)`** 做日志/计数断言回归(§1.3)。 |
|
||||||
| **`activeEnemies` 路径无每 tick 全图扫描** | **`rebuild` / `patch`** 实装 |
|
| **`activeEnemies` 路径无每 tick 全图扫描** | **`resolveEnemyActionsForSingleTick`** 不 **`extractBlocks`**;地图变更走 **`patch`/`rebuild`**(§1.4)。**例外**:**庇护 29** 每次行动 **`extractBlocks`** 一次(测试专用,§1.4)。 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@ -45,18 +45,29 @@
|
|||||||
|
|
||||||
### 3.1 技能定义(items 扩展)
|
### 3.1 技能定义(items 扩展)
|
||||||
|
|
||||||
|
技能品类通过 **`cls`** 区分(写入 `project/items.js`,无需另行注册「技能类型枚举」):
|
||||||
|
|
||||||
|
| `cls` | 含义 | `timeCost` 与地图回合 |
|
||||||
|
|-------|------|----------------------|
|
||||||
|
| **`skillbattle`** | 战斗技能(开关型) | 使用瞬间 **不** `consumeTime`;数值参与战后 **`settleBattleTimeCost`** 与基础耗时的 **max** |
|
||||||
|
| **`skillremote`** | 远程技能 | 使用后立即按 **`timeCost`** `consumeTime`(规范 §4) |
|
||||||
|
| **`skillrecover`** | 恢复技能 | 同上 |
|
||||||
|
| **`skillupdate`** | 状态技能 | **`timeCost` 固定为 `0`**;开关 **不** `consumeTime`;持续层数等走 **`skillState`** |
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// project/items.js 每个可用技能道具(tools类)建议字段
|
// project/items.js 示例字段(按需)
|
||||||
{
|
{
|
||||||
skillType: "battle" | "status" | "recover" | "ranged",
|
cls: "skillbattle" | "skillremote" | "skillrecover" | "skillupdate",
|
||||||
timeCost: number, // 统一时间消耗,状态技能固定为0
|
timeCost: number, // 战斗/远程/恢复语义见上表;状态技能为 0
|
||||||
canCancel: boolean, // 可否取消(主要用于status)
|
canCancel: boolean, // 可否取消(主要用于 skillupdate)
|
||||||
exclusiveGroup: string | null, // 战斗技能互斥组,例如 "battleSkill"
|
exclusiveGroup: string | null, // 战斗技能互斥组,例如 "battleSkill"
|
||||||
durationBattles: number | null,// 状态技能持续战斗次数;null表示非按战斗计数
|
durationBattles: number | null,// 状态技能持续战斗次数;null表示非按战斗计数
|
||||||
stackPolicy: "refresh" | "stack" | "replace" // 后续扩展
|
stackPolicy: "refresh" | "stack" | "replace" // 后续扩展
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
与运行时 **`flag:skill`** 对齐时:约定道具 **`id`** 为 **`skill` + 编号**(如 `skill1` → `flag:skill === 1`),地图回合侧据此同步 **`activeBattleSkillId`**。
|
||||||
|
|
||||||
### 3.2 怪物定义(enemys/enemy48 扩展)
|
### 3.2 怪物定义(enemys/enemy48 扩展)
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@ -122,9 +133,10 @@ flags.skillState = {
|
|||||||
- 轻按拾取(不移动):推进,默认 `+1`。
|
- 轻按拾取(不移动):推进,默认 `+1`。
|
||||||
- 使用 tools 类道具(如 bigKey):按道具 `timeCost` 推进。
|
- 使用 tools 类道具(如 bigKey):按道具 `timeCost` 推进。
|
||||||
- 单场战斗:推进,按 `battleFinalTimeCost`。
|
- 单场战斗:推进,按 `battleFinalTimeCost`。
|
||||||
- 远程技能(不可撤回):立即按技能 `timeCost` 推进。
|
- 远程技能:立即按 `timeCost` 推进;工程上对应道具 **`cls: "skillremote"`**(见 §3.1)。
|
||||||
- 恢复技能:视同远程技能,立即按 `timeCost` 推进。
|
- 恢复技能:视同远程;对应 **`cls: "skillrecover"`**。
|
||||||
- 状态技能:`timeCost=0`,不推进地图时间。
|
- 状态技能:`timeCost=0`,不推进;对应 **`cls: "skillupdate"`**。
|
||||||
|
- 战斗技能(开关型):使用瞬间不推进;战后按 **`settleBattleTimeCost`** 与基础耗时取 max;对应 **`cls: "skillbattle"`**。
|
||||||
- 纯 UI 操作(菜单、手册、预览模拟):不推进。
|
- 纯 UI 操作(菜单、手册、预览模拟):不推进。
|
||||||
|
|
||||||
**说明**:矩阵中的「推进 `+n`」均指调用 `consumeTime(n, ...)`;引擎内部必须把 `n` 拆成 `n` 次 `advanceMapTurnOne`(§2.1)。
|
**说明**:矩阵中的「推进 `+n`」均指调用 `consumeTime(n, ...)`;引擎内部必须把 `n` 拆成 `n` 次 `advanceMapTurnOne`(§2.1)。
|
||||||
|
|||||||
@ -1516,7 +1516,7 @@ actions.prototype._keyUpQuickShop = function (keycode) {
|
|||||||
////// 工具栏界面时的点击操作 //////
|
////// 工具栏界面时的点击操作 //////
|
||||||
actions.prototype._clickToolbox = function (x, y) {
|
actions.prototype._clickToolbox = function (x, y) {
|
||||||
var tools = core.getToolboxItems('tools'),
|
var tools = core.getToolboxItems('tools'),
|
||||||
constants = core.getToolboxItems('constants');
|
constants = core.ui.getToolboxPermanentItems();
|
||||||
|
|
||||||
// 装备栏
|
// 装备栏
|
||||||
if (x >= this.LAST - 2 && y == 0) {
|
if (x >= this.LAST - 2 && y == 0) {
|
||||||
@ -1580,7 +1580,7 @@ actions.prototype._clickToolbox = function (x, y) {
|
|||||||
////// 选择工具栏界面中某个Index后的操作 //////
|
////// 选择工具栏界面中某个Index后的操作 //////
|
||||||
actions.prototype._clickToolboxIndex = function (index) {
|
actions.prototype._clickToolboxIndex = function (index) {
|
||||||
var tools = core.getToolboxItems('tools'),
|
var tools = core.getToolboxItems('tools'),
|
||||||
constants = core.getToolboxItems('constants');
|
constants = core.ui.getToolboxPermanentItems();
|
||||||
|
|
||||||
var items = null;
|
var items = null;
|
||||||
var select;
|
var select;
|
||||||
@ -1612,7 +1612,7 @@ actions.prototype._keyDownToolbox = function (keycode) {
|
|||||||
var last_index = this.LAST - 1;
|
var last_index = this.LAST - 1;
|
||||||
|
|
||||||
var tools = core.getToolboxItems('tools'),
|
var tools = core.getToolboxItems('tools'),
|
||||||
constants = core.getToolboxItems('constants');
|
constants = core.ui.getToolboxPermanentItems();
|
||||||
var index = core.status.event.selection;
|
var index = core.status.event.selection;
|
||||||
var toolsPage = core.status.event.data.toolsPage;
|
var toolsPage = core.status.event.data.toolsPage;
|
||||||
var constantsPage = core.status.event.data.constantsPage;
|
var constantsPage = core.status.event.data.constantsPage;
|
||||||
|
|||||||
@ -1732,7 +1732,7 @@ control.prototype._replayAction_item = function (action) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
var tools = core.getToolboxItems('tools'),
|
var tools = core.getToolboxItems('tools'),
|
||||||
constants = core.getToolboxItems('constants');
|
constants = core.ui.getToolboxPermanentItems();
|
||||||
var index, per = core._WIDTH_ - 1;
|
var index, per = core._WIDTH_ - 1;
|
||||||
if ((index = tools.indexOf(itemId)) >= 0) {
|
if ((index = tools.indexOf(itemId)) >= 0) {
|
||||||
core.status.event.data = { "toolsPage": Math.floor(index / per) + 1, "constantsPage": 1 };
|
core.status.event.data = { "toolsPage": Math.floor(index / per) + 1, "constantsPage": 1 };
|
||||||
|
|||||||
@ -89,12 +89,17 @@ items.prototype.useItem = function (itemId, noRoute, callback) {
|
|||||||
}
|
}
|
||||||
// 执行道具效果
|
// 执行道具效果
|
||||||
this._useItemEffect(itemId);
|
this._useItemEffect(itemId);
|
||||||
// 地图回合:按 project/items.js 中 timeCost(null 不推进);见 docs/map-turn-spec.md
|
// 地图回合:见 docs/map-turn-spec.md §3.1 / §4。skillbattle、skillupdate 使用瞬间不 consumeTime;skillbattle 的 timeCost 战后 settleBattleTimeCost 取 max。
|
||||||
try {
|
try {
|
||||||
var _item = core.material.items[itemId];
|
var _item = core.material.items[itemId];
|
||||||
var _tc = _item && _item.timeCost;
|
var _tc = _item && _item.timeCost;
|
||||||
if (typeof _tc === "number" && _tc > 0 && core.plugin && core.plugin.mapTurn && typeof core.plugin.mapTurn.consumeTime === "function")
|
var _cls = _item && _item.cls;
|
||||||
|
var _role = _item && _item.mapTurnSkillRole;
|
||||||
|
var _skipTick = _cls === "skillbattle" || _cls === "skillupdate" || _role === "battle" || _role === "update";
|
||||||
|
if (!_skipTick && typeof _tc === "number" && _tc > 0 && core.plugin && core.plugin.mapTurn && typeof core.plugin.mapTurn.consumeTime === "function")
|
||||||
core.plugin.mapTurn.consumeTime(_tc, "item:" + itemId);
|
core.plugin.mapTurn.consumeTime(_tc, "item:" + itemId);
|
||||||
|
if ((_cls === "skillbattle" || _role === "battle") && core.plugin && core.plugin.mapTurn && typeof core.plugin.mapTurn.syncBattleSkillItemState === "function")
|
||||||
|
core.plugin.mapTurn.syncBattleSkillItemState(itemId);
|
||||||
} catch (e) { }
|
} catch (e) { }
|
||||||
// 执行完毕
|
// 执行完毕
|
||||||
this._afterUseItem(itemId);
|
this._afterUseItem(itemId);
|
||||||
@ -125,9 +130,10 @@ items.prototype._useItemEffect = function (itemId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
items.prototype._afterUseItem = function (itemId) {
|
items.prototype._afterUseItem = function (itemId) {
|
||||||
// 道具使用完毕:删除
|
// 道具使用完毕:删除(mapTurnKeepAfterUse:地图回合测试用技能,占 tools 栏但不扣数量)
|
||||||
var itemCls = core.material.items[itemId].cls;
|
var itemCls = core.material.items[itemId].cls;
|
||||||
if (itemCls == 'tools')
|
var _keep = (core.material.items[itemId] || {}).mapTurnKeepAfterUse;
|
||||||
|
if (itemCls == 'tools' && !_keep)
|
||||||
core.status.hero.items[itemCls][itemId]--;
|
core.status.hero.items[itemCls][itemId]--;
|
||||||
if (core.status.hero.items[itemCls][itemId] <= 0)
|
if (core.status.hero.items[itemCls][itemId] <= 0)
|
||||||
delete core.status.hero.items[itemCls][itemId];
|
delete core.status.hero.items[itemCls][itemId];
|
||||||
@ -205,8 +211,8 @@ items.prototype.addItem = function (itemId, itemNum) {
|
|||||||
if (core.status.hero.items[itemCls][itemId] <= 0) {
|
if (core.status.hero.items[itemCls][itemId] <= 0) {
|
||||||
delete core.status.hero.items[itemCls][itemId];
|
delete core.status.hero.items[itemCls][itemId];
|
||||||
}
|
}
|
||||||
// 永久道具只能有一个
|
// 永久道具只能有一个(含技能 cls);地图回合测试用 tools+mapTurnKeepAfterUse 同上限 1
|
||||||
if (itemCls == 'constants' && core.status.hero.items[itemCls][itemId] > 1)
|
if ((itemCls == 'constants' || itemCls == 'skillbattle' || itemCls == 'skillremote' || itemCls == 'skillrecover' || itemCls == 'skillupdate' || (itemCls == 'tools' && itemData.mapTurnKeepAfterUse)) && core.status.hero.items[itemCls][itemId] > 1)
|
||||||
core.status.hero.items[itemCls][itemId] = 1;
|
core.status.hero.items[itemCls][itemId] = 1;
|
||||||
core.updateStatusBar();
|
core.updateStatusBar();
|
||||||
}
|
}
|
||||||
|
|||||||
14
libs/ui.js
14
libs/ui.js
@ -2701,13 +2701,25 @@ ui.prototype.getToolboxItems = function (cls) {
|
|||||||
.sort();
|
.sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////// 永久道具栏:constants + 技能四类 cls(与 docs/map-turn-spec.md §3.1 一致) //////
|
||||||
|
ui.prototype.getToolboxPermanentItems = function () {
|
||||||
|
var keys = ["constants", "skillbattle", "skillremote", "skillrecover", "skillupdate"];
|
||||||
|
var out = [];
|
||||||
|
for (var i = 0; i < keys.length; i++) {
|
||||||
|
var sub = this.getToolboxItems(keys[i]);
|
||||||
|
if (sub && sub.length) out = out.concat(sub);
|
||||||
|
}
|
||||||
|
out.sort();
|
||||||
|
return out;
|
||||||
|
};
|
||||||
|
|
||||||
ui.prototype._drawToolbox_getInfo = function (index) {
|
ui.prototype._drawToolbox_getInfo = function (index) {
|
||||||
// 设定eventdata
|
// 设定eventdata
|
||||||
if (!core.status.event.data || core.status.event.data.toolsPage == null)
|
if (!core.status.event.data || core.status.event.data.toolsPage == null)
|
||||||
core.status.event.data = { "toolsPage": 1, "constantsPage": 1, "selectId": null }
|
core.status.event.data = { "toolsPage": 1, "constantsPage": 1, "selectId": null }
|
||||||
// 获取物品列表
|
// 获取物品列表
|
||||||
var tools = core.getToolboxItems('tools'),
|
var tools = core.getToolboxItems('tools'),
|
||||||
constants = core.getToolboxItems('constants');
|
constants = core.ui.getToolboxPermanentItems();
|
||||||
// 处理页数
|
// 处理页数
|
||||||
var n = core._WIDTH_ - 1;
|
var n = core._WIDTH_ - 1;
|
||||||
var toolsPage = core.status.event.data.toolsPage;
|
var toolsPage = core.status.event.data.toolsPage;
|
||||||
|
|||||||
@ -7,7 +7,7 @@ var enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80 =
|
|||||||
"bat": {"name":"小蝙蝠","hp":30,"atk":12,"def":3,"money":2,"exp":0,"point":0,"timeCost":null,"special":[4]},
|
"bat": {"name":"小蝙蝠","hp":30,"atk":12,"def":3,"money":2,"exp":0,"point":0,"timeCost":null,"special":[4]},
|
||||||
"bigBat": {"name":"大蝙蝠","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"timeCost":null,"special":0},
|
"bigBat": {"name":"大蝙蝠","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"timeCost":null,"special":0},
|
||||||
"redBat": {"name":"红蝙蝠","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"timeCost":null,"special":[]},
|
"redBat": {"name":"红蝙蝠","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"timeCost":null,"special":[]},
|
||||||
"vampire": {"name":"冥灵魔王","hp":888,"atk":888,"def":888,"money":888,"exp":888,"point":0,"timeCost":null,"special":[],"n":8},
|
"vampire": {"name":"冥灵魔王","hp":888,"atk":888,"def":888,"money":888,"exp":888,"point":0,"timeCost":1,"special":[29],"n":null},
|
||||||
"skeleton": {"name":"骷髅人","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"timeCost":null,"special":0},
|
"skeleton": {"name":"骷髅人","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"timeCost":null,"special":0},
|
||||||
"skeletonCaptain": {"name":"骷髅队长","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"timeCost":null,"special":0},
|
"skeletonCaptain": {"name":"骷髅队长","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"timeCost":null,"special":0},
|
||||||
"zombie": {"name":"兽人","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"timeCost":null,"special":0},
|
"zombie": {"name":"兽人","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"timeCost":null,"special":0},
|
||||||
@ -49,7 +49,7 @@ var enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80 =
|
|||||||
"yellowGateKeeper": {"name":"初级卫兵","hp":100,"atk":120,"def":0,"money":10,"exp":0,"point":0,"timeCost":null,"special":0},
|
"yellowGateKeeper": {"name":"初级卫兵","hp":100,"atk":120,"def":0,"money":10,"exp":0,"point":0,"timeCost":null,"special":0},
|
||||||
"blueGateKeeper": {"name":"中级卫兵","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"timeCost":null,"special":0},
|
"blueGateKeeper": {"name":"中级卫兵","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"timeCost":null,"special":0},
|
||||||
"redGateKeeper": {"name":"高级卫兵","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"timeCost":null,"special":0},
|
"redGateKeeper": {"name":"高级卫兵","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"timeCost":null,"special":0},
|
||||||
"magicMaster": {"name":"黑暗大法师","hp":100,"atk":120,"def":0,"money":12,"exp":0,"point":0,"timeCost":null,"special":11,"value":0.3333333333333333,"add":true,"notBomb":true},
|
"magicMaster": {"name":"黑暗大法师","hp":100,"atk":120,"def":0,"money":12,"exp":0,"point":0,"timeCost":null,"special":11,"value":0.3333333333333333,"notBomb":true},
|
||||||
"devilWarrior": {"name":"魔神武士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"timeCost":null,"special":0},
|
"devilWarrior": {"name":"魔神武士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"timeCost":null,"special":0},
|
||||||
"fairyEnemy": {"name":"仙子","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"timeCost":null,"special":0},
|
"fairyEnemy": {"name":"仙子","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"timeCost":null,"special":0},
|
||||||
"dragon": {"name":"魔龙","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"timeCost":null,"special":0,"bigImage":"dragon_0.png"},
|
"dragon": {"name":"魔龙","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"timeCost":null,"special":0,"bigImage":"dragon_0.png"},
|
||||||
|
|||||||
@ -49,15 +49,15 @@ main.floors.C0_B03=
|
|||||||
[ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17],
|
[ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17],
|
||||||
[ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17],
|
[ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17],
|
||||||
[ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17],
|
[ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17],
|
||||||
[20164, 0, 32, 0,20164, 22, 0,201, 17, 17, 17, 17, 17, 17, 17],
|
[20164, 0, 32,350,20164, 22, 0,201, 17, 17, 17, 17, 17, 17, 17],
|
||||||
[20164, 27, 0,205, 0, 0,20164, 0, 31, 0,201, 0, 0, 17, 17],
|
[20164, 27,348,205,347, 0,20164, 0, 31, 0,201,208, 0, 17, 17],
|
||||||
[20164,20164,20164,20164,20145,20164,20164, 0,20164,20164, 0,20164, 30, 17, 17],
|
[20164,20164,20164,20164,20145,20164,20164, 0,20164,20164, 0,20164, 30, 17, 17],
|
||||||
[ 92, 83,203, 0,20164, 0, 0,202, 0, 0,201,20164, 0, 17, 17],
|
[ 92, 83,203, 0,20164, 0, 0,202, 0, 0,201,20164, 0, 17, 17],
|
||||||
[20164,20164,20164,205,20164,201,20164,20157, 0,20164, 0, 0,201, 22,20164],
|
[20164,20164,20164,205,20164,201,20164,20157, 0,20164, 0, 0,201, 22,20164],
|
||||||
[20164, 0,202, 0,20164, 0, 21,20164, 0, 17, 0, 17, 17, 31,20164],
|
[20164, 0,202, 0,20164, 0, 21,20164, 0, 17, 0, 17, 17, 31,20164],
|
||||||
[20164,201,20164,20164,20164, 32, 0, 0,203, 17, 0, 17, 17, 0,20164],
|
[20164,201,20164,20164,20164, 32, 0, 0,203, 17, 0, 17, 17, 0,20164],
|
||||||
[20164, 0, 82, 81, 0, 0,20164,20164, 0, 31, 0,205, 0, 82, 94],
|
[20164, 0, 82, 81, 0, 0,20164,20164, 0, 31, 0,205, 0, 82, 94],
|
||||||
[20172,20164,20164, 0,202,20164, 21, 0, 0, 0,201,20164,20164, 0,20164],
|
[20172,20164,20164, 26,202,20164, 21, 0, 0, 0,201,20164,20164, 0,20164],
|
||||||
[20164, 31, 0, 28, 0,20164, 0, 29, 0,20164, 0, 0, 0, 81,20164],
|
[20164, 31, 0, 28, 0,20164, 0, 29, 0,20164, 0, 0, 0, 81,20164],
|
||||||
[20164,20164,20164,20164,20164,20164, 17, 17, 17,20164, 93,20164,20164,20164,20164]
|
[20164,20164,20164,20164,20164,20164, 17, 17, 17,20164, 93,20164,20164,20164,20164]
|
||||||
],
|
],
|
||||||
|
|||||||
@ -518,7 +518,9 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
|
|||||||
[25, "光环", function (enemy) { return (enemy.range != null ? ((enemy.haloSquare ? "该怪物九宫格" : "该怪物十字") + enemy.haloRange + "格范围内") : "同楼层所有") + "怪物生命提升" + (enemy.hpBuff || 0) + "%,攻击提升" + (enemy.atkBuff || 0) + "%,防御提升" + (enemy.defBuff || 0) + "%," + (enemy.haloAdd ? "可叠加" : "不可叠加"); }, "#e6e099", 1],
|
[25, "光环", function (enemy) { return (enemy.range != null ? ((enemy.haloSquare ? "该怪物九宫格" : "该怪物十字") + enemy.haloRange + "格范围内") : "同楼层所有") + "怪物生命提升" + (enemy.hpBuff || 0) + "%,攻击提升" + (enemy.atkBuff || 0) + "%,防御提升" + (enemy.defBuff || 0) + "%," + (enemy.haloAdd ? "可叠加" : "不可叠加"); }, "#e6e099", 1],
|
||||||
[26, "支援", "当周围一圈的怪物受到攻击时将上前支援,并组成小队战斗。", "#77c0b6", 1],
|
[26, "支援", "当周围一圈的怪物受到攻击时将上前支援,并组成小队战斗。", "#77c0b6", 1],
|
||||||
[27, "捕捉", function (enemy) { return "当走到怪物周围" + (enemy.zoneSquare ? "九宫格" : "十字") + "时会强制进行战斗。"; }, "#c0ddbb"],
|
[27, "捕捉", function (enemy) { return "当走到怪物周围" + (enemy.zoneSquare ? "九宫格" : "十字") + "时会强制进行战斗。"; }, "#c0ddbb"],
|
||||||
[28, "追击", "追击", "#cc8866"]
|
[28, "追击", "追击", "#cc8866"],
|
||||||
|
// 29 庇护:测试用;正式版地图回合类技能序号从 101 起
|
||||||
|
[29, "庇护", "(测试)地图回合每推进一次,本层所有怪物最大生命+1;数值写入存档,换层不重置。", "#99ccee", 0]
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
"getEnemyInfo": function (enemy, hero, x, y, floorId) {
|
"getEnemyInfo": function (enemy, hero, x, y, floorId) {
|
||||||
@ -1588,7 +1590,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
|
|||||||
"ui": {
|
"ui": {
|
||||||
"getToolboxItems": function (cls) {
|
"getToolboxItems": function (cls) {
|
||||||
// 获得道具栏中当前某类型道具的显示项和显示顺序
|
// 获得道具栏中当前某类型道具的显示项和显示顺序
|
||||||
// cls为道具类型,只可能是 tools, constants 和 equips
|
// cls 为 tools、constants、equips 或技能四类(skillbattle 等),见 map-turn-spec §3.1
|
||||||
// 返回一个数组,代表当前某类型道具的显示内容和顺序
|
// 返回一个数组,代表当前某类型道具的显示内容和顺序
|
||||||
// 默认按id升序排列,您可以取消下面的注释改为按名称排列
|
// 默认按id升序排列,您可以取消下面的注释改为按名称排列
|
||||||
|
|
||||||
|
|||||||
@ -273,7 +273,18 @@ var icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1 =
|
|||||||
"jumpShoes": 49,
|
"jumpShoes": 49,
|
||||||
"skill1": 30,
|
"skill1": 30,
|
||||||
"wand": 10,
|
"wand": 10,
|
||||||
"pack": 46
|
"pack": 46,
|
||||||
|
"I344": 5,
|
||||||
|
"I345": 7,
|
||||||
|
"I346": 26,
|
||||||
|
"I347": 31,
|
||||||
|
"I348": 32,
|
||||||
|
"I349": 34,
|
||||||
|
"I350": 35,
|
||||||
|
"I351": 36,
|
||||||
|
"I352": 37,
|
||||||
|
"I353": 38,
|
||||||
|
"I354": 39
|
||||||
},
|
},
|
||||||
"autotile": {
|
"autotile": {
|
||||||
"autotile": 0,
|
"autotile": 0,
|
||||||
|
|||||||
@ -505,7 +505,7 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
|||||||
},
|
},
|
||||||
"centerFly": {
|
"centerFly": {
|
||||||
"cls": "tools",
|
"cls": "tools",
|
||||||
"timeCost": null,
|
"timeCost": 3,
|
||||||
"name": "中心对称飞行器",
|
"name": "中心对称飞行器",
|
||||||
"text": "可以飞向当前楼层中心对称的位置",
|
"text": "可以飞向当前楼层中心对称的位置",
|
||||||
"useItemEffect": "core.playSound('centerFly.mp3');\ncore.clearMap('hero');\ncore.setHeroLoc('x', core.bigmap.width - 1 - core.getHeroLoc('x'));\ncore.setHeroLoc('y', core.bigmap.height - 1 - core.getHeroLoc('y'));\ncore.drawHero();\ncore.drawTip(core.material.items[itemId].name + '使用成功');",
|
"useItemEffect": "core.playSound('centerFly.mp3');\ncore.clearMap('hero');\ncore.setHeroLoc('x', core.bigmap.width - 1 - core.getHeroLoc('x'));\ncore.setHeroLoc('y', core.bigmap.height - 1 - core.getHeroLoc('y'));\ncore.drawHero();\ncore.drawTip(core.material.items[itemId].name + '使用成功');",
|
||||||
@ -641,10 +641,12 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
|||||||
"canUseItemEffect": "(function () {\n\tvar nx = core.nextX(2),\n\t\tny = core.nextY(2);\n\treturn nx >= 0 && nx < core.bigmap.width && ny >= 0 && ny < core.bigmap.height && core.getBlockId(nx, ny) == null;\n})();"
|
"canUseItemEffect": "(function () {\n\tvar nx = core.nextX(2),\n\t\tny = core.nextY(2);\n\treturn nx >= 0 && nx < core.bigmap.width && ny >= 0 && ny < core.bigmap.height && core.getBlockId(nx, ny) == null;\n})();"
|
||||||
},
|
},
|
||||||
"skill1": {
|
"skill1": {
|
||||||
"cls": "constants",
|
"cls": "tools",
|
||||||
|
"mapTurnSkillRole": "battle",
|
||||||
|
"mapTurnKeepAfterUse": true,
|
||||||
"timeCost": 3,
|
"timeCost": 3,
|
||||||
"name": "技能:二倍斩",
|
"name": "技能:二倍斩",
|
||||||
"text": "可以打开或关闭主动技能二倍斩",
|
"text": "可以打开或关闭主动技能二倍斩(暂用 tools 栏位:拾取/轻拾与消耗道具同地图时轴;使用后不占消耗)。",
|
||||||
"hideInReplay": true,
|
"hideInReplay": true,
|
||||||
"useItemEffect": "(function () {\n\tvar skillValue = 1; // 技能的flag:skill值,可用于当前开启技能的判定;对于新技能可以依次改成2,3等等\n\tvar skillNeed = 5; // 技能的需求\n\tvar skillName = '二倍斩'; // 技能的名称\n\n\tif (core.getFlag('skill', 0) != skillValue) { // 判断当前是否已经开了技能\n\t\tif (core.getStatus('mana') >= skillNeed) { // 这里要写当前能否开技能的条件判断,比如魔力值至少要多少\n\t\t\tcore.playSound('打开界面');\n\t\t\tcore.setFlag('skill', skillValue); // 开技能1\n\t\t\tcore.setFlag('skillName', skillName); // 设置技能名\n\t\t} else {\n\t\t\tcore.playSound('操作失败');\n\t\t\tcore.drawTip('魔力不足,无法开启技能');\n\t\t}\n\t} else { // 关闭技能\n\t\tcore.setFlag('skill', 0); // 关闭技能状态\n\t\tcore.setFlag('skillName', '无');\n\t}\n})();",
|
"useItemEffect": "(function () {\n\tvar skillValue = 1; // 技能的flag:skill值,可用于当前开启技能的判定;对于新技能可以依次改成2,3等等\n\tvar skillNeed = 5; // 技能的需求\n\tvar skillName = '二倍斩'; // 技能的名称\n\n\tif (core.getFlag('skill', 0) != skillValue) { // 判断当前是否已经开了技能\n\t\tif (core.getStatus('mana') >= skillNeed) { // 这里要写当前能否开技能的条件判断,比如魔力值至少要多少\n\t\t\tcore.playSound('打开界面');\n\t\t\tcore.setFlag('skill', skillValue); // 开技能1\n\t\t\tcore.setFlag('skillName', skillName); // 设置技能名\n\t\t} else {\n\t\t\tcore.playSound('操作失败');\n\t\t\tcore.drawTip('魔力不足,无法开启技能');\n\t\t}\n\t} else { // 关闭技能\n\t\tcore.setFlag('skill', 0); // 关闭技能状态\n\t\tcore.setFlag('skillName', '无');\n\t}\n})();",
|
||||||
"canUseItemEffect": "true"
|
"canUseItemEffect": "true"
|
||||||
@ -660,5 +662,88 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
|
|||||||
"name": "钱袋",
|
"name": "钱袋",
|
||||||
"itemEffect": "core.status.hero.money += 500",
|
"itemEffect": "core.status.hero.money += 500",
|
||||||
"itemEffectTip": ",金币+500"
|
"itemEffectTip": ",金币+500"
|
||||||
|
},
|
||||||
|
"I344": {
|
||||||
|
"cls": "items",
|
||||||
|
"name": "新物品",
|
||||||
|
"timeCost": null,
|
||||||
|
"canUseItemEffect": "true"
|
||||||
|
},
|
||||||
|
"I345": {
|
||||||
|
"cls": "items",
|
||||||
|
"name": "新物品",
|
||||||
|
"timeCost": null,
|
||||||
|
"canUseItemEffect": "true"
|
||||||
|
},
|
||||||
|
"I346": {
|
||||||
|
"cls": "items",
|
||||||
|
"name": "新物品",
|
||||||
|
"timeCost": null,
|
||||||
|
"canUseItemEffect": "true"
|
||||||
|
},
|
||||||
|
"I347": {
|
||||||
|
"cls": "tools",
|
||||||
|
"mapTurnSkillRole": "recover",
|
||||||
|
"mapTurnKeepAfterUse": true,
|
||||||
|
"timeCost": 2,
|
||||||
|
"name": "恢复技能1",
|
||||||
|
"text": "恢复100点生命(不超过上限);使用后推进2个地图回合。暂用 tools 栏位,拾取与消耗道具同地图时轴。",
|
||||||
|
"hideInReplay": true,
|
||||||
|
"useItemEffect": "(function () {\n\tvar hpmax = core.getRealStatus(\"hpmax\");\n\tvar h = core.status.hero.hp + 100;\n\tif (h > hpmax) h = hpmax;\n\tcore.status.hero.hp = h;\n\tcore.playSound(\"回血\");\n\tcore.updateStatusBar(false, true);\n\tcore.drawTip(\"恢复生命至\" + h + \"/\" + hpmax);\n})();",
|
||||||
|
"canUseItemEffect": "true"
|
||||||
|
},
|
||||||
|
"I348": {
|
||||||
|
"cls": "tools",
|
||||||
|
"mapTurnSkillRole": "remote",
|
||||||
|
"mapTurnKeepAfterUse": true,
|
||||||
|
"timeCost": 1,
|
||||||
|
"name": "远程技能1",
|
||||||
|
"text": "对主角朝向正前方射线上的第一个敌人造成当前攻击100%伤害(非战斗击杀);使用后推进1个地图回合。暂用 tools 栏位,拾取与消耗道具同地图时轴。",
|
||||||
|
"hideInReplay": true,
|
||||||
|
"useItemEffect": "(function () {\n\tvar floorId = core.status.floorId;\n\tvar d = core.getHeroLoc(\"direction\");\n\tvar sc = core.utils.scan[d];\n\tif (!sc) {\n\t\tcore.drawTip(\"朝向无效\");\n\t\treturn;\n\t}\n\tvar hx = core.getHeroLoc(\"x\"),\n\t\thy = core.getHeroLoc(\"y\");\n\tvar atk = Math.max(0, Math.floor(core.getRealStatus(\"atk\")));\n\tif (atk <= 0) {\n\t\tcore.drawTip(\"攻击为0\");\n\t\treturn;\n\t}\n\tvar hit = false;\n\tfor (var n = 1; n < 500; n++) {\n\t\tvar x = hx + sc.x * n,\n\t\t\ty = hy + sc.y * n;\n\t\tif (x < 0 || y < 0 || x >= core.bigmap.width || y >= core.bigmap.height) break;\n\t\tvar block = core.getBlock(x, y, floorId);\n\t\tif (!block || block.disable) continue;\n\t\tvar ev = block.event;\n\t\tif (ev && ev.cls && String(ev.cls).indexOf(\"enemy\") === 0) {\n\t\t\tvar curHp = core.enemys.getEnemyValue(ev.id, \"hp\", x, y, floorId);\n\t\t\tif (typeof curHp !== \"number\") curHp = (core.material.enemys[ev.id] || {}).hp || 0;\n\t\t\tif (curHp <= atk) {\n\t\t\t\tcore.removeBlock(x, y, floorId);\n\t\t\t\tcore.drawTip(\"远程击杀\");\n\t\t\t} else {\n\t\t\t\tcore.events.setEnemyOnPoint(x, y, floorId, \"hp\", atk, \"-=\", undefined, false);\n\t\t\t\tcore.drawTip(\"远程伤害\" + atk);\n\t\t\t}\n\t\t\tcore.playSound(\"爆炸\");\n\t\t\thit = true;\n\t\t\tbreak;\n\t\t}\n\t\tif (ev && ev.noPass) break;\n\t}\n\tif (!hit) core.drawTip(\"前方无敌人\");\n})();",
|
||||||
|
"canUseItemEffect": "true"
|
||||||
|
},
|
||||||
|
"I349": {
|
||||||
|
"cls": "tools",
|
||||||
|
"mapTurnSkillRole": "update",
|
||||||
|
"mapTurnKeepAfterUse": true,
|
||||||
|
"name": "新物品",
|
||||||
|
"timeCost": 0,
|
||||||
|
"canUseItemEffect": "true"
|
||||||
|
},
|
||||||
|
"I350": {
|
||||||
|
"cls": "tools",
|
||||||
|
"mapTurnSkillRole": "update",
|
||||||
|
"mapTurnKeepAfterUse": true,
|
||||||
|
"timeCost": 0,
|
||||||
|
"name": "状态技能1",
|
||||||
|
"text": "叠加3层攻击强化,每层+50%攻击(乘区,状态栏攻击数字直接提高);层数随地图回合每tick减1。暂用 tools 栏位;不与战后 activeStatusSkills 混用。",
|
||||||
|
"hideInReplay": true,
|
||||||
|
"useItemEffect": "(function () {\n\tvar L = core.getFlag(\"mapTestAtkLayers\", 0);\n\tif (typeof L !== \"number\") L = 0;\n\tcore.setFlag(\"mapTestAtkLayers\", L + 3);\n\tcore.addBuff(\"atk\", 1.5);\n\tcore.updateStatusBar(false, true);\n\tvar a = core.getRealStatus(\"atk\");\n\tcore.drawTip(\"强化+3层,当前攻击\" + a);\n\tcore.playSound(\"打开界面\");\n})();",
|
||||||
|
"canUseItemEffect": "true"
|
||||||
|
},
|
||||||
|
"I351": {
|
||||||
|
"cls": "items",
|
||||||
|
"name": "新物品",
|
||||||
|
"timeCost": null,
|
||||||
|
"canUseItemEffect": "true"
|
||||||
|
},
|
||||||
|
"I352": {
|
||||||
|
"cls": "items",
|
||||||
|
"name": "新物品",
|
||||||
|
"timeCost": null,
|
||||||
|
"canUseItemEffect": "true"
|
||||||
|
},
|
||||||
|
"I353": {
|
||||||
|
"cls": "items",
|
||||||
|
"name": "新物品",
|
||||||
|
"timeCost": null,
|
||||||
|
"canUseItemEffect": "true"
|
||||||
|
},
|
||||||
|
"I354": {
|
||||||
|
"cls": "items",
|
||||||
|
"name": "新物品",
|
||||||
|
"timeCost": null,
|
||||||
|
"canUseItemEffect": "true"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -266,12 +266,6 @@ var maps_90f36752_8815_4be8_b32b_d7fad1d0542e =
|
|||||||
"329": {"cls":"enemy48","id":"bearRight"},
|
"329": {"cls":"enemy48","id":"bearRight"},
|
||||||
"330": {"cls":"enemy48","id":"bearUp"},
|
"330": {"cls":"enemy48","id":"bearUp"},
|
||||||
"331": {"cls":"terrains","id":"T331"},
|
"331": {"cls":"terrains","id":"T331"},
|
||||||
"20360": {"cls":"tileset","id":"X20360","canPass":true},
|
|
||||||
"20361": {"cls":"tileset","id":"X20361","canPass":true},
|
|
||||||
"20368": {"cls":"tileset","id":"X20368","canPass":true},
|
|
||||||
"20369": {"cls":"tileset","id":"X20369","canPass":true},
|
|
||||||
"20376": {"cls":"tileset","id":"X20376","canPass":true},
|
|
||||||
"20377": {"cls":"tileset","id":"X20377","canPass":true},
|
|
||||||
"332": {"cls":"items","id":"yellowKey2","name":"黄钥匙×2"},
|
"332": {"cls":"items","id":"yellowKey2","name":"黄钥匙×2"},
|
||||||
"333": {"cls":"items","id":"blueKey2","name":"蓝钥匙×2"},
|
"333": {"cls":"items","id":"blueKey2","name":"蓝钥匙×2"},
|
||||||
"334": {"cls":"items","id":"redKey2","name":"红钥匙×2"},
|
"334": {"cls":"items","id":"redKey2","name":"红钥匙×2"},
|
||||||
@ -283,5 +277,22 @@ var maps_90f36752_8815_4be8_b32b_d7fad1d0542e =
|
|||||||
"340": {"cls":"items","id":"redPotion2","name":"大红血瓶"},
|
"340": {"cls":"items","id":"redPotion2","name":"大红血瓶"},
|
||||||
"341": {"cls":"items","id":"bluePotion2","name":"大蓝血瓶"},
|
"341": {"cls":"items","id":"bluePotion2","name":"大蓝血瓶"},
|
||||||
"342": {"cls":"items","id":"yellowPotion2","name":"大黄血瓶"},
|
"342": {"cls":"items","id":"yellowPotion2","name":"大黄血瓶"},
|
||||||
"343": {"cls":"items","id":"greenPotion2","name":"大绿血瓶"}
|
"343": {"cls":"items","id":"greenPotion2","name":"大绿血瓶"},
|
||||||
|
"344": {"cls":"items","id":"I344"},
|
||||||
|
"345": {"cls":"items","id":"I345"},
|
||||||
|
"346": {"cls":"items","id":"I346"},
|
||||||
|
"347": {"cls":"items","id":"I347"},
|
||||||
|
"348": {"cls":"items","id":"I348"},
|
||||||
|
"349": {"cls":"items","id":"I349"},
|
||||||
|
"350": {"cls":"items","id":"I350"},
|
||||||
|
"351": {"cls":"items","id":"I351"},
|
||||||
|
"352": {"cls":"items","id":"I352"},
|
||||||
|
"353": {"cls":"items","id":"I353"},
|
||||||
|
"354": {"cls":"items","id":"I354"},
|
||||||
|
"20360": {"cls":"tileset","id":"X20360","canPass":true},
|
||||||
|
"20361": {"cls":"tileset","id":"X20361","canPass":true},
|
||||||
|
"20368": {"cls":"tileset","id":"X20368","canPass":true},
|
||||||
|
"20369": {"cls":"tileset","id":"X20369","canPass":true},
|
||||||
|
"20376": {"cls":"tileset","id":"X20376","canPass":true},
|
||||||
|
"20377": {"cls":"tileset","id":"X20377","canPass":true}
|
||||||
}
|
}
|
||||||
@ -2738,9 +2738,74 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
|
|||||||
core.setFlag("mapTurnEnabled", !!v);
|
core.setFlag("mapTurnEnabled", !!v);
|
||||||
if (v) ensureFlags();
|
if (v) ensureFlags();
|
||||||
},
|
},
|
||||||
/** 读档或 setValue 写入 flag 后调用,在 flag 为真时补齐 mapTurnState / skillState */
|
/** 读档或 setValue 写入 flag 后调用;先迁移道具桶(cls 从 constants 改为 skill* 的旧存档),再按需补齐 mapTurnState / skillState */
|
||||||
bootstrapPersistedState: function () {
|
bootstrapPersistedState: function () {
|
||||||
if (mapTurnEnabled()) ensureFlags();
|
if (typeof this.migrateSkillItemBuckets === "function") this.migrateSkillItemBuckets();
|
||||||
|
if (mapTurnEnabled()) {
|
||||||
|
ensureFlags();
|
||||||
|
if (typeof this.resyncBattleSkillItemStates === "function") this.resyncBattleSkillItemStates();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 旧存档:constants 或旧 skill* 桶中的条目,按当前 material 迁到正确桶(含 cls:tools + mapTurnSkillRole 的地图回合技能线) */
|
||||||
|
migrateSkillItemBuckets: function () {
|
||||||
|
if (!core.status.hero || !core.status.hero.items) return;
|
||||||
|
var mat = core.material.items || {};
|
||||||
|
var hi = core.status.hero.items;
|
||||||
|
var skillClses = ["skillbattle", "skillremote", "skillrecover", "skillupdate"];
|
||||||
|
var old = hi.constants || {};
|
||||||
|
for (var itemId in old) {
|
||||||
|
var def = mat[itemId];
|
||||||
|
if (!def) continue;
|
||||||
|
var n = old[itemId];
|
||||||
|
if (typeof n !== "number" || n <= 0) continue;
|
||||||
|
if (def.cls === "tools" && def.mapTurnSkillRole) {
|
||||||
|
if (!hi.tools) hi.tools = {};
|
||||||
|
hi.tools[itemId] = (hi.tools[itemId] || 0) + n;
|
||||||
|
delete old[itemId];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var c = def.cls;
|
||||||
|
if (skillClses.indexOf(c) < 0) continue;
|
||||||
|
if (!hi[c]) hi[c] = {};
|
||||||
|
hi[c][itemId] = (hi[c][itemId] || 0) + n;
|
||||||
|
delete old[itemId];
|
||||||
|
}
|
||||||
|
for (var bi = 0; bi < skillClses.length; bi++) {
|
||||||
|
var b = skillClses[bi];
|
||||||
|
var buck = hi[b];
|
||||||
|
if (!buck) continue;
|
||||||
|
for (var iid in buck) {
|
||||||
|
var d2 = mat[iid];
|
||||||
|
var n2 = buck[iid];
|
||||||
|
if (typeof n2 !== "number" || n2 <= 0) continue;
|
||||||
|
if (!d2 || d2.cls !== "tools" || !d2.mapTurnSkillRole) continue;
|
||||||
|
if (!hi.tools) hi.tools = {};
|
||||||
|
hi.tools[iid] = (hi.tools[iid] || 0) + n2;
|
||||||
|
delete buck[iid];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 与 project/items 中 battle 技能(cls:skillbattle 或 mapTurnSkillRole:battle)及 id「skillN」对齐 flag:skill;读档后由 bootstrapPersistedState 全量校正 */
|
||||||
|
syncBattleSkillItemState: function (itemId) {
|
||||||
|
ensureFlags();
|
||||||
|
var it = core.material.items[itemId];
|
||||||
|
if (!it || (it.cls !== "skillbattle" && it.mapTurnSkillRole !== "battle")) return;
|
||||||
|
var m = typeof itemId === "string" && /^skill(\d+)$/.exec(itemId);
|
||||||
|
var fv = m ? parseInt(m[1], 10) : null;
|
||||||
|
if (fv == null || isNaN(fv)) return;
|
||||||
|
var ss = core.getFlag("skillState");
|
||||||
|
var cur = core.getFlag("skill", 0);
|
||||||
|
if (cur === fv) ss.activeBattleSkillId = itemId;
|
||||||
|
else if (ss.activeBattleSkillId === itemId) ss.activeBattleSkillId = null;
|
||||||
|
core.setFlag("skillState", ss);
|
||||||
|
},
|
||||||
|
resyncBattleSkillItemStates: function () {
|
||||||
|
var items = core.material.items || {};
|
||||||
|
for (var id in items) {
|
||||||
|
var idm = items[id];
|
||||||
|
if (idm && (idm.cls === "skillbattle" || idm.mapTurnSkillRole === "battle"))
|
||||||
|
this.syncBattleSkillItemState(id);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
consumeTime: function (deltaTime, reason) {
|
consumeTime: function (deltaTime, reason) {
|
||||||
if (!mapTurnEnabled() || !deltaTime || deltaTime <= 0) return;
|
if (!mapTurnEnabled() || !deltaTime || deltaTime <= 0) return;
|
||||||
@ -2757,6 +2822,16 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
|
|||||||
var s = core.getFlag("mapTurnState");
|
var s = core.getFlag("mapTurnState");
|
||||||
s.mapTurn = (s.mapTurn || 0) + 1;
|
s.mapTurn = (s.mapTurn || 0) + 1;
|
||||||
this.resolveEnemyActionsForSingleTick(reason);
|
this.resolveEnemyActionsForSingleTick(reason);
|
||||||
|
// 测试道具 I350:每层强化随「地图 tick」跌落(由任意 consumeTime 推进触发;远程击杀不另扣层)
|
||||||
|
this.mapTurnTickDecayMapTestAtkLayers();
|
||||||
|
},
|
||||||
|
/** I350 地图回合驱动:每 tick 层数 -1,atk 乘区 -0.5(与每层 +50% 对齐) */
|
||||||
|
mapTurnTickDecayMapTestAtkLayers: function () {
|
||||||
|
var layers = core.getFlag("mapTestAtkLayers", 0);
|
||||||
|
if (typeof layers !== "number" || layers <= 0) return;
|
||||||
|
core.setFlag("mapTestAtkLayers", layers - 1);
|
||||||
|
if (typeof core.addBuff === "function") core.addBuff("atk", -0.5);
|
||||||
|
core.updateStatusBar(false, true);
|
||||||
},
|
},
|
||||||
/** 单 tick 怪物调度:仅扫 activeEnemiesByFloor;不调用 extractBlocks(map-turn-spec §6.2) */
|
/** 单 tick 怪物调度:仅扫 activeEnemiesByFloor;不调用 extractBlocks(map-turn-spec §6.2) */
|
||||||
resolveEnemyActionsForSingleTick: function (reason) {
|
resolveEnemyActionsForSingleTick: function (reason) {
|
||||||
@ -2789,8 +2864,26 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
|
|||||||
/**
|
/**
|
||||||
* 达阈行动:初版仅实现 actType === idle(无操作)。
|
* 达阈行动:初版仅实现 actType === idle(无操作)。
|
||||||
* chase/patrol/skill 等若在此同步改图块,会经引擎 removeBlock 触发 extractBlocks,违反单 tick 约束;后续用 insertAction 链或专用无扫描迁移 API 再接。
|
* chase/patrol/skill 等若在此同步改图块,会经引擎 removeBlock 触发 extractBlocks,违反单 tick 约束;后续用 insertAction 链或专用无扫描迁移 API 再接。
|
||||||
|
* 特殊 29【庇护】(测试):仅改 flags.enemyOnPoint,不经 removeBlock/setBlock。
|
||||||
*/
|
*/
|
||||||
performEnemyAction: function (enemyRef, def, floorId, reason) {
|
performEnemyAction: function (enemyRef, def, floorId, reason) {
|
||||||
|
if (def && core.enemys && typeof core.enemys.hasSpecial === "function" && core.enemys.hasSpecial(def.special, 29)) {
|
||||||
|
floorId = floorId || core.status.floorId;
|
||||||
|
if (floorId && core.floors && core.floors[floorId]) {
|
||||||
|
core.extractBlocks(floorId);
|
||||||
|
var _mapShelter = core.status.maps && core.status.maps[floorId];
|
||||||
|
var _blocksShelter = (_mapShelter && _mapShelter.blocks) || [];
|
||||||
|
for (var _si = 0; _si < _blocksShelter.length; _si++) {
|
||||||
|
var _b = _blocksShelter[_si];
|
||||||
|
if (!_b || _b.disable) continue;
|
||||||
|
var _ev = _b.event;
|
||||||
|
if (!_ev || !_ev.cls || String(_ev.cls).indexOf("enemy") !== 0) continue;
|
||||||
|
core.events.setEnemyOnPoint(_b.x, _b.y, floorId, "hp", 1, "+=", undefined, true);
|
||||||
|
}
|
||||||
|
core.updateStatusBar();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
var actType = def.actType || "idle";
|
var actType = def.actType || "idle";
|
||||||
if (actType === "idle") return;
|
if (actType === "idle") return;
|
||||||
/* chase / patrol / skill:占位,不在此 tick 内改图块 */
|
/* chase / patrol / skill:占位,不在此 tick 内改图块 */
|
||||||
@ -2934,6 +3027,18 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
|
|||||||
var v = st && st.battleTimeCost;
|
var v = st && st.battleTimeCost;
|
||||||
if (typeof v === "number" && v > statusBattleTimeCostMax) statusBattleTimeCostMax = v;
|
if (typeof v === "number" && v > statusBattleTimeCostMax) statusBattleTimeCostMax = v;
|
||||||
}
|
}
|
||||||
|
var ss = core.getFlag("skillState");
|
||||||
|
var bid = ss.activeBattleSkillId;
|
||||||
|
if (bid) {
|
||||||
|
var bit = core.material.items[bid];
|
||||||
|
if (
|
||||||
|
bit &&
|
||||||
|
(bit.cls === "skillbattle" || bit.mapTurnSkillRole === "battle") &&
|
||||||
|
typeof bit.timeCost === "number" &&
|
||||||
|
bit.timeCost > statusBattleTimeCostMax
|
||||||
|
)
|
||||||
|
statusBattleTimeCostMax = bit.timeCost;
|
||||||
|
}
|
||||||
return Math.max(baseBattleTimeCost, statusBattleTimeCostMax);
|
return Math.max(baseBattleTimeCost, statusBattleTimeCostMax);
|
||||||
},
|
},
|
||||||
applyStatusAfterBattle: function (battleResult) {
|
applyStatusAfterBattle: function (battleResult) {
|
||||||
@ -3045,6 +3150,110 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
|
|||||||
mtCall({ op: "migratePoint", fromX: fromX, fromY: fromY, toX: toX, toY: toY }, floorId || core.status.floorId);
|
mtCall({ op: "migratePoint", fromX: fromX, fromY: fromY, toX: toX, toY: toY }, floorId || core.status.floorId);
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
},
|
||||||
|
"瞬移轨迹": function () {
|
||||||
|
// 在此增加新插件
|
||||||
|
function popMove() {
|
||||||
|
var ctx = core.getContextByName("popMove");
|
||||||
|
if (!ctx)
|
||||||
|
ctx = core.createCanvas(
|
||||||
|
"popMove",
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
core.__PIXELS__,
|
||||||
|
core.__PIXELS__,
|
||||||
|
71
|
||||||
|
);
|
||||||
|
ctx.canvas.classList.add("gameCanvas", "anti-aliasing");
|
||||||
|
core.clearMap(ctx);
|
||||||
|
if (core.status.replay.speed <= 3 && !flags.stopPop) {
|
||||||
|
var list = core.status.popMove || [];
|
||||||
|
var count = 0;
|
||||||
|
list.forEach(function (one) {
|
||||||
|
// 由frame计算出dy
|
||||||
|
|
||||||
|
one.frame++;
|
||||||
|
// 绘制
|
||||||
|
|
||||||
|
if (one.frame >= 0) core.setAlpha(ctx, 1 - one.frame / 30);
|
||||||
|
else core.setAlpha(ctx, 1);
|
||||||
|
|
||||||
|
var length = Math.sqrt(
|
||||||
|
Math.pow(one.px2 - one.px, 2) + Math.pow(one.py2 - one.py, 2)
|
||||||
|
);
|
||||||
|
//console.log(length)
|
||||||
|
var li = length / 16;
|
||||||
|
var lx = (one.px2 - one.px) / li;
|
||||||
|
var ly = (one.py2 - one.py) / li;
|
||||||
|
for (var i = 0; i < li; i += 1) {
|
||||||
|
core.setAlpha(ctx, (1 - one.frame / 30) * ((i / li) * 0.8 + 0.2));
|
||||||
|
core.drawLine(
|
||||||
|
"popMove",
|
||||||
|
one.px + i * lx,
|
||||||
|
one.py + i * ly,
|
||||||
|
one.px + (i + 0.5) * lx,
|
||||||
|
one.py + (i + 0.5) * ly,
|
||||||
|
"#E1E1E1",
|
||||||
|
6
|
||||||
|
);
|
||||||
|
if (i == 0)
|
||||||
|
core.strokeCircle("popMove", one.px, one.py, 6, "#E1E1E1", 3);
|
||||||
|
}
|
||||||
|
core.strokeCircle("popMove", one.px2, one.py2, 6, "#E1E1E1", 3);
|
||||||
|
core.strokeCircle(
|
||||||
|
"popMove",
|
||||||
|
one.px2,
|
||||||
|
one.py2,
|
||||||
|
6 + (16 * one.frame) / 30,
|
||||||
|
"#E1E1E1",
|
||||||
|
6 * (1 - one.frame / 30)
|
||||||
|
);
|
||||||
|
//core.drawLine('popMove', one.px, one.py, one.px2, one.py2, '#E1E1E1', 6);
|
||||||
|
|
||||||
|
if (one.frame >= 30) count++;
|
||||||
|
});
|
||||||
|
if (count > 0) list.splice(0, count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!main.replayChecking) {
|
||||||
|
core.registerAnimationFrame("popMove", true, popMove);
|
||||||
|
}
|
||||||
|
this.addPopMove = function (px, py, px2, py2, frame) {
|
||||||
|
var data = { px: px, py: py, px2: px2, py2: py2, frame: frame || 0 };
|
||||||
|
if (core.status.replay.speed <= 3) {
|
||||||
|
if (!core.status.popMove) core.status.popMove = [data];
|
||||||
|
else core.status.popMove.push(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
"伤害跳字": //将下面的代码粘贴到脚本编辑 - 插件编写中
|
||||||
|
this.tiaozi = function (neirong, yanse) { //跳字
|
||||||
|
if (core.status.replay.replaying) {} else {
|
||||||
|
var shangsheng = 1;
|
||||||
|
var gaodu = 0;
|
||||||
|
var tiaozizhong = 0;
|
||||||
|
var herox = core.status.hero.loc.x,
|
||||||
|
heroy = core.status.hero.loc.y;
|
||||||
|
var name = "tiaozi" + Math.floor(Math.random() * 1000000); //如不需要连续跳字可不加随机数
|
||||||
|
core.createCanvas(name, (herox - 1) * 32 - 13, (heroy - 1) * 32 + gaodu, 96, 64, 74);
|
||||||
|
core.fillText(name, neirong, 32, 32, yanse, "bold 17px Verdana");
|
||||||
|
var fade = setInterval(function () {
|
||||||
|
if (gaodu >= -6 && shangsheng == 1) {
|
||||||
|
gaodu = gaodu - 1;
|
||||||
|
if (gaodu == -6) { shangsheng = 0 }
|
||||||
|
} else if (gaodu <= 12) {
|
||||||
|
gaodu = gaodu + 1;
|
||||||
|
if (gaodu == 12) { tiaozizhong = 1; }
|
||||||
|
};
|
||||||
|
core.relocateCanvas(name, (herox - 1) * 32 - 13, (heroy - 1) * 32 + gaodu);
|
||||||
|
if (tiaozizhong == 1) {
|
||||||
|
delete core.animateFrame.asyncId[fade];
|
||||||
|
clearInterval(fade);
|
||||||
|
core.deleteCanvas(name);
|
||||||
|
}
|
||||||
|
}, 16);
|
||||||
|
core.animateFrame.asyncId[fade] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user