From c8ca08cb788a528058d498aa5be4396a817db359 Mon Sep 17 00:00:00 2001 From: oc Date: Sun, 30 Dec 2018 00:38:24 +0800 Subject: [PATCH] callBook & callSave/Load --- _server/blockly/MotaAction.g4 | 54 ++++++++++ _server/editor_blockly.js | 3 + docs/event.md | 18 ++++ docs/personalization.md | 1 - libs/actions.js | 48 +++++++-- libs/control.js | 74 ++++++++++---- libs/events.js | 34 +++++++ project/data.js | 181 +++++++++++++++++----------------- project/functions.js | 31 ++++-- 9 files changed, 317 insertions(+), 127 deletions(-) diff --git a/_server/blockly/MotaAction.g4 b/_server/blockly/MotaAction.g4 index 591b0136..235bd9dc 100644 --- a/_server/blockly/MotaAction.g4 +++ b/_server/blockly/MotaAction.g4 @@ -294,6 +294,9 @@ action | input_s | input2_s | choices_s + | callBook_s + | callSave_s + | callLoad_s | function_s | pass_s ; @@ -1556,6 +1559,45 @@ return code; */; +callBook_s + : '呼出怪物手册' + + +/* callBook_s +tooltip : callBook: 呼出怪物手册;返回游戏后将继续执行后面的事件 +helpUrl : https://h5mota.com/games/template/docs/#/event?id=waitAsync%ef%bc%9a%e7%ad%89%e5%be%85%e6%89%80%e6%9c%89%e5%bc%82%e6%ad%a5%e4%ba%8b%e4%bb%b6%e6%89%a7%e8%a1%8c%e5%ae%8c%e6%af%95 +colour : this.soundColor +var code = '{"type": "callBook"},\n'; +return code; +*/; + + +callSave_s + : '呼出存档页面' + + +/* callSave_s +tooltip : callSave: 呼出存档页面;之后读此档将执行eachArrive +helpUrl : https://h5mota.com/games/template/docs/#/event?id=waitAsync%ef%bc%9a%e7%ad%89%e5%be%85%e6%89%80%e6%9c%89%e5%bc%82%e6%ad%a5%e4%ba%8b%e4%bb%b6%e6%89%a7%e8%a1%8c%e5%ae%8c%e6%af%95 +colour : this.soundColor +var code = '{"type": "callSave"},\n'; +return code; +*/; + + +callLoad_s + : '呼出读档页面' + + +/* callLoad_s +tooltip : callLoad: 呼出存档页面;返回游戏后将继续执行后面的事件 +helpUrl : https://h5mota.com/games/template/docs/#/event?id=waitAsync%ef%bc%9a%e7%ad%89%e5%be%85%e6%89%80%e6%9c%89%e5%bc%82%e6%ad%a5%e4%ba%8b%e4%bb%b6%e6%89%a7%e8%a1%8c%e5%ae%8c%e6%af%95 +colour : this.soundColor +var code = '{"type": "callLoad"},\n'; +return code; +*/; + + function_s : '自定义JS脚本' '不自动执行下一个事件' Bool BGNL? Newline RawEvalString Newline BEND Newline @@ -2378,6 +2420,18 @@ ActionParser.prototype.parseAction = function() { this.next = MotaActionBlocks['revisit_s'].xmlText([ this.next]); break; + case "callBook": // 呼出怪物手册 + this.next = MotaActionBlocks['callBook_s'].xmlText([ + this.next]); + break; + case "callSave": // 呼出存档界面 + this.next = MotaActionBlocks['callSave_s'].xmlText([ + this.next]); + break; + case "callLoad": // 呼出读档界面 + this.next = MotaActionBlocks['callLoad_s'].xmlText([ + this.next]); + break; case "exit": // 立刻结束事件 this.next = MotaActionBlocks['exit_s'].xmlText([ this.next]); diff --git a/_server/editor_blockly.js b/_server/editor_blockly.js index 2339341e..dcf7a288 100644 --- a/_server/editor_blockly.js +++ b/_server/editor_blockly.js @@ -150,6 +150,9 @@ editor_blockly = function () { MotaActionBlocks['freeBgm_s'].xmlText(), MotaActionBlocks['playSound_s'].xmlText(), MotaActionBlocks['setVolume_s'].xmlText(), + MotaActionBlocks['callBook_s'].xmlText(), + MotaActionBlocks['callSave_s'].xmlText(), + MotaActionBlocks['callLoad_s'].xmlText(), ], '原生脚本':[ MotaActionBlocks['function_s'].xmlText(), diff --git a/docs/event.md b/docs/event.md index 25c6e73b..f5815ed1 100644 --- a/docs/event.md +++ b/docs/event.md @@ -1308,6 +1308,24 @@ async可选,如果为true则会异步执行(即不等待当前事件执行 该事件会显示失败页面,并重新开始游戏。 +### callBook:呼出怪物手册 + +`{"type": "callBook"}` 可以呼出怪物手册,玩家可以自由查看当前楼层怪物数据和详细信息。 + +返回游戏后将继续执行后面的事件。没有怪物手册或在录像播放中,则会跳过本事件。 + +### callSave:呼出存档界面 + +`{"type": "callSave"}` 可以呼出存档页面并允许玩家存一次档。 + +在玩家进行一次存档,或者直接点返回游戏后,将接着执行后面的事件。录像播放将会跳过本事件。 + +### callLoad:呼出读档界面 + +`{"type": "callLoad"}` 可以呼出读档页面并允许玩家进行读档。 + +如果玩家没有进行读档而是直接返回游戏,则会继续执行后面的事件。录像播放将会跳过本事件。 + ### input:接受用户输入数字 使用`{"type": "input"}`可以接受用户的输入的数字。 diff --git a/docs/personalization.md b/docs/personalization.md index 6209c2dd..208b85a7 100644 --- a/docs/personalization.md +++ b/docs/personalization.md @@ -957,7 +957,6 @@ this.getAchievements = function () { - **`flag:saveEquips`**: 快速换装时保存的套装。 - **`flag:__visited__`**: 当前访问过的楼层。 - **`flag:equip_atk_buff`**, **`flag:equip_def_buff`**, **`flag:equip_mdef_buff`**: 当前攻防魔防的实际计算比例加成。 -- **`flag:forceSave`**: 是否允许事件中强制自动存档。如果将此项置为true并调用core.autosave()即可在事件中强制自动存档,读档时会自动执行该楼层的`eachArrive`事件。 - **`flag:__color__`**, **`flag:__weather__`**, **`flag:__volume__`**: 当前的画面色调、天气和音量。 - **`flag:textAttribute`**, **`flag:globalAttribute`**, **`flag:globalFlags`**: 当前的剧情文本属性,当前的全局属性,当前的全局开关。 - **`flag:cannotMoveDirectly`**, **`flag:clickMove`**: 当前是否不允许瞬间移动,当前用户是否开启了单击瞬移。 diff --git a/libs/actions.js b/libs/actions.js index 978d7499..d37b2fa3 100644 --- a/libs/actions.js +++ b/libs/actions.js @@ -886,12 +886,19 @@ actions.prototype.clickBook = function(x,y) { } // 返回 if (x>=10 && x<=12 && y==12) { - if (core.status.event.selection==null) + if (core.status.event.interval != null) { + var data = core.status.event.interval; core.ui.closePanel(); - else { - core.status.boxAnimateObjs = []; - core.ui.drawMaps(core.status.event.selection); + core.lockControl(); + core.status.event.id = 'action'; + core.status.event.data = data; + core.doAction(); } + else if (core.status.event.ui != null) { + core.status.boxAnimateObjs = []; + core.ui.drawMaps(core.status.event.ui); + } + else core.ui.closePanel(); return; } // 怪物信息 @@ -919,12 +926,19 @@ actions.prototype.keyDownBook = function (keycode) { ////// 怪物手册界面时,放开某个键的操作 ////// actions.prototype.keyUpBook = function (keycode) { if (keycode==27 || keycode==88) { - if (core.status.event.selection==null) + if (core.status.event.interval != null) { + var data = core.status.event.interval; core.ui.closePanel(); - else { - core.status.boxAnimateObjs = []; - core.ui.drawMaps(core.status.event.selection); + core.lockControl(); + core.status.event.id = 'action'; + core.status.event.data = data; + core.doAction(); } + else if (core.status.event.ui != null) { + core.status.boxAnimateObjs = []; + core.ui.drawMaps(core.status.event.ui); + } + else core.ui.closePanel(); return; } if (keycode==13 || keycode==32 || keycode==67) { @@ -1649,6 +1663,15 @@ actions.prototype.clickSL = function(x,y) { } // 返回 if (x>=10 && x<=12 && y==12) { + if (core.status.event.interval != null) { + var data = core.status.event.interval; + core.ui.closePanel(); + core.lockControl(); + core.status.event.id = 'action'; + core.status.event.data = data; + core.doAction(); + return; + } core.ui.closePanel(); if (!core.isPlaying()) { core.showStartAnimate(true); @@ -1761,6 +1784,15 @@ actions.prototype.keyUpSL = function (keycode) { var page = parseInt(index/10), offset=index%10; if (keycode==27 || keycode==88 || (core.status.event.id == 'save' && keycode==83) || (core.status.event.id == 'load' && keycode==68)) { + if (core.status.event.interval != null) { + var data = core.status.event.interval; + core.ui.closePanel(); + core.lockControl(); + core.status.event.id = 'action'; + core.status.event.data = data; + core.doAction(); + return; + } core.ui.closePanel(); if (!core.isPlaying()) { core.showStartAnimate(true); diff --git a/libs/control.js b/libs/control.js index 9be95f8b..c29990e2 100644 --- a/libs/control.js +++ b/libs/control.js @@ -1967,17 +1967,27 @@ control.prototype.checkStatus = function (name, need, item) { control.prototype.openBook = function (need) { if (core.isReplaying()) return; + if (core.status.event.id == 'book' && core.isset(core.status.event.interval)) { + var data = core.status.event.interval; + core.ui.closePanel(); + core.lockControl(); + core.status.event.id = 'action'; + core.status.event.data = data; + core.doAction(); + return; + } + // 当前是book,且从“浏览地图”打开 - if (core.status.event.id == 'book' && core.isset(core.status.event.selection)) { + if (core.status.event.id == 'book' && core.isset(core.status.event.ui)) { core.status.boxAnimateObjs = []; - core.ui.drawMaps(core.status.event.selection); + core.ui.drawMaps(core.status.event.ui); return; } // 从“浏览地图”页面打开 if (core.status.event.id=='viewMaps') { need=false; - core.status.event.selection = core.status.event.data; + core.status.event.ui = core.status.event.data; } if (!core.checkStatus('book', need, true)) @@ -2039,6 +2049,17 @@ control.prototype.openQuickShop = function (need) { ////// 点击保存按钮时的打开操作 ////// control.prototype.save = function(need) { if (core.isReplaying()) return; + + if (core.status.event.id == 'save' && core.isset(core.status.event.interval)) { + var data = core.status.event.interval; + core.ui.closePanel(); + core.lockControl(); + core.status.event.id = 'action'; + core.status.event.data = data; + core.doAction(); + return; + } + if (!core.checkStatus('save', need)) return; @@ -2052,6 +2073,16 @@ control.prototype.save = function(need) { control.prototype.load = function (need) { if (core.isReplaying()) return; + if (core.status.event.id == 'load' && core.isset(core.status.event.interval)) { + var data = core.status.event.interval; + core.ui.closePanel(); + core.lockControl(); + core.status.event.id = 'action'; + core.status.event.data = data; + core.doAction(); + return; + } + var saveIndex = core.saves.saveIndex; var page=parseInt((saveIndex-1)/5), offset=saveIndex-5*page; @@ -2082,23 +2113,15 @@ control.prototype.openSettings = function (need) { ////// 自动存档 ////// control.prototype.autosave = function (removeLast) { - var addLast = true; - if (core.status.event.id!=null) { - // 检查是否是强制自动存档 - if (core.status.event.id=='action' && core.hasFlag("forceSave")) addLast = false; - else return; - } + if (core.status.event.id!=null) return; var x=null; if (removeLast) x=core.status.route.pop(); - if (addLast) - core.status.route.push("turn:"+core.getHeroLoc('direction')); + core.status.route.push("turn:"+core.getHeroLoc('direction')); core.setLocalForage("autoSave", core.saveData()); - if (addLast) - core.status.route.pop(); + core.status.route.pop(); if (removeLast && core.isset(x)) core.status.route.push(x); - core.removeFlag("forceSave"); } ////// 实际进行存读档事件 ////// @@ -2108,13 +2131,27 @@ control.prototype.doSL = function (id, type) { core.drawTip('不能覆盖自动存档!'); return; } + // 事件中的存档 + if (core.status.event.interval != null) { + core.setFlag("__events__", core.status.event.interval); + } core.setLocalForage("save"+id, core.saveData(), function() { - core.ui.closePanel(); - core.drawTip('存档成功!'); if (id!="autoSave") { core.saves.saveIndex=id; core.setLocalStorage('saveIndex', core.saves.saveIndex); } + if (core.status.event.interval != null) { + var data = core.status.event.interval; + core.ui.closePanel(); + core.lockControl(); + core.status.event.id = 'action'; + core.status.event.data = data; + core.drawTip("存档成功!"); + core.doAction(); + return; + } + core.ui.closePanel(); + core.drawTip('存档成功!'); }, function(err) { console.info(err); if (core.platform.useLocalForage) { @@ -2123,12 +2160,11 @@ control.prototype.doSL = function (id, type) { else { alert("存档失败,错误信息:\n"+err+"\n建议使用垃圾存档清理工具进行清理!"); } - }) + }); + core.removeFlag("__events__"); return; } else if (type=='load') { - // var data = core.getLocalStorage(id=='autoSave'?id:"save"+id, null); - core.getLocalForage(id=='autoSave'?id:"save"+id, null, function(data) { if (!core.isset(data)) { alert("无效的存档"); diff --git a/libs/events.js b/libs/events.js index 747422c4..1fc28cf1 100644 --- a/libs/events.js +++ b/libs/events.js @@ -1231,6 +1231,40 @@ events.prototype.doAction = function() { this.doAction(); break; } + case "callBook": // 呼出怪物手册 + if (core.isReplaying() || !core.hasItem('book')) { + this.doAction(); + } + else { + var e = core.clone(core.status.event.data); + core.ui.closePanel(); + core.openBook(); + core.status.event.interval = e; + } + break; + case "callSave": // 呼出存档页面 + if (core.isReplaying() || core.hasFlag("__events__")) { + core.removeFlag("__events__"); + this.doAction(); + } + else { + var e = core.clone(core.status.event.data); + core.ui.closePanel(); + core.save(); + core.status.event.interval = e; + } + break; + case "callLoad": // 呼出读档页面 + if (core.isReplaying()) { + this.doAction(); + } + else { + var e = core.clone(core.status.event.data); + core.ui.closePanel(); + core.load(); + core.status.event.interval = e; + } + break; case "exit": // 立刻结束事件 core.status.event.data.list = []; core.events.doAction(); diff --git a/project/data.js b/project/data.js index 969c0da9..cead9406 100644 --- a/project/data.js +++ b/project/data.js @@ -108,6 +108,10 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = "type": "comment", "text": "在这里可以用事件来自定义绘制标题界面的背景图等" }, + { + "type": "comment", + "text": "也可以直接切换到其他楼层(比如某个开始剧情楼层)进行操作。" + }, { "type": "showImage", "code": 1, @@ -122,111 +126,108 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = "time": 0 }, { - "type": "comment", - "text": "给用户提供选择项,这里简单的使用了choices事件" - }, - { - "type": "comment", - "text": "也可以贴按钮图然后使用循环处理+等待操作来完成" - }, - { - "type": "choices", - "choices": [ + "type": "while", + "condition": "1", + "data": [ { - "text": "开始游戏", - "action": [ + "type": "comment", + "text": "给用户提供选择项,这里简单的使用了choices事件" + }, + { + "type": "comment", + "text": "也可以贴按钮图然后使用等待操作来完成" + }, + { + "type": "choices", + "choices": [ { - "type": "comment", - "text": "检查bgm状态,下同" - }, - { - "type": "function", - "function": "function(){\ncore.control.checkBgm()\n}" - }, - { - "type": "if", - "condition": "core.flags.startDirectly", - "true": [ + "text": "开始游戏", + "action": [ { "type": "comment", - "text": "直接开始游戏,设置初始化数据" + "text": "检查bgm状态,下同" }, { "type": "function", - "function": "function(){\ncore.events.setInitData('')\n}" - } - ], - "false": [ - { - "type": "comment", - "text": "动态生成难度选择项" + "function": "function(){\ncore.control.checkBgm()\n}" }, { - "type": "function", - "function": "function(){\nvar choices = [];\nmain.levelChoose.forEach(function (one) {\n\tchoices.push({\"text\": one[0], \"action\": [\n\t\t{\"type\": \"function\", \"function\": \"function() { core.status.hard = '\"+one[1]+\"'; core.events.setInitData('\"+one[1]+\"'); }\"}\n\t]});\n})\ncore.insertAction({\"type\": \"choices\", \"choices\": choices});\n}" + "type": "if", + "condition": "core.flags.startDirectly", + "true": [ + { + "type": "comment", + "text": "直接开始游戏,设置初始化数据" + }, + { + "type": "function", + "function": "function(){\ncore.events.setInitData('')\n}" + } + ], + "false": [ + { + "type": "comment", + "text": "动态生成难度选择项" + }, + { + "type": "function", + "function": "function(){\nvar choices = [];\nmain.levelChoose.forEach(function (one) {\n\tchoices.push({\"text\": one[0], \"action\": [\n\t\t{\"type\": \"function\", \"function\": \"function() { core.status.hard = '\"+one[1]+\"'; core.events.setInitData('\"+one[1]+\"'); }\"}\n\t]});\n})\ncore.insertAction({\"type\": \"choices\", \"choices\": choices});\n}" + } + ] + }, + { + "type": "hideImage", + "code": 1, + "time": 0 + }, + { + "type": "comment", + "text": "成功选择难度" + }, + { + "type": "break" } ] }, { - "type": "hideImage", - "code": 1, - "time": 0 + "text": "读取存档", + "action": [ + { + "type": "function", + "function": "function(){\ncore.control.checkBgm()\n}" + }, + { + "type": "comment", + "text": "简单的使用“呼出读档界面”来处理" + }, + { + "type": "callLoad" + } + ] }, { - "type": "comment", - "text": "成功选择难度" - } - ] - }, - { - "text": "读取存档", - "action": [ - { - "type": "function", - "function": "function(){\ncore.control.checkBgm()\n}" - }, - { - "type": "hideImage", - "code": 1, - "time": 0 - }, - { - "type": "comment", - "text": "这段代码会结束事件,打开读档页面,读取存档或重新开始" - }, - { - "type": "function", - "function": "function(){\ncore.insertAction([{\"type\": \"exit\"}], null, null, function() {\n\tcore.status.played = false;\n\tcore.load();\n})\n}" - }, - { - "type": "comment", - "text": "不管读档有没有成功,都会重新开始,这个地方不会被执行到" - } - ] - }, - { - "text": "回放录像", - "action": [ - { - "type": "function", - "function": "function(){\ncore.control.checkBgm()\n}" - }, - { - "type": "hideImage", - "code": 1, - "time": 0 - }, - { - "type": "comment", - "text": "这段代码会结束事件,选择录像文件,播放录像或重新开始" - }, - { - "type": "function", - "function": "function(){\ncore.insertAction([{\"type\": \"exit\"}], null, null, function() {\n\tcore.restart();\n\tcore.chooseReplayFile();\n})\n}" - }, - { - "type": "comment", - "text": "不管录像有没有成功,都会重新开始,这个地方不会被执行到" + "text": "回放录像", + "action": [ + { + "type": "function", + "function": "function(){\ncore.control.checkBgm()\n}" + }, + { + "type": "comment", + "text": "这段代码会弹框选择录像文件" + }, + { + "type": "if", + "condition": "!core.isReplaying()", + "true": [ + { + "type": "function", + "function": "function(){\ncore.chooseReplayFile()\n}" + } + ], + "false": [] + } + ] } ] } diff --git a/project/functions.js b/project/functions.js index 3fb07776..f462b625 100644 --- a/project/functions.js +++ b/project/functions.js @@ -144,17 +144,30 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // 转换楼层结束的事件;此函数会在整个楼层切换完全结束后再执行 // floorId是切换到的楼层;fromLoad若为true则代表是从读档行为造成的楼层切换 - // 每次抵达楼层时执行的事件 - if (!fromLoad || core.hasFlag("forceSave")) { - core.insertAction(core.floors[floorId].eachArrive); + // 如果是读档,则进行检查 + if (fromLoad) { + var data = core.getFlag("__events__"); + if (core.isset(data)) { + // 是事件中的存档... 恢复现场 + core.lockControl(); + core.status.event.id = 'action'; + core.status.event.data = data; + setTimeout(function () { + core.doAction(); + }, 30); + } } + else { + // 每次抵达楼层执行的事件 + core.insertAction(core.floors[floorId].eachArrive); - // 首次抵达楼层时执行的事件(后插入,先执行) - var visited = core.getFlag("__visited__", []); - if (visited.indexOf(floorId)===-1) { - core.insertAction(core.floors[floorId].firstArrive); - visited.push(floorId); - core.setFlag("__visited__", visited); + // 首次抵达楼层时执行的事件(后插入,先执行) + var visited = core.getFlag("__visited__", []); + if (visited.indexOf(floorId)===-1) { + core.insertAction(core.floors[floorId].firstArrive); + visited.push(floorId); + core.setFlag("__visited__", visited); + } } }, "addPoint": function (enemy) {