From ba74ab06d9c786bdd185c681cdf6c296919710b1 Mon Sep 17 00:00:00 2001 From: salt <1109119613@qq.com> Date: Fri, 24 Apr 2026 17:38:00 +0800 Subject: [PATCH] =?UTF-8?q?0.14=E5=9C=B0=E5=9B=BE=E5=9B=9E=E5=90=88?= =?UTF-8?q?=E6=9E=84=E7=AD=91-=E5=90=84=E8=A1=8C=E5=8A=A8=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E6=8F=92=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _server/CodeMirror/defs.js | 4 + _server/MotaAction.g4 | 18 ++ _server/MotaActionParser.js | 13 ++ _server/config.json | 2 +- _server/editor_blocklyconfig.js | 1 + claude.md | 77 +++++++ docs/map-turn-implementation-status.md | 106 +++++++++ docs/map-turn-spec.md | 43 +++- docs/暂定大纲.docx | Bin 0 -> 19389 bytes docs/暂定大纲.txt | 48 ++++ libs/events.js | 58 +++++ project/data.js | 9 + project/floors/C0_T01.js | 6 + project/functions.js | 4 + project/items.js | 4 +- project/plugins.js | 302 ++++++++++++++++++++++++- 16 files changed, 674 insertions(+), 21 deletions(-) create mode 100644 claude.md create mode 100644 docs/map-turn-implementation-status.md create mode 100644 docs/暂定大纲.docx create mode 100644 docs/暂定大纲.txt diff --git a/_server/CodeMirror/defs.js b/_server/CodeMirror/defs.js index 8e0ee9f..cb4b641 100644 --- a/_server/CodeMirror/defs.js +++ b/_server/CodeMirror/defs.js @@ -2379,6 +2379,10 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [ "!doc": "连续前进,不撞南墙不回头
例如:core.moveHero(); // 连续前进
direction: 可选,如果设置了就会先转身到该方向
callback: 可选,如果设置了就只走一步
【异步脚本,请勿在脚本中直接调用(而是使用对应的事件),否则可能导致录像出错】", "!type": "fn(direction?: string, callback?: fn())" }, + "moveHeroMapTurn": { + "!doc": "事件用:移动勇者(每落一格推进地图回合)。勿直接调用 core.moveHeroMapTurn;请用事件 JSON type: moveHeroMapTurn", + "!type": "fn()" + }, "getRealStatusOrDefault": { "!doc": "从status中获得实际属性(增幅后的),如果不存在则从勇士属性中获取", "!type": "fn(status?: ?, name?: string)" diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4 index bcbbbe9..0edc1de 100644 --- a/_server/MotaAction.g4 +++ b/_server/MotaAction.g4 @@ -887,6 +887,7 @@ action | move_s | moveAction_s | moveHero_s + | moveHeroMapTurn_s | jump_s | jump_1_s | jumpHero_s @@ -2430,6 +2431,23 @@ var code = '{"type": "moveHero"'+IntString_0+Bool_0+', "steps": ['+moveDirection return code; */; + + +moveHeroMapTurn_s + : '移动勇者' '动画时间' IntString? '不等待执行完毕' Bool BGNL? moveDirection+ Newline + + +/* moveHeroMapTurn_s +tooltip : moveHeroMapTurn:移动勇者;同无视地形移动勇士,但每落一格后推进地图回合并结算敌人(见 project/plugins mapTurn) +helpUrl : /_docs/#/instruction +default : ["",false,"上右3下2后4左前2"] +colour : this.mapColor +IntString_0 = IntString_0 ?(', "time": '+IntString_0):''; +Bool_0 = Bool_0?', "async": true':''; +var code = '{"type": "moveHeroMapTurn"'+IntString_0+Bool_0+', "steps": ['+moveDirection_0.trim().substring(2)+']},\n'; +return code; +*/; + jump_s : '跳跃事件' '起始 x' PosString? ',' 'y' PosString? '终止 x' PosString? ',' 'y' PosString? '动画时间' IntString? '不消失' Bool '不等待执行完毕' Bool Newline diff --git a/_server/MotaActionParser.js b/_server/MotaActionParser.js index bb16fac..095fae3 100644 --- a/_server/MotaActionParser.js +++ b/_server/MotaActionParser.js @@ -504,6 +504,19 @@ ActionParser.prototype.parseAction = function() { this.next = MotaActionBlocks['moveHero_s'].xmlText([ data.time,data.async||false,buildMoveDirection(data.steps),this.next]); break; + case "moveHeroMapTurn": // 移动勇者(每格推进地图回合) + var buildMoveDirectionMT= function (obj) { + obj = MotaActionFunctions.processMoveDirections(obj||[]); + var res = null; + for(var ii=obj.length-1,one;one=obj[ii];ii--) { + var v = one.split(':'); + res=MotaActionBlocks['moveDirection'].xmlText([v[0], parseInt(v[1]), res]); + } + return res; + } + this.next = MotaActionBlocks['moveHeroMapTurn_s'].xmlText([ + data.time,data.async||false,buildMoveDirectionMT(data.steps),this.next]); + break; case "jump": // 跳跃事件 data.from=data.from||['','']; if (data.dxy) { diff --git a/_server/config.json b/_server/config.json index 9f48deb..cda5be7 100644 --- a/_server/config.json +++ b/_server/config.json @@ -1 +1 @@ -{"viewportLoc":[0,0],"lastUsed":[{"idnum":20164,"id":"X20164","images":"2.png","x":4,"y":20,"isTile":true,"recent":1776857705177,"frequent":259},{"idnum":184,"id":"autotile35","images":"autotile","y":0,"recent":1776857694291,"frequent":240},{"idnum":20176,"id":"X20176","images":"2.png","x":0,"y":22,"isTile":true,"recent":1776857656109,"frequent":11},{"idnum":343,"id":"greenPotion2","images":"items","y":73,"recent":1776857277188,"frequent":2},{"idnum":342,"id":"yellowPotion2","images":"items","y":72,"recent":1776857274835,"frequent":2},{"idnum":341,"id":"bluePotion2","images":"items","y":71,"recent":1776857264609,"frequent":2},{"idnum":340,"id":"redPotion2","images":"items","y":70,"recent":1776857262165,"frequent":2},{"idnum":85,"id":"specialDoor","images":"animates","y":8,"recent":1776856176629,"frequent":1},{"idnum":74,"id":"yellowKey2","images":"items","y":62,"recent":1776854998632,"frequent":4},{"idnum":80,"id":"redKey3","images":"items","y":68,"recent":1776853587031,"frequent":2},{"idnum":141,"id":"autotile5","images":"autotile","y":0,"recent":1776848567879,"frequent":39},{"idnum":171,"id":"autotile22","images":"autotile","y":0,"recent":1776848554173,"frequent":39},{"idnum":182,"id":"autotile33","images":"autotile","y":0,"recent":1776847967238,"frequent":7},{"idnum":21,"id":"yellowKey","images":"items","y":0,"recent":1776781827350,"frequent":26},{"idnum":20143,"id":"X20143","images":"2.png","x":7,"y":17,"isTile":true,"recent":1776512715632,"frequent":6},{"idnum":20150,"id":"X20150","images":"2.png","x":6,"y":18,"isTile":true,"recent":1776512664076,"frequent":9},{"idnum":20133,"id":"X20133","images":"2.png","x":5,"y":16,"isTile":true,"recent":1776512643654,"frequent":6},{"idnum":20172,"id":"X20172","images":"2.png","x":4,"y":21,"isTile":true,"recent":1776512387522,"frequent":13},{"idnum":20084,"id":"X20084","images":"2.png","x":4,"y":10,"isTile":true,"recent":1776512245465,"frequent":2},{"idnum":20092,"id":"X20092","images":"2.png","x":4,"y":11,"isTile":true,"recent":1776512229522,"frequent":1},{"idnum":202,"id":"redSlime","images":"enemys","y":1,"recent":1776512150147,"frequent":24},{"idnum":32,"id":"bluePotion","images":"items","y":21,"recent":1776512046283,"frequent":18},{"idnum":31,"id":"redPotion","images":"items","y":20,"recent":1776512038429,"frequent":33},{"idnum":203,"id":"blackSlime","images":"enemys","y":2,"recent":1776512006297,"frequent":18},{"idnum":20130,"id":"X20130","images":"2.png","x":2,"y":16,"isTile":true,"recent":1766314641672,"frequent":12},{"idnum":20136,"id":"X20136","images":"2.png","x":0,"y":17,"isTile":true,"recent":1766314626879,"frequent":3},{"idnum":20155,"id":"X20155","images":"2.png","x":3,"y":19,"isTile":true,"recent":1766242567284,"frequent":2},{"idnum":92,"id":"leftPortal","images":"animates","y":24,"recent":1766242323340,"frequent":10},{"idnum":20129,"id":"X20129","images":"2.png","x":1,"y":16,"isTile":true,"recent":1766242240348,"frequent":11},{"idnum":20148,"id":"X20148","images":"2.png","x":4,"y":18,"isTile":true,"recent":1766242214972,"frequent":4},{"idnum":201,"id":"greenSlime","images":"enemys","y":0,"recent":1766242054491,"frequent":39},{"idnum":81,"id":"yellowDoor","images":"animates","y":4,"recent":1766242045915,"frequent":24},{"idnum":205,"id":"bat","images":"enemys","y":4,"recent":1766241989305,"frequent":16},{"idnum":20147,"id":"X20147","images":"2.png","x":3,"y":18,"isTile":true,"recent":1766241963088,"frequent":6},{"idnum":20139,"id":"X20139","images":"2.png","x":3,"y":17,"isTile":true,"recent":1766241957974,"frequent":3},{"idnum":20145,"id":"X20145","images":"2.png","x":1,"y":18,"isTile":true,"recent":1766241930214,"frequent":10},{"idnum":93,"id":"downPortal","images":"animates","y":23,"recent":1766241906074,"frequent":9},{"idnum":20035,"id":"X20035","images":"2.png","x":3,"y":4,"isTile":true,"recent":1766241873454,"frequent":9},{"idnum":20036,"id":"X20036","images":"2.png","x":4,"y":4,"isTile":true,"recent":1766241865762,"frequent":13},{"idnum":29,"id":"greenGem","images":"items","y":18,"recent":1766241712359,"frequent":12},{"idnum":27,"id":"redGem","images":"items","y":16,"recent":1766241704713,"frequent":11},{"idnum":94,"id":"rightPortal","images":"animates","y":25,"recent":1766241657340,"frequent":9},{"idnum":30,"id":"yellowGem","images":"items","y":19,"recent":1766241275091,"frequent":9},{"idnum":20154,"id":"X20154","images":"2.png","x":2,"y":19,"isTile":true,"recent":1766241194626,"frequent":1},{"idnum":20334,"id":"X20334","images":"2.png","x":6,"y":41,"isTile":true,"recent":1766241103417,"frequent":1},{"idnum":20316,"id":"X20316","images":"2.png","x":4,"y":39,"isTile":true,"recent":1766241089661,"frequent":1},{"idnum":20131,"id":"X20131","images":"2.png","x":3,"y":16,"isTile":true,"recent":1766241066196,"frequent":10},{"idnum":20166,"id":"X20166","images":"2.png","x":6,"y":20,"isTile":true,"recent":1766240988032,"frequent":8},{"idnum":20174,"id":"X20174","images":"2.png","x":6,"y":21,"isTile":true,"recent":1766240983106,"frequent":3},{"idnum":20169,"id":"X20169","images":"2.png","x":1,"y":21,"isTile":true,"recent":1766240962775,"frequent":4},{"idnum":28,"id":"blueGem","images":"items","y":17,"recent":1766240795831,"frequent":7},{"idnum":10215,"id":"X10215","images":"magictower.png","x":7,"y":26,"isTile":true,"recent":1766240735472,"frequent":4},{"idnum":82,"id":"blueDoor","images":"animates","y":5,"recent":1766240729469,"frequent":8},{"idnum":151,"id":"autotile1","images":"autotile","y":0,"recent":1766240566131,"frequent":173},{"idnum":20331,"id":"X20331","images":"2.png","x":3,"y":41,"isTile":true,"recent":1766240553709,"frequent":4},{"idnum":20141,"id":"X20141","images":"2.png","x":5,"y":17,"isTile":true,"recent":1766240534368,"frequent":7},{"idnum":20017,"id":"X20017","images":"2.png","x":1,"y":2,"isTile":true,"recent":1766240520573,"frequent":30},{"idnum":20177,"id":"X20177","images":"2.png","x":1,"y":22,"isTile":true,"recent":1766240514125,"frequent":9},{"idnum":20016,"id":"X20016","images":"2.png","x":0,"y":2,"isTile":true,"recent":1766240486491,"frequent":3},{"idnum":20360,"id":"X20360","images":"2.png","x":0,"y":45,"isTile":true,"recent":1766240400718,"frequent":4},{"idnum":20033,"id":"X20033","images":"2.png","x":1,"y":4,"isTile":true,"recent":1766240311250,"frequent":134},{"idnum":192,"id":"autotile43","images":"autotile","y":0,"recent":1766240179483,"frequent":19},{"idnum":20032,"id":"X20032","images":"2.png","x":0,"y":4,"isTile":true,"recent":1766239819484,"frequent":25},{"idnum":20028,"id":"X20028","images":"2.png","x":4,"y":3,"isTile":true,"recent":1766239742340,"frequent":12},{"idnum":20213,"id":"X20213","images":"2.png","x":5,"y":26,"isTile":true,"recent":1766239711340,"frequent":3},{"idnum":20040,"id":"X20040","images":"2.png","x":0,"y":5,"isTile":true,"recent":1766239554481,"frequent":16},{"idnum":20041,"id":"X20041","images":"2.png","x":1,"y":5,"isTile":true,"recent":1766239544668,"frequent":43},{"idnum":20200,"id":"X20200","images":"2.png","x":0,"y":25,"isTile":true,"recent":1766239537552,"frequent":4},{"idnum":20064,"id":"X20064","images":"2.png","x":0,"y":8,"isTile":true,"recent":1766239521936,"frequent":12},{"idnum":4,"id":"star","images":"animates","y":0,"recent":1766239387179,"frequent":4},{"idnum":305,"id":"grass","images":"terrains","y":1,"recent":1766239347385,"frequent":4},{"idnum":20160,"id":"X20160","images":"2.png","x":0,"y":20,"isTile":true,"recent":1766239240004,"frequent":4},{"idnum":20024,"id":"X20024","images":"2.png","x":0,"y":3,"isTile":true,"recent":1766239040023,"frequent":9},{"idnum":20052,"id":"X20052","images":"2.png","x":4,"y":6,"isTile":true,"recent":1766238874602,"frequent":1},{"idnum":20245,"id":"X20245","images":"2.png","x":5,"y":30,"isTile":true,"recent":1766238847081,"frequent":2},{"idnum":20180,"id":"X20180","images":"2.png","x":4,"y":22,"isTile":true,"recent":1766238833997,"frequent":7},{"idnum":20120,"id":"X20120","images":"2.png","x":0,"y":15,"isTile":true,"recent":1766238609644,"frequent":2},{"idnum":20135,"id":"X20135","images":"2.png","x":7,"y":16,"isTile":true,"recent":1766238554803,"frequent":7},{"idnum":20134,"id":"X20134","images":"2.png","x":6,"y":16,"isTile":true,"recent":1766238533819,"frequent":4},{"idnum":23,"id":"redKey","images":"items","y":2,"recent":1766237357121,"frequent":2},{"idnum":303,"id":"sWallR","images":"terrains","y":23,"recent":1756265573660,"frequent":1},{"idnum":20144,"id":"X20144","images":"2.png","x":0,"y":18,"isTile":true,"recent":1756265529340,"frequent":4},{"idnum":302,"id":"sWallL","images":"terrains","y":22,"recent":1756265497832,"frequent":17},{"idnum":20140,"id":"X20140","images":"2.png","x":4,"y":17,"isTile":true,"recent":1753774585698,"frequent":2},{"idnum":20332,"id":"X20332","images":"2.png","x":4,"y":41,"isTile":true,"recent":1753774524347,"frequent":1},{"idnum":20333,"id":"X20333","images":"2.png","x":5,"y":41,"isTile":true,"recent":1753774519578,"frequent":1},{"idnum":20303,"id":"X20303","images":"2.png","x":7,"y":37,"isTile":true,"recent":1753774455384,"frequent":3},{"idnum":20157,"id":"X20157","images":"2.png","x":5,"y":19,"isTile":true,"recent":1753774420471,"frequent":1},{"idnum":20156,"id":"X20156","images":"2.png","x":4,"y":19,"isTile":true,"recent":1753774407871,"frequent":3},{"idnum":20146,"id":"X20146","images":"2.png","x":2,"y":18,"isTile":true,"recent":1753774353142,"frequent":7},{"idnum":143,"id":"autotile7","images":"autotile","y":0,"recent":1753774091410,"frequent":6},{"idnum":144,"id":"autotile8","images":"autotile","y":0,"recent":1753773953432,"frequent":1},{"idnum":181,"id":"autotile32","images":"autotile","y":0,"recent":1753773925734,"frequent":4},{"idnum":173,"id":"autotile24","images":"autotile","y":0,"recent":1753773911798,"frequent":3},{"idnum":148,"id":"autotile12","images":"autotile","y":0,"recent":1753773893469,"frequent":2},{"idnum":20368,"id":"X20368","images":"2.png","x":0,"y":46,"isTile":true,"recent":1753632196387,"frequent":6},{"idnum":88,"id":"downFloor","images":"terrains","y":5,"recent":1753632181169,"frequent":1},{"idnum":87,"id":"upFloor","images":"terrains","y":6,"recent":1753632174063,"frequent":1},{"idnum":254,"id":"redSwordsman","images":"enemys","y":53,"recent":1753631421770,"frequent":2},{"idnum":45,"id":"book","images":"items","y":9,"recent":1753631118788,"frequent":1},{"idnum":129,"id":"sign","images":"npcs","y":8,"recent":1753610708012,"frequent":1},{"idnum":20306,"id":"X20306","images":"2.png","x":2,"y":38,"isTile":true,"recent":1753072252483,"frequent":6},{"idnum":20196,"id":"X20196","images":"2.png","x":4,"y":24,"isTile":true,"recent":1753072229938,"frequent":25},{"idnum":20026,"id":"X20026","images":"2.png","x":2,"y":3,"isTile":true,"recent":1752335493815,"frequent":31},{"idnum":20376,"id":"X20376","images":"2.png","x":0,"y":47,"isTile":true,"recent":1752069078126,"frequent":2},{"idnum":308,"id":"grass2","images":"terrains","y":2,"recent":1751793406519,"frequent":1},{"idnum":140,"id":"autotile4","images":"autotile","y":0,"recent":1751734041473,"frequent":65},{"idnum":20325,"id":"X20325","images":"2.png","x":5,"y":40,"isTile":true,"recent":1751733296580,"frequent":3},{"idnum":20317,"id":"X20317","images":"2.png","x":5,"y":39,"isTile":true,"recent":1751733293663,"frequent":4},{"idnum":20319,"id":"X20319","images":"2.png","x":7,"y":39,"isTile":true,"recent":1751733272003,"frequent":1},{"idnum":91,"id":"upPortal","images":"animates","y":26,"recent":1751732145191,"frequent":4},{"idnum":22,"id":"blueKey","images":"items","y":1,"recent":1751729533259,"frequent":4},{"idnum":189,"id":"autotile40","images":"autotile","y":0,"recent":1751729502284,"frequent":4},{"idnum":20369,"id":"X20369","images":"2.png","x":1,"y":46,"isTile":true,"recent":1751729296750,"frequent":2},{"idnum":20377,"id":"X20377","images":"2.png","x":1,"y":47,"isTile":true,"recent":1751729251037,"frequent":2},{"idnum":20361,"id":"X20361","images":"2.png","x":1,"y":45,"isTile":true,"recent":1751729242359,"frequent":2},{"idnum":191,"id":"autotile42","images":"autotile","y":0,"recent":1751729130841,"frequent":2},{"idnum":190,"id":"autotile41","images":"autotile","y":0,"recent":1751729127691,"frequent":6},{"idnum":20238,"id":"X20238","images":"2.png","x":6,"y":29,"isTile":true,"recent":1751728303355,"frequent":2},{"idnum":20236,"id":"X20236","images":"2.png","x":4,"y":29,"isTile":true,"recent":1751728295376,"frequent":2},{"idnum":20212,"id":"X20212","images":"2.png","x":4,"y":26,"isTile":true,"recent":1751728281575,"frequent":2},{"idnum":20019,"id":"X20019","images":"2.png","x":3,"y":2,"isTile":true,"recent":1751728241217,"frequent":2},{"idnum":188,"id":"autotile39","images":"autotile","y":0,"recent":1751727929573,"frequent":13},{"idnum":121,"id":"man","images":"npcs","y":0,"recent":1751646123653,"frequent":4},{"idnum":180,"id":"autotile31","images":"autotile","y":0,"recent":1751645997658,"frequent":60},{"idnum":20138,"id":"X20138","images":"2.png","x":2,"y":17,"isTile":true,"recent":1751645672326,"frequent":9},{"idnum":150,"id":"autotile14","images":"autotile","y":0,"recent":1751644554451,"frequent":10},{"idnum":179,"id":"autotile30","images":"autotile","y":0,"recent":1751355356118,"frequent":18},{"idnum":20284,"id":"X20284","images":"2.png","x":4,"y":35,"isTile":true,"recent":1751355312181,"frequent":2},{"idnum":20297,"id":"X20297","images":"2.png","x":1,"y":37,"isTile":true,"recent":1751355248416,"frequent":2},{"idnum":20321,"id":"X20321","images":"2.png","x":1,"y":40,"isTile":true,"recent":1751355245971,"frequent":1},{"idnum":20296,"id":"X20296","images":"2.png","x":0,"y":37,"isTile":true,"recent":1751355235868,"frequent":3},{"idnum":20320,"id":"X20320","images":"2.png","x":0,"y":40,"isTile":true,"recent":1751355222886,"frequent":2},{"idnum":20328,"id":"X20328","images":"2.png","x":0,"y":41,"isTile":true,"recent":1751355208703,"frequent":1},{"idnum":20025,"id":"X20025","images":"2.png","x":1,"y":3,"isTile":true,"recent":1751355030014,"frequent":9},{"idnum":20034,"id":"X20034","images":"2.png","x":2,"y":4,"isTile":true,"recent":1751355016737,"frequent":40},{"idnum":20042,"id":"X20042","images":"2.png","x":2,"y":5,"isTile":true,"recent":1751354986114,"frequent":26},{"idnum":20260,"id":"X20260","images":"2.png","x":4,"y":32,"isTile":true,"recent":1751354981826,"frequent":1},{"idnum":20268,"id":"X20268","images":"2.png","x":4,"y":33,"isTile":true,"recent":1751354971399,"frequent":3},{"idnum":20178,"id":"X20178","images":"2.png","x":2,"y":22,"isTile":true,"recent":1751354514329,"frequent":9},{"idnum":20126,"id":"X20126","images":"2.png","x":6,"y":15,"isTile":true,"recent":1751298630823,"frequent":2},{"idnum":20127,"id":"X20127","images":"2.png","x":7,"y":15,"isTile":true,"recent":1751297554068,"frequent":1},{"idnum":20027,"id":"X20027","images":"2.png","x":3,"y":3,"isTile":true,"recent":1751297516808,"frequent":3},{"idnum":20020,"id":"X20020","images":"2.png","x":4,"y":2,"isTile":true,"recent":1751297395193,"frequent":2},{"idnum":20187,"id":"X20187","images":"2.png","x":3,"y":23,"isTile":true,"recent":1751297343385,"frequent":36},{"idnum":20300,"id":"X20300","images":"2.png","x":4,"y":37,"isTile":true,"recent":1751296676841,"frequent":7},{"idnum":20308,"id":"X20308","images":"2.png","x":4,"y":38,"isTile":true,"recent":1751296667698,"frequent":2},{"idnum":20309,"id":"X20309","images":"2.png","x":5,"y":38,"isTile":true,"recent":1751296579393,"frequent":1},{"idnum":20301,"id":"X20301","images":"2.png","x":5,"y":37,"isTile":true,"recent":1751296574180,"frequent":1},{"idnum":20299,"id":"X20299","images":"2.png","x":3,"y":37,"isTile":true,"recent":1751296473431,"frequent":2},{"idnum":20223,"id":"X20223","images":"2.png","x":7,"y":27,"isTile":true,"recent":1751296109900,"frequent":2},{"idnum":20231,"id":"X20231","images":"2.png","x":7,"y":28,"isTile":true,"recent":1751296107800,"frequent":3},{"idnum":20230,"id":"X20230","images":"2.png","x":6,"y":28,"isTile":true,"recent":1751296103030,"frequent":2},{"idnum":20083,"id":"X20083","images":"2.png","x":3,"y":10,"isTile":true,"recent":1751296098200,"frequent":1},{"idnum":20075,"id":"X20075","images":"2.png","x":3,"y":9,"isTile":true,"recent":1751296094038,"frequent":2},{"idnum":20067,"id":"X20067","images":"2.png","x":3,"y":8,"isTile":true,"recent":1751296089418,"frequent":2},{"idnum":20018,"id":"X20018","images":"2.png","x":2,"y":2,"isTile":true,"recent":1751296013269,"frequent":13},{"idnum":20195,"id":"X20195","images":"2.png","x":3,"y":24,"isTile":true,"recent":1751295874848,"frequent":22},{"idnum":20001,"id":"X20001","images":"2.png","x":1,"y":0,"isTile":true,"recent":1751295741729,"frequent":3},{"idnum":20209,"id":"X20209","images":"2.png","x":1,"y":26,"isTile":true,"recent":1751295695933,"frequent":7},{"idnum":20208,"id":"X20208","images":"2.png","x":0,"y":26,"isTile":true,"recent":1751295656730,"frequent":4},{"idnum":20210,"id":"X20210","images":"2.png","x":2,"y":26,"isTile":true,"recent":1751295648728,"frequent":1},{"idnum":20229,"id":"X20229","images":"2.png","x":5,"y":28,"isTile":true,"recent":1751295566466,"frequent":3},{"idnum":20066,"id":"X20066","images":"2.png","x":2,"y":8,"isTile":true,"recent":1751295561194,"frequent":1},{"idnum":20082,"id":"X20082","images":"2.png","x":2,"y":10,"isTile":true,"recent":1751295557556,"frequent":2},{"idnum":20074,"id":"X20074","images":"2.png","x":2,"y":9,"isTile":true,"recent":1751295555014,"frequent":3},{"idnum":20227,"id":"X20227","images":"2.png","x":3,"y":28,"isTile":true,"recent":1751295536114,"frequent":4},{"idnum":20072,"id":"X20072","images":"2.png","x":0,"y":9,"isTile":true,"recent":1751295445603,"frequent":5},{"idnum":20219,"id":"X20219","images":"2.png","x":3,"y":27,"isTile":true,"recent":1751295438013,"frequent":1},{"idnum":20222,"id":"X20222","images":"2.png","x":6,"y":27,"isTile":true,"recent":1751295422818,"frequent":2},{"idnum":20221,"id":"X20221","images":"2.png","x":5,"y":27,"isTile":true,"recent":1751295409925,"frequent":1},{"idnum":20241,"id":"X20241","images":"2.png","x":1,"y":30,"isTile":true,"recent":1751295311680,"frequent":1},{"idnum":20242,"id":"X20242","images":"2.png","x":2,"y":30,"isTile":true,"recent":1751295302111,"frequent":1},{"idnum":20240,"id":"X20240","images":"2.png","x":0,"y":30,"isTile":true,"recent":1751295283720,"frequent":4},{"idnum":20044,"id":"X20044","images":"2.png","x":4,"y":5,"isTile":true,"recent":1751294688204,"frequent":2},{"idnum":159,"id":"autotile20","images":"autotile","y":0,"recent":1751294307928,"frequent":1},{"idnum":20204,"id":"X20204","images":"2.png","x":4,"y":25,"isTile":true,"recent":1751294035817,"frequent":5},{"idnum":20298,"id":"X20298","images":"2.png","x":2,"y":37,"isTile":true,"recent":1751293984365,"frequent":1},{"idnum":20117,"id":"X20117","images":"2.png","x":5,"y":14,"isTile":true,"recent":1751293929577,"frequent":1},{"idnum":20179,"id":"X20179","images":"2.png","x":3,"y":22,"isTile":true,"recent":1751293467370,"frequent":3},{"idnum":20124,"id":"X20124","images":"2.png","x":4,"y":15,"isTile":true,"recent":1751293139382,"frequent":2},{"idnum":20125,"id":"X20125","images":"2.png","x":5,"y":15,"isTile":true,"recent":1751293136224,"frequent":1},{"idnum":20244,"id":"X20244","images":"2.png","x":4,"y":30,"isTile":true,"recent":1751293027638,"frequent":2},{"idnum":20252,"id":"X20252","images":"2.png","x":4,"y":31,"isTile":true,"recent":1751292940480,"frequent":2},{"idnum":20218,"id":"X20218","images":"2.png","x":2,"y":27,"isTile":true,"recent":1751292712004,"frequent":2},{"idnum":20194,"id":"X20194","images":"2.png","x":2,"y":24,"isTile":true,"recent":1751292700957,"frequent":1},{"idnum":1,"id":"yellowWall","images":"animates","y":10,"recent":1751291350769,"frequent":24},{"idnum":156,"id":"autotile17","images":"autotile","y":0,"recent":1751290710263,"frequent":5},{"idnum":174,"id":"autotile25","images":"autotile","y":0,"recent":1751290708103,"frequent":7},{"idnum":155,"id":"autotile16","images":"autotile","y":0,"recent":1751290693357,"frequent":3},{"idnum":178,"id":"autotile29","images":"autotile","y":0,"recent":1751290644944,"frequent":2},{"idnum":177,"id":"autotile28","images":"autotile","y":0,"recent":1751290641831,"frequent":2},{"idnum":176,"id":"autotile27","images":"autotile","y":0,"recent":1751290638315,"frequent":2},{"idnum":175,"id":"autotile26","images":"autotile","y":0,"recent":1751290630652,"frequent":4},{"idnum":187,"id":"autotile38","images":"autotile","y":0,"recent":1751290462067,"frequent":1},{"idnum":186,"id":"autotile37","images":"autotile","y":0,"recent":1751290458783,"frequent":1},{"idnum":147,"id":"autotile11","images":"autotile","y":0,"recent":1751290445770,"frequent":1},{"idnum":46,"id":"fly","images":"items","y":12,"recent":1751287655585,"frequent":1},{"idnum":20149,"id":"X20149","images":"2.png","x":5,"y":18,"isTile":true,"recent":1751287476693,"frequent":5},{"idnum":20050,"id":"X20050","images":"2.png","x":2,"y":6,"isTile":true,"recent":1751287425752,"frequent":1},{"idnum":34,"id":"yellowPotion","images":"items","y":23,"recent":1751287097810,"frequent":4},{"idnum":20137,"id":"X20137","images":"2.png","x":1,"y":17,"isTile":true,"recent":1751286497724,"frequent":2},{"idnum":20132,"id":"X20132","images":"2.png","x":4,"y":16,"isTile":true,"recent":1751286472877,"frequent":1},{"idnum":160,"id":"autotile21","images":"autotile","y":0,"recent":1751286105550,"frequent":10},{"idnum":20312,"id":"X20312","images":"2.png","x":0,"y":39,"isTile":true,"recent":1751285024981,"frequent":3},{"idnum":204,"id":"slimelord","images":"enemys","y":3,"recent":1751284913404,"frequent":1},{"idnum":20110,"id":"X20110","images":"2.png","x":6,"y":13,"isTile":true,"recent":1751284873458,"frequent":1},{"idnum":20057,"id":"X20057","images":"2.png","x":1,"y":7,"isTile":true,"recent":1751284563310,"frequent":2},{"idnum":20058,"id":"X20058","images":"2.png","x":2,"y":7,"isTile":true,"recent":1751284560324,"frequent":3},{"idnum":20255,"id":"X20255","images":"2.png","x":7,"y":31,"isTile":true,"recent":1751284381388,"frequent":1},{"idnum":20247,"id":"X20247","images":"2.png","x":7,"y":30,"isTile":true,"recent":1751284376949,"frequent":1},{"idnum":20304,"id":"X20304","images":"2.png","x":0,"y":38,"isTile":true,"recent":1751274087536,"frequent":1},{"idnum":20280,"id":"X20280","images":"2.png","x":0,"y":35,"isTile":true,"recent":1751274061721,"frequent":1},{"idnum":20224,"id":"X20224","images":"2.png","x":0,"y":28,"isTile":true,"recent":1751273995577,"frequent":5},{"idnum":20225,"id":"X20225","images":"2.png","x":1,"y":28,"isTile":true,"recent":1751273972057,"frequent":4},{"idnum":20226,"id":"X20226","images":"2.png","x":2,"y":28,"isTile":true,"recent":1751273928114,"frequent":1},{"idnum":20233,"id":"X20233","images":"2.png","x":1,"y":29,"isTile":true,"recent":1751273891108,"frequent":2},{"idnum":20234,"id":"X20234","images":"2.png","x":2,"y":29,"isTile":true,"recent":1751273840798,"frequent":1},{"idnum":20235,"id":"X20235","images":"2.png","x":3,"y":29,"isTile":true,"recent":1751273837476,"frequent":1},{"idnum":20,"id":"autotile","images":"autotile","y":0,"recent":1751273789070,"frequent":1},{"idnum":20161,"id":"X20161","images":"2.png","x":1,"y":20,"isTile":true,"recent":1751263270255,"frequent":1},{"idnum":20163,"id":"X20163","images":"2.png","x":3,"y":20,"isTile":true,"recent":1751261820316,"frequent":1},{"idnum":20056,"id":"X20056","images":"2.png","x":0,"y":7,"isTile":true,"recent":1751260326752,"frequent":1},{"idnum":20202,"id":"X20202","images":"2.png","x":2,"y":25,"isTile":true,"recent":1751260098697,"frequent":1},{"idnum":20089,"id":"X20089","images":"2.png","x":1,"y":11,"isTile":true,"recent":1751259818267,"frequent":1},{"idnum":20090,"id":"X20090","images":"2.png","x":2,"y":11,"isTile":true,"recent":1751259814772,"frequent":1},{"idnum":20096,"id":"X20096","images":"2.png","x":0,"y":12,"isTile":true,"recent":1751259811255,"frequent":1},{"idnum":20104,"id":"X20104","images":"2.png","x":0,"y":13,"isTile":true,"recent":1751259805922,"frequent":1},{"idnum":20097,"id":"X20097","images":"2.png","x":1,"y":12,"isTile":true,"recent":1751259797177,"frequent":1},{"idnum":20088,"id":"X20088","images":"2.png","x":0,"y":11,"isTile":true,"recent":1751259793930,"frequent":4},{"idnum":20080,"id":"X20080","images":"2.png","x":0,"y":10,"isTile":true,"recent":1751259786744,"frequent":4},{"idnum":20258,"id":"X20258","images":"2.png","x":2,"y":32,"isTile":true,"recent":1751204006380,"frequent":2},{"idnum":20274,"id":"X20274","images":"2.png","x":2,"y":34,"isTile":true,"recent":1751204002060,"frequent":3},{"idnum":20272,"id":"X20272","images":"2.png","x":0,"y":34,"isTile":true,"recent":1751203999083,"frequent":2},{"idnum":20273,"id":"X20273","images":"2.png","x":1,"y":34,"isTile":true,"recent":1751203981353,"frequent":2},{"idnum":20275,"id":"X20275","images":"2.png","x":3,"y":34,"isTile":true,"recent":1751203973831,"frequent":1},{"idnum":20259,"id":"X20259","images":"2.png","x":3,"y":32,"isTile":true,"recent":1751203783680,"frequent":1},{"idnum":20311,"id":"X20311","images":"2.png","x":7,"y":38,"isTile":true,"recent":1751203482400,"frequent":1},{"idnum":30011,"id":"X30011","images":"1.png","x":11,"y":0,"isTile":true,"recent":1751203433011,"frequent":4},{"idnum":20108,"id":"X20108","images":"2.png","x":4,"y":13,"isTile":true,"recent":1751203403010,"frequent":1},{"idnum":20302,"id":"X20302","images":"2.png","x":6,"y":37,"isTile":true,"recent":1751203197965,"frequent":1},{"idnum":20165,"id":"X20165","images":"2.png","x":5,"y":20,"isTile":true,"recent":1751203068483,"frequent":2},{"idnum":20173,"id":"X20173","images":"2.png","x":5,"y":21,"isTile":true,"recent":1751203065154,"frequent":2},{"idnum":30043,"id":"X30043","images":"1.png","x":11,"y":2,"isTile":true,"recent":1751202033615,"frequent":1},{"idnum":30173,"id":"X30173","images":"1.png","x":13,"y":10,"isTile":true,"recent":1751201992312,"frequent":2},{"idnum":146,"id":"autotile10","images":"autotile","y":0,"recent":1751201353192,"frequent":5},{"idnum":20142,"id":"X20142","images":"2.png","x":6,"y":17,"isTile":true,"recent":1751201341904,"frequent":2},{"idnum":30000,"id":"X30000","images":"1.png","x":0,"y":0,"isTile":true,"recent":1751201181808,"frequent":35,"istop":0},{"idnum":20167,"id":"X20167","images":"2.png","x":7,"y":20,"isTile":true,"recent":1751200995222,"frequent":1},{"idnum":20085,"id":"X20085","images":"2.png","x":5,"y":10,"isTile":true,"recent":1751200910345,"frequent":1},{"idnum":20266,"id":"X20266","images":"2.png","x":2,"y":33,"isTile":true,"recent":1751200757440,"frequent":1},{"idnum":20265,"id":"X20265","images":"2.png","x":1,"y":33,"isTile":true,"recent":1751200750938,"frequent":1},{"idnum":20257,"id":"X20257","images":"2.png","x":1,"y":32,"isTile":true,"recent":1751200749026,"frequent":4},{"idnum":20256,"id":"X20256","images":"2.png","x":0,"y":32,"isTile":true,"recent":1751200737468,"frequent":1},{"idnum":20217,"id":"X20217","images":"2.png","x":1,"y":27,"isTile":true,"recent":1751200516306,"frequent":6},{"idnum":20214,"id":"X20214","images":"2.png","x":6,"y":26,"isTile":true,"recent":1751200393597,"frequent":1},{"idnum":20043,"id":"X20043","images":"2.png","x":3,"y":5,"isTile":true,"recent":1751200264304,"frequent":1},{"idnum":20077,"id":"X20077","images":"2.png","x":5,"y":9,"isTile":true,"recent":1751200140876,"frequent":1},{"idnum":20069,"id":"X20069","images":"2.png","x":5,"y":8,"isTile":true,"recent":1751200138806,"frequent":1},{"idnum":20070,"id":"X20070","images":"2.png","x":6,"y":8,"isTile":true,"recent":1751200133414,"frequent":3},{"idnum":20078,"id":"X20078","images":"2.png","x":6,"y":9,"isTile":true,"recent":1751200125636,"frequent":1},{"idnum":20004,"id":"X20004","images":"2.png","x":4,"y":0,"isTile":true,"recent":1751199966634,"frequent":5},{"idnum":20005,"id":"X20005","images":"2.png","x":5,"y":0,"isTile":true,"recent":1751199964302,"frequent":6},{"idnum":20006,"id":"X20006","images":"2.png","x":6,"y":0,"isTile":true,"recent":1751199947374,"frequent":5},{"idnum":20014,"id":"X20014","images":"2.png","x":6,"y":1,"isTile":true,"recent":1751199944269,"frequent":6},{"idnum":20008,"id":"X20008","images":"2.png","x":0,"y":1,"isTile":true,"recent":1751199900658,"frequent":4},{"idnum":20013,"id":"X20013","images":"2.png","x":5,"y":1,"isTile":true,"recent":1751199877213,"frequent":3},{"idnum":20012,"id":"X20012","images":"2.png","x":4,"y":1,"isTile":true,"recent":1751199874331,"frequent":2},{"idnum":20011,"id":"X20011","images":"2.png","x":3,"y":1,"isTile":true,"recent":1751199870258,"frequent":5},{"idnum":20010,"id":"X20010","images":"2.png","x":2,"y":1,"isTile":true,"recent":1751199867701,"frequent":5},{"idnum":20031,"id":"X20031","images":"2.png","x":7,"y":3,"isTile":true,"recent":1751199792498,"frequent":4},{"idnum":185,"id":"autotile36","images":"autotile","y":0,"recent":1751199764665,"frequent":5},{"idnum":20081,"id":"X20081","images":"2.png","x":1,"y":10,"isTile":true,"recent":1751199585737,"frequent":1},{"idnum":20038,"id":"X20038","images":"2.png","x":6,"y":4,"isTile":true,"recent":1751199550936,"frequent":4},{"idnum":142,"id":"autotile6","images":"autotile","y":0,"recent":1751199357607,"frequent":15},{"idnum":10056,"id":"X10056","images":"magictower.png","x":0,"y":7,"isTile":true,"recent":1751199285539,"frequent":1,"istop":0},{"idnum":40032,"id":"X40032","images":"3.png","x":0,"y":4,"isTile":true,"recent":1751199110060,"frequent":1},{"idnum":40002,"id":"X40002","images":"3.png","x":2,"y":0,"isTile":true,"recent":1751199107555,"frequent":2},{"idnum":40001,"id":"X40001","images":"3.png","x":1,"y":0,"isTile":true,"recent":1751199105020,"frequent":2},{"idnum":30016,"id":"X30016","images":"1.png","x":0,"y":1,"isTile":true,"recent":1751199100715,"frequent":6},{"idnum":30050,"id":"X30050","images":"1.png","x":2,"y":3,"isTile":true,"recent":1751199037572,"frequent":1},{"idnum":20039,"id":"X20039","images":"2.png","x":7,"y":4,"isTile":true,"recent":1751041358488,"frequent":1},{"idnum":20037,"id":"X20037","images":"2.png","x":5,"y":4,"isTile":true,"recent":1751041353688,"frequent":1},{"idnum":211,"id":"skeletonCaptain","images":"enemys","y":10,"recent":1673440202872,"frequent":1}],"editor_multi.fontSize":14,"editorLastFloorId":"C0_B06","foldPerCol":50,"folded":true,"alertTileModeV2.7":true} \ No newline at end of file +{"viewportLoc":[0,0],"lastUsed":[{"idnum":20164,"id":"X20164","images":"2.png","x":4,"y":20,"isTile":true,"recent":1776857705177,"frequent":259},{"idnum":184,"id":"autotile35","images":"autotile","y":0,"recent":1776857694291,"frequent":240},{"idnum":20176,"id":"X20176","images":"2.png","x":0,"y":22,"isTile":true,"recent":1776857656109,"frequent":11},{"idnum":343,"id":"greenPotion2","images":"items","y":73,"recent":1776857277188,"frequent":2},{"idnum":342,"id":"yellowPotion2","images":"items","y":72,"recent":1776857274835,"frequent":2},{"idnum":341,"id":"bluePotion2","images":"items","y":71,"recent":1776857264609,"frequent":2},{"idnum":340,"id":"redPotion2","images":"items","y":70,"recent":1776857262165,"frequent":2},{"idnum":85,"id":"specialDoor","images":"animates","y":8,"recent":1776856176629,"frequent":1},{"idnum":74,"id":"yellowKey2","images":"items","y":62,"recent":1776854998632,"frequent":4},{"idnum":80,"id":"redKey3","images":"items","y":68,"recent":1776853587031,"frequent":2},{"idnum":141,"id":"autotile5","images":"autotile","y":0,"recent":1776848567879,"frequent":39},{"idnum":171,"id":"autotile22","images":"autotile","y":0,"recent":1776848554173,"frequent":39},{"idnum":182,"id":"autotile33","images":"autotile","y":0,"recent":1776847967238,"frequent":7},{"idnum":21,"id":"yellowKey","images":"items","y":0,"recent":1776781827350,"frequent":26},{"idnum":20143,"id":"X20143","images":"2.png","x":7,"y":17,"isTile":true,"recent":1776512715632,"frequent":6},{"idnum":20150,"id":"X20150","images":"2.png","x":6,"y":18,"isTile":true,"recent":1776512664076,"frequent":9},{"idnum":20133,"id":"X20133","images":"2.png","x":5,"y":16,"isTile":true,"recent":1776512643654,"frequent":6},{"idnum":20172,"id":"X20172","images":"2.png","x":4,"y":21,"isTile":true,"recent":1776512387522,"frequent":13},{"idnum":20084,"id":"X20084","images":"2.png","x":4,"y":10,"isTile":true,"recent":1776512245465,"frequent":2},{"idnum":20092,"id":"X20092","images":"2.png","x":4,"y":11,"isTile":true,"recent":1776512229522,"frequent":1},{"idnum":202,"id":"redSlime","images":"enemys","y":1,"recent":1776512150147,"frequent":24},{"idnum":32,"id":"bluePotion","images":"items","y":21,"recent":1776512046283,"frequent":18},{"idnum":31,"id":"redPotion","images":"items","y":20,"recent":1776512038429,"frequent":33},{"idnum":203,"id":"blackSlime","images":"enemys","y":2,"recent":1776512006297,"frequent":18},{"idnum":20130,"id":"X20130","images":"2.png","x":2,"y":16,"isTile":true,"recent":1766314641672,"frequent":12},{"idnum":20136,"id":"X20136","images":"2.png","x":0,"y":17,"isTile":true,"recent":1766314626879,"frequent":3},{"idnum":20155,"id":"X20155","images":"2.png","x":3,"y":19,"isTile":true,"recent":1766242567284,"frequent":2},{"idnum":92,"id":"leftPortal","images":"animates","y":24,"recent":1766242323340,"frequent":10},{"idnum":20129,"id":"X20129","images":"2.png","x":1,"y":16,"isTile":true,"recent":1766242240348,"frequent":11},{"idnum":20148,"id":"X20148","images":"2.png","x":4,"y":18,"isTile":true,"recent":1766242214972,"frequent":4},{"idnum":201,"id":"greenSlime","images":"enemys","y":0,"recent":1766242054491,"frequent":39},{"idnum":81,"id":"yellowDoor","images":"animates","y":4,"recent":1766242045915,"frequent":24},{"idnum":205,"id":"bat","images":"enemys","y":4,"recent":1766241989305,"frequent":16},{"idnum":20147,"id":"X20147","images":"2.png","x":3,"y":18,"isTile":true,"recent":1766241963088,"frequent":6},{"idnum":20139,"id":"X20139","images":"2.png","x":3,"y":17,"isTile":true,"recent":1766241957974,"frequent":3},{"idnum":20145,"id":"X20145","images":"2.png","x":1,"y":18,"isTile":true,"recent":1766241930214,"frequent":10},{"idnum":93,"id":"downPortal","images":"animates","y":23,"recent":1766241906074,"frequent":9},{"idnum":20035,"id":"X20035","images":"2.png","x":3,"y":4,"isTile":true,"recent":1766241873454,"frequent":9},{"idnum":20036,"id":"X20036","images":"2.png","x":4,"y":4,"isTile":true,"recent":1766241865762,"frequent":13},{"idnum":29,"id":"greenGem","images":"items","y":18,"recent":1766241712359,"frequent":12},{"idnum":27,"id":"redGem","images":"items","y":16,"recent":1766241704713,"frequent":11},{"idnum":94,"id":"rightPortal","images":"animates","y":25,"recent":1766241657340,"frequent":9},{"idnum":30,"id":"yellowGem","images":"items","y":19,"recent":1766241275091,"frequent":9},{"idnum":20154,"id":"X20154","images":"2.png","x":2,"y":19,"isTile":true,"recent":1766241194626,"frequent":1},{"idnum":20334,"id":"X20334","images":"2.png","x":6,"y":41,"isTile":true,"recent":1766241103417,"frequent":1},{"idnum":20316,"id":"X20316","images":"2.png","x":4,"y":39,"isTile":true,"recent":1766241089661,"frequent":1},{"idnum":20131,"id":"X20131","images":"2.png","x":3,"y":16,"isTile":true,"recent":1766241066196,"frequent":10},{"idnum":20166,"id":"X20166","images":"2.png","x":6,"y":20,"isTile":true,"recent":1766240988032,"frequent":8},{"idnum":20174,"id":"X20174","images":"2.png","x":6,"y":21,"isTile":true,"recent":1766240983106,"frequent":3},{"idnum":20169,"id":"X20169","images":"2.png","x":1,"y":21,"isTile":true,"recent":1766240962775,"frequent":4},{"idnum":28,"id":"blueGem","images":"items","y":17,"recent":1766240795831,"frequent":7},{"idnum":10215,"id":"X10215","images":"magictower.png","x":7,"y":26,"isTile":true,"recent":1766240735472,"frequent":4},{"idnum":82,"id":"blueDoor","images":"animates","y":5,"recent":1766240729469,"frequent":8},{"idnum":151,"id":"autotile1","images":"autotile","y":0,"recent":1766240566131,"frequent":173},{"idnum":20331,"id":"X20331","images":"2.png","x":3,"y":41,"isTile":true,"recent":1766240553709,"frequent":4},{"idnum":20141,"id":"X20141","images":"2.png","x":5,"y":17,"isTile":true,"recent":1766240534368,"frequent":7},{"idnum":20017,"id":"X20017","images":"2.png","x":1,"y":2,"isTile":true,"recent":1766240520573,"frequent":30},{"idnum":20177,"id":"X20177","images":"2.png","x":1,"y":22,"isTile":true,"recent":1766240514125,"frequent":9},{"idnum":20016,"id":"X20016","images":"2.png","x":0,"y":2,"isTile":true,"recent":1766240486491,"frequent":3},{"idnum":20360,"id":"X20360","images":"2.png","x":0,"y":45,"isTile":true,"recent":1766240400718,"frequent":4},{"idnum":20033,"id":"X20033","images":"2.png","x":1,"y":4,"isTile":true,"recent":1766240311250,"frequent":134},{"idnum":192,"id":"autotile43","images":"autotile","y":0,"recent":1766240179483,"frequent":19},{"idnum":20032,"id":"X20032","images":"2.png","x":0,"y":4,"isTile":true,"recent":1766239819484,"frequent":25},{"idnum":20028,"id":"X20028","images":"2.png","x":4,"y":3,"isTile":true,"recent":1766239742340,"frequent":12},{"idnum":20213,"id":"X20213","images":"2.png","x":5,"y":26,"isTile":true,"recent":1766239711340,"frequent":3},{"idnum":20040,"id":"X20040","images":"2.png","x":0,"y":5,"isTile":true,"recent":1766239554481,"frequent":16},{"idnum":20041,"id":"X20041","images":"2.png","x":1,"y":5,"isTile":true,"recent":1766239544668,"frequent":43},{"idnum":20200,"id":"X20200","images":"2.png","x":0,"y":25,"isTile":true,"recent":1766239537552,"frequent":4},{"idnum":20064,"id":"X20064","images":"2.png","x":0,"y":8,"isTile":true,"recent":1766239521936,"frequent":12},{"idnum":4,"id":"star","images":"animates","y":0,"recent":1766239387179,"frequent":4},{"idnum":305,"id":"grass","images":"terrains","y":1,"recent":1766239347385,"frequent":4},{"idnum":20160,"id":"X20160","images":"2.png","x":0,"y":20,"isTile":true,"recent":1766239240004,"frequent":4},{"idnum":20024,"id":"X20024","images":"2.png","x":0,"y":3,"isTile":true,"recent":1766239040023,"frequent":9},{"idnum":20052,"id":"X20052","images":"2.png","x":4,"y":6,"isTile":true,"recent":1766238874602,"frequent":1},{"idnum":20245,"id":"X20245","images":"2.png","x":5,"y":30,"isTile":true,"recent":1766238847081,"frequent":2},{"idnum":20180,"id":"X20180","images":"2.png","x":4,"y":22,"isTile":true,"recent":1766238833997,"frequent":7},{"idnum":20120,"id":"X20120","images":"2.png","x":0,"y":15,"isTile":true,"recent":1766238609644,"frequent":2},{"idnum":20135,"id":"X20135","images":"2.png","x":7,"y":16,"isTile":true,"recent":1766238554803,"frequent":7},{"idnum":20134,"id":"X20134","images":"2.png","x":6,"y":16,"isTile":true,"recent":1766238533819,"frequent":4},{"idnum":23,"id":"redKey","images":"items","y":2,"recent":1766237357121,"frequent":2},{"idnum":303,"id":"sWallR","images":"terrains","y":23,"recent":1756265573660,"frequent":1},{"idnum":20144,"id":"X20144","images":"2.png","x":0,"y":18,"isTile":true,"recent":1756265529340,"frequent":4},{"idnum":302,"id":"sWallL","images":"terrains","y":22,"recent":1756265497832,"frequent":17},{"idnum":20140,"id":"X20140","images":"2.png","x":4,"y":17,"isTile":true,"recent":1753774585698,"frequent":2},{"idnum":20332,"id":"X20332","images":"2.png","x":4,"y":41,"isTile":true,"recent":1753774524347,"frequent":1},{"idnum":20333,"id":"X20333","images":"2.png","x":5,"y":41,"isTile":true,"recent":1753774519578,"frequent":1},{"idnum":20303,"id":"X20303","images":"2.png","x":7,"y":37,"isTile":true,"recent":1753774455384,"frequent":3},{"idnum":20157,"id":"X20157","images":"2.png","x":5,"y":19,"isTile":true,"recent":1753774420471,"frequent":1},{"idnum":20156,"id":"X20156","images":"2.png","x":4,"y":19,"isTile":true,"recent":1753774407871,"frequent":3},{"idnum":20146,"id":"X20146","images":"2.png","x":2,"y":18,"isTile":true,"recent":1753774353142,"frequent":7},{"idnum":143,"id":"autotile7","images":"autotile","y":0,"recent":1753774091410,"frequent":6},{"idnum":144,"id":"autotile8","images":"autotile","y":0,"recent":1753773953432,"frequent":1},{"idnum":181,"id":"autotile32","images":"autotile","y":0,"recent":1753773925734,"frequent":4},{"idnum":173,"id":"autotile24","images":"autotile","y":0,"recent":1753773911798,"frequent":3},{"idnum":148,"id":"autotile12","images":"autotile","y":0,"recent":1753773893469,"frequent":2},{"idnum":20368,"id":"X20368","images":"2.png","x":0,"y":46,"isTile":true,"recent":1753632196387,"frequent":6},{"idnum":88,"id":"downFloor","images":"terrains","y":5,"recent":1753632181169,"frequent":1},{"idnum":87,"id":"upFloor","images":"terrains","y":6,"recent":1753632174063,"frequent":1},{"idnum":254,"id":"redSwordsman","images":"enemys","y":53,"recent":1753631421770,"frequent":2},{"idnum":45,"id":"book","images":"items","y":9,"recent":1753631118788,"frequent":1},{"idnum":129,"id":"sign","images":"npcs","y":8,"recent":1753610708012,"frequent":1},{"idnum":20306,"id":"X20306","images":"2.png","x":2,"y":38,"isTile":true,"recent":1753072252483,"frequent":6},{"idnum":20196,"id":"X20196","images":"2.png","x":4,"y":24,"isTile":true,"recent":1753072229938,"frequent":25},{"idnum":20026,"id":"X20026","images":"2.png","x":2,"y":3,"isTile":true,"recent":1752335493815,"frequent":31},{"idnum":20376,"id":"X20376","images":"2.png","x":0,"y":47,"isTile":true,"recent":1752069078126,"frequent":2},{"idnum":308,"id":"grass2","images":"terrains","y":2,"recent":1751793406519,"frequent":1},{"idnum":140,"id":"autotile4","images":"autotile","y":0,"recent":1751734041473,"frequent":65},{"idnum":20325,"id":"X20325","images":"2.png","x":5,"y":40,"isTile":true,"recent":1751733296580,"frequent":3},{"idnum":20317,"id":"X20317","images":"2.png","x":5,"y":39,"isTile":true,"recent":1751733293663,"frequent":4},{"idnum":20319,"id":"X20319","images":"2.png","x":7,"y":39,"isTile":true,"recent":1751733272003,"frequent":1},{"idnum":91,"id":"upPortal","images":"animates","y":26,"recent":1751732145191,"frequent":4},{"idnum":22,"id":"blueKey","images":"items","y":1,"recent":1751729533259,"frequent":4},{"idnum":189,"id":"autotile40","images":"autotile","y":0,"recent":1751729502284,"frequent":4},{"idnum":20369,"id":"X20369","images":"2.png","x":1,"y":46,"isTile":true,"recent":1751729296750,"frequent":2},{"idnum":20377,"id":"X20377","images":"2.png","x":1,"y":47,"isTile":true,"recent":1751729251037,"frequent":2},{"idnum":20361,"id":"X20361","images":"2.png","x":1,"y":45,"isTile":true,"recent":1751729242359,"frequent":2},{"idnum":191,"id":"autotile42","images":"autotile","y":0,"recent":1751729130841,"frequent":2},{"idnum":190,"id":"autotile41","images":"autotile","y":0,"recent":1751729127691,"frequent":6},{"idnum":20238,"id":"X20238","images":"2.png","x":6,"y":29,"isTile":true,"recent":1751728303355,"frequent":2},{"idnum":20236,"id":"X20236","images":"2.png","x":4,"y":29,"isTile":true,"recent":1751728295376,"frequent":2},{"idnum":20212,"id":"X20212","images":"2.png","x":4,"y":26,"isTile":true,"recent":1751728281575,"frequent":2},{"idnum":20019,"id":"X20019","images":"2.png","x":3,"y":2,"isTile":true,"recent":1751728241217,"frequent":2},{"idnum":188,"id":"autotile39","images":"autotile","y":0,"recent":1751727929573,"frequent":13},{"idnum":121,"id":"man","images":"npcs","y":0,"recent":1751646123653,"frequent":4},{"idnum":180,"id":"autotile31","images":"autotile","y":0,"recent":1751645997658,"frequent":60},{"idnum":20138,"id":"X20138","images":"2.png","x":2,"y":17,"isTile":true,"recent":1751645672326,"frequent":9},{"idnum":150,"id":"autotile14","images":"autotile","y":0,"recent":1751644554451,"frequent":10},{"idnum":179,"id":"autotile30","images":"autotile","y":0,"recent":1751355356118,"frequent":18},{"idnum":20284,"id":"X20284","images":"2.png","x":4,"y":35,"isTile":true,"recent":1751355312181,"frequent":2},{"idnum":20297,"id":"X20297","images":"2.png","x":1,"y":37,"isTile":true,"recent":1751355248416,"frequent":2},{"idnum":20321,"id":"X20321","images":"2.png","x":1,"y":40,"isTile":true,"recent":1751355245971,"frequent":1},{"idnum":20296,"id":"X20296","images":"2.png","x":0,"y":37,"isTile":true,"recent":1751355235868,"frequent":3},{"idnum":20320,"id":"X20320","images":"2.png","x":0,"y":40,"isTile":true,"recent":1751355222886,"frequent":2},{"idnum":20328,"id":"X20328","images":"2.png","x":0,"y":41,"isTile":true,"recent":1751355208703,"frequent":1},{"idnum":20025,"id":"X20025","images":"2.png","x":1,"y":3,"isTile":true,"recent":1751355030014,"frequent":9},{"idnum":20034,"id":"X20034","images":"2.png","x":2,"y":4,"isTile":true,"recent":1751355016737,"frequent":40},{"idnum":20042,"id":"X20042","images":"2.png","x":2,"y":5,"isTile":true,"recent":1751354986114,"frequent":26},{"idnum":20260,"id":"X20260","images":"2.png","x":4,"y":32,"isTile":true,"recent":1751354981826,"frequent":1},{"idnum":20268,"id":"X20268","images":"2.png","x":4,"y":33,"isTile":true,"recent":1751354971399,"frequent":3},{"idnum":20178,"id":"X20178","images":"2.png","x":2,"y":22,"isTile":true,"recent":1751354514329,"frequent":9},{"idnum":20126,"id":"X20126","images":"2.png","x":6,"y":15,"isTile":true,"recent":1751298630823,"frequent":2},{"idnum":20127,"id":"X20127","images":"2.png","x":7,"y":15,"isTile":true,"recent":1751297554068,"frequent":1},{"idnum":20027,"id":"X20027","images":"2.png","x":3,"y":3,"isTile":true,"recent":1751297516808,"frequent":3},{"idnum":20020,"id":"X20020","images":"2.png","x":4,"y":2,"isTile":true,"recent":1751297395193,"frequent":2},{"idnum":20187,"id":"X20187","images":"2.png","x":3,"y":23,"isTile":true,"recent":1751297343385,"frequent":36},{"idnum":20300,"id":"X20300","images":"2.png","x":4,"y":37,"isTile":true,"recent":1751296676841,"frequent":7},{"idnum":20308,"id":"X20308","images":"2.png","x":4,"y":38,"isTile":true,"recent":1751296667698,"frequent":2},{"idnum":20309,"id":"X20309","images":"2.png","x":5,"y":38,"isTile":true,"recent":1751296579393,"frequent":1},{"idnum":20301,"id":"X20301","images":"2.png","x":5,"y":37,"isTile":true,"recent":1751296574180,"frequent":1},{"idnum":20299,"id":"X20299","images":"2.png","x":3,"y":37,"isTile":true,"recent":1751296473431,"frequent":2},{"idnum":20223,"id":"X20223","images":"2.png","x":7,"y":27,"isTile":true,"recent":1751296109900,"frequent":2},{"idnum":20231,"id":"X20231","images":"2.png","x":7,"y":28,"isTile":true,"recent":1751296107800,"frequent":3},{"idnum":20230,"id":"X20230","images":"2.png","x":6,"y":28,"isTile":true,"recent":1751296103030,"frequent":2},{"idnum":20083,"id":"X20083","images":"2.png","x":3,"y":10,"isTile":true,"recent":1751296098200,"frequent":1},{"idnum":20075,"id":"X20075","images":"2.png","x":3,"y":9,"isTile":true,"recent":1751296094038,"frequent":2},{"idnum":20067,"id":"X20067","images":"2.png","x":3,"y":8,"isTile":true,"recent":1751296089418,"frequent":2},{"idnum":20018,"id":"X20018","images":"2.png","x":2,"y":2,"isTile":true,"recent":1751296013269,"frequent":13},{"idnum":20195,"id":"X20195","images":"2.png","x":3,"y":24,"isTile":true,"recent":1751295874848,"frequent":22},{"idnum":20001,"id":"X20001","images":"2.png","x":1,"y":0,"isTile":true,"recent":1751295741729,"frequent":3},{"idnum":20209,"id":"X20209","images":"2.png","x":1,"y":26,"isTile":true,"recent":1751295695933,"frequent":7},{"idnum":20208,"id":"X20208","images":"2.png","x":0,"y":26,"isTile":true,"recent":1751295656730,"frequent":4},{"idnum":20210,"id":"X20210","images":"2.png","x":2,"y":26,"isTile":true,"recent":1751295648728,"frequent":1},{"idnum":20229,"id":"X20229","images":"2.png","x":5,"y":28,"isTile":true,"recent":1751295566466,"frequent":3},{"idnum":20066,"id":"X20066","images":"2.png","x":2,"y":8,"isTile":true,"recent":1751295561194,"frequent":1},{"idnum":20082,"id":"X20082","images":"2.png","x":2,"y":10,"isTile":true,"recent":1751295557556,"frequent":2},{"idnum":20074,"id":"X20074","images":"2.png","x":2,"y":9,"isTile":true,"recent":1751295555014,"frequent":3},{"idnum":20227,"id":"X20227","images":"2.png","x":3,"y":28,"isTile":true,"recent":1751295536114,"frequent":4},{"idnum":20072,"id":"X20072","images":"2.png","x":0,"y":9,"isTile":true,"recent":1751295445603,"frequent":5},{"idnum":20219,"id":"X20219","images":"2.png","x":3,"y":27,"isTile":true,"recent":1751295438013,"frequent":1},{"idnum":20222,"id":"X20222","images":"2.png","x":6,"y":27,"isTile":true,"recent":1751295422818,"frequent":2},{"idnum":20221,"id":"X20221","images":"2.png","x":5,"y":27,"isTile":true,"recent":1751295409925,"frequent":1},{"idnum":20241,"id":"X20241","images":"2.png","x":1,"y":30,"isTile":true,"recent":1751295311680,"frequent":1},{"idnum":20242,"id":"X20242","images":"2.png","x":2,"y":30,"isTile":true,"recent":1751295302111,"frequent":1},{"idnum":20240,"id":"X20240","images":"2.png","x":0,"y":30,"isTile":true,"recent":1751295283720,"frequent":4},{"idnum":20044,"id":"X20044","images":"2.png","x":4,"y":5,"isTile":true,"recent":1751294688204,"frequent":2},{"idnum":159,"id":"autotile20","images":"autotile","y":0,"recent":1751294307928,"frequent":1},{"idnum":20204,"id":"X20204","images":"2.png","x":4,"y":25,"isTile":true,"recent":1751294035817,"frequent":5},{"idnum":20298,"id":"X20298","images":"2.png","x":2,"y":37,"isTile":true,"recent":1751293984365,"frequent":1},{"idnum":20117,"id":"X20117","images":"2.png","x":5,"y":14,"isTile":true,"recent":1751293929577,"frequent":1},{"idnum":20179,"id":"X20179","images":"2.png","x":3,"y":22,"isTile":true,"recent":1751293467370,"frequent":3},{"idnum":20124,"id":"X20124","images":"2.png","x":4,"y":15,"isTile":true,"recent":1751293139382,"frequent":2},{"idnum":20125,"id":"X20125","images":"2.png","x":5,"y":15,"isTile":true,"recent":1751293136224,"frequent":1},{"idnum":20244,"id":"X20244","images":"2.png","x":4,"y":30,"isTile":true,"recent":1751293027638,"frequent":2},{"idnum":20252,"id":"X20252","images":"2.png","x":4,"y":31,"isTile":true,"recent":1751292940480,"frequent":2},{"idnum":20218,"id":"X20218","images":"2.png","x":2,"y":27,"isTile":true,"recent":1751292712004,"frequent":2},{"idnum":20194,"id":"X20194","images":"2.png","x":2,"y":24,"isTile":true,"recent":1751292700957,"frequent":1},{"idnum":1,"id":"yellowWall","images":"animates","y":10,"recent":1751291350769,"frequent":24},{"idnum":156,"id":"autotile17","images":"autotile","y":0,"recent":1751290710263,"frequent":5},{"idnum":174,"id":"autotile25","images":"autotile","y":0,"recent":1751290708103,"frequent":7},{"idnum":155,"id":"autotile16","images":"autotile","y":0,"recent":1751290693357,"frequent":3},{"idnum":178,"id":"autotile29","images":"autotile","y":0,"recent":1751290644944,"frequent":2},{"idnum":177,"id":"autotile28","images":"autotile","y":0,"recent":1751290641831,"frequent":2},{"idnum":176,"id":"autotile27","images":"autotile","y":0,"recent":1751290638315,"frequent":2},{"idnum":175,"id":"autotile26","images":"autotile","y":0,"recent":1751290630652,"frequent":4},{"idnum":187,"id":"autotile38","images":"autotile","y":0,"recent":1751290462067,"frequent":1},{"idnum":186,"id":"autotile37","images":"autotile","y":0,"recent":1751290458783,"frequent":1},{"idnum":147,"id":"autotile11","images":"autotile","y":0,"recent":1751290445770,"frequent":1},{"idnum":46,"id":"fly","images":"items","y":12,"recent":1751287655585,"frequent":1},{"idnum":20149,"id":"X20149","images":"2.png","x":5,"y":18,"isTile":true,"recent":1751287476693,"frequent":5},{"idnum":20050,"id":"X20050","images":"2.png","x":2,"y":6,"isTile":true,"recent":1751287425752,"frequent":1},{"idnum":34,"id":"yellowPotion","images":"items","y":23,"recent":1751287097810,"frequent":4},{"idnum":20137,"id":"X20137","images":"2.png","x":1,"y":17,"isTile":true,"recent":1751286497724,"frequent":2},{"idnum":20132,"id":"X20132","images":"2.png","x":4,"y":16,"isTile":true,"recent":1751286472877,"frequent":1},{"idnum":160,"id":"autotile21","images":"autotile","y":0,"recent":1751286105550,"frequent":10},{"idnum":20312,"id":"X20312","images":"2.png","x":0,"y":39,"isTile":true,"recent":1751285024981,"frequent":3},{"idnum":204,"id":"slimelord","images":"enemys","y":3,"recent":1751284913404,"frequent":1},{"idnum":20110,"id":"X20110","images":"2.png","x":6,"y":13,"isTile":true,"recent":1751284873458,"frequent":1},{"idnum":20057,"id":"X20057","images":"2.png","x":1,"y":7,"isTile":true,"recent":1751284563310,"frequent":2},{"idnum":20058,"id":"X20058","images":"2.png","x":2,"y":7,"isTile":true,"recent":1751284560324,"frequent":3},{"idnum":20255,"id":"X20255","images":"2.png","x":7,"y":31,"isTile":true,"recent":1751284381388,"frequent":1},{"idnum":20247,"id":"X20247","images":"2.png","x":7,"y":30,"isTile":true,"recent":1751284376949,"frequent":1},{"idnum":20304,"id":"X20304","images":"2.png","x":0,"y":38,"isTile":true,"recent":1751274087536,"frequent":1},{"idnum":20280,"id":"X20280","images":"2.png","x":0,"y":35,"isTile":true,"recent":1751274061721,"frequent":1},{"idnum":20224,"id":"X20224","images":"2.png","x":0,"y":28,"isTile":true,"recent":1751273995577,"frequent":5},{"idnum":20225,"id":"X20225","images":"2.png","x":1,"y":28,"isTile":true,"recent":1751273972057,"frequent":4},{"idnum":20226,"id":"X20226","images":"2.png","x":2,"y":28,"isTile":true,"recent":1751273928114,"frequent":1},{"idnum":20233,"id":"X20233","images":"2.png","x":1,"y":29,"isTile":true,"recent":1751273891108,"frequent":2},{"idnum":20234,"id":"X20234","images":"2.png","x":2,"y":29,"isTile":true,"recent":1751273840798,"frequent":1},{"idnum":20235,"id":"X20235","images":"2.png","x":3,"y":29,"isTile":true,"recent":1751273837476,"frequent":1},{"idnum":20,"id":"autotile","images":"autotile","y":0,"recent":1751273789070,"frequent":1},{"idnum":20161,"id":"X20161","images":"2.png","x":1,"y":20,"isTile":true,"recent":1751263270255,"frequent":1},{"idnum":20163,"id":"X20163","images":"2.png","x":3,"y":20,"isTile":true,"recent":1751261820316,"frequent":1},{"idnum":20056,"id":"X20056","images":"2.png","x":0,"y":7,"isTile":true,"recent":1751260326752,"frequent":1},{"idnum":20202,"id":"X20202","images":"2.png","x":2,"y":25,"isTile":true,"recent":1751260098697,"frequent":1},{"idnum":20089,"id":"X20089","images":"2.png","x":1,"y":11,"isTile":true,"recent":1751259818267,"frequent":1},{"idnum":20090,"id":"X20090","images":"2.png","x":2,"y":11,"isTile":true,"recent":1751259814772,"frequent":1},{"idnum":20096,"id":"X20096","images":"2.png","x":0,"y":12,"isTile":true,"recent":1751259811255,"frequent":1},{"idnum":20104,"id":"X20104","images":"2.png","x":0,"y":13,"isTile":true,"recent":1751259805922,"frequent":1},{"idnum":20097,"id":"X20097","images":"2.png","x":1,"y":12,"isTile":true,"recent":1751259797177,"frequent":1},{"idnum":20088,"id":"X20088","images":"2.png","x":0,"y":11,"isTile":true,"recent":1751259793930,"frequent":4},{"idnum":20080,"id":"X20080","images":"2.png","x":0,"y":10,"isTile":true,"recent":1751259786744,"frequent":4},{"idnum":20258,"id":"X20258","images":"2.png","x":2,"y":32,"isTile":true,"recent":1751204006380,"frequent":2},{"idnum":20274,"id":"X20274","images":"2.png","x":2,"y":34,"isTile":true,"recent":1751204002060,"frequent":3},{"idnum":20272,"id":"X20272","images":"2.png","x":0,"y":34,"isTile":true,"recent":1751203999083,"frequent":2},{"idnum":20273,"id":"X20273","images":"2.png","x":1,"y":34,"isTile":true,"recent":1751203981353,"frequent":2},{"idnum":20275,"id":"X20275","images":"2.png","x":3,"y":34,"isTile":true,"recent":1751203973831,"frequent":1},{"idnum":20259,"id":"X20259","images":"2.png","x":3,"y":32,"isTile":true,"recent":1751203783680,"frequent":1},{"idnum":20311,"id":"X20311","images":"2.png","x":7,"y":38,"isTile":true,"recent":1751203482400,"frequent":1},{"idnum":30011,"id":"X30011","images":"1.png","x":11,"y":0,"isTile":true,"recent":1751203433011,"frequent":4},{"idnum":20108,"id":"X20108","images":"2.png","x":4,"y":13,"isTile":true,"recent":1751203403010,"frequent":1},{"idnum":20302,"id":"X20302","images":"2.png","x":6,"y":37,"isTile":true,"recent":1751203197965,"frequent":1},{"idnum":20165,"id":"X20165","images":"2.png","x":5,"y":20,"isTile":true,"recent":1751203068483,"frequent":2},{"idnum":20173,"id":"X20173","images":"2.png","x":5,"y":21,"isTile":true,"recent":1751203065154,"frequent":2},{"idnum":30043,"id":"X30043","images":"1.png","x":11,"y":2,"isTile":true,"recent":1751202033615,"frequent":1},{"idnum":30173,"id":"X30173","images":"1.png","x":13,"y":10,"isTile":true,"recent":1751201992312,"frequent":2},{"idnum":146,"id":"autotile10","images":"autotile","y":0,"recent":1751201353192,"frequent":5},{"idnum":20142,"id":"X20142","images":"2.png","x":6,"y":17,"isTile":true,"recent":1751201341904,"frequent":2},{"idnum":30000,"id":"X30000","images":"1.png","x":0,"y":0,"isTile":true,"recent":1751201181808,"frequent":35,"istop":0},{"idnum":20167,"id":"X20167","images":"2.png","x":7,"y":20,"isTile":true,"recent":1751200995222,"frequent":1},{"idnum":20085,"id":"X20085","images":"2.png","x":5,"y":10,"isTile":true,"recent":1751200910345,"frequent":1},{"idnum":20266,"id":"X20266","images":"2.png","x":2,"y":33,"isTile":true,"recent":1751200757440,"frequent":1},{"idnum":20265,"id":"X20265","images":"2.png","x":1,"y":33,"isTile":true,"recent":1751200750938,"frequent":1},{"idnum":20257,"id":"X20257","images":"2.png","x":1,"y":32,"isTile":true,"recent":1751200749026,"frequent":4},{"idnum":20256,"id":"X20256","images":"2.png","x":0,"y":32,"isTile":true,"recent":1751200737468,"frequent":1},{"idnum":20217,"id":"X20217","images":"2.png","x":1,"y":27,"isTile":true,"recent":1751200516306,"frequent":6},{"idnum":20214,"id":"X20214","images":"2.png","x":6,"y":26,"isTile":true,"recent":1751200393597,"frequent":1},{"idnum":20043,"id":"X20043","images":"2.png","x":3,"y":5,"isTile":true,"recent":1751200264304,"frequent":1},{"idnum":20077,"id":"X20077","images":"2.png","x":5,"y":9,"isTile":true,"recent":1751200140876,"frequent":1},{"idnum":20069,"id":"X20069","images":"2.png","x":5,"y":8,"isTile":true,"recent":1751200138806,"frequent":1},{"idnum":20070,"id":"X20070","images":"2.png","x":6,"y":8,"isTile":true,"recent":1751200133414,"frequent":3},{"idnum":20078,"id":"X20078","images":"2.png","x":6,"y":9,"isTile":true,"recent":1751200125636,"frequent":1},{"idnum":20004,"id":"X20004","images":"2.png","x":4,"y":0,"isTile":true,"recent":1751199966634,"frequent":5},{"idnum":20005,"id":"X20005","images":"2.png","x":5,"y":0,"isTile":true,"recent":1751199964302,"frequent":6},{"idnum":20006,"id":"X20006","images":"2.png","x":6,"y":0,"isTile":true,"recent":1751199947374,"frequent":5},{"idnum":20014,"id":"X20014","images":"2.png","x":6,"y":1,"isTile":true,"recent":1751199944269,"frequent":6},{"idnum":20008,"id":"X20008","images":"2.png","x":0,"y":1,"isTile":true,"recent":1751199900658,"frequent":4},{"idnum":20013,"id":"X20013","images":"2.png","x":5,"y":1,"isTile":true,"recent":1751199877213,"frequent":3},{"idnum":20012,"id":"X20012","images":"2.png","x":4,"y":1,"isTile":true,"recent":1751199874331,"frequent":2},{"idnum":20011,"id":"X20011","images":"2.png","x":3,"y":1,"isTile":true,"recent":1751199870258,"frequent":5},{"idnum":20010,"id":"X20010","images":"2.png","x":2,"y":1,"isTile":true,"recent":1751199867701,"frequent":5},{"idnum":20031,"id":"X20031","images":"2.png","x":7,"y":3,"isTile":true,"recent":1751199792498,"frequent":4},{"idnum":185,"id":"autotile36","images":"autotile","y":0,"recent":1751199764665,"frequent":5},{"idnum":20081,"id":"X20081","images":"2.png","x":1,"y":10,"isTile":true,"recent":1751199585737,"frequent":1},{"idnum":20038,"id":"X20038","images":"2.png","x":6,"y":4,"isTile":true,"recent":1751199550936,"frequent":4},{"idnum":142,"id":"autotile6","images":"autotile","y":0,"recent":1751199357607,"frequent":15},{"idnum":10056,"id":"X10056","images":"magictower.png","x":0,"y":7,"isTile":true,"recent":1751199285539,"frequent":1,"istop":0},{"idnum":40032,"id":"X40032","images":"3.png","x":0,"y":4,"isTile":true,"recent":1751199110060,"frequent":1},{"idnum":40002,"id":"X40002","images":"3.png","x":2,"y":0,"isTile":true,"recent":1751199107555,"frequent":2},{"idnum":40001,"id":"X40001","images":"3.png","x":1,"y":0,"isTile":true,"recent":1751199105020,"frequent":2},{"idnum":30016,"id":"X30016","images":"1.png","x":0,"y":1,"isTile":true,"recent":1751199100715,"frequent":6},{"idnum":30050,"id":"X30050","images":"1.png","x":2,"y":3,"isTile":true,"recent":1751199037572,"frequent":1},{"idnum":20039,"id":"X20039","images":"2.png","x":7,"y":4,"isTile":true,"recent":1751041358488,"frequent":1},{"idnum":20037,"id":"X20037","images":"2.png","x":5,"y":4,"isTile":true,"recent":1751041353688,"frequent":1},{"idnum":211,"id":"skeletonCaptain","images":"enemys","y":10,"recent":1673440202872,"frequent":1}],"editor_multi.fontSize":14,"editorLastFloorId":"C0_T01","foldPerCol":50,"folded":true,"alertTileModeV2.7":true} \ No newline at end of file diff --git a/_server/editor_blocklyconfig.js b/_server/editor_blocklyconfig.js index 5d95776..e973a55 100644 --- a/_server/editor_blocklyconfig.js +++ b/_server/editor_blocklyconfig.js @@ -158,6 +158,7 @@ editor_blocklyconfig=(function(){ MotaActionBlocks['setBlockFilter_s'].xmlText(), MotaActionBlocks['turnBlock_s'].xmlText(), MotaActionBlocks['moveHero_s'].xmlText(), + MotaActionBlocks['moveHeroMapTurn_s'].xmlText(), MotaActionBlocks['move_s'].xmlText(), MotaActionBlocks['jumpHero_s'].xmlText(), MotaActionBlocks['jumpHero_1_s'].xmlText(), diff --git a/claude.md b/claude.md new file mode 100644 index 0000000..3167605 --- /dev/null +++ b/claude.md @@ -0,0 +1,77 @@ +# Claude Project Memory + +## 1. 项目定位(长期不变) + +- 项目类型:魔塔Like(固定地图探索 + 数值驱动 + 剧情导向 + 解谜)。 +- 目标体量:按原定体量推进,不主动缩减世界观与章节目标。 +- 开发模式:代码主力由 AI 完成;人工主要负责美工、地图、剧情、体验验收与方向裁决。 +- 当前基础:塔的基础结构已完成,支持正常战斗与可视化地图修改。 + +## 2. 当前开发优先级(默认顺序) + +1. 地图回合时轴(Map Turn)剩余接线与稳定性。 +2. 回档系统(状态继承、存读档一致性)。 +3. 敌人可相互战斗与伤害。 +4. 玩家多角色(队友/阵容)系统。 + +> 未经明确指令,不要跳级并行实现高风险模块。 + +## 3. 规则来源与冲突处理 + +- 机制规则唯一口径:`docs/map-turn-spec.md` +- 代码落地状态台账:`docs/map-turn-implementation-status.md` +- 协作与开发边界:本文件 `claude.md` +- 若规则冲突:先列出冲突点与影响,不擅自改规则,等待用户裁决。 + +## 4. 开发硬约束(来自 DEVELOPMENT_RULES 共识) + +1. 新功能默认写在 `project/plugins.js`。 +2. 优先使用 `_docs/api.md` 中的样板接口实现需求。 +3. 所有绘制基于 `core.createCanvas` 体系。 +4. 所有异步流程基于 `core.insertAction`(含 function/async 事件流)。 +5. 使用非样板接口时,必须就地注释:用途、原因、风险。 +6. 不直接改动 `libs/` 与 `main.js` 等核心底层文件,除非用户明确授权。 +7. 不直接破坏核心运行态结构(如整体替换 `core.status` / `core.material`)。 + +## 5. Map Turn 专项原则(必须遵守) + +- 单一时间总线:时间推进统一走 `consumeTime(deltaTime, reason)`。 +- 单 tick 语义:`deltaTime = n` 必须触发恰好 `n` 次 `advanceMapTurnOne`。 +- 规则优先级:死亡流程优先、战后成功再扣层、状态技能 `timeCost=0` 不推进时间。 +- 耗时规则:`battleFinalTimeCost = max(baseBattleTimeCost, statusBattleTimeCostMax)`。 +- 性能底线:每 tick 禁止全图扫描;敌方调度仅遍历 `activeEnemiesByFloor` 缓存。 +- 存档一致:`flags.mapTurnState` 与 `flags.skillState` 保持可序列化并可恢复。 +- 缓存策略:`activeEnemiesByFloor` 作为派生缓存,读档或换层后允许重建。 + +## 6. AI 输出与执行格式 + +每次任务默认按以下顺序输出: + +1. 先给结论(本次做什么/不做什么)。 +2. 给改动范围(文件与模块)。 +3. 对齐到规则(引用 `map-turn-spec.md` / 台账条目)。 +4. 给最小验证步骤(可复现、可回归)。 +5. 若有风险,给 1-2 条可选方案并标出推荐项。 + +## 7. 验收偏好 + +- 优先级:正确性与可验证性 > 写法优雅。 +- 关键机制必须可回归验证(如 `consumeTime(3)` 的 3 tick 断言、战后扣层、读档连续、`timeCost=0` 过滤)。 +- 遇到不确定行为,先加可观测日志/断言,再做进一步改动。 + +## 8. Git 与协作习惯 + +- 已使用 Git;改动应保持小步、可读、可回退。 +- 未经明确要求,不做破坏性历史操作(如强推、硬重置)。 +- 不覆盖与当前任务无关的既有改动。 + +## 9. 调用短语约定 + +当用户说“按 claude 执行”时,AI 必须默认执行: + +1. 先复述目标与当前阶段优先级。 +2. 明确本次任务对应哪个优先级模块。 +3. 检查是否违反第 4、5 节约束。 +4. 输出最小可执行步骤,再开始实现。 + +当用户说“先讨论不改代码”时,AI 只给方案,不做实现。 diff --git a/docs/map-turn-implementation-status.md b/docs/map-turn-implementation-status.md new file mode 100644 index 0000000..777fe3a --- /dev/null +++ b/docs/map-turn-implementation-status.md @@ -0,0 +1,106 @@ +# 地图回合实现进度(台账) + +本文档记录**代码已落地内容**与**待接线任务**,便于在对话上下文变长时单独查阅。规则、伪代码与冻结优先级以 [map-turn-spec.md](map-turn-spec.md) 为唯一口径;本文不写新规则,只写状态与文件指针。**`patch` / `rebuild` / `performEnemyAction` 等与实现对齐的契约说明**见规范 **§6.2、§6.3、§6.7**。 + +--- + +## 1. 已完成(截至当前仓库) + +### 1.1 数据表(`timeCost` 默认 `null`) + +| 区域 | 说明 | +|------|------| +| [project/items.js](../project/items.js) | 每条道具在 `"cls"` 下一行含 **`"timeCost": null`**;需消耗地图时间时改为正整数。 | +| [project/enemys.js](../project/enemys.js) | 每条怪物在 **`point` 与 `special` 之间**含 **`"timeCost": null`**。 | +| `enemy48` | 与 `enemys` 共用 **`core.material.enemys`** 数值,**无**独立 `libs/enemys48.js` 数据表。 | + +### 1.2 引擎初始化缺省补全 + +| 文件 | 行为 | +|------|------| +| [libs/items.js](../libs/items.js) `items.prototype._init` | 若道具 **`timeCost === undefined`**,补 **`timeCost: null`**(含编辑器新注册道具漏字段)。 | +| [libs/enemys.js](../libs/enemys.js) `enemys.prototype._init` | 若怪物 **`timeCost === undefined`**,补 **`timeCost: null`**。 | + +### 1.3 使用道具推进地图时间 + +| 文件 | 行为 | +|------|------| +| [libs/items.js](../libs/items.js) `items.prototype.useItem` | 在 **`_useItemEffect`** 之后:若 **`typeof timeCost === "number"` 且 `> 0`**,且存在 **`core.plugin.mapTurn.consumeTime`**,则调用 **`consumeTime(_tc, "item:" + itemId)`**。`null` 或非正数不推进。 | + +### 1.4 插件:`core.plugin.mapTurn` + +| 文件 | 说明 | +|------|------| +| [project/plugins.js](../project/plugins.js) 插件键 **`"mapTurn"`** | 挂载 **`this.mapTurn = { ... }`**,对外即 **`core.plugin.mapTurn.*`**。 | + +已实现的 API(名称与 [map-turn-spec.md](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)`**:已挂载;初版 **`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`** 的包装调用。 +- **`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)。 +- **`applyStatusAfterBattle` / `clearOnDeath`**:已按规范 §6.5–6.6 操作 **`flags.skillState`**(经 **`core.getFlag` / `core.setFlag`** 维护的 **`mapTurnState` / `skillState`** 结构)。 + +### 1.5 编辑器 / 新素材注册 + +| 文件 | 说明 | +|------|------| +| [_server/table/comment.js](../_server/table/comment.js) | 道具表、怪物表增加 **`timeCost`** 列说明;**`items_template`** / **`enemys_template`** 含 **`timeCost: null`**,新建行时带该字段。 | + +### 1.6 当前接线口径补充(2026-04) + +- **总开关开启时机**:已在 [project/data.js](../project/data.js) 的 **`startText` 前两条**:**`setValue`** 写入 **`flag:mapTurnEnabled`** 为真,再 **`bootstrapPersistedState()`** 补齐结构。开关存于存档,读档后随存档恢复。 +- **首次触发路径约束**:新开局统一经过 `startText` 写入总开关;读档后由 [project/functions.js](../project/functions.js) **`loadData`** 调用 **`bootstrapPersistedState()`** 与存档中的 **`mapTurnEnabled`** 对齐。 +- **演出移动与地图回合**:事件编辑器「地图处理」中在「无视地形移动勇士」下增加图块 **「移动勇者」**(JSON `type`: **`moveHeroMapTurn`**)。运行时由 [libs/events.js](../libs/events.js) **`_action_moveHeroMapTurn`** 将路径拆成每格一次 `eventMoveHero`,每格落点后 **`consumeTime(1, "event:moveHeroMapTurn")`**(`speed:` 与 `:0` 段不扣时)。语法见 [_server/MotaAction.g4](../_server/MotaAction.g4) `moveHeroMapTurn_s`。 +- **分层相对回合约定**:`mapTurn` 以楼层相对值使用;**普通切层**后当前层回合计数按 `0` 起算。**读档**导致的换层(`__fromLoad__` 为真)不归零,以保持与存档一致。`clock` 可继续作为全局累计观测值。 + +--- + +## 2. 待完成(接线清单,对齐 map-turn-spec §4 / §6 / §8) + +已完成接线见 **§1**(含 §1.4、§1.6)。以下为尚未实现的步骤说明;完成后在 §3 验收表对应行打勾。 + +- [x] **`resolveEnemyActionsForSingleTick`**:已在 [project/plugins.js](../project/plugins.js) **`mapTurn`** 中实现 §2 该条所列 1–4 步(含 **`performEnemyAction`**,`idle` 已实现,其余 `actType` 占位)。 + +- [x] **`rebuildActiveEnemies`**:已在 **`mapTurn.rebuildActiveEnemies`** 实现 §2 该条 1–4 步;**`afterChangeFloor`** 中已调用 **`rebuildActiveEnemies(core.status.floorId || floorId)`**。 + +- [x] **`patchActiveEnemiesForBlockChange`**:已在 **`mapTurn.patchActiveEnemiesForBlockChange`** 实现 **`removeCell` / `syncCell` / `migratePoint` / `rebuild`**;[project/plugins.js](../project/plugins.js) 在 **`mapTurn`** 插件末尾对 **`core.maps`** / **`core.events`** 安装挂钩(含 **`moveBlock`/`jumpBlock`** 与 **`keep===false`** 补清)。 + +### 2.1 后续扩展接线备忘 + +对应 [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`** 内联)按怪物表字段分支执行移动/技能等行为。 + +--- + +## 3. 验收清单映射(对应 map-turn-spec §10) + +| §10 条目 | 依赖的待办小节 | +|----------|----------------| +| 状态技能不立即推进时间;战后层数 `-1` | 战斗胜利接线 + **`skillState`** 数据与 **`applyStatusAfterBattle`** 调用时机 | +| 远程/恢复立即推进;怪物按时间响应 | 道具 **`timeCost`**(已有 `useItem` 钩子)+ **`resolveEnemyActions` / `activeEnemies`** 实装 | +| 战斗耗时 **`max`** | **`settleBattleTimeCost`** 已在插件中;需战斗路径实际调用 | +| 多怪捕捉逐场扣层 | **`afterBattle`** 多场链路与每场成功分支 | +| Boss **`contactBattleOnly`** | 战斗触发层逻辑 + 怪物字段 | +| 死亡清理 | **`clearOnDeath`** 接入 **`lose` / 失败** | +| 存档读档连续 | **`flags`** 持久化已有方向;读档后 **`rebuildActiveEnemies`** | +| **`timeCost=0`** 不参与调度 | **`rebuildActiveEnemies`** 过滤 + **`resolveEnemyActions`** 只扫缓存 | +| **`consumeTime(3)`** 恰好 3 tick | **`consumeTime`** 已实现循环;需集成测试断言 | +| **`activeEnemies` 路径无每 tick 全图扫描** | **`rebuild` / `patch`** 实装 | + +--- + +## 4. 相关路径速查 + +| 用途 | 路径 | +|------|------| +| 规范全文 | [docs/map-turn-spec.md](map-turn-spec.md) | +| 样板 API | [_docs/api.md](../_docs/api.md) | +| 地图回合插件 | [project/plugins.js](../project/plugins.js) 搜索 **`"mapTurn"`** | diff --git a/docs/map-turn-spec.md b/docs/map-turn-spec.md index cd99f6c..f782ff3 100644 --- a/docs/map-turn-spec.md +++ b/docs/map-turn-spec.md @@ -1,5 +1,7 @@ # 地图回合与技能状态伪代码规范 +实现进度与代码接线台账见 [map-turn-implementation-status.md](map-turn-implementation-status.md)。**角色分工**:本规范写冻结规则与实现契约(尤其 §6);台账写「已接线文件 / API 清单 / 待办勾选项」,二者交叉引用,避免重复维护大段表格。 + ## 1. 目标与范围 本规范用于在当前项目中引入“地图时间(Map Turn)”和“四类技能状态”机制,确保: @@ -81,7 +83,7 @@ flags.mapTurnState = { // 仅收录「怪物定义 timeCost > 0」的实例;按楼层缓存,供每 tick 遍历,避免全图 extractBlocks activeEnemiesByFloor: { // [floorId]: [ - // { runtimeId, x, y, enemyId, blockIndex?, ... } // runtimeId 实现阶段约定,如 "floorId:x:y:enemyId" + // { runtimeId, x, y, enemyId, def, ... } // runtimeId 约定如 "floorId:x:y:enemyId";def 为 material.enemys[id] 引用,供 resolve 读 timeCost / actType // ] }, // 可选:每次 rebuild / patch 后自增,便于调试与断言缓存有效 @@ -109,9 +111,10 @@ flags.skillState = { - 实现 `core.plugin.mapTurn`(名称可调整,全文保持一致),至少包含: - `consumeTime(deltaTime, reason)` - `advanceMapTurnOne(reason)` - - `rebuildActiveEnemies(floorId)`、`patchActiveEnemiesForBlockChange(...)`(见 §6.6) + - `rebuildActiveEnemies(floorId)`、`patchActiveEnemiesForBlockChange(floorId, hint)`(见 §6.3) - `resolveEnemyActionsForSingleTick(reason)`(仅遍历当前层 `activeEnemies`) -- 可选:`__enable` 总开关,关闭时上述函数为空操作,便于分步接入游戏。 + - `performEnemyAction(...)`、`settleBattleTimeCost()`、`applyStatusAfterBattle` / `clearOnDeath` 等与 §6 对齐的辅助入口 +- **总开关**:持久化在 **`flags.mapTurnEnabled`**(随存档);由 `isEnabled` / `setEnabled` / `bootstrapPersistedState` 维护。开关为假时,`consumeTime` / `advanceMapTurnOne` 等推进与敌调度为空操作。勿再用闭包 `__enable` 与上述 flag 混用。 ## 4. 行为触发矩阵(是否推进地图时间) @@ -192,10 +195,18 @@ function resolveEnemyActionsForSingleTick(reason) { **注意**:列表中的怪物已保证 `enemyDef.timeCost > 0`(见 §6.3);此处 **禁止** 每 tick 调用 `extractBlocks` 全图扫描。 +**`performEnemyAction`(当前契约)**:达阈时调用;`actType === "idle"`(或未配置)不产生额外地图效果。`chase` / `patrol` / `skill` 等在本阶段可为占位——若在单 tick 内同步调用会改写图块的引擎路径(如经 `removeBlock` 间接触发全图块整理),与上条性能约束冲突;后续应改为异步动作链或引擎侧无全表扫描的迁移 API 再接。 + ### 6.3 `activeEnemies` 维护契约(性能) 1. **建表**:进入某楼层且地图块就绪后,调用 `rebuildActiveEnemies(floorId)`,扫描该层 `blocks`(或等价 API),仅加入「怪物图块且对应 `core.material.enemys[id].timeCost > 0`」的项,写入 `flags.mapTurnState.activeEnemiesByFloor[floorId]`,并 `activeEnemiesVersion++`。 -2. **局部更新**:当 **地图上的怪物集合或坐标** 发生变化时(如 `removeBlock`、`setBlock`、怪物 `moveBlock` 结束、`hideBlock` 等),调用 `patchActiveEnemiesForBlockChange(...)` 增删或更新对应条目,**不** 全量重建(除非实现成本过高,可退化为对该层 `rebuildActiveEnemies`)。 +2. **局部更新**:当 **地图上的怪物集合或坐标** 发生变化时(如 `removeBlock`、`setBlock`、怪物 `moveBlock` 结束、`hideBlock` 等),调用 `patchActiveEnemiesForBlockChange(floorId, hint)` 增删或更新对应条目,**不** 全量重建(除非实现成本过高,可退化为对该层 `rebuildActiveEnemies`)。`hint.op` 语义(与本仓库实现一致): + - **`removeCell`**:按坐标 `(x,y)` 从列表移除实例,并删除 `enemyActionGauge[floorId][runtimeId]`(删怪、隐藏怪等)。 + - **`syncCell`**:先清除该格在列表中的旧项及对应 gauge,再按当前地图块若存在可调度怪则 **新建** 条目;**不继承**旧槽(同格召唤、替换、显示后出现新怪等均为默认槽位)。 + - **`migratePoint`**:将 **同一实例** 从 `(fromX,fromY)` 迁到 `(toX,toY)`:更新条目中 `x,y` 与 `runtimeId`,并把 gauge 从旧 `runtimeId` 键迁到新键;与引擎在块移动落点后调用的 **`moveEnemyOnPoint`** 配套。 + - **`rebuild`**(或缺省 `hint`):等价于对该层执行一次 **`rebuildActiveEnemies`**:本路径内允许 **单次** `extractBlocks`,重建列表并按仍存在的 `runtimeId` 修剪 gauge。 + - **`moveBlock` / `jumpBlock`**:块位移动画期间,对中途触发的 `removeBlock` / `setBlock` **抑制**上述 patch,避免与 **`migratePoint`** 重复或乱序;动画 **`keep === false`**(块消失不落点)结束时,须补一次 **`removeCell`** 清理起点格上的调度数据。 + - **`removeBlockByIndexes`**(等多点批量删除):本仓库采用 **一次调用结束后** 对该层 **`rebuild`** 的退化策略(规范允许)。 3. **遍历**:`resolveEnemyActionsForSingleTick` **仅** 遍历当前层缓存列表;`deltaTime > 1` 时,重复 `deltaTime` 次单 tick 调度,等价于 mapTurn 从 `k` 逐步走到 `k+deltaTime`。 4. **换层**:`core.status.floorId` 切换后,下一 tick 使用新层的 `activeEnemiesByFloor[floorId]`;未访问过的楼层可无列表,首次结算前 `rebuild`。 5. **读档**:`activeEnemiesByFloor` 为派生缓存,**允许** 在读档结束、当前楼层已 `drawMap` 就绪后执行一次 `rebuildActiveEnemies(currentFloorId)`;`enemyActionGauge` 等需持久化的数据仍放在 `flags.mapTurnState` 内随存档走。 @@ -246,6 +257,17 @@ function clearOnDeath() { } ``` +### 6.7 本仓库实现锚点(与当前代码一致) + +以下与 [project/plugins.js](project/plugins.js) 及关联工程文件一致,便于对照 §8;**文件级清单仍以** [map-turn-implementation-status.md](map-turn-implementation-status.md) **为准**。 + +- **`core.plugin.mapTurn`** 定义于 [project/plugins.js](project/plugins.js) 插件 **`"mapTurn"`**:`consumeTime`、`advanceMapTurnOne`、`resolveEnemyActionsForSingleTick`、`performEnemyAction`、`rebuildActiveEnemies`、`patchActiveEnemiesForBlockChange`、`settleBattleTimeCost`、`applyStatusAfterBattle`、`clearOnDeath`、`bootstrapPersistedState` 等均挂在此对象上。 +- **地图与块移动挂钩**:在 **`mapTurn`** 插件末尾 IIFE 内对 **`core.maps`** 原型包装 `removeBlock`、`setBlock`、`hideBlock`、`showBlock`、`removeBlockByIndexes`、`moveBlock`、`jumpBlock`;对 **`core.events`** 包装 **`moveEnemyOnPoint`**,从而触发 §6.3 所列 `patch` / `rebuild` 行为(含 `moveBlock` / `jumpBlock` 深度计数与 `keep === false` 补清)。 +- **换层**:在 **`序章追击`** 等对 **`events.prototype.afterChangeFloor`** 的包装中调用 **`rebuildActiveEnemies`**;**普通换层**将当前层 **`mapTurn` 归零**、**读档换层**不归零 `mapTurn` 的口径见台账 §1.6。 +- **读档 / 开局**:`loadData` 中 **`bootstrapPersistedState`** 见 [project/functions.js](project/functions.js);开局 **`mapTurnEnabled`** 与 `bootstrapPersistedState` 见 [project/data.js](project/data.js)(台账 §1.6)。 +- **移动与战后时间**:在 [project/plugins.js](project/plugins.js) 的 **`序章追击`** 等插件段内对 **`control.prototype.moveOneStep` / `moveDirectly`** 与 **`events.prototype.afterBattle`** 包装,调用 **`consumeTime`**(含战后 **`settleBattleTimeCost`** 与 **`applyStatusAfterBattle`**);**非** [project/functions.js](project/functions.js) 默认空壳上的直接编辑。 +- **道具推进时间**:`useItem` 内按 `timeCost` 调用 `consumeTime` 见 [libs/items.js](libs/items.js)(与台账 §1.3 一致)。 + ## 7. 关键业务分支 ### 7.1 多怪捕捉导致多场战斗 @@ -273,13 +295,12 @@ function activateBattleSkill(skillId) { ## 8. 工程接入点映射 -- `project/plugins.js`:实现 `core.plugin.mapTurn`(§3.4),包含 `consumeTime`、`advanceMapTurnOne`、`resolveEnemyActionsForSingleTick`、`rebuildActiveEnemies`、`patchActiveEnemiesForBlockChange`、`clearOnDeath` 等;**所有「推进多少时间就结算多少次 tick」的逻辑集中于此**。 -- `project/functions.js` -> `moveOneStep`:移动完成后调用 `core.plugin.mapTurn.consumeTime(1, "move")`(或封装名一致即可)。 -- `project/functions.js` -> `afterBattle`:成功结算后先 `consumeTime(settleBattleTimeCost(), "battle")`(内部按 §2.1 拆 tick),再 `applyStatusAfterBattle("success")`。 -- `project/functions.js` -> `afterChangeFloor`(或 `changingFloor` 结束、楼层已绘制后):**一行** `core.plugin.mapTurn.rebuildActiveEnemies(core.status.floorId)`,建立当前层 `activeEnemies`(§6.3)。 -- `libs/items.js` -> `useItem`(或道具 `useItemEffect` 末尾):恢复/远程/tools 按 `item.timeCost` 调用 `consumeTime(item.timeCost, ...)`;状态技能只更新 `flags.skillState`,不调用 `consumeTime`。 +- `project/plugins.js`:实现 `core.plugin.mapTurn`(§3.4)及 §6.7 所列原型挂钩;**所有「推进多少时间就结算多少次 tick」及单 tick 敌调度入口集中于此**。 +- **移动 / 战后 / 换层与地图回合**:见 **§6.7**(对 `control` / `events` / `maps` 的包装;**非** `project/functions.js` 默认模板中的 `moveOneStep` / `afterBattle` / `afterChangeFloor` 直接改法)。 +- `project/functions.js` -> `loadData`:读档后调用 **`bootstrapPersistedState`**(§6.7);默认 **`afterChangeFloor`** 仍可由项目模板保留,地图回合换层 **`rebuild`** 由 plugins 内对 **`afterChangeFloor`** 的包装完成。 +- `libs/items.js` -> `useItem`:正数 `timeCost` 时调用 `consumeTime`(§6.7);状态技能只更新 `flags.skillState`,不调用 `consumeTime`。 - `project/enemys.js`(及 enemy48):按需为参与地图回合的怪物设置 `timeCost > 0` 与 `actType`;`timeCost === 0` 的怪不得进入 `activeEnemies`。 -- **地图变更挂钩(实现时择优)**:在会改变怪物位置/存亡的 API 之后调用 `patchActiveEnemiesForBlockChange`(若短期无法统一挂钩,可退化为每次变更后对该层 `rebuildActiveEnemies`)。 +- **地图变更挂钩**:本仓库已通过 §6.7 对 `maps` / `events` 的包装触发 **`patchActiveEnemiesForBlockChange`** 或 **`rebuildActiveEnemies`**;若日后增加其它改图 API(如未包装的 `swapBlock` 等),可再补挂钩或对该层退化为 **`rebuild`**。 ## 9. 存读档一致性要求 @@ -299,5 +320,5 @@ function activateBattleSkill(skillId) { - 存档读档后状态层数与地图时间连续。 - 设置怪物 `timeCost=0` 时,该怪不参与调度,性能无明显回退。 - **`consumeTime(3, ...)` 触发恰好 3 次 `advanceMapTurnOne`**:`mapTurn` 连续 `+3`,且敌人行动槽/行为按 **3 个独立 tick** 结算(可用日志或计数器断言)。 -- **`activeEnemies` 路径**:每 tick 不调用全图 `extractBlocks`;进楼 `rebuild` 后,增删怪仅 `patch` 或单次 `rebuild`;`timeCost=0` 的怪不在列表中。 +- **`activeEnemies` 路径**:每 tick 不调用全图 `extractBlocks`;进楼 `rebuild` 后,增删怪以 **`patch`(`removeCell` / `syncCell` / `migratePoint`)或单次 `rebuild`** 维护;`moveBlock` / `jumpBlock` 与深度计数规则见 §6.3;`timeCost=0` 的怪不在列表中。 diff --git a/docs/暂定大纲.docx b/docs/暂定大纲.docx new file mode 100644 index 0000000000000000000000000000000000000000..7d346715ad6268097f09b353a412caacc16e2105 GIT binary patch literal 19389 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 P0MFaH08CHU-9efFt`d-) literal 0 HcmV?d00001 diff --git a/docs/暂定大纲.txt b/docs/暂定大纲.txt new file mode 100644 index 0000000..ad787ab --- /dev/null +++ b/docs/暂定大纲.txt @@ -0,0 +1,48 @@ +简易大纲:魔塔Like +1. 游戏概述 +游戏名称:待定 (暂定) +游戏类型:固定地图探索+数值驱动+剧情导向+解谜 +核心玩法:魔塔类玩法,攻防血等变量作为基础 +核心体验: +固定地图探索:地图结构固定,鼓励探索、记忆和路线规划 +线性成长:通过宝石、血瓶、战斗获得属性提升,逐步挑战更强敌人 +状态继承:区域内状态会沿用上一场战斗剩余状态 + +非连续性:主角持有回档能力,在经过剧情后,对关键、信息道具继承,可以改变自身持有状态,改变地图通行,提前截获信息改变剧情走向到自己所需要的方向,剧情发生较大差异的变化可以视为不同周目 +技能与队友:主角跟随剧情获得不同技能,同时,跟随主角的队友可以提供额外技能(被动+主动均有)提,更好的处理地图与敌人,按种类可以分为战斗伤害、地图伤害、敌我位移、状态变化、远程操作等技能 +目标与敌对:在经过不同剧情后,主角的区域目标会跟随自己的想法而变动,不同周目所需面对的敌人是并不一致的,有些可以视为临时友军,并参与地图战斗(不可直接操作) +2. 设计目标 +核心循环清晰:区域目标→探索战斗→达成目标→情况对比→更换思路→再设目标→敌我判断→重复战斗→再次对比→......→确认结果 +信息透明:战场信息应当明确,玩家可以快速识别不同周目的差异 +路线规划:周目间差异,之前剧情信息所限制的路线可以逐步对玩家放开 +适度的挑战性:回档提供足够的下限保证玩家顺利度过区域战斗,同时,用严谨的技能方案、数值设计,提供足够的空间与深度给老玩家游玩。 +3. 基础内容 +生命值:归零则失败,触发回档。 +攻防:回合制战斗逻辑,每回合按先后互相造成伤害 +金币经验:金币作采购武器、补给品,经验自动分配给技能,少量提升数值,两者一般集中于boss身上,占区域的30% +固定能力:区域提供能力为固定数值,玩家可以通过技能进行临时分配,不提供额外属性以降低复杂 +战场时轴:技能、战斗与地图联系的方式,魔塔不可采用实际时间,作为地图上的回合制使用,达成敌我交互,普通怪一般为站桩,部分怪会主动攻击,BOSS更进一步要求也仅要求BOSS层内的操作,不同地图间一般独立互不影响。 +地图通行:多为平面地图,地图间一般有多个联系方式,但初见只需到达目的地,无需重复移动,且由于回档带来的状态重置,通行性空间更大。 +4. 章节流程 +本塔预设为5个章节,100-150层数,受回档的多玩法影响,一般玩家实际体验约为500-600层。 +面向群众包含无基础玩家和老玩家,需对魔塔基本战斗方式、本塔引入机制等都进行介绍。 +预设4个难度,根据对现实修改能力强弱进行区分,最高难度除剧情外无法修改任何内容。 +预计在序章前半段介绍魔塔战斗方式,后半段启用并熟悉回档方式。 +第一章,初期引入装备、技能(固定的临时队友加入,仅作为技能提供对象),讲述如何处理地图的难处理敌人,在后期引入时轴,介绍敌人在高强度战斗中技能造成的不同影响。 +第二章,引入阵容和多队友选择,玩家自由选择作战人员(主角+2队友)。 +第三章,接触针对性技能,玩家需要合理分配资源和反制这些技能。 +第四章,引入复杂机制敌人,需要更好的分配作战,同时提供一定的地图战略技能支援,直接击杀这些敌人。 +第五章,玩家统合信息到达boss面前,触发剧情,被夺走回档技能,主角为了队友选择放弃该能力,回到最初。现在主角拥有一切的信息,也保留所有技能,但是无法使用资源差,视为同个难度,再次踏上旅程。 +5. 任务分配 +技术支持:由于多种机制,本塔录像要求较高,且需要各种界面ui实现简化操作,且战斗判断复杂。 +地图、剧情:本塔剧情、地图结合紧密,需要剧情先行,且一定程度上互相配合妥协以降低实现难度。 +玩家体验:对平常地图和BOSS地图进行分割,降低前者难度,提高后者操作要求,并对玩家持有资源量进行保障,减少简易模式下卡关的出现。 + + +设计思路 +魔塔这类游戏的核心玩法,是通过对整体信息把控,用思路对路线做出规划,在这个过程中往往需要对路线可行性进行验证、修改局部,背板时间较多。玩家体验上看,区域规划>细节布局>整塔逻辑(意味着前面全部需要重打,成本大),针对这些问题,历来的各种功能、逻辑都给出了自己的答案,依次有浏览地图、快速存档、整塔重开,等等。 +如何去玩法解决魔塔类游戏中的卡关问题,这是本作品探讨的核心内容,玩家往往会遇到以下几种问题,资源消耗完之后无法再获取,卡死在道中或者boss前,特别是boss,战前已知胜败结果,需要通过大回档来重新规划,甚至在规划后仍旧卡关。选择了采用部分继承机制——回档,融入存档系统与剧情内,也是正在讨论的内容。回档倾向于作为辅助功能和剧情功能。 +而这自然衍生出另一个问题,重复游玩不可行,必然需要引入其他玩法,这个内容可参考内容较多,选择了较为可视且与地图拓扑相关的队友与阵容。将不同剧情下的地图区分开,作为提供给各种玩法的空白画布。队友系统是作为主要系统,让玩家进行决策,且可参考内容多,预计采用地图变化和添加特效等方式让效果更为直观,例如怪物坑入它们设下的陷阱、消耗其技能为无意义释放或者操纵他们去内斗等多种方式,可以参考战旗和ARPG等多种游戏。 +卡关的本质是资源积累问题,或者说对不优秀路线的惩罚。需要弱化道中决策成本,而这会可能导致游玩节奏缺乏张力,自然要提高boss战的难度作为张弛。在不考虑添加玩法的情况下,如果只是模仿将boss拆分为多只怪,这不过一堆怪而已,而且与平常区域的玩法分割(没能考虑拓扑性,且boss单纯独立机制制作成本大,玩家理解成本大),考虑采用时轴辅助,将机制与地图进行联系。按讨论所述,系统不应占用太大空间,但是会成为技能设计的重要方向。 +多个系统同时引入一个塔理解成本大,需对流程进行把控各种元素的出场时机。需要尽早与玩家达成共识,将常规层游玩成本降低到多数玩家可接受,将重要怪物也添增足够的笔墨让玩家愿意去战胜并记住。 +并且,由于篇幅带来的资源和状态差异问题问题,需注意到怪物技能设置问题和角色可用技能组的问题。同时需要避免两个问题,怪物技能着力过度导致角色只能推资源硬过,怪物技能无趣闭锁不与角色发生交互。 diff --git a/libs/events.js b/libs/events.js index 66d9954..4ac06c1 100644 --- a/libs/events.js +++ b/libs/events.js @@ -1604,6 +1604,64 @@ events.prototype._action_moveHero = function (data, x, y, prefix) { this.__action_doAsyncFunc(data.async, core.eventMoveHero, data.steps, data.time); } +/** + * 将 moveHero 的 steps 拆成每格一段(含 speed 段原样保留),供 moveHeroMapTurn 逐格 consumeTime。 + * 非样板扩展:与 core.eventMoveHero 语义对齐,避免与 project/plugins 中 moveOneStep 扣时重复。 + */ +events.prototype._expandMoveHeroMapTurnSteps = function (steps) { + var cardinal = ['up', 'down', 'left', 'right', 'forward', 'backward', 'leftup', 'leftdown', 'rightup', 'rightdown']; + var out = []; + (steps || []).forEach(function (t) { + if (typeof t !== 'string') return; + var v = t.split(':'); + var dir = v[0]; + if (dir === 'speed') { + out.push(t); + return; + } + var num = parseInt(v[1], 10); + if (v.length === 1 || isNaN(num)) num = 1; + if (num <= 0) { + out.push(dir + ':0'); + return; + } + if (cardinal.indexOf(dir) < 0) { + out.push(t); + return; + } + for (var i = 0; i < num; i++) out.push(dir + ':1'); + }); + return out; +} + +events.prototype._action_moveHeroMapTurn = function (data, x, y, prefix) { + var time = data.time != null ? data.time : null; + var flat = this._expandMoveHeroMapTurnSteps(data.steps || []); + if (flat.length === 0) return core.doAction(); + var todo = []; + flat.forEach(function (oneStep) { + var timeStr = time != null ? String(time) : 'null'; + var stepJson = JSON.stringify([oneStep]); + var parts = oneStep.split(':'); + var skipConsume = oneStep.indexOf('speed:') === 0 || + (parts.length > 1 && parseInt(parts[1], 10) === 0); + var consumeJs = skipConsume ? '' : + ('if (core.plugin && core.plugin.mapTurn && typeof core.plugin.mapTurn.consumeTime === "function") {\n' + + '\tcore.plugin.mapTurn.consumeTime(1, "event:moveHeroMapTurn");\n' + + '}\n'); + todo.push({ + "type": "function", + "async": true, + "function": 'function(){\ncore.eventMoveHero(' + stepJson + ', ' + timeStr + ', function(){\n' + + consumeJs + + 'core.doAction();\n' + + '});\n}' + }); + }); + core.insertAction(todo, x, y); + core.doAction(); +} + events.prototype._action_jump = function (data, x, y, prefix) { var from = this.__action_getLoc(data.from, x, y, prefix), to; if (data.dxy) { diff --git a/project/data.js b/project/data.js index b795bc1..22b7989 100644 --- a/project/data.js +++ b/project/data.js @@ -561,6 +561,15 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = } ], "startText": [ + { + "type": "setValue", + "name": "flag:mapTurnEnabled", + "value": "1" + }, + { + "type": "function", + "function": "function(){\nif (core.plugin && core.plugin.mapTurn && typeof core.plugin.mapTurn.bootstrapPersistedState === \"function\") {\n\tcore.plugin.mapTurn.bootstrapPersistedState();\n}\n}" + }, { "type": "comment", "text": "初始剧情" diff --git a/project/floors/C0_T01.js b/project/floors/C0_T01.js index 233d5a4..765bc67 100644 --- a/project/floors/C0_T01.js +++ b/project/floors/C0_T01.js @@ -32,6 +32,12 @@ main.floors.C0_T01= "type": "setValue", "name": "flag:序追", "value": "1" + }, + { + "type": "moveHeroMapTurn", + "steps": [ + "right:1" + ] } ], "3,7": [ diff --git a/project/functions.js b/project/functions.js index b9f1f3e..19a6a36 100644 --- a/project/functions.js +++ b/project/functions.js @@ -1076,6 +1076,10 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = } core.setFlag('__fromLoad__', true); + if (core.plugin && core.plugin.mapTurn && typeof core.plugin.mapTurn.bootstrapPersistedState === "function") { + core.plugin.mapTurn.bootstrapPersistedState(); + } + // TODO:增加自己的一些读档处理 // 切换到对应的楼层 diff --git a/project/items.js b/project/items.js index ca849c3..7b37ef9 100644 --- a/project/items.js +++ b/project/items.js @@ -465,7 +465,7 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = }, "bigKey": { "cls": "tools", - "timeCost": null, + "timeCost": 3, "name": "大黄门钥匙", "text": "可以开启当前层所有黄门", "itemEffect": "core.addItem('yellowKey', 1);\ncore.addItem('blueKey', 1);\ncore.addItem('redKey', 1);", @@ -642,7 +642,7 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = }, "skill1": { "cls": "constants", - "timeCost": null, + "timeCost": 3, "name": "技能:二倍斩", "text": "可以打开或关闭主动技能二倍斩", "hideInReplay": true, diff --git a/project/plugins.js b/project/plugins.js index 7399d53..f820eda 100644 --- a/project/plugins.js +++ b/project/plugins.js @@ -2334,6 +2334,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = } var old_moveOneStep = control.prototype.moveOneStep; + var old_moveDirectly = control.prototype.moveDirectly; var old_changeFloor = events.prototype.changeFloor; var old_afterChangeFloor = events.prototype.afterChangeFloor; var old_afterGetItem = events.prototype.afterGetItem; @@ -2349,10 +2350,30 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = enqueuePursuitTurn(); } old_moveOneStep.call(this, callback); + if (core.plugin && core.plugin.mapTurn && typeof core.plugin.mapTurn.consumeTime === "function") { + core.plugin.mapTurn.consumeTime(1, "move"); + } + }; + + control.prototype.moveDirectly = function (x, y, ignoreSteps) { + var effectiveIgnoreSteps = ignoreSteps; + if (effectiveIgnoreSteps == null && typeof core.canMoveDirectly === "function") { + effectiveIgnoreSteps = core.canMoveDirectly(x, y); + } + var ok = old_moveDirectly.call(this, x, y, ignoreSteps); + if (ok && typeof effectiveIgnoreSteps === "number" && effectiveIgnoreSteps > 0 && + core.plugin && core.plugin.mapTurn && typeof core.plugin.mapTurn.consumeTime === "function") { + core.plugin.mapTurn.consumeTime(effectiveIgnoreSteps, "moveDirectly"); + } + return ok; }; events.prototype.afterGetItem = function (id, x, y, isGentleClick) { old_afterGetItem.call(this, id, x, y, isGentleClick); + // 走路踩到 getItem 时引擎传 isGentleClick=false,时轴已在 moveOneStep 扣过,此处不再扣以免双倍 + if (isGentleClick && core.plugin && core.plugin.mapTurn && typeof core.plugin.mapTurn.consumeTime === "function") { + core.plugin.mapTurn.consumeTime(1, "getItem:gentleClick"); + } if (isPursuitEnabled() && core.getFlag("1fBoss_loc")) { core.setFlag("序追_lock", { x: core.getHeroLoc("x"), y: core.getHeroLoc("y"), floorId: core.status.floorId }); enqueuePursuitTurn(); @@ -2361,6 +2382,15 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = events.prototype.afterBattle = function (enemyId, x, y) { old_afterBattle.call(this, enemyId, x, y); + if (core.status.hero && core.status.hero.hp > 0 && core.plugin && core.plugin.mapTurn) { + var mt = core.plugin.mapTurn; + if (typeof mt.settleBattleTimeCost === "function" && typeof mt.consumeTime === "function") { + mt.consumeTime(mt.settleBattleTimeCost(), "battle"); + } + if (typeof mt.applyStatusAfterBattle === "function") { + mt.applyStatusAfterBattle("success"); + } + } if (enemyId === "redSwordsman") { core.removeFlag("1fBoss_loc"); core.setFlag("序追", 0); @@ -2388,6 +2418,16 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = let in_point = core.getFlag("in_point", {}); old_afterChangeFloor.call(this, floorId); + // 读档换层时保留存档中的 mapTurn;普通换层仍按层相对回合归零(见 docs/map-turn-implementation-status.md) + if (!fromLoad) { + var mapTurnState = core.getFlag("mapTurnState"); + if (mapTurnState && typeof mapTurnState === "object") { + mapTurnState.mapTurn = 0; + } + } + if (core.plugin && core.plugin.mapTurn && typeof core.plugin.mapTurn.rebuildActiveEnemies === "function") { + core.plugin.mapTurn.rebuildActiveEnemies(core.status.floorId || floorId); + } if (!fromLoad && core.status.floorId) in_point[core.status.floorId] = { x: core.status.hero.loc.x, y: core.status.hero.loc.y, @@ -2658,7 +2698,10 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = }, "mapTurn": function () { - var __enable = false; + // 总开关持久化在 flags.mapTurnEnabled(随存档/读档);勿再用闭包 __enable + function mapTurnEnabled() { + return !!core.getFlag("mapTurnEnabled"); + } function ensureFlags() { var m = core.getFlag("mapTurnState"); @@ -2689,13 +2732,18 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = this.mapTurn = { isEnabled: function () { - return __enable; + return mapTurnEnabled(); }, setEnabled: function (v) { - __enable = !!v; + core.setFlag("mapTurnEnabled", !!v); + if (v) ensureFlags(); + }, + /** 读档或 setValue 写入 flag 后调用,在 flag 为真时补齐 mapTurnState / skillState */ + bootstrapPersistedState: function () { + if (mapTurnEnabled()) ensureFlags(); }, consumeTime: function (deltaTime, reason) { - if (!__enable || !deltaTime || deltaTime <= 0) return; + if (!mapTurnEnabled() || !deltaTime || deltaTime <= 0) return; ensureFlags(); var n = Math.floor(deltaTime); var s = core.getFlag("mapTurnState"); @@ -2704,26 +2752,177 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = this.advanceMapTurnOne(reason); }, advanceMapTurnOne: function (reason) { - if (!__enable) return; + if (!mapTurnEnabled()) return; ensureFlags(); var s = core.getFlag("mapTurnState"); s.mapTurn = (s.mapTurn || 0) + 1; this.resolveEnemyActionsForSingleTick(reason); }, + /** 单 tick 怪物调度:仅扫 activeEnemiesByFloor;不调用 extractBlocks(map-turn-spec §6.2) */ resolveEnemyActionsForSingleTick: function (reason) { - /* 占位:按 docs/map-turn-spec.md §6.2 接入 activeEnemies 与怪物行动 */ + if (!mapTurnEnabled()) return; + ensureFlags(); + var floorId = core.status.floorId; + if (!floorId) return; + var s = core.getFlag("mapTurnState"); + var list = s.activeEnemiesByFloor[floorId] || []; + if (list.length === 0) return; + var eg = s.enemyActionGauge; + if (!eg[floorId] || typeof eg[floorId] !== "object") eg[floorId] = {}; + var gmap = eg[floorId]; + var snapshot = list.slice(); + var self = this; + for (var i = 0; i < snapshot.length; i++) { + var enemyRef = snapshot[i]; + if (!enemyRef || !enemyRef.runtimeId) continue; + var def = enemyRef.def || core.material.enemys[enemyRef.enemyId]; + if (!def || typeof def.timeCost !== "number" || def.timeCost <= 0) continue; + var rid = enemyRef.runtimeId; + gmap[rid] = (gmap[rid] || 0) + 1; + while (gmap[rid] >= def.timeCost) { + gmap[rid] -= def.timeCost; + self.performEnemyAction(enemyRef, def, floorId, reason); + rid = enemyRef.runtimeId; + } + } }, + /** + * 达阈行动:初版仅实现 actType === idle(无操作)。 + * chase/patrol/skill 等若在此同步改图块,会经引擎 removeBlock 触发 extractBlocks,违反单 tick 约束;后续用 insertAction 链或专用无扫描迁移 API 再接。 + */ + performEnemyAction: function (enemyRef, def, floorId, reason) { + var actType = def.actType || "idle"; + if (actType === "idle") return; + /* chase / patrol / skill:占位,不在此 tick 内改图块 */ + }, + /** + * 全量重建当前层 activeEnemies(map-turn-spec §6.3);仅此路径内调用 extractBlocks。 + * 条目含 runtimeId / x / y / enemyId / def;gauge 仅保留仍存在于图上的 runtimeId。 + */ rebuildActiveEnemies: function (floorId) { ensureFlags(); var s = core.getFlag("mapTurnState"); floorId = floorId || core.status.floorId; if (!floorId) return; + if (!core.floors || !core.floors[floorId]) return; + core.extractBlocks(floorId); + var map = core.status.maps && core.status.maps[floorId]; + var blocks = (map && map.blocks) || []; + var list = []; + for (var bi = 0; bi < blocks.length; bi++) { + var block = blocks[bi]; + if (!block || block.disable) continue; + var ev = block.event; + if (!ev || !ev.cls) continue; + if (String(ev.cls).indexOf("enemy") !== 0) continue; + var enemyId = ev.id; + var def = core.material.enemys[enemyId]; + if (!def || typeof def.timeCost !== "number" || def.timeCost <= 0) continue; + var runtimeId = floorId + ":" + block.x + ":" + block.y + ":" + enemyId; + list.push({ + runtimeId: runtimeId, + x: block.x, + y: block.y, + enemyId: enemyId, + def: def + }); + } if (!s.activeEnemiesByFloor) s.activeEnemiesByFloor = {}; - s.activeEnemiesByFloor[floorId] = []; + s.activeEnemiesByFloor[floorId] = list; s.activeEnemiesVersion = (s.activeEnemiesVersion || 0) + 1; + var eg = s.enemyActionGauge; + var prev = eg[floorId]; + var nextG = {}; + if (prev && typeof prev === "object") { + for (var li = 0; li < list.length; li++) { + var rid = list[li].runtimeId; + if (typeof prev[rid] === "number") nextG[rid] = prev[rid]; + } + } + eg[floorId] = nextG; }, + /** + * 局部维护 activeEnemies / enemyActionGauge(map-turn-spec §6.3)。 + * hint.op: removeCell | syncCell | migratePoint | rebuild(默认 rebuild) + */ patchActiveEnemiesForBlockChange: function (floorId, hint) { + if (!mapTurnEnabled()) return; ensureFlags(); + hint = hint || {}; + floorId = floorId || core.status.floorId; + if (!floorId || !core.floors[floorId]) return; + var s = core.getFlag("mapTurnState"); + if (!s.activeEnemiesByFloor) s.activeEnemiesByFloor = {}; + var op = hint.op || "rebuild"; + if (op === "rebuild") { + this.rebuildActiveEnemies(floorId); + return; + } + var eg = s.enemyActionGauge; + if (!eg[floorId] || typeof eg[floorId] !== "object") eg[floorId] = {}; + var gmap = eg[floorId]; + + if (op === "removeCell") { + var rx = hint.x, + ry = hint.y; + var list0 = s.activeEnemiesByFloor[floorId] || []; + var out0 = []; + for (var a = 0; a < list0.length; a++) { + var e0 = list0[a]; + if (e0.x === rx && e0.y === ry) { + delete gmap[e0.runtimeId]; + continue; + } + out0.push(e0); + } + s.activeEnemiesByFloor[floorId] = out0; + s.activeEnemiesVersion = (s.activeEnemiesVersion || 0) + 1; + return; + } + + if (op === "syncCell") { + var cx = hint.x, + cy = hint.y; + var list1 = s.activeEnemiesByFloor[floorId] || []; + var out1 = []; + for (var b = 0; b < list1.length; b++) { + var e1 = list1[b]; + if (e1.x === cx && e1.y === cy) delete gmap[e1.runtimeId]; + else out1.push(e1); + } + var block = core.getBlock(cx, cy, floorId, false); + if (block && !block.disable && block.event && block.event.cls && String(block.event.cls).indexOf("enemy") === 0) { + var eid = block.event.id; + var def = core.material.enemys[eid]; + if (def && typeof def.timeCost === "number" && def.timeCost > 0) { + var rid = floorId + ":" + cx + ":" + cy + ":" + eid; + out1.push({ runtimeId: rid, x: cx, y: cy, enemyId: eid, def: def }); + } + } + s.activeEnemiesByFloor[floorId] = out1; + s.activeEnemiesVersion = (s.activeEnemiesVersion || 0) + 1; + return; + } + + if (op === "migratePoint") { + var list2 = s.activeEnemiesByFloor[floorId] || []; + for (var c = 0; c < list2.length; c++) { + var e2 = list2[c]; + if (e2.x === hint.fromX && e2.y === hint.fromY) { + var oldR = e2.runtimeId; + var newR = floorId + ":" + hint.toX + ":" + hint.toY + ":" + e2.enemyId; + e2.x = hint.toX; + e2.y = hint.toY; + e2.runtimeId = newR; + if (typeof gmap[oldR] === "number") { + gmap[newR] = gmap[oldR]; + delete gmap[oldR]; + } + s.activeEnemiesVersion = (s.activeEnemiesVersion || 0) + 1; + return; + } + } + } }, settleBattleTimeCost: function () { ensureFlags(); @@ -2757,6 +2956,95 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ss.activeStatusSkills = {}; } }; + + var mapTurnImpl = this.mapTurn; + (function installMapTurnActiveEnemyHooks() { + if (!core || !core.maps || !core.events) return; + var mapsProto = Object.getPrototypeOf(core.maps); + if (mapsProto.__mapTurnActiveEnemyHooks) return; + mapsProto.__mapTurnActiveEnemyHooks = true; + + function blockAnimDepth() { + return core.__mapTurnBlockAnimDepth || 0; + } + function incBlockAnim() { + core.__mapTurnBlockAnimDepth = blockAnimDepth() + 1; + } + function decBlockAnim() { + core.__mapTurnBlockAnimDepth = Math.max(0, blockAnimDepth() - 1); + } + function mtCall(hint, floorId) { + if (!mapTurnEnabled() || !mapTurnImpl || typeof mapTurnImpl.patchActiveEnemiesForBlockChange !== "function") return; + mapTurnImpl.patchActiveEnemiesForBlockChange(floorId, hint); + } + function mtRebuild(floorId) { + if (!mapTurnEnabled() || !mapTurnImpl || typeof mapTurnImpl.rebuildActiveEnemies !== "function") return; + mapTurnImpl.rebuildActiveEnemies(floorId); + } + + var oldRemoveBlock = mapsProto.removeBlock; + mapsProto.removeBlock = function (x, y, floorId) { + var ret = oldRemoveBlock.call(this, x, y, floorId); + if (ret && blockAnimDepth() <= 0) mtCall({ op: "removeCell", x: x, y: y }, floorId || core.status.floorId); + return ret; + }; + + var oldSetBlock = mapsProto.setBlock; + mapsProto.setBlock = function (number, x, y, floorId) { + var ret = oldSetBlock.call(this, number, x, y, floorId); + if (blockAnimDepth() <= 0) mtCall({ op: "syncCell", x: x, y: y }, floorId || core.status.floorId); + return ret; + }; + + var oldRemoveBlockByIndexes = mapsProto.removeBlockByIndexes; + mapsProto.removeBlockByIndexes = function (indexes, floorId) { + oldRemoveBlockByIndexes.call(this, indexes, floorId); + mtRebuild(floorId || core.status.floorId); + }; + + var oldMoveBlock = mapsProto.moveBlock; + mapsProto.moveBlock = function (x, y, steps, time, keep, callback) { + incBlockAnim(); + return oldMoveBlock.call(this, x, y, steps, time, keep, function () { + decBlockAnim(); + if (!keep && mapTurnEnabled() && mapTurnImpl) + mapTurnImpl.patchActiveEnemiesForBlockChange(core.status.floorId, { op: "removeCell", x: x, y: y }); + if (callback) callback(); + }); + }; + + var oldJumpBlock = mapsProto.jumpBlock; + mapsProto.jumpBlock = function (sx, sy, ex, ey, time, keep, callback) { + incBlockAnim(); + return oldJumpBlock.call(this, sx, sy, ex, ey, time, keep, function () { + decBlockAnim(); + if (!keep && mapTurnEnabled() && mapTurnImpl) + mapTurnImpl.patchActiveEnemiesForBlockChange(core.status.floorId, { op: "removeCell", x: sx, y: sy }); + if (callback) callback(); + }); + }; + + var oldHideBlock = mapsProto.hideBlock; + mapsProto.hideBlock = function (x, y, floorId) { + var ret = oldHideBlock.call(this, x, y, floorId); + if (blockAnimDepth() <= 0) mtCall({ op: "removeCell", x: x, y: y }, floorId || core.status.floorId); + return ret; + }; + + var oldShowBlock = mapsProto.showBlock; + mapsProto.showBlock = function (x, y, floorId) { + var ret = oldShowBlock.call(this, x, y, floorId); + if (blockAnimDepth() <= 0) mtCall({ op: "syncCell", x: x, y: y }, floorId || core.status.floorId); + return ret; + }; + + var evProto = Object.getPrototypeOf(core.events); + var oldMoveEnemyOnPoint = evProto.moveEnemyOnPoint; + evProto.moveEnemyOnPoint = function (fromX, fromY, toX, toY, floorId, norefresh) { + oldMoveEnemyOnPoint.call(this, fromX, fromY, toX, toY, floorId, norefresh); + mtCall({ op: "migratePoint", fromX: fromX, fromY: fromY, toX: toX, toY: toY }, floorId || core.status.floorId); + }; + })(); } } \ No newline at end of file