Merge remote-tracking branch 'refs/remotes/ckcz123/v2.0' into v2.x

This commit is contained in:
YouWei Zhao 2018-05-24 11:57:26 +08:00
commit 1865f2368a
48 changed files with 2251 additions and 970 deletions

View File

@ -5,7 +5,7 @@
HTML5 canvas制作的魔塔样板支持全平台游戏 HTML5 canvas制作的魔塔样板支持全平台游戏
**即使完全不会编程的用户,按照模板和说明文档也能很快做出一个魔塔游戏!** **即使完全不会编程的用户,按照模板和说明文档也能很快做出一个魔塔游戏!**
* [List / HTML5魔塔游戏列表](http://mota.pw/) * [List / HTML5魔塔游戏列表](https://h5mota.com/)
* [Demo / 样板效果](https://ckcz123.com/games/template/) * [Demo / 样板效果](https://ckcz123.com/games/template/)
* [Docs / 使用文档说明](https://ckcz123.github.io/mota-js/) * [Docs / 使用文档说明](https://ckcz123.github.io/mota-js/)
* [Video / 视频教程](http://www.bilibili.com/video/av17608025/) * [Video / 视频教程](http://www.bilibili.com/video/av17608025/)
@ -35,18 +35,12 @@ HTML5 canvas制作的魔塔样板支持全平台游戏
│ ├─ /animates/ # 动画目录 │ ├─ /animates/ # 动画目录
│ ├─ /floors/ # 剧本文件,记录了每个地图的数据和事件 │ ├─ /floors/ # 剧本文件,记录了每个地图的数据和事件
│ ├─ /images/ # 所有图片素材目录 │ ├─ /images/ # 所有图片素材目录
│ │ ├─ /常用素材/ # 可以被直接替换的素材
│ │ └─ *.png # 对应的某个具体的图片素材
│ ├─ /sounds/ # 音效目录 │ ├─ /sounds/ # 音效目录
│ ├─ comments.js # 对怪物、道具、楼层等的注释
│ ├─ data.comment.js # 对全局变量的注释
│ ├─ data.js # 全局变量信息 │ ├─ data.js # 全局变量信息
│ ├─ enemys.js # 怪物属性数据 │ ├─ enemys.js # 怪物属性数据
│ ├─ functions.comment.js # 脚本编辑的注释
│ ├─ functions.js # 可能会被修改的脚本代码 │ ├─ functions.js # 可能会被修改的脚本代码
│ ├─ icons.js # 素材和ID的对应关系定义 │ ├─ icons.js # 素材和ID的对应关系定义
│ ├─ items.js # 道具的定义,获得道具的效果 │ ├─ items.js # 道具的定义,获得道具的效果
│ ├─ maps.commment.js # 地图信息的注释
│ └─ maps.js # 地图和数字的对应关系 │ └─ maps.js # 地图和数字的对应关系
├── /常用工具/ # 一些常用工具,可以辅助造塔 ├── /常用工具/ # 一些常用工具,可以辅助造塔
│ ├─ RM动画导出器.exe # 能从RMXP中导出动画以供H5使用。 http://github.com/ckcz123/animate_export/ │ ├─ RM动画导出器.exe # 能从RMXP中导出动画以供H5使用。 http://github.com/ckcz123/animate_export/
@ -224,4 +218,4 @@ HTML5 canvas制作的魔塔样板支持全平台游戏
HTML5魔塔交流群群号 `539113091` HTML5魔塔交流群群号 `539113091`
如有其它意见或建议,也可以通过发[issues](https://github.com/ckcz123/mota-js/issues)、或邮件至[ckcz123.com](mailto:ckcz123.com)联系我。 如有其它意见或建议,也可以通过发[issues](https://github.com/ckcz123/mota-js/issues)、或邮件至[ckcz123@126.com](mailto:ckcz123@126.com)联系我。

View File

@ -236,7 +236,7 @@ text_0_s
/* text_0_s /* text_0_s
tooltip : text显示一段文字剧情 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 : ["欢迎使用事件编辑器(双击方块进入多行编辑)"] default : ["欢迎使用事件编辑器(双击方块进入多行编辑)"]
var code = '"'+EvalString_0+'",\n'; var code = '"'+EvalString_0+'",\n';
return code; return code;
@ -248,7 +248,7 @@ text_1_s
/* text_1_s /* text_1_s
tooltip : text显示一段文字剧情,选项较多请右键点击帮助 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","","欢迎使用事件编辑器(双击方块进入多行编辑)"] default : ["小妖精","fairy","","欢迎使用事件编辑器(双击方块进入多行编辑)"]
var title=''; var title='';
if (EvalString_0==''){ if (EvalString_0==''){
@ -272,7 +272,7 @@ autoText_s
/* autoText_s /* autoText_s
tooltip : autoText自动剧情文本,用户无法跳过自动剧情文本,大段剧情文本请添加“是否跳过剧情”的提示 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自动剧情文本"] default : ["小妖精","fairy","",3000,"双击方块进入多行编辑\\n自动剧情文本\\n自动剧情文本\\n自动剧情文本"]
var title=''; var title='';
if (EvalString_0==''){ if (EvalString_0==''){
@ -296,7 +296,7 @@ setText_s
/* setText_s /* setText_s
tooltip : setText设置剧情文本的属性,颜色为RGB三元组或RGBA四元组,打字间隔为剧情文字添加的时间间隔,为整数或不填 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,''] default : [null,"","","",null,'']
SetTextPosition_List_0 =SetTextPosition_List_0==='null'?'': ', "position": "'+SetTextPosition_List_0+'"'; 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)?$/; 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 /* tip_s
tooltip : tip显示一段提示文字 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 : ["这段话将在左上角以气泡形式显示"] default : ["这段话将在左上角以气泡形式显示"]
var code = '{"type": "tip", "text": "'+EvalString_0+'"},\n'; var code = '{"type": "tip", "text": "'+EvalString_0+'"},\n';
return code; return code;
@ -339,37 +339,41 @@ setValue_s
/* setValue_s /* setValue_s
tooltip : setValue设置勇士的某个属性、道具个数, 或某个变量/Flag的值 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 colour : this.dataColor
var code = '{"type": "setValue", "name": "'+idString_e_0+'", "value": "'+expression_0+'"},\n'; var code = '{"type": "setValue", "name": "'+idString_e_0+'", "value": "'+expression_0+'"},\n';
return code; return code;
*/; */;
show_s show_s
: '显示事件' 'x' EvalString ',' 'y' EvalString '楼层' IdString? '动画时间' Int? Newline : '显示事件' 'x' EvalString? ',' 'y' EvalString? '楼层' IdString? '动画时间' Int? Newline
/* show_s /* show_s
tooltip : show: 将禁用事件启用,楼层和动画时间可不填,xy可用逗号分隔表示多个点 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 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 : ["0","0","",500] default : ["","","",500]
colour : this.eventColor colour : this.eventColor
IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"'); var floorstr = '';
var pattern1 = /^flag:[0-9a-zA-Z_][0-9a-zA-Z_\-:]*$/; if (EvalString_0 && EvalString_1) {
if(pattern1.test(EvalString_0) || pattern1.test(EvalString_1)){ var pattern1 = /^flag:[0-9a-zA-Z_][0-9a-zA-Z_\-:]*$/;
EvalString_0=MotaActionFunctions.PosString_pre(EvalString_0); if(pattern1.test(EvalString_0) || pattern1.test(EvalString_1)){
EvalString_1=MotaActionFunctions.PosString_pre(EvalString_1); EvalString_0=MotaActionFunctions.PosString_pre(EvalString_0);
EvalString_0=[EvalString_0,EvalString_1] EvalString_1=MotaActionFunctions.PosString_pre(EvalString_1);
} else { EvalString_0=[EvalString_0,EvalString_1]
var pattern2 = /^([+-]?\d+)(,[+-]?\d+)*$/; } else {
if(!pattern2.test(EvalString_0) || !pattern2.test(EvalString_1))throw new Error('坐标格式错误,请右键点击帮助查看格式'); var pattern2 = /^([+-]?\d+)(,[+-]?\d+)*$/;
EvalString_0=EvalString_0.split(','); if(!pattern2.test(EvalString_0) || !pattern2.test(EvalString_1))throw new Error('坐标格式错误,请右键点击帮助查看格式');
EvalString_1=EvalString_1.split(','); EvalString_0=EvalString_0.split(',');
if(EvalString_0.length!==EvalString_1.length)throw new Error('坐标格式错误,请右键点击帮助查看格式'); EvalString_1=EvalString_1.split(',');
for(var ii=0;ii<EvalString_0.length;ii++)EvalString_0[ii]='['+EvalString_0[ii]+','+EvalString_1[ii]+']'; if(EvalString_0.length!==EvalString_1.length)throw new Error('坐标格式错误,请右键点击帮助查看格式');
for(var ii=0;ii<EvalString_0.length;ii++)EvalString_0[ii]='['+EvalString_0[ii]+','+EvalString_1[ii]+']';
}
floorstr = ', "loc": ['+EvalString_0.join(',')+']';
} }
IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"');
Int_0 = Int_0 ?(', "time": '+Int_0):''; Int_0 = Int_0 ?(', "time": '+Int_0):'';
var code = '{"type": "show", "loc": ['+EvalString_0.join(',')+']'+IdString_0+''+Int_0+'},\n'; var code = '{"type": "show"'+floorstr+IdString_0+''+Int_0+'},\n';
return code; return code;
*/; */;
@ -379,7 +383,7 @@ hide_s
/* hide_s /* hide_s
tooltip : hide: 将一个启用事件禁用,所有参数均可不填,代表禁用事件自身,xy可用逗号分隔表示多个点 tooltip : hide: 将一个启用事件禁用,所有参数均可不填,代表禁用事件自身,xy可用逗号分隔表示多个点
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=hide-%e5%b0%86%e4%b8%80%e4%b8%aa%e5%90%af%e7%94%a8%e4%ba%8b%e4%bb%b6%e7%a6%81%e7%94%a8 helpUrl : https://ckcz123.github.io/mota-js/#/event?id=hide%EF%BC%9A%E5%B0%86%E4%B8%80%E4%B8%AA%E5%90%AF%E7%94%A8%E4%BA%8B%E4%BB%B6%E7%A6%81%E7%94%A8
default : ["","","",500] default : ["","","",500]
colour : this.eventColor colour : this.eventColor
var floorstr = ''; var floorstr = '';
@ -411,7 +415,7 @@ trigger_s
/* trigger_s /* trigger_s
tooltip : trigger: 立即触发另一个地点的事件 tooltip : trigger: 立即触发另一个地点的事件
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=trigger-%e7%ab%8b%e5%8d%b3%e8%a7%a6%e5%8f%91%e5%8f%a6%e4%b8%80%e4%b8%aa%e5%9c%b0%e7%82%b9%e7%9a%84%e4%ba%8b%e4%bb%b6 helpUrl : https://ckcz123.github.io/mota-js/#/event?id=trigger%EF%BC%9A%E7%AB%8B%E5%8D%B3%E8%A7%A6%E5%8F%91%E5%8F%A6%E4%B8%80%E4%B8%AA%E5%9C%B0%E7%82%B9%E7%9A%84%E4%BA%8B%E4%BB%B6
default : ["0","0"] default : ["0","0"]
colour : this.eventColor colour : this.eventColor
var code = '{"type": "trigger", "loc": ['+PosString_0+','+PosString_1+']},\n'; var code = '{"type": "trigger", "loc": ['+PosString_0+','+PosString_1+']},\n';
@ -424,7 +428,7 @@ revisit_s
/* revisit_s /* revisit_s
tooltip : revisit: 立即重启当前事件 tooltip : revisit: 立即重启当前事件
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=revisit-%e7%ab%8b%e5%8d%b3%e9%87%8d%e5%90%af%e5%bd%93%e5%89%8d%e4%ba%8b%e4%bb%b6 helpUrl : https://ckcz123.github.io/mota-js/#/event?id=revisit%EF%BC%9A%E7%AB%8B%E5%8D%B3%E9%87%8D%E5%90%AF%E5%BD%93%E5%89%8D%E4%BA%8B%E4%BB%B6
colour : this.eventColor colour : this.eventColor
var code = '{"type": "revisit"},\n'; var code = '{"type": "revisit"},\n';
return code; return code;
@ -436,7 +440,7 @@ exit_s
/* exit_s /* exit_s
tooltip : exit: 立刻结束当前事件 tooltip : exit: 立刻结束当前事件
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=exit-%e7%ab%8b%e5%88%bb%e7%bb%93%e6%9d%9f%e5%bd%93%e5%89%8d%e4%ba%8b%e4%bb%b6 helpUrl : https://ckcz123.github.io/mota-js/#/event?id=exit%EF%BC%9A%E7%AB%8B%E5%88%BB%E7%BB%93%E6%9D%9F%E5%BD%93%E5%89%8D%E4%BA%8B%E4%BB%B6
colour : this.eventColor colour : this.eventColor
var code = '{"type": "exit"},\n'; var code = '{"type": "exit"},\n';
return code; return code;
@ -448,7 +452,7 @@ setBlock_s
/* setBlock_s /* setBlock_s
tooltip : setBlock设置某个图块,忽略坐标楼层则为当前事件 tooltip : setBlock设置某个图块,忽略坐标楼层则为当前事件
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=setblock%ef%bc%9a%e8%ae%be%e7%bd%ae%e6%9f%90%e4%b8%aa%e5%9b%be%e5%9d%97 helpUrl : https://ckcz123.github.io/mota-js/#/event?id=setblock%EF%BC%9A%E8%AE%BE%E7%BD%AE%E6%9F%90%E4%B8%AA%E5%9B%BE%E5%9D%97
colour : this.dataColor colour : this.dataColor
default : [0,"","",""] default : [0,"","",""]
var floorstr = ''; var floorstr = '';
@ -466,7 +470,7 @@ setHeroIcon_s
/* setHeroIcon_s /* setHeroIcon_s
tooltip : setHeroIcon更改角色行走图 tooltip : setHeroIcon更改角色行走图
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=setHeroIcon-%e6%9b%b4%e6%94%b9%e8%a7%92%e8%89%b2%e8%a1%8c%e8%b5%b0%e5%9b%be helpUrl : https://ckcz123.github.io/mota-js/#/event?id=setheroicon%EF%BC%9A%E6%9B%B4%E6%94%B9%E8%A7%92%E8%89%B2%E8%A1%8C%E8%B5%B0%E5%9B%BE
colour : this.dataColor colour : this.dataColor
default : ["hero.png"] default : ["hero.png"]
EvalString_0 = EvalString_0 && (', "name": "'+EvalString_0+'"'); EvalString_0 = EvalString_0 && (', "name": "'+EvalString_0+'"');
@ -480,7 +484,7 @@ update_s
/* update_s /* update_s
tooltip : update: 立刻更新状态栏和地图显伤 tooltip : update: 立刻更新状态栏和地图显伤
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=update-%e7%ab%8b%e5%88%bb%e6%9b%b4%e6%96%b0%e7%8a%b6%e6%80%81%e6%a0%8f%e5%92%8c%e5%9c%b0%e5%9b%be%e6%98%be%e4%bc%a4 helpUrl : https://ckcz123.github.io/mota-js/#/event?id=update%EF%BC%9A%E7%AB%8B%E5%88%BB%E6%9B%B4%E6%96%B0%E7%8A%B6%E6%80%81%E6%A0%8F%E5%92%8C%E5%9C%B0%E5%9B%BE%E6%98%BE%E4%BC%A4
colour : this.dataColor colour : this.dataColor
var code = '{"type": "update"},\n'; var code = '{"type": "update"},\n';
return code; return code;
@ -492,32 +496,20 @@ sleep_s
/* sleep_s /* sleep_s
tooltip : sleep: 等待多少毫秒 tooltip : sleep: 等待多少毫秒
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=sleep-%e7%ad%89%e5%be%85%e5%a4%9a%e5%b0%91%e6%af%ab%e7%a7%92 helpUrl : https://ckcz123.github.io/mota-js/#/event?id=sleep%EF%BC%9A%E7%AD%89%E5%BE%85%E5%A4%9A%E5%B0%91%E6%AF%AB%E7%A7%92
default : [500] default : [500]
colour : this.soundColor colour : this.soundColor
var code = '{"type": "sleep", "time": '+Int_0+'},\n'; var code = '{"type": "sleep", "time": '+Int_0+'},\n';
return code; return code;
*/; */;
wait_s
: '等待用户操作'
/* wait_s
tooltip : wait: 等待用户操作
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=wait-%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;
*/;
battle_s battle_s
: '强制战斗' IdString Newline : '强制战斗' IdString Newline
/* battle_s /* battle_s
tooltip : battle: 强制战斗 tooltip : battle: 强制战斗
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=battle-%e5%bc%ba%e5%88%b6%e6%88%98%e6%96%97 helpUrl : https://ckcz123.github.io/mota-js/#/event?id=battle%EF%BC%9A%E5%BC%BA%E5%88%B6%E6%88%98%E6%96%97
default : ["greenSlime"] default : ["greenSlime"]
colour : this.dataColor colour : this.dataColor
var code = '{"type": "battle", "id": "'+IdString_0+'"},\n'; var code = '{"type": "battle", "id": "'+IdString_0+'"},\n';
@ -530,7 +522,7 @@ openDoor_s
/* openDoor_s /* openDoor_s
tooltip : openDoor: 开门,楼层可不填表示当前层 tooltip : openDoor: 开门,楼层可不填表示当前层
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=opendoor-%e5%bc%80%e9%97%a8 helpUrl : https://ckcz123.github.io/mota-js/#/event?id=opendoor%EF%BC%9A%E5%BC%80%E9%97%A8
default : ["","",""] default : ["","",""]
colour : this.dataColor colour : this.dataColor
IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"'); IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"');
@ -544,7 +536,7 @@ changeFloor_s
/* changeFloor_s /* changeFloor_s
tooltip : changeFloor: 楼层切换,动画时间可不填 tooltip : changeFloor: 楼层切换,动画时间可不填
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=changefloor-%e6%a5%bc%e5%b1%82%e5%88%87%e6%8d%a2 helpUrl : https://ckcz123.github.io/mota-js/#/event?id=changefloor%EF%BC%9A%E6%A5%BC%E5%B1%82%E5%88%87%E6%8D%A2
default : ["MT1","0","0",null,500] default : ["MT1","0","0",null,500]
colour : this.dataColor colour : this.dataColor
DirectionEx_List_0 = DirectionEx_List_0 && (', "direction": "'+DirectionEx_List_0+'"'); DirectionEx_List_0 = DirectionEx_List_0 && (', "direction": "'+DirectionEx_List_0+'"');
@ -559,7 +551,7 @@ changePos_0_s
/* changePos_0_s /* changePos_0_s
tooltip : changePos: 当前位置切换 tooltip : changePos: 当前位置切换
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=changepos-%e5%bd%93%e5%89%8d%e4%bd%8d%e7%bd%ae%e5%88%87%e6%8d%a2%e5%8b%87%e5%a3%ab%e8%bd%ac%e5%90%91 helpUrl : https://ckcz123.github.io/mota-js/#/event?id=changepos%EF%BC%9A%E5%BD%93%E5%89%8D%E4%BD%8D%E7%BD%AE%E5%88%87%E6%8D%A2%E5%8B%87%E5%A3%AB%E8%BD%AC%E5%90%91
default : ["","",null] default : ["","",null]
colour : this.dataColor colour : this.dataColor
DirectionEx_List_0 = DirectionEx_List_0 && (', "direction": "'+DirectionEx_List_0+'"'); DirectionEx_List_0 = DirectionEx_List_0 && (', "direction": "'+DirectionEx_List_0+'"');
@ -573,7 +565,7 @@ changePos_1_s
/* changePos_1_s /* changePos_1_s
tooltip : changePos: 勇士转向 tooltip : changePos: 勇士转向
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=changepos-%e5%bd%93%e5%89%8d%e4%bd%8d%e7%bd%ae%e5%88%87%e6%8d%a2%e5%8b%87%e5%a3%ab%e8%bd%ac%e5%90%91 helpUrl : https://ckcz123.github.io/mota-js/#/event?id=changepos%EF%BC%9A%E5%BD%93%E5%89%8D%E4%BD%8D%E7%BD%AE%E5%88%87%E6%8D%A2%E5%8B%87%E5%A3%AB%E8%BD%AC%E5%90%91
colour : this.dataColor colour : this.dataColor
default : [null] default : [null]
var code = '{"type": "changePos", "direction": "'+Direction_List_0+'"},\n'; var code = '{"type": "changePos", "direction": "'+Direction_List_0+'"},\n';
@ -586,7 +578,7 @@ openShop_s
/* openShop_s /* openShop_s
tooltip : 全局商店 tooltip : 全局商店
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=%e5%85%a8%e5%b1%80%e5%95%86%e5%ba%97 helpUrl : https://ckcz123.github.io/mota-js/#/event?id=openshop%EF%BC%9A%E6%89%93%E5%BC%80%E4%B8%80%E4%B8%AA%E5%85%A8%E5%B1%80%E5%95%86%E5%BA%97
default : ["shop1"] default : ["shop1"]
var code = '{"type": "openShop", "id": "'+IdString_0+'"},\n'; var code = '{"type": "openShop", "id": "'+IdString_0+'"},\n';
return code; return code;
@ -598,7 +590,7 @@ disableShop_s
/* disableShop_s /* disableShop_s
tooltip : 全局商店 tooltip : 全局商店
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=%e5%85%a8%e5%b1%80%e5%95%86%e5%ba%97 helpUrl : https://ckcz123.github.io/mota-js/#/event?id=disableshop%EF%BC%9A%E7%A6%81%E7%94%A8%E4%B8%80%E4%B8%AA%E5%85%A8%E5%B1%80%E5%95%86%E5%BA%97
default : ["shop1"] default : ["shop1"]
colour : this.eventColor colour : this.eventColor
var code = '{"type": "disableShop", "id": "'+IdString_0+'"},\n'; var code = '{"type": "disableShop", "id": "'+IdString_0+'"},\n';
@ -611,7 +603,7 @@ animate_s
/* animate_s /* animate_s
tooltip : animate显示动画,位置填hero或者1,2形式的位置,或者不填代表当前事件点 tooltip : animate显示动画,位置填hero或者1,2形式的位置,或者不填代表当前事件点
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=animate%ef%bc%9a%e6%98%be%e7%a4%ba%e5%8a%a8%e7%94%bb helpUrl : https://ckcz123.github.io/mota-js/#/event?id=animate%EF%BC%9A%E6%98%BE%E7%A4%BA%E5%8A%A8%E7%94%BB
default : ["zone","hero"] default : ["zone","hero"]
colour : this.soundColor colour : this.soundColor
if (EvalString_0) { if (EvalString_0) {
@ -635,7 +627,7 @@ showImage_0_s
/* showImage_0_s /* showImage_0_s
tooltip : showImage显示图片 tooltip : showImage显示图片
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=showimage%ef%bc%9a%e6%98%be%e7%a4%ba%e5%9b%be%e7%89%87 helpUrl : https://ckcz123.github.io/mota-js/#/event?id=showimage%EF%BC%9A%E6%98%BE%E7%A4%BA%E5%9B%BE%E7%89%87
default : ["bg.jpg","0","0"] default : ["bg.jpg","0","0"]
colour : this.printColor colour : this.printColor
var code = '{"type": "showImage", "name": "'+EvalString_0+'", "loc": ['+PosString_0+','+PosString_1+']},\n'; var code = '{"type": "showImage", "name": "'+EvalString_0+'", "loc": ['+PosString_0+','+PosString_1+']},\n';
@ -648,7 +640,7 @@ showImage_1_s
/* showImage_1_s /* showImage_1_s
tooltip : showImage清除所有显示的图片 tooltip : showImage清除所有显示的图片
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=showimage%ef%bc%9a%e6%98%be%e7%a4%ba%e5%9b%be%e7%89%87 helpUrl : https://ckcz123.github.io/mota-js/#/event?id=showimage%EF%BC%9A%E6%98%BE%E7%A4%BA%E5%9B%BE%E7%89%87
colour : this.printColor colour : this.printColor
var code = '{"type": "showImage"},\n'; var code = '{"type": "showImage"},\n';
return code; return code;
@ -660,7 +652,7 @@ animateImage_0_s
/* animateImage_0_s /* animateImage_0_s
tooltip : animageImage图片淡入 tooltip : animageImage图片淡入
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=animateimage%ef%bc%9a%e5%9b%be%e7%89%87%e6%b7%a1%e5%85%a5%e6%b7%a1%e5%87%b helpUrl : https://ckcz123.github.io/mota-js/#/event?id=animateimage%EF%BC%9A%E5%9B%BE%E7%89%87%E6%B7%A1%E5%85%A5%E6%B7%A1%E5%87%BA
default : ["bg.jpg","0","0",500] default : ["bg.jpg","0","0",500]
colour : this.printColor colour : this.printColor
var code = '{"type": "animateImage", "action": "show", "name": "'+EvalString_0+'", "loc": ['+PosString_0+','+PosString_1+'], "time": '+Int_0+'},\n'; var code = '{"type": "animateImage", "action": "show", "name": "'+EvalString_0+'", "loc": ['+PosString_0+','+PosString_1+'], "time": '+Int_0+'},\n';
@ -673,7 +665,7 @@ animateImage_1_s
/* animateImage_1_s /* animateImage_1_s
tooltip : animageImage图片淡出 tooltip : animageImage图片淡出
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=animateimage%ef%bc%9a%e5%9b%be%e7%89%87%e6%b7%a1%e5%85%a5%e6%b7%a1%e5%87%b helpUrl : https://ckcz123.github.io/mota-js/#/event?id=animateimage%EF%BC%9A%E5%9B%BE%E7%89%87%E6%B7%A1%E5%85%A5%E6%B7%A1%E5%87%BA
default : ["bg.jpg","0","0",500] default : ["bg.jpg","0","0",500]
colour : this.printColor colour : this.printColor
var code = '{"type": "animateImage", "action": "hide", "name": "'+EvalString_0+'", "loc": ['+PosString_0+','+PosString_1+'], "time": '+Int_0+'},\n'; var code = '{"type": "animateImage", "action": "hide", "name": "'+EvalString_0+'", "loc": ['+PosString_0+','+PosString_1+'], "time": '+Int_0+'},\n';
@ -686,7 +678,7 @@ showGif_0_s
/* showGif_0_s /* showGif_0_s
tooltip : showGif显示动图 tooltip : showGif显示动图
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=showgif%ef%bc%9a%e6%98%be%e7%a4%ba%e5%8a%a8%e5%9b%be helpUrl : https://ckcz123.github.io/mota-js/#/event?id=showgif%EF%BC%9A%E6%98%BE%E7%A4%BA%E5%8A%A8%E5%9B%BE
default : ["bg.gif","0","0"] default : ["bg.gif","0","0"]
colour : this.printColor colour : this.printColor
var code = '{"type": "showGif", "name": "'+EvalString_0+'", "loc": ['+PosString_0+','+PosString_1+']},\n'; var code = '{"type": "showGif", "name": "'+EvalString_0+'", "loc": ['+PosString_0+','+PosString_1+']},\n';
@ -699,7 +691,7 @@ showGif_1_s
/* showGif_1_s /* showGif_1_s
tooltip : showGif清除所有显示的动图 tooltip : showGif清除所有显示的动图
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=showgif%ef%bc%9a%e6%98%be%e7%a4%ba%e5%8a%a8%e5%9b%be helpUrl : https://ckcz123.github.io/mota-js/#/event?id=showgif%EF%BC%9A%E6%98%BE%E7%A4%BA%E5%8A%A8%E5%9B%BE
colour : this.printColor colour : this.printColor
var code = '{"type": "showGif"},\n'; var code = '{"type": "showGif"},\n';
return code; return code;
@ -712,7 +704,7 @@ moveImage_0_s
/* moveImage_0_s /* moveImage_0_s
tooltip : moveImage图片移动 tooltip : moveImage图片移动
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=moveImage%ef%bc%9a%e6%98%be%e7%a4%ba%e5%8a%a8%e5%9b%be helpUrl : https://ckcz123.github.io/mota-js/#/event?id=moveimage%EF%BC%9A%E5%9B%BE%E7%89%87%E7%A7%BB%E5%8A%A8
default : ["bg.jpg","0","0","0","0",500] default : ["bg.jpg","0","0","0","0",500]
colour : this.printColor colour : this.printColor
var code = '{"type": "moveImage", "name": "'+EvalString_0+'", "from": ['+PosString_0+','+PosString_1+'], "to": ['+PosString_2+','+PosString_3+'], "time": '+Int_0+'},\n'; var code = '{"type": "moveImage", "name": "'+EvalString_0+'", "from": ['+PosString_0+','+PosString_1+'], "to": ['+PosString_2+','+PosString_3+'], "time": '+Int_0+'},\n';
@ -725,7 +717,7 @@ setFg_0_s
/* setFg_0_s /* setFg_0_s
tooltip : setFg: 更改画面色调,动画时间可不填 tooltip : setFg: 更改画面色调,动画时间可不填
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=setfg-%e6%9b%b4%e6%94%b9%e7%94%bb%e9%9d%a2%e8%89%b2%e8%b0%83 helpUrl : https://ckcz123.github.io/mota-js/#/event?id=setfg%EF%BC%9A%E6%9B%B4%E6%94%B9%E7%94%BB%E9%9D%A2%E8%89%B2%E8%B0%83
default : [255,255,255,1,500] default : [255,255,255,1,500]
colour : this.soundColor colour : this.soundColor
var limit = function(v,min,max) { var limit = function(v,min,max) {
@ -748,7 +740,7 @@ setFg_1_s
/* setFg_1_s /* setFg_1_s
tooltip : setFg: 恢复画面色调,动画时间可不填 tooltip : setFg: 恢复画面色调,动画时间可不填
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=setfg-%e6%9b%b4%e6%94%b9%e7%94%bb%e9%9d%a2%e8%89%b2%e8%b0%83 helpUrl : https://ckcz123.github.io/mota-js/#/event?id=setfg%EF%BC%9A%E6%9B%B4%E6%94%B9%E7%94%BB%E9%9D%A2%E8%89%B2%E8%B0%83
default : [500] default : [500]
colour : this.soundColor colour : this.soundColor
Int_0 = Int_0 ?(', "time": '+Int_0):''; Int_0 = Int_0 ?(', "time": '+Int_0):'';
@ -762,7 +754,7 @@ setWeather_s
/* setWeather_s /* setWeather_s
tooltip : setWeather更改天气 tooltip : setWeather更改天气
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=setweather%ef%bc%9a%e6%9b%b4%e6%94%b9%e5%a4%a9%e6%b0%94 helpUrl : https://ckcz123.github.io/mota-js/#/event?id=setweather%EF%BC%9A%E6%9B%B4%E6%94%B9%E5%A4%A9%E6%B0%94
default : [null,1] default : [null,1]
colour : this.soundColor colour : this.soundColor
if(Int_0<1 || Int_0>10) throw new Error('天气的强度等级, 在1-10之间'); if(Int_0<1 || Int_0>10) throw new Error('天气的强度等级, 在1-10之间');
@ -777,7 +769,7 @@ move_s
/* move_s /* move_s
tooltip : move: 让某个NPC/怪物移动,位置可不填代表当前事件 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"] default : ["","",500,null,"上右3下2左上左2"]
colour : this.eventColor colour : this.eventColor
var floorstr = ''; var floorstr = '';
@ -795,7 +787,7 @@ moveHero_s
/* moveHero_s /* moveHero_s
tooltip : moveHero移动勇士,用这种方式移动勇士的过程中将无视一切地形, 无视一切事件, 中毒状态也不会扣血 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"] default : [500,"上右3下2左上左2"]
colour : this.dataColor colour : this.dataColor
Int_0 = Int_0 ?(', "time": '+Int_0):''; Int_0 = Int_0 ?(', "time": '+Int_0):'';
@ -809,7 +801,7 @@ playBgm_s
/* playBgm_s /* playBgm_s
tooltip : playBgm: 播放背景音乐 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"] default : ["bgm.mp3"]
colour : this.soundColor colour : this.soundColor
var code = '{"type": "playBgm", "name": "'+EvalString_0+'"},\n'; var code = '{"type": "playBgm", "name": "'+EvalString_0+'"},\n';
@ -822,7 +814,7 @@ pauseBgm_s
/* pauseBgm_s /* pauseBgm_s
tooltip : pauseBgm: 暂停背景音乐 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 colour : this.soundColor
var code = '{"type": "pauseBgm"},\n'; var code = '{"type": "pauseBgm"},\n';
return code; return code;
@ -834,7 +826,7 @@ resumeBgm_s
/* resumeBgm_s /* resumeBgm_s
tooltip : resumeBgm: 恢复背景音乐 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 colour : this.soundColor
var code = '{"type": "resumeBgm"},\n'; var code = '{"type": "resumeBgm"},\n';
return code; return code;
@ -846,8 +838,8 @@ playSound_s
/* playSound_s /* playSound_s
tooltip : playSound: 播放音效 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"] default : ["item.mp3"]
colour : this.soundColor colour : this.soundColor
var code = '{"type": "playSound", "name": "'+EvalString_0+'"},\n'; var code = '{"type": "playSound", "name": "'+EvalString_0+'"},\n';
return code; return code;
@ -859,7 +851,7 @@ setVolume_s
/* setVolume_s /* setVolume_s
tooltip : setVolume: 设置音量 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] default : [90]
colour : this.soundColor colour : this.soundColor
var code = '{"type": "setVolume", "value": '+Int_0+'},\n'; var code = '{"type": "setVolume", "value": '+Int_0+'},\n';
@ -872,7 +864,7 @@ win_s
/* win_s /* win_s
tooltip : win: 获得胜利, 该事件会显示获胜页面, 并重新游戏 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 : [""] default : [""]
var code = '{"type": "win", "reason": "'+EvalString_0+'"},\n'; var code = '{"type": "win", "reason": "'+EvalString_0+'"},\n';
return code; return code;
@ -884,7 +876,7 @@ lose_s
/* lose_s /* lose_s
tooltip : lose: 游戏失败, 该事件会显示失败页面, 并重新开始游戏 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 : [""] default : [""]
var code = '{"type": "lose", "reason": "'+EvalString_0+'"},\n'; var code = '{"type": "lose", "reason": "'+EvalString_0+'"},\n';
return code; return code;
@ -896,7 +888,7 @@ input_s
/* input_s /* input_s
tooltip : input接受用户输入, 事件只能接受非负整数输入, 所有非法的输入将全部变成0 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 : ["请输入一个数"] default : ["请输入一个数"]
colour : this.dataColor colour : this.dataColor
var code = '{"type": "input", "text": "'+EvalString_0+'"},\n'; var code = '{"type": "input", "text": "'+EvalString_0+'"},\n';
@ -909,7 +901,7 @@ if_s
/* if_s /* if_s
tooltip : if: 条件判断 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 colour : this.eventColor
var code = ['{"type": "if", "condition": "',expression_0,'",\n', var code = ['{"type": "if", "condition": "',expression_0,'",\n',
'"true": [\n',action_0,'],\n', '"true": [\n',action_0,'],\n',
@ -918,6 +910,43 @@ var code = ['{"type": "if", "condition": "',expression_0,'",\n',
return code; 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 while_s
: '循环处理' '' '当' expression '时' BGNL? Newline action+ BEND Newline : '循环处理' '' '当' expression '时' BGNL? Newline action+ BEND Newline
@ -953,40 +982,16 @@ var code = '{"type": "continue"},\n';
return code; return code;
*/; */;
choices_s
: '选项' ':' EvalString? BGNL? '标题' EvalString? '图像' IdString? BGNL? Newline choicesContext+ BEND Newline
/* choices_s wait_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;
*/;
choicesContext
: '子选项' EvalString BGNL? Newline action+
/* choicesContext /* wait_s
tooltip : 选项的选择 tooltip : wait: 等待用户操作并获得按键或点击信息(具体用法看文档)
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 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
default : ["提示文字:红钥匙"] colour : this.soundColor
colour : this.subColor var code = '{"type": "wait"},\n';
var code = '{"text": "'+EvalString_0+'", "action": [\n'+action_0+']},\n';
return code; return code;
*/; */;
@ -995,8 +1000,8 @@ function_s
/* function_s /* function_s
tooltip : function: 自定义JS脚本 tooltip : 可双击多行编辑请勿使用异步代码。常见API参见文档附录。
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\"));"] default : ["alert(core.getStatus(\"atk\"));"]
colour : this.dataColor colour : this.dataColor
var code = '{"type": "function", "function": "function(){\\n'+JSON.stringify(RawEvalString_0).slice(1,-1).split('\\\\n').join('\\n')+'\\n}"},\n'; var code = '{"type": "function", "function": "function(){\\n'+JSON.stringify(RawEvalString_0).slice(1,-1).split('\\\\n').join('\\n')+'\\n}"},\n';
@ -1380,8 +1385,7 @@ ActionParser.prototype.parseAction = function() {
break; break;
case "tip": case "tip":
this.next = MotaActionBlocks['tip_s'].xmlText([ this.next = MotaActionBlocks['tip_s'].xmlText([
data.data,this.next]); data.text,this.next]);
this.parseAction();
break; break;
case "show": // 显示 case "show": // 显示
if (!(data.loc[0] instanceof Array)) if (!(data.loc[0] instanceof Array))

View File

@ -415,6 +415,12 @@ data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc =
"_bool": "bool", "_bool": "bool",
"_data": "是否允许等级提升进阶如果上面enableExperience为false则此项恒视为false" "_data": "是否允许等级提升进阶如果上面enableExperience为false则此项恒视为false"
}, },
"enableKeys": {
"_leaf": true,
"_type": "checkbox",
"_bool": "bool",
"_data": "是否在状态栏显示三色钥匙数量"
},
"enableDebuff": { "enableDebuff": {
"_leaf": true, "_leaf": true,
"_type": "checkbox", "_type": "checkbox",

View File

@ -542,6 +542,29 @@ editor.prototype.listen = function () {
currDrawData = JSON.parse(JSON.stringify(reDo)); currDrawData = JSON.parse(JSON.stringify(reDo));
reDo = null; reDo = null;
} }
// PGUP和PGDOWN切换楼层
if (e.keyCode==33) {
e.preventDefault();
var index=editor.core.floorIds.indexOf(editor.currentFloorId);
if (index>0) {
var toId = editor.core.floorIds[index-1];
editor_mode.onmode('nextChange');
editor_mode.onmode('floor');
document.getElementById('selectFloor').value = toId;
editor.changeFloor(toId);
}
}
if (e.keyCode==34) {
e.preventDefault();
var index=editor.core.floorIds.indexOf(editor.currentFloorId);
if (index<editor.core.floorIds.length-1) {
var toId = editor.core.floorIds[index+1];
editor_mode.onmode('nextChange');
editor_mode.onmode('floor');
document.getElementById('selectFloor').value = toId;
editor.changeFloor(toId);
}
}
} }
var dataSelection = document.getElementById('dataSelection'); var dataSelection = document.getElementById('dataSelection');

View File

@ -191,6 +191,26 @@ editor_blockly = function () {
"false": [] "false": []
}, },
],'afterBattle'), ],'afterBattle'),
'<label text="杀死魔龙后隐藏其余图块"></label>',
MotaActionFunctions.actionParser.parse([
{"type": "setValue", "name": "flag:y", "value": "core.status.event.data.y-2"},
{"type": "setValue", "name": "flag:x", "value": "core.status.event.data.x-1"},
{"type": "hide", "loc": ["flag:x", "flag:y"]},
{"type": "setValue", "name": "flag:x", "value": "core.status.event.data.x"},
{"type": "hide", "loc": ["flag:x", "flag:y"]},
{"type": "setValue", "name": "flag:x", "value": "core.status.event.data.x+1"},
{"type": "hide", "loc": ["flag:x", "flag:y"]},
{"type": "setValue", "name": "flag:y", "value": "core.status.event.data.y-1"},
{"type": "hide", "loc": ["flag:x", "flag:y"]},
{"type": "setValue", "name": "flag:x", "value": "core.status.event.data.x"},
{"type": "hide", "loc": ["flag:x", "flag:y"]},
{"type": "setValue", "name": "flag:x", "value": "core.status.event.data.x-1"},
{"type": "hide", "loc": ["flag:x", "flag:y"]},
{"type": "setValue", "name": "flag:y", "value": "core.status.event.data.y"},
{"type": "hide", "loc": ["flag:x", "flag:y"]},
{"type": "setValue", "name": "flag:x", "value": "core.status.event.data.x+1"},
{"type": "hide", "loc": ["flag:x", "flag:y"]},
],'afterBattle'),
'<label text="获得圣水后变成墙"></label>', '<label text="获得圣水后变成墙"></label>',
MotaActionFunctions.actionParser.parse({ MotaActionFunctions.actionParser.parse({
"trigger": "action", "trigger": "action",

View File

@ -161,11 +161,17 @@ editor_file = function (editor, callback) {
var image = info.images; var image = info.images;
if (image!='items' && image.indexOf('enemy')!=0) { if (image=='autotile') {
callback('只有怪物和道具才能自动注册!'); callback('不能对自动元件进行自动注册!');
return; return;
} }
var c=image=='items'?'I':'M'; var c=image.toUpperCase().charAt(0);
// terrains id
var terrainsId = [];
Object.keys(core.material.icons.terrains).forEach(function (id) {
terrainsId[core.material.icons.terrains[id]]=id;
})
var allIds = []; var allIds = [];
editor.ids.forEach(function (v) { editor.ids.forEach(function (v) {
@ -180,17 +186,25 @@ editor_file = function (editor, callback) {
for (var y=0; y<editor.widthsX[image][3]/per_height;y++) { for (var y=0; y<editor.widthsX[image][3]/per_height;y++) {
if (allIds[y]) continue; if (allIds[y]) continue;
while (editor.core.maps.blocksInfo[idnum]) idnum++; while (editor.core.maps.blocksInfo[idnum]) idnum++;
// get id num
var id = c+idnum; var id = c+idnum;
iconActions.push(["add", "['" + image + "']['" + id + "']", y])
if (image=='terrains' && core.isset(terrainsId[y])) {
id=terrainsId[y];
}
else {
iconActions.push(["add", "['" + image + "']['" + id + "']", y])
}
mapActions.push(["add", "['" + idnum + "']", {'cls': image, 'id': id}]) mapActions.push(["add", "['" + idnum + "']", {'cls': image, 'id': id}])
if (image=='items') if (image=='items')
templateActions.push(["add", "['items']['" + id + "']", editor_file.comment._data.items_template]); templateActions.push(["add", "['items']['" + id + "']", editor_file.comment._data.items_template]);
else else if (image.indexOf('enemy')==0)
templateActions.push(["add", "['" + id + "']", editor_file.comment._data.enemys_template]); templateActions.push(["add", "['" + id + "']", editor_file.comment._data.enemys_template]);
idnum++; idnum++;
} }
if (iconActions.length==0) { if (mapActions.length==0) {
callback("没有要注册的项!"); callback("没有要注册的项!");
return; return;
} }
@ -198,7 +212,7 @@ editor_file = function (editor, callback) {
var templist = []; var templist = [];
var tempcallback = function (err) { var tempcallback = function (err) {
templist.push(err); templist.push(err);
if (templist.length == 2) { if (templist.length == 3) {
if (templist[0] != null || templist[1] != null || templist[2] != null) if (templist[0] != null || templist[1] != null || templist[2] != null)
callback((templist[0] || '') + '\n' + (templist[1] || '') + '\n' + (templist[2] || '')); callback((templist[0] || '') + '\n' + (templist[1] || '') + '\n' + (templist[2] || ''));
//这里如果一个成功一个失败会出严重bug //这里如果一个成功一个失败会出严重bug
@ -206,12 +220,17 @@ editor_file = function (editor, callback) {
callback(null); callback(null);
} }
} }
saveSetting('icons', iconActions, tempcallback); if (iconActions.length>0)
saveSetting('icons', iconActions, tempcallback);
else tempcallback(null);
saveSetting('maps', mapActions, tempcallback); saveSetting('maps', mapActions, tempcallback);
if (image=='items') if (image=='items')
saveSetting('items', templateActions, tempcallback); saveSetting('items', templateActions, tempcallback);
else else if (image.indexOf('enemy')==0)
saveSetting('enemys', templateActions, tempcallback); saveSetting('enemys', templateActions, tempcallback);
else tempcallback(null);
} }
editor_file.changeIdAndIdnum = function (id, idnum, info, callback) { editor_file.changeIdAndIdnum = function (id, idnum, info, callback) {

View File

@ -1,32 +1,57 @@
(function () { (function () {
fs = {}; fs = {};
var postsomething = function (data, _ip, callback) {
//callback:function(err, data)
//data:字符串 var _http = function (type, url, formData, success, error, mimeType, responseType) {
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () { xhr.open(type, url, true);
switch (xhr.readyState) { if (core.isset(mimeType))
case 4 : xhr.overrideMimeType(mimeType);
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) { if (core.isset(responseType))
if (Boolean(callback)) { xhr.responseType = responseType;
if (xhr.responseText.slice(0, 6) == 'error:') { xhr.onload = function(e) {
callback(xhr.responseText, null); if (xhr.status==200) {
} else { if (core.isset(success)) {
callback(null, xhr.responseText); success(xhr.response);
} }
}
//printf(xhr.responseText)
} else {
if (Boolean(callback)) callback(xhr.status, null);
//printf('error:' + xhr.status+'<br>'+(xhr.responseText||''));
}
break;
} }
else {
if (core.isset(error))
error("HTTP "+xhr.status);
}
};
xhr.onabort = function () {
if (core.isset(error))
error("Abort");
} }
xhr.open('post', _ip); xhr.ontimeout = function() {
xhr.setRequestHeader('Content-Type', 'text/plain'); if (core.isset(error))
error("Timeout");
}
xhr.onerror = function() {
if (core.isset(error))
error("Error on Connection");
}
if (core.isset(formData))
xhr.send(formData);
else xhr.send();
}
var postsomething = function (data, _ip, callback) {
if (typeof(data) == typeof([][0]) || data == null) data = JSON.stringify({1: 2}); if (typeof(data) == typeof([][0]) || data == null) data = JSON.stringify({1: 2});
xhr.send(data);
_http("POST", _ip, data, function (data) {
if (data.slice(0, 6) == 'error:') {
callback(data, null);
}
else {
callback(null, data);
}
}, function (e) {
console.log(e);
callback(e+":请检查启动服务是否处于正常运行状态。");
}, "text/plain; charset=x-user-defined");
} }
fs.readFile = function (filename, encoding, callback) { fs.readFile = function (filename, encoding, callback) {

367
docs/_api.md Normal file
View File

@ -0,0 +1,367 @@
# 附录:API列表
?> 目前版本**v2.2.1**,上次更新时间:* {docsify-updated} *
所有系统支持的API都列在了这里。所有可能被用到的API都在前面用\*标记。
可以在chrome浏览器的控制台中`ctrl+shift+I`找到Console中直接进行调用以查看效果。
!> **`main.js`游戏入口所有其他JS文件都是被此文件加载。**
``` js
main.init // 初始化
main.loaderJs // 动态加载所有核心JS文件
main,loaderFloors // 动态加载所有楼层(剧本)
main.loadMod // 加载某一个JS文件
main.loadFloor // 加载某一个楼层
main.setMainTipsText // 加载过程提示
window.onresize // 窗口大小变化时
main.dom.body.onkeydown // 在界面上按下某按键时
main.dom.body.onkeydown // 在界面上放开某按键时
main.dom.body.onselectstart // 开始选择时
main.dom.data.onmousedown // 鼠标按下时
main.dom.data.onmousemove // 鼠标移动时
main.dom.data.onmouseup // 鼠标放开时
main.dom.data.onmousewheel // 鼠标滑轮滚动时
main.dom.data.ontouchstart // 手指在触摸屏开始触摸时
main.dom.data.ontouchmove // 手指在触摸屏上移动时
main.dom.data.ontouchend // 手指离开触摸屏时
main.statusBar.image.book.onclick // 点击状态栏中的怪物手册时
main.statusBar.image.fly.onclick // 点击状态栏中的楼层传送器时
main.statusBar.image.toolbox.onclick // 点击状态栏中的工具箱时
main.statusBar.image.shop.onclick // 点击状态栏中的快捷商店时
main.statusBar.image.save.onclick // 点击状态栏中的存档按钮时
main.statusBar.image.load.onclick // 点击状态栏中的读档按钮时
main.statusBar.image.settings.onclick // 点击状态栏中的系统菜单时
main.dom.playGame.onclick // 点击“开始游戏”时
main.dom.loadGame.onclick // 点击“载入游戏”时
main.dom.replayGame.onclick // 点击“录像回放”时
main.dom.easyLevel.onclick // 点击“简单难度”时
main.dom.normalLevel.onclick // 点击“普通难度”时
main.dom.hardLevel.onclick // 点击“困难难度”时
```
!> **`core.js`:系统核心文件。所有核心逻辑处理都在此文件完成。**
``` js
* core.status.floorId // 获得当前层floorId
* core.status.thisMap // 获得当前层的地图信息
* core.status.maps // 获得所有楼层的地图信息
* core.floors // 获得所有楼层的剧本
// ------ 初始化部分 ------
core.init // 初始化
core.showStartAnimate // 显示游戏开始界面
core.hideStartAnimate // 隐藏游戏开始界面
core.setStartProgressVal // 设置加载进度条进度
core.setStartLoadTipText // 设置加载进度条提示文字
core.loader // 加载图片和音频
core.loadAutotile // 加载Autotile
core.loadImage // 加载图片
core.loadMusic // 加载音频
core.isPlaying // 游戏是否已经开始
core.clearStatus // 清除游戏状态和数据
core.resetStatus // 重置游戏状态和初始数据
core.startGame // 开始游戏
* core.restart // 重新开始游戏;此函数将回到标题页面
// ------ 键盘、鼠标事件 ------
core.onKeyDown // 按下某个键时
core.onKeyUp // 放开某个键时
core.pressKey // 按住某个键时
core.keyDown // 根据按下键的code来执行一系列操作
core.keyUp // 根据放开键的code来执行一系列操作
core.ondown // 点击(触摸)事件按下时
core.onmove // 当在触摸屏上滑动时
core.onup // 当点击(触摸)事件放开时
core.getClickLoc // 获得点击事件相对左上角的坐标0到12之间
core.onclick // 具体点击屏幕上(x,y)点时,执行的操作
core.onmousewheel // 滑动鼠标滚轮时的操作
// ------ 自动寻路代码相关 ------
core.clearAutomaticRouteNode // 清除自动寻路路线
core.stopAutomaticRoute // 停止自动寻路操作
core.continueAutomaticRoute // 继续剩下的自动寻路操作
core.clearContinueAutomaticRoute // 清空剩下的自动寻路列表
core.setAutomaticRoute // 设置自动寻路路线
core.automaticRoute // 自动寻路算法,找寻最优路径
core.fillPosWithPoint // 显示离散的寻路点
core.clearStepPostfix // 清除已经寻路过的部分
// ------ 自动行走,行走控制 ------
core.stopAutoHeroMove // 停止勇士的自动行走
core.setAutoHeroMove // 设置勇士的自动行走路线
core.autoHeroMove // 让勇士开始自动行走
core.setHeroMoveInterval // 设置行走的效果动画
core.setHeroMoveTriggerInterval // 设置勇士行走过程中对事件的触发检测
core.moveAction // 实际每一步的行走过程
* core.turnHero(direction) // 设置勇士的方向(转向)
core.canMoveHero // 勇士能否前往某方向
core.moveHero // 让勇士开始移动
core.eventMoveHero // 使用事件让勇士移动。这个函数将不会触发任何事件。
core.moveOneStep // 每移动一格后执行的事件。中毒时在这里进行扣血判断。
core.waitHeroToStop(callback) // 停止勇士的一切行动等待勇士行动结束后再执行callback回调函数。
core.stopHero // 停止勇士的移动状态。
core.drawHero // 绘制勇士。
* core.setHeroLoc(name, value) // 设置勇士的位置。name为”direction”,”x”,”y”
* core.getHeroLoc(name) // 获得勇士的位置。
* core.nextX // 获得勇士面对位置的x坐标
* core.nextY // 获得勇士面对位置的y坐标
// ------ 地图和事件处理 ------
* core.openDoor(id, x, y, needKey, callback) // 打开一扇位于 (x,y) 的门
* core.battle(id, x, y, force, callback) // 进行战斗force表示是否强制战斗
core.afterBattle // 战斗完毕
core.trigger(x,y) // 触发x,y点的事件
* core.changeFloor(floorId, stair, heroLoc, time, callback) // 楼层切换。floorId为目标楼层Idstair可指定为上/下楼梯time动画时间
core.mapChangeAnimate // 地图切换动画效果
core.clearMap // 清除地图
core.fillText // 在某个canvas上绘制一段文字
core.fillRect // 在某个canvas上绘制一个矩形
core.strokeRect // 在某个canvas上绘制一个矩形的边框
core.drawLine // 在某个canvas上绘制一条线
core.setFont // 设置某个canvas的文字字体
core.setLineWidth // 设置某个canvas的线宽度
core.saveCanvas // 保存某个canvas状态
core.loadCanvas // 加载某个canvas状态
core.setStrokeStyle // 设置某个canvas边框属性
core.setAlpha // 设置某个canvas的alpha值
core.setOpacity // 设置某个canvas的透明度
core.setFillStyle // 设置某个canvas的绘制属性如颜色等
* core.drawMap(mapId, callback) // 绘制某张地图。mapId为地图Id绘制完毕将执行callback回调函数。
core.drawAutotile // 绘制Autotile
* core.noPassExists(x,y) // 某个点是否不可通行
core.noPass // 某个点是否在区域内且不可通行
* core.npcExists(x,y) // 某个点是否存在NPC
* core.terrainExists(x,y) // 某个点是否存在(指定的)地形
* core.stairExists(x,y) // 某个点是否存在楼梯
* core.nearStair // 当前位置是否在楼梯边
* core.enemyExists(x,y) // 某个点是否存在(指定的)怪物
* core.getBlock(x, y, floorId, needEnable) // 获得某个点的block。floorId指定目标楼层needEnable如果为false则即使该点的事件处于禁用状态也将被返回否则只有事件启用的点才被返回
core.moveBlock // 显示移动某块的动画,达到{“type”:”move”}的效果
core.animateBlock // 显示/隐藏某个块时的动画效果
core.showBlock // 将某个块从禁用变成启用状态
core.removeBlock // 将某个块从启用变成禁用状态
core.removeBlockById // 根据block的索引删除该块
core.removeBlockByIds // 一次性删除多个block
core.addGlobalAnimate // 添加一个全局动画
core.removeGlobalAnimate // 删除一个或所有全局动画
core.setGlobalAnimate // 设置全局动画的显示效果
core.syncGlobalAnimate // 同步所有的全局动画效果
core.drawBoxAnimate // 绘制UI层的box动画
core.updateCheckBlock // 更新领域、夹击、阻击的伤害地图
core.checkBlock // 检查并执行领域、夹击、阻击事件
core.snipe // 阻击事件(动画效果)
core.setFg // 更改画面色调
* core.updateFg // 更新全地图显伤
* core.itemCount // 获得某个物品的个数
* core.hasItem // 是否存在某个物品
* core.setItem // 设置某个物品的个数
* core.removeItem // 删除某个物品
* core.useItem // 使用某个物品直接调用items.js中的useItem函数。
* core.canUseItem // 能否使用某个物品。直接调用items.js中的canUseItem函数。
* core.addItem // 增加某个物品的个数
core.getNextItem // 获得面前的物品(轻按)
* core.getItem // 获得某个物品
* core.drawTip // 左上角绘制一段提示
* core.drawText // 地图中间绘制一段文字
// ------ 系统机制 ------
core.replaceText // 将文字中的${和}(表达式)进行替换
core.calValue // 计算表达式的值
core.doEffect // 执行一个表达式的effect操作
core.splitLines // 字符串自动换行的分割
core.unshift // 向某个数组前插入另一个数组或元素
core.setLocalStorage // 设置本地存储
core.getLocalStorage // 获得本地存储
core.removeLocalStorage // 移除本地存储
core.clone // 深拷贝一个对象
core.formatDate // 格式化时间为字符串
core.formatDate2 // 格式化时间为最简字符串
core.setTwoDigits // 两位数显示
core.debug // 进入Debug模式攻防血和钥匙都调成很高的数值
core.replay // 开始回放
core.checkStatus // 判断当前能否进入某个事件
core.openBook // 点击怪物手册时的打开操作
core.useFly // 点击楼层传送器时的打开操作
core.openToolbox // 点击工具栏时的打开操作
core.openQuickShop // 点击快捷商店时的打开操作
core.save // 点击保存按钮时的打开操作
core.load // 点击读取按钮时的打开操作
core.openSettings // 点击设置按钮时的打开操作
core.autosave // 自动存档
core.doSL // 实际进行存读档事件
core.syncSave // 存档同步操作
core.saveData // 存档到本地
core.loadData // 从本地读档
core.encodeRoute // 将路线压缩
core.decodeRoute // 将路线解压缩
* core.setStatus // 设置勇士属性
* core.getStatus // 获得勇士属性
core.getLvName // 获得某个等级的名称
* core.setFlag // 设置某个自定义变量或flag
* core.getFlag // 获得某个自定义变量或flag
* core.hasFlag // 是否存在某个自定义变量或flag且值为true
core.insertAction // 往当前事件列表之前插入一系列事件
* core.lockControl // 锁定状态栏,常常用于事件处理
* core.unlockControl // 解锁状态栏
* core.isset // 判断某对象是否不为undefined也不会null
core.readFile // 读取一个本地文件内容
core.download // 下载文件到本地
core.copy // 复制一段文字到剪切板
* core.playBgm // 播放背景音乐
* core.pauseBgm // 暂停背景音乐的播放
* core.resumeBgm // 恢复背景音乐的播放
* core.playSound // 播放音频
core.show // 动画显示某对象
core.hide // 动画使某对象消失
core.clearStatusBar // 清空状态栏
core.updateStatusBar // 更新状态栏
core.resize // 屏幕分辨率改变后重新自适应
core.domRenderer // 渲染DOM
// ------ core.js 结束 ------
```
!> **`data.js` 定义了一些初始化的数据信息。**
!> **`enemys.js` 定义了怪物信息。**
``` js
core.enemys.init // 初始化
* core.enemys.getEnemys // 获得一个或所有怪物数据
* core.enemys.hasSpecial // 判断是否含有某特殊属性
* core.enemys.getSpecialText // 获得所有特殊属性的名称
* core.enemys.getSpecialHint // 获得每个特殊属性的说明
* core.enemys.getDamage // 获得某个怪物的伤害
* core.enemys.getExtraDamage // 获得某个怪物的额外伤害
* core.enemys.getCritical // 临界值计算
* core.enemys.getCriticalDamage // 临界减伤计算
* core.enemys.getDefDamage // 1防减伤计算
* core.enemys.calDamage // 具体的伤害计算公式
core.enemys.getCurrentEnemys // 获得当前楼层的怪物列表
```
!> **`events.js` 定义了各个事件的处理流程。**
``` js
core.events.init // 初始化
core.events.getEvents // 获得一个或所有系统事件类型
core.events.startGame // 游戏开始事件
* core.events.setInitData // 不同难度分别设置初始属性
* core.events.win // 游戏获胜事件
* core.events.lose // 游戏失败事件
core.evens.gameOver // 游戏结束
core.events.afterChangeFloor // 转换楼层结束的事件
core.events.doEvents // 开始执行一系列自定义事件
core.events.doAction // 执行当前自定义事件列表中的下一个事件
core.events.insertAction // 往当前事件列表之前添加一个或多个事件
core.events.openShop // 打开一个全局商店
core.events.disableQuickShop // 禁用一个全局商店
* core.events.canUseQuickShop // 当前能否使用快捷商店
* core.events.checkLvUp // 检查升级事件
* core.events.useItem // 尝试使用道具
core.events.addPoint // 加点事件
core.events.afterBattle // 战斗结束后触发的事件
core.events.afterOpenDoor // 开一个门后触发的事件
core.events.passNet // 经过一个路障
core.events.changeLight // 改变亮灯(感叹号)的事件
* core.events.afterChangeLight // 改变亮灯之后,可以触发的事件
* core.events.afterUseBomb // 使用炸弹/圣锤后的事件
* core.events.beforeSaveData // 即将存档前可以执行的操作
* core.events.afterLoadData // 读档事件后,载入事件前,可以执行的操作
// ------ 点击事件和键盘事件的处理 ------
core.events.longClick // 长按
core.events.keyDownCtrl // 按下Ctrl键时快捷跳过对话
core.events.clickConfirmBox // 确认框界面时的点击操作
core.events.keyUpConfirmBox // 确认框界面时,放开某个键的操作
core.events.clickAction // 自定义事件时的点击操作
core.events.keyDownAction // 自定义事件时,按下某个键的操作
core.events.keyUpAction // 自定义事件时,放开某个键的操作
core.events.clickBook // 怪物手册界面的点击操作
core.events.keyDownBook // 怪物手册界面时,按下某个键的操作
core.events.keyUpBook // 怪物手册界面时,放开某个键的操作
core.events.clickBookDetail // 怪物手册属性显示界面时的点击操作
core.events.clickFly // 楼层传送器界面时的点击操作
core.events.keyDownFly // 楼层传送器界面时,按下某个键的操作
core.events.keyUpFly // 楼层传送器界面时,放开某个键的操作
core.events.clickViewMaps // 浏览地图界面时的点击操作
core.events.keyDownViewMaps // 浏览地图界面时,按下某个键的操作
core.events.keyUpViewMaps // 浏览地图界面时,放开某个键的操作
core.events.clickShop // 商店界面时的点击操作
core.events.keyDownShop // 商店界面时,按下某个键的操作
core.events.keyUpShop // 商店界面时,放开某个键的操作
core.events.clickQuickShop // 快捷商店界面时的点击操作
core.events.keyDownQuickShop // 快捷商店界面时,按下某个键的操作
core.events.keyUpQuickShop // 快捷商店界面时,放开某个键的操作
core.events.clickToolbox // 工具栏界面时的点击操作
core.events.clickToolboxIndex // 选择工具栏界面中某个Index后的操作
core.events.keyDownToolbox // 工具栏界面时,按下某个键的操作
core.events.keyUpToolbox // 工具栏界面时,放开某个键的操作
core.events.clickSL // 存读档界面时的点击操作
core.events.keyDownSL // 存读档界面时,按下某个键的操作
core.events.keyUpSL // 存读档界面时,放开某个键的操作
core.events.clickSwitchs // 系统设置界面时的点击操作
core.events.keyDownSwitchs // 系统设置界面时,按下某个键的操作
core.events.keyUpSwitchs // 系统设置界面时,放开某个键的操作
core.events.clickSettings // 系统菜单栏界面时的点击事件
core.events.keyDownSettings // 系统菜单栏界面时,按下某个键的操作
core.events.keyUpSettings // 系统菜单栏界面时,放开某个键的操作
core.events.clickSyncSave // 同步存档界面时的点击操作
core.events.keyDownSyncSave // 同步存档界面时,按下某个键的操作
core.events.keyUpSyncSave // 同步存档界面时,放开某个键的操作
core.events.clickKeyBoard // 虚拟键盘界面时的点击操作
core.events.clickAbout // “关于”界面时的点击操作
```
!> `icons.js` 定义了素材ID和它在图片上的索引的对应关系。
!> `items.js` 定义了每个道具的名称,以及使用效果。
``` js
core.items.init // 初始化
core.items.getItems // 获得所有道具
core.items.getItemEffect // “即捡即用类”道具的使用效果
core.items.getItemEffectTip // “即捡即用类”道具的文字提示
* core.items.useItem // 使用道具
* core.items.cauUseItem // 当前能否使用道具
```
!> `maps.js` 定义了数字-ID的对应关系。
``` js
core.maps.loadFloor // 加载某个楼层(从剧本或存档中)
core.maps.getBlock // 数字和ID的对应关系
core.maps.addEvent // 向该楼层添加剧本的自定义事件
core.maps.addChangeFloor // 向该楼层添加剧本的楼层转换事件
core.maps.initMaps // 初始化所有地图
core.maps.save // 将当前地图重新变成数字,以便于存档
core.maps.load // 将存档中的地图信息重新读取出来
core.maps.getMapArray // 将当前地图重新变成二维数组形式
```
!> `ui.js` 定义了各种界面的绘制。
``` js
core.ui.closePanel // 结束一切事件和绘制关闭UI窗口返回游戏进程
core.ui.drawTextBox // 绘制一个对话框
core.ui.drawChoices // 绘制一个选项界面
core.ui.drawConfirmBox // 绘制一个确认/取消的警告页面
core.ui.drawSwitchs // 绘制系统设置界面
core.ui.drawSettings // 绘制系统菜单栏
core.ui.drawQuickShop // 绘制快捷商店选择栏
core.ui.drawBattleAnimate // 绘制战斗动画
core.ui.drawWaiting // 绘制等待界面
core.ui.drawSyncSave // 绘制存档同步界面
core.ui.drawPagination // 绘制分页
core.ui.drawEnemyBook // 绘制怪物手册
core.ui.drawBookDetail // 绘制怪物属性的详细信息
core.ui.drawFly // 绘制楼层传送器
core.ui.drawMaps // 绘制浏览地图界面
core.ui.drawToolbox // 绘制道具栏
core.ui.drawSLPanel // 绘制存档/读档界面
core.ui.drawThumbnail // 绘制一个缩略图
core.ui.drawAbout // 绘制“关于”界面
core.ui.drawHelp // 绘制帮助界面
```

View File

@ -1,367 +1,467 @@
# 附录:API列表 # 附录: API列表
?> 目前版本**v2.2.1**,上次更新时间:* {docsify-updated} * ?> 目前版本**v2.2.1**,上次更新时间:* {docsify-updated} *
所有系统支持的API都列在了这里。所有可能被用到的API都在前面用\*标记。 **这里只列出所有可能会被造塔者用到的常用API更多的有关内容请在代码内进行查询。**
如有任何疑问,请联系小艾寻求帮助。
可以在chrome浏览器的控制台中`ctrl+shift+I`找到Console中直接进行调用以查看效果。 可以在chrome浏览器的控制台中`ctrl+shift+I`找到Console中直接进行调用以查看效果。
!> **`main.js`游戏入口所有其他JS文件都是被此文件加载。** **以下所有异步API都会加上[异步]的说明,存在此说明的请勿在事件处理的自定义脚本中使用。**
!> 最常用的新手向命令,强烈建议每个人了解
``` text
core.status.floorId
获得当前层的floorId。
core.status.maps
获得所有楼层的地图信息。
core.status.thisMap
获得当前楼层信息其等价于core.status.maps[core.status.floorId]。
core.floors
获得所有楼层的信息。例如core.floors[core.status.floorId].events可获得本楼层的所有自定义事件。
core.status.hero
获得当前勇士状态信息。例如core.status.hero.atk就是当前勇士的攻击力数值。
core.material.enemys
获得所有怪物信息。例如core.material.enemys.greenSlime就是获得绿色史莱姆的属性数据。
core.material.items
获得所有道具的信息。
core.debug()
开启调试模式。此模式下可以按Ctrl键进行穿墙并忽略一切事件。
此模式下不可回放录像和上传成绩。
core.updateStatusBar()
立刻刷新状态栏和地图显伤。
core.setStatus('atk', 1000)
将攻击力设置为1000这里把atk可以改成hp, def, mdef, money, experience等等。
本句等价于 core.status.hero.atk = 1000
core.getStatus('atk')
返回当前攻击力数值。本句等价于 core.status.hero.atk。
core.setHeroLoc('x', 5)
设置勇士位置。这句话的意思是将勇士当前位置的横坐标设置为5。
同理可以设置勇士纵坐标 core.setHeroLoc('y', 3)。
值得注意的是,这句话虽然会使勇士改变位置,但并不会使界面重新绘制;如需立刻重新绘制地图还需调用:
core.clearMap('hero'); core.drawHero();
来对界面进行更新。
core.setItem('pickaxe', 10)
将破墙镐个数设置为10个。这里可以写任何道具的ID。
core.getItem('pickaxe', 4)
另勇士获得四个破墙镐。这里可以写任何道具的ID。
core.itemCount('pickaxe')
返回当前破墙镐的个数。这里可以写任何道具的ID。
core.hasItem('pickaxe')
返回当前是否存在某个道具。等价于 core.itemCount('pickaxe')>0 。
core.setFlag('xyz', 2)
设置某个flag/变量的值为2。这里可以写任何的flag变量名。
core.getFlag('xyz', 7)
获得某个flag/变量的值;如果该变量不存在,则返回第二个参数。
比如 core.getFlag('point', 2) 则获得变量point的值如果该变量从未定义过则返回2。
core.hasFlag('xyz')
返回是否存在某个变量且不为0。等价于 core.getFlag('xyz', 0)!=0 。
core.insertAction(list, x, y, callback)
插入并执行一段自定义事件。在这里你可以写任意的自定义事件列表,有关详细写法请参见文档-事件。
x和y如果设置则覆盖"当前事件点"的坐标callback如果设置则覆盖事件执行完毕后的回调函数。
例如: core.insertAction(["楼层切换", {"type":"changeFloor", "floorId": "MT3"}])
将依次显示剧情文本,并执行一个楼层切换的自定义事件。
core.changeFloor(floorId, stair, heroLoc, time, callback) [异步]
立刻切换到指定楼层。
floorId为目标楼层IDstair为到达的目标楼梯heroLoc为到达的指定点time为动画时间callback为切换完毕后的回调。
例如:
core.changeFloor('MT2', 'upFloor', null, 600) 切换到MT2层的上楼点动画事件600ms
core.changeFloor('MT5', null, {'x': 3, 'y': 6}, 0) 无动画切换到MT5层的(3,6)位置。
core.resetMap()
重置当前楼层地图。
当我们修改某一层地图后,进游戏读档,会发现修改的内容并没有被更新上去。
这是因为H5的存档是会存下来每一个楼层的地图的读档会从档里面获得地图信息。
此时,如果我们在某一层地图执行 core.resetMap() ,则可以立刻从剧本中读取并重置当前楼层地图。
已经被修改过的内容也会相应出现。
R
录像回放的快捷键;这不是一个控制台命令,但是也把它放在这里供使用。
录像回放在修改地图或新增数据后会很有用。
localStorage
获得所有的存档数据。可以用 core.getLocalStorage('save1') 来具体获得某个存档。
``` js
main.init // 初始化
main.loaderJs // 动态加载所有核心JS文件
main,loaderFloors // 动态加载所有楼层(剧本)
main.loadMod // 加载某一个JS文件
main.loadFloor // 加载某一个楼层
main.setMainTipsText // 加载过程提示
window.onresize // 窗口大小变化时
main.dom.body.onkeydown // 在界面上按下某按键时
main.dom.body.onkeydown // 在界面上放开某按键时
main.dom.body.onselectstart // 开始选择时
main.dom.data.onmousedown // 鼠标按下时
main.dom.data.onmousemove // 鼠标移动时
main.dom.data.onmouseup // 鼠标放开时
main.dom.data.onmousewheel // 鼠标滑轮滚动时
main.dom.data.ontouchstart // 手指在触摸屏开始触摸时
main.dom.data.ontouchmove // 手指在触摸屏上移动时
main.dom.data.ontouchend // 手指离开触摸屏时
main.statusBar.image.book.onclick // 点击状态栏中的怪物手册时
main.statusBar.image.fly.onclick // 点击状态栏中的楼层传送器时
main.statusBar.image.toolbox.onclick // 点击状态栏中的工具箱时
main.statusBar.image.shop.onclick // 点击状态栏中的快捷商店时
main.statusBar.image.save.onclick // 点击状态栏中的存档按钮时
main.statusBar.image.load.onclick // 点击状态栏中的读档按钮时
main.statusBar.image.settings.onclick // 点击状态栏中的系统菜单时
main.dom.playGame.onclick // 点击“开始游戏”时
main.dom.loadGame.onclick // 点击“载入游戏”时
main.dom.replayGame.onclick // 点击“录像回放”时
main.dom.easyLevel.onclick // 点击“简单难度”时
main.dom.normalLevel.onclick // 点击“普通难度”时
main.dom.hardLevel.onclick // 点击“困难难度”时
``` ```
!> **`core.js`:系统核心文件。所有核心逻辑处理都在此文件完成。** !> 一些相对高级的命令,针对有一定脚本经验的人
``` js ``` text
* core.status.floorId // 获得当前层floorId
* core.status.thisMap // 获得当前层的地图信息
* core.status.maps // 获得所有楼层的地图信息
* core.floors // 获得所有楼层的剧本
// ------ 初始化部分 ------ ========== 可直接从core中调用的最常被使用的函数 ==========
core.init // 初始化 core.js实际上是所有API的入口路由核心API的实现在其他几个文件中core.js主要进行转发操作。
core.showStartAnimate // 显示游戏开始界面
core.hideStartAnimate // 隐藏游戏开始界面
core.setStartProgressVal // 设置加载进度条进度
core.setStartLoadTipText // 设置加载进度条提示文字
core.loader // 加载图片和音频
core.loadAutotile // 加载Autotile
core.loadImage // 加载图片
core.loadMusic // 加载音频
core.isPlaying // 游戏是否已经开始
core.clearStatus // 清除游戏状态和数据
core.resetStatus // 重置游戏状态和初始数据
core.startGame // 开始游戏
* core.restart // 重新开始游戏;此函数将回到标题页面
// ------ 键盘、鼠标事件 ------
core.onKeyDown // 按下某个键时
core.onKeyUp // 放开某个键时
core.pressKey // 按住某个键时
core.keyDown // 根据按下键的code来执行一系列操作
core.keyUp // 根据放开键的code来执行一系列操作
core.ondown // 点击(触摸)事件按下时
core.onmove // 当在触摸屏上滑动时
core.onup // 当点击(触摸)事件放开时
core.getClickLoc // 获得点击事件相对左上角的坐标0到12之间
core.onclick // 具体点击屏幕上(x,y)点时,执行的操作
core.onmousewheel // 滑动鼠标滚轮时的操作
// ------ 自动寻路代码相关 ------ core.nextX()
core.clearAutomaticRouteNode // 清除自动寻路路线 获得勇士面向的下一个位置的x坐标
core.stopAutomaticRoute // 停止自动寻路操作
core.continueAutomaticRoute // 继续剩下的自动寻路操作
core.clearContinueAutomaticRoute // 清空剩下的自动寻路列表
core.setAutomaticRoute // 设置自动寻路路线
core.automaticRoute // 自动寻路算法,找寻最优路径
core.fillPosWithPoint // 显示离散的寻路点
core.clearStepPostfix // 清除已经寻路过的部分
// ------ 自动行走,行走控制 ------ core.nextY()
core.stopAutoHeroMove // 停止勇士的自动行走 获得勇士面向的下一个位置的y坐标
core.setAutoHeroMove // 设置勇士的自动行走路线
core.autoHeroMove // 让勇士开始自动行走
core.setHeroMoveInterval // 设置行走的效果动画
core.setHeroMoveTriggerInterval // 设置勇士行走过程中对事件的触发检测
core.moveAction // 实际每一步的行走过程
* core.turnHero(direction) // 设置勇士的方向(转向)
core.canMoveHero // 勇士能否前往某方向
core.moveHero // 让勇士开始移动
core.eventMoveHero // 使用事件让勇士移动。这个函数将不会触发任何事件。
core.moveOneStep // 每移动一格后执行的事件。中毒时在这里进行扣血判断。
core.waitHeroToStop(callback) // 停止勇士的一切行动等待勇士行动结束后再执行callback回调函数。
core.stopHero // 停止勇士的移动状态。
core.drawHero // 绘制勇士。
* core.setHeroLoc(name, value) // 设置勇士的位置。name为”direction”,”x”,”y”
* core.getHeroLoc(name) // 获得勇士的位置。
* core.nextX // 获得勇士面对位置的x坐标
* core.nextY // 获得勇士面对位置的y坐标
// ------ 地图和事件处理 ------ core.openDoor(id, x, y, needKey, callback) [异步]
* core.openDoor(id, x, y, needKey, callback) // 打开一扇位于 (x,y) 的门 尝试开门操作。id为目标点的IDx和y为坐标needKey表示是否需要使用钥匙callback为开门完毕后的回调函数。
* core.battle(id, x, y, force, callback) // 进行战斗force表示是否强制战斗 例如core.openDoor('yellowDoor', 10, 3, false, function() {console.log("1")})
core.afterBattle // 战斗完毕
core.trigger(x,y) // 触发x,y点的事件
* core.changeFloor(floorId, stair, heroLoc, time, callback) // 楼层切换。floorId为目标楼层Idstair可指定为上/下楼梯time动画时间
core.mapChangeAnimate // 地图切换动画效果
core.clearMap // 清除地图
core.fillText // 在某个canvas上绘制一段文字
core.fillRect // 在某个canvas上绘制一个矩形
core.strokeRect // 在某个canvas上绘制一个矩形的边框
core.drawLine // 在某个canvas上绘制一条线
core.setFont // 设置某个canvas的文字字体
core.setLineWidth // 设置某个canvas的线宽度
core.saveCanvas // 保存某个canvas状态
core.loadCanvas // 加载某个canvas状态
core.setStrokeStyle // 设置某个canvas边框属性
core.setAlpha // 设置某个canvas的alpha值
core.setOpacity // 设置某个canvas的透明度
core.setFillStyle // 设置某个canvas的绘制属性如颜色等
* core.drawMap(mapId, callback) // 绘制某张地图。mapId为地图Id绘制完毕将执行callback回调函数。
core.drawAutotile // 绘制Autotile
* core.noPassExists(x,y) // 某个点是否不可通行
core.noPass // 某个点是否在区域内且不可通行
* core.npcExists(x,y) // 某个点是否存在NPC
* core.terrainExists(x,y) // 某个点是否存在(指定的)地形
* core.stairExists(x,y) // 某个点是否存在楼梯
* core.nearStair // 当前位置是否在楼梯边
* core.enemyExists(x,y) // 某个点是否存在(指定的)怪物
* core.getBlock(x, y, floorId, needEnable) // 获得某个点的block。floorId指定目标楼层needEnable如果为false则即使该点的事件处于禁用状态也将被返回否则只有事件启用的点才被返回
core.moveBlock // 显示移动某块的动画,达到{“type”:”move”}的效果
core.animateBlock // 显示/隐藏某个块时的动画效果
core.showBlock // 将某个块从禁用变成启用状态
core.removeBlock // 将某个块从启用变成禁用状态
core.removeBlockById // 根据block的索引删除该块
core.removeBlockByIds // 一次性删除多个block
core.addGlobalAnimate // 添加一个全局动画
core.removeGlobalAnimate // 删除一个或所有全局动画
core.setGlobalAnimate // 设置全局动画的显示效果
core.syncGlobalAnimate // 同步所有的全局动画效果
core.drawBoxAnimate // 绘制UI层的box动画
core.updateCheckBlock // 更新领域、夹击、阻击的伤害地图
core.checkBlock // 检查并执行领域、夹击、阻击事件
core.snipe // 阻击事件(动画效果)
core.setFg // 更改画面色调
* core.updateFg // 更新全地图显伤
* core.itemCount // 获得某个物品的个数
* core.hasItem // 是否存在某个物品
* core.setItem // 设置某个物品的个数
* core.removeItem // 删除某个物品
* core.useItem // 使用某个物品直接调用items.js中的useItem函数。
* core.canUseItem // 能否使用某个物品。直接调用items.js中的canUseItem函数。
* core.addItem // 增加某个物品的个数
core.getNextItem // 获得面前的物品(轻按)
* core.getItem // 获得某个物品
* core.drawTip // 左上角绘制一段提示
* core.drawText // 地图中间绘制一段文字
// ------ 系统机制 ------
core.replaceText // 将文字中的${和}(表达式)进行替换
core.calValue // 计算表达式的值
core.doEffect // 执行一个表达式的effect操作
core.splitLines // 字符串自动换行的分割
core.unshift // 向某个数组前插入另一个数组或元素
core.setLocalStorage // 设置本地存储
core.getLocalStorage // 获得本地存储
core.removeLocalStorage // 移除本地存储
core.clone // 深拷贝一个对象
core.formatDate // 格式化时间为字符串
core.formatDate2 // 格式化时间为最简字符串
core.setTwoDigits // 两位数显示
core.debug // 进入Debug模式攻防血和钥匙都调成很高的数值
core.replay // 开始回放
core.checkStatus // 判断当前能否进入某个事件
core.openBook // 点击怪物手册时的打开操作
core.useFly // 点击楼层传送器时的打开操作
core.openToolbox // 点击工具栏时的打开操作
core.openQuickShop // 点击快捷商店时的打开操作
core.save // 点击保存按钮时的打开操作
core.load // 点击读取按钮时的打开操作
core.openSettings // 点击设置按钮时的打开操作
core.autosave // 自动存档
core.doSL // 实际进行存读档事件
core.syncSave // 存档同步操作
core.saveData // 存档到本地
core.loadData // 从本地读档
core.encodeRoute // 将路线压缩
core.decodeRoute // 将路线解压缩
* core.setStatus // 设置勇士属性
* core.getStatus // 获得勇士属性
core.getLvName // 获得某个等级的名称
* core.setFlag // 设置某个自定义变量或flag
* core.getFlag // 获得某个自定义变量或flag
* core.hasFlag // 是否存在某个自定义变量或flag且值为true
core.insertAction // 往当前事件列表之前插入一系列事件
* core.lockControl // 锁定状态栏,常常用于事件处理
* core.unlockControl // 解锁状态栏
* core.isset // 判断某对象是否不为undefined也不会null
core.readFile // 读取一个本地文件内容
core.download // 下载文件到本地
core.copy // 复制一段文字到剪切板
* core.playBgm // 播放背景音乐
* core.pauseBgm // 暂停背景音乐的播放
* core.resumeBgm // 恢复背景音乐的播放
* core.playSound // 播放音频
core.show // 动画显示某对象
core.hide // 动画使某对象消失
core.clearStatusBar // 清空状态栏
core.updateStatusBar // 更新状态栏
core.resize // 屏幕分辨率改变后重新自适应
core.domRenderer // 渲染DOM
// ------ core.js 结束 ------ core.battle(id, x, y, force, callback) [异步]
``` 执行战斗事件。id为怪物的idx和y为坐标force为bool值表示是否是强制战斗callback为战斗完毕后的回调函数。
例如core.battle('greenSlime', null, null, true)
!> **`data.js` 定义了一些初始化的数据信息。**
!> **`enemys.js` 定义了怪物信息。** core.trigger(x, y)
触发某个地点的事件。
``` js
core.enemys.init // 初始化
* core.enemys.getEnemys // 获得一个或所有怪物数据 core.clearMap(mapName)
* core.enemys.hasSpecial // 判断是否含有某特殊属性 清空某个画布图层。
* core.enemys.getSpecialText // 获得所有特殊属性的名称 mapName可为'bg', 'event', 'fg', 'event2', 'hero', 'animate', 'weather', 'ui', 'data', 'all'之一。
* core.enemys.getSpecialHint // 获得每个特殊属性的说明 如果mapName为'all',则为清空所有画布;否则只清空对应的画布。
* core.enemys.getDamage // 获得某个怪物的伤害
* core.enemys.getExtraDamage // 获得某个怪物的额外伤害
* core.enemys.getCritical // 临界值计算 core.drawBlock(block)
* core.enemys.getCriticalDamage // 临界减伤计算 重绘某个图块。block应为core.status.thisMap.blocks中的一项。
* core.enemys.getDefDamage // 1防减伤计算
* core.enemys.calDamage // 具体的伤害计算公式
core.enemys.getCurrentEnemys // 获得当前楼层的怪物列表 core.drawMap(floorId, callback)
``` 重绘某一层的地图。floorId为要绘制楼层的floorIdcallback为绘制完毕后的回调函数。
!> **`events.js` 定义了各个事件的处理流程。**
core.terrainExists(x, y, id, floorId)
``` js 检测某个点是否存在(指定的)地形。
core.events.init // 初始化 x和y为坐标id为地形ID可为null表示任意地形floorId为楼层ID可忽略表示当前楼层。
core.events.getEvents // 获得一个或所有系统事件类型
core.events.startGame // 游戏开始事件
* core.events.setInitData // 不同难度分别设置初始属性 core.enemyExists(x, y, id, floorId)
* core.events.win // 游戏获胜事件 检测某个点是否存在(指定的)怪物。
* core.events.lose // 游戏失败事件 x和y为坐标id为怪物ID可为null表示任意怪物floorId为楼层ID可忽略表示当前楼层。
core.evens.gameOver // 游戏结束
core.events.afterChangeFloor // 转换楼层结束的事件
core.events.doEvents // 开始执行一系列自定义事件 core.getBlock(x, y, floorId, needEnable)
core.events.doAction // 执行当前自定义事件列表中的下一个事件 获得某个点的当前图块信息。
core.events.insertAction // 往当前事件列表之前添加一个或多个事件 x和y为坐标floorId为楼层ID可忽略或null表示当前楼层。
core.events.openShop // 打开一个全局商店 needEnable表示该点是否启用时才返回其值不设置则默认为true。
core.events.disableQuickShop // 禁用一个全局商店 如果该点不存在图块则返回null。
* core.events.canUseQuickShop // 当前能否使用快捷商店 否则,返回值如下: {"index": xxx, "block": xxx}
* core.events.checkLvUp // 检查升级事件 其中index为该点在该楼层blocks数组中的索引block为该图块实际内容。
* core.events.useItem // 尝试使用道具
core.events.addPoint // 加点事件
core.events.afterBattle // 战斗结束后触发的事件 core.getBlockId(x, y, floorId, needEnable)
core.events.afterOpenDoor // 开一个门后触发的事件 获得某个点的图块ID。
core.events.passNet // 经过一个路障 x和y为坐标floorId为楼层ID可忽略或null表示当前楼层。
core.events.changeLight // 改变亮灯(感叹号)的事件 needEnable表示是否需要该点处于启用状态才返回其值不设置则默认为true。
* core.events.afterChangeLight // 改变亮灯之后,可以触发的事件 如果该点不存在图块则返回null否则返回该点的图块ID。
* core.events.afterUseBomb // 使用炸弹/圣锤后的事件
* core.events.beforeSaveData // 即将存档前可以执行的操作
* core.events.afterLoadData // 读档事件后,载入事件前,可以执行的操作 core.showBlock(x, y, floorId)
将某个点从禁用变成启用状态
// ------ 点击事件和键盘事件的处理 ------
core.events.longClick // 长按
core.events.keyDownCtrl // 按下Ctrl键时快捷跳过对话 core.removeBlock(x, y, floorId)
core.events.clickConfirmBox // 确认框界面时的点击操作 将某个点删除或从禁用变成启用状态。
core.events.keyUpConfirmBox // 确认框界面时,放开某个键的操作 如果该点不存在自定义事件(比如普通的怪物),则将直接从地图中删除。
core.events.clickAction // 自定义事件时的点击操作 否则将该点设置为禁用,以供以后可能的启用事件。
core.events.keyDownAction // 自定义事件时,按下某个键的操作
core.events.keyUpAction // 自定义事件时,放开某个键的操作
core.events.clickBook // 怪物手册界面的点击操作 core.useItem(itemId, callback)
core.events.keyDownBook // 怪物手册界面时,按下某个键的操作 尝试使用某个道具。itemId为道具IDcallback为成功或失败后的回调。
core.events.keyUpBook // 怪物手册界面时,放开某个键的操作
core.events.clickBookDetail // 怪物手册属性显示界面时的点击操作
core.events.clickFly // 楼层传送器界面时的点击操作 core.canUseItem(itemId)
core.events.keyDownFly // 楼层传送器界面时,按下某个键的操作 返回当前能否使用某个道具。
core.events.keyUpFly // 楼层传送器界面时,放开某个键的操作
core.events.clickViewMaps // 浏览地图界面时的点击操作
core.events.keyDownViewMaps // 浏览地图界面时,按下某个键的操作 core.getNextItem()
core.events.keyUpViewMaps // 浏览地图界面时,放开某个键的操作 轻按。
core.events.clickShop // 商店界面时的点击操作
core.events.keyDownShop // 商店界面时,按下某个键的操作
core.events.keyUpShop // 商店界面时,放开某个键的操作 core.drawTip(text, itemIcon)
core.events.clickQuickShop // 快捷商店界面时的点击操作 在左上角绘制一段提示信息2秒后消失。itemIcon为道具图标的索引。
core.events.keyDownQuickShop // 快捷商店界面时,按下某个键的操作
core.events.keyUpQuickShop // 快捷商店界面时,放开某个键的操作
core.events.clickToolbox // 工具栏界面时的点击操作 core.drawText(contents, callback) [异步]
core.events.clickToolboxIndex // 选择工具栏界面中某个Index后的操作 绘制一段文字。
core.events.keyDownToolbox // 工具栏界面时,按下某个键的操作 不推荐使用此函数尽量使用core.insertAction(contents)来显示剧情文本。
core.events.keyUpToolbox // 工具栏界面时,放开某个键的操作
core.events.clickSL // 存读档界面时的点击操作
core.events.keyDownSL // 存读档界面时,按下某个键的操作 core.closePanel()
core.events.keyUpSL // 存读档界面时,放开某个键的操作 结束一切事件和绘制关闭UI窗口返回游戏进程。
core.events.clickSwitchs // 系统设置界面时的点击操作
core.events.keyDownSwitchs // 系统设置界面时,按下某个键的操作
core.events.keyUpSwitchs // 系统设置界面时,放开某个键的操作 core.replaceText(text)
core.events.clickSettings // 系统菜单栏界面时的点击事件 将一段文字中的${}进行计算并替换。
core.events.keyDownSettings // 系统菜单栏界面时,按下某个键的操作
core.events.keyUpSettings // 系统菜单栏界面时,放开某个键的操作
core.events.clickSyncSave // 同步存档界面时的点击操作 core.calValue(value)
core.events.keyDownSyncSave // 同步存档界面时,按下某个键的操作 计算表达式的实际值。这个函数可以传入status:atk等这样的参数。
core.events.keyUpSyncSave // 同步存档界面时,放开某个键的操作
core.events.clickKeyBoard // 虚拟键盘界面时的点击操作
core.events.clickAbout // “关于”界面时的点击操作 core.getLocalStorage(key, defaultValue)
``` 从localStorage中获得某个数据已被parse如果对应的key不存在则返回defaultValue。
!> `icons.js` 定义了素材ID和它在图片上的索引的对应关系。
core.clone(data)
!> `items.js` 定义了每个道具的名称,以及使用效果。 深拷贝某个对象。
``` js
core.items.init // 初始化 core.isset(x)
core.items.getItems // 获得所有道具 测试x是否不为null不为undefined也不为NaN。
core.items.getItemEffect // “即捡即用类”道具的使用效果
core.items.getItemEffectTip // “即捡即用类”道具的文字提示
* core.items.useItem // 使用道具 core.rand(num)
* core.items.cauUseItem // 当前能否使用道具 使用伪种子生成伪随机数。该随机函数能被录像支持。
``` num如果设置大于0则生成一个[0, num-1]之间的数否则生成一个0到1之间的浮点数。
此函数为伪随机算法SL大法无效。即多次SL后调用的该函数返回的值都是相同的。
!> `maps.js` 定义了数字-ID的对应关系。
``` js core.rand2(num)
core.maps.loadFloor // 加载某个楼层(从剧本或存档中) 使用系统的随机数算法得到的随机数。该随机函数能被录像支持。
core.maps.getBlock // 数字和ID的对应关系 num如果设置大于0则生成一个[0, num-1]之间的数否则生成一个0到2147483647之间的整数。
core.maps.addEvent // 向该楼层添加剧本的自定义事件 此函数使用了系统的Math.random()函数支持SL大法。
core.maps.addChangeFloor // 向该楼层添加剧本的楼层转换事件 但是,此函数会将生成的随机数值存入录像,因此如果调用次数太多则会导致录像文件过大。
core.maps.initMaps // 初始化所有地图
core.maps.save // 将当前地图重新变成数字,以便于存档
core.maps.load // 将存档中的地图信息重新读取出来 core.restart() [异步]
core.maps.getMapArray // 将当前地图重新变成二维数组形式 返回标题界面。
```
!> `ui.js` 定义了各种界面的绘制。 core.updateFg()
更新全地图显伤。包括怪物显伤、临界显示和领域显伤等。
``` js
core.ui.closePanel // 结束一切事件和绘制关闭UI窗口返回游戏进程
core.ui.drawTextBox // 绘制一个对话框 ========== core.actions.XXX 和游戏控制相关的函数 ==========
core.ui.drawChoices // 绘制一个选项界面 actions.js主要用来进行用户交互行为的处理。
core.ui.drawConfirmBox // 绘制一个确认/取消的警告页面 所有用户行为,比如按键、点击、滑动等等,都会被此文件接收并进行操作。
core.ui.drawSwitchs // 绘制系统设置界面
core.ui.drawSettings // 绘制系统菜单栏
core.ui.drawQuickShop // 绘制快捷商店选择栏 ========== core.control.XXX 和游戏控制相关的函数 ==========
core.ui.drawBattleAnimate // 绘制战斗动画 control.js主要用来进行游戏控制比如行走控制、自动寻路、存读档等等游戏核心内容。
core.ui.drawWaiting // 绘制等待界面
core.ui.drawSyncSave // 绘制存档同步界面
core.ui.drawPagination // 绘制分页 ========== core.enemys.XXX 和怪物相关的函数 ==========
core.ui.drawEnemyBook // 绘制怪物手册 enemys.js主要用来进行怪物相关的内容比如怪物的特殊属性伤害和临界计算等。
core.ui.drawBookDetail // 绘制怪物属性的详细信息
core.ui.drawFly // 绘制楼层传送器
core.ui.drawMaps // 绘制浏览地图界面 core.enemys.hasSpecial(special, test)
core.ui.drawToolbox // 绘制道具栏 测试怪物是否含有某个特殊属性。
core.ui.drawSLPanel // 绘制存档/读档界面 常见用法: core.enemys.hasSpecial(monster.special, 3) ## 测试是否拥有坚固
core.ui.drawThumbnail // 绘制一个缩略图
core.ui.drawAbout // 绘制“关于”界面
core.ui.drawHelp // 绘制帮助界面 core.enemys.getSpecialText(enemyId)
返回一个列表包含该怪物ID对应的所有特殊属性。
core.enemys.getSpecialHint(enemy, special)
获得怪物某个(或全部)特殊属性的文字说明。
core.enemys.canBattle(enemyId)
返回当前能否战胜某个怪物。
core.enemys.getDamage(enemyId)
返回当前对某个怪物的战斗伤害。如果无法战斗返回null。
core.enemys.getExtraDamage(enemyId)
返回某个怪物会对勇士造成的额外伤害(不可被魔防抵消),例如仇恨、固伤等等。
core.enemys.nextCriticals(enemyId, number)
返回一个列表为接下来number可忽略默认为1个该怪物的临界值和临界减伤。
列表每一项类似 [x,y] 表示临界值为x且临界减伤为y。
如果无临界值,则返回空列表。
core.enemys.getDefDamage(enemyId, k)
获得k可忽略默认为1防减伤值。
core.enemys.getDamageInfo(enemy, hero_hp, hero_atk, hero_def, hero_mdef)
获得实际战斗信息,比如伤害,回合数,每回合伤害等等。
此函数是实际战斗过程的计算。
core.enemys.calDamage(enemy, hero_hp, hero_atk, hero_def, hero_mdef)
计算战斗伤害实际返回的是上面getDamageInfo中伤害的数值。
core.enemys.getCurrentEnemys(floorId)
获得某一层楼剩余所有怪物的信息(供怪物手册使用)
========== core.events.XXX 和事件相关的函数 ==========
events.js主要用来进行事件处理比如自定义事件以及某些条件下可能会被触发的事件。
大多数事件API都在脚本编辑中存在这里只列出部分比较重要的脚本编辑中不存在的API。
core.events.gameOver(ending, fromReplay)
游戏结束并上传的事件。
该函数将提问是否上传和是否下载录像,并返回标题界面。
core.events.doEvents(list, x, y, callback) [异步]
开始执行某个事件。
请不要执行此函数,尽量使用 core.insertAction(list, x, y, callback) 来开始执行一段事件。
core.events.doAction()
执行下一个事件。此函数中将对所有自定义事件类型分别处理。
core.events.openShop(shopId, needVisited) [异步]
打开一个全局商店。needVisited表示是否需要该商店已被打开过。
core.events.disableQuickShop(shopId)
禁用一个全局商店
core.events.canUseQuickShop(shopId)
当前能否使用某个快捷商店
core.events.setHeroIcon(name)
设置勇士行走图
========== core.items.XXX 和道具相关的函数 ==========
items.js将处理和道具相关的内容比如道具的使用获取和删除等等。
========== core.loader.XXX 和游戏加载相关的函数 ==========
loader.js将主要用来进行资源的加载比如加载音乐、图片、动画等等。
========== core.maps.XXX 和地图处理相关的函数 ==========
maps.js主要用来进行地图相关的的操作。包括绘制地图获取地图上的点等等。
core.maps.canMoveHero(x,y,direction,floorId)
判断能否前往某个方向。x,y为坐标可忽略为当前点direction为方向可忽略为当前方向。
floorId为楼层ID可忽略为当前楼层。
core.maps.canMoveDirectly(destX, destY)
判断当前能否瞬间移动到某个点。
core.maps.removeBlockById(index, floorId)
根据索引删除或禁用某块。
core.maps.removeBlockByIds(floorId, ids)
根据索引删除或禁用若干块。
========== core.ui.XXX 和对话框绘制相关的函数 ==========
ui.js主要用来进行UI窗口的绘制比如对话框、怪物手册、楼传器、存读档界面等等。
core.ui.drawThumbnail(floorId, canvas, blocks, x, y, size, heroLoc, heroIcon)
绘制一个缩略图,比如楼传器界面,存读档界面等情况。
floorId为目标楼层IDcanvas为要绘制到的图层blocks为要绘制的所有图块。
x,y为该图层开始绘制的起始点坐标size为每一格的像素heroLoc为勇士坐标heroIcon为勇士图标。
========== core.utils.XXX 工具类的辅助函数 ==========
utils.js主要用来进行一些辅助函数的计算。
core.utils.splitLines(canvas, text, maxLength, font)
自动切分长文本的换行。
canvas为图层text为要自动换行的内容maxLength为每行最长像素font为文本的字体。
core.utils.cropImage(image, size)
纵向对图片进行切分(裁剪)。
core.utils.unshift(a, b)
向某个数组前插入另一个数组或元素
core.utils.formatBigNumber(x)
大数据的格式化
core.utils.arrayToRGB(color)
将形如[255,0,0]之类的数组转成#FF0000这样的RGB形式。
core.utils.encodeRoute(list)
压缩加密路线。可以使用core.encodeRoute(core.status.route)来压缩当前路线。
core.utils.decodeRoute(route)
解压缩(解密)路线。
core.utils.readFile(success, error, readType) [异步]
尝试请求读取一个本地文件内容。
success和error为成功/失败后的回调readType不设置则以文本读取否则以DataUrl形式读取。
core.utils.readFileContent(content) [异步]
文件读取完毕后的内容处理。
core.utils.download(filename, content)
尝试生成并下载一个文件。
core.utils.copy(data)
尝试复制一段文本到剪切板。
core.utils.http(type, url, formData, success, error) [异步]
发送一个异步HTTP请求。
type为'GET'或者'POST'url为目标地址formData如果是POST请求则为表单数据。
success为成功后的回调error为失败后的回调。
``` ```

View File

@ -36,7 +36,8 @@
## 怪物 ## 怪物
本塔支持的怪物列表参见`enemys.js`。其与images目录下的`enemys.png`素材按顺序一一对应。如不知道怪物素材长啥样的请打开`enemys.png`对比查看。 本塔支持的怪物列表参见`project/enemys.js`。其与images目录下的`enemys.png`素材按顺序一一对应。
如有自己的怪物素材需求请参见[自定义素材](personalization#自定义素材)的内容。 如有自己的怪物素材需求请参见[自定义素材](personalization#自定义素材)的内容。
怪物可以有特殊属性,每个怪物可以有多个自定义属性。 怪物可以有特殊属性,每个怪物可以有多个自定义属性。
@ -89,27 +90,23 @@ enemys.prototype.getSpecialText = function (enemyId) {
下面的`getSpecialHint`函数则给定了每个特殊属性的详细描述。这个描述将在怪物手册中看到。 下面的`getSpecialHint`函数则给定了每个特殊属性的详细描述。这个描述将在怪物手册中看到。
**打败怪物后可以进行加点操作。有关加点塔的制作可参见[加点事件](event#加点事件)。** 打败怪物后可以进行加点操作。有关加点塔的制作可参见[加点事件](event#加点事件)。
如果`data.js`中的enableExperience为false即不启用经验的话怪物手册里将不显示怪物的经验值打败怪物也不获得任何经验。 如果`data.js`中的enableExperience为false即不启用经验的话怪物手册里将不显示怪物的经验值打败怪物也不获得任何经验。
拿到幸运金币后,打怪获得的金币将翻倍。 拿到幸运金币后,打怪获得的金币将翻倍。
如果怪物有`"notBomb": true`,则该系列诖怪物均不可被炸。
N连击怪物的special是6且我们可以为它定义n代表实际连击数。参见样板中剑王的写法。 N连击怪物的special是6且我们可以为它定义n代表实际连击数。参见样板中剑王的写法。
![N连击](./img/nattack.png) 吸血怪需要给怪物设置value代表吸血的比例。
吸血怪需要在怪物后添加value代表吸血的比例。
可以给吸血怪添加`'add': true`来将吸血的数值加到自身上。 可以给吸血怪添加`'add': true`来将吸血的数值加到自身上。
![怪物吸血](./img/blood.png)
中毒怪让勇士中毒后,每步扣减的生命值由`data.js`中的values定义。 中毒怪让勇士中毒后,每步扣减的生命值由`data.js`中的values定义。
衰弱怪让勇士衰弱后,攻防会暂时下降一定的数值(直到衰弱状态解除恢复);这个下降的数值同在`data.js`中的values定义。 衰弱怪让勇士衰弱后,攻防会下降一定比例或固定数值(直到衰弱状态解除恢复);其在`data.js`中的values定义。
![debuff](./img/debuff.png)
诅咒怪将让勇士陷入诅咒状态,诅咒状态下杀怪不获得金币和经验值。 诅咒怪将让勇士陷入诅咒状态,诅咒状态下杀怪不获得金币和经验值。
@ -117,21 +114,17 @@ N连击怪物的special是6且我们可以为它定义n代表实际连击数
领域是十字伤害还是九宫格伤害由`zoneSquare`设定如设置为true则为九宫格伤害不指定或为false则为十字伤害。 领域是十字伤害还是九宫格伤害由`zoneSquare`设定如设置为true则为九宫格伤害不指定或为false则为十字伤害。
`range`选项可选,代表该领域怪的范围不写则默认为1。 领域怪还可以设置`range`选项代表该领域怪的范围不写则默认为1。
![怪物领域](./img/zone.png) 阻击怪同样需要设置value代表领域伤害的数值。如果勇士生命值扣减到0则直接死亡触发lose事件。
阻击怪同样需要在怪物后添加value代表领域伤害的数值。如果勇士生命值扣减到0则直接死亡触发lose事件。
!> 阻击怪后退的地点不能有任何事件存在,即使是已经被禁用的自定义事件! !> 阻击怪后退的地点不能有任何事件存在,即使是已经被禁用的自定义事件!
请注意如果吸血、领域、阻击中任何两个同时存在则value会冲突。**因此请勿将吸血、领域或阻击放置在同一个怪物身上。** 请注意如果吸血、领域、阻击中任何两个同时存在则value会冲突。**因此请勿将吸血、领域或阻击放置在同一个怪物身上。**
退化怪需要在后面增加'atkValue'和'defValue'表示退化的数值。 退化怪需要设置'atkValue'和'defValue'表示退化的数值也可以不设置默认为0
![怪物退化](./img/tuihua.png) 固伤怪则需要设置`damage`选项,代表战前扣血数值。
固伤怪则需要在后面增加`damage`选项,代表战前扣血数值。
如有额外需求,可参见[自定义怪物属性](personalization#自定义自定义怪物属性),里面讲了如何设置一个新的怪物属性。 如有额外需求,可参见[自定义怪物属性](personalization#自定义自定义怪物属性),里面讲了如何设置一个新的怪物属性。
@ -197,16 +190,16 @@ floorId指定的是目标楼层的唯一标识符ID
本塔支持BGM和SE的播放。 本塔支持BGM和SE的播放。
要播放音乐和音效你需要将对应的文件放在sounds目录下然后在main.js中进行定义 要播放音乐和音效你需要将对应的文件放在sounds目录下然后在全塔属性中进行定义
``` js ``` js
"bgms": [ // 在此存放所有的bgm和文件名一致。第一项为默认播放项 "bgms": [ // 在此存放所有的bgm和文件名一致。第一项为默认播放项
// 音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好 // 音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好
'bgm.mp3', 'qianjin.mid', 'star.mid', 'bgm.mp3'
]; ];
"sounds": [ // 在此存放所有的SE和文件名一致 "sounds": [ // 在此存放所有的SE和文件名一致
// 音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好 // 音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好
'floor.mp3', 'attack.ogg', 'door.ogg', 'item.ogg', 'zone.ogg' 'floor.mp3', 'attack.mp3', 'door.mp3', 'item.mp3', 'zone.mp3'
] ]
``` ```

View File

@ -26,7 +26,7 @@
它能通过拖动、复制粘贴等方式帮助你快速生成事件列表,而不用手动打大量字符。 它能通过拖动、复制粘贴等方式帮助你快速生成事件列表,而不用手动打大量字符。
但是,仍然强烈建议要对每个事件的写法进行了解。 但是,仍然强烈建议要对每个事件的写法进行了解,因为在脚本编辑,`insertAction`等地方需要插入自定义事件时,还是很有必要的
## 自定义事件 ## 自定义事件
@ -252,18 +252,19 @@
``` js ``` js
"x,y": [ // 实际执行的事件列表 "x,y": [ // 实际执行的事件列表
"你当前的攻击力是${status:atk}, 防御是${status:def}", "你当前的攻击力是${status:atk}, 防御是${status:def},坐标是(${status:x},${status:y})",
"你的攻防和的十倍是${10*(status:atk+status:def)}", "你的攻防和的十倍是${10*(status:atk+status:def)}",
"你的红黄蓝钥匙总数为${item:yellowKey+item:blueKey+item:redKey}", "你的红黄蓝钥匙总数为${item:yellowKey+item:blueKey+item:redKey}",
"你访问某个老人的次数为${flag:man_times}", "你访问某个老人的次数为${flag:man_times}",
] ]
``` ```
- `status:xxx` 获取勇士属性时只能使用如下几个hp生命值atk攻击力def防御力mdef魔防值money金币experience经验 - `status:xxx` 获取勇士属性时只能使用如下几个hp生命值atk攻击力def防御力mdef魔防值money金币experience经验x勇士的横坐标y勇士的纵坐标direction勇士的方向
- `item:xxx` 中的xxx为道具ID。所有道具的ID定义在items.js中请自行查看。例如`item:centerFly` 代表中心对称飞行器的个数。 - `item:xxx` 中的xxx为道具ID。所有道具的ID定义在items.js中请自行查看。例如`item:centerFly` 代表中心对称飞行器的个数。
- `flag:xxx` 中的xxx为一个自定义的变量/Flag如果没有对其进行赋值则默认值为false。 - `flag:xxx` 中的xxx为一个自定义的变量/Flag如果没有对其进行赋值则默认值为false。
另外,有个小`trick`。是否想立刻知道显示效果? 另外,有个小`trick`。是否想立刻知道显示效果?
你可以用Chrome浏览器打开游戏按Ctrl+Shift+I打开开发者工具找到Console控制台并中输入`core.drawText("...")` 即可立刻看到文字显示的效果。适当调整文字,使得显示效果满意后,再复制粘贴到你的剧情文本中。 你可以用Chrome浏览器打开游戏按Ctrl+Shift+I打开开发者工具找到Console控制台并中输入`core.drawText("...")` 即可立刻看到文字显示的效果。适当调整文字,使得显示效果满意后,再复制粘贴到你的剧情文本中。
![调试](./img/eventdebug.png) ![调试](./img/eventdebug.png)
@ -322,7 +323,7 @@ time为可选项表示文字添加的速度。若此项设置为0将直接全
] ]
``` ```
值得注意的是提示的text内容是可以使用`${ }`来计算表达式的值的。 值得注意的是提示的text内容是可以使用`${ }`来计算表达式的值的。
### setValue设置勇士的某个属性、道具个数或某个变量/Flag的值 ### setValue设置勇士的某个属性、道具个数或某个变量/Flag的值
@ -356,7 +357,7 @@ value是一个表达式将通过这个表达式计算出的结果赋值给nam
另外注意一点的是如果hp被设置成了0或以下将触发lose事件直接死亡。 另外注意一点的是如果hp被设置成了0或以下将触发lose事件直接死亡。
### show: 将一个禁用事件启用 ### show将一个禁用事件启用
我们上面提到了所有事件都必须靠其他事件驱动来完成不存在当某个flag为true时自动执行的说法。那么我们自然要有启用事件的写法。 我们上面提到了所有事件都必须靠其他事件驱动来完成不存在当某个flag为true时自动执行的说法。那么我们自然要有启用事件的写法。
@ -381,7 +382,7 @@ time为动画效果时间如果指定了某个大于0的数则会以动画
!> **要注意的是调用show事件后只是让该事件从禁用状态变成启用从不可见不可交互变成可见可交互但本身不会去执行该点的事件。** !> **要注意的是调用show事件后只是让该事件从禁用状态变成启用从不可见不可交互变成可见可交互但本身不会去执行该点的事件。**
### hide: 将一个启用事件禁用 ### hide将一个启用事件禁用
`{"type":"hide"}`和show刚好相反它会让一个已经启用的事件被禁用。 `{"type":"hide"}`和show刚好相反它会让一个已经启用的事件被禁用。
@ -407,7 +408,7 @@ NPC对话事件结束后如果需要NPC消失也需要调用 `{"type": "hide"}`
] ]
``` ```
### trigger: 立即触发另一个地点的事件 ### trigger立即触发另一个地点的事件
`{"type":"trigger"}` 会立刻触发当层另一个地点的自定义事件。 `{"type":"trigger"}` 会立刻触发当层另一个地点的自定义事件。
@ -428,7 +429,7 @@ NPC对话事件结束后如果需要NPC消失也需要调用 `{"type": "hide"}`
例如上面这个例子,下面的文字将不会再被显示,而是直接跳转到`"3,6"`对应的事件列表从头执行。 例如上面这个例子,下面的文字将不会再被显示,而是直接跳转到`"3,6"`对应的事件列表从头执行。
### revisit: 立即重启当前事件 ### revisit立即重启当前事件
revisit和trigger完全相同只不过是立刻触发的还是本地点的事件 revisit和trigger完全相同只不过是立刻触发的还是本地点的事件
@ -443,7 +444,7 @@ revisit其实是trigger的简写只不过是loc固定为当前点。
revisit常常使用在一些商人之类的地方当用户购买物品后不是离开而是立刻重新访问重新进入购买页面。 revisit常常使用在一些商人之类的地方当用户购买物品后不是离开而是立刻重新访问重新进入购买页面。
### exit: 立刻结束当前事件 ### exit立刻结束当前事件
上面说到像商人一类购买物品后可以立刻revisit重新访问但是这样就相当于陷入了死循环导致无法离开。 上面说到像商人一类购买物品后可以立刻revisit重新访问但是这样就相当于陷入了死循环导致无法离开。
@ -504,11 +505,11 @@ name是可选的代表目标行走图的文件名。
如果你需要同时修改勇士的名称,可以使用`setValue`事件来修改`status:name`但请注意value必须加单引号不然会报错。 如果你需要同时修改勇士的名称,可以使用`setValue`事件来修改`status:name`但请注意value必须加单引号不然会报错。
### update: 立刻更新状态栏和地图显伤 ### update立刻更新状态栏和地图显伤
如果你需要刷新状态栏和地图显伤,只需要简单地调用 `{"type": "update"}` 即可。 如果你需要刷新状态栏和地图显伤,只需要简单地调用 `{"type": "update"}` 即可。
### sleep: 等待多少毫秒 ### sleep等待多少毫秒
等价于RMXP中的"等待x帧",不过是以毫秒来计算。 等价于RMXP中的"等待x帧",不过是以毫秒来计算。
@ -521,11 +522,7 @@ name是可选的代表目标行走图的文件名。
] ]
``` ```
### wait等待用户操作 ### battle强制战斗
使用 `{"type": "wait"}` 可以等待用户进行操作(如点击、回车等)。
### battle: 强制战斗
调用battle可强制与某怪物进行战斗而无需去触碰到它 调用battle可强制与某怪物进行战斗而无需去触碰到它
@ -556,7 +553,7 @@ name是可选的代表目标行走图的文件名。
强制战斗没有指定loc的选项因此战斗后需要调用hide使怪物消失如果有必要 强制战斗没有指定loc的选项因此战斗后需要调用hide使怪物消失如果有必要
### openDoor: 开门 ### openDoor开门
调用`{"type":"openDoor"}`可以打开一扇门。 调用`{"type":"openDoor"}`可以打开一扇门。
@ -573,7 +570,7 @@ loc指定门的坐标floorId指定门所在的楼层ID。如果是当前层
如果loc所在的点既不是门也不是墙壁则忽略本事件。 如果loc所在的点既不是门也不是墙壁则忽略本事件。
### changeFloor: 楼层切换 ### changeFloor楼层切换
在事件中也可以对楼层进行切换。一个比较典型的例子就是TSW中勇士在三楼的陷阱被扔到了二楼就是一个楼层切换事件。 在事件中也可以对楼层进行切换。一个比较典型的例子就是TSW中勇士在三楼的陷阱被扔到了二楼就是一个楼层切换事件。
@ -598,7 +595,7 @@ time为可选的指定的话将作为楼层切换动画的时间。
!> **changeFloor到达一个新的楼层将不会执行firstArrive事件如有需求请在到达点设置自定义事件然后使用type: trigger立刻调用之。** !> **changeFloor到达一个新的楼层将不会执行firstArrive事件如有需求请在到达点设置自定义事件然后使用type: trigger立刻调用之。**
### changePos: 当前位置切换/勇士转向 ### changePos当前位置切换/勇士转向
有时候我们不想要楼层切换的动画效果而是直接让勇士从A点到B点。 有时候我们不想要楼层切换的动画效果而是直接让勇士从A点到B点。
@ -612,11 +609,11 @@ time为可选的指定的话将作为楼层切换动画的时间。
] ]
``` ```
### openShop: 打开一个全局商店 ### openShop打开一个全局商店
使用openShop可以打开一个全局商店。有关全局商店的说明可参见[全局商店](#全局商店)。 使用openShop可以打开一个全局商店。有关全局商店的说明可参见[全局商店](#全局商店)。
### disableShop: 禁用一个全局商店 ### disableShop禁用一个全局商店
使用disableShop可以永久禁用全局商店直到再次被openShop打开为止。有关全局商店的说明可参见[全局商店](#全局商店)。 使用disableShop可以永久禁用全局商店直到再次被openShop打开为止。有关全局商店的说明可参见[全局商店](#全局商店)。
@ -726,7 +723,7 @@ time为总移动的时间。
!> 移动图片只是会在顶层绘制“移动”效果动画结束即消失并不会实际对图片的显示造成影响。请与showImage事件合用。 !> 移动图片只是会在顶层绘制“移动”效果动画结束即消失并不会实际对图片的显示造成影响。请与showImage事件合用。
### setFg: 更改画面色调 ### setFg更改画面色调
我们可以使用 `{"type": "setFg"}` 来更改画面色调。 我们可以使用 `{"type": "setFg"}` 来更改画面色调。
@ -766,7 +763,7 @@ level为天气的强度等级在1-10之间。1级为最弱10级为最强
!> 使用setWeather更改的天气在切换地图后会被目标地图的默认天气覆盖。 !> 使用setWeather更改的天气在切换地图后会被目标地图的默认天气覆盖。
### move: 让某个NPC/怪物移动 ### move让某个NPC/怪物移动
如果我们需要移动某个NPC或怪物可以使用`{"type": "move"}`。 如果我们需要移动某个NPC或怪物可以使用`{"type": "move"}`。
@ -836,7 +833,7 @@ move完毕后移动的NPC/怪物一定会消失只不过可以通过immediate
不过值得注意的是,用这种方式移动勇士的过程中将无视一切地形,无视一切事件,中毒状态也不会扣血。 不过值得注意的是,用这种方式移动勇士的过程中将无视一切地形,无视一切事件,中毒状态也不会扣血。
### playBgm: 播放背景音乐 ### playBgm播放背景音乐
使用playBgm可以播放一个背景音乐。 使用playBgm可以播放一个背景音乐。
@ -848,19 +845,19 @@ move完毕后移动的NPC/怪物一定会消失只不过可以通过immediate
有关BGM播放的详细说明参见[背景音乐](element#背景音乐) 有关BGM播放的详细说明参见[背景音乐](element#背景音乐)
### pauseBgm: 暂停背景音乐 ### pauseBgm暂停背景音乐
使用`{"type": "pauseBgm"}`可以暂停背景音乐的播放。 使用`{"type": "pauseBgm"}`可以暂停背景音乐的播放。
### resumeBgm: 恢复背景音乐 ### resumeBgm恢复背景音乐
使用`{"type": "resumeBgm"}`可以恢复背景音乐的播放。 使用`{"type": "resumeBgm"}`可以恢复背景音乐的播放。
### playSound: 播放音效 ### playSound播放音效
使用playSound可以立刻播放一个音效。 使用playSound可以立刻播放一个音效。
使用方法:`{"type": "playSound", "name": "item.ogg"}` 使用方法:`{"type": "playSound", "name": "item.mp3"}`
值得注意的是如果是额外添加进文件的音效则需在main.js中this.sounds里加载它。 值得注意的是如果是额外添加进文件的音效则需在main.js中this.sounds里加载它。
@ -872,7 +869,7 @@ move完毕后移动的NPC/怪物一定会消失只不过可以通过immediate
value为音量大小在0到100之间默认为100。设置后BGM和SE都将使用该音量进行播放。 value为音量大小在0到100之间默认为100。设置后BGM和SE都将使用该音量进行播放。
### win: 获得胜利 ### win获得胜利
`{"type": "win", "reason": "xxx"}` 将会直接调用events.js中的win函数并将reason作为结局传入。 `{"type": "win", "reason": "xxx"}` 将会直接调用events.js中的win函数并将reason作为结局传入。
@ -880,7 +877,7 @@ value为音量大小在0到100之间默认为100。设置后BGM和SE都
!> 如果`reason`不为空则会以reason作为获胜的结局! !> 如果`reason`不为空则会以reason作为获胜的结局!
### lose: 游戏失败 ### lose游戏失败
`{"type": "lose", "reason": "xxx"}` 将会直接调用`events.js`中的lose函数并将reason作为参数传入。 `{"type": "lose", "reason": "xxx"}` 将会直接调用`events.js`中的lose函数并将reason作为参数传入。
@ -905,7 +902,7 @@ text为提示文字可以在这里给输入提示文字。这里同样可以
输入得到的结果将被赋值给flag:input可以供后续if来进行判断。 输入得到的结果将被赋值给flag:input可以供后续if来进行判断。
### if: 条件判断 ### if条件判断
使用`{"type": "if"}`可以对条件进行判断,根据判断结果将会选择不同的分支执行。 使用`{"type": "if"}`可以对条件进行判断,根据判断结果将会选择不同的分支执行。
@ -956,7 +953,7 @@ text为提示文字可以在这里给输入提示文字。这里同样可以
- if可以不断进行嵌套一层套一层如成立的场合再进行另一个if判断等。 - if可以不断进行嵌套一层套一层如成立的场合再进行另一个if判断等。
- if语句内的内容执行完毕后将接着其后面的语句继续执行。 - if语句内的内容执行完毕后将接着其后面的语句继续执行。
### choices: 给用户提供选项 ### choices给用户提供选项
choices是一个很麻烦的事件它将弹出一个列表供用户进行选择。 choices是一个很麻烦的事件它将弹出一个列表供用户进行选择。
@ -1118,6 +1115,45 @@ choices为一个数组其中每一项都是一个选项列表。
!> 如果continue事件不在任何循环中被执行则和exit等价即会立刻结束当前事件 !> 如果continue事件不在任何循环中被执行则和exit等价即会立刻结束当前事件
### wait等待用户操作
使用 `{"type": "wait"}` 可以等待用户进行操作(如点击、按键等)。
当用户执行操作后:
- 如果是键盘的按键操作则会将flag:type置为0并且把flag:keycode置为刚刚按键的keycode。
- 如果是屏幕的点击操作则会将flag:type置为1并且设置flag:x和flag:y为刚刚的点击坐标。
下面是一个while事件和wait合并使用的例子这个例子将不断接收用户的点击或按键行为并输出该信息。
如果用户按下了ESC或者点击了屏幕正中心则退出循环。
``` js
"x,y": [ // 实际执行的事件列表
{"type": "while", "condition": "true", // 永久循环
"data": [
{"type": "wait"}, // 等待用户操作
{"type": "if", "condition": "flag:type==0", // flag:type==0键盘按键
"true": [
"你当前按键了keycode是${flag:keycode}",
{"type": "if", "condition": "flag:keycode==27", // ESC的keycode是27
"true": [{"type": "break"}], // 跳出循环
"false": []
}
],
"false": [ // flag:type==1鼠标点击
"你当前点击屏幕了,坐标是[${flag:x},${flag:y}]",
{"type": "if", "condition": "flag:x==6 && flag:y==6", // 点击(6,6)
"true": [{"type": "break"}], // 跳出循环
"false": []
}
]
}
]
}
]
```
### function: 自定义JS脚本 ### function: 自定义JS脚本
上述给出了这么多事件,但有时候往往不能满足需求,这时候就需要执行自定义脚本了。 上述给出了这么多事件,但有时候往往不能满足需求,这时候就需要执行自定义脚本了。
@ -1133,22 +1169,23 @@ choices为一个数组其中每一项都是一个选项列表。
`{"type":"function"}`需要有一个`"function"`参数它是一个JS函数里面可以写任何自定义的JS脚本系统将会执行它。 `{"type":"function"}`需要有一个`"function"`参数它是一个JS函数里面可以写任何自定义的JS脚本系统将会执行它。
系统所有支持的API都在[附录](api)中给出 系统常见可能会被造塔所用到的的API都在[附录API列表](api)中给出,请进行参照
这里只简单列出给一些最常见的API **警告自定义脚本中只能执行同步代码不可执行任何异步代码比如直接调用core.changeFloor(...)之类都是不行的。**
[附录API列表](api)中的所有异步API都进行了标记如果你不确定一个函数是同步的还是异步的请向小艾咨询。
如果需要异步的代码都需要用事件insertAction来执行这样事件处理过程和录像回放才不会出错。
举个例子,如果我们想随机切换到某个楼层的某个点,我们可以这么写自定义脚本:
``` js ``` js
core.getStatus(name) //获得勇士的某个属性hp/atk/def/…) var toFloor = core.floorIds[core.rand(core.floorIds.length)]; // 随机一个楼层ID
core.setStatus(name, value) //设置勇士某个属性值为value var toX = core.rand(13), toY = core.rand(13); // 随机一个点
core.itemCount(name) //获得某个道具的个数 core.insertAction([
core.getItem(name, count) //获得某个道具count个 {"type": "changeFloor", "floorId": toFloor, "loc": [toX, toY]} // 插入一个changeFloor事件并在该脚本结束后执行。
core.setItem(name, value) //设置某个道具为value个 ])
core.getFlag(name, defaultValue) //获得某个自定义变量flag如果未定义则返回defaultValue // 请勿直接调用 core.changeFloor(toFloor, ...),这个代码是异步的,会导致事件处理和录像出问题!
core.setFlag(name, value) //将某个自定义变量/flag设置为value
core.hasFlag(name) //判断某个自定义flag是否成立。只有被被赋值过且不为0或false时才会返回true。
core.updateStatusBar() //立刻更新状态栏和地图显伤。上面各种get和set均不会对状态栏和地图显伤更新需要手动调用这个函数。
core.insertAction(list) //往当前事件列表中插入一系列事件。使用这个函数插入的事件将在这段自定义JS脚本执行完毕后立刻执行。
// ……
``` ```
## 同一个点的多事件处理 ## 同一个点的多事件处理
@ -1161,7 +1198,7 @@ core.insertAction(list) //往当前事件列表中插入一系列事件。使用
下面以几个具体例子来进行详细说明。 下面以几个具体例子来进行详细说明。
### 打怪掉宝(怪物->道具) ### 打怪掉宝
我们注意到怪物和道具都是系统默认事件因此无需写events而是直接在afterBattle中setBlock即可。 我们注意到怪物和道具都是系统默认事件因此无需写events而是直接在afterBattle中setBlock即可。
@ -1173,22 +1210,24 @@ core.insertAction(list) //往当前事件列表中插入一系列事件。使用
} }
``` ```
### 打怪变成可对话的NPC怪物->NPC ### 打怪变成楼梯
由于NPC是自定义事件因此我们需要写events。注意到events中不覆盖trigger则还是怪物时存在系统trigger因此会战斗变成NPC后没有系统trigger因此会触发自定义事件。 因为涉及到多事件处理因此我们不能写changeFloor那一项而是使用events自定义事件里写楼层转换
注意到events中不覆盖trigger则还是怪物时存在系统trigger因此会战斗并触发afterBattle变成NPC后没有系统trigger因此会触发自定义事件楼层转换
请注意打死怪物时默认会禁用该点因此替换后需要手动进行show来启用。 请注意打死怪物时默认会禁用该点因此替换后需要手动进行show来启用。
``` js ``` js
"events": { "events": {
"x,y": [ "x,y": [
"可对话的NPC" {"type": "changeFloor", "loc": [0,0], "floorId": "MT1"}
] ]
}, },
"afterBattle": { "afterBattle": {
"x,y": [ "x,y": [
{"type": "setBlock", "number": 121}, // 变成老人 {"type": "setBlock", "number": 87}, // 变成上楼梯
{"type": "show", "loc": [x,y]} // 启用该点 {"type": "show"} // 启用该点
] ]
} }
``` ```
@ -1228,6 +1267,7 @@ core.insertAction(list) //往当前事件列表中插入一系列事件。使用
- 触发器(trigger)亦采用覆盖原则,即**首先取该图块的默认触发器例如怪物是battle道具是getItem门是openDoor如果剧本的events中定义了该点的trigger则覆盖**。 - 触发器(trigger)亦采用覆盖原则,即**首先取该图块的默认触发器例如怪物是battle道具是getItem门是openDoor如果剧本的events中定义了该点的trigger则覆盖**。
- 可以通过if语句和flag来控制自定义事件具体走向哪个分支。 - 可以通过if语句和flag来控制自定义事件具体走向哪个分支。
- 如果弄不清楚系统trigger和自定义事件等的区别也可以全部覆盖为自定义事件然后通过type:battletype:openDoor等来具体进行控制。 - 如果弄不清楚系统trigger和自定义事件等的区别也可以全部覆盖为自定义事件然后通过type:battletype:openDoor等来具体进行控制。
- 多事件处理时请不要使用`changeFloor`那一项,而是使用`events`或者`afterXXX`来处理。
## 加点事件 ## 加点事件
@ -1237,13 +1277,7 @@ core.insertAction(list) //往当前事件列表中插入一系列事件。使用
如果要对某个怪物进行加点操作,则首先需要修改该怪物的`point`数值,代表怪物本身的加点数值。 如果要对某个怪物进行加点操作,则首先需要修改该怪物的`point`数值,代表怪物本身的加点数值。
``` js 然后在脚本编辑中找到加点事件双击进行修改。它将返回一个choices事件。修改此函数为我们需要的加点项即可。
... 'def': 0, 'money': 1, 'experience': 1, 'point': 1, 'special': 0}, // 在怪物后面添加point代表怪物的加点数
```
然后在`functions.js`文件中找到`addPoint`函数。它将返回一个choices事件。修改此函数为我们需要的加点项即可。
!> V2.0版本可以直接在“脚本编辑 - 加点事件”中双击进行修改!
``` js ``` js
////// 加点事件 ////// ////// 加点事件 //////
@ -1279,6 +1313,8 @@ core.insertAction(list) //往当前事件列表中插入一系列事件。使用
全局商店定义在`data.js`中找到shops一项。 全局商店定义在`data.js`中找到shops一项。
从V2.2以后,全局商店也可以使用图块进行编辑,但仍需知道每一项的使用。
``` js ``` js
"shops": [ // 定义全局商店(即快捷商店) "shops": [ // 定义全局商店(即快捷商店)
{ {
@ -1477,7 +1513,7 @@ core.insertAction(list) //往当前事件列表中插入一系列事件。使用
而在我们的存档中是不会对怪物数据进行存储的只会存各个变量和Flag因此我们需要在读档后根据变量或Flag来调整怪物数据。 而在我们的存档中是不会对怪物数据进行存储的只会存各个变量和Flag因此我们需要在读档后根据变量或Flag来调整怪物数据。
我们可以在functions.js中的`afterLoadData`进行处理。 我们可以在脚本编辑中的`afterLoadData`进行处理。
``` js ``` js
////// 读档事件后,载入事件前,可以执行的操作 ////// ////// 读档事件后,载入事件前,可以执行的操作 //////
@ -1540,7 +1576,7 @@ core.insertAction(list) //往当前事件列表中插入一系列事件。使用
// effect也允许写一个function代表本次升级将会执行的操作比如可以显示一段提示文字或者触发一个事件 // effect也允许写一个function代表本次升级将会执行的操作比如可以显示一段提示文字或者触发一个事件
{"need": 40, "effect": function () { {"need": 40, "effect": function () {
core.drawText("恭喜升级!"); core.drawTip("恭喜升级!");
core.status.hero.hp *= 2; core.status.hero.hp *= 2;
core.status.hero.atk += 100; core.status.hero.atk += 100;
core.status.hero.def += 100; core.status.hero.def += 100;

BIN
docs/img/console.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

BIN
docs/img/plugin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 KiB

After

Width:  |  Height:  |  Size: 138 KiB

View File

@ -44,8 +44,13 @@
mergeNavbar: true, mergeNavbar: true,
formatUpdated: '{YYYY}-{MM}-{DD} {HH}:{mm}:{ss}', formatUpdated: '{YYYY}-{MM}-{DD} {HH}:{mm}:{ss}',
} }
if (typeof navigator.serviceWorker !== 'undefined') { if (navigator.serviceWorker) {
navigator.serviceWorker.register('serviceWorker.js') navigator.serviceWorker.getRegistrations()
.then(function(registrations) {
for(let registration of registrations) {
registration.unregister();
}
});
} }
</script> </script>
<script src="https://cdn.bootcss.com/docsify/4.5.5/docsify.min.js"></script> <script src="https://cdn.bootcss.com/docsify/4.5.5/docsify.min.js"></script>

View File

@ -75,7 +75,7 @@ images为一个数组代表当前层所有作为背景素材的图片信息
如果第四项为true则会在前景层event2上绘制能覆盖勇士常常用来作为柱子的上半部分等情况。 如果第四项为true则会在前景层event2上绘制能覆盖勇士常常用来作为柱子的上半部分等情况。
**如果你需要让某些点不可通行(比如你建了个房子,墙壁和家具等位置不让通行),则需在`events`中指定`{"noPass": false}`,参见[自定义事件](event#自定义事件)的写法。 **如果你需要让某些点不可通行(比如你建了个房子,墙壁和家具等位置不让通行),则需在`events`中指定`{"noPass": false}`,参见[自定义事件](event#自定义事件)的写法。**
``` js ``` js
"events": { "events": {
@ -114,8 +114,35 @@ images为一个数组代表当前层所有作为背景素材的图片信息
**`ID-数字` 对应关系定义在maps.js文件中。该文件将唯一确定一个ID对应的数字是多少。** **`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和文件名应确保完全相同
<!--
#### 新添加自定义地形(路面、墙壁等) #### 新添加自定义地形(路面、墙壁等)
如果你在terrains.png中新增了一行 如果你在terrains.png中新增了一行
@ -177,6 +204,8 @@ images为一个数组代表当前层所有作为背景素材的图片信息
!> 如果是48x32的怪物素材请放在npc48.png中然后在icons.js的npc48下添加索引。 !> 如果是48x32的怪物素材请放在npc48.png中然后在icons.js的npc48下添加索引。
-->
### 地图生成器使用自定义素材 ### 地图生成器使用自定义素材
地图生成器是直接从js文件中读取数字-图标对应关系的。 地图生成器是直接从js文件中读取数字-图标对应关系的。
@ -196,7 +225,7 @@ images为一个数组代表当前层所有作为背景素材的图片信息
如果你想要同种宝石在不同层效果不同的话,可以进行如下操作: 如果你想要同种宝石在不同层效果不同的话,可以进行如下操作:
1. 在楼层的item_ratio中定义宝石的比率比如1-10的写111-20层写2等 1. 在楼层的item_ratio中定义宝石的比率比如1-10的写111-20层写2等
2. 修改获得道具的itemEffect函数在items.js中的itemEffect中编辑V2.0中也可以使用编辑器 2. 修改获得道具的itemEffect函数编辑器中双击进行编辑
``` js ``` js
// ratio为楼层的item_ratio值可以进行翻倍宝石属性 // ratio为楼层的item_ratio值可以进行翻倍宝石属性
@ -278,7 +307,53 @@ control.prototype.checkBlock = function () {
} }
// ... 下略 // ... 下略
``` ```
4. 如果有更高的需求,例如想让吸血效果变成一半(如异空间),则还是在上面这些地方进行对应的修改即可。 4. 如果有更高的需求,例如想让吸血效果变成一半,则还是在上面这些地方进行对应的修改即可。
## 新增门和对应的钥匙
如果要新增一个门和对应的钥匙,需要进行如下几步:
1. 在terrains.png中添加新的门的素材并在地图编辑器中注册门的ID。该ID必须是以`Door`结尾,例如`abcDoor`。
2. 在animates.png中添加开门的四格动画然后直接打开icons.js文件在animates下直接添加ID和索引信息例如`'abcDoor': 34`。
3. 在items.png中添加钥匙的素材并在地图编辑器中注册钥匙的ID。该ID必须是和门对应且以`Key`结尾,例如`abcKey`。
4. 该道具的cls应为`tools`,可以自行写道具描述,最下面几项均留`null`即可。
!> **请勿在animates中对门的动画素材进行注册而是请直接打开icons.js文件并添加ID和索引信息**
!> terrains和animates的门ID必须完全一致且以`Door`结尾所对应的钥匙ID应当是把`Door`换成`Key`,这样才能对应的上!
## 覆盖楼传事件
对于特殊的塔,我们可以考虑修改楼传事件来完成一些特殊的要求,比如镜子可以按楼传来切换表里。
要修改楼传事件,需要进行如下几步:
1. 截获楼传的点击事件。在control.js中找到useFly函数并将其替换成如下内容
``` js
////// 点击楼层传送器时的打开操作 //////
control.prototype.useFly = function (need) {
if (!core.status.heroStop) {
core.drawTip("请先停止勇士行动");
return;
}
if (core.canUseItem('fly')) core.useItem('fly');
else core.drawTip("当前无法使用"+core.material.items.fly.name);
}
```
2. 让录像记下楼传的使用。在items.js的useItem函数中找到记录路线的那几行修改为
``` js
// 记录路线
if (itemId!='book') { // 把 `&& itemId!='fly'` 给删除
core.status.route.push("item:"+itemId);
}
```
3. 修改楼传的使用事件。和其他永久道具一样在地图编辑器的图块属性中修改楼传的useItemEffect和canUseItemEffect两个内容。例如
``` js
"useItemEffect": "core.insertAction([...])" // 执行某段自定义事件,或者其他脚本
"canUseItemEffect": "true" // 任何时候可用
```
修改时,请先把`null`改成空字符串`""`,然后再双击进行编辑。
## 自定义装备 ## 自定义装备
@ -305,7 +380,7 @@ control.prototype.checkBlock = function () {
"shield1": {"atk": 0, "def": 10, "mdef": 10}, // 铁盾加10防和10魔防 "shield1": {"atk": 0, "def": 10, "mdef": 10}, // 铁盾加10防和10魔防
``` ```
通过这种方式,当穿上装备时,将会给你的三围分别加上对应项的数值。 通过这种方式,当穿上装备时,将会给你的三围分别加上对应项的数值(支持负数,比如装剑减防御)
### 新增剑盾 ### 新增剑盾
@ -359,7 +434,7 @@ this.useEquipment = function (itemId) { // 使用装备
你需自己指定一个special数字修改getSpecialText函数属性名和getSpecialHint函数属性提示文字 你需自己指定一个special数字修改getSpecialText函数属性名和getSpecialHint函数属性提示文字
如果要修改伤害计算公式,请修改下面的calDamage函数。请注意,如果无法战斗,该函数必须返回`null`。 如果要修改伤害计算公式,请修改下面的getDamageInfo函数。请注意,如果无法战斗,该函数必须返回`null`。
对于毒衰弱怪物的战斗后结算在`functions.js`中的afterBattle函数中。 对于毒衰弱怪物的战斗后结算在`functions.js`中的afterBattle函数中。
@ -367,6 +442,295 @@ this.useEquipment = function (itemId) { // 使用装备
`getCritical`, `getCriticalDamage`和`getDefDamage`三个函数依次计算的是该怪物的临界值、临界减伤和1防减伤。也可以适当进行修改。 `getCritical`, `getCriticalDamage`和`getDefDamage`三个函数依次计算的是该怪物的临界值、临界减伤和1防减伤。也可以适当进行修改。
## 自定义快捷键
如果需要绑定某个快捷键为处理一段事件,也是可行的。
要修改按键,我们可以在`actions.js`的`keyUp`进行处理:
比如,我们设置一个快捷键进行绑定,比如`W`其keycode是87。有关每个键的keycode搜一下就能得到
然后在`actions.js`的`keyUp`函数的`switch`中进行处理。
``` js
case 87: // W
if (core.status.heroStop) {
// ... 在这里写你要执行脚本
// 请使用同步脚本,请勿执行任何异步代码,否则可能导致游戏过程或录像出现问题。
core.insertAction([...]) // 例如,插入一段自定义事件并执行。
core.status.route.push("key:"+keyCode); // 录像的支持!这句话必须要加,不然录像回放会出错!
}
break;
```
在勇士处于停止的条件下按下W键时将执行你写的脚本代码。请只使用同步脚本而不要使用异步代码不然可能导致游戏出现问题。
`core.status.route.push("key:"+keyCode);` 这句话是对录像的支持,一定要加(这样录像播放时也会模拟该按键)。
!> H5不支持组合快捷键所以不存在`W+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
<div class="status" id="manaCol">
<img id="img-mana">
<p class='statusLabel' id='mana'></p>
</div>
```
3. 在editor.html中的statusBar305行起仿照第二点同样添加这一项如果不进行则会地图编辑器报错。
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表示当前激活的技能名。
```
### 技能的触发
我们可以按键触发技能。有关绑定按键请参见[自定义快捷键](#自定义快捷键)。
下面是一个很简单的例子当勇士按下W后如果魔力不小于5点则允许开启技能"二倍斩"再次按W则关闭技能。
``` js
case 87: // W
if (core.status.heroStop) { // 当前停止状态这个if需要加不能在行走过程中触发不然容易出错。
if (core.getFlag('skill', 0)==0) { // 判断当前是否已经开了技能
if (core.getStatus('mana')>=5) { // 这里要写当前能否开技能的条件判断,比如魔力值至少要多少
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);` 这句话是对录像的支持,一定要加(这样录像播放时也会模拟该按键)。
!> 123这三个键被默认绑定到了破炸飞如果想用的话也是一样只不过是把已有的实现进行替换。
!> 手机端可以通过长按任何位置调出虚拟键盘,再进行按键,和键盘按键是等价的效果!
### 技能的效果
最后一点就是技能的效果其实到了这里就和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', '无');
}
```
&nbsp;
通过上述这几种方式我们就能成功的让H5支持技能啦
## 多角色的支持
其实,我们的样板还能支持多角色的制作。比如《黑·白·间》之类的塔也是完全可以刻的。
你只需要如下几步来达到多角色的效果。
1. 每个角色弄一张行走图。相关信息参见[自定义事件setHeroIcon](event#setHeroIcon更改角色行走图)。
2. [覆盖楼传事件](#覆盖楼传事件),这样可以通过点工具栏的楼层传送按钮来切换角色。当然你也完全可以自己写一个道具,或[自定义快捷键](#自定义快捷键)来进行绑定。
3. 在脚本编辑的setInitData中初始化新角色的属性值。
```js
// 所有需要保存的内容;这些保存的内容不会多角色共用,在切换时会进行恢复。
// 你也可以自行新增或删除,比如不共用金币则可以加上"money"的初始化,不共用道具则可以加上"items"的初始化,
// 多角色共用hp的话则删除hp等等。总之不共用的属性都在这里进行定义就好。
var initData = {
"floorId": "MT0", // 该角色楼层ID
"icon": "hero2.png", // 角色的行走图名称
"name": "2号角色",
"lv": 1,
"hp": 1000,
"atk": 10,
"def": 10,
"mdef": 0,
"loc": {"x": 0, "y": 0, "direction": "up"},
// 不共用的数据都可以在这里加上定义
}
core.setFlag("hero1", initData); // 将属性值存到变量中
```
4. 道具(或快捷键)的脚本如下。
```js
// 这个saveList和上面的初始化定义中的的key除了不要icon行走图名称其他应完全相同。
var saveList = ["floorId", "name", "lv", "hp", "atk", "def", "mdef", "loc"];
// 保存当前内容
var toSave = {};
saveList.forEach(function(name) {
if (name=='floorId') toSave[name] = core.status.floorId; // 楼层单独设置
else toSave[name] = core.clone(core.status.hero[name]); // 使用core.clone()来创建新对象
})
var currHeroId = core.getFlag("heroId", 0); // 获得当前角色ID
var toHeroId = (currHeroId+1)%2; // 获得要切换到的角色ID比如 0->11->0
core.setFlag("hero"+currHeroId, toSave); // 将当前角色信息进行保存
var data = core.getFlag("hero"+toHeroId); // 获得要切换的角色保存内容
// 设置角色的属性值
saveList.forEach(function(name) {
if (core.isset(core.status.hero[name]) && core.isset(data[name]))
core.status.hero[name] = core.clone(data[name]);
})
// 插入事件:改变角色行走图并进行楼层切换
core.insertAction([
{"type": "setHeroIcon", "name": data.icon||"hero.png"}, // 改变行走图
{"type": "changeFloor", "floorId": data.floorId, "loc": [data.loc.x, data.loc.y],
"direction": data.loc.direction, "time": 0} // 楼层切换事件
])
core.setFlag("heroId", toHeroId); // 保存切换到的角色ID
```
## 根据难度分歧来自定义地图 ## 根据难度分歧来自定义地图
遗憾的是所有地图数据必须在剧本的map中指定换句话说我们无法在游戏进行中动态修改地图比如为简单难度增加一个血瓶。 遗憾的是所有地图数据必须在剧本的map中指定换句话说我们无法在游戏进行中动态修改地图比如为简单难度增加一个血瓶。

View File

@ -1,75 +0,0 @@
const RUNTIME = 'docsify'
const HOSTNAME_WHITELIST = [
self.location.hostname,
'fonts.gstatic.com',
'fonts.googleapis.com',
'cdn.bootcss.com'
]
// The Util Function to hack URLs of intercepted requests
const getFixedUrl = (req) => {
var now = Date.now()
var url = new URL(req.url)
// 1. fixed http URL
// Just keep syncing with location.protocol
// fetch(httpURL) belongs to active mixed content.
// And fetch(httpRequest) is not supported yet.
url.protocol = self.location.protocol
// 2. add query for caching-busting.
// Github Pages served with Cache-Control: max-age=600
// max-age on mutable content is error-prone, with SW life of bugs can even extend.
// Until cache mode of Fetch API landed, we have to workaround cache-busting with query string.
// Cache-Control-Bug: https://bugs.chromium.org/p/chromium/issues/detail?id=453190
if (url.hostname === self.location.hostname) {
url.search += (url.search ? '&' : '?') + 'cache-bust=' + now
}
return url.href
}
/**
* @Lifecycle Activate
* New one activated when old isnt being used.
*
* waitUntil(): activating ====> activated
*/
self.addEventListener('activate', event => {
event.waitUntil(self.clients.claim())
})
/**
* @Functional Fetch
* All network requests are being intercepted here.
*
* void respondWith(Promise<Response> r)
*/
self.addEventListener('fetch', event => {
// Skip some of cross-origin requests, like those for Google Analytics.
if (HOSTNAME_WHITELIST.indexOf(new URL(event.request.url).hostname) > -1) {
// Stale-while-revalidate
// similar to HTTP's stale-while-revalidate: https://www.mnot.net/blog/2007/12/12/stale
// Upgrade from Jake's to Surma's: https://gist.github.com/surma/eb441223daaedf880801ad80006389f1
const cached = caches.match(event.request)
const fixedUrl = getFixedUrl(event.request)
const fetched = fetch(fixedUrl, { cache: 'no-store' })
const fetchedCopy = fetched.then(resp => resp.clone())
// Call respondWith() with whatever we get first.
// If the fetch fails (e.g disconnected), wait for the cache.
// If theres nothing in cache, wait for the fetch.
// If neither yields a response, return offline pages.
event.respondWith(
Promise.race([fetched.catch(_ => cached), cached])
.then(resp => resp || fetched)
.catch(_ => { /* eat any errors */ })
)
// Update the cache with the version we fetched (only for ok status)
event.waitUntil(
Promise.all([fetchedCopy, caches.open(RUNTIME)])
.then(([response, cache]) => response.ok && cache.put(event.request, response))
.catch(_ => { /* eat any errors */ })
)
}
})

View File

@ -30,6 +30,8 @@
* “JS代码压缩工具”能对JS代码进行压缩从而减少IO请求数和文件大小。 * “JS代码压缩工具”能对JS代码进行压缩从而减少IO请求数和文件大小。
* “伤害和临界值计算器”是一个很便捷的小工具,能对怪物的伤害和临界值进行计算。 * “伤害和临界值计算器”是一个很便捷的小工具,能对怪物的伤害和临界值进行计算。
!> **整个造塔过程中,启动服务必须全程处于开启状态!切不可手滑关闭,否则做的都是无用功!**
## 绘制地图 ## 绘制地图
有两种绘制地图的方式从头绘制地图从RMXP中导入已有的地图。 有两种绘制地图的方式从头绘制地图从RMXP中导入已有的地图。
@ -44,6 +46,8 @@
如果提示“该素材未被定义”或有红色问号框,请参见[素材注册](#素材注册)。 如果提示“该素材未被定义”或有红色问号框,请参见[素材注册](#素材注册)。
绘制地图时可以右键弹出菜单,移动图块和事件。
### 从RMXP导入已有的地图 ### 从RMXP导入已有的地图
如果我们想复刻一个现有的已经被RMXP所制作的塔也有很便捷的方式那就是用到我们的“地图生成器”。 如果我们想复刻一个现有的已经被RMXP所制作的塔也有很便捷的方式那就是用到我们的“地图生成器”。
@ -168,9 +172,47 @@
素材注册完毕后,即可在游戏中正常使用,也可以被地图生成器所识别(需要重开地图生成器)。 素材注册完毕后,即可在游戏中正常使用,也可以被地图生成器所识别(需要重开地图生成器)。
## 控制台调试
HTML5的塔都是可以进行控制台调试的。
当我们使用Chrome进入游戏后可以按 `Ctrl+Shift+I` ,并找到 `Console` 控制台。
![控制台](./img/console.png)
在控制台中,我们可以输入一些命令对游戏进行调试,常见的命令有:
- `core.status.floorId` 获得当前层的floorId。
- `core.status.thisMap` 获得当前地图信息。例如`core.status.thisMap.blocks`可以获得当前层所有图块。
- `core.floors` 获得所有剧本的信息。例如`core.floors[core.status.floorId].events`可以获得当前层所有事件。
- `core.status.hero` 获得当前勇士状态信息。例如`core.status.hero.atk`就是当前勇士的攻击力数值。
- `core.material.enemys` 获得所有怪物信息。例如`core.material.enemys.greenSlime`就是获得绿色史莱姆的属性数据。
- `core.material.items` 获得所有道具的信息。例如`core.material.items.pickaxe`就是获得破墙镐的信息。
- `core.debug()` 开启调试模式此模式下可以按住Ctrl键进行穿墙。
- `core.updateStatusBar()` 立刻更新状态栏和地图显伤。
- `core.setStatus('atk', 1000)` 直接设置勇士的某项属性。本句等价于 `core.status.hero.atk = 1000`
- `core.getStatus('atk')` 返回勇士当前某项属性数值。本句等价于 `core.status.hero.atk`
- `core.setItem('pickaxe', 10)` 直接设置勇士某个道具的个数。这里可以需要写道具的ID。
- `core.getItem('pickaxe', 2)` 令勇士获得两个破墙镐。
- `core.itemCount('pickaxe')` 返回勇士某个道具的个数。
- `core.hasItem('pickaxe')` 返回勇士是否拥有某个道具。等价于`core.itemCount('pickaxe')!=0`。
- `core.setFlag('xxx', 1)` 设置某个flag/自定义变量的值。
- `core.getFlag('xxx', 10)` 获得某个flag/自定义变量的值;如果该项不存在(未被定义),则返回第二个参数的值。
- `core.hasFlag('xxx')` 返回是否存在某个变量且不为0。等价于`core.getFlag('xxx', 0)!=0`。
- `core.insertAction(list)` 执行一段自定义事件。比如 `core.insertAction(["剧情文本"])` 将执行一个剧情文本显示事件。
- `core.changeFloor('MT2', 'downFloor')` 立刻执行楼层切换到MT2层的下楼点位置。
- `core.changeFloor('MT5', null, {'x': 4, 'y': 7})` 立刻切换楼层到MT5层的(4,7)点。
- `core.getBlock(3, 5, 'MT1')` 获得当前地图上某一个块的信息。第三个参数为floorId可省略表示当前楼层。
- `core.resetMap()` 重置当前层地图。**当修改地图后再读档修改的地图不会立刻生效此时可以使用resetMap来重置当前楼层的地图。**
- `localStorage` 获得所有的存档数据。可以用 `core.getLocalStorage('save1')` 来具体获得某个存档。
- ……
更多API和详细参数介绍可参见[API列表](api)。
## 报错处理 ## 报错处理
有时候刷新后可能页面变成空白,即无法正确加载,游戏也无法正常进入。 有时候刷新后可能地图编辑器页面变成空白,即无法正确加载,游戏也无法正常进入。
出现这种问题的原因往往是如下几种: 出现这种问题的原因往往是如下几种:
- 手动直接打开并错误编辑了文件 - 手动直接打开并错误编辑了文件

View File

@ -82,7 +82,7 @@
<img id="img-up"> <img id="img-up">
<p class='statusLabel' id='up'></p> <p class='statusLabel' id='up'></p>
</div> </div>
<div class="status"> <div class="status" id='keyCol'>
<span class='statusLabel' id='yellowKey' style="color:#FFCCAA"></span> <span class='statusLabel' id='yellowKey' style="color:#FFCCAA"></span>
<span class='statusLabel' id='blueKey' style="color:#AAAADD"></span> <span class='statusLabel' id='blueKey' style="color:#AAAADD"></span>
<span class='statusLabel' id='redKey' style="color:#FF8888"></span> <span class='statusLabel' id='redKey' style="color:#FF8888"></span>

View File

@ -25,6 +25,7 @@ actions.prototype.onkeyDown = function (e) {
core.status.holdingKeys.push(e.keyCode); core.status.holdingKeys.push(e.keyCode);
this.pressKey(e.keyCode); this.pressKey(e.keyCode);
} else { } else {
if (e.keyCode==17) core.status.ctrlDown = true;
this.keyDown(e.keyCode); this.keyDown(e.keyCode);
} }
} }
@ -60,6 +61,7 @@ actions.prototype.onkeyUp = function(e) {
} }
this.keyUp(e.keyCode); this.keyUp(e.keyCode);
} else { } else {
if (e.keyCode==17) core.status.ctrlDown = false;
this.keyUp(e.keyCode); this.keyUp(e.keyCode);
} }
} }
@ -337,8 +339,14 @@ actions.prototype.keyUp = function(keyCode, fromReplay) {
core.ui.drawHelp(); core.ui.drawHelp();
break; break;
case 82: // R case 82: // R
if (core.status.heroStop) if (core.status.heroStop) {
core.ui.drawReplay(); if (core.hasFlag('debug')) {
core.drawText("\t[系统提示]调试模式下无法回放录像");
}
else {
core.ui.drawReplay();
}
}
break; break;
case 33: case 34: // PAGEUP/PAGEDOWN case 33: case 34: // PAGEUP/PAGEDOWN
if (core.status.heroStop) { if (core.status.heroStop) {
@ -409,7 +417,7 @@ actions.prototype.ondown = function (x ,y) {
core.timeout.onDownTimeout = setTimeout(function () { core.timeout.onDownTimeout = setTimeout(function () {
if (core.interval.onDownInterval == null) { if (core.interval.onDownInterval == null) {
core.interval.onDownInterval = setInterval(function () { core.interval.onDownInterval = setInterval(function () {
if (!core.actions.longClick()) { if (!core.actions.longClick(x, y, true)) {
clearInterval(core.interval.onDownInterval); clearInterval(core.interval.onDownInterval);
core.interval.onDownInterval = null; core.interval.onDownInterval = null;
} }
@ -480,10 +488,7 @@ actions.prototype.onup = function () {
// 长按 // 长按
if (!core.status.lockControl && stepPostfix.length==0 && core.status.downTime!=null && new Date()-core.status.downTime>=1000) { if (!core.status.lockControl && stepPostfix.length==0 && core.status.downTime!=null && new Date()-core.status.downTime>=1000) {
core.waitHeroToStop(function () { this.longClick(posx, posy);
// 绘制快捷键
core.ui.drawKeyBoard();
});
} }
else { else {
//posx,posy是寻路的目标点,stepPostfix是后续的移动 //posx,posy是寻路的目标点,stepPostfix是后续的移动
@ -709,15 +714,23 @@ actions.prototype.onmousewheel = function (direct) {
/////////////////// 在某个界面时的按键点击效果 /////////////////// /////////////////// 在某个界面时的按键点击效果 ///////////////////
////// 长按 ////// ////// 长按 //////
actions.prototype.longClick = function () { actions.prototype.longClick = function (x, y, fromEvent) {
if (!core.isPlaying()) return false; if (!core.isPlaying()) return false;
if (core.status.event.id=='text') { if (core.status.lockControl) {
core.drawText(); if (core.status.event.id=='text') {
return true; core.drawText();
return true;
}
if (core.status.event.id=='action' && core.status.event.data.type=='text') {
core.doAction();
return true;
}
} }
if (core.status.event.id=='action' && (core.status.event.data.type=='text' || core.status.event.data.type=='wait')) { else if (!fromEvent) {
core.doAction(); core.waitHeroToStop(function () {
return true; // 绘制快捷键
core.ui.drawKeyBoard();
});
} }
return false; return false;
} }
@ -728,7 +741,7 @@ actions.prototype.keyDownCtrl = function () {
core.drawText(); core.drawText();
return; return;
} }
if (core.status.event.id=='action' && (core.status.event.data.type=='text' || core.status.event.data.type=='wait')) { if (core.status.event.id=='action' && core.status.event.data.type=='text') {
core.doAction(); core.doAction();
return; return;
} }
@ -769,11 +782,20 @@ actions.prototype.keyUpConfirmBox = function (keycode) {
////// 自定义事件时的点击操作 ////// ////// 自定义事件时的点击操作 //////
actions.prototype.clickAction = function (x,y) { actions.prototype.clickAction = function (x,y) {
if (core.status.event.data.type=='text' || core.status.event.data.type=='wait') { if (core.status.event.data.type=='text') {
// 文字 // 文字
core.doAction(); core.doAction();
return; return;
} }
if (core.status.event.data.type=='wait') {
core.setFlag('type', 1);
core.setFlag('x', x);
core.setFlag('y', y);
core.status.route.push("input:"+(10000+100*x+y));
core.doAction();
return;
}
if (core.status.event.data.type=='choices') { if (core.status.event.data.type=='choices') {
// 选项 // 选项
var data = core.status.event.data.current; var data = core.status.event.data.current;
@ -811,7 +833,14 @@ actions.prototype.keyDownAction = function (keycode) {
////// 自定义事件时,放开某个键的操作 ////// ////// 自定义事件时,放开某个键的操作 //////
actions.prototype.keyUpAction = function (keycode) { actions.prototype.keyUpAction = function (keycode) {
if ((core.status.event.data.type=='text' || core.status.event.data.type=='wait') && (keycode==13 || keycode==32 || keycode==67)) { if (core.status.event.data.type=='text' && (keycode==13 || keycode==32 || keycode==67)) {
core.doAction();
return;
}
if (core.status.event.data.type=='wait') {
core.setFlag('type', 0);
core.setFlag('keycode', keycode);
core.status.route.push("input:"+keycode);
core.doAction(); core.doAction();
return; return;
} }
@ -1533,6 +1562,8 @@ actions.prototype.clickSettings = function (x,y) {
}); });
break; break;
case 5: case 5:
core.ui.drawStatistics();
/*
core.ui.drawWaiting("正在拉取统计信息,请稍后..."); core.ui.drawWaiting("正在拉取统计信息,请稍后...");
var formData = new FormData(); var formData = new FormData();
@ -1580,6 +1611,7 @@ actions.prototype.clickSettings = function (x,y) {
core.drawText("出错啦!\n无法拉取统计信息。\n错误原因XHR Error"); core.drawText("出错啦!\n无法拉取统计信息。\n错误原因XHR Error");
} }
xhr.send(formData); xhr.send(formData);
*/
break; break;
case 6: case 6:
core.ui.drawHelp(); core.ui.drawHelp();
@ -1687,6 +1719,10 @@ actions.prototype.clickSyncSave = function (x,y) {
}); });
break; break;
case 4: case 4:
if (core.hasFlag('debug')) {
core.drawText("\t[系统提示]调试模式下无法下载录像");
break;
}
core.download(core.firstData.name+"_"+core.formatDate2(new Date())+".h5route", JSON.stringify({ core.download(core.firstData.name+"_"+core.formatDate2(new Date())+".h5route", JSON.stringify({
'name': core.firstData.name, 'name': core.firstData.name,
'hard': core.status.hard, 'hard': core.status.hard,

View File

@ -59,6 +59,13 @@ control.prototype.setRequestAnimationFrame = function () {
core.animateFrame.moveTime = core.animateFrame.moveTime||timestamp; core.animateFrame.moveTime = core.animateFrame.moveTime||timestamp;
core.animateFrame.weather.time = core.animateFrame.weather.time||timestamp; core.animateFrame.weather.time = core.animateFrame.weather.time||timestamp;
// move time
if (core.isPlaying() && core.isset(core.status) && core.isset(core.status.hero)
&& core.isset(core.status.hero.statistics)) {
core.status.hero.statistics.totalTime += timestamp-(core.status.hero.statistics.start||timestamp);
core.status.hero.statistics.start=timestamp;
}
// Global Animate // Global Animate
if (core.animateFrame.globalAnimate && core.isPlaying()) { if (core.animateFrame.globalAnimate && core.isPlaying()) {
@ -237,6 +244,12 @@ control.prototype.clearStatus = function() {
////// 重置游戏状态和初始数据 ////// ////// 重置游戏状态和初始数据 //////
control.prototype.resetStatus = function(hero, hard, floorId, route, maps) { control.prototype.resetStatus = function(hero, hard, floorId, route, maps) {
var totalTime=0;
if (core.isset(core.status) && core.isset(core.status.hero)
&& core.isset(core.status.hero.statistics) && core.isset(route)) {
totalTime=core.status.hero.statistics.totalTime;
}
this.clearStatus(); this.clearStatus();
// 初始化status // 初始化status
@ -249,6 +262,20 @@ control.prototype.resetStatus = function(hero, hard, floorId, route, maps) {
core.material.enemys = core.clone(core.enemys.getEnemys()); core.material.enemys = core.clone(core.enemys.getEnemys());
// 初始化人物属性 // 初始化人物属性
core.status.hero = core.clone(hero); core.status.hero = core.clone(hero);
// 统计数据
if (!core.isset(core.status.hero.statistics))
core.status.hero.statistics = {
'totalTime': totalTime,
'hp': 0,
'battleDamage': 0,
'poisonDamage': 0,
'extraDamage': 0,
'moveDirectly': 0,
'ignoreSteps': 0,
}
core.status.hero.statistics.totalTime = Math.max(core.status.hero.statistics.totalTime, totalTime);
core.status.hero.statistics.start = null;
core.status.hard = hard; core.status.hard = hard;
// 初始化路线 // 初始化路线
if (core.isset(route)) if (core.isset(route))
@ -349,12 +376,15 @@ control.prototype.setAutomaticRoute = function (destX, destY, stepPostfix) {
core.status.automaticRoute.moveDirectly = true; core.status.automaticRoute.moveDirectly = true;
setTimeout(function () { setTimeout(function () {
if (core.status.automaticRoute.moveDirectly && core.status.heroMoving==0) { if (core.status.automaticRoute.moveDirectly && core.status.heroMoving==0) {
if (core.canMoveDirectly(destX, destY)) { var ignoreSteps = core.canMoveDirectly(destX, destY);
if (ignoreSteps>0) {
core.clearMap('hero', 0, 0, 416, 416); core.clearMap('hero', 0, 0, 416, 416);
core.setHeroLoc('x', destX); core.setHeroLoc('x', destX);
core.setHeroLoc('y', destY); core.setHeroLoc('y', destY);
core.drawHero(); core.drawHero();
core.status.route.push("move:"+destX+":"+destY); core.status.route.push("move:"+destX+":"+destY);
core.status.hero.statistics.moveDirectly++;
core.status.hero.statistics.ignoreSteps+=ignoreSteps;
} }
} }
core.status.automaticRoute.moveDirectly = false; core.status.automaticRoute.moveDirectly = false;
@ -621,6 +651,7 @@ control.prototype.moveAction = function (callback) {
if (core.status.event.id!='ski') if (core.status.event.id!='ski')
core.status.route.push(direction); core.status.route.push(direction);
core.status.automaticRoute.moveStepBeforeStop = []; core.status.automaticRoute.moveStepBeforeStop = [];
core.status.automaticRoute.lastDirection = core.getHeroLoc('direction');
if (canMove) // 非箭头:触发 if (canMove) // 非箭头:触发
core.trigger(x + scan[direction].x, y + scan[direction].y); core.trigger(x + scan[direction].x, y + scan[direction].y);
core.drawHero(direction, x, y); core.drawHero(direction, x, y);
@ -676,7 +707,7 @@ control.prototype.turnHero = function() {
////// 让勇士开始移动 ////// ////// 让勇士开始移动 //////
control.prototype.moveHero = function (direction, callback) { control.prototype.moveHero = function (direction, callback) {
// 如果正在移动直接return // 如果正在移动直接return
if (core.status.heroMoving>0) return; if (core.status.heroMoving!=0) return;
if (core.isset(direction)) if (core.isset(direction))
core.setHeroLoc('direction', direction); core.setHeroLoc('direction', direction);
if (!core.isset(callback)) { // 如果不存在回调函数则使用heroMoveTrigger if (!core.isset(callback)) { // 如果不存在回调函数则使用heroMoveTrigger
@ -685,8 +716,18 @@ control.prototype.moveHero = function (direction, callback) {
var doAction = function () { var doAction = function () {
if (!core.status.heroStop) { if (!core.status.heroStop) {
core.moveAction(); if (core.hasFlag('debug') && core.status.ctrlDown) {
setTimeout(doAction, 50); if (core.status.heroMoving!=0) return;
core.status.heroMoving=-1;
core.eventMoveHero([core.getHeroLoc('direction')], 100, function () {
core.status.heroMoving=0;
doAction();
});
}
else {
core.moveAction();
setTimeout(doAction, 50);
}
} }
else { else {
core.stopHero(); core.stopHero();
@ -770,6 +811,7 @@ control.prototype.moveOneStep = function() {
core.status.hero.steps++; core.status.hero.steps++;
// 中毒状态 // 中毒状态
if (core.hasFlag('poison')) { if (core.hasFlag('poison')) {
core.status.hero.statistics.poisonDamage += core.values.poisonDamage;
core.status.hero.hp -= core.values.poisonDamage; core.status.hero.hp -= core.values.poisonDamage;
if (core.status.hero.hp<=0) { if (core.status.hero.hp<=0) {
core.status.hero.hp=0; core.status.hero.hp=0;
@ -783,6 +825,7 @@ control.prototype.moveOneStep = function() {
////// 停止勇士的一切行动等待勇士行动结束后再执行callback ////// ////// 停止勇士的一切行动等待勇士行动结束后再执行callback //////
control.prototype.waitHeroToStop = function(callback) { control.prototype.waitHeroToStop = function(callback) {
var lastDirection = core.status.automaticRoute.lastDirection;
core.stopAutomaticRoute(); core.stopAutomaticRoute();
core.clearContinueAutomaticRoute(); core.clearContinueAutomaticRoute();
if (core.isset(callback)) { if (core.isset(callback)) {
@ -791,6 +834,8 @@ control.prototype.waitHeroToStop = function(callback) {
core.status.automaticRoute.moveDirectly = false; core.status.automaticRoute.moveDirectly = false;
setTimeout(function(){ setTimeout(function(){
core.status.replay.animate=false; core.status.replay.animate=false;
if (core.isset(lastDirection))
core.setHeroLoc('direction', lastDirection);
core.drawHero(); core.drawHero();
callback(); callback();
}, 30); }, 30);
@ -1007,9 +1052,10 @@ control.prototype.checkBlock = function () {
} }
if (damage>0) { if (damage>0) {
core.playSound('zone.ogg'); core.playSound('zone.mp3');
core.drawAnimate("zone", x, y); core.drawAnimate("zone", x, y);
} }
core.status.hero.statistics.extraDamage += damage;
if (core.status.hero.hp<=0) { if (core.status.hero.hp<=0) {
core.status.hero.hp=0; core.status.hero.hp=0;
@ -1317,7 +1363,9 @@ control.prototype.updateFg = function () {
// 临界显伤 // 临界显伤
if (core.flags.displayCritical) { if (core.flags.displayCritical) {
var critical = core.formatBigNumber(core.enemys.getCritical(id)); var critical = core.enemys.nextCriticals(id);
if (critical.length>0) critical=critical[0];
critical = core.formatBigNumber(critical[0]);
if (critical == '???') critical = '?'; if (critical == '???') critical = '?';
core.setFillStyle('fg', '#000000'); core.setFillStyle('fg', '#000000');
core.canvas.fg.fillText(critical, 32 * x + 2, 32 * (y + 1) - 2 - 10); core.canvas.fg.fillText(critical, 32 * x + 2, 32 * (y + 1) - 2 - 10);
@ -1338,6 +1386,7 @@ control.prototype.updateFg = function () {
for (var y=0;y<13;y++) { for (var y=0;y<13;y++) {
var damage = core.status.checkBlock.damage[13*x+y]; var damage = core.status.checkBlock.damage[13*x+y];
if (damage>0) { if (damage>0) {
damage = core.formatBigNumber(damage);
core.setFillStyle('fg', '#000000'); core.setFillStyle('fg', '#000000');
core.canvas.fg.fillText(damage, 32 * x + 17, 32 * (y + 1) - 13); core.canvas.fg.fillText(damage, 32 * x + 17, 32 * (y + 1) - 13);
core.canvas.fg.fillText(damage, 32 * x + 15, 32 * (y + 1) - 15); core.canvas.fg.fillText(damage, 32 * x + 15, 32 * (y + 1) - 15);
@ -1368,8 +1417,11 @@ control.prototype.doEffect = function (expression) {
} }
} }
////// 作弊 ////// ////// 开启debug模式 //////
control.prototype.debug = function() { control.prototype.debug = function() {
core.setFlag('debug', true);
core.insertAction(["\t[调试模式开启]此模式下按住Ctrl键可以穿墙并忽略一切事件。\n同时录像将失效也无法上传成绩。"]);
/*
core.setStatus('hp', 999999); core.setStatus('hp', 999999);
core.setStatus('atk', 10000); core.setStatus('atk', 10000);
core.setStatus('def', 10000); core.setStatus('def', 10000);
@ -1386,6 +1438,7 @@ control.prototype.debug = function() {
core.status.hero.flyRange.push(i); core.status.hero.flyRange.push(i);
core.updateStatusBar(); core.updateStatusBar();
core.drawTip("作弊成功"); core.drawTip("作弊成功");
*/
} }
////// 开始播放 ////// ////// 开始播放 //////
@ -1660,12 +1713,16 @@ control.prototype.replay = function () {
else if (action.indexOf('move:')==0) { else if (action.indexOf('move:')==0) {
var pos=action.substring(5).split(":"); var pos=action.substring(5).split(":");
var x=parseInt(pos[0]), y=parseInt(pos[1]); var x=parseInt(pos[0]), y=parseInt(pos[1]);
if (core.canMoveDirectly(x,y)) {
var ignoreSteps = core.canMoveDirectly(x, y);
if (ignoreSteps>0) {
core.clearMap('hero', 0, 0, 416, 416); core.clearMap('hero', 0, 0, 416, 416);
core.setHeroLoc('x', x); core.setHeroLoc('x', x);
core.setHeroLoc('y', y); core.setHeroLoc('y', y);
core.drawHero(); core.drawHero();
core.status.route.push("move:"+x+":"+y); core.status.route.push("move:"+x+":"+y);
core.status.hero.statistics.moveDirectly++;
core.status.hero.statistics.ignoreSteps+=ignoreSteps;
core.replay(); core.replay();
return; return;
} }
@ -1807,6 +1864,8 @@ control.prototype.openSettings = function (need) {
////// 自动存档 ////// ////// 自动存档 //////
control.prototype.autosave = function (removeLast) { control.prototype.autosave = function (removeLast) {
if (core.status.event.id!=null)
return;
var x=null; var x=null;
if (removeLast) if (removeLast)
x=core.status.route.pop(); x=core.status.route.pop();
@ -2061,11 +2120,17 @@ control.prototype.loadData = function (data, callback) {
////// 设置勇士属性 ////// ////// 设置勇士属性 //////
control.prototype.setStatus = function (statusName, statusVal) { control.prototype.setStatus = function (statusName, statusVal) {
core.status.hero[statusName] = statusVal; if (core.isset(core.status.hero.loc[statusName]))
core.status.hero.loc[statusName] = statusVal;
else
core.status.hero[statusName] = statusVal;
} }
////// 获得勇士属性 ////// ////// 获得勇士属性 //////
control.prototype.getStatus = function (statusName) { control.prototype.getStatus = function (statusName) {
// support status:x
if (core.isset(core.status.hero.loc[statusName]))
return core.status.hero.loc[statusName];
return core.status.hero[statusName]; return core.status.hero[statusName];
} }
@ -2129,11 +2194,10 @@ control.prototype.playBgm = function (bgm) {
core.material.bgms[core.musicStatus.playingBgm].pause(); core.material.bgms[core.musicStatus.playingBgm].pause();
} }
// 播放当前BGM // 播放当前BGM
core.musicStatus.playingBgm = bgm;
core.material.bgms[bgm].volume = core.musicStatus.volume; core.material.bgms[bgm].volume = core.musicStatus.volume;
core.material.bgms[bgm].play(); core.material.bgms[bgm].play();
core.musicStatus.playingBgm = bgm;
core.musicStatus.isPlaying = true; core.musicStatus.isPlaying = true;
} }
catch (e) { catch (e) {
console.log("无法播放BGM "+bgm); console.log("无法播放BGM "+bgm);
@ -2355,6 +2419,7 @@ control.prototype.resize = function(clientWidth, clientHeight) {
if (!core.flags.enableExperience) count--; if (!core.flags.enableExperience) count--;
if (!core.flags.enableLevelUp) count--; if (!core.flags.enableLevelUp) count--;
if (!core.flags.enableDebuff) count--; if (!core.flags.enableDebuff) count--;
if (core.isset(core.flags.enableKeys) && !core.flags.enableKeys) count--;
var statusLineHeight = BASE_LINEHEIGHT * 9 / count; var statusLineHeight = BASE_LINEHEIGHT * 9 / count;
var statusLineFontSize = DEFAULT_FONT_SIZE; var statusLineFontSize = DEFAULT_FONT_SIZE;
@ -2639,6 +2704,12 @@ control.prototype.resize = function(clientWidth, clientHeight) {
display: core.flags.enableLevelUp ? 'block': 'none' display: core.flags.enableLevelUp ? 'block': 'none'
} }
}, },
{
id: 'keyCol',
rules: {
display: !core.isset(core.flags.enableKeys)||core.flags.enableKeys?'block':'none'
}
},
{ {
'id': 'debuffCol', 'id': 'debuffCol',
rules: { rules: {

View File

@ -107,6 +107,7 @@ function core() {
// 按下键的时间:为了判定双击 // 按下键的时间:为了判定双击
'downTime': null, 'downTime': null,
'ctrlDown': false,
// 路线&回放 // 路线&回放
'route': [], 'route': [],
@ -651,6 +652,11 @@ core.prototype.getBlock = function (x, y, floorId, needEnable) {
return core.maps.getBlock(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”}的效果 ////// ////// 显示移动某块的动画,达到{“type”:”move”}的效果 //////
core.prototype.moveBlock = function(x,y,steps,time,immediateHide,callback) { core.prototype.moveBlock = function(x,y,steps,time,immediateHide,callback) {
core.maps.moveBlock(x,y,steps,time,immediateHide,callback) core.maps.moveBlock(x,y,steps,time,immediateHide,callback)
@ -883,9 +889,19 @@ core.prototype.debug = function() {
core.control.debug(); core.control.debug();
} }
////// 存档前 //////
core.prototype.beforeSaveData = function (data) {
return core.events.beforeSaveData(data);
}
////// 读档后 //////
core.prototype.afterLoadData = function (data) {
return core.events.afterLoadData(data);
}
////// 重置当前地图 ////// ////// 重置当前地图 //////
core.prototype.resetMap = function() { core.prototype.resetMap = function(floorId) {
core.maps.resetMap(); core.maps.resetMap(floorId);
} }
////// 开始播放 ////// ////// 开始播放 //////
@ -893,6 +909,11 @@ core.prototype.startReplay = function (list) {
core.control.startReplay(list); core.control.startReplay(list);
} }
////// 关闭UI窗口 //////
core.prototype.closePanel = function () {
core.ui.closePanel();
}
////// 更改播放状态 ////// ////// 更改播放状态 //////
core.prototype.triggerReplay = function () { core.prototype.triggerReplay = function () {
core.control.triggerReplay(); core.control.triggerReplay();
@ -1023,8 +1044,8 @@ core.prototype.decodeRoute = function (route) {
} }
////// 发送HTTP ////// ////// 发送HTTP //////
core.prototype.http = function (type, url, formData, success, error, header) { core.prototype.http = function (type, url, formData, success, error, mimeType, responseType) {
core.utils.http(type, url, formData, success, error, header) core.utils.http(type, url, formData, success, error, mimeType, responseType)
} }
////// 设置勇士属性 ////// ////// 设置勇士属性 //////

View File

@ -132,92 +132,63 @@ enemys.prototype.getExtraDamage = function (monster) {
return extra_damage; return extra_damage;
} }
////// 接下来若干个临界值计算 ///// ////// 接下来N个临界值和临界减伤计算 //////
enemys.prototype.nextCriticals = function (monsterId, number) { enemys.prototype.nextCriticals = function (monsterId, number) {
number = number||1; var useTurn = true; // 是否使用回合法计算临界值如果要用循环法则直接改为false。
number = number||1;
var monster = core.material.enemys[monsterId]; var monster = core.material.enemys[monsterId];
// 坚固、模仿怪物没有临界! // 坚固、模仿怪物没有临界!
if (this.hasSpecial(monster.special, 3) || this.hasSpecial(monster.special, 10)) return []; if (this.hasSpecial(monster.special, 3) || this.hasSpecial(monster.special, 10)) return [];
var info = this.getDamageInfo(monster, core.status.hero.hp, core.status.hero.atk, core.status.hero.def, core.status.hero.mdef); var info = this.getDamageInfo(monster, core.status.hero.hp, core.status.hero.atk, core.status.hero.def, core.status.hero.mdef);
if (info == null) { if (info == null) {
if (core.status.hero.atk<=monster.def) { if (core.status.hero.atk<=monster.def) {
return [(monster.def+1-core.status.hero.atk)+":?"]; return [[monster.def+1-core.status.hero.atk,'?']];
} }
return []; return [];
} }
if (info.damage <= 0) return [];
var mon_hp = info.mon_hp, hero_atk = core.status.hero.atk, mon_def = monster.def, turn = info.turn;
if (turn<=1) return [];
var list = [], pre = null; var list = [], pre = null;
var mon_hp = info.mon_hp, hero_atk = core.status.hero.atk, mon_def = monster.def, turn = info.turn;
for (var t = turn-1;t>=1;t--) { if (useTurn) { // 回合数计算法
var nextAtk = Math.ceil(mon_hp/t) + mon_def; for (var t = turn-1;t>=1;t--) {
if (nextAtk<=hero_atk) break; var nextAtk = Math.ceil(mon_hp/t) + mon_def;
if (nextAtk!=pre) { if (nextAtk<=hero_atk) break;
var nextInfo = this.getDamageInfo(monster, core.status.hero.hp, nextAtk, core.status.hero.def, core.status.hero.mdef); if (nextAtk!=pre) {
if (nextInfo==null) break; var nextInfo = this.getDamageInfo(monster, core.status.hero.hp, nextAtk, core.status.hero.def, core.status.hero.mdef);
list.push((nextAtk-hero_atk)+":"+(info.damage-nextInfo.damage)); if (nextInfo==null) break;
if (nextInfo.damage<=0) break; list.push([nextAtk-hero_atk,info.damage-nextInfo.damage]);
pre = nextAtk; pre = nextAtk;
}
if (list.length>=number)
break;
} }
if (list.length>=number)
break;
} }
else { // 暴力for循环法
pre = info.damage;
for (var atk=hero_atk+1;atk<=mon_hp+mon_def;atk++) {
var nextInfo = this.getDamageInfo(monster, core.status.hero.hp, atk, core.status.hero.def, core.status.hero.mdef);
if (nextInfo==null) break;
if (pre>nextInfo.damage) {
pre = nextInfo.damage;
list.push([atk-hero_atk, info.damage-nextInfo.damage]);
if (list.length>=number) break;
}
}
}
if (list.length==0) list.push([0,0]);
return list; return list;
} }
////// 临界值计算 ////// ////// N防减伤计算 //////
enemys.prototype.getCritical = function (monsterId) { enemys.prototype.getDefDamage = function (monsterId, k) {
var monster = core.material.enemys[monsterId]; k = k || 1;
// 坚固、模仿怪物没有临界!
if (this.hasSpecial(monster.special, 3) || this.hasSpecial(monster.special, 10)) return "???";
var info = this.getDamageInfo(monster, core.status.hero.hp, core.status.hero.atk, core.status.hero.def, core.status.hero.mdef);
if (info == null) {
if (core.status.hero.atk<=monster.def)
return monster.def+1-core.status.hero.atk;
return '???';
}
if (info.damage <= 0) return 0;
var mon_hp = info.mon_hp, hero_atk = core.status.hero.atk, mon_def = monster.def, turn = info.turn;
// turn 是勇士攻击次数
if (turn<=1) return 0; // 攻杀
// 每回合最小伤害 = ⎡怪物生命/勇士攻击次数⎤
var nextAtk = Math.ceil(mon_hp/(turn-1)) + mon_def;
if (nextAtk <= hero_atk) return 0;
return nextAtk - hero_atk;
}
////// 临界减伤计算 //////
enemys.prototype.getCriticalDamage = function (monsterId) {
var c = this.getCritical(monsterId);
if (c == '???') return '???';
if (c <= 0) return 0;
var monster = core.material.enemys[monsterId];
var last = this.calDamage(monster, core.status.hero.hp, core.status.hero.atk, core.status.hero.def, core.status.hero.mdef);
var now = this.calDamage(monster, core.status.hero.hp, core.status.hero.atk+c, core.status.hero.def, core.status.hero.mdef);
if (last == null || now==null) return '???';
return last - now;
}
////// 1防减伤计算 //////
enemys.prototype.getDefDamage = function (monsterId) {
var monster = core.material.enemys[monsterId]; var monster = core.material.enemys[monsterId];
var nowDamage = this.calDamage(monster, core.status.hero.hp, core.status.hero.atk, core.status.hero.def, core.status.hero.mdef); var nowDamage = this.calDamage(monster, core.status.hero.hp, core.status.hero.atk, core.status.hero.def, core.status.hero.mdef);
var nextDamage = this.calDamage(monster, core.status.hero.hp, core.status.hero.atk, core.status.hero.def + 1, core.status.hero.mdef); var nextDamage = this.calDamage(monster, core.status.hero.hp, core.status.hero.atk, core.status.hero.def + k, core.status.hero.mdef);
if (nowDamage == null || nextDamage ==null) return "???"; if (nowDamage == null || nextDamage ==null) return "???";
return nowDamage - nextDamage; return nowDamage - nextDamage;
} }
@ -225,6 +196,10 @@ enemys.prototype.getDefDamage = function (monsterId) {
////// 获得战斗伤害信息 ////// ////// 获得战斗伤害信息 //////
enemys.prototype.getDamageInfo = function(monster, hero_hp, hero_atk, hero_def, hero_mdef) { enemys.prototype.getDamageInfo = function(monster, hero_hp, hero_atk, hero_def, hero_mdef) {
if (typeof monster == 'string') {
monster = core.material.enemys[monster];
}
var mon_hp = monster.hp, mon_atk = monster.atk, mon_def = monster.def, mon_special = monster.special; var mon_hp = monster.hp, mon_atk = monster.atk, mon_def = monster.def, mon_special = monster.special;
hero_hp=Math.max(0, hero_hp); hero_hp=Math.max(0, hero_hp);
hero_atk=Math.max(0, hero_atk); hero_atk=Math.max(0, hero_atk);
@ -310,6 +285,10 @@ enemys.prototype.getDamageInfo = function(monster, hero_hp, hero_atk, hero_def,
////// 具体的伤害计算公式 ////// ////// 具体的伤害计算公式 //////
enemys.prototype.calDamage = function (monster, hero_hp, hero_atk, hero_def, hero_mdef) { enemys.prototype.calDamage = function (monster, hero_hp, hero_atk, hero_def, hero_mdef) {
if (typeof monster == 'string') {
monster = core.material.enemys[monsterId];
}
var info = this.getDamageInfo(monster, hero_hp, hero_atk, hero_def, hero_mdef); var info = this.getDamageInfo(monster, hero_hp, hero_atk, hero_def, hero_mdef);
if (info == null) return null; if (info == null) return null;
return info.damage; return info.damage;
@ -341,6 +320,9 @@ enemys.prototype.getCurrentEnemys = function (floorId) {
if (specialText.length>=3) specialText = "多属性..."; if (specialText.length>=3) specialText = "多属性...";
else specialText = specialText.join(" "); else specialText = specialText.join(" ");
var critical = this.nextCriticals(monsterId);
if (critical.length>0) critical=critical[0];
enemys.push({ enemys.push({
'id': monsterId, 'id': monsterId,
'name': monster.name, 'name': monster.name,
@ -352,8 +334,8 @@ enemys.prototype.getCurrentEnemys = function (floorId) {
'point': monster.point||0, // 加点 'point': monster.point||0, // 加点
'special': specialText, 'special': specialText,
'damage': this.getDamage(monsterId), 'damage': this.getDamage(monsterId),
'critical': this.getCritical(monsterId), 'critical': critical[0],
'criticalDamage': this.getCriticalDamage(monsterId), 'criticalDamage': critical[1],
'defDamage': this.getDefDamage(monsterId) 'defDamage': this.getDefDamage(monsterId)
}); });

View File

@ -228,6 +228,11 @@ events.prototype.gameOver = function (ending, fromReplay) {
core.restart(); core.restart();
}); });
} }
else if (core.hasFlag('debug')) {
core.drawText("\t[系统提示]调试模式下无法上传成绩", function () {
core.restart();
})
}
else { else {
confirmUpload(); confirmUpload();
} }
@ -349,6 +354,8 @@ events.prototype.doAction = function() {
core.events.doAction(); core.events.doAction();
break; break;
case "show": // 显示 case "show": // 显示
if (!core.isset(data.loc))
data.loc = [x,y];
if ((typeof data.loc[0] == 'number' || typeof data.loc[0] == 'string') if ((typeof data.loc[0] == 'number' || typeof data.loc[0] == 'string')
&& (typeof data.loc[1] == 'number' || typeof data.loc[1] == 'string')) && (typeof data.loc[1] == 'number' || typeof data.loc[1] == 'string'))
data.loc = [[core.calValue(data.loc[0]), core.calValue(data.loc[1])]]; data.loc = [[core.calValue(data.loc[0]), core.calValue(data.loc[1])]];
@ -405,8 +412,6 @@ events.prototype.doAction = function() {
} }
if (floorId==core.status.floorId) { if (floorId==core.status.floorId) {
core.drawMap(floorId); core.drawMap(floorId);
core.drawHero();
core.updateStatusBar();
} }
} }
this.doAction(); this.doAction();
@ -638,13 +643,7 @@ events.prototype.doAction = function() {
break; break;
case "setHeroIcon": case "setHeroIcon":
{ {
var name = "hero.png"; this.setHeroIcon(data.name);
if (core.isset(core.material.images.images[data.name]) && core.material.images.images[data.name].width==128)
name = data.name;
core.setFlag("heroIcon", name);
core.material.images.hero.src = core.material.images.images[name].src;
core.material.icons.hero.height = core.material.images.images[name].height/4;
core.drawHero();
this.doAction(); this.doAction();
break; break;
} }
@ -761,8 +760,27 @@ events.prototype.doAction = function() {
} }
break; break;
case "wait": case "wait":
if (core.status.replay.replaying) if (core.status.replay.replaying) {
core.events.doAction(); var code = core.status.replay.toReplay.shift();
if (code.indexOf("input:")==0) {
var value = parseInt(code.substring(6));
core.status.route.push("input:"+value);
if (value>=10000) {
core.setFlag('type', 1);
core.setFlag('x', parseInt((value-10000)/100));
core.setFlag('y', value%100);
}
else {
core.setFlag('type', 0);
core.setFlag('keycode', value);
}
core.events.doAction();
}
else {
core.stopReplay();
core.drawTip("录像文件出错");
}
}
break; break;
case "revisit": // 立刻重新执行该事件 case "revisit": // 立刻重新执行该事件
{ {
@ -817,7 +835,7 @@ events.prototype.getNextItem = function() {
////// 获得某个物品 ////// ////// 获得某个物品 //////
events.prototype.getItem = function (itemId, itemNum, itemX, itemY, callback) { events.prototype.getItem = function (itemId, itemNum, itemX, itemY, callback) {
// core.getItemAnimate(itemId, itemNum, itemX, itemY); // core.getItemAnimate(itemId, itemNum, itemX, itemY);
core.playSound('item.ogg'); core.playSound('item.mp3');
var itemCls = core.material.items[itemId].cls; var itemCls = core.material.items[itemId].cls;
core.items.getItemEffect(itemId, itemNum); core.items.getItemEffect(itemId, itemNum);
core.removeBlock(itemX, itemY); core.removeBlock(itemX, itemY);
@ -867,7 +885,7 @@ events.prototype.openDoor = function (id, x, y, needKey, callback) {
} }
// open // open
core.playSound("door.ogg"); core.playSound("door.mp3");
var state = 0; var state = 0;
var doorId = id; var doorId = id;
if (!(doorId.substring(doorId.length-4)=="Door")) { if (!(doorId.substring(doorId.length-4)=="Door")) {
@ -921,11 +939,11 @@ events.prototype.battle = function (id, x, y, force, callback) {
else { else {
if (core.flags.equipment && core.getFlag('sword', 'sword0')!='sword0') { if (core.flags.equipment && core.getFlag('sword', 'sword0')!='sword0') {
core.playSound('zone.ogg'); core.playSound('zone.mp3');
core.drawAnimate('sword', x, y); core.drawAnimate('sword', x, y);
} }
else { else {
core.playSound('attack.ogg'); core.playSound('attack.mp3');
core.drawAnimate('hand', x, y); core.drawAnimate('hand', x, y);
} }
@ -1012,10 +1030,10 @@ events.prototype.changeFloor = function (floorId, stair, heroLoc, time, callback
} }
} }
if (core.status.maps[floorId].canFlyTo && core.status.hero.flyRange.indexOf(floorId)<0) { if (core.status.maps[floorId].canFlyTo && core.status.hero.flyRange.indexOf(floorId)<0) {
if (core.floorIds.indexOf(floorId)>core.floorIds.indexOf(core.status.floorId)) core.status.hero.flyRange.push(floorId);
core.status.hero.flyRange.push(floorId); core.status.hero.flyRange.sort(function (a, b) {
else return core.floorIds.indexOf(a) - core.floorIds.indexOf(b);
core.status.hero.flyRange.unshift(floorId); })
} }
window.setTimeout(function () { window.setTimeout(function () {
@ -1073,29 +1091,27 @@ events.prototype.changeFloor = function (floorId, stair, heroLoc, time, callback
}) })
} }
core.drawMap(floorId, function () { core.drawMap(floorId, function () {
setTimeout(function() { if (core.isset(heroLoc.direction))
if (core.isset(heroLoc.direction)) core.setHeroLoc('direction', heroLoc.direction);
core.setHeroLoc('direction', heroLoc.direction); core.setHeroLoc('x', heroLoc.x);
core.setHeroLoc('x', heroLoc.x); core.setHeroLoc('y', heroLoc.y);
core.setHeroLoc('y', heroLoc.y); core.clearMap('hero', 0, 0, 416, 416);
core.drawHero(); core.drawHero();
core.updateStatusBar();
var changed = function () { var changed = function () {
core.unLockControl(); core.unLockControl();
core.status.replay.animate=false; core.status.replay.animate=false;
core.events.afterChangeFloor(floorId); core.events.afterChangeFloor(floorId);
if (core.isset(callback)) callback(); if (core.isset(callback)) callback();
} }
if (displayAnimate) { if (displayAnimate) {
core.hide(core.dom.floorMsgGroup, time/4, function () { core.hide(core.dom.floorMsgGroup, time/4, function () {
changed();
});
}
else {
changed(); changed();
} });
}, 25) }
else {
changed();
}
}); });
} }
core.playSound('floor.mp3'); core.playSound('floor.mp3');
@ -1234,6 +1250,16 @@ events.prototype.canUseQuickShop = function(shopId) {
return null; return null;
} }
////// 设置角色行走图 //////
events.prototype.setHeroIcon = function (name) {
if (core.isset(core.material.images.images[name]) && core.material.images.images[name].width==128) {
core.setFlag("heroIcon", name);
core.material.images.hero.src = core.material.images.images[name].src;
core.material.icons.hero.height = core.material.images.images[name].height/4;
core.drawHero();
}
}
////// 检查升级事件 ////// ////// 检查升级事件 //////
events.prototype.checkLvUp = function () { events.prototype.checkLvUp = function () {
if (!core.flags.enableLevelUp || core.status.hero.lv>=core.firstData.levelUp.length) return; if (!core.flags.enableLevelUp || core.status.hero.lv>=core.firstData.levelUp.length) return;
@ -1325,7 +1351,7 @@ events.prototype.passNet = function (data) {
if (data.event.id=='weakNet') { // 衰网 if (data.event.id=='weakNet') { // 衰网
if (core.hasFlag('weak')) return; if (core.hasFlag('weak')) return;
core.setFlag('weak', true); core.setFlag('weak', true);
var weakValue = core.status.weakValue; var weakValue = core.values.weakValue;
var weakAtk = weakValue>=1?weakValue:Math.floor(weakValue*core.status.hero.atk); var weakAtk = weakValue>=1?weakValue:Math.floor(weakValue*core.status.hero.atk);
var weakDef = weakValue>=1?weakValue:Math.floor(weakValue*core.status.hero.def); var weakDef = weakValue>=1?weakValue:Math.floor(weakValue*core.status.hero.def);
core.setFlag('weakAtk', weakAtk); core.setFlag('weakAtk', weakAtk);

View File

@ -23,7 +23,9 @@ items.prototype.getItemEffect = function(itemId, itemNum) {
// 消耗品 // 消耗品
if (itemCls === 'items') { if (itemCls === 'items') {
var ratio = parseInt(core.floors[core.status.floorId].item_ratio) || 1; var ratio = parseInt(core.floors[core.status.floorId].item_ratio) || 1;
var curr_hp = core.status.hero.hp;
if (itemId in this.itemEffect)eval(this.itemEffect[itemId]); if (itemId in this.itemEffect)eval(this.itemEffect[itemId]);
core.status.hero.statistics.hp += core.status.hero.hp - curr_hp;
} }
else { else {
core.addItem(itemId, itemNum); core.addItem(itemId, itemNum);

View File

@ -204,12 +204,10 @@ loader.prototype.loadMusic = function () {
core.sounds.forEach(function (t) { core.sounds.forEach(function (t) {
if (core.musicStatus.audioContext != null) { if (core.musicStatus.audioContext != null) {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'project/sounds/'+t, true); core.http('GET', 'project/sounds/'+t, null, function (data) {
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) { //下载完成
try { try {
core.musicStatus.audioContext.decodeAudioData(this.response, function (buffer) { core.musicStatus.audioContext.decodeAudioData(data, function (buffer) {
core.material.sounds[t] = buffer; core.material.sounds[t] = buffer;
}, function (e) { }, function (e) {
console.log(e); console.log(e);
@ -220,17 +218,10 @@ loader.prototype.loadMusic = function () {
console.log(ee); console.log(ee);
core.material.sounds[t] = null; core.material.sounds[t] = null;
} }
}; }, function () {
xhr.ontimeout = function(e) {
console.log(e); console.log(e);
core.material.sounds[t] = null; core.material.sounds[t] = null;
} }, null, 'arraybuffer');
xhr.onerror = function(e) {
console.log(e);
core.material.sounds[t] = null;
}
xhr.send();
} }
else { else {
var music = new Audio(); var music = new Audio();

View File

@ -255,20 +255,20 @@ maps.prototype.canMoveHero = function(x,y,direction,floorId) {
////// 能否瞬间移动 ////// ////// 能否瞬间移动 //////
maps.prototype.canMoveDirectly = function (destX,destY) { maps.prototype.canMoveDirectly = function (destX,destY) {
if (!core.flags.enableMoveDirectly) return false; if (!core.flags.enableMoveDirectly) return -1;
// 中毒状态:不能 // 中毒状态:不能
if (core.hasFlag('poison')) return false; if (core.hasFlag('poison')) return -1;
var fromX = core.getHeroLoc('x'), fromY = core.getHeroLoc('y'); var fromX = core.getHeroLoc('x'), fromY = core.getHeroLoc('y');
if (fromX==destX&&fromY==destY) return false; if (fromX==destX&&fromY==destY) return -1;
if (core.getBlock(fromX,fromY)!=null||core.status.checkBlock.damage[13*fromX+fromY]>0) if (core.getBlock(fromX,fromY)!=null||core.status.checkBlock.damage[13*fromX+fromY]>0)
return false; return -1;
// BFS // BFS
var visited=[], queue=[]; var visited=[], queue=[];
visited[13*fromX+fromY]=true; visited[13*fromX+fromY]=0;
queue.push(13*fromX+fromY); queue.push(13*fromX+fromY);
var directions = [[-1,0],[1,0],[0,1],[0,-1]]; var directions = [[-1,0],[1,0],[0,1],[0,-1]];
@ -278,12 +278,12 @@ maps.prototype.canMoveDirectly = function (destX,destY) {
for (var dir in directions) { for (var dir in directions) {
var nx=nowX+directions[dir][0], ny=nowY+directions[dir][1]; var nx=nowX+directions[dir][0], ny=nowY+directions[dir][1];
if (nx<0||nx>=13||ny<0||ny>=13||visited[13*nx+ny]||core.getBlock(nx,ny)!=null||core.status.checkBlock.damage[13*nx+ny]>0) continue; if (nx<0||nx>=13||ny<0||ny>=13||visited[13*nx+ny]||core.getBlock(nx,ny)!=null||core.status.checkBlock.damage[13*nx+ny]>0) continue;
if (nx==destX&&ny==destY) return true; visited[13*nx+ny]=visited[13*nowX+nowY]+1;
visited[13*nx+ny]=true; if (nx==destX&&ny==destY) return visited[13*nx+ny];
queue.push(13*nx+ny); queue.push(13*nx+ny);
} }
} }
return false; return -1;
} }
maps.prototype.drawBlock = function (block, animate, dx, dy) { maps.prototype.drawBlock = function (block, animate, dx, dy) {
@ -389,8 +389,10 @@ maps.prototype.drawMap = function (mapName, callback) {
} }
} else { } else {
drawEvent(); drawEvent();
core.setGlobalAnimate(core.values.animateSpeed);
core.drawHero();
core.updateStatusBar();
} }
core.setGlobalAnimate(core.values.animateSpeed);
if (core.isset(callback)) if (core.isset(callback))
callback(); callback();
} }
@ -398,7 +400,7 @@ maps.prototype.drawMap = function (mapName, callback) {
////// 绘制Autotile ////// ////// 绘制Autotile //////
maps.prototype.drawAutotile = function(ctx, mapArr, block, size, left, top){ maps.prototype.drawAutotile = function(ctx, mapArr, block, size, left, top){
var indexArrs = [ //16种组合的图块索引数组; // 将autotile分割成48块16*16的小块; 数组索引即对应各个小块 var indexArrs = [ //16种组合的图块索引数组; // 将autotile分割成48块16*16的小块; 数组索引即对应各个小块
// +----+----+----+----+----+----+ // +----+----+----+----+----+----+
[10, 9, 4, 3 ], //0 bin:0000 | 1 | 2 | 3 | 4 | 5 | 6 | [10, 9, 4, 3 ], //0 bin:0000 | 1 | 2 | 3 | 4 | 5 | 6 |
[10, 9, 4, 13], //1 bin:0001 +----+----+----+----+----+----+ [10, 9, 4, 13], //1 bin:0001 +----+----+----+----+----+----+
[10, 9, 18, 3 ], //2 bin:0010 | 7 | 8 | 9 | 10 | 11 | 12 | [10, 9, 18, 3 ], //2 bin:0010 | 7 | 8 | 9 | 10 | 11 | 12 |
@ -537,6 +539,14 @@ maps.prototype.getBlock = function (x, y, floorId, needEnable) {
return null; 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”}的效果 ////// ////// 显示移动某块的动画,达到{“type”:”move”}的效果 //////
maps.prototype.moveBlock = function(x,y,steps,time,immediateHide,callback) { maps.prototype.moveBlock = function(x,y,steps,time,immediateHide,callback) {
time = time || 500; time = time || 500;
@ -729,7 +739,7 @@ maps.prototype.removeBlock = function (x, y, floorId) {
// 删除Index // 删除Index
core.removeBlockById(index, floorId); core.removeBlockById(index, floorId);
core.updateFg(); core.updateStatusBar();
} }
////// 根据block的索引删除该块 ////// ////// 根据block的索引删除该块 //////
@ -888,11 +898,15 @@ maps.prototype.drawAnimate = function (name, x, y, callback) {
}, 50); }, 50);
} }
maps.prototype.resetMap = function() { maps.prototype.resetMap = function(floorId) {
var floorId = core.status.floorId; var floorId = floorId||core.status.floorId;
core.status.maps[floorId] = this.loadFloor(floorId); core.status.maps[floorId] = this.loadFloor(floorId);
this.drawMap(floorId, function() { if (floorId==core.status.floorId) {
core.drawHero(); this.drawMap(floorId, function () {
core.updateStatusBar(); core.drawTip("地图重置成功");
}) })
}
else {
core.drawTip(floorId+"地图重置成功");
}
} }

View File

@ -668,8 +668,8 @@ ui.prototype.drawChoices = function(content, choices) {
if (choices.length>0) { if (choices.length>0) {
if (!core.isset(core.status.event.selection)) core.status.event.selection=0; if (!core.isset(core.status.event.selection)) core.status.event.selection=0;
if (core.status.event.selection<0) core.status.event.selection=0; while (core.status.event.selection<0) core.status.event.selection+=choices.length;
if (core.status.event.selection>=choices.length) core.status.event.selection=choices.length-1; while (core.status.event.selection>=choices.length) core.status.event.selection-=choices.length;
var len = core.canvas.ui.measureText(core.replaceText(choices[core.status.event.selection].text || choices[core.status.event.selection])).width; var len = core.canvas.ui.measureText(core.replaceText(choices[core.status.event.selection].text || choices[core.status.event.selection])).width;
core.strokeRect('ui', 208-len/2-5, choice_top + 32 * core.status.event.selection - 20, len+10, 28, "#FFD700", 2); core.strokeRect('ui', 208-len/2-5, choice_top + 32 * core.status.event.selection - 20, len+10, 28, "#FFD700", 2);
} }
@ -981,7 +981,7 @@ ui.prototype.drawBattleAnimate = function(monsterId, callback) {
core.fillText("ui", "S", right_start-8, 208+15, "#FFFFFF", "italic bold 40px Verdana"); core.fillText("ui", "S", right_start-8, 208+15, "#FFFFFF", "italic bold 40px Verdana");
var battleInterval = setInterval(function() { var battleInterval = setInterval(function() {
core.playSound("attack.ogg"); core.playSound("attack.mp3");
if (turn==0) { if (turn==0) {
// 勇士攻击 // 勇士攻击
@ -1341,7 +1341,11 @@ ui.prototype.drawBookDetail = function (index) {
hints.push("该怪物无特殊属性。"); hints.push("该怪物无特殊属性。");
hints.push(""); hints.push("");
hints.push("临界表:"+JSON.stringify(core.enemys.nextCriticals(enemyId,10))) var criticals = core.enemys.nextCriticals(enemyId, 10).map(function (v) {
return v[0]+":"+v[1];
});
while (criticals[0]=='0:0') criticals.shift();
hints.push("临界表:"+JSON.stringify(criticals))
var content=hints.join("\n"); var content=hints.join("\n");
@ -1513,8 +1517,19 @@ ui.prototype.drawToolbox = function(index) {
if (core.isset(selectId)) { if (core.isset(selectId)) {
var item=core.material.items[selectId]; var item=core.material.items[selectId];
core.fillText('ui', item.name, 10, 32, '#FFD700', "bold 20px Verdana") core.fillText('ui', item.name, 10, 32, '#FFD700', "bold 20px Verdana")
core.fillText('ui', item.text||"该道具暂无描述。", 10, 62, '#FFFFFF', '17px Verdana');
core.fillText('ui', '<继续点击该道具即可进行使用>', 10, 89, '#CCCCCC', '14px Verdana'); var text = item.text||"该道具暂无描述。";
var lines = core.splitLines('ui', text, 406, '17px Verdana');
core.fillText('ui', lines[0], 10, 62, '#FFFFFF', '17px Verdana');
if (lines.length==1) {
core.fillText('ui', '<继续点击该道具即可进行使用>', 10, 89, '#CCCCCC', '14px Verdana');
}
else {
var leftText = text.substring(lines[0].length);
core.fillText('ui', leftText, 10, 89, '#FFFFFF', '17px Verdana');
}
} }
core.canvas.ui.textAlign = 'right'; core.canvas.ui.textAlign = 'right';
@ -1734,6 +1749,167 @@ ui.prototype.drawKeyBoard = function () {
core.fillText("ui", "返回游戏", 416-80, offset-3, '#FFFFFF', 'bold 15px Verdana'); core.fillText("ui", "返回游戏", 416-80, offset-3, '#FFFFFF', 'bold 15px Verdana');
} }
////// 绘制“数据统计”界面 //////
ui.prototype.drawStatistics = function () {
// 数据统计要统计如下方面:
// 1. 当前全塔剩余下的怪物数量,总金币数,总经验数,总加点数
// 2. 当前全塔剩余的黄蓝红铁门数量,和对应的钥匙数量
// 3. 当前全塔剩余的三种宝石数量,血瓶数量,装备数量;总共增加的攻防生命值
// 4. 当前层的上述信息
// 5. 当前已走的步数;瞬间移动的步数,瞬间移动的次数(和少走的步数);游戏时长
// 6. 当前已恢复的生命值;当前总伤害、战斗伤害、阻激夹域血网伤害、中毒伤害。
var total = {
'monster': {
'count': 0, 'money': 0, 'experience': 0, 'point': 0,
},
'count': {
'yellowDoor': 0, 'blueDoor': 0, 'redDoor': 0, 'steelDoor': 0,
'yellowKey': 0, 'blueKey': 0, 'redKey': 0, 'steelKey': 0,
'redJewel': 0, 'blueJewel': 0, 'greenJewel': 0, 'yellowJewel': 0,
'redPotion': 0, 'bluePotion': 0, 'greenPotion': 0, 'yellowPotion': 0, 'superPotion': 0,
'pickaxe': 0, 'bomb': 0, 'centerFly': 0,
'poisonWine': 0, 'weakWine': 0, 'curseWine': 0, 'superWine': 0,
'sword1': 0, 'sword2': 0, 'sword3': 0, 'sword4': 0, 'sword5': 0,
'shield1': 0, 'shield2': 0, 'shield3': 0, 'shield4': 0, 'shield5': 0,
},
'add': {
'hp': 0, 'atk': 0, 'def': 0, 'mdef': 0
}
};
var current = core.clone(total);
core.floorIds.forEach(function (floorId) {
var floor=core.floors[floorId];
var blocks=core.status.maps[floorId].blocks;
// 隐藏层不给看
if (floor.cannotViewMap && floorId!=core.status.floorId) return;
blocks.forEach(function (block) {
if (!core.isset(block.event) || (core.isset(block.enable) && !block.enable))
return;
var event = block.event;
if (event.cls.indexOf("enemy")==0) {
var enemyId = event.id, enemy = core.material.enemys[enemyId];
total.monster.money+=enemy.money||0;
total.monster.experience+=enemy.experience||0;
total.monster.point+=enemy.point||0;
total.monster.count++;
if (floorId==core.status.floorId) {
current.monster.money+=enemy.money||0;
current.monster.experience+=enemy.experience||0;
current.monster.point+=enemy.point||0;
current.monster.count++;
}
}
else {
var id = event.id;
var temp = core.clone(core.status.hero);
if (core.isset(total.count[id])) {
var hp=0, atk=0, def=0, mdef=0;
if (core.isset(core.material.items[id]) && core.material.items[id].cls=='items' && id!='superPotion') {
var ratio = floor.item_ratio||1;
if (core.isset(core.items.itemEffect[id])) {
eval(core.items.itemEffect[id]);
}
hp = core.status.hero.hp - temp.hp;
atk = core.status.hero.atk - temp.atk;
def = core.status.hero.def - temp.def;
mdef = core.status.hero.mdef - temp.mdef;
}
else {
if (id.indexOf('sword')==0 && core.isset(core.values[id])) {
var x = core.values[id];
if (typeof x == 'number') x = {'atk': x};
atk += x.atk||0;
def += x.def||0;
mdef += x.mdef||0;
}
if (id.indexOf('shield')==0 && core.isset(core.values[id])) {
var x = core.values[id];
if (typeof x == 'number') x = {'def': x};
atk += x.atk||0;
def += x.def||0;
mdef += x.mdef||0;
}
}
core.status.hero = core.clone(temp);
total.count[id]++;
total.add.hp+=hp;
total.add.atk+=atk;
total.add.def+=def;
total.add.mdef+=mdef;
if (floorId==core.status.floorId) {
current.count[id]++;
current.add.hp+=hp;
current.add.atk+=atk;
current.add.def+=def;
current.add.mdef+=mdef;
}
}
}
})
})
var getText = function (type, data) {
var text = type+"地图中:\n";
text += "共有怪物"+data.monster.count+"个";
if (core.flags.enableMoney) text+=",总金币数"+data.monster.money;
if (core.flags.enableExperience) text+=",总经验数"+data.monster.experience;
if (core.flags.enableAddPoint) text+=",总加点数"+data.monster.point;
text+="。\n\n";
Object.keys(data.count).forEach(function (key) {
var value=data.count[key];
if (value>0) {
var name="";
if (key=='yellowDoor') name="黄门";
else if (key=='blueDoor') name="蓝门";
else if (key=='redDoor') name="红门";
else if (key=='steelDoor') name="铁门";
else name=core.material.items[key].name;
if (core.isset(name)) {
text+=name+value+"个;";
}
}
})
text+="\n\n";
text+="共加生命值"+core.formatBigNumber(data.add.hp)+"点,攻击"
+core.formatBigNumber(data.add.atk)+"点,防御"
+core.formatBigNumber(data.add.def)+"点,魔防"
+core.formatBigNumber(data.add.mdef)+"点。";
return text;
}
var formatTime = function (time) {
return core.setTwoDigits(parseInt(time/3600000))
+":"+core.setTwoDigits(parseInt(time/60000)%60)
+":"+core.setTwoDigits(parseInt(time/1000)%60);
}
var statistics = core.status.hero.statistics;
core.drawText([
getText("全塔", total),
getText("当前", current),
"当前总步数:"+core.status.hero.steps+",游戏时长:"+formatTime(statistics.totalTime)
+"。\n瞬间移动次数"+statistics.moveDirectly+",共计少走"+statistics.ignoreSteps+"步。"
+"\n\n总计通过血瓶恢复生命值为"+core.formatBigNumber(statistics.hp)+"点。\n\n"
+"总计受到的伤害为"+core.formatBigNumber(statistics.battleDamage+statistics.poisonDamage+statistics.extraDamage)
+",其中战斗伤害"+core.formatBigNumber(statistics.battleDamage)+"点"
+(core.flags.enableDebuff?(",中毒伤害"+core.formatBigNumber(statistics.poisonDamage)+"点"):"")
+",领域/夹击/阻击/血网伤害"+core.formatBigNumber(statistics.extraDamage)+"点。",
"\t[说明]1. 地图数据统计的效果仅模拟当前立刻获得该道具的效果。\n2. 不会计算“不可被浏览地图”的隐藏层的数据。\n" +
"3. 不会计算任何通过事件得到的道具(显示事件、改变图块、或直接增加道具等)。\n"+
"4. 在自定义道具例如其他宝石需在ui.js的drawStatistics中注册不然不会进行统计。\n"+
"5. 所有统计信息仅供参考,如有错误,概不负责。"
])
}
////// 绘制“关于”界面 ////// ////// 绘制“关于”界面 //////
ui.prototype.drawAbout = function () { ui.prototype.drawAbout = function () {
return this.uidata.drawAbout(); return this.uidata.drawAbout();

View File

@ -590,11 +590,13 @@ utils.prototype.hide = function (obj, speed, callback) {
}, speed); }, speed);
} }
utils.prototype.http = function (type, url, formData, success, error, mimeType) { utils.prototype.http = function (type, url, formData, success, error, mimeType, responseType) {
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();
xhr.open(type, url, true); xhr.open(type, url, true);
if (core.isset(mimeType)) if (core.isset(mimeType))
xhr.overrideMimeType(mimeType); xhr.overrideMimeType(mimeType);
if (core.isset(responseType))
xhr.responseType = responseType;
xhr.onload = function(e) { xhr.onload = function(e) {
if (xhr.status==200) { if (xhr.status==200) {
if (core.isset(success)) { if (core.isset(success)) {

31
main.js
View File

@ -57,6 +57,7 @@ function main() {
'moneyCol': document.getElementById('moneyCol'), 'moneyCol': document.getElementById('moneyCol'),
'expCol': document.getElementById('expCol'), 'expCol': document.getElementById('expCol'),
'upCol': document.getElementById('upCol'), 'upCol': document.getElementById('upCol'),
'keyCol': document.getElementById('keyCol'),
'debuffCol': document.getElementById('debuffCol'), 'debuffCol': document.getElementById('debuffCol'),
'hard': document.getElementById('hard'), 'hard': document.getElementById('hard'),
}; };
@ -457,6 +458,15 @@ main.statusBar.image.settings.onclick = function () {
main.dom.playGame.onclick = function () { main.dom.playGame.onclick = function () {
main.dom.startButtons.style.display='none'; main.dom.startButtons.style.display='none';
if (main.core.isset(main.core.musicStatus) && main.core.musicStatus.startDirectly
&& main.core.musicStatus.bgmStatus) {
if (main.core.musicStatus.playingBgm==null
|| core.material.bgms[main.core.musicStatus.playingBgm].paused) {
main.core.musicStatus.playingBgm=null;
main.core.playBgm(main.core.bgms[0]);
}
}
if (main.core.isset(main.core.flags.startDirectly) && main.core.flags.startDirectly) { if (main.core.isset(main.core.flags.startDirectly) && main.core.flags.startDirectly) {
core.events.startGame(""); core.events.startGame("");
} }
@ -467,12 +477,31 @@ main.dom.playGame.onclick = function () {
////// 点击“载入游戏”时 ////// ////// 点击“载入游戏”时 //////
main.dom.loadGame.onclick = function() { main.dom.loadGame.onclick = function() {
if (main.core.isset(main.core.musicStatus) && main.core.musicStatus.startDirectly
&& main.core.musicStatus.bgmStatus) {
if (main.core.musicStatus.playingBgm==null
|| core.material.bgms[main.core.musicStatus.playingBgm].paused) {
main.core.musicStatus.playingBgm=null;
main.core.playBgm(main.core.bgms[0]);
}
}
main.core.load(); main.core.load();
} }
////// 点击“录像回放”时 ////// ////// 点击“录像回放”时 //////
main.dom.replayGame.onclick = function () { main.dom.replayGame.onclick = function () {
if (main.core.isset(main.core.musicStatus) && main.core.musicStatus.startDirectly
&& main.core.musicStatus.bgmStatus) {
if (main.core.musicStatus.playingBgm==null
|| core.material.bgms[main.core.musicStatus.playingBgm].paused) {
main.core.musicStatus.playingBgm=null;
main.core.playBgm(main.core.bgms[0]);
}
}
core.readFile(function (obj) { core.readFile(function (obj) {
if (obj.name!=core.firstData.name) { if (obj.name!=core.firstData.name) {
alert("存档和游戏不一致!"); alert("存档和游戏不一致!");
@ -490,9 +519,9 @@ main.dom.replayGame.onclick = function () {
core.dom.startPanel.style.display = 'none'; core.dom.startPanel.style.display = 'none';
core.resetStatus(core.firstData.hero, obj.hard, core.firstData.floorId, null, core.initStatus.maps); core.resetStatus(core.firstData.hero, obj.hard, core.firstData.floorId, null, core.initStatus.maps);
core.events.setInitData(obj.hard);
core.setFlag('seed', obj.seed); core.setFlag('seed', obj.seed);
core.setFlag('rand', obj.seed); core.setFlag('rand', obj.seed);
core.events.setInitData(obj.hard);
core.changeFloor(core.status.floorId, null, core.firstData.hero.loc, null, function() { core.changeFloor(core.status.floorId, null, core.firstData.hero.loc, null, function() {
core.startReplay(core.decodeRoute(obj.route)); core.startReplay(core.decodeRoute(obj.route));
}, true); }, true);

View File

@ -14,7 +14,7 @@ data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
'bgm.mp3' 'bgm.mp3'
], ],
"sounds" : [ "sounds" : [
'floor.mp3', 'attack.ogg', 'door.ogg', 'item.ogg', 'zone.ogg' 'floor.mp3', 'attack.mp3', 'door.mp3', 'item.mp3', 'zone.mp3'
], ],
"startBackground" : "bg.jpg", "startBackground" : "bg.jpg",
"startLogoStyle" : "color: black", "startLogoStyle" : "color: black",
@ -49,11 +49,7 @@ data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
}, },
"flyRange": [], "flyRange": [],
"loc": {"direction": "up", "x": 6, "y": 10}, "loc": {"direction": "up", "x": 6, "y": 10},
"flags": { "flags": {},
"poison": false,
"weak": false,
"curse": false,
},
"steps": 0, "steps": 0,
}, },
"startText": [ "startText": [
@ -144,6 +140,7 @@ data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
"enableMoney": true, "enableMoney": true,
"enableExperience": false, "enableExperience": false,
"enableLevelUp": false, "enableLevelUp": false,
"enableKeys": true,
"enableDebuff": false, "enableDebuff": false,
"flyNearStair": true, "flyNearStair": true,
"pickaxeFourDirections": false, "pickaxeFourDirections": false,

View File

@ -56,7 +56,7 @@ main.floors.sample1 =
"\t[redKing]欢迎来到魔塔,你是第一百位挑战者。\n若你能打败我所有的手下我就与你一对一的决斗。\n现在你必须接受我的安排。", "\t[redKing]欢迎来到魔塔,你是第一百位挑战者。\n若你能打败我所有的手下我就与你一对一的决斗。\n现在你必须接受我的安排。",
{"type": "show", "loc": [[1,6],[0,7],[1,8],[2,7]], "time": 500}, // 显示四个白衣武士每个动画效果500ms {"type": "show", "loc": [[1,6],[0,7],[1,8],[2,7]], "time": 500}, // 显示四个白衣武士每个动画效果500ms
"\t[hero]什么?", "\t[hero]什么?",
{"type": "playSound", "name": "attack.ogg"}, // 播放战斗音频 {"type": "playSound", "name": "attack.mp3"}, // 播放战斗音频
{"type": "setValue", "name": "status:atk", "value": "status:atk/10"}, // 勇士的攻防变成原来的十分之一 {"type": "setValue", "name": "status:atk", "value": "status:atk/10"}, // 勇士的攻防变成原来的十分之一
{"type": "setValue", "name": "status:def", "value": "status:def/10"}, {"type": "setValue", "name": "status:def", "value": "status:def/10"},
{"type": "hide", "loc": [[1,6],[0,7],[2,7],[1,8]]}, // 直接隐藏四个白衣武士,没有动画效果 {"type": "hide", "loc": [[1,6],[0,7],[2,7],[1,8]]}, // 直接隐藏四个白衣武士,没有动画效果

View File

@ -36,22 +36,22 @@ main.floors.sample2 =
"6,11": {"enable": false}, // 下楼梯口的机关门,初始处于关闭状态 "6,11": {"enable": false}, // 下楼梯口的机关门,初始处于关闭状态
"6,10": [ // 进入陷阱后关门 "6,10": [ // 进入陷阱后关门
{"type": "playSound", "name": "door.ogg"}, {"type": "playSound", "name": "door.mp3"},
{"type": "show", "loc": [6,11]}, // 显示机关门 {"type": "show", "loc": [6,11]}, // 显示机关门
{"type": "hide"}, // 隐藏该事件 {"type": "hide"}, // 隐藏该事件
{"type": "trigger", "loc": [6,7]}, // 直接引发"6,7"处的事件,即下面的杰克 {"type": "trigger", "loc": [6,7]}, // 直接引发"6,7"处的事件,即下面的杰克
// 请再次注意"trigger"会立刻结束当前事件,因此"type":"hide"需要在trigger前调用 // 请再次注意"trigger"会立刻结束当前事件,因此"type":"hide"需要在trigger前调用
], ],
"6,7": [ // 杰克事件 "6,7": [ // 杰克事件
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]杰克,你究竟是什么人?", "\t[hero]杰克,你究竟是什么人?",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[杰克,thief]……", "\t[杰克,thief]……",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]我们……是朋友对吧?\n是朋友就应该相互信任对吧", "\t[hero]我们……是朋友对吧?\n是朋友就应该相互信任对吧",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[杰克,thief]……事到如今也没有什么好隐瞒的了。", "\t[杰克,thief]……事到如今也没有什么好隐瞒的了。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[杰克,thief]没错,我就是这一切的背后主谋。", "\t[杰克,thief]没错,我就是这一切的背后主谋。",
{"type": "move", "steps": [ // 移动到黑暗大法师的位置使用move会自动调用hide进行隐藏无需再手动调用 {"type": "move", "steps": [ // 移动到黑暗大法师的位置使用move会自动调用hide进行隐藏无需再手动调用
{"direction": "up", "value": 3} {"direction": "up", "value": 3}
@ -59,105 +59,105 @@ main.floors.sample2 =
{"type": "show", "loc": [6,4], "time": 1000}, // 显示黑暗大法师 {"type": "show", "loc": [6,4], "time": 1000}, // 显示黑暗大法师
{"type": "sleep", "time": 500}, // 等待500毫秒 {"type": "sleep", "time": 500}, // 等待500毫秒
// 下面是黑暗大法师的事件 // 下面是黑暗大法师的事件
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]我的真名为——黑暗大法师,第四区域的头目。", "\t[blackMagician]我的真名为——黑暗大法师,第四区域的头目。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]呵呵,不知道为什么,我竟然对事情走到现在这一步毫不感觉意外。", "\t[hero]呵呵,不知道为什么,我竟然对事情走到现在这一步毫不感觉意外。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]以杰克的名义利用了你这么久,真是抱歉啊。", "\t[blackMagician]以杰克的名义利用了你这么久,真是抱歉啊。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]真正的杰克现在在哪里?", "\t[hero]真正的杰克现在在哪里?",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]盗贼杰克这个人类从未存在过,他只是我用来接近你的一副皮囊而已。", "\t[blackMagician]盗贼杰克这个人类从未存在过,他只是我用来接近你的一副皮囊而已。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]……这样啊,呵呵。", "\t[hero]……这样啊,呵呵。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]为什么你看上去丝毫不生气?", "\t[blackMagician]为什么你看上去丝毫不生气?",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]多亏了鬼帝,我现在的脾气好得连我自己都害怕。", "\t[hero]多亏了鬼帝,我现在的脾气好得连我自己都害怕。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]说起来我还得好好感谢你呢,如果没有杰克……你的帮助,我早就死在第一区域了。", "\t[hero]说起来我还得好好感谢你呢,如果没有杰克……你的帮助,我早就死在第一区域了。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]不论你的目的如何,你的所作所为都是对我有利的。不是吗?", "\t[hero]不论你的目的如何,你的所作所为都是对我有利的。不是吗?",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]能够如此淡定的面对背叛,看来跟五年前相比,你确实成长了很多啊。", "\t[blackMagician]能够如此淡定的面对背叛,看来跟五年前相比,你确实成长了很多啊。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]五年前?……黑暗大法师,在这之前,我们好像素未谋面吧?", "\t[hero]五年前?……黑暗大法师,在这之前,我们好像素未谋面吧?",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]五年前那场屠城你应该这一生都不会忘记吧。", "\t[blackMagician]五年前那场屠城你应该这一生都不会忘记吧。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]很不巧,那场屠城的主谋,也是我。", "\t[blackMagician]很不巧,那场屠城的主谋,也是我。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]……", "\t[hero]……",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]这么说,击中我双亲的那道紫色闪电,也就是你释放的吧……", "\t[hero]这么说,击中我双亲的那道紫色闪电,也就是你释放的吧……",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]你的双亲?这种事情我怎么可能会记得?\n你难道在踩死蚂蚁的时候还会一只只记下他们的样子吗", "\t[blackMagician]你的双亲?这种事情我怎么可能会记得?\n你难道在踩死蚂蚁的时候还会一只只记下他们的样子吗",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]老 子 要 你 的 命", "\t[hero]老 子 要 你 的 命",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]你应该对我心怀感激才对,如果不是那时的我看出了你隐藏的稀有勇者体质,你绝对不可能活到今天。", "\t[blackMagician]你应该对我心怀感激才对,如果不是那时的我看出了你隐藏的稀有勇者体质,你绝对不可能活到今天。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]在暗中动手脚让你通过勇者选拔的人也是我,我一直一直在暗中引导你走到今天这一步。", "\t[blackMagician]在暗中动手脚让你通过勇者选拔的人也是我,我一直一直在暗中引导你走到今天这一步。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]是我救赎了一无是处的你。", "\t[blackMagician]是我救赎了一无是处的你。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]为什么只有我一个人活了下来!!!!", "\t[hero]为什么只有我一个人活了下来!!!!",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]为什么偏偏是我!!!!", "\t[hero]为什么偏偏是我!!!!",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]我刚才不是说过了吗?因为我看出了你有稀有勇者体质啊。", "\t[blackMagician]我刚才不是说过了吗?因为我看出了你有稀有勇者体质啊。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]你刚刚跟鬼帝交过手,应该已经很清楚这稀有勇者体质意味着什么了吧?", "\t[blackMagician]你刚刚跟鬼帝交过手,应该已经很清楚这稀有勇者体质意味着什么了吧?",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]……就因为我有这种体质,就不得不背负如此残酷的宿命吗?", "\t[hero]……就因为我有这种体质,就不得不背负如此残酷的宿命吗?",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]愚蠢!这意味着只要我对你加以引导跟培养,你就能成为这世间实力最强的存在!", "\t[blackMagician]愚蠢!这意味着只要我对你加以引导跟培养,你就能成为这世间实力最强的存在!",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]……所以,你究竟想利用我干什么?", "\t[hero]……所以,你究竟想利用我干什么?",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]我利用你干的事情,你不是已经完成了吗?", "\t[blackMagician]我利用你干的事情,你不是已经完成了吗?",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]……你说什么?", "\t[hero]……你说什么?",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]不知不觉间,你已经在我的指引下跟鬼帝正面交手并且杀掉了他啊。", "\t[blackMagician]不知不觉间,你已经在我的指引下跟鬼帝正面交手并且杀掉了他啊。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]就连我跟鬼帝的对决……也是被你安排好了的?", "\t[hero]就连我跟鬼帝的对决……也是被你安排好了的?",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]你们两个一个是人类勇者,一个是魔物勇者,迟早会有交手的一天。", "\t[blackMagician]你们两个一个是人类勇者,一个是魔物勇者,迟早会有交手的一天。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]我只不过是操纵了一系列的连锁事件让这一天提早了数十年到来而已。", "\t[blackMagician]我只不过是操纵了一系列的连锁事件让这一天提早了数十年到来而已。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]……你这样做对谁有好处?他可是你们魔物世界的救世主啊。", "\t[hero]……你这样做对谁有好处?他可是你们魔物世界的救世主啊。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]一个惧怕征战,爱好和平的懦夫,也配叫救世主?", "\t[blackMagician]一个惧怕征战,爱好和平的懦夫,也配叫救世主?",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]获得了力量,却只会被动挨打而不主动向人类世界出击,龟缩在第二区域惶惶度日,他根本就不配拥有稀有勇者体质。", "\t[blackMagician]获得了力量,却只会被动挨打而不主动向人类世界出击,龟缩在第二区域惶惶度日,他根本就不配拥有稀有勇者体质。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]为了不让这种人霸占着积累多年的庞大灵魂能量无作为,我设计让你杀掉了他。", "\t[blackMagician]为了不让这种人霸占着积累多年的庞大灵魂能量无作为,我设计让你杀掉了他。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]你没有辜负我的期待,成功战胜了那个废物,现在你体内累积的灵魂能量……也就是魔力,已经达到了能跟魔王匹敌的地步。", "\t[blackMagician]你没有辜负我的期待,成功战胜了那个废物,现在你体内累积的灵魂能量……也就是魔力,已经达到了能跟魔王匹敌的地步。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]……是吗?现在的我能与魔王匹敌?", "\t[hero]……是吗?现在的我能与魔王匹敌?",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]不止如此,你现在的力量之强就算是统治世界也是绰绰有余!", "\t[blackMagician]不止如此,你现在的力量之强就算是统治世界也是绰绰有余!",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]怎么样?要不要加入我的麾下,跟随我去征战人类世界?", "\t[blackMagician]怎么样?要不要加入我的麾下,跟随我去征战人类世界?",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]能与魔王匹敌的话,也就是说。", "\t[hero]能与魔王匹敌的话,也就是说。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]我 现 在 对 付 你 这 种 杂 碎 也 绰 绰 有 余 吧 ", "\t[hero]我 现 在 对 付 你 这 种 杂 碎 也 绰 绰 有 余 吧 ",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]……什么?!", "\t[blackMagician]……什么?!",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]等一下!别冲动!你先等我把这利害关系理一理——", "\t[blackMagician]等一下!别冲动!你先等我把这利害关系理一理——",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]你给老子闭嘴。", "\t[hero]你给老子闭嘴。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]老子什么都不想听。", "\t[hero]老子什么都不想听。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]老子现在想做的事情只有一件——", "\t[hero]老子现在想做的事情只有一件——",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]剁掉你的头,把它放回我双亲的墓前。", "\t[hero]剁掉你的头,把它放回我双亲的墓前。",
{"type": "update"} // 本事件剧情结束,更新地图显伤 {"type": "update"} // 本事件剧情结束,更新地图显伤
], ],
@ -175,7 +175,7 @@ main.floors.sample2 =
"data": [ "data": [
"\t[blackMagician]听不进去人话的蠢货,就要用疼痛来管教!", "\t[blackMagician]听不进去人话的蠢货,就要用疼痛来管教!",
{"type": "changePos", "direction": "up"}, {"type": "changePos", "direction": "up"},
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]出来吧!禁忌——紫电凶杀阵!", "\t[blackMagician]出来吧!禁忌——紫电凶杀阵!",
{"type": "show", "loc": [[4,3],[4,6],[8,6],[8,3]], "time": 500}, // 依次显示四个角的法师 {"type": "show", "loc": [[4,3],[4,6],[8,6],[8,3]], "time": 500}, // 依次显示四个角的法师
{"type": "sleep", "time": 500}, {"type": "sleep", "time": 500},
@ -195,13 +195,13 @@ main.floors.sample2 =
{"type": "animate", "name": "yongchang", "loc": [8,6]}, {"type": "animate", "name": "yongchang", "loc": [8,6]},
{"type": "animate", "name": "yongchang", "loc": [8,3]}, {"type": "animate", "name": "yongchang", "loc": [8,3]},
{"type": "sleep", "time": 200}, {"type": "sleep", "time": 200},
{"type": "playSound", "name": "attack.ogg"}, // 播放攻击音效 {"type": "playSound", "name": "attack.mp3"}, // 播放攻击音效
{"type": "animate", "name": "thunder", "loc": "hero"}, {"type": "animate", "name": "thunder", "loc": "hero"},
{"type": "sleep", "time": 200}, {"type": "sleep", "time": 200},
"\t[hero]唔……!!(吐血)", "\t[hero]唔……!!(吐血)",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]我的魔力可是充足的很啊!我会一直折磨到你屈服于我为止!", "\t[blackMagician]我的魔力可是充足的很啊!我会一直折磨到你屈服于我为止!",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]人类!好好感受吧!当初你们施加于我的痛苦!如今我要百倍奉还!", "\t[blackMagician]人类!好好感受吧!当初你们施加于我的痛苦!如今我要百倍奉还!",
{"type": "show", "loc": [6,6], "time": 1000}, // 显示妖精 {"type": "show", "loc": [6,6], "time": 1000}, // 显示妖精
{"type": "sleep", "time": 700}, {"type": "sleep", "time": 700},
@ -232,45 +232,45 @@ main.floors.sample2 =
"6,6": { // 妖精 "6,6": { // 妖精
"enable":false, // 初始时禁用状态 "enable":false, // 初始时禁用状态
"data": [ // 妖精事件 "data": [ // 妖精事件
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]…妖精…小姐……是你吗?", "\t[hero]…妖精…小姐……是你吗?",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[小妖精,fairy]不要绝望,也不要悲伤。", "\t[小妖精,fairy]不要绝望,也不要悲伤。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[小妖精,fairy]你从来都不是独自一人在前进。", "\t[小妖精,fairy]你从来都不是独自一人在前进。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[小妖精,fairy]咱一直,一直都在注视着你。", "\t[小妖精,fairy]咱一直,一直都在注视着你。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[小妖精,fairy]耍小聪明的你、笨笨的你呆呆的你、胆小的你、勇敢的你帅气的你……全部全部都是你。", "\t[小妖精,fairy]耍小聪明的你、笨笨的你呆呆的你、胆小的你、勇敢的你帅气的你……全部全部都是你。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[小妖精,fairy]所以放心吧,无论发生什么,咱都会陪伴在你身边的。", "\t[小妖精,fairy]所以放心吧,无论发生什么,咱都会陪伴在你身边的。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[小妖精,fairy]因为你要是离开我的话,立刻就会死掉吧?", "\t[小妖精,fairy]因为你要是离开我的话,立刻就会死掉吧?",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]…妖精…小姐……其实一直以来,我都非常感激你……", "\t[hero]…妖精…小姐……其实一直以来,我都非常感激你……",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[小妖精,fairy]笨蛋!都这种时候了就不要作出像是临终遗言的发言了啊!!", "\t[小妖精,fairy]笨蛋!都这种时候了就不要作出像是临终遗言的发言了啊!!",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[小妖精,fairy]喂!那边穿衣品味差到极点的黑暗大法师,别左顾右盼说的就是你!你应该知道咱的身份吧?\n还不速速退下", "\t[小妖精,fairy]喂!那边穿衣品味差到极点的黑暗大法师,别左顾右盼说的就是你!你应该知道咱的身份吧?\n还不速速退下",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]可恶…多管闲事的妖精族…明明只要再让他承受一点疼痛来瓦解他的意志力,我的计划就成功了!", "\t[blackMagician]可恶…多管闲事的妖精族…明明只要再让他承受一点疼痛来瓦解他的意志力,我的计划就成功了!",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[小妖精,fairy]哼哼哼~抱歉哦,这个笨蛋的意志力可不像你想象的那么薄弱哦!", "\t[小妖精,fairy]哼哼哼~抱歉哦,这个笨蛋的意志力可不像你想象的那么薄弱哦!",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]不甘心!我不甘心!妖精公主又如何!\n只要是阻挡我的不管是谁我都要铲除", "\t[blackMagician]不甘心!我不甘心!妖精公主又如何!\n只要是阻挡我的不管是谁我都要铲除",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[小妖精,fairy]终于露出狐狸尾巴了,其实咱早就看出你有谋反的念头。你的计划就是拉拢这家伙入伙然后推翻魔王对魔塔的统治对吧?", "\t[小妖精,fairy]终于露出狐狸尾巴了,其实咱早就看出你有谋反的念头。你的计划就是拉拢这家伙入伙然后推翻魔王对魔塔的统治对吧?",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]呵呵呵……那个昏庸的魔王,掌握着那么庞大的魔物军队却只知道固守魔塔,而不主动侵略人类世界扩张领土!", "\t[blackMagician]呵呵呵……那个昏庸的魔王,掌握着那么庞大的魔物军队却只知道固守魔塔,而不主动侵略人类世界扩张领土!",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]我实在是看不过眼,所以我才决定把这个具备稀有勇者体质的家伙培养成新一任魔王!\n来让这个世界的势力重新洗牌", "\t[blackMagician]我实在是看不过眼,所以我才决定把这个具备稀有勇者体质的家伙培养成新一任魔王!\n来让这个世界的势力重新洗牌",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[小妖精,fairy]你觉得一个满脑子想着回家种田的废柴勇者会成为改变世界的魔王?你晃晃脑袋试试,是不是能听到大海的声音?", "\t[小妖精,fairy]你觉得一个满脑子想着回家种田的废柴勇者会成为改变世界的魔王?你晃晃脑袋试试,是不是能听到大海的声音?",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]恼人至极的妖精族!呵呵呵……我干脆一不做二不休,连你也一块收拾了吧!", "\t[blackMagician]恼人至极的妖精族!呵呵呵……我干脆一不做二不休,连你也一块收拾了吧!",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[小妖精,fairy]别小瞧咱!咱好歹也是妖精族里实力数一数二的存在!", "\t[小妖精,fairy]别小瞧咱!咱好歹也是妖精族里实力数一数二的存在!",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]只会耍嘴皮子的恼人苍蝇!我倒要看看一块焦炭会不会说话!\n——招雷弹", "\t[blackMagician]只会耍嘴皮子的恼人苍蝇!我倒要看看一块焦炭会不会说话!\n——招雷弹",
/* /*
{"type": "hide", "loc": [4,3], "time": 150}, // 由于没有动画效果,暂时使用“闪一下”表示 {"type": "hide", "loc": [4,3], "time": 150}, // 由于没有动画效果,暂时使用“闪一下”表示
@ -286,7 +286,7 @@ main.floors.sample2 =
{"type": "animate", "name": "yongchang", "loc": [4,6]}, {"type": "animate", "name": "yongchang", "loc": [4,6]},
{"type": "animate", "name": "yongchang", "loc": [8,6]}, {"type": "animate", "name": "yongchang", "loc": [8,6]},
{"type": "animate", "name": "yongchang", "loc": [8,3]}, {"type": "animate", "name": "yongchang", "loc": [8,3]},
{"type": "playSound", "name": "attack.ogg"}, // 播放攻击音效 {"type": "playSound", "name": "attack.mp3"}, // 播放攻击音效
/* /*
{"type": "hide", "loc": [6,6], "time": 150}, // 妖精也闪一下表示收到了伤害 {"type": "hide", "loc": [6,6], "time": 150}, // 妖精也闪一下表示收到了伤害
{"type": "show", "loc": [6,6], "time": 150}, // 妖精也闪一下表示收到了伤害 {"type": "show", "loc": [6,6], "time": 150}, // 妖精也闪一下表示收到了伤害
@ -294,38 +294,38 @@ main.floors.sample2 =
{"type": "animate", "name": "thunder", "loc": [6,6]}, {"type": "animate", "name": "thunder", "loc": [6,6]},
{"type": "sleep", "time": 500}, // 等待500毫秒 {"type": "sleep", "time": 500}, // 等待500毫秒
"\t[小妖精,fairy]切,这点伤痛跟他刚才经历的身心地狱相比根本就不算什么。", "\t[小妖精,fairy]切,这点伤痛跟他刚才经历的身心地狱相比根本就不算什么。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]哼!翅膀都被烧焦了还要嘴硬?你难不成真以为我不会对你动真格?", "\t[blackMagician]哼!翅膀都被烧焦了还要嘴硬?你难不成真以为我不会对你动真格?",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]……你这混蛋!给我离她远点!!", "\t[hero]……你这混蛋!给我离她远点!!",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[小妖精,fairy]!…你现在受了很严重的致命伤,乱动什么?\n乖。别怕这里有咱顶着", "\t[小妖精,fairy]!…你现在受了很严重的致命伤,乱动什么?\n乖。别怕这里有咱顶着",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[小妖精,fairy]对了,咱再问你一遍,你是很珍惜自己性命的对吧?", "\t[小妖精,fairy]对了,咱再问你一遍,你是很珍惜自己性命的对吧?",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]!…等等…妖精小姐,你不会是……?", "\t[hero]!…等等…妖精小姐,你不会是……?",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[小妖精,fairy]喂,黑暗大法师,你作为魔塔里最博学多识的蠢货,应该对咱妖精族的特殊能力再清楚不过吧?", "\t[小妖精,fairy]喂,黑暗大法师,你作为魔塔里最博学多识的蠢货,应该对咱妖精族的特殊能力再清楚不过吧?",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]什么?!难不成你是想!!不可能……\n就为了一个渺小的人类不可理喻", "\t[blackMagician]什么?!难不成你是想!!不可能……\n就为了一个渺小的人类不可理喻",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[小妖精,fairy]哼哼哼!你害怕的表情可真美味!", "\t[小妖精,fairy]哼哼哼!你害怕的表情可真美味!",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[小妖精,fairy]不过比起这个,咱更期待你吃到“妖精自灭冲击”之后的死状哦!~", "\t[小妖精,fairy]不过比起这个,咱更期待你吃到“妖精自灭冲击”之后的死状哦!~",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[blackMagician]不!!不应该是这样的!我完美的计划竟然会被一只小小的妖精破坏!", "\t[blackMagician]不!!不应该是这样的!我完美的计划竟然会被一只小小的妖精破坏!",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]不要!……千万不要!……为了我这种人……唔!", "\t[hero]不要!……千万不要!……为了我这种人……唔!",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[小妖精,fairy]笨蛋,动都动不了了就不要强撑着站起来了啊。", "\t[小妖精,fairy]笨蛋,动都动不了了就不要强撑着站起来了啊。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[小妖精,fairy]真是的,都到最后一刻了,你这家伙好歹也让咱省点心吧。", "\t[小妖精,fairy]真是的,都到最后一刻了,你这家伙好歹也让咱省点心吧。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[小妖精,fairy]那么,再见了……我的勇者大人。", "\t[小妖精,fairy]那么,再见了……我的勇者大人。",
{"type": "move", "time": 700, "steps": [ // 向上移动三个撞上黑暗大大法师本事件的hide会自动被调用 {"type": "move", "time": 700, "steps": [ // 向上移动三个撞上黑暗大大法师本事件的hide会自动被调用
{"direction": "up", "value": 3} {"direction": "up", "value": 3}
]}, ]},
{"type": "playSound", "name": "attack.ogg"}, // 播放攻击音效 {"type": "playSound", "name": "attack.mp3"}, // 播放攻击音效
{"type": "sleep", "time": 200}, {"type": "sleep", "time": 200},
"\t[blackMagician]不可能!!!!!", "\t[blackMagician]不可能!!!!!",
{"type": "hide", "loc": [6,3]}, // 法师消失 {"type": "hide", "loc": [6,3]}, // 法师消失
@ -336,24 +336,24 @@ main.floors.sample2 =
{"type": "changeFloor", "floorId": "sample2", "loc": [6,6], "direction": "up", "time": 1000}, // 更换勇士地点合计1秒 {"type": "changeFloor", "floorId": "sample2", "loc": [6,6], "direction": "up", "time": 1000}, // 更换勇士地点合计1秒
{"type": "show", "loc": [6,5]}, // 显示黄宝石 {"type": "show", "loc": [6,5]}, // 显示黄宝石
{"type": "sleep", "time": 200}, // 等待200毫秒 {"type": "sleep", "time": 200}, // 等待200毫秒
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
{"type": "sleep", "time": 200}, // 等待200毫秒 {"type": "sleep", "time": 200}, // 等待200毫秒
"\t[hero]…妖精…小姐……", "\t[hero]…妖精…小姐……",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]……妖精小姐!", "\t[hero]……妖精小姐!",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]是梦吗?……不对,为什么我在流泪?", "\t[hero]是梦吗?……不对,为什么我在流泪?",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]这颗漂亮的宝石是……?", "\t[hero]这颗漂亮的宝石是……?",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]我全都想起来了……妖精小姐为了我……\n牺牲了自己的性命。", "\t[hero]我全都想起来了……妖精小姐为了我……\n牺牲了自己的性命。",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]在这颗宝石上,我能感受到你的温度……\n熟悉而又令人安心这就是你最后留给我的东西吗……", "\t[hero]在这颗宝石上,我能感受到你的温度……\n熟悉而又令人安心这就是你最后留给我的东西吗……",
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]好温暖……", "\t[hero]好温暖……",
{"type": "setValue", "name": "item:yellowJewel", "value": "1"}, // 获得1个黄宝石 {"type": "setValue", "name": "item:yellowJewel", "value": "1"}, // 获得1个黄宝石
{"type": "hide", "loc": [6,5]}, // 隐藏黄宝石 {"type": "hide", "loc": [6,5]}, // 隐藏黄宝石
{"type": "playSound", "name": "item.ogg"}, {"type": "playSound", "name": "item.mp3"},
"\t[hero]……", "\t[hero]……",
{"type": "openDoor", "loc": [6,2]}, // 开门 {"type": "openDoor", "loc": [6,2]}, // 开门
{"type": "openDoor", "loc": [6,11]} {"type": "openDoor", "loc": [6,11]}

View File

@ -119,6 +119,10 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
// 扣减体力值 // 扣减体力值
core.status.hero.hp -= damage; core.status.hero.hp -= damage;
// 记录
core.status.hero.statistics.battleDamage += damage;
if (core.status.hero.hp<=0) { if (core.status.hero.hp<=0) {
core.status.hero.hp=0; core.status.hero.hp=0;
core.updateStatusBar(); core.updateStatusBar();
@ -155,7 +159,7 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
// 衰弱 // 衰弱
if (core.enemys.hasSpecial(special, 13) && !core.hasFlag('weak')) { if (core.enemys.hasSpecial(special, 13) && !core.hasFlag('weak')) {
core.setFlag('weak', true); core.setFlag('weak', true);
var weakValue = core.status.weakValue; var weakValue = core.values.weakValue;
var weakAtk = weakValue>=1?weakValue:Math.floor(weakValue*core.status.hero.atk); var weakAtk = weakValue>=1?weakValue:Math.floor(weakValue*core.status.hero.atk);
var weakDef = weakValue>=1?weakValue:Math.floor(weakValue*core.status.hero.def); var weakDef = weakValue>=1?weakValue:Math.floor(weakValue*core.status.hero.def);
core.setFlag('weakAtk', weakAtk); core.setFlag('weakAtk', weakAtk);
@ -346,7 +350,7 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
console.log("插件函数执行测试"); console.log("插件函数执行测试");
} }
var _useEquipment = function (itemId, name, type) { var _useEquipment = function (itemId, name, type) { // 具体的装备使用效果
if (itemId.indexOf(name)==0) { if (itemId.indexOf(name)==0) {
var now=core.getFlag(name, name+"0"); var now=core.getFlag(name, name+"0");
@ -356,7 +360,7 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
else { else {
core.status.hero.atk -= core.values[now].atk || 0; core.status.hero.atk -= core.values[now].atk || 0;
core.status.hero.def -= core.values[now].def || 0; core.status.hero.def -= core.values[now].def || 0;
core.status.hero.mdef -= core.values[now].mdef || 0; core.status.hero.mdef -= core.values[now].mdef || 0;
} }
if (typeof core.values[itemId] == 'number') { if (typeof core.values[itemId] == 'number') {

View File

@ -27,8 +27,8 @@ icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1 =
'white': 17, 'white': 17,
'ground6': 18, 'ground6': 18,
'soil': 19, 'soil': 19,
'star': 20, 'ground7': 20,
'lava': 21, 'ground8': 21,
'ice': 22, 'ice': 22,
'downFloor': 23, 'downFloor': 23,
'upFloor': 24, 'upFloor': 24,
@ -70,9 +70,9 @@ icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1 =
'lavaDoor': 13, 'lavaDoor': 13,
'starDoor': 14, 'starDoor': 14,
'starPortal': 15, 'starPortal': 15,
//'exclamation': 16, 'fire': 16,
'portal': 17, 'portal': 17,
//'switch': 18, 'switch': 18,
'lavaNet': 19, 'lavaNet': 19,
'poisonNet': 20, 'poisonNet': 20,
'weakNet': 21, 'weakNet': 21,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -278,13 +278,13 @@ items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
"useItemEffect": { "useItemEffect": {
"book": "core.ui.drawBook(0);", "book": "core.ui.drawBook(0);",
"fly": "core.ui.drawFly(core.status.hero.flyRange.indexOf(core.status.floorId));", "fly": "core.ui.drawFly(core.status.hero.flyRange.indexOf(core.status.floorId));",
"earthquake": "core.removeBlockByIds(core.status.floorId, core.status.event.data);\ncore.drawMap(core.status.floorId, function () {\n core.drawHero();\n core.updateFg();\n core.drawTip(core.material.items[itemId].name + '使用成功');\n});", "earthquake": "core.removeBlockByIds(core.status.floorId, core.status.event.data);\ncore.drawMap(core.status.floorId, function () {\n core.drawTip(core.material.items[itemId].name + '使用成功');\n});",
"pickaxe": "core.removeBlockByIds(core.status.floorId, core.status.event.data);\ncore.drawMap(core.status.floorId, function () {\n core.drawHero();\n core.updateFg();\n core.drawTip(core.material.items[itemId].name + '使用成功');\n});", "pickaxe": "core.removeBlockByIds(core.status.floorId, core.status.event.data);\ncore.drawMap(core.status.floorId, function () {\n core.drawTip(core.material.items[itemId].name + '使用成功');\n});",
"icePickaxe": "core.removeBlockByIds(core.status.floorId, core.status.event.data);\ncore.drawMap(core.status.floorId, function () {\n core.drawHero(), 'stop');\n core.updateFg();\n core.drawTip(core.material.items[itemId].name + '使用成功');\n});", "icePickaxe": "core.removeBlockByIds(core.status.floorId, core.status.event.data);\ncore.drawMap(core.status.floorId, function () {\n core.drawTip(core.material.items[itemId].name + '使用成功');\n});",
"snow": "core.removeBlockByIds(core.status.floorId, core.status.event.data);\ncore.drawMap(core.status.floorId, function () {\n core.drawHero();\n core.updateFg();\n core.drawTip(core.material.items[itemId].name + '使用成功');\n});", "snow": "core.removeBlockByIds(core.status.floorId, core.status.event.data);\ncore.drawMap(core.status.floorId, function () {\n core.drawTip(core.material.items[itemId].name + '使用成功');\n});",
"bigKey": "core.removeBlockByIds(core.status.floorId, core.status.event.data);\ncore.drawMap(core.status.floorId, function () {\n core.drawHero();\n core.updateFg();\n core.drawTip(core.material.items[itemId].name + '使用成功');\n});", "bigKey": "core.removeBlockByIds(core.status.floorId, core.status.event.data);\ncore.drawMap(core.status.floorId, function () {\n core.drawTip(core.material.items[itemId].name + '使用成功');\n});",
"bomb": "core.removeBlockByIds(core.status.floorId, core.status.event.data);\ncore.drawMap(core.status.floorId, function () {\n core.drawHero();\n core.updateFg();\n core.drawTip(core.material.items[itemId].name + '使用成功');\n core.events.afterUseBomb();\n});", "bomb": "core.removeBlockByIds(core.status.floorId, core.status.event.data);\ncore.drawMap(core.status.floorId, function () {\n core.drawTip(core.material.items[itemId].name + '使用成功');\n core.events.afterUseBomb();\n});",
"hammer": "core.removeBlockByIds(core.status.floorId, core.status.event.data);\ncore.drawMap(core.status.floorId, function () {\n core.drawHero();\n core.updateFg();\n core.drawTip(core.material.items[itemId].name + '使用成功');\n core.events.afterUseBomb();\n});", "hammer": "core.removeBlockByIds(core.status.floorId, core.status.event.data);\ncore.drawMap(core.status.floorId, function () {\n core.drawTip(core.material.items[itemId].name + '使用成功');\n core.events.afterUseBomb();\n});",
"centerFly": "core.clearMap('hero', 0, 0, 416, 416);\ncore.setHeroLoc('x', core.status.event.data.x);\ncore.setHeroLoc('y', core.status.event.data.y);\ncore.drawHero();\ncore.drawTip(core.material.items[itemId].name + '使用成功');", "centerFly": "core.clearMap('hero', 0, 0, 416, 416);\ncore.setHeroLoc('x', core.status.event.data.x);\ncore.setHeroLoc('y', core.status.event.data.y);\ncore.drawHero();\ncore.drawTip(core.material.items[itemId].name + '使用成功');",
"upFly": "var loc = {'direction': core.status.hero.loc.direction, 'x': core.status.event.data.x, 'y': core.status.event.data.y};\ncore.changeFloor(core.status.event.data.id, null, loc, null, function (){\n core.drawTip(core.material.items[itemId].name + '使用成功');\n core.replay();\n});", "upFly": "var loc = {'direction': core.status.hero.loc.direction, 'x': core.status.event.data.x, 'y': core.status.event.data.y};\ncore.changeFloor(core.status.event.data.id, null, loc, null, function (){\n core.drawTip(core.material.items[itemId].name + '使用成功');\n core.replay();\n});",
"downFly": "var loc = {'direction': core.status.hero.loc.direction, 'x': core.status.event.data.x, 'y': core.status.event.data.y};\ncore.changeFloor(core.status.event.data.id, null, loc, null, function (){\n core.drawTip(core.material.items[itemId].name + '使用成功');\n core.replay();\n});", "downFly": "var loc = {'direction': core.status.hero.loc.direction, 'x': core.status.event.data.x, 'y': core.status.event.data.y};\ncore.changeFloor(core.status.event.data.id, null, loc, null, function (){\n core.drawTip(core.material.items[itemId].name + '使用成功');\n core.replay();\n});",

BIN
project/sounds/attack.mp3 Normal file

Binary file not shown.

Binary file not shown.

BIN
project/sounds/door.mp3 Normal file

Binary file not shown.

Binary file not shown.

BIN
project/sounds/item.mp3 Normal file

Binary file not shown.

Binary file not shown.

BIN
project/sounds/zone.mp3 Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,12 +1,19 @@
HTML5魔塔样板V2.2.1 HTML5魔塔样板V2.2.1
衰弱减少攻防的比例 √ 地图编辑器可以右键复制或移动图块 √
while循环事件 √ 事件while循环处理 √
地图数据统计 事件:等待用户操作并获得按键或点击信息 √
衰弱可以减少攻防的比例 √
地图数据统计 √
支持 status:x 获得当前坐标 √
core.debug()改成调试模式可以Ctrl穿墙 √
最大存档个数提到main处理 √ 最大存档个数提到main处理 √
新建地图可以保留楼层属性 √ 新建地图可以保留楼层属性 √
自定义装备的教程(个性化 - 自定义装备) √ 地图编辑器可用PageUp和PageDown切换楼层 √
部分Bug修复 √ 道具描述过长时可以自动换行 √
除Autotile外均可自动注册 √
重写大部分教程,新增大量拓展描述 √
大量细节进行优化所有已知的bug进行了修复 √
----------------------------------------------------------------------- -----------------------------------------------------------------------