From 9d591d50a59dd8940a063dc3f1e76a2bdadeec8e Mon Sep 17 00:00:00 2001 From: oc Date: Tue, 20 Feb 2018 17:47:44 +0800 Subject: [PATCH 1/3] Input, Show Multiple blocks, Load --- README.md | 3 +++ docs/event.md | 38 ++++++++++++++++++++++++------ libs/core.js | 41 +++++++++++++++++++++----------- libs/events.js | 53 +++++++++++++++++++++++++++++++++--------- libs/floors/sample1.js | 23 +++++++++++------- libs/floors/sample2.js | 5 +--- libs/maps.js | 6 ++--- 更新说明.txt | 3 +++ 8 files changed, 126 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index f559d374..3d9aecdb 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,9 @@ HTML5 canvas制作的魔塔样板,支持全平台游戏! * [x] 改变图块(setBlock事件)。 * [x] 同一个点的多事件处理(做法详见文档)。 +* [x] 增加新地图后可以接档而不用重新开始 +* [x] 可以同时show/hide多个事件。 +* [x] 增加可以接收用户输入的事件(type:prompt) * [x] 现在可以支持滑冰和推箱子事件了。 * [x] 地图中每个块的可通行方向控制(悬崖效果)。 * [x] 动画支持带旋转和翻转的帧。 diff --git a/docs/event.md b/docs/event.md index 77a1e39e..8a89fe88 100644 --- a/docs/event.md +++ b/docs/event.md @@ -334,11 +334,12 @@ value是一个表达式,将通过这个表达式计算出的结果赋值给nam "x,y": [ // 实际执行的事件列表 {"type": "show", "loc": [3,6], "floorId": "MT1", "time": 500 } // 启用MT1层[3,6]位置事件,动画500ms {"type": "show", "loc": [3,6], "time": 500 } // 如果启用目标是当前层,则可以省略floorId项 - {"type": "show", "loc": [3,6]} // 如果不指定动画时间,则立刻显示,否则动画效果逐渐显示,time为动画时间 + {"type": "show", "loc": [3,6]}, // 如果不指定动画时间,则立刻显示,否则动画效果逐渐显示,time为动画时间 + {"type": "show", "loc": [[3,6],[2,9],[1,2]], "time": 500} // 我们也可以同时动画显示多个点。 ] ``` -show事件需要用loc指定目标点的坐标;剩下有两个参数floorId和time。 +show事件需要用loc指定目标点的坐标,可以简单的写[x,y]代表一个点,也可以写个二维数组[[x1,y1],[x2,y2],...]来同时显示多个点。 floorId为目标点的楼层,如果不是该楼层的事件(比如4楼小偷开2楼的门)则是必须的,如果是当前楼层可以忽略不写。 @@ -352,6 +353,8 @@ time为动画效果时间,如果指定了某个大于0的数,则会以动画 其参数和show也完全相同,loc指定事件的位置,floorId为楼层(同层可忽略),time指定的话事件会以动画效果从有到无慢慢消失。 +loc同样可以简单的写[x,y]表示单个点,或二维数组[[x1,y1],[x2,y2],...]表示多个点。 + 但是和show事件有所区别的是:loc选项也可以忽略;如果忽略loc则使当前事件禁用。(即使禁用当前事件,也不会立刻结束当前正在进行的,而是仍然会依次将列表中剩下的事件执行完) 请注意,一次性事件必须要加 `{"type":"hide"}`,尤其是例如走到某个点,触发对话或机关门(陷阱)这种,否则每次都会重复触发。 @@ -360,11 +363,13 @@ NPC对话事件结束后如果需要NPC消失也需要调用 `{"type": "hide"}` ``` js "x,y": [ // 实际执行的事件列表 - {"type": "hide", "loc": [3,6], "floorId": "MT1", "time": 500 } // 禁用MT1层[3,6]位置事件,动画500ms - {"type": "hide", "loc": [3,6], "time": 500 } // 如果启用目标是当前层,则可以省略floorId项 - {"type": "hide", "loc": [3,6] } // 如果不指定动画时间,则立刻消失,否则动画效果逐渐消失,time为动画时间 - {"type": "hide", "time": 500 } // 如果不指定loc选项则默认为当前点, 例如这个就是500ms消失当前对话的NPC - {"type": "hide" } // 无动画将当前事件禁用,常常适用于某个空地点(触发陷阱事件、触发机关门这种) + {"type": "hide", "loc": [3,6], "floorId": "MT1", "time": 500}, // 禁用MT1层[3,6]位置事件,动画500ms + {"type": "hide", "loc": [3,6], "time": 500}, // 如果启用目标是当前层,则可以省略floorId项 + {"type": "hide", "loc": [3,6]}, // 如果不指定动画时间,则立刻消失,否则动画效果逐渐消失,time为动画时间 + {"type": "hide", "loc": [[3,6],[2,9],[1,2]], "time": 500}, // 也可以同时指定多个点消失 + {"type": "hide", "time": 500}, // 如果不指定loc选项则默认为当前点, 例如这个就是500ms消失当前对话的NPC + {"type": "hide"}, // 无动画将当前事件禁用,常常适用于某个空地点(触发陷阱事件、触发机关门这种) + ] ``` @@ -749,6 +754,25 @@ move完毕后移动的NPC/怪物一定会消失,只不过可以通过immediate 该事件会显示失败页面,并重新开始游戏。 +### input:接受用户输入 + +使用`{"type": "input"}`可以接受用户的输入。 + +``` js +"x,y": [ // 实际执行的事件列表 + {"type": "input", "text": "请输入一个数"}, // 显示一个弹窗让用户输入内容 + "你刚刚输入的数是${flag:input}" // 输入结果将被赋值为flag:input +] +``` + +text为提示文字,可以在这里给输入提示文字。这里同样可以使用${ }来计算表达式的值。 + +当执行input事件时,将显示一个弹窗,并提示用户输入一个内容。 + +!> 该事件只能接受非负整数输入,所有非法的输入将全部变成`0`。例如用户在输入框内输入“你好”或者-3,都将实际得到0。 + +输入得到的结果将被赋值给flag:input,可以供后续if来进行判断。 + ### if: 条件判断 使用`{"type": "if"}`可以对条件进行判断,根据判断结果将会选择不同的分支执行。 diff --git a/libs/core.js b/libs/core.js index 0678d697..0569d823 100644 --- a/libs/core.js +++ b/libs/core.js @@ -1982,7 +1982,7 @@ core.prototype.canMoveHero = function(x,y,direction,floorId) { 'down': {'x': 0, 'y': 1}, 'right': {'x': 1, 'y': 0} }; - var nextBlock = core.getBlock(x+scan[direction].x,y+scan[direction].y); + var nextBlock = core.getBlock(x+scan[direction].x,y+scan[direction].y,floorId); if (nextBlock!=null){ nextId = nextBlock.block.event.id; // 遇到单向箭头处理 @@ -2955,7 +2955,7 @@ core.prototype.moveBlock = function(x,y,steps,time,immediateHide,callback) { } ////// 显示/隐藏某个块时的动画效果 ////// -core.prototype.animateBlock = function (x,y,type,time,callback) { +core.prototype.animateBlock = function (loc,type,time,callback) { if (type!='hide') type='show'; core.status.replay.animate=true; @@ -2963,31 +2963,46 @@ core.prototype.animateBlock = function (x,y,type,time,callback) { core.saveCanvas('animate'); core.clearMap('animate', 0, 0, 416, 416); - var block = core.getBlock(x,y,core.status.floorId,false); - if (block==null) {// 不存在 + if (typeof loc[0] == 'number' && typeof loc[1] == 'number') + loc = [loc]; + + var list = []; + loc.forEach(function (t) { + var block = core.getBlock(t[0],t[1],core.status.floorId,false); + if (block==null) return; + block=block.block; + list.push({ + 'x': t[0], 'y': t[1], + 'blockIcon': core.material.icons[block.event.cls][block.event.id], + 'blockImage': core.material.images[block.event.cls] + }) + }) + + if (list.length==0) { if (core.isset(callback)) callback(); return; } - // 清空UI - //core.clearMap('ui', 0, 0, 416, 416); - //core.setAlpha('ui', 1.0); - block=block.block; - blockIcon = core.material.icons[block.event.cls][block.event.id]; - blockImage = core.material.images[block.event.cls]; + var draw = function () { + list.forEach(function (t) { + core.canvas.animate.drawImage(t.blockImage, 0, t.blockIcon * 32, 32, 32, t.x * 32, t.y * 32, 32, 32); + }) + } var opacityVal = 0; if (type=='hide') opacityVal=1; core.setOpacity('animate', opacityVal); - core.canvas.animate.drawImage(blockImage, 0, blockIcon * 32, 32, 32, block.x * 32, block.y * 32, 32, 32); + draw(); var animate = window.setInterval(function () { if (type=='show') opacityVal += 0.1; else opacityVal -= 0.1; core.setOpacity('animate', opacityVal); - core.clearMap('animate',block.x * 32, block.y * 32, 32, 32); - core.canvas.animate.drawImage(blockImage, 0, blockIcon * 32, 32, 32, block.x * 32, block.y * 32, 32, 32); + core.clearMap('animate',0,0,416,416); + + // core.canvas.animate.drawImage(blockImage, 0, blockIcon * 32, 32, 32, block.x * 32, block.y * 32, 32, 32); + draw(); if (opacityVal >=1 || opacityVal<=0) { clearInterval(animate); core.loadCanvas('animate'); diff --git a/libs/events.js b/libs/events.js index 2596a46d..eb8bc9cc 100644 --- a/libs/events.js +++ b/libs/events.js @@ -320,26 +320,33 @@ events.prototype.doAction = function() { core.events.doAction(); break; case "show": // 显示 + if (typeof data.loc[0] == 'number' && typeof data.loc[1] == 'number') + data.loc = [data.loc]; if (core.isset(data.time) && data.time>0 && (!core.isset(data.floorId) || data.floorId==core.status.floorId)) { - core.animateBlock(data.loc[0],data.loc[1],'show', data.time, function () { - core.showBlock(data.loc[0],data.loc[1],data.floorId); + core.animateBlock(data.loc,'show', data.time, function () { + data.loc.forEach(function (t) { + core.showBlock(t[0],t[1],data.floorId) + }) core.events.doAction(); }); } else { - core.showBlock(data.loc[0],data.loc[1],data.floorId) + data.loc.forEach(function (t) { + core.showBlock(t[0],t[1],data.floorId) + }) this.doAction(); } break; case "hide": // 消失 - var toX=x, toY=y, toId=core.status.floorId; - if (core.isset(data.loc)) { - toX=data.loc[0]; toY=data.loc[1]; - } - if (core.isset(data.floorId)) toId=data.floorId; - core.removeBlock(toX,toY,toId) - if (core.isset(data.time) && data.time>0 && toId==core.status.floorId) { - core.animateBlock(toX,toY,'hide',data.time, function () { + if (!core.isset(data.loc)) + data.loc = [x,y]; + if (typeof data.loc[0] == 'number' && typeof data.loc[1] == 'number') + data.loc = [data.loc]; + data.loc.forEach(function (t) { + core.removeBlock(t[0],t[1],data.floorId); + }) + if (core.isset(data.time) && data.time>0 && (!core.isset(data.floorId) || data.floorId==core.status.floorId)) { + core.animateBlock(data.loc,'hide',data.time, function () { core.events.doAction(); }); } @@ -531,6 +538,30 @@ events.prototype.doAction = function() { this.doAction(); } break; + case "input": + { + var value; + if (core.status.replay.replaying) { + var action = core.status.replay.toReplay.shift(); + if (action.indexOf("input:")==0 ) { + value=parseInt(action.substring(6)); + } + else { + core.stopReplay(); + core.drawTip("录像文件出错"); + return; + } + + } + else { + value = prompt(core.replaceText(data.text)); + } + value = Math.abs(parseInt(value)||0); + core.status.route.push("input:"+value); + core.setFlag("input", value); + this.doAction(); + } + break; case "if": // 条件判断 if (core.calValue(data.condition)) core.events.insertAction(data["true"]) diff --git a/libs/floors/sample1.js b/libs/floors/sample1.js index 4fbc0fd7..85163853 100644 --- a/libs/floors/sample1.js +++ b/libs/floors/sample1.js @@ -52,18 +52,12 @@ main.floors.sample1 = { {"type": "show", "loc": [1,5], "time": 1500}, // 显示红衣魔王,动画效果1500ms {"type": "sleep", "time": 500}, // 等待500ms "\t[redKing]欢迎来到魔塔,你是第一百位挑战者。\n若你能打败我所有的手下,我就与你一对一的决斗。\n现在你必须接受我的安排。", - {"type": "show", "loc": [1,6], "time": 500}, // 显示四个白衣武士,每个动画效果500ms - {"type": "show", "loc": [0,7], "time": 500}, - {"type": "show", "loc": [1,8], "time": 500}, - {"type": "show", "loc": [2,7], "time": 500}, + {"type": "show", "loc": [[1,6],[0,7],[1,8],[2,7]], "time": 500}, // 显示四个白衣武士,每个动画效果500ms "\t[hero]什么?", {"type": "playSound", "name": "attack.ogg"}, // 播放战斗音频 {"type": "setValue", "name": "status:atk", "value": "status:atk/10"}, // 勇士的攻防变成原来的十分之一 {"type": "setValue", "name": "status:def", "value": "status:def/10"}, - {"type": "hide", "loc": [1,6]}, // 直接隐藏四个白衣武士,没有动画效果 - {"type": "hide", "loc": [0,7]}, - {"type": "hide", "loc": [2,7]}, - {"type": "hide", "loc": [1,8]}, + {"type": "hide", "loc": [[1,6],[0,7],[2,7],[1,8]]}, // 直接隐藏四个白衣武士,没有动画效果 {"type": "hide", "loc": [1,5], "time": 500}, // 隐藏红衣魔王,动画500ms {"type": "hide"}, // 隐藏本事件 {"type": "setFg", "color": [0,0,0], 'time': 1250}, // 渐变为白色 @@ -258,6 +252,7 @@ main.floors.sample1 = { "12,11": [ // 自定义事件的老人 "\t[老人,womanMagician]使用 {\"type\":\"function\"} 可以写自定义的JS脚本。\n本塔支持的所有主要API会在doc文档内给出。", "\t[老人,womanMagician]例如这个例子:即将弹出一个输入窗口,然后会将你的输入结果直接加到你的攻击力上。", + /* {"type": "function", "function": function() { // 自己写JS脚本并执行 // 注意一下prompt对于录像是如何处理的 @@ -289,6 +284,18 @@ main.floors.sample1 = { ]); } }}, + */ + {"type": "input", "text": "请输入你要加攻击力的数值:"}, + {"type": "if", "condition": "flag:input>0", + "true": [ + {"type": "setValue", "name": "status:atk", "value": "status:atk+flag:input"}, + {"type": "tip", "text": "操作成功,攻击+${flag:input}"}, + "操作成功,攻击+${flag:input}" + ], + "false": [ + + ] + }, "\t[老人,womanMagician]具体可参见样板中本事件的写法。" ] }, diff --git a/libs/floors/sample2.js b/libs/floors/sample2.js index d57b5b2f..c24c78f0 100644 --- a/libs/floors/sample2.js +++ b/libs/floors/sample2.js @@ -175,10 +175,7 @@ main.floors.sample2 = { {"type": "changePos", "direction": "up"}, {"type": "playSound", "name": "item.ogg"}, "\t[blackMagician]出来吧!禁忌——紫电凶杀阵!", - {"type": "show", "loc": [4,3], "time": 500}, // 依次显示四个角的法师 - {"type": "show", "loc": [4,6], "time": 500}, // 依次显示四个角的法师 - {"type": "show", "loc": [8,6], "time": 500}, // 依次显示四个角的法师 - {"type": "show", "loc": [8,3], "time": 500}, // 依次显示四个角的法师 + {"type": "show", "loc": [[4,3],[4,6],[8,6],[8,3]], "time": 500}, // 依次显示四个角的法师 {"type": "sleep", "time": 500}, "\t[blackMagician]感受绝望吧!冥顽不化的蠢货!", /* diff --git a/libs/maps.js b/libs/maps.js index 0db22e10..60f14182 100644 --- a/libs/maps.js +++ b/libs/maps.js @@ -355,9 +355,9 @@ maps.prototype.save = function(maps, floorId) { maps.prototype.load = function (data, floorId) { if (floorId == undefined) { var map = {}; - for (var id in data) { - map[id] = this.load(data, id); - } + core.floorIds.forEach(function (id) { + map[id] = core.maps.loadFloor(id, data[id]); + }) return map; } return this.loadFloor(floorId, data[floorId]); diff --git a/更新说明.txt b/更新说明.txt index e4171431..afec2ad2 100644 --- a/更新说明.txt +++ b/更新说明.txt @@ -2,6 +2,9 @@ 改变图块(setBlock事件)。 同一个点的多事件处理(做法详见文档)。 +增加新地图后可以接档而不用重新开始 +可以同时show/hide多个事件。 +增加可以接收用户输入的事件(type:prompt) 现在可以支持滑冰和推箱子事件了。 地图中每个块的可通行方向控制(悬崖效果)。 动画支持带旋转和翻转的帧。 From 1eb1e33fe18b0ad316a835a78afeb2e0387ac00b Mon Sep 17 00:00:00 2001 From: oc Date: Tue, 20 Feb 2018 17:51:14 +0800 Subject: [PATCH 2/3] Input, Show Multiple blocks, Load --- README.md | 4 ++-- docs/event.md | 4 ++-- 更新说明.txt | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 3d9aecdb..aa6b6e24 100644 --- a/README.md +++ b/README.md @@ -51,9 +51,9 @@ HTML5 canvas制作的魔塔样板,支持全平台游戏! * [x] 改变图块(setBlock事件)。 * [x] 同一个点的多事件处理(做法详见文档)。 -* [x] 增加新地图后可以接档而不用重新开始 +* [x] 增加新地图后可以接档而不用重新开始。 +* [x] 增加可以接收用户输入的事件(type:input)。 * [x] 可以同时show/hide多个事件。 -* [x] 增加可以接收用户输入的事件(type:prompt) * [x] 现在可以支持滑冰和推箱子事件了。 * [x] 地图中每个块的可通行方向控制(悬崖效果)。 * [x] 动画支持带旋转和翻转的帧。 diff --git a/docs/event.md b/docs/event.md index 8a89fe88..403aa69c 100644 --- a/docs/event.md +++ b/docs/event.md @@ -332,8 +332,8 @@ value是一个表达式,将通过这个表达式计算出的结果赋值给nam ``` js "x,y": [ // 实际执行的事件列表 - {"type": "show", "loc": [3,6], "floorId": "MT1", "time": 500 } // 启用MT1层[3,6]位置事件,动画500ms - {"type": "show", "loc": [3,6], "time": 500 } // 如果启用目标是当前层,则可以省略floorId项 + {"type": "show", "loc": [3,6], "floorId": "MT1", "time": 500}, // 启用MT1层[3,6]位置事件,动画500ms + {"type": "show", "loc": [3,6], "time": 500}, // 如果启用目标是当前层,则可以省略floorId项 {"type": "show", "loc": [3,6]}, // 如果不指定动画时间,则立刻显示,否则动画效果逐渐显示,time为动画时间 {"type": "show", "loc": [[3,6],[2,9],[1,2]], "time": 500} // 我们也可以同时动画显示多个点。 ] diff --git a/更新说明.txt b/更新说明.txt index afec2ad2..ffbff98f 100644 --- a/更新说明.txt +++ b/更新说明.txt @@ -2,9 +2,9 @@ 改变图块(setBlock事件)。 同一个点的多事件处理(做法详见文档)。 -增加新地图后可以接档而不用重新开始 +增加新地图后可以接档而不用重新开始。 +增加可以接收用户输入的事件(type:input)。 可以同时show/hide多个事件。 -增加可以接收用户输入的事件(type:prompt) 现在可以支持滑冰和推箱子事件了。 地图中每个块的可通行方向控制(悬崖效果)。 动画支持带旋转和翻转的帧。 From 89bd795cf0da23180828701e3cb5d516de3e028e Mon Sep 17 00:00:00 2001 From: YouWei Zhao Date: Tue, 20 Feb 2018 20:45:18 +0800 Subject: [PATCH 3/3] =?UTF-8?q?blockly=E4=B8=AD=E6=94=AF=E6=8C=81show=20hi?= =?UTF-8?q?de=E5=A4=9A=E4=BA=8B=E4=BB=B6=E4=BB=A5=E5=8F=8Atype:input?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _server/blockly/MotaAction.g4 | 60 ++++++++++++++++++++++++++++++----- _server/editor_blockly.js | 8 ++--- project/comment.js | 5 ++- 3 files changed, 58 insertions(+), 15 deletions(-) diff --git a/_server/blockly/MotaAction.g4 b/_server/blockly/MotaAction.g4 index a350fc9c..c9b936d5 100644 --- a/_server/blockly/MotaAction.g4 +++ b/_server/blockly/MotaAction.g4 @@ -187,6 +187,7 @@ action | win_s | lose_s | if_s + | input_s | choices_s | function_s | pass_s @@ -279,17 +280,23 @@ return code; */ show_s - : '显示事件' 'x' Int ',' 'y' Int '楼层' IdString? '动画时间' Int? Newline + : '显示事件' 'x' EvalString ',' 'y' EvalString '楼层' IdString? '动画时间' Int? Newline ; /* show_s -tooltip : show: 将一个禁用事件启用,楼层和动画时间可不填 +tooltip : show: 将禁用事件启用,楼层和动画时间可不填,xy可用逗号分隔表示多个点 helpUrl : https://ckcz123.github.io/mota-js/#/event?id=show-%e5%b0%86%e4%b8%80%e4%b8%aa%e7%a6%81%e7%94%a8%e4%ba%8b%e4%bb%b6%e5%90%af%e7%94%a8 default : [0,0,"",500] colour : this.eventColor IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"'); -Int_2 = Int_2 ?(', "time": '+Int_2):''; -var code = '{"type": "show", "loc": ['+Int_0+','+Int_1+']'+IdString_0+''+Int_2+'},\n'; +var pattern = /^(\d|1[0-2])(,\d|1[0-2])*$/; +if(!pattern.test(EvalString_0) || !pattern.test(EvalString_1))throw new Error('坐标格式错误,请右键点击帮助查看格式'); +EvalString_0=EvalString_0.split(','); +EvalString_1=EvalString_1.split(','); +if(EvalString_0.length!==EvalString_1.length)throw new Error('坐标格式错误,请右键点击帮助查看格式'); +for(var ii=0;ii', MotaActionBlocks['setValue_s'].xmlText(), + MotaActionBlocks['input_s'].xmlText(), MotaActionBlocks['update_s'].xmlText(), MotaActionBlocks['moveHero_s'].xmlText(), MotaActionBlocks['changeFloor_s'].xmlText(), @@ -154,12 +155,7 @@ initscript=String.raw` } ] },'event'), - '', - MotaActionFunctions.actionParser.parseList([ - {"type": "setValue", "name": "flag:inputMsg", "value": "请输入密码"}, - {"type": "function", "function": "function(){core.setFlag('input',prompt(core.getFlag('inputMsg','请输入字符串'),'xxx')||'')}"}, - {"type": "if", "condition": 'flag:input == "123456"',"true": [],"false": []}, - ]), + ], } var toolboxgap = '' diff --git a/project/comment.js b/project/comment.js index 545b6af8..23761025 100644 --- a/project/comment.js +++ b/project/comment.js @@ -18,13 +18,16 @@ comment_c456ea59_6018_45ef_8bcc_211a24c627dc = 'def': '防御力', 'money': '金币', 'experience': '经验', - 'special': '特殊属性\n\n0:无,1:先攻,2:魔攻,3:坚固,4:2连击,\n5:3连击,6:n连击,7:破甲,8:反击,9:净化,\n10:模仿,11:吸血,12:中毒,13:衰弱,14:诅咒,\n15:领域,16:夹击,17:仇恨,18:阻击,19:自爆,\n20:无敌\n\n多个属性例如用[1,4,11]表示先攻2连击吸血\n模仿怪的攻防设为0就好\n$leaf(true)$end', + 'special': '特殊属性\n\n0:无,1:先攻,2:魔攻,3:坚固,4:2连击,\n5:3连击,6:n连击,7:破甲,8:反击,9:净化,\n10:模仿,11:吸血,12:中毒,13:衰弱,14:诅咒,\n15:领域,16:夹击,17:仇恨,18:阻击,19:自爆,\n20:无敌,21:退化,22:固伤\n\n多个属性例如用[1,4,11]表示先攻2连击吸血\n模仿怪的攻防设为0就好\n$leaf(true)$end', 'value': '特殊属性的数值\n领域怪需要加value表示领域伤害的数值\n吸血怪需要在后面添加value代表吸血比例', 'zoneSquare': '领域怪zoneSquare代表是否九宫格伤害', 'range': 'range可选,代表领域伤害的范围;不加默认为1\n$range((thiseval==~~thiseval && thiseval>0)||thiseval==null)$end', 'bomb':' 加入 "bomb": false 代表该怪物不可被炸弹或圣锤炸掉\n$select({\"values\":[true,false]})$end', 'point': 'point可以在打败怪物后进行加点,详见文档说明\n$range((thiseval==~~thiseval && thiseval>0)||thiseval==null)$end', 'n': '多连击需要在后面指定n代表是几连击\n$range((thiseval==~~thiseval && thiseval>0)||thiseval==null)$end', + 'atkValue':'退化时勇士下降的攻击力点数\n$range(thiseval==~~thiseval||thiseval==null)$end', + 'defValue':'退化时勇士下降的防御力点数\n$range(thiseval==~~thiseval||thiseval==null)$end', + 'damage':'战前扣血的点数\n$range(thiseval==~~thiseval||thiseval==null)$end' }, "enemys_template" : {'name': '新敌人', 'hp': 0, 'atk': 0, 'def': 0, 'money': 0, 'experience': 0, 'special': 0}, "floors" : {