From 7af4e6d45636a05963d1b7a13fe0f61e014ea702 Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Sun, 13 May 2018 16:10:13 +0800 Subject: [PATCH] Update Docs --- _server/blockly/MotaAction.g4 | 213 +++++++++++++++--------------- docs/api.md | 10 +- docs/element.md | 33 ++--- docs/event.md | 95 ++++++------- docs/img/plugin.png | Bin 0 -> 35281 bytes docs/personalization.md | 242 +++++++++++++++++++++++++++++++++- libs/core.js | 5 + libs/events.js | 2 + libs/maps.js | 8 ++ 9 files changed, 422 insertions(+), 186 deletions(-) create mode 100644 docs/img/plugin.png diff --git a/_server/blockly/MotaAction.g4 b/_server/blockly/MotaAction.g4 index 5c6e5f82..2483aaef 100644 --- a/_server/blockly/MotaAction.g4 +++ b/_server/blockly/MotaAction.g4 @@ -236,7 +236,7 @@ text_0_s /* text_0_s tooltip : text:显示一段文字(剧情) -helpUrl : https://ckcz123.github.io/mota-js/#/event?id=text%ef%bc%9a%e6%98%be%e7%a4%ba%e4%b8%80%e6%ae%b5%e6%96%87%e5%ad%97%ef%bc%88%e5%89%a7%e6%83%85%ef%bc%89 +helpUrl : https://ckcz123.github.io/mota-js/#/event?id=text%EF%BC%9A%E6%98%BE%E7%A4%BA%E4%B8%80%E6%AE%B5%E6%96%87%E5%AD%97%EF%BC%88%E5%89%A7%E6%83%85%EF%BC%89 default : ["欢迎使用事件编辑器(双击方块进入多行编辑)"] var code = '"'+EvalString_0+'",\n'; return code; @@ -248,7 +248,7 @@ text_1_s /* text_1_s tooltip : text:显示一段文字(剧情),选项较多请右键点击帮助 -helpUrl : https://ckcz123.github.io/mota-js/#/event?id=text%ef%bc%9a%e6%98%be%e7%a4%ba%e4%b8%80%e6%ae%b5%e6%96%87%e5%ad%97%ef%bc%88%e5%89%a7%e6%83%85%ef%bc%89 +helpUrl : https://ckcz123.github.io/mota-js/#/event?id=text%EF%BC%9A%E6%98%BE%E7%A4%BA%E4%B8%80%E6%AE%B5%E6%96%87%E5%AD%97%EF%BC%88%E5%89%A7%E6%83%85%EF%BC%89 default : ["小妖精","fairy","","欢迎使用事件编辑器(双击方块进入多行编辑)"] var title=''; if (EvalString_0==''){ @@ -272,7 +272,7 @@ autoText_s /* autoText_s tooltip : autoText:自动剧情文本,用户无法跳过自动剧情文本,大段剧情文本请添加“是否跳过剧情”的提示 -helpUrl : https://ckcz123.github.io/mota-js/#/event?id=autotext%ef%bc%9a%e8%87%aa%e5%8a%a8%e5%89%a7%e6%83%85%e6%96%87%e6%9c%ac +helpUrl : https://ckcz123.github.io/mota-js/#/event?id=autotext%EF%BC%9A%E8%87%AA%E5%8A%A8%E5%89%A7%E6%83%85%E6%96%87%E6%9C%AC default : ["小妖精","fairy","",3000,"双击方块进入多行编辑\\n自动剧情文本\\n自动剧情文本\\n自动剧情文本"] var title=''; if (EvalString_0==''){ @@ -296,7 +296,7 @@ setText_s /* setText_s tooltip : setText:设置剧情文本的属性,颜色为RGB三元组或RGBA四元组,打字间隔为剧情文字添加的时间间隔,为整数或不填 -helpUrl : https://ckcz123.github.io/mota-js/#/event?id=settext%ef%bc%9a%e8%ae%be%e7%bd%ae%e5%89%a7%e6%83%85%e6%96%87%e6%9c%ac%e7%9a%84%e5%b1%9e%e6%80%a7 +helpUrl : https://ckcz123.github.io/mota-js/#/event?id=settext%EF%BC%9A%E8%AE%BE%E7%BD%AE%E5%89%A7%E6%83%85%E6%96%87%E6%9C%AC%E7%9A%84%E5%B1%9E%E6%80%A7 default : [null,"","","",null,''] SetTextPosition_List_0 =SetTextPosition_List_0==='null'?'': ', "position": "'+SetTextPosition_List_0+'"'; 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)?$/; @@ -327,7 +327,7 @@ tip_s /* tip_s tooltip : tip:显示一段提示文字 -helpUrl : https://ckcz123.github.io/mota-js/#/event?id=tip%ef%bc%9a%e6%98%be%e7%a4%ba%e4%b8%80%e6%ae%b5%e6%8f%90%e7%a4%ba%e6%96%87%e5%ad%97 +helpUrl : https://ckcz123.github.io/mota-js/#/event?id=tip%EF%BC%9A%E6%98%BE%E7%A4%BA%E4%B8%80%E6%AE%B5%E6%8F%90%E7%A4%BA%E6%96%87%E5%AD%97 default : ["这段话将在左上角以气泡形式显示"] var code = '{"type": "tip", "text": "'+EvalString_0+'"},\n'; return code; @@ -339,37 +339,41 @@ setValue_s /* setValue_s tooltip : setValue:设置勇士的某个属性、道具个数, 或某个变量/Flag的值 -helpUrl : https://ckcz123.github.io/mota-js/#/event?id=text%ef%bc%9a%e6%98%be%e7%a4%ba%e4%b8%80%e6%ae%b5%e6%96%87%e5%ad%97%ef%bc%88%e5%89%a7%e6%83%85%ef%bc%89 +helpUrl : https://ckcz123.github.io/mota-js/#/event?id=setvalue%EF%BC%9A%E8%AE%BE%E7%BD%AE%E5%8B%87%E5%A3%AB%E7%9A%84%E6%9F%90%E4%B8%AA%E5%B1%9E%E6%80%A7%E3%80%81%E9%81%93%E5%85%B7%E4%B8%AA%E6%95%B0%EF%BC%8C%E6%88%96%E6%9F%90%E4%B8%AA%E5%8F%98%E9%87%8Fflag%E7%9A%84%E5%80%BC colour : this.dataColor var code = '{"type": "setValue", "name": "'+idString_e_0+'", "value": "'+expression_0+'"},\n'; return code; */; show_s - : '显示事件' 'x' EvalString ',' 'y' EvalString '楼层' IdString? '动画时间' Int? Newline + : '显示事件' 'x' EvalString? ',' 'y' EvalString? '楼层' IdString? '动画时间' Int? Newline /* show_s 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] +helpUrl : https://ckcz123.github.io/mota-js/#/event?id=show%EF%BC%9A%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 : ["","","",500] colour : this.eventColor -IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"'); -var pattern1 = /^flag:[0-9a-zA-Z_][0-9a-zA-Z_\-:]*$/; -if(pattern1.test(EvalString_0) || pattern1.test(EvalString_1)){ - EvalString_0=MotaActionFunctions.PosString_pre(EvalString_0); - EvalString_1=MotaActionFunctions.PosString_pre(EvalString_1); - EvalString_0=[EvalString_0,EvalString_1] -} else { - var pattern2 = /^([+-]?\d+)(,[+-]?\d+)*$/; - if(!pattern2.test(EvalString_0) || !pattern2.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;ii10) throw new Error('天气的强度等级, 在1-10之间'); @@ -777,7 +769,7 @@ move_s /* move_s tooltip : move: 让某个NPC/怪物移动,位置可不填代表当前事件 -helpUrl : https://ckcz123.github.io/mota-js/#/event?id=move-%e8%ae%a9%e6%9f%90%e4%b8%aanpc%e6%80%aa%e7%89%a9%e7%a7%bb%e5%8a%a8 +helpUrl : https://ckcz123.github.io/mota-js/#/event?id=move%EF%BC%9A%E8%AE%A9%E6%9F%90%E4%B8%AAnpc%E6%80%AA%E7%89%A9%E7%A7%BB%E5%8A%A8 default : ["","",500,null,"上右3下2左上左2"] colour : this.eventColor var floorstr = ''; @@ -795,7 +787,7 @@ moveHero_s /* moveHero_s tooltip : moveHero:移动勇士,用这种方式移动勇士的过程中将无视一切地形, 无视一切事件, 中毒状态也不会扣血 -helpUrl : https://ckcz123.github.io/mota-js/#/event?id=movehero%ef%bc%9a%e7%a7%bb%e5%8a%a8%e5%8b%87%e5%a3%ab +helpUrl : https://ckcz123.github.io/mota-js/#/event?id=movehero%EF%BC%9A%E7%A7%BB%E5%8A%A8%E5%8B%87%E5%A3%AB default : [500,"上右3下2左上左2"] colour : this.dataColor Int_0 = Int_0 ?(', "time": '+Int_0):''; @@ -809,7 +801,7 @@ playBgm_s /* playBgm_s tooltip : playBgm: 播放背景音乐 -helpUrl : https://ckcz123.github.io/mota-js/#/event?id=playbgm-%e6%92%ad%e6%94%be%e8%83%8c%e6%99%af%e9%9f%b3%e4%b9%90 +helpUrl : https://ckcz123.github.io/mota-js/#/event?id=playbgm%EF%BC%9A%E6%92%AD%E6%94%BE%E8%83%8C%E6%99%AF%E9%9F%B3%E4%B9%90 default : ["bgm.mp3"] colour : this.soundColor var code = '{"type": "playBgm", "name": "'+EvalString_0+'"},\n'; @@ -822,7 +814,7 @@ pauseBgm_s /* pauseBgm_s tooltip : pauseBgm: 暂停背景音乐 -helpUrl : https://ckcz123.github.io/mota-js/#/event?id=pausebgm-%e6%9a%82%e5%81%9c%e8%83%8c%e6%99%af%e9%9f%b3%e4%b9%90 +helpUrl : https://ckcz123.github.io/mota-js/#/event?id=pausebgm%EF%BC%9A%E6%9A%82%E5%81%9C%E8%83%8C%E6%99%AF%E9%9F%B3%E4%B9%90 colour : this.soundColor var code = '{"type": "pauseBgm"},\n'; return code; @@ -834,7 +826,7 @@ resumeBgm_s /* resumeBgm_s tooltip : resumeBgm: 恢复背景音乐 -helpUrl : https://ckcz123.github.io/mota-js/#/event?id=resumebgm-%e6%81%a2%e5%a4%8d%e8%83%8c%e6%99%af%e9%9f%b3%e4%b9%90 +helpUrl : https://ckcz123.github.io/mota-js/#/event?id=resumebgm%EF%BC%9A%E6%81%A2%E5%A4%8D%E8%83%8C%E6%99%AF%E9%9F%B3%E4%B9%90 colour : this.soundColor var code = '{"type": "resumeBgm"},\n'; return code; @@ -846,7 +838,7 @@ playSound_s /* playSound_s tooltip : playSound: 播放音效 -helpUrl : https://ckcz123.github.io/mota-js/#/event?id=playsound-%e6%92%ad%e6%94%be%e9%9f%b3%e6%95%88 +helpUrl : https://ckcz123.github.io/mota-js/#/event?id=playsound%EF%BC%9A%E6%92%AD%E6%94%BE%E9%9F%B3%E6%95%88 default : ["item.ogg"] colour : this.soundColor var code = '{"type": "playSound", "name": "'+EvalString_0+'"},\n'; @@ -859,7 +851,7 @@ setVolume_s /* setVolume_s tooltip : setVolume: 设置音量 -helpUrl : https://ckcz123.github.io/mota-js/#/event?id=setVolume-%e8%ae%be%e7%bd%ae%e9%9f%b3%e9%87%8f +helpUrl : https://ckcz123.github.io/mota-js/#/event?id=setvolume%EF%BC%9A%E8%AE%BE%E7%BD%AE%E9%9F%B3%E9%87%8F default : [90] colour : this.soundColor var code = '{"type": "setVolume", "value": '+Int_0+'},\n'; @@ -872,7 +864,7 @@ win_s /* win_s tooltip : win: 获得胜利, 该事件会显示获胜页面, 并重新游戏 -helpUrl : https://ckcz123.github.io/mota-js/#/event?id=win-%e8%8e%b7%e5%be%97%e8%83%9c%e5%88%a9 +helpUrl : https://ckcz123.github.io/mota-js/#/event?id=win%EF%BC%9A%E8%8E%B7%E5%BE%97%E8%83%9C%E5%88%A9 default : [""] var code = '{"type": "win", "reason": "'+EvalString_0+'"},\n'; return code; @@ -884,7 +876,7 @@ lose_s /* lose_s tooltip : lose: 游戏失败, 该事件会显示失败页面, 并重新开始游戏 -helpUrl : https://ckcz123.github.io/mota-js/#/event?id=lose-%e6%b8%b8%e6%88%8f%e5%a4%b1%e8%b4%a5 +helpUrl : https://ckcz123.github.io/mota-js/#/event?id=lose%EF%BC%9A%E6%B8%B8%E6%88%8F%E5%A4%B1%E8%B4%A5 default : [""] var code = '{"type": "lose", "reason": "'+EvalString_0+'"},\n'; return code; @@ -896,7 +888,7 @@ input_s /* input_s tooltip : input:接受用户输入, 事件只能接受非负整数输入, 所有非法的输入将全部变成0 -helpUrl : https://ckcz123.github.io/mota-js/#/event?id=input%ef%bc%9a%e6%8e%a5%e5%8f%97%e7%94%a8%e6%88%b7%e8%be%93%e5%85%a5 +helpUrl : https://ckcz123.github.io/mota-js/#/event?id=input%EF%BC%9A%E6%8E%A5%E5%8F%97%E7%94%A8%E6%88%B7%E8%BE%93%E5%85%A5 default : ["请输入一个数"] colour : this.dataColor var code = '{"type": "input", "text": "'+EvalString_0+'"},\n'; @@ -909,7 +901,7 @@ if_s /* if_s tooltip : if: 条件判断 -helpUrl : https://ckcz123.github.io/mota-js/#/event?id=if-%e6%9d%a1%e4%bb%b6%e5%88%a4%e6%96%ad +helpUrl : https://ckcz123.github.io/mota-js/#/event?id=if%EF%BC%9A%E6%9D%A1%E4%BB%B6%E5%88%A4%E6%96%AD colour : this.eventColor var code = ['{"type": "if", "condition": "',expression_0,'",\n', '"true": [\n',action_0,'],\n', @@ -918,6 +910,43 @@ var code = ['{"type": "if", "condition": "',expression_0,'",\n', return code; */; +choices_s + : '选项' ':' EvalString? BGNL? '标题' EvalString? '图像' IdString? BGNL? Newline choicesContext+ BEND Newline + + +/* choices_s +tooltip : choices: 给用户提供选项 +helpUrl : https://ckcz123.github.io/mota-js/#/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 : ["","流浪者","woman"] +var title=''; +if (EvalString_1==''){ + if (IdString_0=='')title=''; + else title='\\t['+IdString_0+']'; +} else { + if (IdString_0=='')title='\\t['+EvalString_1+']'; + else title='\\t['+EvalString_1+','+IdString_0+']'; +} +EvalString_0 = title+EvalString_0; +EvalString_0 = EvalString_0 ?(', "text": "'+EvalString_0+'"'):''; +var code = ['{"type": "choices"',EvalString_0,', "choices": [\n', + choicesContext_0, +']},\n'].join(''); +return code; +*/; + +choicesContext + : '子选项' EvalString BGNL? Newline action+ + + +/* choicesContext +tooltip : 选项的选择 +helpUrl : https://ckcz123.github.io/mota-js/#/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 : ["提示文字:红钥匙"] +colour : this.subColor +var code = '{"text": "'+EvalString_0+'", "action": [\n'+action_0+']},\n'; +return code; +*/; + while_s : '循环处理' ':' '当' expression '时' BGNL? Newline action+ BEND Newline @@ -953,40 +982,16 @@ var code = '{"type": "continue"},\n'; return code; */; -choices_s - : '选项' ':' EvalString? BGNL? '标题' EvalString? '图像' IdString? BGNL? Newline choicesContext+ BEND Newline - -/* choices_s -tooltip : choices: 给用户提供选项 -helpUrl : https://ckcz123.github.io/mota-js/#/event?id=choices-%e7%bb%99%e7%94%a8%e6%88%b7%e6%8f%90%e4%be%9b%e9%80%89%e9%a1%b9 -default : ["","流浪者","woman"] -var title=''; -if (EvalString_1==''){ - if (IdString_0=='')title=''; - else title='\\t['+IdString_0+']'; -} else { - if (IdString_0=='')title='\\t['+EvalString_1+']'; - else title='\\t['+EvalString_1+','+IdString_0+']'; -} -EvalString_0 = title+EvalString_0; -EvalString_0 = EvalString_0 ?(', "text": "'+EvalString_0+'"'):''; -var code = ['{"type": "choices"',EvalString_0,', "choices": [\n', - choicesContext_0, -']},\n'].join(''); -return code; -*/; +wait_s + : '等待用户操作并获得按键或点击信息' -choicesContext - : '子选项' EvalString BGNL? Newline action+ - -/* choicesContext -tooltip : 选项的选择 -helpUrl : https://ckcz123.github.io/mota-js/#/event?id=choices-%e7%bb%99%e7%94%a8%e6%88%b7%e6%8f%90%e4%be%9b%e9%80%89%e9%a1%b9 -default : ["提示文字:红钥匙"] -colour : this.subColor -var code = '{"text": "'+EvalString_0+'", "action": [\n'+action_0+']},\n'; +/* wait_s +tooltip : wait: 等待用户操作并获得按键或点击信息(具体用法看文档) +helpUrl : https://ckcz123.github.io/mota-js/#/event?id=wait%EF%BC%9A%E7%AD%89%E5%BE%85%E7%94%A8%E6%88%B7%E6%93%8D%E4%BD%9C +colour : this.soundColor +var code = '{"type": "wait"},\n'; return code; */; @@ -996,7 +1001,7 @@ function_s /* function_s tooltip : function: 自定义JS脚本 -helpUrl : https://ckcz123.github.io/mota-js/#/event?id=function-%e8%87%aa%e5%ae%9a%e4%b9%89js%e8%84%9a%e6%9c%ac +helpUrl : https://ckcz123.github.io/mota-js/#/event?id=function%EF%BC%9A%E8%87%AA%E5%AE%9A%E4%B9%89js%E8%84%9A%E6%9C%AC default : ["alert(core.getStatus(\"atk\"));"] colour : this.dataColor var code = '{"type": "function", "function": "function(){\\n'+JSON.stringify(RawEvalString_0).slice(1,-1).split('\\\\n').join('\\n')+'\\n}"},\n'; diff --git a/docs/api.md b/docs/api.md index b074575b..37580c0d 100644 --- a/docs/api.md +++ b/docs/api.md @@ -181,10 +181,18 @@ core.getBlock(x, y, floorId, needEnable) 获得某个点的当前图块信息。 x和y为坐标;floorId为楼层ID,可忽略或null表示当前楼层。 needEnable表示该点是否启用时才返回,其值不设置则默认为true。 -该函数返回值如下: {"index": xxx, "block": xxx} +如果该点不存在图块,则返回null。 +否则,返回值如下: {"index": xxx, "block": xxx} 其中index为该点在该楼层blocks数组中的索引,block为该图块实际内容。 +core.getBlockId(x, y, floorId, needEnable) +获得某个点的图块ID +x和y为坐标;floorId为楼层ID,可忽略或null表示当前楼层。 +needEnable表示是否需要该点处于启用状态才返回,其值不设置则默认为true。 +如果该点不存在图块,则返回null,否则返回该点的图块ID。 + + core.showBlock(x, y, floorId) 将某个点从禁用变成启用状态 diff --git a/docs/element.md b/docs/element.md index 44e3bd97..3e915cdb 100644 --- a/docs/element.md +++ b/docs/element.md @@ -36,7 +36,8 @@ ## 怪物 -本塔支持的怪物列表参见`enemys.js`。其与images目录下的`enemys.png`素材按顺序一一对应。如不知道怪物素材长啥样的请打开`enemys.png`对比查看。 +本塔支持的怪物列表参见`project/enemys.js`。其与images目录下的`enemys.png`素材按顺序一一对应。 + 如有自己的怪物素材需求请参见[自定义素材](personalization#自定义素材)的内容。 怪物可以有特殊属性,每个怪物可以有多个自定义属性。 @@ -89,27 +90,23 @@ enemys.prototype.getSpecialText = function (enemyId) { 下面的`getSpecialHint`函数则给定了每个特殊属性的详细描述。这个描述将在怪物手册中看到。 -**打败怪物后可以进行加点操作。有关加点塔的制作可参见[加点事件](event#加点事件)。** +打败怪物后可以进行加点操作。有关加点塔的制作可参见[加点事件](event#加点事件)。 如果`data.js`中的enableExperience为false,即不启用经验的话,怪物手册里将不显示怪物的经验值,打败怪物也不获得任何经验。 拿到幸运金币后,打怪获得的金币将翻倍。 +如果怪物有`"notBomb": true`,则该系列诖怪物均不可被炸。 + N连击怪物的special是6,且我们可以为它定义n代表实际连击数。参见样板中剑王的写法。 -![N连击](./img/nattack.png) - -吸血怪需要在怪物后添加value,代表吸血的比例。 +吸血怪需要给怪物设置value,代表吸血的比例。 可以给吸血怪添加`'add': true`来将吸血的数值加到自身上。 -![怪物吸血](./img/blood.png) - 中毒怪让勇士中毒后,每步扣减的生命值由`data.js`中的values定义。 -衰弱怪让勇士衰弱后,攻防会暂时下降一定的数值(直到衰弱状态解除恢复);这个下降的数值同在`data.js`中的values定义。 - -![debuff](./img/debuff.png) +衰弱怪让勇士衰弱后,攻防会下降一定比例或固定数值(直到衰弱状态解除恢复);其在`data.js`中的values定义。 诅咒怪将让勇士陷入诅咒状态,诅咒状态下杀怪不获得金币和经验值。 @@ -117,21 +114,17 @@ N连击怪物的special是6,且我们可以为它定义n代表实际连击数 领域是十字伤害还是九宫格伤害由`zoneSquare`设定,如设置为true则为九宫格伤害,不指定或为false则为十字伤害。 -`range`选项可选,代表该领域怪的范围,不写则默认为1。 +领域怪还可以设置`range`选项代表该领域怪的范围,不写则默认为1。 -![怪物领域](./img/zone.png) - -阻击怪同样需要在怪物后添加value,代表领域伤害的数值。如果勇士生命值扣减到0,则直接死亡触发lose事件。 +阻击怪同样需要设置value,代表领域伤害的数值。如果勇士生命值扣减到0,则直接死亡触发lose事件。 !> 阻击怪后退的地点不能有任何事件存在,即使是已经被禁用的自定义事件! 请注意如果吸血、领域、阻击中任何两个同时存在,则value会冲突。**因此请勿将吸血、领域或阻击放置在同一个怪物身上。** -退化怪需要在后面增加'atkValue'和'defValue'表示退化的数值。 +退化怪需要设置'atkValue'和'defValue'表示退化的数值;也可以不设置默认为0。 -![怪物退化](./img/tuihua.png) - -固伤怪则需要在后面增加`damage`选项,代表战前扣血数值。 +固伤怪则需要设置`damage`选项,代表战前扣血数值。 如有额外需求,可参见[自定义怪物属性](personalization#自定义自定义怪物属性),里面讲了如何设置一个新的怪物属性。 @@ -197,12 +190,12 @@ floorId指定的是目标楼层的唯一标识符(ID)。 本塔支持BGM和SE的播放。 -要播放音乐和音效,你需要将对应的文件放在sounds目录下,然后在main.js中进行定义 +要播放音乐和音效,你需要将对应的文件放在sounds目录下,然后在全塔属性中进行定义 ``` js "bgms": [ // 在此存放所有的bgm,和文件名一致。第一项为默认播放项 // 音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好 - 'bgm.mp3', 'qianjin.mid', 'star.mid', + 'bgm.mp3' ]; "sounds": [ // 在此存放所有的SE,和文件名一致 // 音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好 diff --git a/docs/event.md b/docs/event.md index 51f84109..d8d50530 100644 --- a/docs/event.md +++ b/docs/event.md @@ -26,7 +26,7 @@ 它能通过拖动、复制粘贴等方式帮助你快速生成事件列表,而不用手动打大量字符。 -但是,仍然强烈建议要对每个事件的写法进行了解。 +但是,仍然强烈建议要对每个事件的写法进行了解,因为在脚本编辑,`insertAction`等地方需要插入自定义事件时,还是很有必要的。 ## 自定义事件 @@ -264,6 +264,7 @@ - `flag:xxx` 中的xxx为一个自定义的变量/Flag;如果没有对其进行赋值则默认值为false。 另外,有个小`trick`。是否想立刻知道显示效果? + 你可以用Chrome浏览器打开游戏,按Ctrl+Shift+I打开开发者工具,找到Console(控制台),并中输入`core.drawText("...")` 即可立刻看到文字显示的效果。适当调整文字,使得显示效果满意后,再复制粘贴到你的剧情文本中。 ![调试](./img/eventdebug.png) @@ -322,7 +323,7 @@ time为可选项,表示文字添加的速度。若此项设置为0将直接全 ] ``` -值得注意的是,提示的text内容是可以使用`${ }`来计算表达式的值的。 +值得注意的是,提示的text内容也是可以使用`${ }`来计算表达式的值的。 ### setValue:设置勇士的某个属性、道具个数,或某个变量/Flag的值 @@ -356,7 +357,7 @@ value是一个表达式,将通过这个表达式计算出的结果赋值给nam 另外注意一点的是,如果hp被设置成了0或以下,将触发lose事件,直接死亡。 -### show: 将一个禁用事件启用 +### show:将一个禁用事件启用 我们上面提到了,所有事件都必须靠其他事件驱动来完成,不存在当某个flag为true时自动执行的说法。那么,我们自然要有启用事件的写法。 @@ -381,7 +382,7 @@ time为动画效果时间,如果指定了某个大于0的数,则会以动画 !> **要注意的是,调用show事件后只是让该事件从禁用状态变成启用,从不可见不可交互变成可见可交互,但本身不会去执行该点的事件。** -### hide: 将一个启用事件禁用 +### hide:将一个启用事件禁用 `{"type":"hide"}`和show刚好相反,它会让一个已经启用的事件被禁用。 @@ -407,7 +408,7 @@ NPC对话事件结束后如果需要NPC消失也需要调用 `{"type": "hide"}` ] ``` -### trigger: 立即触发另一个地点的事件 +### trigger:立即触发另一个地点的事件 `{"type":"trigger"}` 会立刻触发当层另一个地点的自定义事件。 @@ -428,7 +429,7 @@ NPC对话事件结束后如果需要NPC消失也需要调用 `{"type": "hide"}` 例如上面这个例子,下面的文字将不会再被显示,而是直接跳转到`"3,6"`对应的事件列表从头执行。 -### revisit: 立即重启当前事件 +### revisit:立即重启当前事件 revisit和trigger完全相同,只不过是立刻触发的还是本地点的事件 @@ -443,7 +444,7 @@ revisit其实是trigger的简写,只不过是loc固定为当前点。 revisit常常使用在一些商人之类的地方,当用户购买物品后不是离开,而是立刻重新访问重新进入购买页面。 -### exit: 立刻结束当前事件 +### exit:立刻结束当前事件 上面说到像商人一类,购买物品后可以立刻revisit重新访问,但是这样就相当于陷入了死循环导致无法离开。 @@ -504,11 +505,11 @@ name是可选的,代表目标行走图的文件名。 如果你需要同时修改勇士的名称,可以使用`setValue`事件来修改`status:name`,但请注意value必须加单引号,不然会报错。 -### update: 立刻更新状态栏和地图显伤 +### update:立刻更新状态栏和地图显伤 如果你需要刷新状态栏和地图显伤,只需要简单地调用 `{"type": "update"}` 即可。 -### sleep: 等待多少毫秒 +### sleep:等待多少毫秒 等价于RMXP中的"等待x帧",不过是以毫秒来计算。 @@ -521,7 +522,7 @@ name是可选的,代表目标行走图的文件名。 ] ``` -### battle: 强制战斗 +### battle:强制战斗 调用battle可强制与某怪物进行战斗(而无需去触碰到它)。 @@ -552,7 +553,7 @@ name是可选的,代表目标行走图的文件名。 强制战斗没有指定loc的选项,因此战斗后需要调用hide使怪物消失(如果有必要)。 -### openDoor: 开门 +### openDoor:开门 调用`{"type":"openDoor"}`可以打开一扇门。 @@ -569,7 +570,7 @@ loc指定门的坐标,floorId指定门所在的楼层ID。如果是当前层 如果loc所在的点既不是门也不是墙壁,则忽略本事件。 -### changeFloor: 楼层切换 +### changeFloor:楼层切换 在事件中也可以对楼层进行切换。一个比较典型的例子就是TSW中,勇士在三楼的陷阱被扔到了二楼,就是一个楼层切换事件。 @@ -594,7 +595,7 @@ time为可选的,指定的话将作为楼层切换动画的时间。 !> **changeFloor到达一个新的楼层,将不会执行firstArrive事件!如有需求请在到达点设置自定义事件,然后使用type: trigger立刻调用之。** -### changePos: 当前位置切换/勇士转向 +### changePos:当前位置切换/勇士转向 有时候我们不想要楼层切换的动画效果,而是直接让勇士从A点到B点。 @@ -608,11 +609,11 @@ time为可选的,指定的话将作为楼层切换动画的时间。 ] ``` -### openShop: 打开一个全局商店 +### openShop:打开一个全局商店 使用openShop可以打开一个全局商店。有关全局商店的说明可参见[全局商店](#全局商店)。 -### disableShop: 禁用一个全局商店 +### disableShop:禁用一个全局商店 使用disableShop可以永久禁用全局商店直到再次被openShop打开为止。有关全局商店的说明可参见[全局商店](#全局商店)。 @@ -722,7 +723,7 @@ time为总移动的时间。 !> 移动图片只是会在顶层绘制“移动”效果,动画结束即消失,并不会实际对图片的显示造成影响。请与showImage事件合用。 -### setFg: 更改画面色调 +### setFg:更改画面色调 我们可以使用 `{"type": "setFg"}` 来更改画面色调。 @@ -762,7 +763,7 @@ level为天气的强度等级,在1-10之间。1级为最弱,10级为最强 !> 使用setWeather更改的天气在切换地图后会被目标地图的默认天气覆盖。 -### move: 让某个NPC/怪物移动 +### move:让某个NPC/怪物移动 如果我们需要移动某个NPC或怪物,可以使用`{"type": "move"}`。 @@ -832,7 +833,7 @@ move完毕后移动的NPC/怪物一定会消失,只不过可以通过immediate 不过值得注意的是,用这种方式移动勇士的过程中将无视一切地形,无视一切事件,中毒状态也不会扣血。 -### playBgm: 播放背景音乐 +### playBgm:播放背景音乐 使用playBgm可以播放一个背景音乐。 @@ -844,15 +845,15 @@ move完毕后移动的NPC/怪物一定会消失,只不过可以通过immediate 有关BGM播放的详细说明参见[背景音乐](element#背景音乐) -### pauseBgm: 暂停背景音乐 +### pauseBgm:暂停背景音乐 使用`{"type": "pauseBgm"}`可以暂停背景音乐的播放。 -### resumeBgm: 恢复背景音乐 +### resumeBgm:恢复背景音乐 使用`{"type": "resumeBgm"}`可以恢复背景音乐的播放。 -### playSound: 播放音效 +### playSound:播放音效 使用playSound可以立刻播放一个音效。 @@ -868,7 +869,7 @@ move完毕后移动的NPC/怪物一定会消失,只不过可以通过immediate value为音量大小,在0到100之间,默认为100。设置后,BGM和SE都将使用该音量进行播放。 -### win: 获得胜利 +### win:获得胜利 `{"type": "win", "reason": "xxx"}` 将会直接调用events.js中的win函数,并将reason作为结局传入。 @@ -876,7 +877,7 @@ value为音量大小,在0到100之间,默认为100。设置后,BGM和SE都 !> 如果`reason`不为空,则会以reason作为获胜的结局! -### lose: 游戏失败 +### lose:游戏失败 `{"type": "lose", "reason": "xxx"}` 将会直接调用`events.js`中的lose函数,并将reason作为参数传入。 @@ -901,7 +902,7 @@ text为提示文字,可以在这里给输入提示文字。这里同样可以 输入得到的结果将被赋值给flag:input,可以供后续if来进行判断。 -### if: 条件判断 +### if:条件判断 使用`{"type": "if"}`可以对条件进行判断,根据判断结果将会选择不同的分支执行。 @@ -952,7 +953,7 @@ text为提示文字,可以在这里给输入提示文字。这里同样可以 - if可以不断进行嵌套,一层套一层;如成立的场合再进行另一个if判断等。 - if语句内的内容执行完毕后将接着其后面的语句继续执行。 -### choices: 给用户提供选项 +### choices:给用户提供选项 choices是一个很麻烦的事件,它将弹出一个列表供用户进行选择。 @@ -1153,7 +1154,6 @@ choices为一个数组,其中每一项都是一个选项列表。 ``` - ### function: 自定义JS脚本 上述给出了这么多事件,但有时候往往不能满足需求,这时候就需要执行自定义脚本了。 @@ -1169,23 +1169,7 @@ choices为一个数组,其中每一项都是一个选项列表。 `{"type":"function"}`需要有一个`"function"`参数,它是一个JS函数,里面可以写任何自定义的JS脚本;系统将会执行它。 -系统所有支持的API都在[附录](api)中给出。 - -这里只简单列出给一些最常见的API: - -``` js -core.getStatus(name) //获得勇士的某个属性(hp/atk/def/…) -core.setStatus(name, value) //设置勇士某个属性值为value -core.itemCount(name) //获得某个道具的个数 -core.getItem(name, count) //获得某个道具count个 -core.setItem(name, value) //设置某个道具为value个 -core.getFlag(name, defaultValue) //获得某个自定义变量flag;如果未定义则返回defaultValue -core.setFlag(name, value) //将某个自定义变量/flag设置为value -core.hasFlag(name) //判断某个自定义flag是否成立。只有被被赋值过,且不为0或false时才会返回true。 -core.updateStatusBar() //立刻更新状态栏和地图显伤。(上面各种get和set均不会对状态栏和地图显伤更新,需要手动调用这个函数。) -core.insertAction(list) //往当前事件列表中插入一系列事件。使用这个函数插入的事件将在这段自定义JS脚本执行完毕后立刻执行。 -// …… -``` +系统所有支持的API都在[附录](api)中给出,请进行参照。 ## 同一个点的多事件处理 @@ -1197,7 +1181,7 @@ core.insertAction(list) //往当前事件列表中插入一系列事件。使用 下面以几个具体例子来进行详细说明。 -### 打怪掉宝(怪物->道具) +### 打怪掉宝 我们注意到怪物和道具都是系统默认事件,因此无需写events,而是直接在afterBattle中setBlock即可。 @@ -1209,22 +1193,24 @@ core.insertAction(list) //往当前事件列表中插入一系列事件。使用 } ``` -### 打怪变成可对话的NPC(怪物->NPC) +### 打怪变成楼梯 -由于NPC是自定义事件,因此我们需要写events。注意到events中不覆盖trigger,则还是怪物时,存在系统trigger因此会战斗;变成NPC后没有系统trigger因此会触发自定义事件。 +因为涉及到多事件处理,因此我们不能写changeFloor那一项,而是使用events(自定义事件里写楼层转换)。 + +注意到events中不覆盖trigger,则还是怪物时,存在系统trigger因此会战斗并触发afterBattle;变成NPC后没有系统trigger因此会触发自定义事件(楼层转换)。 请注意打死怪物时默认会禁用该点,因此替换后需要手动进行show来启用。 ``` js "events": { "x,y": [ - "可对话的NPC" + {"type": "changeFloor", "loc": [0,0], "floorId": "MT1"} ] }, "afterBattle": { "x,y": [ - {"type": "setBlock", "number": 121}, // 变成老人 - {"type": "show", "loc": [x,y]} // 启用该点 + {"type": "setBlock", "number": 87}, // 变成上楼梯 + {"type": "show"} // 启用该点 ] } ``` @@ -1264,6 +1250,7 @@ core.insertAction(list) //往当前事件列表中插入一系列事件。使用 - 触发器(trigger)亦采用覆盖原则,即**首先取该图块的默认触发器(例如怪物是battle,道具是getItem,门是openDoor),如果剧本的events中定义了该点的trigger则覆盖**。 - 可以通过if语句和flag来控制自定义事件具体走向哪个分支。 - 如果弄不清楚系统trigger和自定义事件等的区别,也可以全部覆盖为自定义事件,然后通过type:battle,type:openDoor等来具体进行控制。 + - 多事件处理时请不要使用`changeFloor`那一项,而是使用`events`或者`afterXXX`来处理。 ## 加点事件 @@ -1273,13 +1260,7 @@ core.insertAction(list) //往当前事件列表中插入一系列事件。使用 如果要对某个怪物进行加点操作,则首先需要修改该怪物的`point`数值,代表怪物本身的加点数值。 -``` js -... 'def': 0, 'money': 1, 'experience': 1, 'point': 1, 'special': 0}, // 在怪物后面添加point代表怪物的加点数 -``` - -然后在`functions.js`文件中找到`addPoint`函数。它将返回一个choices事件。修改此函数为我们需要的加点项即可。 - -!> V2.0版本可以直接在“脚本编辑 - 加点事件”中双击进行修改! +然后在脚本编辑中找到加点事件,双击进行修改。它将返回一个choices事件。修改此函数为我们需要的加点项即可。 ``` js ////// 加点事件 ////// @@ -1315,6 +1296,8 @@ core.insertAction(list) //往当前事件列表中插入一系列事件。使用 全局商店定义在`data.js`中,找到shops一项。 +从V2.2以后,全局商店也可以使用图块进行编辑,但仍需知道每一项的使用。 + ``` js "shops": [ // 定义全局商店(即快捷商店) { diff --git a/docs/img/plugin.png b/docs/img/plugin.png new file mode 100644 index 0000000000000000000000000000000000000000..4e87fa840c009bbdd881597ad710fd60dcbb7ec3 GIT binary patch literal 35281 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 dN6Fj5Gs<9>L{{Vfu%me@c literal 0 HcmV?d00001 diff --git a/docs/personalization.md b/docs/personalization.md index c287e4e7..36191624 100644 --- a/docs/personalization.md +++ b/docs/personalization.md @@ -75,7 +75,7 @@ images为一个数组,代表当前层所有作为背景素材的图片信息 如果第四项为true,则会在前景层(event2)上绘制,能覆盖勇士,常常用来作为柱子的上半部分等情况。 -**如果你需要让某些点不可通行(比如你建了个房子,墙壁和家具等位置不让通行),则需在`events`中指定`{"noPass": false}`,参见[自定义事件](event#自定义事件)的写法。 +**如果你需要让某些点不可通行(比如你建了个房子,墙壁和家具等位置不让通行),则需在`events`中指定`{"noPass": false}`,参见[自定义事件](event#自定义事件)的写法。** ``` js "events": { @@ -114,8 +114,35 @@ images为一个数组,代表当前层所有作为背景素材的图片信息 **`ID-数字` 对应关系定义在maps.js文件中。该文件将唯一确定一个ID对应的数字是多少。** -如果需要添加一个素材到游戏,则必须为其分配一个唯一标识符,并同时修改`icons.js`和`maps.js`两个文件。 +在V2.0中,我们可以在地图编辑器中很方便查看每个图块的三个属性信息。 +#### 注册素材 + +在V2.0的地图编辑器中,要注册新素材,我们只需要在图块属性一栏输入新素材的ID和数字。 + +![素材注册](./img/register.png) + +ID必须由数字字母下划线组成,数字在1000以内,且均不能和已有的进行重复。 + +之后刷新编辑器即可。 + +对于怪物和道具,我们也可以进行自动注册,只需要点击“自动注册”按钮,将对该栏下所有未注册的素材进行自动注册(自动分配ID和数字)。 + +素材注册完毕后,即可在游戏中正常使用,也可以被地图生成器所识别(需要重开地图生成器)。 + +#### Autotile的注册 + +但是,通过上面这种方式,我们是没办法新增并注册Autotile的。 + +除了替换样板现有的几个外,如果我们还需要新添加Autotile,则: + +1. 将新的Autotile图片复制到images目录下。文件名必须是字母数字和下划线组成。 +2. 进入icons.js,在autotile分类下进行添加该文件的名称,索引简单的写0。 +3. 指定一个数字,在maps.js中类似进行添加。 + +!> Autotile的ID和文件名应确保完全相同! + + + ### 地图生成器使用自定义素材 地图生成器是直接从js文件中读取数字-图标对应关系的。 @@ -196,7 +225,7 @@ images为一个数组,代表当前层所有作为背景素材的图片信息 如果你想要同种宝石在不同层效果不同的话,可以进行如下操作: 1. 在楼层的item_ratio中定义宝石的比率(比如1-10的写1,11-20层写2等) -2. 修改获得道具的itemEffect函数(在items.js中的itemEffect中编辑,V2.0中也可以使用编辑器) +2. 修改获得道具的itemEffect函数(编辑器中双击进行编辑) ``` js // ratio为楼层的item_ratio值,可以进行翻倍宝石属性 @@ -278,7 +307,7 @@ control.prototype.checkBlock = function () { } // ... 下略 ``` -4. 如果有更高的需求,例如想让吸血效果变成一半(如异空间),则还是在上面这些地方进行对应的修改即可。 +4. 如果有更高的需求,例如想让吸血效果变成一半,则还是在上面这些地方进行对应的修改即可。 ## 自定义装备 @@ -359,7 +388,7 @@ this.useEquipment = function (itemId) { // 使用装备 你需自己指定一个special数字,修改getSpecialText函数(属性名)和getSpecialHint函数(属性提示文字)。 -如果要修改伤害计算公式,请修改下面的calDamage函数。请注意,如果无法战斗,该函数必须返回`null`。 +如果要修改伤害计算公式,请修改下面的getDamageInfo函数。请注意,如果无法战斗,该函数必须返回`null`。 对于毒衰弱怪物的战斗后结算在`functions.js`中的afterBattle函数中。 @@ -367,6 +396,209 @@ this.useEquipment = function (itemId) { // 使用装备 `getCritical`, `getCriticalDamage`和`getDefDamage`三个函数依次计算的是该怪物的临界值、临界减伤和1防减伤。也可以适当进行修改。 +## 公共事件 + +在RM中,存在公共事件的说法;也就是通过某个指令来调用一系列事件的触发。 + +在H5中,我们可以使用“插件”的形式来达成这个效果。具体参见“脚本编辑 - 插件编写”。 + +![插件编写](./img/plugin.png) + +当我们在这上面定义了自己需要的函数(插件后),就可以通过任何方式进行调用。 + +在这个插件编写的过程中,我们可以使用任何[常见API](api)里面的代码调用;也可以通过`core.insertAction`来插入自定义事件执行。 + +下面是一个很简单的例子,我编写一个公共事件(插件),其效果是让勇士生命值变成原来的x倍,并令面前的图块消失。 + +``` js +this.myfunc = function(x) { + core.status.hero.hp *= x; // 勇士生命翻若干倍 + core.insertAction([ // 自定义事件:令面前的图块消失。 + {"type": "setValue", "name": "flag:x", "value": "core.nextX()"}, + {"type": "setValue", "name": "flag:y", "value": "core.nextY()"}, + {"type": "hide", "loc": ["flag:x", "flag:y"]} + ]); +} +``` + +然后比如我们在某个道具的使用效果 `useItemEffect` 中写 `core.plugin.myfunc(2)` 即可调用此公共事件(插件)。也可以在战后事件或自定义脚本等位置来写。 + +通过这种,将脚本和自定义事件混用的方式,可以达到和RM中公共事件类似的效果,即一个调用触发一系列事件。 + +## 自定义状态栏(新增显示项) + +在V2.2以后,我们可以自定义状态栏背景图(全塔属性 - statusLeftBackground)等等。 + +但是,如果我们还想新增其他项目的显示,比如技能塔所需要的魔力值(气息),该怎么办? + +需要进行如下几个操作: + +1. 定义图标ID;比如魔力我就定义mana,气息可以简单的定义qixi;你也可以定义其他的ID,但是不能和已有的重复。这里以mana为例。 +2. 在index.html的statusBar中(44行起),进行该状态栏项的定义。仿照其他几项,插在其应当显示的位置,注意替换掉相应的ID。 +``` html +
+ +

+
+``` +3. 在editor.html中的statusBar(305行起),仿照第二点同样添加;这一项如果不进行则会地图编辑器报错。 +4. 使用便捷PS工具,打开icons.png,新增一行并将魔力的图标P上去;记下其索引比如23(减速播放图标的下方)。 +5. 在main.js的this.statusBar中增加图片、图标和内容的定义。 +``` js +this.statusBar = { + 'images': { + // ...其他略 + 'mana': document.getElementById("img-mana"), // 图片的定义 + }, + 'icons': { + // ...其他略 + 'mana': 23, // 图标的定义,这里对应的是icons.png中的索引 + }, + // ...其他略 + 'mana': document.getElementById('mana'), // 显示内容(数据)的定义 +} +``` +6. 显示内容的设置。在control.js的updateStatusBar函数,可以对该状态栏显示内容进行设置,下面是几个例子。 +``` js +core.statusBar.mana.innerHTML = core.getFlag('mana', 0); // 设置其显示内容为flag:mana值。 +core.statusBar.mana.innerHTML = core.getFlag('mana', 0) + '/' + core.getFlag('manaMax', 0); // 显示内容将类似 "32/60" 这样。 +core.statusBar.mana.style.fontStyle = 'normal'; // 这一行会取消斜体。如果是汉字(比如技能名)的话,斜体起来会非常难看,可以通过这一句取消。 +``` +7. 在control.js的clearStatusBar函数,`statusList`里面也要增加mana项,这样清空状态栏时也会对其清空。 + +## 技能塔的支持 + +其实,在HTML5上制作技能塔是完全可行的。 + +要支持技能塔,可能需要如下几个方面: + +- 魔力(和上限)的定义添加 +- 状态栏的显示 +- 技能的触发(按键与录像问题) +- 技能的效果 + +下面依次进行描述。 + +### 魔力的定义添加 + +当我们定义了魔力的ID,比如`mana`后,要使用它,一般有两种方式:属性获取`status:mana`或者flag标记`flag:mana`。 + +如果要属性获取,则需要打开`data.js`文件,并在`hero`中添加定义。 + +通过这种方式定义的,可以通过`core.setStatus('mana', 0)`以及`core.getStatus('mana')`来设置或获取。 + +``` js +'hero': { + // ... 上略 + 'mana': 0, // 增添mana定义,可以放在experience之后。同理可定义manaMax表示当前最大魔力值。 +} +``` + +如果要flag标记,则无需额外在任何地方进行定义。只需要在设置或取用的时候使用 `core.setFlag('mana', 0)` 或 `core.getFlag('mana', 0)` 即可。 + +下面我都使用属性获取的方式来进行说明。 + +### 状态栏的显示 + +首先我们需要额外新增一个状态栏;参见上面的自定义状态栏的做法来新增一栏。 + +我们可以在魔力那一行显示当前值和最大值: + +``` js +core.setStatus('mana', Math.min(core.getStatus('mana'), core.getStatus('manaMax')); // 如果魔力存在上限,则不能超过其上限值 +core.statusBar.mana.innerHTML = core.getStatus('mana') + '/' + core.getStatus('manaMax', 0); // 显示比如 6/30 这样 +``` + +如果我们还需要显示当前使用的技能名,也是可以的;定义一个ID为skill,然后按照上面的做法新增一行。 + +请注意,如果是中文字符,需要取消斜体(不然会非常难看的)! + +``` js +core.statusBar.skill.style.fontStyle = 'normal'; // 取消斜体显示 +core.statusBar.skill.innerHTML = core.getFlag('skillName', '无'); // 使用flag:skillName表示当前激活的技能名。 +``` + +### 技能的触发 + +我们可以按键触发技能。 + +要修改按键,我们可以在`actions.js`的`keyUp`进行处理: + +我们设置一个快捷键进行绑定,比如`W`,其keycode是87。(有关每个键的keycode搜一下就能得到) + +!> H5不支持组合快捷键,所以不存在`W+1`这种组合快捷键的说法! + +然后在`actions.js`的`keyUp`函数的`switch`中进行处理。 + +``` js +case 87: // W + if (core.status.heroStop) { // 当前停止状态;这个if需要加,不能在行走过程中触发不然容易出错。 + if (core.getFlag('skill', 0)==0) { // 判断当前是否已经开了技能 + if (能开技能) { // 这里要写当前能否开技能的条件判断 + core.setFlag('skill', 1); // 开技能1 + core.setFlag('skillName', '二倍斩'); // 设置技能名 + } + else { + core.drawTip("当前不能开技能!"); + } + } + else { // 关闭技能 + core.setFlag('skill', 0); // 关闭技能状态 + core.setFlag('skillName', '无'); + } + core.updateStatusBar(); // 立刻更新状态栏和地图显伤 + core.status.route.push("key:"+keyCode); // 录像的支持!这句话必须要加,不然录像回放会出错! + } + break; +``` + +简单的说,用flag:skill判断当前开启的技能,flag:skillName表示该技能名。(可在状态栏显示) + +在勇士处于停止的条件下,按下W键时,判断当前是否开启了技能,如果开启则关闭,没开则再判断是否允许开启(魔力值够不够等)。 + +`core.status.route.push("key:"+keyCode);` 这句话是对录像的支持,一定要加(这样录像播放时也会模拟该按键)。 + +!> 1,2,3这三个键被默认绑定到了破炸飞;如果想用的话也是一样,只不过是把已有的实现进行替换。 + +!> 手机端可以通过长按任何位置调出虚拟键盘,再进行按键,和键盘按键是等价的效果! + +### 技能的效果 + +最后一点就是技能的效果;其实到了这里就和RM差不多了。 + +技能的效果要分的话有地图类技能,战斗效果类技能,后续影响类技能什么的,这里只介绍最简单的战斗效果类技能。 +其他的几类技能根据需求可能更为麻烦,有兴趣可自行进行研究。 + +战斗效果内技能要改两个地方:战斗伤害计算,战后扣除魔力值。 + +战斗伤害计算在`enenmys.js`的`getDamageInfo`函数,有需求直接修改这个函数即可。 + +战后扣除魔力值则在脚本编辑的`afterBattle`中进行编辑即可。 + +举个例子,我设置一个勇士的技能:二倍斩,开启技能消耗5点魔力,下一场战斗攻击力翻倍。 + +那么,直接在`getDamageInfo`中进行判断: + +``` js +if (core.getFlag('skill', 0)==1) { // 开启了技能1 + hero_atk *= 2; // 计算时攻击力翻倍 +} +``` + +然后在脚本编辑的战后事件中进行魔力值的扣除: + +``` js +if (core.getFlag('skill', 0)==1) { // 开启了技能1 + core.status.hero.mana -= 5; // 扣除5点魔力值 + core.setFlag('skill', 0); // 自动关闭技能 + core.setFlag('skillName', '无'); +} +``` + +  + +通过上述这几种方式,我们就能成功的让H5支持技能啦! + ## 根据难度分歧来自定义地图 遗憾的是,所有地图数据必须在剧本的map中指定,换句话说,我们无法在游戏进行中动态修改地图,比如为简单难度增加一个血瓶。 diff --git a/libs/core.js b/libs/core.js index 34e06f1a..78d0a7fa 100644 --- a/libs/core.js +++ b/libs/core.js @@ -651,6 +651,11 @@ core.prototype.getBlock = function (x, y, floorId, needEnable) { return core.maps.getBlock(x,y,floorId,needEnable); } +////// 获得某个点的blockId ////// +core.prototype.getBlockId = function (x, y, floorId, needEnable) { + return core.maps.getBlockId(x, y, floorId, needEnable); +} + ////// 显示移动某块的动画,达到{“type”:”move”}的效果 ////// core.prototype.moveBlock = function(x,y,steps,time,immediateHide,callback) { core.maps.moveBlock(x,y,steps,time,immediateHide,callback) diff --git a/libs/events.js b/libs/events.js index 35d8d70c..8cf62d64 100644 --- a/libs/events.js +++ b/libs/events.js @@ -349,6 +349,8 @@ events.prototype.doAction = function() { core.events.doAction(); break; case "show": // 显示 + if (!core.isset(data.loc)) + data.loc = [x,y]; if ((typeof data.loc[0] == 'number' || typeof data.loc[0] == 'string') && (typeof data.loc[1] == 'number' || typeof data.loc[1] == 'string')) data.loc = [[core.calValue(data.loc[0]), core.calValue(data.loc[1])]]; diff --git a/libs/maps.js b/libs/maps.js index fa80da9f..39a0e306 100644 --- a/libs/maps.js +++ b/libs/maps.js @@ -537,6 +537,14 @@ maps.prototype.getBlock = function (x, y, floorId, needEnable) { return null; } +////// 获得某个点的blockId ////// +maps.prototype.getBlockId = function (x, y, floorId, needEnable) { + var block = core.getBlock(x, y, floorId, needEnable); + if (block == null) return null; + if (core.isset(block.block.event)) return block.block.event.id; + return null; +} + ////// 显示移动某块的动画,达到{“type”:”move”}的效果 ////// maps.prototype.moveBlock = function(x,y,steps,time,immediateHide,callback) { time = time || 500;