diff --git a/_server/CodeMirror/defs.js b/_server/CodeMirror/defs.js index 425b4cbf..96ad8afc 100644 --- a/_server/CodeMirror/defs.js +++ b/_server/CodeMirror/defs.js @@ -2533,6 +2533,14 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [ "moveDirectly": { "!doc": "瞬间移动", "!type": "fn(destX?: number, destY?: number, ignoreSteps?: number)" + }, + "clearRouteFolding": { + "!doc": "清空录像折叠信息", + "!type": "fn()" + }, + "checkRouteFolding": { + "!doc": "检查录像折叠信息", + "!type": "fn()" } }, "icons": { diff --git a/_server/table/data.comment.js b/_server/table/data.comment.js index 2edcaea2..80e51f03 100644 --- a/_server/table/data.comment.js +++ b/_server/table/data.comment.js @@ -629,6 +629,12 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_docs": "允许瞬移", "_data": "是否允许瞬间移动" }, + "enableRouteFolding": { + "_leaf": true, + "_type": "checkbox", + "_docs": "录像折叠", + "_data": "是否开启录像折叠功能。\n此功能将尽可能的通过优化无损耗反复走的方式来缩短录像,但在某些情况下(尤其是创新向塔中)可能会存在副作用影响录像的正确性。" + }, "disableShopOnDamage": { "_leaf": true, "_type": "checkbox", diff --git a/editor-mobile.html b/editor-mobile.html index 7f8a0d75..2e97f65f 100644 --- a/editor-mobile.html +++ b/editor-mobile.html @@ -359,7 +359,7 @@ 线 矩形 - tileset平铺 + tile平铺 填充 diff --git a/libs/control.js b/libs/control.js index 3d8ec317..26517b0b 100644 --- a/libs/control.js +++ b/libs/control.js @@ -648,6 +648,7 @@ control.prototype._moveAction_moving = function (callback) { core.status.route.push(direction); core.moveOneStep(); + core.checkRouteFolding(); if (callback) callback(); }); } @@ -741,6 +742,7 @@ control.prototype.turnHero = function(direction) { core.setHeroLoc('direction', core.turnDirection(':right')); core.drawHero(); core.status.route.push("turn"); + core.checkRouteFolding(); } ////// 瞬间移动 ////// @@ -2170,6 +2172,45 @@ control.prototype.debug = function() { core.drawText("\t[调试模式开启]此模式下按住Ctrl键(或Ctrl+Shift键)可以穿墙并忽略一切事件。\n此模式下将无法上传成绩。"); } +control.prototype._bindRoutePush = function () { + core.status.route.push = function (element) { + // 忽视移动、转向、瞬移 + if (["up", "down", "left", "right", "turn"].indexOf(element) < 0 && !element.startsWith("move:")) { + core.clearRouteFolding(); + } + Array.prototype.push.call(core.status.route, element); + } +} + +////// 清除录像折叠信息 ////// +control.prototype.clearRouteFolding = function () { + core.status.routeFolding = {}; +} + +////// 检查录像折叠 ////// +control.prototype.checkRouteFolding = function () { + // 未开启、未开始游戏、正在录像播放中、正在事件中:不执行 + if (!core.flags.enableRouteFolding || !core.isPlaying() || core.isReplaying() || core.status.event.id) { + return this.clearRouteFolding(); + } + var hero = core.clone(core.status.hero, function (name, value) { + return name != 'steps' && typeof value == 'number'; + }); + var index = [core.getHeroLoc('x'),core.getHeroLoc('y'),core.getHeroLoc('direction').charAt(0)].join(','); + core.status.routeFolding = core.status.routeFolding || {}; + if (core.status.routeFolding[index]) { + var one = core.status.routeFolding[index]; + if (core.same(one.hero, hero) && one.length < core.status.route.length) { + Object.keys(core.status.routeFolding).forEach(function (v) { + if (core.status.routeFolding[v].length >= one.length) delete core.status.routeFolding[v]; + }); + core.status.route = core.status.route.slice(0, one.length); + this._bindRoutePush(); + } + } + core.status.routeFolding[index] = {hero: hero, length: core.status.route.length}; +} + // ------ 天气,色调,BGM ------ // control.prototype.getMappedName = function (name) { @@ -2462,6 +2503,7 @@ control.prototype.updateStatusBar = function (doNotCheckAutoEvents) { this.controldata.updateStatusBar(); if (!doNotCheckAutoEvents) core.checkAutoEvents(); this._updateStatusBar_setToolboxIcon(); + core.clearRouteFolding(); } control.prototype._updateStatusBar_setToolboxIcon = function () { diff --git a/libs/core.js b/libs/core.js index 878eb52f..b9589f12 100644 --- a/libs/core.js +++ b/libs/core.js @@ -167,6 +167,8 @@ function core() { 'steps': 0, 'save': [], }, + // 录像折叠 + 'routeFolding': {}, // event事件 'shops': {}, diff --git a/libs/events.js b/libs/events.js index 31e737c0..877781e0 100644 --- a/libs/events.js +++ b/libs/events.js @@ -300,6 +300,7 @@ events.prototype.unregisterSystemEvent = function (type) { ////// 执行一个系统事件 ////// events.prototype.doSystemEvent = function (type, data, callback) { + core.clearRouteFolding(); if (this.systemEvents[type]) { try { return core.doFunc(this.systemEvents[type], this, data, callback); @@ -337,9 +338,12 @@ events.prototype.trigger = function (x, y, callback) { block = block.block; // 执行该点的脚本 - try { - eval(block.event.script); - } catch (e) { main.log(e); } + if (block.event.script) { + core.clearRouteFolding(); + try { + eval(block.event.script); + } catch (e) { main.log(e); } + } if (block.event.trigger && block.event.trigger != 'null') { var noPass = block.event.noPass, trigger = block.event.trigger; @@ -987,6 +991,7 @@ events.prototype.insertAction = function (action, x, y, callback, addToLast) { if (core.hasFlag("__statistics__")) return; if (core.status.gameOver) return; if (!action) return; + core.clearRouteFolding(); action = this.precompile(action); @@ -2561,6 +2566,7 @@ events.prototype.follow = function (name) { core.clearMap('hero'); core.drawHero(); } + core.clearRouteFolding(); } ////// 取消跟随 ////// @@ -2580,6 +2586,7 @@ events.prototype.unfollow = function (name) { core.gatherFollowers(); core.clearMap('hero'); core.drawHero(); + core.clearRouteFolding(); } ////// 数值操作 ////// diff --git a/project/data.js b/project/data.js index 8149e0b7..78647a8c 100644 --- a/project/data.js +++ b/project/data.js @@ -462,6 +462,7 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = "ignoreChangeFloor": true, "canGoDeadZone": false, "enableMoveDirectly": true, + "enableRouteFolding": true, "disableShopOnDamage": false, "blurFg": false } diff --git a/project/functions.js b/project/functions.js index 983ebdd2..5db0a2c1 100644 --- a/project/functions.js +++ b/project/functions.js @@ -12,6 +12,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = core.status = core.clone(core.initStatus, function (name) { return name != 'hero' && name != 'maps'; }); + core.control._bindRoutePush(); core.status.played = true; // 初始化人物,图标,统计信息 core.status.hero = core.clone(hero); @@ -956,6 +957,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // 重置游戏和路线 core.resetGame(data.hero, data.hard, data.floorId, core.maps.loadMap(data.maps, null, data.hero.flags), data.values); core.status.route = core.decodeRoute(data.route); + core.control._bindRoutePush(); // 文字属性,全局属性 core.status.textAttribute = core.getFlag('textAttribute', core.status.textAttribute); var toAttribute = core.getFlag('globalAttribute', core.status.globalAttribute); @@ -1348,6 +1350,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = if (core.hasFlag('poison')) { core.updateStatusBar(); } + core.checkRouteFolding(); return true; } return false; diff --git a/runtime.d.ts b/runtime.d.ts index a7c42474..7f359345 100644 --- a/runtime.d.ts +++ b/runtime.d.ts @@ -741,6 +741,12 @@ declare class control { /** 解锁用户控制 */ unlockControl(): void + /** 清空录像折叠信息 */ + clearRouteFolding(): void + + /** 检查录像折叠信息 */ + checkRouteFolding(): void + /** 获得映射文件名 */ getMappedName(name?: string): string