diff --git a/_docs/event.md b/_docs/event.md index 9fd851a4..e5a2b7b9 100644 --- a/_docs/event.md +++ b/_docs/event.md @@ -1502,7 +1502,7 @@ text为提示文字,可以在这里给输入提示文字。这里同样可以 {"case": "a", "action": [// 若表达式的值等于a则执行该处事件 ], - {"case": "b", "action": [// 若表达式的值等于b则执行该处事件 + {"case": "b", "nobreak": true, "action": [// 若表达式的值等于b则执行该处事件,不跳出 ], {"case": "default", "action": [ // 没有条件成立则执行该处里的事件 @@ -1519,6 +1519,8 @@ text为提示文字,可以在这里给输入提示文字。这里同样可以 如果没有符合的值,则将执行`default`中的列表事件内容。 +nobreak是可选的,如果设置,则在当前条件满足并插入事件后,不跳出多重分歧,而是继续判定下一个条件。 + 例如下面这个例子,将检查当前游戏难度并赠送不同属性。 ``` js @@ -1551,7 +1553,7 @@ text为提示文字,可以在这里给输入提示文字。这里同样可以 - 即使某个场合不执行事件,对应的action数组也需要存在,不过简单的留空就好。 - switch语句内的内容执行完毕后将接着其后面的语句继续执行。 -由于`case`中的内容是会被计算的,因此如下写法也是合法的 +另外由于`case`中的内容是会被计算的,因此如下写法也是合法的 ```js [ @@ -1614,6 +1616,32 @@ icon是可选的,如果设置则会在选项前绘制图标,其可以是一 选项可以有任意多个,但一般不要超过6个,否则屏幕可能塞不下。 +### confirm:显示确认框 + +`{"type": "confirm"}`将提供一个确认框供用户选择,其基本写法如下: + +```js +[ + {"type": "confirm", "text": "...", // 提示文字 + "default": false, // 是否默认选中【确定】 + "yes": [ + // 点击确定时执行的事件 + ], + "no": [ + // 点击取消时执行的事件 + ] + }, +] +``` + +text为必填项,代表提示的文字,支持${}的表达式计算和\n的手动换行。 + +text暂时不支持自动换行、变色\r、图标绘制\i等效果。如有需求请使用choices事件。 + +default可选,如果为true则显示选择项时默认选中【确定】,否则默认选中【取消】。 + +yes和no均为必填项,即用户点击确认或取消后执行的事件。 + ### while:循环处理 从2.2.1样板开始,我们提供了循环处理(while事件)。 diff --git a/_docs/personalization.md b/_docs/personalization.md index 3341f2dd..c8f517e6 100644 --- a/_docs/personalization.md +++ b/_docs/personalization.md @@ -714,4 +714,4 @@ if (core.flags.enableSkill) { ========================================================================================== -[继续阅读脚本](api) +[继续阅读脚本](script) diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4 index aee1ed18..a43d0c9a 100644 --- a/_server/MotaAction.g4 +++ b/_server/MotaAction.g4 @@ -1604,14 +1604,16 @@ return code; */; switchCase - : '如果是' expression '的场合' BGNL? Newline action+ + : '如果是' expression '的场合' '不跳出' Bool BGNL? Newline action+ /* switchCase tooltip : 选项的选择 helpUrl : https://h5mota.com/games/template/docs/#/event?id=switch%EF%BC%9A%E5%A4%9A%E9%87%8D%E6%9D%A1%E4%BB%B6%E5%88%86%E6%AD%A7 +default : ["", false] colour : this.subColor -var code = '{"case": "'+expression_0+'", "action": [\n'+action_0+']},\n'; +Bool_0 = Bool_0?', "nobreak": true':''; +var code = '{"case": "'+expression_0+'"'+Bool_0+', "action": [\n'+action_0+']},\n'; return code; */; @@ -1640,13 +1642,13 @@ return code; */; choicesContext - : '子选项' EvalString '图标' IdString? '颜色' EvalString? Colour '不跳出' Bool BGNL? Newline action+ + : '子选项' EvalString '图标' IdString? '颜色' EvalString? Colour BGNL? Newline action+ /* choicesContext tooltip : 选项的选择 helpUrl : https://h5mota.com/games/template/docs/#/event?id=choices%EF%BC%9A%E7%BB%99%E7%94%A8%E6%88%B7%E6%8F%90%E4%BE%9B%E9%80%89%E9%A1%B9 -default : ["提示文字:红钥匙","","",null,false] +default : ["提示文字:红钥匙","",""] colour : this.subColor if (EvalString_1) { var colorRe = /^(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d),(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d),(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(,0(\.\d+)?|,1)?$/; @@ -1656,19 +1658,19 @@ if (EvalString_1) { EvalString_1 = ', "color": "'+EvalString_1+'"'; } IdString_0 = IdString_0?(', "icon": "'+IdString_0+'"'):''; -var nobreak = Bool_0?', "nobreak": true':''; -var code = '{"text": "'+EvalString_0+'"'+IdString_0+EvalString_1+', "action": [\n'+action_0+']'+nobreak+'},\n'; +var code = '{"text": "'+EvalString_0+'"'+IdString_0+EvalString_1+', "action": [\n'+action_0+']},\n'; return code; */; confirm_s - : '显示确认框' ':' EvalString BGNL? '确定' ':' BGNL? Newline action+ '取消' ':' BGNL? Newline action+ BEND Newline + : '显示确认框' ':' EvalString BGNL? '确定的场合' ':' '(默认选中' Bool ')' BGNL? Newline action+ '取消的场合' ':' BGNL? Newline action+ BEND Newline /* confirm_s tooltip : 弹出确认框 helpUrl : https://h5mota.com/games/template/docs/#/ -default : ["确认要???吗?"] -var code = ['{"type": "confirm", "text": "',EvalString_0,'",\n', +default : ["确认要xxx吗?",false] +Bool_0 = Bool_0?', "default": true':'' +var code = ['{"type": "confirm"'+Bool_0+', "text": "',EvalString_0,'",\n', '"yes": [\n',action_0,'],\n', '"no": [\n',action_1,']\n', '},\n'].join(''); @@ -2590,7 +2592,7 @@ ActionParser.prototype.parseAction = function() { break; case "confirm": // 显示确认框 this.next = MotaActionBlocks['confirm_s'].xmlText([ - this.EvalString(data.text), + this.EvalString(data.text), data["default"], this.insertActionList(data["yes"]), this.insertActionList(data["no"]), this.next]); @@ -2599,7 +2601,7 @@ ActionParser.prototype.parseAction = function() { var case_caseList = null; for(var ii=data.caseList.length-1,caseNow;caseNow=data.caseList[ii];ii--) { case_caseList=MotaActionBlocks['switchCase'].xmlText([ - this.isset(caseNow.case)?MotaActionBlocks['evalString_e'].xmlText([caseNow.case]):"值",this.insertActionList(caseNow.action),case_caseList]); + this.isset(caseNow.case)?MotaActionBlocks['evalString_e'].xmlText([caseNow.case]):"值",caseNow.nobreak,this.insertActionList(caseNow.action),case_caseList]); } this.next = MotaActionBlocks['switch_s'].xmlText([ // MotaActionBlocks['evalString_e'].xmlText([data.condition]), @@ -2610,7 +2612,7 @@ ActionParser.prototype.parseAction = function() { var text_choices = null; for(var ii=data.choices.length-1,choice;choice=data.choices[ii];ii--) { text_choices=MotaActionBlocks['choicesContext'].xmlText([ - choice.text,choice.icon,choice.color,'rgba('+choice.color+')',choice.nobreak,this.insertActionList(choice.action),text_choices]); + choice.text,choice.icon,choice.color,'rgba('+choice.color+')',this.insertActionList(choice.action),text_choices]); } this.next = MotaActionBlocks['choices_s'].xmlText([ this.isset(data.text)?this.EvalString(data.text):null,'','',text_choices,this.next]); diff --git a/_server/editor_blockly.js b/_server/editor_blockly.js index 09ba5f45..1c81e65c 100644 --- a/_server/editor_blockly.js +++ b/_server/editor_blockly.js @@ -70,9 +70,9 @@ editor_blockly = function () { MotaActionBlocks['lose_s'].xmlText(), MotaActionBlocks['choices_s'].xmlText([ '选择剑或者盾','流浪者','man',MotaActionBlocks['choicesContext'].xmlText([ - '剑','','',null,null,MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [3,3]}]), + '剑','','',null,MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [3,3]}]), MotaActionBlocks['choicesContext'].xmlText([ - '盾','','',null,null,MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [9,3]}]), + '盾','','',null,MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [9,3]}]), ]) ]) ]), @@ -113,7 +113,7 @@ editor_blockly = function () { MotaActionBlocks['if_s'].xmlText(), MotaActionFunctions.actionParser.parseList({"type": "switch", "condition": "判别值", "caseList": [ {"action": [{"type": "comment", "text": "当判别值是值的场合执行此事件"}]}, - {"action": []}, + {"action": [], "nobreak": true}, {"case": "default", "action": [{"type": "comment", "text": "当没有符合的值的场合执行default事件"}]}, ]}), MotaActionBlocks['while_s'].xmlText(), diff --git a/libs/actions.js b/libs/actions.js index 2d516b52..bb0cce1f 100644 --- a/libs/actions.js +++ b/libs/actions.js @@ -892,6 +892,19 @@ actions.prototype._clickAction = function (x, y) { } } } + + if (core.status.event.data.type == 'confirm') { + if ((x == this.HSIZE-2 || x == this.HSIZE-1) && y == this.HSIZE+1) { + core.status.route.push("choices:0"); + core.insertAction(core.status.event.ui.yes); + core.doAction(); + } + if ((x == this.HSIZE+2 || x == this.HSIZE+1) && y == this.HSIZE+1) { + core.status.route.push("choices:1"); + core.insertAction(core.status.event.ui.no); + core.doAction(); + } + } } ////// 自定义事件时,按下某个键的操作 ////// @@ -899,6 +912,10 @@ actions.prototype._keyDownAction = function (keycode) { if (core.status.event.data.type == 'choices') { this._keyDownChoices(keycode); } + if (core.status.event.data.type == 'confirm' && (keycode == 37 || keycode == 39)) { + core.status.event.selection = 1 - core.status.event.selection; + core.drawConfirmBox(core.status.event.ui.text); + } } ////// 自定义事件时,放开某个键的操作 ////// @@ -924,6 +941,15 @@ actions.prototype._keyUpAction = function (keycode) { if (choices.length > 0) { this._selectChoices(choices.length, keycode, this._clickAction); } + return; + } + if (core.status.event.data.type == 'confirm'&& (keycode == 13 || keycode == 32 || keycode == 67)) { + core.status.route.push("choices:" + core.status.event.selection); + if (core.status.event.selection == 0) + core.insertAction(core.status.event.ui.yes); + else core.insertAction(core.status.event.ui.no); + core.doAction(); + return; } } diff --git a/libs/events.js b/libs/events.js index 6b3d5beb..b5b1170f 100644 --- a/libs/events.js +++ b/libs/events.js @@ -1329,13 +1329,16 @@ events.prototype._action_if = function (data, x, y, prefix) { events.prototype._action_switch = function (data, x, y, prefix) { var key = core.calValue(data.condition, prefix) + var list = []; for (var i = 0; i < data.caseList.length; i++) { var condition = data.caseList[i]["case"]; if (condition == "default" || core.calValue(condition, prefix) == key) { - this.insertAction(data.caseList[i].action); - break; + core.push(list, data.caseList[i].action); + if (!data.caseList[i].nobreak) + break; } } + core.insertAction(list); core.doAction(); } @@ -1363,6 +1366,35 @@ events.prototype._action_choices = function (data, x, y, prefix) { core.ui.drawChoices(data.text, data.choices); } +events.prototype._action_confirm = function (data, x, y, prefix) { + core.status.event.ui = {"text": data.text, "yes": data.yes, "no": data.no}; + if (core.isReplaying()) { + var action = core.status.replay.toReplay.shift(), index; + // --- 忽略可能的turn事件 + if (action == 'turn') action = core.status.replay.toReplay.shift(); + if (action.indexOf("choices:") == 0 && ((index = parseInt(action.substring(8))) >= 0) && index < 2) { + core.status.event.selection = index; + setTimeout(function () { + core.status.route.push("choices:" + index); + if (index == 0) core.insertAction(data.yes); + else core.insertAction(data.no); + core.doAction(); + }, 750 / Math.max(1, core.status.replay.speed)) + } + else { + main.log("录像文件出错!当前需要一个 choices: 项,实际为 " + action); + core.stopReplay(); + core.insertAction(["录像文件出错,请在控制台查看报错信息。", {"type": "exit"}]); + core.doAction(); + return; + } + } + else { + core.status.event.selection = data["default"] ? 0 : 1; + } + core.ui.drawConfirmBox(data.text); +} + events.prototype._action_while = function (data, x, y, prefix) { if (core.calValue(data.condition, prefix)) { core.unshift(core.status.event.data.list, diff --git a/libs/ui.js b/libs/ui.js index 54dbccc1..db1a09e9 100644 --- a/libs/ui.js +++ b/libs/ui.js @@ -1081,9 +1081,12 @@ ui.prototype.drawConfirmBox = function (text, yesCallback, noCallback) { core.lockControl(); text = core.replaceText(text || ""); - core.status.event.id = 'confirmBox'; - core.status.event.data = {'yes': yesCallback, 'no': noCallback}; - core.status.event.ui = text; + // 处理自定义事件 + if (core.status.event.id != 'action') { + core.status.event.id = 'confirmBox'; + core.status.event.data = {'yes': yesCallback, 'no': noCallback}; + } + if (core.status.event.selection != 0) core.status.event.selection = 1; this.clearUI();