From 78f4210eb710118dfc37ce12a01edff988dc3bba Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Fri, 8 May 2020 15:13:47 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0for/forEach=E4=BA=8B=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _docs/_api.md | 2 +- _server/MotaAction.g4 | 51 +++++++++++++++++++++++- _server/editor_blockly.js | 6 +-- libs/events.js | 81 +++++++++++++++++++++++++++++++++++---- libs/ui.js | 4 +- libs/utils.js | 4 +- runtime.d.ts | 2 +- 7 files changed, 131 insertions(+), 19 deletions(-) diff --git a/_docs/_api.md b/_docs/_api.md index 8b15582f..5bd7cb23 100644 --- a/_docs/_api.md +++ b/_docs/_api.md @@ -287,7 +287,7 @@ core.closePanel() 结束一切事件和绘制,关闭UI窗口,返回游戏进程。 -core.replaceText(text) +core.replaceText(text, prefix, need, times) 将一段文字中的${}进行计算并替换。 diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4 index 4589daec..84819759 100644 --- a/_server/MotaAction.g4 +++ b/_server/MotaAction.g4 @@ -1,3 +1,5 @@ +// 编辑此文件用的vscode插件: https://marketplace.visualstudio.com/items?itemName=zhaouv.vscode-mota-js-extension + grammar MotaAction; //===============parser=============== @@ -400,6 +402,8 @@ action | if_s | if_1_s | switch_s + | for_s + | forEach_s | while_s | dowhile_s | break_s @@ -1936,6 +1940,35 @@ var code = ['{"type": "confirm"'+Int_0+Bool_0+', "text": "',EvalString_0,'",\n', return code; */; +for_s + : '循环遍历' ': ' expression '从' EvalString '到' EvalString '步增' EvalString BGNL? Newline action+ BEND Newline + +/* for_s +tooltip : for:循环遍历 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=while%ef%bc%9a%e5%89%8d%e7%bd%ae%e6%9d%a1%e4%bb%b6%e5%be%aa%e7%8e%af +colour : this.eventColor +if (!/^switch:[A-Z]$/.test(expression_0)) { + throw new Error('循环遍历仅允许使用独立开关!'); +} +return '{"type": "for", "name": "'+expression_0+'", "from": "'+EvalString_0+'", "to": "'+EvalString_1+'", "step": "'+EvalString_2+'",\n"data": [\n'+action_0+']},\n'; +*/; + +forEach_s + : '循环遍历' ': ' expression '在列表' JsonEvalString '中' BGNL? Newline action+ BEND Newline + +/* forEach_s +tooltip : forEach:循环遍历列表 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=while%ef%bc%9a%e5%89%8d%e7%bd%ae%e6%9d%a1%e4%bb%b6%e5%be%aa%e7%8e%af +colour : this.eventColor +if (!/^switch:[A-Z]$/.test(expression_0)) { + throw new Error('循环遍历仅允许使用独立开关!'); +} +if (JsonEvalString_0 == '' || !(JSON.parse(JsonEvalString_0) instanceof Array)) { + throw new Error('参数列表必须是个有效的数组!'); +} +return '{"type": "forEach", "name": "'+expression_0+'", "list": '+JsonEvalString_0 + ',\n"data": [\n'+action_0+']},\n'; +*/; + while_s : '前置条件循环' ':' '当' expression '时' BGNL? Newline action+ BEND Newline @@ -3529,16 +3562,30 @@ ActionParser.prototype.parseAction = function() { this.next = MotaActionBlocks['choices_s'].xmlText([ info[3],info[0],info[1],data.timeout||0,text_choices,this.next]); break; + case "for": // 循环遍历 + this.next = MotaActionBlocks['for_s'].xmlText([ + this.tryToUseEvFlag_e('evalString_e', [data.name]), + data.from || 0, data.to || 0, data.step || 0, + this.insertActionList(data.data), + this.next]); + break; + case "forEach": // 循环遍历列表 + this.next = MotaActionBlocks['forEach_s'].xmlText([ + this.tryToUseEvFlag_e('evalString_e', [data.name]), + JSON.stringify(data.list), + this.insertActionList(data.data), + this.next]); + break; case "while": // 前置条件循环处理 this.next = MotaActionBlocks['while_s'].xmlText([ // MotaActionBlocks['evalString_e'].xmlText([data.condition]), this.tryToUseEvFlag_e('evalString_e', [data.condition]), - this.insertActionList(data["data"]), + this.insertActionList(data.data), this.next]); break; case "dowhile": // 后置条件循环处理 this.next = MotaActionBlocks['dowhile_s'].xmlText([ - this.insertActionList(data["data"]), + this.insertActionList(data.data), // MotaActionBlocks['evalString_e'].xmlText([data.condition]), this.tryToUseEvFlag_e('evalString_e', [data.condition]), this.next]); diff --git a/_server/editor_blockly.js b/_server/editor_blockly.js index 1ea29fed..95e35786 100644 --- a/_server/editor_blockly.js +++ b/_server/editor_blockly.js @@ -93,9 +93,6 @@ editor_blockly = function () { MotaActionBlocks['choices_s'].xmlText([ '选择剑或者盾','流浪者','man',0,MotaActionBlocks['choicesContext'].xmlText([ '剑','','',null,'',MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [3,3]}]), - MotaActionBlocks['choicesContext'].xmlText([ - '盾','','',null,'',MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [9,3]}]), - ]) ]) ]), ], @@ -149,9 +146,10 @@ editor_blockly = function () { MotaActionBlocks['if_s'].xmlText(), MotaActionFunctions.actionParser.parseList({"type": "switch", "condition": "判别值", "caseList": [ {"action": [{"type": "comment", "text": "当判别值是值的场合执行此事件"}]}, - {"action": [], "nobreak": true}, {"case": "default", "action": [{"type": "comment", "text": "当没有符合的值的场合执行default事件"}]}, ]}), + MotaActionFunctions.actionParser.parseList({"type": "for", "name": "switch:A", "from": "0", "to": "12", "step": "1", "data": []}), + MotaActionFunctions.actionParser.parseList({"type": "forEach", "name": "switch:A", "list": ["status:atk","status:def"], "data": []}), MotaActionBlocks['while_s'].xmlText(), MotaActionBlocks['dowhile_s'].xmlText(), MotaActionBlocks['break_s'].xmlText(), diff --git a/libs/events.js b/libs/events.js index a484d97c..437a7a3e 100644 --- a/libs/events.js +++ b/libs/events.js @@ -1210,17 +1210,20 @@ events.prototype.__action_doAsyncFunc = function (isAsync, func) { events.prototype._action_text = function (data, x, y, prefix) { if (this.__action_checkReplaying()) return; + data.text = core.replaceText(data.text, prefix); core.ui.drawTextBox(data.text, data.showAll); } events.prototype._action_autoText = function (data, x, y, prefix) { if (this.__action_checkReplaying()) return; + data.text = core.replaceText(data.text, prefix); core.ui.drawTextBox(data.text); setTimeout(core.doAction, data.time || 3000); } events.prototype._action_scrollText = function (data, x, y, prefix) { if (this.__action_checkReplaying()) return; + data.text = core.replaceText(data.text, prefix); this.__action_doAsyncFunc(data.async, core.drawScrollText, data.text, data.time || 5000, data.lineHeight || 1.4); } @@ -1250,7 +1253,7 @@ events.prototype._action_setText = function (data, x, y, prefix) { } events.prototype._action_tip = function (data, x, y, prefix) { - core.drawTip(core.replaceText(data.text), data.icon); + core.drawTip(core.replaceText(data.text, prefix), data.icon); core.doAction(); } @@ -1412,6 +1415,7 @@ events.prototype._precompile_showImage = function (data) { events.prototype._action_showTextImage = function (data, x, y, prefix) { var loc = this.__action_getLoc(data.loc, 0, 0, prefix); if (core.isReplaying()) data.time = 0; + data.text = core.replaceText(data.text, prefix); this.__action_doAsyncFunc(data.async || data.time == 0, core.showImage, data.code, core.ui.textImage(data.text), null, loc, data.opacity, data.time); } @@ -1676,7 +1680,7 @@ events.prototype._action_setHeroIcon = function (data, x, y, prefix) { } events.prototype._action_input = function (data, x, y, prefix) { - this.__action_getInput(data.text, false, function (value) { + this.__action_getInput(core.replaceText(data.text, prefix), false, function (value) { value = Math.abs(parseInt(value) || 0); core.status.route.push("input:" + value); core.setFlag("input", value); @@ -1685,7 +1689,7 @@ events.prototype._action_input = function (data, x, y, prefix) { } events.prototype._action_input2 = function (data, x, y, prefix) { - this.__action_getInput(data.text, true, function (value) { + this.__action_getInput(core.replaceText(data.text, prefix), true, function (value) { value = value || ""; core.status.route.push("input2:" + core.encodeBase64(value)); core.setFlag("input", value); @@ -1782,7 +1786,7 @@ events.prototype._action_choices = function (data, x, y, prefix) { core.doAction(); }, data.timeout); } - core.ui.drawChoices(data.text, data.choices); + core.ui.drawChoices(core.replaceText(data.text, prefix), data.choices); } events.prototype._precompile_choices = function (data) { @@ -1796,7 +1800,7 @@ events.prototype._precompile_choices = function (data) { } events.prototype._action_confirm = function (data, x, y, prefix) { - core.status.event.ui = {"text": data.text, "yes": data.yes, "no": data.no}; + core.status.event.ui = {"text": core.replaceText(data.text, prefix), "yes": data.yes, "no": data.no}; if (core.isReplaying()) { var action = core.status.replay.toReplay.shift(); // --- 忽略可能的turn事件 @@ -1837,6 +1841,66 @@ events.prototype._precompile_confirm = function (data) { return data; } +events.prototype._action_for = function (data, x, y, prefix) { + // Only support switch:A + if (!/^switch:[A-Z]$/.test(data.name)) { + core.insertAction(['循环遍历事件只支持独立开关!']); + return core.doAction(); + } + var from = core.calValue(data.from); + if (typeof from != 'number') { + core.insertAction('循环遍历事件要求【起始点】仅能是数字!'); + return core.doAction(); + } + this._setValue_setSwitch(data.name, from, prefix); + var toName = '__for@to@' + prefix + '@' + data.name.substring(7) + '__'; + var stepName = '__for@step@' + prefix + '@' + data.name.substring(7) + '__'; + core.setFlag(toName, data.to); + core.setFlag(stepName, data.step); + var condition = "(function () {"+ + "var to = core.calValue(core.getFlag('" + toName + "'));"+ + "var step = core.calValue(core.getFlag('" + stepName + "'));"+ + "if (typeof step != 'number' || typeof to != 'number') return false;"+ + "if (step == 0) return true;"+ + "var currentValue = core.calValue('switch:'+'" + data.name.substring(7) + "', '"+prefix+"');"+ + "currentValue += step;"+ + "core.events._setValue_setSwitch('switch:'+'" + data.name.substring(7) + "', currentValue, '"+prefix+"');"+ + "if (step > 0) { return currentValue <= to; }"+ + "else { return currentValue >= to; }"+ + "})()"; + return this._action_dowhile({"condition": condition, "data": data.data}, x, y, prefix); +} + +events.prototype._precompile_for = function (data) { + data.from = core.replaceValue(data.from); + data.to = core.replaceValue(data.to); + data.step = core.replaceValue(data.step); + data.data = this.precompile(data.data); + return data; +} + +events.prototype._action_forEach = function (data, x, y, prefix) { + // Only support switch:A + if (!/^switch:[A-Z]$/.test(data.name)) { + core.insertAction(['循环遍历事件只支持独立开关!']); + return core.doAction(); + } + var listName = '__forEach@' + prefix + '@' + data.name.substring(7) + '__'; + core.setFlag(listName, core.clone(data.list)); + var condition = "(function () {" + + "var list = core.getFlag('"+listName+"', []);"+ + "if (list.length == 0) { core.removeFlag('" + listName + "'); return false; }"+ + "core.events._setValue_setSwitch('switch:'+'" + data.name.substring(7) + "', list.shift(), '"+prefix+"');"+ + "return true;"+ + "})()"; + return this._action_while({"condition": condition, "data": data.data}, x, y, prefix); +} + +events.prototype._precompile_forEach = function (data) { + data.data = this.precompile(data.data); + return data; +} + events.prototype._action_while = function (data, x, y, prefix) { if (core.calValue(data.condition, prefix)) { core.unshift(core.status.event.data.list, @@ -1881,11 +1945,11 @@ events.prototype._action_continue = function (data, x, y, prefix) { } events.prototype._action_win = function (data, x, y, prefix) { - this.win(core.replaceText(data.reason), data.norank, data.noexit); + this.win(core.replaceText(data.reason, prefix), data.norank, data.noexit); } events.prototype._action_lose = function (data, x, y, prefix) { - this.lose(core.replaceText(data.reason)); + this.lose(core.replaceText(data.reason, prefix)); } events.prototype._action_restart = function (data, x, y, prefix) { @@ -2129,10 +2193,12 @@ events.prototype._action_clearMap = function (data, x, y, prefix) { } events.prototype._action_fillText = function (data, x, y, prefix) { + data.text = core.replaceText(data.text, prefix); this.__action_doUIEvent(data); } events.prototype._action_fillBoldText = function (data, x, y, prefix) { + data.text = core.replaceText(data.text, prefix); this.__action_doUIEvent(data); } @@ -2199,6 +2265,7 @@ events.prototype._action_drawBackground = function (data, x, y, prefix) { } events.prototype._action_drawTextContent = function (data, x, y, prefix) { + data.text = core.replaceText(data.text, prefix); this.__action_doUIEvent(data); } diff --git a/libs/ui.js b/libs/ui.js index 803852f2..0cf54352 100644 --- a/libs/ui.js +++ b/libs/ui.js @@ -2023,12 +2023,12 @@ ui.prototype.drawShop = function (shopId) { core.status.event.selection = selection; var times = shop.times, need=core.calValue(shop.need, null, null, times); - var content = "\t["+shop.name+","+shop.icon+"]" + core.replaceText(shop.text, need, times); + var content = "\t["+shop.name+","+shop.icon+"]" + core.replaceText(shop.text, null, need, times); var use = shop.use=='experience'?'经验':'金币'; var choices = []; for (var i=0;i