diff --git a/API列表.txt b/API列表.txt index 8233a735..b2013082 100644 --- a/API列表.txt +++ b/API列表.txt @@ -1,4 +1,4 @@ -附录:API列表(V2.6版) +附录:API列表(V2.6.3版) 这里将列出所有被转发到core的API,没有被转发的函数此处不会列出,请自行在代码中查看。 @@ -56,7 +56,6 @@ core.platform.isPC (是否是电脑端) core.platform.isAndroid (是否是安卓端) core.platform.isIOS (是否是iOS端) core.platform.useLocalForage (是否开启了新版存档) -core.platform.extendKeyBoard (是否开启了拓展键盘) core.domStyle @@ -1742,7 +1741,7 @@ id可选,为同时绘制的图标ID,如果不为null则会同时绘制该图 core.drawText(content, callback) 绘制一段文字。contents为一个字符串或一个字符串数组,callback为全部绘制完毕的回调。 -支持所有的文字效果(如\n,${},\r,\\i等),也支持\t和\b的语法。 +支持所有的文字效果(如\n,${},\r,\\i,\\c,\\d,\\e等),也支持\t和\b的语法。 如果当前在事件处理中或录像回放中,则会自动转成core.insertAction处理。 不建议使用该函数,如有绘制文字的需求请尽量使用core.insertAction()插入剧情文本事件。 @@ -1767,7 +1766,7 @@ posInfo如果不为null则是一个含position, px和py的对象,表示一个 core.drawTextContent(ctx, content, config) 根据配置在某个画布上绘制一段文字。此函数会被core.drawTextBox()所调用。 ctx为画布名或画布本身,如果不设置则会忽略该函数。 -content为要绘制的文字内容,支持所有的文字效果(如\n,${},\r,\\i等),但不支持支持\t和\b的语法。 +content为要绘制的文字内容,支持所有的文字效果(如\n,${},\r,\\i,\\c,\\d,\\e等),但不支持支持\t和\b的语法。 config为绘制的配置项,目前可以包括如下几项: - left, top:在该画布上绘制的左上角像素位置,不设置默认为(0,0)。 > 该函数绘制时会将textBaseline设置为'top',因此只需要考虑第一个字的左上角位置。 @@ -1782,7 +1781,7 @@ config为绘制的配置项,目前可以包括如下几项: core.drawTextBox(content, showAll) 绘制一个对话框。content为一个字符串或一个字符串数组。 -支持所有的文字效果(如\n,${},\r,\\i等),也支持\t和\b的语法。 +支持所有的文字效果(如\n,${},\r,\\i,\\c,\\d,\\e等),也支持\t和\b的语法。 该函数将使用用户在剧情文本设置中的配置项进行绘制。 实际执行时,会计算文本框宽度并绘制背景,绘制标题和头像,再调用core.drawTextContent()绘制正文内容。 showAll可选,如果为true则不会使用打字机效果而全部显示,主要用于打字机效果的点击显示全部。 @@ -1790,7 +1789,7 @@ showAll可选,如果为true则不会使用打字机效果而全部显示,主 core.drawScrollText(content, time, lineHeight, callback) 绘制一个滚动字幕。content为绘制内容,time为总时间(默认为5000),lineHeight为行距比例(默认为1.4)。 -滚动字幕将绘制在UI上,支持所有的文字效果(如\n,${},\r,\\i等),但不支持\t和\b效果。 +滚动字幕将绘制在UI上,支持所有的文字效果(如\n,${},\r,\\i,\\c,\\d,\\e等),但不支持\t和\b效果。 可以通过剧情文本设置中的align控制是否居中绘制,offset控制其距离左边的偏移量。 @@ -1802,7 +1801,7 @@ core.textImage(content, lineHeight) core.drawChoices(content, choices) 绘制一个选项框。 -content可选,为选项上方的提示文字,支持所有的文字效果(如\n,${},\r,\\i等),也支持\t效果。 +content可选,为选项上方的提示文字,支持所有的文字效果(如\n,${},\r,\\i,\\c,\\d,\\e等),也支持\t效果。 choices必选,为要绘制的选项内容,是一个列表。其中的每一项: - 可以是一个字符串,表示选项文字,将使用剧情文本设置中的正文颜色来绘制,仅支持${}表达式计算。 - 或者是一个包含text, color和icon的对象。 @@ -1872,8 +1871,11 @@ core.ui.relocateCanvas(name, x, y) 重新定位一个自定义画布。x和y为画布的左上角坐标。 -core.ui.resizeCanvas(name, width, height) -重新设置一个自定义画布的大小。width和height为新设置的宽高。此操作会清空画布。 +core.ui.resizeCanvas(name, width, height, styleOnly) +重新设置一个自定义画布的大小。width和height为新设置的宽高。 +styleOnly控制是否只修改画布的显示大小(而不修改画布的内部大小)。 +如果styleOnly为true,则只修改其显示大小(即canvas.style.width); +否则,则会同时修改画布的显示大小和内部大小并清空画布内容。 core.ui.deleteCanvas(name) diff --git a/README.md b/README.md index 7e331545..7ccf34ca 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,39 @@ HTML5 canvas制作的魔塔样板,支持全平台游戏! ## 更新说明 +### 2019.7.24 V2.6.3 + +* [x] 标题界面大幅美化,增加闪烁光标,支持键盘开始游戏 +* [x] 事件编辑器支持自动补全,能对flag和API列表等进行补全 +* [x] 剧情文本中\\c修改字体大小,\\d和\\e切换粗体和斜体 +* [x] 事件:设置视角&移动视角 +* [x] 可以指定显示选择项的出现条件并动态生成 +* [x] 楼层传送器的平面传送模式(哪里离开飞回到哪里) +* [x] UI绘制事件增添绘制圆和绘制圆边框 +* [x] 所有的UI绘制事件均可以双击预览 +* [x] 播放BGM事件可以一直持续播放直到下次调用 +* [x] \f立绘支持alpha值 +* [x] 支持在脚本编辑中直接flags.xxx调用自定义变量 +* [x] 首次获得道具将给予提示 +* [x] 等待用户操作支持滚轮,视为PgUp和PgDn +* [x] 脚本编辑器语法错误将禁止保存 +* [x] 录像播放时B键查看数据统计 +* [x] 所有已知bug的修复,大量细节优化 + +### 2019.6.7 V2.6.2 + +* [x] 可以拖动地图上的图块和事件,复制剪切和跨楼层粘贴 +* [x] 新增事件的地图选点功能,可以在地图上选择落点 +* [x] 现在素材区可以进行折叠与自动换列了 +* [x] 新增UI绘制系列事件,并且可以进行预览 +* [x] 显示文本事件的标题解析 +* [x] 新增常用工具:额外素材合并工具 +* [x] 进一步提升24倍速的播放速度 +* [x] 楼层转换增加对称点 +* [x] 增加编辑器快捷键说明,H键查看 +* [x] 文档-事件增加事件编辑器截图 +* [x] 大量细节优化,所有已知的Bug修复 + ### 2019.5.2 V2.6.1 * [x] 区域优化的录像播放功能,R键使用 diff --git a/_docs/V2.0.md b/_docs/V2.0.md index 0b8bd92a..30a38017 100644 --- a/_docs/V2.0.md +++ b/_docs/V2.0.md @@ -1,6 +1,6 @@ # V2.0版本介绍 -?> 目前版本**v2.6.1**,上次更新时间:* {docsify-updated} * +?> 目前版本**v2.6.3*,上次更新时间:* {docsify-updated} * 目前样板已经更新到V2.0版本以上,本章将对V2.0的一些内容进行介绍。 diff --git a/_docs/api.md b/_docs/api.md index c1c65a3d..6424dcf3 100644 --- a/_docs/api.md +++ b/_docs/api.md @@ -1,6 +1,6 @@ # 附录:API列表 -?> 目前版本**v2.6.1**,上次更新时间:* {docsify-updated} * +?> 目前版本**v2.6.3**,上次更新时间:* {docsify-updated} * 这里将列出所有被转发到core的API,没有被转发的函数此处不会列出,请自行在代码中查看。 @@ -57,7 +57,6 @@ core.platform.isPC (是否是电脑端) core.platform.isAndroid (是否是安卓端) core.platform.isIOS (是否是iOS端) core.platform.useLocalForage (是否开启了新版存档) -core.platform.extendKeyBoard (是否开启了拓展键盘) core.domStyle @@ -952,10 +951,11 @@ core.startEvents(list, x, y, callback) 此函数将调用core.setEvents,然后停止勇士,再执行core.doAction()。 -core.doAction() +core.doAction(keepUI) 执行下一个自定义事件。 此函数将检测事件列表是否全部执行完毕,如果是则执行回调函数。 否则,将从事件列表中弹出下一个事件,并调用core.doEvent进行执行。 +如果keepUI为true,则不会清掉UI层和selector,适合于自己用脚本的绘制。 core.insertAction(action, x, y, callback, addToLast) @@ -1615,9 +1615,10 @@ core.clearMap(name) 该函数的name也可以是'all',若为'all'则为清空所有系统画布。 -core.fillText(name, text, x, y, style, font) +core.fillText(name, text, x, y, style, font, maxWidth) 在某个画布上绘制一段文字。 text为要绘制的文本,x,y为要绘制的坐标,style可选为绘制的样式,font可选为绘制的字体。(下同) +如果maxWidth不为null,则视为文字最大宽度,如果超过此宽度则会自动放缩文字直到自适应为止。 请注意textAlign和textBaseline将决定绘制的左右对齐和上下对齐方式。 具体可详见core.setTextAlign()和core.setTextBaseline()函数。 @@ -1693,6 +1694,13 @@ core.drawImage(name, image, x, y, w, h, x1, y1, w1, h1) http://www.w3school.com.cn/html5/canvas_drawimage.asp 这里的image允许传一个图片,画布。也允许传递图片名,将从你导入的图片中获取图片内容。 + +core.drawIcon(name, id, x, y, w, h) +在一张画布上绘制一个图标。 +id为注册过的图标ID,也可以使用状态栏的图标ID,例如lv, hp, up, save, settings等。 +x和y为绘制的左上角坐标;w和h可选为绘制的宽高,如果不填或null则使用该图标的默认宽高。 + + // ------ 具体的某个UI界面的绘制 ------ // core.closePanel() 结束一切事件和UI绘制,关闭UI窗口,返回游戏。 @@ -1712,7 +1720,7 @@ id可选,为同时绘制的图标ID,如果不为null则会同时绘制该图 core.drawText(content, callback) 绘制一段文字。contents为一个字符串或一个字符串数组,callback为全部绘制完毕的回调。 -支持所有的文字效果(如\n,${},\r,\\i等),也支持\t和\b的语法。 +支持所有的文字效果(如\n,${},\r,\\i,\\c,\\d,\\e等),也支持\t和\b的语法。 如果当前在事件处理中或录像回放中,则会自动转成core.insertAction处理。 不建议使用该函数,如有绘制文字的需求请尽量使用core.insertAction()插入剧情文本事件。 @@ -1737,7 +1745,8 @@ posInfo如果不为null则是一个含position, px和py的对象,表示一个 core.drawTextContent(ctx, content, config) 根据配置在某个画布上绘制一段文字。此函数会被core.drawTextBox()所调用。 ctx为画布名或画布本身,如果不设置则会忽略该函数。 -content为要绘制的文字内容,支持所有的文字效果(如\n,${},\r,\\i等),但不支持支持\t和\b的语法。 +content为要绘制的文字内容,支持所有的文字效果(如\n,${},\r,\\i,\\c,\\d,\\e等) + ,但不支持支持\t和\b的语法。 config为绘制的配置项,目前可以包括如下几项: - left, top:在该画布上绘制的左上角像素位置,不设置默认为(0,0)。 > 该函数绘制时会将textBaseline设置为'top',因此只需要考虑第一个字的左上角位置。 @@ -1746,13 +1755,13 @@ config为绘制的配置项,目前可以包括如下几项: - bold:是否粗体。如果不设置默认为false。 - align:文字对齐方式,仅在maxWidth设置时有效,默认为'left'。 - fontSize:字体大小,如果不设置则使用剧情文本设置中的正文字体大小。 - - lineHeight:绘制的行距值,如果不设置则使用fontSize*1.3(即1.3被行距)。 + - lineHeight:绘制的行距值,如果不设置则使用fontSize*1.3(即1.3倍行距)。 - time:打字机效果。若不为0,则会逐个字进行绘制,并设置core.status.event.interval定时器。 core.drawTextBox(content, showAll) 绘制一个对话框。content为一个字符串或一个字符串数组。 -支持所有的文字效果(如\n,${},\r,\\i等),也支持\t和\b的语法。 +支持所有的文字效果(如\n,${},\r,\\i,\\c,\\d,\\e等),也支持\t和\b的语法。 该函数将使用用户在剧情文本设置中的配置项进行绘制。 实际执行时,会计算文本框宽度并绘制背景,绘制标题和头像,再调用core.drawTextContent()绘制正文内容。 showAll可选,如果为true则不会使用打字机效果而全部显示,主要用于打字机效果的点击显示全部。 @@ -1760,7 +1769,7 @@ showAll可选,如果为true则不会使用打字机效果而全部显示,主 core.drawScrollText(content, time, lineHeight, callback) 绘制一个滚动字幕。content为绘制内容,time为总时间(默认为5000),lineHeight为行距比例(默认为1.4)。 -滚动字幕将绘制在UI上,支持所有的文字效果(如\n,${},\r,\\i等),但不支持\t和\b效果。 +滚动字幕将绘制在UI上,支持所有的文字效果(如\n,${},\r,\\i,\\c,\\d,\\e等),但不支持\t和\b效果。 可以通过剧情文本设置中的align控制是否居中绘制,offset控制其距离左边的偏移量。 @@ -1772,7 +1781,7 @@ core.textImage(content, lineHeight) core.drawChoices(content, choices) 绘制一个选项框。 -content可选,为选项上方的提示文字,支持所有的文字效果(如\n,${},\r,\\i等),也支持\t效果。 +content可选,为选项上方的提示文字,支持所有的文字效果(如\n,${},\r,\\i,\\c,\\d,\\e等),也支持\t。 choices必选,为要绘制的选项内容,是一个列表。其中的每一项: - 可以是一个字符串,表示选项文字,将使用剧情文本设置中的正文颜色来绘制,仅支持${}表达式计算。 - 或者是一个包含text, color和icon的对象。 @@ -1842,8 +1851,11 @@ core.ui.relocateCanvas(name, x, y) 重新定位一个自定义画布。x和y为画布的左上角坐标。 -core.ui.resizeCanvas(name, width, height) -重新设置一个自定义画布的大小。width和height为新设置的宽高。此操作会清空画布。 +core.ui.resizeCanvas(name, width, height, styleOnly) +重新设置一个自定义画布的大小。width和height为新设置的宽高。 +styleOnly控制是否只修改画布的显示大小(而不修改画布的内部大小)。 +如果styleOnly为true,则只修改其显示大小(即canvas.style.width); +否则,则会同时修改画布的显示大小和内部大小并清空画布内容。 core.ui.deleteCanvas(name) diff --git a/_docs/element.md b/_docs/element.md index a6fbcc9f..b7dca11d 100644 --- a/_docs/element.md +++ b/_docs/element.md @@ -1,6 +1,6 @@ # 元件说明 -?> 目前版本**v2.6.1**,上次更新时间:* {docsify-updated} * +?> 目前版本**v2.6.3**,上次更新时间:* {docsify-updated} * 在本章中,将对样板里的各个元件进行说明。各个元件主要包括道具、门、怪物、楼梯等等。 @@ -282,10 +282,13 @@ floorId指定的是目标楼层的唯一标识符(ID)。 - 使用`${}`来计算一个表达式的值,如`${status:atk+status:def}`。 - 使用`\f[...]`来同时插入一张立绘图,如`\f[1.png,100,200]`。 - 使用`\\i[...]`来在对话框中绘制一个图标,如`\\i[fly]`。 +- 使用`\\c[...]`来修改字体大小,如`\\b[16]`。 +- 使用`\\d`来加粗或者取消粗体。 +- 使用`\\e`来加斜体或取消斜体。 从V2.5.2开始,也允许绘制一张头像图在对话框中,只要通过`\t[1.png]`或`\t[标题,1.png]`的写法。 -**使用`\\i[...]`绘制图标请注意:在事件块中,允许只写一个反斜杠`\i`,系统会自动转义成`\\i`;但是在脚本中必须两个反斜杠都写上!** +**使用`\\i,\\c,\\d,\\e`时请注意:在事件块中,允许只写一个反斜杠`\`,系统会自动转义成`\\`;但是在脚本中必须两个反斜杠都写上!** 详细信息请参见[剧情文本控制](event#text:显示一段文字(剧情))中的说明。 diff --git a/_docs/event.md b/_docs/event.md index 34fff45b..aaf97b4a 100644 --- a/_docs/event.md +++ b/_docs/event.md @@ -1,6 +1,6 @@ # 事件 -?> 目前版本**v2.6.1**,上次更新时间:* {docsify-updated} * +?> 目前版本**v2.6.3**,上次更新时间:* {docsify-updated} * 本章内将对样板所支持的事件进行介绍。 @@ -24,7 +24,7 @@ 它能通过拖动、复制粘贴等方式帮助你快速生成事件列表,而不用手动打大量字符。 -下述所说的都是在事件编辑器右边所展示的,该事件的代码化写法。 +下述所说的都是在事件编辑器右边所展示的,该事件的代码化写法;部分增加了可视化事件编辑器的截图示意(感谢秋橙的制作)。 强烈建议要对每个事件的写法进行了解,因为在脚本编辑,`insertAction`等地方需要插入自定义事件时,还是很有必要的。 @@ -154,6 +154,8 @@ ] ``` +![](img/events/1.jpg) + 该项可以简写成直接的字符串的形式,即下面这种方式也是可以的: ``` js @@ -188,7 +190,9 @@ 从V2.5.2以后,新增了绘制大头像的功能。绘制大头像图的基本写法是`\t[1.png]`或者`\t[标题,1.png]`。 -从V2.6开始,所有图块都允许只写ID,对于非怪物则没有标题。 +从V2.6开始,所有图块都允许只写ID,对于非怪物则仅当图块属性中设置了name才有标题(否则不显示标题)。 + +另外注意的是,名字可以用null从而只显示动画而不显示标题。 ``` js [ @@ -202,10 +206,13 @@ "\t[1.png]绘制1.png这个头像图", "\t[标题,1.png]同时绘制标题和1.png这个头像图", "\t[sword1]获得铁剑,没有标题", - "\t[man]没有标题的npc动画" + "\t[man]没有标题的npc动画", + "\t[null,greenSlime]只绘制怪物动画而不显示标题" ] ``` +![](img/events/2.jpg) + !> 大头像的头像图需要在全塔属性中注册,且必须是png格式,不可以用jpg或者其他格式,请自行转换。 除此以外,我们还能实现“对话框效果”,只要有`\b[...]`就可以。 @@ -231,9 +238,7 @@ ] ``` -从V2.6开始,`\b`提供了更多功能,包括: - -- `\b[hero]` +![](img/events/3.jpg) !> `\t[...]`必须在`\b[...]`前面!不然两者都无法正常显示。 @@ -247,10 +252,14 @@ ] ``` +![](img/events/4.jpg) + 从V2.5.3以后,也可以使用`\f[...]`来同时绘制一张图片。 其基本写法是`\f[img,x,y]`,或者`\f[img,x,y,w,h]`,或者`\f[img,sx,sy,sw,sh,x,y,w,h]`。 +从V2.6.3开始,也可以在最后加上alpha值,即`\f[img,sx,sy,sw,sh,x,y,w,h,alpha]`。 + 需要注意的是,这个图片是绘制在UI层上的,下一个事件执行时即会擦除;同时如果使用了\t的图标动画效果,重叠的地方也会被图标动画给覆盖掉。 ``` js @@ -258,10 +267,13 @@ "\t[勇士]\b[up,hero]\f[1.png,100,100]以(100,100)为左上角绘制1.png图片", "\t[hero]\f[1.png,100,100]\f[2.png,300,300]同时绘制了两张图片", "\f[1.png,100,100,300,300]也可以填写宽高,这样会把图片强制进行放缩到指定的宽高值", - "\f[1.png,64,64,128,128,100,100,128,128]裁剪1.png上以(64,64)开始的128x128图片,并绘制到画布的(100,100)处" + "\f[1.png,64,64,128,128,100,100,128,128]裁剪1.png上以(64,64)开始的128x128图片,并绘制到画布的(100,100)处", + "\f[1.png,64,64,128,128,100,100,128,128,0.5]同上,不透明度0.5", ] ``` +![](img/events/5.jpg) + 从V2.5.5以后,也可以使用`\\i[...]`来在对话框中绘制一个图标。 这里可以使用一个合法ID(32x48图块除外),或使用一个系统图标(`core.statusBar.icons`中的内容)。 @@ -273,10 +285,24 @@ ] ``` +![](img/events/6.jpg) + **可以在控制台中输入`core.statusBar.icons`以查看所有的系统图标定义。** !> 注意,在事件块中,允许只写一个反斜杠`\i`,系统会自动转义成`\\i`;但是在脚本中必须两个反斜杠都写上! +从V2.6.3开始,也可以使用`\\c[...]`来切换当前字体,`\\d`来加粗或取消粗体,`\\e`来加斜体或取消斜体。 + +``` js +[ + "这是原始字体,\\c[20]使用20号字体,\\c[10]使用10号字体", + "\\c如果不加中括号则切换回原始字体。", + "\\d这是粗体\\d取消粗体,\\e加斜体\\e取消斜体" +] +``` + +!> 注意,在事件块中,允许只写一个反斜杠`\c`,系统会自动转义成`\\c`;但是在脚本中必须两个反斜杠都写上!`\d`和`\e`同理。 + 另外值得一提的是,我们是可以在文字中计算一个表达式的值的。只需要将表达式用 `${ }`整个括起来就可以。 ``` js @@ -299,6 +325,8 @@ ] ``` +![](img/events/7.jpg) + - `status:xxx` 获取勇士属性时只能使用如下几个:hp(生命值),atk(攻击力),def(防御力),mdef(魔防值),money(金币),experience(经验),x(勇士的横坐标),y(勇士的纵坐标),direction(勇士的方向)。 - `item:xxx` 中的xxx为道具ID。所有道具的ID定义在items.js中,请自行查看。例如,`item:centerFly` 代表中心对称飞行器的个数。 - `flag:xxx` 中的xxx为一个自定义的变量/Flag(支持中文);如果没有对其进行赋值则默认值为0。 @@ -314,6 +342,8 @@ ] ``` +![](img/events/8.jpg) + text为文本正文内容,和上面的写法完全一致。 time为可选项,代表该自动文本的时间。可以不指定,不指定默认为3000毫秒。 @@ -334,6 +364,8 @@ time为可选项,代表该自动文本的时间。可以不指定,不指定 ] ``` +![](img/events/9.jpg) + text为正文文本内容。可以使用`${ }`来计算表达式的值,且使用`\n`手动换行。系统不会对滚动剧情文本进行自动换行。 time为可选项,代表总的滚动时间。默认为5000毫秒。 @@ -359,6 +391,8 @@ async可选,如果为true则会异步执行(即不等待当前事件执行 ] ``` +![](img/events/10.jpg) + title为可选项,如果设置则为一个RGB三元组或RGBA四元组,表示标题(名字)颜色。 默认值:`[255,215,0,1]` text为可选项,如果设置则为一个RGB三元组或RGBA四元组,表示正文颜色。 默认值:`[255,255,255,1]` @@ -389,6 +423,8 @@ time为可选项,表示文字添加的速度。若此项设置为0将直接全 ] ``` +![](img/events/11.jpg) + text必填,为显示的内容,支持`${}`的表达式计算。 icon是可选的,如果设置则会绘制图标,其可以是一个有效的ID,或者`core.statusBar.icons`中的系统图标。 @@ -403,6 +439,8 @@ icon是可选的,如果设置则会绘制图标,其可以是一个有效的I ] ``` +![](img/events/12.jpg) + 这个事件将在运行时被游戏跳过。 ### setValue:设置勇士的某个属性、道具个数,或某个变量/Flag的值 @@ -436,6 +474,8 @@ value是一个表达式,将通过这个表达式计算出的结果赋值给nam ] ``` +![](img/events/13.jpg) + 另外注意一点的是,如果hp被设置成了0或以下,将触发lose事件,直接死亡。 ### addValue:增减勇士的某个属性、道具个数,或某个变量/Flag的值 @@ -455,6 +495,8 @@ value是一个表达式,将通过这个表达式计算出的结果赋值给nam ] ``` +![](img/events/14.jpg) + ### setFloor:设置楼层属性 使用`{"type":"setFloor"}`可以设置某层楼的楼层属性。 @@ -471,6 +513,8 @@ value是一个表达式,将通过这个表达式计算出的结果赋值给nam ] ``` +![](img/events/15.jpg) + name为必填项,代表要修改的楼层属性,和楼层属性中的一一对应。 floorId为可选项,代表要修改的楼层ID;可以省略代表当前楼层。 @@ -489,6 +533,8 @@ value为必填项,代表要修改到的数值。其应该和楼层属性中的 ] ``` +![](img/events/16.jpg) + name必填项,代表要修改的全局属性。 value为必填项,代表要修改到的结果。此项无需再手动加单引号。 @@ -503,6 +549,8 @@ value为必填项,代表要修改到的结果。此项无需再手动加单引 ] ``` +![](img/events/17.jpg) + name必填项,代表要修改的全局数值,其和全塔属性中的values一一对应。 value为必填项,代表要修改到的结果。该项必须是个数值。 @@ -517,6 +565,8 @@ value为必填项,代表要修改到的结果。该项必须是个数值。 ] ``` +![](img/events/18.jpg) + name必填项,代表要修改的系统开关,其是全塔属性中的flags中的一部分。 value为必填项,只能为true或false,代表要修改到的结果。 @@ -537,6 +587,8 @@ value为必填项,只能为true或false,代表要修改到的结果。 ] ``` +![](img/events/19.jpg) + show事件需要用loc指定目标点的坐标,可以简单的写[x,y]代表一个点,也可以写个二维数组[[x1,y1],[x2,y2],...]来同时显示多个点。 从V2.2开始,loc也可以用变量来代替,例如 `"loc": ["flag:x", "flag:y"]`。下同。 @@ -575,6 +627,8 @@ NPC对话事件结束后如果需要NPC消失也需要调用 `{"type": "hide"}` ] ``` +![](img/events/20.jpg) + ### trigger:立即触发另一个地点的事件 `{"type":"trigger"}` 会立刻触发当层另一个地点的自定义事件。 @@ -588,6 +642,8 @@ NPC对话事件结束后如果需要NPC消失也需要调用 `{"type": "hide"}` ] ``` +![](img/events/21.jpg) + 其后面带有loc选项,代表另一个地点的坐标。 keep可选,如果此项为true则不会结束当前的事件列表,否则会中断当前的事件流。 @@ -613,6 +669,8 @@ keep可选,如果此项为true则不会结束当前的事件列表,否则会 ] ``` +![](img/events/22.jpg) + `insert`的写法有两种,可以写`name`,或者`loc`。 - 如果写了`"name": "xxx"`,则会去公共事件列表中找寻对应的事件,并执行。 @@ -650,6 +708,8 @@ revisit和trigger完全相同,只不过是立刻触发的还是本地点的事 ] ``` +![](img/events/23.jpg) + revisit其实是trigger的简写,只不过是loc固定为当前点。 revisit常常使用在一些商人之类的地方,当用户购买物品后不是离开,而是立刻重新访问重新进入购买页面。 @@ -669,6 +729,8 @@ revisit常常使用在一些商人之类的地方,当用户购买物品后不 ] ``` +![](img/events/24.jpg) + ### setBlock:设置某个图块 我们可以采用 `{"type": "setBlock"}` 来改变某个地图块。 @@ -682,6 +744,8 @@ revisit常常使用在一些商人之类的地方,当用户购买物品后不 ] ``` +![](img/events/25.jpg) + floorId为可选的,表示要更改的目标楼层。如果忽略此项,则默认为当前楼层。 loc为可选的,表示要更改地图块的坐标。如果忽略此项,则默认为当前事件点。 @@ -712,6 +776,8 @@ number为**要更改到的数字**,有关“数字”的定义详见参见[素 ] ``` +![](img/events/26.jpg) + loc为要隐藏的贴图的左上角坐标,可以简单的写[x,y]代表一个点,也可以写个二维数组[[x1,y1],[x2,y2],...]来同时显示多个点。 如果同时存在若干个贴图都是是该坐标为左上角,则这些贴图全部会被隐藏。 @@ -744,6 +810,8 @@ floorId为目标点的楼层,如果是当前楼层可以忽略不写。 ] ``` +![](img/events/27.jpg) + name为必选的,且只能是`bg`和`fg`之一,分别代表背景图层和前景图层。 loc为要隐藏的贴图的左上角坐标,可以简单的写[x,y]代表一个点,也可以写个二维数组[[x1,y1],[x2,y2],...]来同时显示多个点。 @@ -774,6 +842,8 @@ floorId为目标点的楼层,如果是当前楼层可以忽略不写。 ] ``` +![](img/events/28.jpg) + name为必选的,且只能是`bg`和`fg`之一,分别代表背景层和前景层。 floorId为可选的,表示要更改的目标楼层。如果忽略此项,则默认为当前楼层。 @@ -794,6 +864,8 @@ loc为可选的,表示要更改地图块的坐标。如果忽略此项,则 ] ``` +![](img/events/29.jpg) + name是可选的,代表目标行走图的文件名。 !> **目标行走图必须在全塔属性的this.images中被定义过,且宽度必须是128像素(高度不限)。** @@ -816,6 +888,14 @@ name是可选的,代表目标行走图的文件名。 使用`{"type": "showStatusBar"}`会重新显示状态栏。 +### hideHero:隐藏勇士 + +使用`{"type": "hideHero"}`可以隐藏勇士。 + +### showHero:显示勇士 + +使用`{"type": "showHero"}`会重新显示勇士。 + ### updateEnemys:更新怪物数据 使用 `{"type": "updateEnemys"}` 可以动态修改怪物数据。 @@ -836,6 +916,8 @@ name是可选的,代表目标行走图的文件名。 ] ``` +![](img/events/30.jpg) + 默认的等待事件可以被Ctrl跳过,下面两种情况下不可呗跳过: - 加上`"noSkip": true`后 - 当前存在尚未执行完毕的异步事件。 @@ -851,6 +933,8 @@ name是可选的,代表目标行走图的文件名。 ], ``` +![](img/events/31.jpg) + 从V2.6开始,有两种写法: - 写id,则视为和空降怪物进行强制战斗,不会执行一些战后事件,也不会隐藏任何点。 - 写loc(可选,不填默认当前点),则视为和某点怪物进行强制战斗,会隐藏该点并且插入该点战后事件执行。 @@ -871,6 +955,8 @@ name是可选的,代表目标行走图的文件名。 ] ``` +![](img/events/32.jpg) + loc指定门的坐标,floorId指定门所在的楼层ID。如果是当前层则可以忽略floorId选项。 如果loc所在的点是一个墙壁,则作为暗墙来开启。 @@ -896,6 +982,8 @@ async可选,如果为true则会异步执行(即不等待当前事件执行 ] ``` +![](img/events/33.jpg) + id为你要关门的ID,需要是一个合法的门,系统默认只支持如下几种: ``` @@ -924,6 +1012,8 @@ changeFloor的事件写法大致如下。 ] ``` +![](img/events/34.jpg) + 可以看到,与上面的楼梯、传送门的写法十分类似。 但是相比那个而言,不支持stair楼梯位置(只能写坐标),没有穿透选项。 @@ -948,6 +1038,8 @@ time为可选的,指定的话将作为楼层切换动画的时间。 ] ``` +![](img/events/35.jpg) + ### useItem:使用道具 调用`{"type": "useItem"}`可以使用一个道具。 @@ -960,6 +1052,8 @@ time为可选的,指定的话将作为楼层切换动画的时间。 ] ``` +![](img/events/36.jpg) + 使用道具事件会消耗对应的道具。 如果当前不可使用该道具(如没有,或者达不到使用条件),则会进行提示并跳过本事件。 @@ -996,7 +1090,7 @@ name所指定的图片必须存在,在全塔属性中的images中被定义过 ``` js [ {"type": "unfollow", "name": "npc.png"}, // 将 npc.png 这个行走图取消跟随 - {"type": "follow"}, // 取消所有跟随 + {"type": "unfollow"}, // 取消所有跟随 ] ``` @@ -1029,6 +1123,8 @@ async可选,如果为true则会异步执行(即不等待当前事件执行 ] ``` +![](img/events/37.jpg) + name为动画名,**请确保动画在全塔属性中的animates中被定义过。** loc为动画的位置,可以是`[x,y]`表示在(x,y)点显示,也可以是字符串`"hero"`表示在勇士点显示。 @@ -1052,6 +1148,8 @@ loc可忽略,如果忽略则显示为事件当前点。 ] ``` +![](img/events/38.jpg) + code为图片编号,如果两张图片重叠,编号较大会覆盖编号较小的。该值需要在1~50之间。 image为图片名。**请确保图片在全塔属性中的images中被定义过。** @@ -1138,6 +1236,8 @@ loc为动图左上角坐标,以像素为单位进行计算。 ] ``` +![](img/events/39.jpg) + code为图片编号。该值需要在1~50之间。 to为终点图片左上角坐标,以像素为单位进行计算,不填写则视为当前图片位置。 @@ -1160,6 +1260,8 @@ async可选,如果为true则会异步执行(即不等待当前事件执行 ] ``` +![](img/events/40.jpg) + color为需要更改画面色调的颜色。它是一个数组,分别指定目标颜色的R,G,B,A值。 - 常见RGB颜色: 纯黑[0,0,0],纯白[255,255,255],纯红[255,0,0],等等。 - 第四元为Alpha值,即不透明度,为一个0到1之间的数。可以不指定,则默认为Alpha=1 @@ -1227,6 +1329,8 @@ level为天气的强度等级,在1-10之间。1级为最弱,10级为最强 ] ``` +![](img/events/41.jpg) + time选项必须指定,为每移动一步所需要用到的时间。 loc为需要移动的事件位置。可以省略,如果省略则移动本事件。 @@ -1257,6 +1361,8 @@ keep为一个可选项,代表该事件移动完毕后是否消失。如果该 } ``` +![](img/events/42.jpg) + 即,在移动的到达点指定一个事件,然后move事件中指定"keep":true,然后就可以触发目标点的事件了。 async可选,如果为true则会异步执行(即不等待当前事件执行完毕,立刻执行下一个事件)。 @@ -1335,6 +1441,8 @@ async可选,如果为true则会异步执行(即不等待当前事件执行 目前支持mp3/ogg/wav等多种格式的音乐播放。 +从V2.6.3开始,还提供了keep项。如果此项为真,则会记录该bgm,并且持续到下次调用本事件位置(楼层切换不改变bgm,读档也有效)。 + 有关BGM播放的详细说明参见[背景音乐](element#背景音乐) ### pauseBgm:暂停背景音乐 @@ -1381,6 +1489,8 @@ async可选,如果为true则会异步执行(即不等待当前事件执行 使用方法: `{"type": "setVolume", "value": 90, "time": 500, "async": true}` +![](img/events/43.jpg) + value为音量大小,在0到100之间,默认为100。设置后,BGM将使用该音量进行播放。SE的音量大小不会发生改变。 可以设置time为音量渐变时间。 @@ -1440,6 +1550,8 @@ async可选,如果为true则会异步执行(即不等待当前事件执行 ] ``` +![](img/events/44.jpg) + text为提示文字,可以在这里给输入提示文字。这里同样可以使用${ }来计算表达式的值。 当执行input事件时,将显示一个弹窗,并提示用户输入一个内容。 @@ -1459,6 +1571,8 @@ text为提示文字,可以在这里给输入提示文字。这里同样可以 ] ``` +![](img/events/45.jpg) + text为提示文字,可以在这里给输入提示文字。这里同样可以使用${ }来计算表达式的值。 当执行input2事件时,将显示一个弹窗,并提示用户输入一个内容。 @@ -1510,6 +1624,8 @@ text为提示文字,可以在这里给输入提示文字。这里同样可以 ] ``` +![](img/events/46.jpg) + 需要额外注意的几点: - 给定的表达式(condition)一般需要返回true或false。 @@ -1575,6 +1691,8 @@ nobreak是可选的,如果设置,则在当前条件满足并插入事件后 ] ``` +![](img/events/47.jpg) + 需要额外注意的几点: - 各个条件分支的判断是顺序执行的,因此若多个分支的条件都满足,将只执行最靠前的分支。 @@ -1603,6 +1721,7 @@ nobreak是可选的,如果设置,则在当前条件满足并插入事件后 ] ``` +![](img/events/48.jpg) ### choices:给用户提供选项 @@ -1708,12 +1827,16 @@ yes和no均为必填项,即用户点击确认或取消后执行的事件。 ] ``` +![](img/events/49.jpg) + ### dowhile:后置条件循环 `type:dowhile`可以制作一个后置条件循环。 其写法与参数和`type:while`完全一致,不过与其不同的是,会先执行一次事件列表,再对条件进行判定,就和C/C++中的 `do {...} while (...);` 语法一样。 +![](img/events/50.jpg) + ### break:跳出循环 使用 `{"type": "break"}` 可以跳出当前循环。 @@ -1743,6 +1866,8 @@ yes和no均为必填项,即用户点击确认或取消后执行的事件。 ] ``` +![](img/events/51.jpg) + !> 如果continue事件不在任何循环中被执行,则和exit等价,即会立刻结束当前事件! ### wait:等待用户操作 @@ -1782,6 +1907,8 @@ yes和no均为必填项,即用户点击确认或取消后执行的事件。 ] ``` +![](img/events/52.jpg) + ### waitAsync:等待所有异步事件执行完毕 上面有很多很多的异步事件(也就是执行时不等待执行完毕)。 @@ -1795,6 +1922,290 @@ yes和no均为必填项,即用户点击确认或取消后执行的事件。 该事件会进行等待,直到所有可能的异步事件(异步动画除外)执行完毕。 +### previewUI:UI绘制并预览 + +此项可在地图编辑器中预览UI界面的绘制效果。 + +在编辑器中将会把此项包含的所有UI绘制事件进行绘制从而可以进行预览。 + +值得注意的是,在游戏中,UI绘制事件都是绘制在uievent层上的。 + +### clearMap:清除画布 + +UI绘制事件。 + +`{"type": "clearMap"}`可以清除`uievent`画布的内容。 + +```js +[ + {"type": "clearMap", "x": 0, "y": 0, "width": "flag:width", "height": 416}, // 清除画布的一部分 + {"type": "clearMap"}, // 清空并删除画布 +] +``` + +x, y, width, height均可选,表示要清除的坐标和长宽。也可以使用`flag:xxx`。 + +如果存在某一项不填则会清空全部画布并删除。 + +### setAttribute:设置画布属性 + +UI绘制事件。 + +此项可以设置`uievent`画布的各项属性。 + +```js +[ + {"type": "setAttribute", "font": "17px Verdana", "fillStyle": [255,0,0,1]}, +] +``` + +可以选择性的设置如下几项内容: +- `font`:字体,必须是`[italic] [bold] 14px Verdana`这种形式 +- `fillStyle`:填充样式,必须是三元组RGB或四元组RGBA +- `strokeStyle`:边框样式,必须是三元组RGB或者四元组RGBA +- `lineWidth`:线宽度,必须是正整数 +- `alpha`:不透明度,必须是0到1之间的浮点数 +- `align`:对齐方式,只能是`left`, `center`, `right`,分别代表左对齐,居中和右对齐 +- `baseline`:基准线,只能是`top`, `middle`, `alphabetic`, `bottom`,分别代表顶部,居中,标准值和底部。 +- `z`:画布的z值,必须是正整数。初始创建时画布的z值是135。请注意,闪烁光标所在画布的z值永远比该画布大1。 + +### fillText:绘制文本 + +UI绘制事件。 + +此项可以绘制一行文本。 + +```js +[ + {"type": "fillText", "text":"要绘制的文本", "x": 10, "y": 20, "maxWidth": 50} +] +``` + +text必填,为要绘制的文本,支持`${}`的写法,不支持一切转义字符或换行符。 + +x和y必填,为要绘制的左上角坐标。请使用`setAttribute`来设置绘制的对齐方式和基准线。 + +style可选,如果设置需要是三元组RGB或四元组RBGA,代表绘制样式。 + +font可选,如果设置则是要绘制的字体。 + +maxWidth可选,如果设置且不为0,则代表要绘制的最大宽度;超过此宽度会自动放缩。 + +### fillBoldText:绘制描边文本 + +UI绘制事件。 + +此项可以绘制一行描边文本。 + +```js +[ + {"type": "fillText", "text":"要绘制的描边文本", "x": 10, "y": 20, "style": [255,0,0,1]} +] +``` + +text必填,为要绘制的文本,支持`${}`的写法,不支持一切转义字符或换行符。 + +x和y必填,为要绘制的左上角坐标。请使用`setAttribute`来设置绘制的对齐方式和基准线。 + +style可选,如果设置需要是三元组RGB或四元组RBGA,代表绘制样式。 + +font可选,如果设置则是要绘制的字体。 + +### drawTextContent:绘制多行文本 + +UI绘制事件。 + +此项可以绘制多行文本。 + +```js +[ + {"type": "drawTextContent", "text":"要绘制的多行文本", "left": 10, "top": 20, "maxWidth": 100} +] +``` + +text必填,为要绘制的文本,支持所有的文字效果(如\n,${},\r,\\i,\\c,\\d,\\e等),但不支持支持\t和\b的语法。 + +left和top必填,为要绘制的起始像素坐标。实际绘制时会将textBaseline设置为'top',因此只需要考虑第一个字的左上角位置。 + +maxWidth可选,为单行最大宽度,超过此宽度将自动换行,不设置不会自动换行。 + +color可选,表示绘制时的颜色,为三元组RGB或四元组RGBA。如果不设置则使用剧情文本设置中的正文颜色。 + +bold可选,是否粗体。如果不设置默认为false。 + +align可选,文字对齐方式,仅在maxWidth设置时有效,默认为'left'。 + +fontSize可选,为字体大小,如果不设置则使用剧情文本设置中的正文字体大小。 + +lineHeight可选,绘制的行距值,如果不设置则使用fontSize*1.3(即1.3倍行距)。 + +此项不支持字体样式的设置,使用的是全塔属性中的全局字体;如有需要请使用“设置全局属性”事件来设置字体样式。 + +### fillRect:绘制矩形 + +UI绘制事件。此项可以绘制一个矩形。 + +```js +[ + {"type": "fillRect", "x": 100, "y": 100, "width": 120, "height": 120, "style": [255,0,0,1]} +] +``` + +x, y, width, height必填,为要绘制的起点坐标和宽高;也可以用`flag:xxx`。 + +color可选,表示绘制时的颜色,为三元组RGB或四元组RGBA。 + +### strokeRect:绘制矩形边框 + +UI绘制事件。此项可以绘制一个矩形边框。 + +```js +[ + {"type": "strokeRect", "x": 100, "y": 100, "width": 120, "height": 120, "style": [255,0,0,1], "lineWidth": 4} +] +``` + +x, y, width, height必填,为要绘制的起点坐标和宽高;也可以用`flag:xxx`。 + +style可选,表示绘制时的颜色,为三元组RGB或四元组RGBA。 + +lineWidth可选,表示边框的线宽。 + +### drawLine:绘制线段 + +UI绘制事件。此事件可以绘制一个函数。 + +```js +[ + {"type": "drawLine", "x1": 0, "y1": 0, "x2": "flag:x", "y2": 200, "style": [255,0,0,1]} +] +``` + +x1, y1, x2, x2必填,为要绘制的起点和终点坐标;也可以用`flag:xxx`的写法。 + +style可选,表示绘制时的颜色,为三元组RGB或四元组RGBA。 + +lineWidth可选,表示边框的线宽。 + +### drawArrow:绘制箭头 + +UI绘制事件。此事件可以绘制一个箭头。 + +参数和写法与`drawLine`完全一致,只不过是会多画一个箭头标记。 + +### fillPolygon:绘制多边形 + +UI绘制事件。此事件可以绘制一个多边形。 + +```js +[ + {"type": "fillPolygon", "nodes": [[0,0],[0,100],[100,0]], "style": [255,0,0,1]} +] +``` + +nodes必填,为一个二维数组,其中每一项都是多边形一个顶点坐标。(与显示/隐藏事件写法相同) + +style可选,表示绘制时的颜色,为三元组RGB或四元组RGBA。 + +### strokePolygon:绘制多边形边框 + +UI绘制事件。此事件可以绘制一个多边形边框。 + +参数列表和`fillPolygon`基本相同,不过多了一个`lineWidth`表示的绘制线宽。 + +### fillCircle:绘制圆 + +UI绘制事件。此项可以绘制一个圆。 + +```js +[ + {"type": "fillCircle", "x": 100, "y": 100, "r": 10, "style": [255,0,0,1]} +] +``` + +x, y, r必填,为要绘制的圆心和半径;也可以用`flag:xxx`。 + +color可选,表示绘制时的颜色,为三元组RGB或四元组RGBA。 + +### strokeCircle:绘制圆边框 + +UI绘制事件。此项可以绘制一个圆边框。 + +参数列表和`fillCircle`基本相同,不过多了一个`lineWidth`表示的绘制线宽。 + +### drawImage:绘制图片 + +UI绘制事件。此事件可以绘制一个图片。 + +```js +[ + {"type": "drawImage", "image": "bg.jpg", "x": 0, "y": 0}, // 在(0,0)绘制bg.jpg + {"type": "drawImage", "image": "bg.jpg", "x": 0, "y": 0, "w": 100, "h": 100}, // 在(0,0)绘制bg.jpg,且放缩到100x100 + // 裁剪并放缩图片 + {"type": "drawImage", "image": "bg.jpg", "x": 0, "y": 0, "w": 100, "h": 100, "x1": 0, "y1": 0, "w1": 100, "h1": 100} +] +``` + +image必填,为图片名。图片必须在全塔属性中被注册过。 + +此函数有三种写法: + +- 只写x和y:表示要绘制到的位置。 +- 写x, y, w, h:表示要绘制到的位置,且将图片放缩到指定宽高。 +- 写x, y, w, h, x1, y1, w1, h1:从原始图片上裁剪[x,y,w,h]的图片,并绘制画布上的[x1,y1,w1,h1] + +可以查看下面的文档以了解各项参数的信息: +http://www.w3school.com.cn/html5/canvas_drawimage.asp + +### drawIcon:绘制图标 + +UI绘制事件。此事件可以绘制一个图标。 + +```js +[ + {"type": "drawIcon", "id": "yellowKey", "x": 100, "y": 100}, // 在(100,100)绘制黄钥匙 +] +``` + +id必填,为要绘制的图标ID。可以是一个注册过的图标ID,也可以使用状态栏的图标ID,例如lv, hp, up, save, settings等。 + +x, y必填,为要绘制的左上角坐标。width和height可选,如果设置则会将图标放缩成对应的宽高。 + +### drawBackground:绘制背景图 + +UI绘制事件。此事件可以绘制一个背景图。 + +```js +[ + {"type": "drawBackground", "background": "winskin.png", "x": 0, "y": 0, "width": 100, "height": 100}, +] +``` + +background必填,为要绘制的背景图内容。其可以是一个三元组RGB或四元组RGBA(纯色绘制),或一个WindowSkin的图片名。 + +x, y, width, height必填,分别为要绘制的起点坐标和长宽。 + +可以使用“设置画布属性”来设置不透明度和纯色绘制时的边框颜色。 + +### drawSelector:绘制闪烁光标 + +UI绘制事件。此事件可以绘制闪烁光标。 + +```js +[ + {"type": "drawSelector", "image": "winskin.png", "x": 0, "y": 0, "width": 100, "height": 100}, + {"type": "drawSelector"} // 清除闪烁光标 +] +``` + +image为要绘制的WindowSkin图片名;如果不填则视为“清除闪烁光标”。 + +x, y, width, height分别为要绘制的起点坐标和长宽。 + +请注意,同时只会有一个闪烁光标存在,如果创建多个则后者会替换前者。 + +闪烁光标将会一直存在即使事件流结束;请使用本事件并不填`image`来清除闪烁光标。 + ### function: 自定义JS脚本 上述给出了这么多事件,但有时候往往不能满足需求,这时候就需要执行自定义脚本了。 @@ -1835,7 +2246,7 @@ core.insertAction([ 从V2.5.3开始,针对每个事件都提供了独立开关。 -独立开关的写法是`switch:A`, `switch:A`直到`switch:Z`,共计26个;不过样板中的值块默认只提供前6个。 +独立开关的写法是`switch:A`, `switch:A`直到`switch:Z`,共计26个。 独立开关算是特殊的flag,它在事件中使用时会和事件的楼层及坐标进行绑定;换句话说每个事件对应的`switch:A`都是不同的。 @@ -1846,6 +2257,8 @@ core.insertAction([ 通过独立开关的方式,我们无需对某些NPC的对话都设立单独的互不重复flag,只需要关注该事件自身的逻辑即可。 +![](img/events/53.jpg) + ## 同一个点的多事件处理 我们可以发现,就目前而且,每个点的事件是和该点进行绑定,并以该点坐标作为唯一索引来查询。 @@ -1890,6 +2303,8 @@ core.insertAction([ } ``` +![](img/events/54.jpg) + ### 获得圣水后变成墙 这个例子要求获得圣水时不前进(也就是不能走到圣水地方),然后把圣水位置变成墙。 @@ -1917,6 +2332,8 @@ core.insertAction([ } ``` +![](img/events/55.jpg) + 总之,记住如下两点: - 可以使用setBlock来更改一个图块。 @@ -2098,11 +2515,13 @@ if (core.flags.enableAddPoint && point > 0) { ] ``` +![](img/events/56.jpg) + `id`, `textInList`, `mustEnable`和上述完全相同。 `commonEvent`为公共事件名,即选择此项时要执行的公共事件。 -`args`为向该公共事件传递的参数,参见[type:insert](#insert:插入公共事件或另一个地点的事件并执行)的说明。 +`args`可选,为向该公共事件传递的参数,参见[type:insert](#insert:插入公共事件或另一个地点的事件并执行)的说明。 ## 系统引发的自定义事件 @@ -2140,6 +2559,8 @@ if (core.flags.enableAddPoint && point > 0) { }, ``` +![](img/events/60.jpg) + !> 多个机关门请分别设置开门变量如door1, door2等等。请勿存在两个机关门用相同的变量! 除此以外,每层楼还提供了`firstArrive`和`eachArrive`事件,分别为首次到达该楼层和每次到达该楼层时执行的事件。 @@ -2259,6 +2680,8 @@ if (core.flags.enableAddPoint && point > 0) { } ``` +![](img/events/57.jpg) + 另外,从V2.6开始,脚本编辑中提供了战前事件`beforeBattle`,这里不再详细展开,如有需求可自行前往研究。 ## 经验升级(进阶/境界塔) @@ -2288,6 +2711,8 @@ if (core.flags.enableAddPoint && point > 0) { ] ``` +![](img/events/58.jpg) + `levelUp`是一个数组,里面分别定义了每个等级的信息。里面每一项有三个参数`need`, `title`, `effect` - `need` 该等级所需要的经验值,可以是个表达式。请确保数组中的need依次递增。 - `title` 该等级的名称,比如“佣兵下级”等。该项可以忽略,以使用系统默认的等级。该项将显示在状态栏中。 @@ -2341,6 +2766,8 @@ if (core.flags.enableAddPoint && point > 0) { ] ``` +![](img/events/59.jpg) + ========================================================================================== [继续阅读下一章:个性化](personalization) diff --git a/_docs/img/events/1.jpg b/_docs/img/events/1.jpg new file mode 100644 index 00000000..6cc44ab5 Binary files /dev/null and b/_docs/img/events/1.jpg differ diff --git a/_docs/img/events/10.jpg b/_docs/img/events/10.jpg new file mode 100644 index 00000000..9e7166a6 Binary files /dev/null and b/_docs/img/events/10.jpg differ diff --git a/_docs/img/events/11.jpg b/_docs/img/events/11.jpg new file mode 100644 index 00000000..c6f3aa1b Binary files /dev/null and b/_docs/img/events/11.jpg differ diff --git a/_docs/img/events/12.jpg b/_docs/img/events/12.jpg new file mode 100644 index 00000000..12551990 Binary files /dev/null and b/_docs/img/events/12.jpg differ diff --git a/_docs/img/events/13.jpg b/_docs/img/events/13.jpg new file mode 100644 index 00000000..af81a7f0 Binary files /dev/null and b/_docs/img/events/13.jpg differ diff --git a/_docs/img/events/14.jpg b/_docs/img/events/14.jpg new file mode 100644 index 00000000..53221968 Binary files /dev/null and b/_docs/img/events/14.jpg differ diff --git a/_docs/img/events/15.jpg b/_docs/img/events/15.jpg new file mode 100644 index 00000000..14aa4cd2 Binary files /dev/null and b/_docs/img/events/15.jpg differ diff --git a/_docs/img/events/16.jpg b/_docs/img/events/16.jpg new file mode 100644 index 00000000..4e77816f Binary files /dev/null and b/_docs/img/events/16.jpg differ diff --git a/_docs/img/events/17.jpg b/_docs/img/events/17.jpg new file mode 100644 index 00000000..a8e94528 Binary files /dev/null and b/_docs/img/events/17.jpg differ diff --git a/_docs/img/events/18.jpg b/_docs/img/events/18.jpg new file mode 100644 index 00000000..8cbe6f94 Binary files /dev/null and b/_docs/img/events/18.jpg differ diff --git a/_docs/img/events/19.jpg b/_docs/img/events/19.jpg new file mode 100644 index 00000000..e250b7bd Binary files /dev/null and b/_docs/img/events/19.jpg differ diff --git a/_docs/img/events/2.jpg b/_docs/img/events/2.jpg new file mode 100644 index 00000000..e2461d34 Binary files /dev/null and b/_docs/img/events/2.jpg differ diff --git a/_docs/img/events/20.jpg b/_docs/img/events/20.jpg new file mode 100644 index 00000000..3c616d9e Binary files /dev/null and b/_docs/img/events/20.jpg differ diff --git a/_docs/img/events/21.jpg b/_docs/img/events/21.jpg new file mode 100644 index 00000000..6cccb422 Binary files /dev/null and b/_docs/img/events/21.jpg differ diff --git a/_docs/img/events/22.jpg b/_docs/img/events/22.jpg new file mode 100644 index 00000000..e814be0c Binary files /dev/null and b/_docs/img/events/22.jpg differ diff --git a/_docs/img/events/23.jpg b/_docs/img/events/23.jpg new file mode 100644 index 00000000..5cad5714 Binary files /dev/null and b/_docs/img/events/23.jpg differ diff --git a/_docs/img/events/24.jpg b/_docs/img/events/24.jpg new file mode 100644 index 00000000..2852e509 Binary files /dev/null and b/_docs/img/events/24.jpg differ diff --git a/_docs/img/events/25.jpg b/_docs/img/events/25.jpg new file mode 100644 index 00000000..d5492386 Binary files /dev/null and b/_docs/img/events/25.jpg differ diff --git a/_docs/img/events/26.jpg b/_docs/img/events/26.jpg new file mode 100644 index 00000000..6eaca21b Binary files /dev/null and b/_docs/img/events/26.jpg differ diff --git a/_docs/img/events/27.jpg b/_docs/img/events/27.jpg new file mode 100644 index 00000000..6c5b3a25 Binary files /dev/null and b/_docs/img/events/27.jpg differ diff --git a/_docs/img/events/28.jpg b/_docs/img/events/28.jpg new file mode 100644 index 00000000..5f6c6a19 Binary files /dev/null and b/_docs/img/events/28.jpg differ diff --git a/_docs/img/events/29.jpg b/_docs/img/events/29.jpg new file mode 100644 index 00000000..a04439c1 Binary files /dev/null and b/_docs/img/events/29.jpg differ diff --git a/_docs/img/events/3.jpg b/_docs/img/events/3.jpg new file mode 100644 index 00000000..b5aff14b Binary files /dev/null and b/_docs/img/events/3.jpg differ diff --git a/_docs/img/events/30.jpg b/_docs/img/events/30.jpg new file mode 100644 index 00000000..c1e9aca2 Binary files /dev/null and b/_docs/img/events/30.jpg differ diff --git a/_docs/img/events/31.jpg b/_docs/img/events/31.jpg new file mode 100644 index 00000000..663f3a30 Binary files /dev/null and b/_docs/img/events/31.jpg differ diff --git a/_docs/img/events/32.jpg b/_docs/img/events/32.jpg new file mode 100644 index 00000000..9a0fddfa Binary files /dev/null and b/_docs/img/events/32.jpg differ diff --git a/_docs/img/events/33.jpg b/_docs/img/events/33.jpg new file mode 100644 index 00000000..10246b96 Binary files /dev/null and b/_docs/img/events/33.jpg differ diff --git a/_docs/img/events/34.jpg b/_docs/img/events/34.jpg new file mode 100644 index 00000000..222ad18b Binary files /dev/null and b/_docs/img/events/34.jpg differ diff --git a/_docs/img/events/35.jpg b/_docs/img/events/35.jpg new file mode 100644 index 00000000..ff8ef556 Binary files /dev/null and b/_docs/img/events/35.jpg differ diff --git a/_docs/img/events/36.jpg b/_docs/img/events/36.jpg new file mode 100644 index 00000000..40a951fa Binary files /dev/null and b/_docs/img/events/36.jpg differ diff --git a/_docs/img/events/37.jpg b/_docs/img/events/37.jpg new file mode 100644 index 00000000..5267ed13 Binary files /dev/null and b/_docs/img/events/37.jpg differ diff --git a/_docs/img/events/38.jpg b/_docs/img/events/38.jpg new file mode 100644 index 00000000..b6ccf550 Binary files /dev/null and b/_docs/img/events/38.jpg differ diff --git a/_docs/img/events/39.jpg b/_docs/img/events/39.jpg new file mode 100644 index 00000000..d30c8d79 Binary files /dev/null and b/_docs/img/events/39.jpg differ diff --git a/_docs/img/events/4.jpg b/_docs/img/events/4.jpg new file mode 100644 index 00000000..d447565f Binary files /dev/null and b/_docs/img/events/4.jpg differ diff --git a/_docs/img/events/40.jpg b/_docs/img/events/40.jpg new file mode 100644 index 00000000..e10f56b7 Binary files /dev/null and b/_docs/img/events/40.jpg differ diff --git a/_docs/img/events/41.jpg b/_docs/img/events/41.jpg new file mode 100644 index 00000000..ec9b7e49 Binary files /dev/null and b/_docs/img/events/41.jpg differ diff --git a/_docs/img/events/42.jpg b/_docs/img/events/42.jpg new file mode 100644 index 00000000..24d0c2f4 Binary files /dev/null and b/_docs/img/events/42.jpg differ diff --git a/_docs/img/events/43.jpg b/_docs/img/events/43.jpg new file mode 100644 index 00000000..cb8f1c31 Binary files /dev/null and b/_docs/img/events/43.jpg differ diff --git a/_docs/img/events/44.jpg b/_docs/img/events/44.jpg new file mode 100644 index 00000000..59b3ecb7 Binary files /dev/null and b/_docs/img/events/44.jpg differ diff --git a/_docs/img/events/45.jpg b/_docs/img/events/45.jpg new file mode 100644 index 00000000..44dec550 Binary files /dev/null and b/_docs/img/events/45.jpg differ diff --git a/_docs/img/events/46.jpg b/_docs/img/events/46.jpg new file mode 100644 index 00000000..1eea4e37 Binary files /dev/null and b/_docs/img/events/46.jpg differ diff --git a/_docs/img/events/47.jpg b/_docs/img/events/47.jpg new file mode 100644 index 00000000..dd7bb88e Binary files /dev/null and b/_docs/img/events/47.jpg differ diff --git a/_docs/img/events/48.jpg b/_docs/img/events/48.jpg new file mode 100644 index 00000000..2086b1c3 Binary files /dev/null and b/_docs/img/events/48.jpg differ diff --git a/_docs/img/events/49.jpg b/_docs/img/events/49.jpg new file mode 100644 index 00000000..f81e0451 Binary files /dev/null and b/_docs/img/events/49.jpg differ diff --git a/_docs/img/events/5.jpg b/_docs/img/events/5.jpg new file mode 100644 index 00000000..333c972c Binary files /dev/null and b/_docs/img/events/5.jpg differ diff --git a/_docs/img/events/50.jpg b/_docs/img/events/50.jpg new file mode 100644 index 00000000..568eabf0 Binary files /dev/null and b/_docs/img/events/50.jpg differ diff --git a/_docs/img/events/51.jpg b/_docs/img/events/51.jpg new file mode 100644 index 00000000..1a3f70c3 Binary files /dev/null and b/_docs/img/events/51.jpg differ diff --git a/_docs/img/events/52.jpg b/_docs/img/events/52.jpg new file mode 100644 index 00000000..b66d2a22 Binary files /dev/null and b/_docs/img/events/52.jpg differ diff --git a/_docs/img/events/53.jpg b/_docs/img/events/53.jpg new file mode 100644 index 00000000..c3e488bb Binary files /dev/null and b/_docs/img/events/53.jpg differ diff --git a/_docs/img/events/54.jpg b/_docs/img/events/54.jpg new file mode 100644 index 00000000..6dbfc95e Binary files /dev/null and b/_docs/img/events/54.jpg differ diff --git a/_docs/img/events/55.jpg b/_docs/img/events/55.jpg new file mode 100644 index 00000000..fff606c2 Binary files /dev/null and b/_docs/img/events/55.jpg differ diff --git a/_docs/img/events/56.jpg b/_docs/img/events/56.jpg new file mode 100644 index 00000000..15fac681 Binary files /dev/null and b/_docs/img/events/56.jpg differ diff --git a/_docs/img/events/57.jpg b/_docs/img/events/57.jpg new file mode 100644 index 00000000..60196800 Binary files /dev/null and b/_docs/img/events/57.jpg differ diff --git a/_docs/img/events/58.jpg b/_docs/img/events/58.jpg new file mode 100644 index 00000000..e9ff8af9 Binary files /dev/null and b/_docs/img/events/58.jpg differ diff --git a/_docs/img/events/59.jpg b/_docs/img/events/59.jpg new file mode 100644 index 00000000..48c58e01 Binary files /dev/null and b/_docs/img/events/59.jpg differ diff --git a/_docs/img/events/6.jpg b/_docs/img/events/6.jpg new file mode 100644 index 00000000..7be2810b Binary files /dev/null and b/_docs/img/events/6.jpg differ diff --git a/_docs/img/events/60.jpg b/_docs/img/events/60.jpg new file mode 100644 index 00000000..408cebb3 Binary files /dev/null and b/_docs/img/events/60.jpg differ diff --git a/_docs/img/events/7.jpg b/_docs/img/events/7.jpg new file mode 100644 index 00000000..546a8bab Binary files /dev/null and b/_docs/img/events/7.jpg differ diff --git a/_docs/img/events/8.jpg b/_docs/img/events/8.jpg new file mode 100644 index 00000000..1c78a313 Binary files /dev/null and b/_docs/img/events/8.jpg differ diff --git a/_docs/img/events/9.jpg b/_docs/img/events/9.jpg new file mode 100644 index 00000000..bb6d752d Binary files /dev/null and b/_docs/img/events/9.jpg differ diff --git a/_docs/index.md b/_docs/index.md index 510bd14c..74d241d7 100644 --- a/_docs/index.md +++ b/_docs/index.md @@ -1,6 +1,6 @@ # HTML5 魔塔样板说明文档 -?> 目前版本**v2.6.1**,上次更新时间:* {docsify-updated} * +?> 目前版本**v2.6.3**,上次更新时间:* {docsify-updated} * 众所周知,魔塔的趋势是向移动端发展,贴吧中也常常能见到“求手机魔塔”的帖子。然而现有的工具中,NekoRPG有着比较大的局限性,游戏感较差,更是完全没法在iOS上运行。而一些APP的魔塔虽然可用,但是必须要下载安装,对于Android和iOS还必须开发不同的版本,非常麻烦。 diff --git a/_docs/personalization.md b/_docs/personalization.md index 72de08cd..d7faa37f 100644 --- a/_docs/personalization.md +++ b/_docs/personalization.md @@ -1,6 +1,6 @@ # 个性化 -?> 目前版本**v2.6.1**,上次更新时间:* {docsify-updated} * +?> 目前版本**v2.6.3**,上次更新时间:* {docsify-updated} * 有时候只靠样板本身可能是不够的。我们需要一些个性化、自定义的素材,道具效果,怪物属性,等等。 @@ -22,6 +22,7 @@ HTML5魔塔是使用画布(canvas)来绘制,存在若干个图层,它们 - paint**[D]**:绘图层;主要用来进行绘图模式。(z-index: 95) - curtain:色调层;用来控制当前楼层的画面色调 (z-index: 125) - image1\~50**[D]**:图片层;用来绘制图片等操作。(z-index: 100+code, 101~150) +- uievent**[D]**:自定义UI绘制层;用来进行自定义UI绘制等操作。(z-index:135,可以通过事件设置该值) - ui:UI层;用来绘制一切UI窗口,如剧情文本、怪物手册、楼传器、系统菜单等等 (z-index: 140) - data:数据层;用来绘制一些顶层的或更新比较快的数据,如左上角的提示,战斗界面中数据的变化等等。 (z-index: 170) @@ -29,6 +30,8 @@ HTML5魔塔是使用画布(canvas)来绘制,存在若干个图层,它们 而,色调层的z-index是25,ui层的z-index是140;因此,图片编号在1~24的将被色调层遮挡,25~40的将被ui层遮挡,41~50的将遮挡UI层。 +uievent层为自定义UI绘制所在的层,其z值初始是135,可以通过事件设置;自定义绘制的闪烁光标所在层的z值永远比该值大1。 + ### 动态创建canvas 从V2.5.3开始,可以在H5样板中任意动态创建canvas并进行使用。 @@ -559,8 +562,6 @@ core.statusBar.speed.innerHTML = core.getFlag('speed', 0); 如果flag:skill不为0,则代表当前处于某个技能开启状态,且状态栏显示flag:skillName值。伤害计算函数中只需要对flag:skill进行处理即可。 -!> 关于魔力上限:样板中默认没有提供status:manamax - ### 状态栏的显示 从V2.5开始,魔力值和技能名的状态栏项目已经被添加,可以直接使用。 diff --git a/_docs/script.md b/_docs/script.md index c6d0aeff..44e31e2d 100644 --- a/_docs/script.md +++ b/_docs/script.md @@ -1,6 +1,6 @@ # 脚本 -?> 目前版本**v2.6.1**,上次更新时间:* {docsify-updated} * +?> 目前版本**v2.6.3**,上次更新时间:* {docsify-updated} * 在V2.6版本中,基本对整个项目代码进行了重写,更加方便造塔者的使用和复写函数。 diff --git a/_docs/start.md b/_docs/start.md index 87319f4c..ced7faa1 100644 --- a/_docs/start.md +++ b/_docs/start.md @@ -1,6 +1,6 @@ # 快速上手 -?> 目前版本**v2.6.1**,上次更新时间:* {docsify-updated} * +?> 目前版本**v2.6.3**,上次更新时间:* {docsify-updated} * 在这一节中,将详细介绍做一部塔的流程。现在,让我们来做一部单层塔! diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4 index d8593e39..79b11511 100644 --- a/_server/MotaAction.g4 +++ b/_server/MotaAction.g4 @@ -10,7 +10,7 @@ event_m /* event_m tooltip : 编辑魔塔的事件 -helpUrl : https://h5mota.com/games/template/docs/#/event +helpUrl : https://h5mota.com/games/template/_docs/#/event default : [false,null,null,null,null] B_0_List_0=eval(B_0_List_0); var code = { @@ -33,7 +33,7 @@ level_m /* level_m tooltip : 升级事件 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=%e7%bb%8f%e9%aa%8c%e5%8d%87%e7%ba%a7%ef%bc%88%e8%bf%9b%e9%98%b6%2f%e5%a2%83%e7%95%8c%e5%a1%94%ef%bc%89 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=%e7%bb%8f%e9%aa%8c%e5%8d%87%e7%ba%a7%ef%bc%88%e8%bf%9b%e9%98%b6%2f%e5%a2%83%e7%95%8c%e5%a1%94%ef%bc%89 var code = '[\n'+levelCase_0+']\n'; return code; */; @@ -44,7 +44,7 @@ levelCase /* levelCase tooltip : 升级设定 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=%e7%bb%8f%e9%aa%8c%e5%8d%87%e7%ba%a7%ef%bc%88%e8%bf%9b%e9%98%b6%2f%e5%a2%83%e7%95%8c%e5%a1%94%ef%bc%89 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=%e7%bb%8f%e9%aa%8c%e5%8d%87%e7%ba%a7%ef%bc%88%e8%bf%9b%e9%98%b6%2f%e5%a2%83%e7%95%8c%e5%a1%94%ef%bc%89 default : [0,"",false,null] colour : this.subColor Bool_0 = Bool_0?', "clear": true':''; @@ -58,7 +58,7 @@ shop_m /* shop_m tooltip : 全局商店列表 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=%e5%85%a8%e5%b1%80%e5%95%86%e5%ba%97 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=%e5%85%a8%e5%b1%80%e5%95%86%e5%ba%97 var code = '['+shoplist_0+']\n'; return code; */; @@ -83,7 +83,7 @@ shopcommonevent /* shopcommonevent tooltip : 全局商店, 执行一个公共事件 -helpUrl : https://h5mota.com/games/template/docs/#/ +helpUrl : https://h5mota.com/games/template/_docs/#/ default : ["shop1","回收钥匙商店",false,"回收钥匙商店",""] if (EvalString_2) { if (EvalString_2.indexOf('"')>=0) @@ -109,12 +109,12 @@ return code; */; shopsub - : '商店 id' IdString '标题' EvalString '图标' IdString BGNL? Newline '快捷商店栏中名称' EvalString '共用times' Bool BGNL? Newline '未开启状态则不显示在列表中' Bool BGNL? NewLine '使用' ShopUse_List '消耗' EvalString BGNL? Newline '显示文字' EvalString BGNL? Newline shopChoices+ BEND + : '商店 id' IdString '标题' EvalString '图标' IdString BGNL? Newline '快捷商店栏中名称' EvalString '共用times' Bool BGNL? Newline '未开启状态则不显示在列表中' Bool BGNL? Newline '使用' ShopUse_List '消耗' EvalString BGNL? Newline '显示文字' EvalString BGNL? Newline shopChoices+ BEND /* shopsub tooltip : 全局商店,消耗填-1表示每个选项的消耗不同,正数表示消耗数值 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=%e5%85%a8%e5%b1%80%e5%95%86%e5%ba%97 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=%e5%85%a8%e5%b1%80%e5%95%86%e5%ba%97 default : ["shop1","贪婪之神","blueShop","1F金币商店",false,false,null,"20+10*times*(times+1)","勇敢的武士啊, 给我${need}金币就可以:"] var code = { 'id': IdString_0, @@ -138,7 +138,7 @@ shopChoices /* shopChoices tooltip : 商店选项,商店消耗是-1时,这里的消耗对应各自选项的消耗,商店消耗不是-1时这里的消耗不填 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=%e5%85%a8%e5%b1%80%e5%95%86%e5%ba%97 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=%e5%85%a8%e5%b1%80%e5%95%86%e5%ba%97 default : ["攻击+1",""] colour : this.subColor EvalString_1 = EvalString_1 && (', "need": "'+EvalString_1+'"'); @@ -163,7 +163,7 @@ afterBattle_m /* afterBattle_m tooltip : 系统引发的自定义事件 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=%e7%b3%bb%e7%bb%9f%e5%bc%95%e5%8f%91%e7%9a%84%e8%87%aa%e5%ae%9a%e4%b9%89%e4%ba%8b%e4%bb%b6 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=%e7%b3%bb%e7%bb%9f%e5%bc%95%e5%8f%91%e7%9a%84%e8%87%aa%e5%ae%9a%e4%b9%89%e4%ba%8b%e4%bb%b6 var code = '[\n'+action_0+']\n'; return code; */; @@ -175,7 +175,7 @@ afterGetItem_m /* afterGetItem_m tooltip : 系统引发的自定义事件 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=%e7%b3%bb%e7%bb%9f%e5%bc%95%e5%8f%91%e7%9a%84%e8%87%aa%e5%ae%9a%e4%b9%89%e4%ba%8b%e4%bb%b6 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=%e7%b3%bb%e7%bb%9f%e5%bc%95%e5%8f%91%e7%9a%84%e8%87%aa%e5%ae%9a%e4%b9%89%e4%ba%8b%e4%bb%b6 var code = '[\n'+action_0+']\n'; return code; */; @@ -187,7 +187,7 @@ afterOpenDoor_m /* afterOpenDoor_m tooltip : 系统引发的自定义事件 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=%e7%b3%bb%e7%bb%9f%e5%bc%95%e5%8f%91%e7%9a%84%e8%87%aa%e5%ae%9a%e4%b9%89%e4%ba%8b%e4%bb%b6 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=%e7%b3%bb%e7%bb%9f%e5%bc%95%e5%8f%91%e7%9a%84%e8%87%aa%e5%ae%9a%e4%b9%89%e4%ba%8b%e4%bb%b6 var code = '[\n'+action_0+']\n'; return code; */; @@ -199,7 +199,7 @@ firstArrive_m /* firstArrive_m tooltip : 首次到达楼层 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=%e7%b3%bb%e7%bb%9f%e5%bc%95%e5%8f%91%e7%9a%84%e8%87%aa%e5%ae%9a%e4%b9%89%e4%ba%8b%e4%bb%b6 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=%e7%b3%bb%e7%bb%9f%e5%bc%95%e5%8f%91%e7%9a%84%e8%87%aa%e5%ae%9a%e4%b9%89%e4%ba%8b%e4%bb%b6 var code = '[\n'+action_0+']\n'; return code; */; @@ -211,7 +211,7 @@ eachArrive_m /* eachArrive_m tooltip : 每次到达楼层 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=%e7%b3%bb%e7%bb%9f%e5%bc%95%e5%8f%91%e7%9a%84%e8%87%aa%e5%ae%9a%e4%b9%89%e4%ba%8b%e4%bb%b6 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=%e7%b3%bb%e7%bb%9f%e5%bc%95%e5%8f%91%e7%9a%84%e8%87%aa%e5%ae%9a%e4%b9%89%e4%ba%8b%e4%bb%b6 var code = '[\n'+action_0+']\n'; return code; */; @@ -223,12 +223,12 @@ changeFloor_m /* changeFloor_m tooltip : 楼梯, 传送门, 如果目标楼层有多个楼梯, 写upFloor或downFloor可能会导致到达的楼梯不确定, 这时候请使用loc方式来指定具体的点位置 -helpUrl : https://h5mota.com/games/template/docs/#/element?id=%e8%b7%af%e9%9a%9c%ef%bc%8c%e6%a5%bc%e6%a2%af%ef%bc%8c%e4%bc%a0%e9%80%81%e9%97%a8 -default : [null,"MT1",null,0,0,null,500,null] +helpUrl : https://h5mota.com/games/template/_docs/#/element?id=%e8%b7%af%e9%9a%9c%ef%bc%8c%e6%a5%bc%e6%a2%af%ef%bc%8c%e4%bc%a0%e9%80%81%e9%97%a8 +default : [null,"MTx",null,0,0,null,500,null] var toFloorId = IdString_0; if (Floor_List_0!='floorId') toFloorId = Floor_List_0; var loc = ', "loc": ['+Number_0+', '+Number_1+']'; -if (Stair_List_0==='now')loc = ''; +if (Stair_List_0===':now') loc = ''; else if (Stair_List_0!=='loc')loc = ', "stair": "'+Stair_List_0+'"'; DirectionEx_List_0 = DirectionEx_List_0 && (', "direction": "'+DirectionEx_List_0+'"'); Int_0 = (Int_0!=='') ?(', "time": '+Int_0):''; @@ -244,7 +244,7 @@ commonEvent_m /* commonEvent_m tooltip : 公共事件 -helpUrl : https://h5mota.com/games/template/docs/#/event +helpUrl : https://h5mota.com/games/template/_docs/#/event var code = '[\n'+action_0+']\n'; return code; */; @@ -282,6 +282,8 @@ action | update_s | showStatusBar_s | hideStatusBar_s + | showHero_s + | hideHero_s | updateEnemys_s | sleep_s | wait_s @@ -293,6 +295,8 @@ action | changeFloor_s | changePos_0_s | changePos_1_s + | setViewport_s + | moveViewport_s | useItem_s | openShop_s | disableShop_s @@ -341,6 +345,27 @@ action | callSave_s | autoSave_s | callLoad_s + | previewUI_s + | clearMap_s + | clearMap_1_s + | setAttribute_s + | fillText_s + | fillBoldText_s + | drawTextContent_s + | fillRect_s + | strokeRect_s + | drawLine_s + | drawArrow_s + | fillPolygon_s + | strokePolygon_s + | fillCircle_s + | strokeCircle_s + | drawImage_s + | drawImage_1_s + | drawIcon_s + | drawBackground_s + | drawSelector_s + | drawSelector_1_s | unknown_s | function_s | pass_s @@ -352,7 +377,7 @@ text_0_s /* text_0_s tooltip : text:显示一段文字(剧情) -helpUrl : https://h5mota.com/games/template/docs/#/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://h5mota.com/games/template/_docs/#/event?id=text%EF%BC%9A%E6%98%BE%E7%A4%BA%E4%B8%80%E6%AE%B5%E6%96%87%E5%AD%97%EF%BC%88%E5%89%A7%E6%83%85%EF%BC%89 default : ["欢迎使用事件编辑器(双击方块进入多行编辑)"] var code = '"'+EvalString_0+'",\n'; return code; @@ -364,7 +389,7 @@ text_1_s /* text_1_s tooltip : text:显示一段文字(剧情),选项较多请右键点击帮助 -helpUrl : https://h5mota.com/games/template/docs/#/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://h5mota.com/games/template/_docs/#/event?id=text%EF%BC%9A%E6%98%BE%E7%A4%BA%E4%B8%80%E6%AE%B5%E6%96%87%E5%AD%97%EF%BC%88%E5%89%A7%E6%83%85%EF%BC%89 default : ["小妖精","fairy","","欢迎使用事件编辑器(双击方块进入多行编辑)"] var title=''; if (EvalString_0==''){ @@ -374,7 +399,7 @@ if (EvalString_0==''){ if (IdString_0=='')title='\\t['+EvalString_0+']'; else title='\\t['+EvalString_0+','+IdString_0+']'; } -if(EvalString_1 && !(/^(up|down)(,hero)?(,([+-]?\d+),([+-]?\d+))?$/.test(EvalString_1))) { +if(EvalString_1 && !(/^(up|center|down|hero|null)(,(hero|null|\d+,\d+|\d+))?$/.test(EvalString_1))) { throw new Error('对话框效果的用法请右键点击帮助'); } EvalString_1 = EvalString_1 && ('\\b['+EvalString_1+']'); @@ -388,7 +413,7 @@ comment_s /* comment_s tooltip : comment:添加一段会被游戏跳过的注释内容 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=comment%ef%bc%9a%e6%b7%bb%e5%8a%a0%e6%b3%a8%e9%87%8a +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=comment%ef%bc%9a%e6%b7%bb%e5%8a%a0%e6%b3%a8%e9%87%8a default : ["可以在这里写添加任何注释内容"] colour : this.commentColor var code = '{"type": "comment", "text": "'+EvalString_0+'"},\n'; @@ -401,7 +426,7 @@ autoText_s /* autoText_s tooltip : autoText:自动剧情文本,用户无法跳过自动剧情文本,大段剧情文本请添加“是否跳过剧情”的提示 -helpUrl : https://h5mota.com/games/template/docs/#/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://h5mota.com/games/template/_docs/#/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,"用户无法跳过自动剧情文本,大段剧情文本请添加“是否跳过剧情”的提示"] var title=''; if (EvalString_0==''){ @@ -425,7 +450,7 @@ scrollText_s /* scrollText_s tooltip : scrollText:滚动剧情文本,将从下到上进行滚动显示。 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=scrollText%ef%bc%9a%e6%bb%9a%e5%8a%a8%e5%89%a7%e6%83%85%e6%96%87%e6%9c%ac +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=scrollText%ef%bc%9a%e6%bb%9a%e5%8a%a8%e5%89%a7%e6%83%85%e6%96%87%e6%9c%ac default : [5000,1.4,false,"时间是总时间,可以使用setText事件来控制字体、颜色、大小、偏移量等"] Bool_0 = Bool_0?', "async": true':''; var code = '{"type": "scrollText", "text": "'+EvalString_0+'"'+Bool_0+', "time" :'+Int_0+', "lineHeight": '+Number_0+'},\n'; @@ -433,15 +458,15 @@ return code; */; setText_s - : '设置剧情文本的属性' '位置' SetTextPosition_List '偏移像素' EvalString? '对齐' SetTextAlign_List? BGNL? '标题颜色' EvalString? Colour '正文颜色' EvalString? Colour '背景色' EvalString? Colour BGNL? '粗体' B_1_List '标题字体大小' EvalString? '正文字体大小' EvalString? '打字间隔' EvalString? Newline + : '设置剧情文本的属性' '位置' SetTextPosition_List '偏移像素' EvalString? '对齐' TextAlign_List? BGNL? '标题颜色' EvalString? Colour '正文颜色' EvalString? Colour '背景色' EvalString? Colour BGNL? '粗体' B_1_List '标题字体大小' EvalString? '正文字体大小' EvalString? '打字间隔' EvalString? Newline /* setText_s tooltip : setText:设置剧情文本的属性,颜色为RGB三元组或RGBA四元组,打字间隔为剧情文字添加的时间间隔,为整数或不填 -helpUrl : https://h5mota.com/games/template/docs/#/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://h5mota.com/games/template/_docs/#/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,"",'rgba(255,255,255,1)',"",'rgba(255,255,255,1)',"",'rgba(255,255,255,1)',null,"","",""] SetTextPosition_List_0 =SetTextPosition_List_0==='null'?'': ', "position": "'+SetTextPosition_List_0+'"'; -SetTextAlign_List_0 =SetTextAlign_List_0==='null'?'': ', "align": "'+SetTextAlign_List_0+'"'; +TextAlign_List_0 = TextAlign_List_0==='null'?'': ', "align": "'+TextAlign_List_0+'"'; var colorRe = MotaActionFunctions.pattern.colorRe; if (EvalString_0) { if (!/^\d+$/.test(EvalString_0))throw new Error('像素偏移量必须是整数或不填'); @@ -479,7 +504,7 @@ if (EvalString_6) { EvalString_6 = ', "time": '+EvalString_6; } B_1_List_0 = B_1_List_0==='null'?'':', "bold": '+B_1_List_0; -var code = '{"type": "setText"'+SetTextPosition_List_0+EvalString_0+SetTextAlign_List_0+EvalString_1+EvalString_2+B_1_List_0+EvalString_3+EvalString_4+EvalString_5+EvalString_6+'},\n'; +var code = '{"type": "setText"'+SetTextPosition_List_0+EvalString_0+TextAlign_List_0+EvalString_1+EvalString_2+B_1_List_0+EvalString_3+EvalString_4+EvalString_5+EvalString_6+'},\n'; return code; */; @@ -489,7 +514,7 @@ tip_s /* tip_s tooltip : tip:显示一段提示文字 -helpUrl : https://h5mota.com/games/template/docs/#/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://h5mota.com/games/template/_docs/#/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 : ["这段话将在左上角以气泡形式显示",""] IdString_0 = IdString_0 && (', "icon": "' + IdString_0 + '"'); var code = '{"type": "tip", "text": "'+EvalString_0+'"'+IdString_0+'},\n'; @@ -502,7 +527,7 @@ setValue_s /* setValue_s tooltip : setValue:设置勇士的某个属性、道具个数, 或某个变量/Flag的值 -helpUrl : https://h5mota.com/games/template/docs/#/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 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=setvalue%EF%BC%9A%E8%AE%BE%E7%BD%AE%E5%8B%87%E5%A3%AB%E7%9A%84%E6%9F%90%E4%B8%AA%E5%B1%9E%E6%80%A7%E3%80%81%E9%81%93%E5%85%B7%E4%B8%AA%E6%95%B0%EF%BC%8C%E6%88%96%E6%9F%90%E4%B8%AA%E5%8F%98%E9%87%8Fflag%E7%9A%84%E5%80%BC colour : this.dataColor var code = '{"type": "setValue", "name": "'+idString_e_0+'", "value": "'+expression_0+'"},\n'; return code; @@ -514,7 +539,7 @@ addValue_s /* addValue_s tooltip : addValue:增减勇士的某个属性、道具个数, 或某个变量/Flag的值 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=addValue%ef%bc%9a%e5%a2%9e%e5%87%8f%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%8f%2fFlag%e7%9a%84%e5%80%bc +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=addValue%ef%bc%9a%e5%a2%9e%e5%87%8f%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%8f%2fFlag%e7%9a%84%e5%80%bc colour : this.dataColor var code = '{"type": "addValue", "name": "'+idString_e_0+'", "value": "'+expression_0+'"},\n'; return code; @@ -526,7 +551,7 @@ setFloor_s /* setFloor_s tooltip : setFloor:设置楼层属性;该楼层属性和编辑器中的楼层属性一一对应 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=setFloor%ef%bc%9a%e8%ae%be%e7%bd%ae%e6%a5%bc%e5%b1%82%e5%b1%9e%e6%80%a7 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=setFloor%ef%bc%9a%e8%ae%be%e7%bd%ae%e6%a5%bc%e5%b1%82%e5%b1%9e%e6%80%a7 default : ["title","","'字符串类型的值要加引号,其他类型则不用'"] colour : this.dataColor IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"'); @@ -541,7 +566,7 @@ setGlobalAttribute_s /* setGlobalAttribute_s tooltip : setGlobalAttribute:设置全局属性 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=setGlobalAttribute%ef%bc%9a%e8%ae%be%e7%bd%ae%e4%b8%80%e4%b8%aa%e5%85%a8%e5%b1%80%e5%b1%9e%e6%80%a7 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=setGlobalAttribute%ef%bc%9a%e8%ae%be%e7%bd%ae%e4%b8%80%e4%b8%aa%e5%85%a8%e5%b1%80%e5%b1%9e%e6%80%a7 default : ["font","Verdana"] colour : this.dataColor var code = '{"type": "setGlobalAttribute", "name": "'+Global_Attribute_List_0+'", "value": "'+EvalString_0+'"},\n'; @@ -555,7 +580,7 @@ setGlobalValue_s /* setGlobalValue_s tooltip : setGlobalValue:设置全局属性 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=setGlobalValue%ef%bc%9a%e8%ae%be%e7%bd%ae%e4%b8%80%e4%b8%aa%e5%85%a8%e5%b1%80%e6%95%b0%e5%80%bc +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=setGlobalValue%ef%bc%9a%e8%ae%be%e7%bd%ae%e4%b8%80%e4%b8%aa%e5%85%a8%e5%b1%80%e6%95%b0%e5%80%bc default : ["lavaDamage","100"] colour : this.dataColor var code = '{"type": "setGlobalValue", "name": "'+Global_Value_List_0+'", "value": '+EvalString_0+'},\n'; @@ -569,7 +594,7 @@ setGlobalFlag_s /* setGlobalFlag_s tooltip : setGlobalFlag:设置系统开关 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=setGlobalFlag%ef%bc%9a%e8%ae%be%e7%bd%ae%e4%b8%80%e4%b8%aa%e7%b3%bb%e7%bb%9f%e5%bc%80%e5%85%b3 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=setGlobalFlag%ef%bc%9a%e8%ae%be%e7%bd%ae%e4%b8%80%e4%b8%aa%e7%b3%bb%e7%bb%9f%e5%bc%80%e5%85%b3 default : ["enableFloor","true"] colour : this.dataColor var code = '{"type": "setGlobalFlag", "name": "'+Global_Flag_List_0+'", "value": '+Bool_0+'},\n'; @@ -583,7 +608,7 @@ show_s /* show_s tooltip : show: 将禁用事件启用,楼层和动画时间可不填,xy可用逗号分隔表示多个点 -helpUrl : https://h5mota.com/games/template/docs/#/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 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=show%EF%BC%9A%E5%B0%86%E4%B8%80%E4%B8%AA%E7%A6%81%E7%94%A8%E4%BA%8B%E4%BB%B6%E5%90%AF%E7%94%A8 default : ["","","",500,false] colour : this.mapColor var floorstr = ''; @@ -616,7 +641,7 @@ hide_s /* hide_s tooltip : hide: 将一个启用事件禁用,所有参数均可不填,代表禁用事件自身,xy可用逗号分隔表示多个点 -helpUrl : https://h5mota.com/games/template/docs/#/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 +helpUrl : https://h5mota.com/games/template/_docs/#/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,false] colour : this.mapColor var floorstr = ''; @@ -649,7 +674,7 @@ trigger_s /* trigger_s tooltip : trigger: 立即触发另一个地点的事件 -helpUrl : https://h5mota.com/games/template/docs/#/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 +helpUrl : https://h5mota.com/games/template/_docs/#/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",false] colour : this.eventColor Bool_0 = Bool_0 ?', "keep": true':''; @@ -663,7 +688,7 @@ insert_1_s /* insert_1_s tooltip : insert: 插入公共事件并执行 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=insert%ef%bc%9a%e6%8f%92%e5%85%a5%e5%85%ac%e5%85%b1%e4%ba%8b%e4%bb%b6%e6%88%96%e5%8f%a6%e4%b8%80%e4%b8%aa%e5%9c%b0%e7%82%b9%e7%9a%84%e4%ba%8b%e4%bb%b6%e5%b9%b6%e6%89%a7%e8%a1%8c +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=insert%ef%bc%9a%e6%8f%92%e5%85%a5%e5%85%ac%e5%85%b1%e4%ba%8b%e4%bb%b6%e6%88%96%e5%8f%a6%e4%b8%80%e4%b8%aa%e5%9c%b0%e7%82%b9%e7%9a%84%e4%ba%8b%e4%bb%b6%e5%b9%b6%e6%89%a7%e8%a1%8c default : ["加点事件", ""] colour : this.eventColor if (EvalString_1) { @@ -683,12 +708,12 @@ return code; */; insert_2_s - : '插入事件' 'x' PosString ',' 'y' PosString Event_List? '楼层' IdString? '参数列表' EvalString? ENewline + : '插入事件' 'x' PosString ',' 'y' PosString Event_List? '楼层' IdString? '参数列表' EvalString? Newline /* insert_2_s tooltip : insert: 立即插入另一个地点的事件执行,当前事件不会中断,事件坐标不会改变 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=insert%ef%bc%9a%e6%8f%92%e5%85%a5%e5%85%ac%e5%85%b1%e4%ba%8b%e4%bb%b6%e6%88%96%e5%8f%a6%e4%b8%80%e4%b8%aa%e5%9c%b0%e7%82%b9%e7%9a%84%e4%ba%8b%e4%bb%b6%e5%b9%b6%e6%89%a7%e8%a1%8c +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=insert%ef%bc%9a%e6%8f%92%e5%85%a5%e5%85%ac%e5%85%b1%e4%ba%8b%e4%bb%b6%e6%88%96%e5%8f%a6%e4%b8%80%e4%b8%aa%e5%9c%b0%e7%82%b9%e7%9a%84%e4%ba%8b%e4%bb%b6%e5%b9%b6%e6%89%a7%e8%a1%8c default : ["0","0",null,"",""] colour : this.eventColor IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"'); @@ -716,7 +741,7 @@ revisit_s /* revisit_s tooltip : revisit: 立即重启当前事件 -helpUrl : https://h5mota.com/games/template/docs/#/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 +helpUrl : https://h5mota.com/games/template/_docs/#/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 var code = '{"type": "revisit"},\n'; return code; @@ -728,24 +753,37 @@ exit_s /* exit_s tooltip : exit: 立刻结束当前事件 -helpUrl : https://h5mota.com/games/template/docs/#/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 +helpUrl : https://h5mota.com/games/template/_docs/#/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 var code = '{"type": "exit"},\n'; return code; */; setBlock_s - : '转变图块为' EvalString 'x' PosString? ',' 'y' PosString? '楼层' IdString? Newline + : '转变图块为' EvalString 'x' EvalString? ',' 'y' EvalString? '楼层' IdString? Newline /* setBlock_s tooltip : setBlock:设置某个图块,忽略坐标楼层则为当前事件 -helpUrl : https://h5mota.com/games/template/docs/#/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://h5mota.com/games/template/_docs/#/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.mapColor default : ["yellowDoor","","",""] var floorstr = ''; -if (PosString_0 && PosString_1) { - floorstr = ', "loc": ['+PosString_0+','+PosString_1+']'; +if (EvalString_1 && EvalString_2) { + var pattern1 = MotaActionFunctions.pattern.id; + if(pattern1.test(EvalString_1) || pattern1.test(EvalString_2)){ + EvalString_1=MotaActionFunctions.PosString_pre(EvalString_1); + EvalString_2=MotaActionFunctions.PosString_pre(EvalString_2); + EvalString_1=[EvalString_1,EvalString_2] + } else { + var pattern2 = /^([+-]?\d+)(,[+-]?\d+)*$/; + if(!pattern2.test(EvalString_1) || !pattern2.test(EvalString_2))throw new Error('坐标格式错误,请右键点击帮助查看格式'); + EvalString_1=EvalString_1.split(','); + EvalString_2=EvalString_2.split(','); + if(EvalString_1.length!==EvalString_2.length)throw new Error('坐标格式错误,请右键点击帮助查看格式'); + for(var ii=0;ii50) throw new Error('图片编号在1~50之间'); @@ -1218,7 +1325,7 @@ showImage_1_s /* showImage_1_s tooltip : showImage_1:显示图片 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=showImage%ef%bc%9a%e6%98%be%e7%a4%ba%e5%9b%be%e7%89%87 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=showImage%ef%bc%9a%e6%98%be%e7%a4%ba%e5%9b%be%e7%89%87 default : [1,"bg.jpg","0","0","","",1,"0","0","","",0,false] colour : this.printColor if(Int_0<=0 || Int_0>50) throw new Error('图片编号在1~50之间'); @@ -1237,7 +1344,7 @@ showTextImage_s /* showTextImage_s tooltip : showTextImage:显示图片化文本 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=showTextImage%ef%bc%9a%e6%98%be%e7%a4%ba%e6%96%87%e6%9c%ac%e5%8c%96%e5%9b%be%e7%89%87 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=showTextImage%ef%bc%9a%e6%98%be%e7%a4%ba%e6%96%87%e6%9c%ac%e5%8c%96%e5%9b%be%e7%89%87 colour : this.printColor default : ["可以使用setText事件来控制字体、颜色、大小、偏移量等",1,"0","0",1.4,1,0,false] if(Int_0<=0 || Int_0>50) throw new Error('图片编号在1~50之间'); @@ -1252,7 +1359,7 @@ hideImage_s /* hideImage_s tooltip : hideImage:清除图片 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=hideImage%ef%bc%9a%e6%b8%85%e9%99%a4%e5%9b%be%e7%89%87 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=hideImage%ef%bc%9a%e6%b8%85%e9%99%a4%e5%9b%be%e7%89%87 colour : this.printColor default : [1,0,false] if(Int_0<=0 || Int_0>50) throw new Error('图片编号在1~50之间'); @@ -1267,7 +1374,7 @@ showGif_0_s /* showGif_0_s tooltip : showGif:显示动图 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=showgif%EF%BC%9A%E6%98%BE%E7%A4%BA%E5%8A%A8%E5%9B%BE +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=showgif%EF%BC%9A%E6%98%BE%E7%A4%BA%E5%8A%A8%E5%9B%BE default : ["bg.gif","0","0"] colour : this.printColor var code = '{"type": "showGif", "name": "'+EvalString_0+'", "loc": ['+PosString_0+','+PosString_1+']},\n'; @@ -1280,7 +1387,7 @@ showGif_1_s /* showGif_1_s tooltip : showGif:清除所有显示的动图 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=showgif%EF%BC%9A%E6%98%BE%E7%A4%BA%E5%8A%A8%E5%9B%BE +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=showgif%EF%BC%9A%E6%98%BE%E7%A4%BA%E5%8A%A8%E5%9B%BE colour : this.printColor var code = '{"type": "showGif"},\n'; return code; @@ -1293,7 +1400,7 @@ moveImage_s /* moveImage_s tooltip : moveImage:图片移动 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=moveImage%ef%bc%9a%e5%9b%be%e7%89%87%e7%a7%bb%e5%8a%a8 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=moveImage%ef%bc%9a%e5%9b%be%e7%89%87%e7%a7%bb%e5%8a%a8 default : [1,'','','',500,false] colour : this.printColor if(Int_0<=0 || Int_0>50) throw new Error('图片编号在1~50之间'); @@ -1312,7 +1419,7 @@ setCurtain_0_s /* setCurtain_0_s tooltip : setCurtain: 更改画面色调,动画时间可不填 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=setcurtain%EF%BC%9A%E6%9B%B4%E6%94%B9%E7%94%BB%E9%9D%A2%E8%89%B2%E8%B0%83 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=setcurtain%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",'rgba(255,255,255,1)',500,false] colour : this.soundColor var colorRe = MotaActionFunctions.pattern.colorRe; @@ -1329,7 +1436,7 @@ setCurtain_1_s /* setCurtain_1_s tooltip : setCurtain: 恢复画面色调,动画时间可不填 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=setcurtain%EF%BC%9A%E6%9B%B4%E6%94%B9%E7%94%BB%E9%9D%A2%E8%89%B2%E8%B0%83 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=setcurtain%EF%BC%9A%E6%9B%B4%E6%94%B9%E7%94%BB%E9%9D%A2%E8%89%B2%E8%B0%83 default : [500,false] colour : this.soundColor Int_0 = Int_0!=='' ?(', "time": '+Int_0):''; @@ -1343,7 +1450,7 @@ screenFlash_s /* screenFlash_s tooltip : screenFlash: 画面闪烁,动画时间可不填 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=screenFlash%EF%BC%9A%E7%94%BB%E9%9D%A2%E9%97%AA%E7%83%81 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=screenFlash%EF%BC%9A%E7%94%BB%E9%9D%A2%E9%97%AA%E7%83%81 default : ["255,255,255,1",'rgba(255,255,255,1)',500,1,false] colour : this.soundColor var colorRe = MotaActionFunctions.pattern.colorRe; @@ -1360,7 +1467,7 @@ setWeather_s /* setWeather_s tooltip : setWeather:更改天气 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=setweather%EF%BC%9A%E6%9B%B4%E6%94%B9%E5%A4%A9%E6%B0%94 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=setweather%EF%BC%9A%E6%9B%B4%E6%94%B9%E5%A4%A9%E6%B0%94 default : [null,1] colour : this.soundColor if(Int_0<1 || Int_0>10) throw new Error('天气的强度等级, 在1-10之间'); @@ -1375,7 +1482,7 @@ move_s /* move_s tooltip : move: 让某个NPC/怪物移动,位置可不填代表当前事件 -helpUrl : https://h5mota.com/games/template/docs/#/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 +helpUrl : https://h5mota.com/games/template/_docs/#/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,false,false,"上右3下2后4左前2"] colour : this.mapColor var floorstr = ''; @@ -1395,7 +1502,7 @@ moveHero_s /* moveHero_s tooltip : moveHero:移动勇士,用这种方式移动勇士的过程中将无视一切地形, 无视一切事件, 中毒状态也不会扣血 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=movehero%EF%BC%9A%E7%A7%BB%E5%8A%A8%E5%8B%87%E5%A3%AB +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=movehero%EF%BC%9A%E7%A7%BB%E5%8A%A8%E5%8B%87%E5%A3%AB default : [500,false,"上右3下2后4左前2"] colour : this.dataColor Int_0 = Int_0!=='' ?(', "time": '+Int_0):''; @@ -1410,7 +1517,7 @@ jump_s /* jump_s tooltip : jump: 让某个NPC/怪物跳跃 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=jump%EF%BC%9A%E8%AE%A9%E6%9F%90%E4%B8%AANPC%2F%E6%80%AA%E7%89%A9%E8%B7%B3%E8%B7%83 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=jump%EF%BC%9A%E8%AE%A9%E6%9F%90%E4%B8%AANPC%2F%E6%80%AA%E7%89%A9%E8%B7%B3%E8%B7%83 default : ["","","","",500,true,false] colour : this.mapColor var floorstr = ''; @@ -1433,7 +1540,7 @@ jumpHero_s /* jumpHero_s tooltip : jumpHero: 跳跃勇士 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=jumpHero%EF%BC%9A%E8%B7%B3%E8%B7%83%E5%8B%87%E5%A3%AB +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=jumpHero%EF%BC%9A%E8%B7%B3%E8%B7%83%E5%8B%87%E5%A3%AB default : ["","",500,false] colour : this.dataColor var floorstr = ''; @@ -1447,15 +1554,16 @@ return code; */; playBgm_s - : '播放背景音乐' EvalString Newline + : '播放背景音乐' EvalString '持续到下个本事件' Bool Newline /* playBgm_s tooltip : playBgm: 播放背景音乐 -helpUrl : https://h5mota.com/games/template/docs/#/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"] +helpUrl : https://h5mota.com/games/template/_docs/#/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", true] colour : this.soundColor -var code = '{"type": "playBgm", "name": "'+EvalString_0+'"},\n'; +Bool_0 = Bool_0 ? ', "keep": true' : ''; +var code = '{"type": "playBgm", "name": "'+EvalString_0+'"'+Bool_0+'},\n'; return code; */; @@ -1465,7 +1573,7 @@ pauseBgm_s /* pauseBgm_s tooltip : pauseBgm: 暂停背景音乐 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=pausebgm%EF%BC%9A%E6%9A%82%E5%81%9C%E8%83%8C%E6%99%AF%E9%9F%B3%E4%B9%90 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=pausebgm%EF%BC%9A%E6%9A%82%E5%81%9C%E8%83%8C%E6%99%AF%E9%9F%B3%E4%B9%90 colour : this.soundColor var code = '{"type": "pauseBgm"},\n'; return code; @@ -1477,7 +1585,7 @@ resumeBgm_s /* resumeBgm_s tooltip : resumeBgm: 恢复背景音乐 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=resumebgm%EF%BC%9A%E6%81%A2%E5%A4%8D%E8%83%8C%E6%99%AF%E9%9F%B3%E4%B9%90 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=resumebgm%EF%BC%9A%E6%81%A2%E5%A4%8D%E8%83%8C%E6%99%AF%E9%9F%B3%E4%B9%90 colour : this.soundColor var code = '{"type": "resumeBgm"},\n'; return code; @@ -1489,7 +1597,7 @@ loadBgm_s /* loadBgm_s tooltip : loadBgm: 预加载某个背景音乐,之后可以直接播放 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=loadBgm%ef%bc%9a%e9%a2%84%e5%8a%a0%e8%bd%bd%e4%b8%80%e4%b8%aa%e8%83%8c%e6%99%af%e9%9f%b3%e4%b9%90 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=loadBgm%ef%bc%9a%e9%a2%84%e5%8a%a0%e8%bd%bd%e4%b8%80%e4%b8%aa%e8%83%8c%e6%99%af%e9%9f%b3%e4%b9%90 default : ["bgm.mp3"] colour : this.soundColor var code = '{"type": "loadBgm", "name": "'+EvalString_0+'"},\n'; @@ -1502,7 +1610,7 @@ freeBgm_s /* freeBgm_s tooltip : freeBgm: 释放背景音乐的缓存 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=freeBgm%ef%bc%9a%e9%87%8a%e6%94%be%e4%b8%80%e4%b8%aa%e8%83%8c%e6%99%af%e9%9f%b3%e4%b9%90%e7%9a%84%e7%bc%93%e5%ad%98 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=freeBgm%ef%bc%9a%e9%87%8a%e6%94%be%e4%b8%80%e4%b8%aa%e8%83%8c%e6%99%af%e9%9f%b3%e4%b9%90%e7%9a%84%e7%bc%93%e5%ad%98 default : ["bgm.mp3"] colour : this.soundColor var code = '{"type": "freeBgm", "name": "'+EvalString_0+'"},\n'; @@ -1515,7 +1623,7 @@ playSound_s /* playSound_s tooltip : playSound: 播放音效 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=playsound%EF%BC%9A%E6%92%AD%E6%94%BE%E9%9F%B3%E6%95%88 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=playsound%EF%BC%9A%E6%92%AD%E6%94%BE%E9%9F%B3%E6%95%88 default : ["item.mp3",false] colour : this.soundColor Bool_0 = Bool_0 ? ', "stop": true' : ''; @@ -1529,7 +1637,7 @@ stopSound_s /* stopSound_s tooltip : stopSound: 停止所有音效 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=stopSound%ef%bc%9a%e5%81%9c%e6%ad%a2%e6%89%80%e6%9c%89%e9%9f%b3%e6%95%88 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=stopSound%ef%bc%9a%e5%81%9c%e6%ad%a2%e6%89%80%e6%9c%89%e9%9f%b3%e6%95%88 colour : this.soundColor var code = '{"type": "stopSound"},\n'; return code; @@ -1541,7 +1649,7 @@ setVolume_s /* setVolume_s tooltip : setVolume: 设置音量 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=setvolume%EF%BC%9A%E8%AE%BE%E7%BD%AE%E9%9F%B3%E9%87%8F +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=setvolume%EF%BC%9A%E8%AE%BE%E7%BD%AE%E9%9F%B3%E9%87%8F default : [90, 500, false] colour : this.soundColor Int_1 = Int_1!==''?(', "time": '+Int_1):"" @@ -1556,7 +1664,7 @@ win_s /* win_s tooltip : win: 获得胜利, 该事件会显示获胜页面, 并重新游戏 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=win%EF%BC%9A%E8%8E%B7%E5%BE%97%E8%83%9C%E5%88%A9 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=win%EF%BC%9A%E8%8E%B7%E5%BE%97%E8%83%9C%E5%88%A9 default : ["",false] Bool_0 = Bool_0?', "norank": 1':''; var code = '{"type": "win", "reason": "'+EvalString_0+'"'+Bool_0+'},\n'; @@ -1569,7 +1677,7 @@ lose_s /* lose_s tooltip : lose: 游戏失败, 该事件会显示失败页面, 并重新开始游戏 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=lose%EF%BC%9A%E6%B8%B8%E6%88%8F%E5%A4%B1%E8%B4%A5 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=lose%EF%BC%9A%E6%B8%B8%E6%88%8F%E5%A4%B1%E8%B4%A5 default : [""] var code = '{"type": "lose", "reason": "'+EvalString_0+'"},\n'; return code; @@ -1581,7 +1689,7 @@ restart_s /* restart_s tooltip : restart: 直接回到标题界面 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=restart%ef%bc%9a%e7%9b%b4%e6%8e%a5%e5%9b%9e%e5%88%b0%e6%a0%87%e9%a2%98%e7%95%8c%e9%9d%a2 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=restart%ef%bc%9a%e7%9b%b4%e6%8e%a5%e5%9b%9e%e5%88%b0%e6%a0%87%e9%a2%98%e7%95%8c%e9%9d%a2 var code = '{"type": "restart"},\n'; return code; */; @@ -1592,7 +1700,7 @@ input_s /* input_s tooltip : input:接受用户输入数字, 事件只能接受非负整数输入, 所有非法的输入将全部变成0 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=input%ef%bc%9a%e6%8e%a5%e5%8f%97%e7%94%a8%e6%88%b7%e8%be%93%e5%85%a5%e6%95%b0%e5%ad%97 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=input%ef%bc%9a%e6%8e%a5%e5%8f%97%e7%94%a8%e6%88%b7%e8%be%93%e5%85%a5%e6%95%b0%e5%ad%97 default : ["请输入一个数"] colour : this.dataColor var code = '{"type": "input", "text": "'+EvalString_0+'"},\n'; @@ -1605,7 +1713,7 @@ input2_s /* input2_s tooltip : input2:接受用户输入文本, 允许用户输入任何形式的文本 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=input2%ef%bc%9a%e6%8e%a5%e5%8f%97%e7%94%a8%e6%88%b7%e8%be%93%e5%85%a5%e6%96%87%e6%9c%ac +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=input2%ef%bc%9a%e6%8e%a5%e5%8f%97%e7%94%a8%e6%88%b7%e8%be%93%e5%85%a5%e6%96%87%e6%9c%ac default : ["请输入文本"] colour : this.dataColor var code = '{"type": "input2", "text": "'+EvalString_0+'"},\n'; @@ -1618,7 +1726,7 @@ if_s /* if_s tooltip : if: 条件判断 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=if%EF%BC%9A%E6%9D%A1%E4%BB%B6%E5%88%A4%E6%96%AD +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=if%EF%BC%9A%E6%9D%A1%E4%BB%B6%E5%88%A4%E6%96%AD colour : this.eventColor var code = ['{"type": "if", "condition": "',expression_0,'",\n', '"true": [\n',action_0,'],\n', @@ -1633,7 +1741,7 @@ if_1_s /* if_1_s tooltip : if: 条件判断 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=if%EF%BC%9A%E6%9D%A1%E4%BB%B6%E5%88%A4%E6%96%AD +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=if%EF%BC%9A%E6%9D%A1%E4%BB%B6%E5%88%A4%E6%96%AD colour : this.eventColor var code = ['{"type": "if", "condition": "',expression_0,'",\n', '"true": [\n',action_0,'],\n', @@ -1647,7 +1755,7 @@ switch_s /* switch_s tooltip : switch: 多重条件分歧 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=switch%EF%BC%9A%E5%A4%9A%E9%87%8D%E6%9D%A1%E4%BB%B6%E5%88%86%E6%AD%A7 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=switch%EF%BC%9A%E5%A4%9A%E9%87%8D%E6%9D%A1%E4%BB%B6%E5%88%86%E6%AD%A7 default : ["判别值"] colour : this.eventColor var code = ['{"type": "switch", "condition": "',expression_0,'", "caseList": [\n', @@ -1662,7 +1770,7 @@ switchCase /* switchCase tooltip : 选项的选择 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=switch%EF%BC%9A%E5%A4%9A%E9%87%8D%E6%9D%A1%E4%BB%B6%E5%88%86%E6%AD%A7 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=switch%EF%BC%9A%E5%A4%9A%E9%87%8D%E6%9D%A1%E4%BB%B6%E5%88%86%E6%AD%A7 default : ["", false] colour : this.subColor Bool_0 = Bool_0?', "nobreak": true':''; @@ -1676,7 +1784,7 @@ choices_s /* choices_s tooltip : choices: 给用户提供选项 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=choices%EF%BC%9A%E7%BB%99%E7%94%A8%E6%88%B7%E6%8F%90%E4%BE%9B%E9%80%89%E9%A1%B9 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=choices%EF%BC%9A%E7%BB%99%E7%94%A8%E6%88%B7%E6%8F%90%E4%BE%9B%E9%80%89%E9%A1%B9 default : ["","流浪者","woman"] var title=''; if (EvalString_1==''){ @@ -1695,13 +1803,13 @@ return code; */; choicesContext - : '子选项' EvalString '图标' IdString? '颜色' EvalString? Colour BGNL? Newline action+ + : '子选项' EvalString '图标' IdString? '颜色' EvalString? Colour '出现条件' EvalString? BGNL? Newline action+ /* choicesContext tooltip : 选项的选择 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=choices%EF%BC%9A%E7%BB%99%E7%94%A8%E6%88%B7%E6%8F%90%E4%BE%9B%E9%80%89%E9%A1%B9 -default : ["提示文字:红钥匙","",""] +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=choices%EF%BC%9A%E7%BB%99%E7%94%A8%E6%88%B7%E6%8F%90%E4%BE%9B%E9%80%89%E9%A1%B9 +default : ["提示文字:红钥匙","","",""] colour : this.subColor if (EvalString_1) { var colorRe = MotaActionFunctions.pattern.colorRe; @@ -1710,8 +1818,9 @@ if (EvalString_1) { else EvalString_1 = ', "color": "'+EvalString_1+'"'; } +EvalString_2 = EvalString_2 && (', "condition": "'+EvalString_2+'"') IdString_0 = IdString_0?(', "icon": "'+IdString_0+'"'):''; -var code = '{"text": "'+EvalString_0+'"'+IdString_0+EvalString_1+', "action": [\n'+action_0+']},\n'; +var code = '{"text": "'+EvalString_0+'"'+IdString_0+EvalString_1+EvalString_2+', "action": [\n'+action_0+']},\n'; return code; */; @@ -1720,7 +1829,7 @@ confirm_s /* confirm_s tooltip : 弹出确认框 -helpUrl : https://h5mota.com/games/template/docs/#/ +helpUrl : https://h5mota.com/games/template/_docs/#/ default : ["确认要xxx吗?",false] Bool_0 = Bool_0?', "default": true':'' var code = ['{"type": "confirm"'+Bool_0+', "text": "',EvalString_0,'",\n', @@ -1735,7 +1844,7 @@ while_s /* while_s tooltip : while:前置条件循环 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=while%ef%bc%9a%e5%89%8d%e7%bd%ae%e6%9d%a1%e4%bb%b6%e5%be%aa%e7%8e%af +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=while%ef%bc%9a%e5%89%8d%e7%bd%ae%e6%9d%a1%e4%bb%b6%e5%be%aa%e7%8e%af colour : this.eventColor var code = ['{"type": "while", "condition": "',expression_0,'",\n', '"data": [\n',action_0,'],\n', @@ -1748,7 +1857,7 @@ dowhile_s /* dowhile_s tooltip : dowhile:后置条件循环 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=dowhile%ef%bc%9a%e5%90%8e%e7%bd%ae%e6%9d%a1%e4%bb%b6%e5%be%aa%e7%8e%af +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=dowhile%ef%bc%9a%e5%90%8e%e7%bd%ae%e6%9d%a1%e4%bb%b6%e5%be%aa%e7%8e%af colour : this.eventColor var code = ['{"type": "dowhile", "condition": "',expression_0,'",\n', '"data": [\n',action_0,'],\n', @@ -1761,7 +1870,7 @@ break_s /* break_s tooltip : break:跳出循环, 如果break事件不在任何循环中被执行,则和exit等价,即会立刻结束当前事件! -helpUrl : https://h5mota.com/games/template/docs/#/event?id=break%EF%BC%9A%E8%B7%B3%E5%87%BA%E5%BE%AA%E7%8E%AF +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=break%EF%BC%9A%E8%B7%B3%E5%87%BA%E5%BE%AA%E7%8E%AF colour : this.eventColor var code = '{"type": "break"},\n'; return code; @@ -1772,7 +1881,7 @@ continue_s /* continue_s tooltip : continue:继续执行当前循环的下一轮, 如果continue事件不在任何循环中被执行,则和exit等价,即会立刻结束当前事件! -helpUrl : https://h5mota.com/games/template/docs/#/event?id=continue%EF%BC%9A%E7%BB%A7%E7%BB%AD%E6%89%A7%E8%A1%8C%E5%BD%93%E5%89%8D%E5%BE%AA%E7%8E%AF +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=continue%EF%BC%9A%E7%BB%A7%E7%BB%AD%E6%89%A7%E8%A1%8C%E5%BD%93%E5%89%8D%E5%BE%AA%E7%8E%AF colour : this.eventColor var code = '{"type": "continue"},\n'; return code; @@ -1785,7 +1894,7 @@ wait_s /* wait_s tooltip : wait: 等待用户操作并获得按键或点击信息(具体用法看文档) -helpUrl : https://h5mota.com/games/template/docs/#/event?id=wait%EF%BC%9A%E7%AD%89%E5%BE%85%E7%94%A8%E6%88%B7%E6%93%8D%E4%BD%9C +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=wait%EF%BC%9A%E7%AD%89%E5%BE%85%E7%94%A8%E6%88%B7%E6%93%8D%E4%BD%9C colour : this.soundColor var code = '{"type": "wait"},\n'; return code; @@ -1798,7 +1907,7 @@ waitAsync_s /* waitAsync_s tooltip : waitAsync: 等待所有异步事件执行完毕 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=waitAsync%ef%bc%9a%e7%ad%89%e5%be%85%e6%89%80%e6%9c%89%e5%bc%82%e6%ad%a5%e4%ba%8b%e4%bb%b6%e6%89%a7%e8%a1%8c%e5%ae%8c%e6%af%95 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=waitAsync%ef%bc%9a%e7%ad%89%e5%be%85%e6%89%80%e6%9c%89%e5%bc%82%e6%ad%a5%e4%ba%8b%e4%bb%b6%e6%89%a7%e8%a1%8c%e5%ae%8c%e6%af%95 colour : this.soundColor var code = '{"type": "waitAsync"},\n'; return code; @@ -1811,7 +1920,7 @@ callBook_s /* callBook_s tooltip : callBook: 呼出怪物手册;返回游戏后将继续执行后面的事件 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=callBook%ef%bc%9a%e5%91%bc%e5%87%ba%e6%80%aa%e7%89%a9%e6%89%8b%e5%86%8c +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=callBook%ef%bc%9a%e5%91%bc%e5%87%ba%e6%80%aa%e7%89%a9%e6%89%8b%e5%86%8c colour : this.soundColor var code = '{"type": "callBook"},\n'; return code; @@ -1824,7 +1933,7 @@ callSave_s /* callSave_s tooltip : callSave: 呼出存档页面 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=callSave%ef%bc%9a%e5%91%bc%e5%87%ba%e5%ad%98%e6%a1%a3%e7%95%8c%e9%9d%a2 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=callSave%ef%bc%9a%e5%91%bc%e5%87%ba%e5%ad%98%e6%a1%a3%e7%95%8c%e9%9d%a2 colour : this.soundColor var code = '{"type": "callSave"},\n'; return code; @@ -1832,36 +1941,462 @@ return code; autoSave_s - : '自动存档' + : '自动存档' '不提示' Bool Newline /* autoSave_s tooltip : autoSave: 自动存档 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=autoSave%ef%bc%9a%e8%87%aa%e5%8a%a8%e5%ad%98%e6%a1%a3 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=autoSave%ef%bc%9a%e8%87%aa%e5%8a%a8%e5%ad%98%e6%a1%a3 colour : this.soundColor -var code = '{"type": "autoSave"},\n'; +default : [false] +Bool_0 = Bool_0 ? (', "nohint": true') : ''; +var code = '{"type": "autoSave"'+Bool_0+'},\n'; return code; */; callLoad_s - : '呼出读档页面' + : '呼出读档页面' Newline /* callLoad_s tooltip : callLoad: 呼出存档页面;返回游戏后将继续执行后面的事件 -helpUrl : https://h5mota.com/games/template/docs/#/event?id=callLoad%ef%bc%9a%e5%91%bc%e5%87%ba%e8%af%bb%e6%a1%a3%e7%95%8c%e9%9d%a2 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=callLoad%ef%bc%9a%e5%91%bc%e5%87%ba%e8%af%bb%e6%a1%a3%e7%95%8c%e9%9d%a2 colour : this.soundColor var code = '{"type": "callLoad"},\n'; return code; */; + +previewUI_s + : 'ui绘制并预览' '(双击此项可进行预览)' BGNL? Newline action+ BEND Newline + + +/* previewUI_s +tooltip : previewUI: ui绘制并预览 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=previewUI%ef%bc%9aUI%e7%bb%98%e5%88%b6%e5%b9%b6%e9%a2%84%e8%a7%88 +var code = ['{"type": "previewUI", "action": [\n', action_0,']},\n'].join(''); +return code; +*/; + + +clearMap_s + : '清除画布' '起点像素' 'x' PosString 'y' PosString '宽' PosString '高' PosString Newline + +/* clearMap_s +tooltip : clearMap: 清除画布 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=clearMap%ef%bc%9a%e6%b8%85%e9%99%a4%e7%94%bb%e5%b8%83 +colour : this.subColor +default : ["0", "0", "100", "100"] +var code = '{"type": "clearMap", "x": ' + PosString_0 + ', "y": ' + PosString_1 + + ', "width": ' + PosString_2 + ', "height": ' + PosString_3 + '},\n'; +return code; +*/; + + +clearMap_1_s + : '清空画布' Newline + +/* clearMap_1_s +tooltip : clearMap: 清除画布 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=clearMap%ef%bc%9a%e6%b8%85%e9%99%a4%e7%94%bb%e5%b8%83 +colour : this.subColor +var code = '{"type": "clearMap"},\n'; +return code; +*/; + + +setAttribute_s + : '设置画布属性' '字体' EvalString? '填充样式' EvalString? Colour '边框样式' EvalString? Colour BGNL? '线宽度' EvalString? '不透明度' EvalString? '对齐' TextAlign_List '基准线' TextBaseline_List 'z值' EvalString? Newline + +/* setAttribute_s +tooltip : setAttribute:设置画布属性 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=setAttribute%ef%bc%9a%e8%ae%be%e7%bd%ae%e7%94%bb%e5%b8%83%e5%b1%9e%e6%80%a7 +colour : this.subColor +default : ["","",'rgba(255,255,255,1)',"",'rgba(255,255,255,1)',"","",null,null,""] +TextAlign_List_0 = TextAlign_List_0==='null'?'': ', "align": "'+TextAlign_List_0+'"'; +TextBaseline_List_0 = TextBaseline_List_0==='null'?'': ', "baseline": "'+TextBaseline_List_0+'"'; +var colorRe = MotaActionFunctions.pattern.colorRe; +var fontRe = MotaActionFunctions.pattern.fontRe; +if (EvalString_0) { + if (!fontRe.test(EvalString_0)) throw new Error('字体必须是 [italic] [bold] 14px Verdana 这种形式或不填'); + EvalString_0 = ', "font": "' + EvalString_0 + '"'; +} +if (EvalString_1) { + if (!colorRe.test(EvalString_1))throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1'); + EvalString_1 = ', "fillStyle": ['+EvalString_1+']'; +} +if (EvalString_2) { + if (!colorRe.test(EvalString_2))throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1'); + EvalString_2 = ', "strokeStyle": ['+EvalString_2+']'; +} +if (EvalString_3) { + if (!/^\d+$/.test(EvalString_3))throw new Error('线宽必须是整数或不填'); + EvalString_3 = ', "lineWidth": '+EvalString_3; +} +if (EvalString_4) { + var f = parseFloat(EvalString_4); + if (isNaN(f) || f<0 || f>1) throw new Error('不透明度必须是0到1的浮点数或不填'); + EvalString_4 = ', "alpha": '+EvalString_4; +} +if (EvalString_5) { + if (!/^\d+$/.test(EvalString_5))throw new Error('z值必须是整数或不填'); + EvalString_5 = ', "z": '+EvalString_5; +} +var code = '{"type": "setAttribute"'+EvalString_0+EvalString_1+EvalString_2+EvalString_3+EvalString_4+TextAlign_List_0+TextBaseline_List_0+EvalString_5+'},\n'; +return code; +*/; + +fillText_s + : '绘制文本' 'x' PosString 'y' PosString '样式' EvalString? Colour '字体' EvalString? '最大宽度' EvalString? BGNL? EvalString Newline + +/* fillText_s +tooltip : fillText:绘制一行文本;可以设置最大宽度进行放缩 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=fillText%ef%bc%9a%e7%bb%98%e5%88%b6%e6%96%87%e6%9c%ac +colour : this.subColor +default : ["0","0","",'rgba(255,255,255,1)',"","","绘制一行文本"] +var colorRe = MotaActionFunctions.pattern.colorRe; +var fontRe = MotaActionFunctions.pattern.fontRe; +if (EvalString_0) { + if (!colorRe.test(EvalString_0))throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1'); + EvalString_0 = ', "style": ['+EvalString_0+']'; +} +if (EvalString_1) { + if (!fontRe.test(EvalString_1)) throw new Error('字体必须是 [italic] [bold] 14px Verdana 这种形式或不填'); + EvalString_1 = ', "font": "' + EvalString_1 + '"'; +} +if (EvalString_2) { + if (!/^\d+$/.test(EvalString_2)) throw new Error('最大宽度必须是整数或不填'); + EvalString_2 = ', "maxWidth": ' + EvalString_2; +} +var code = '{"type": "fillText", "x": '+PosString_0+', "y": '+PosString_1+EvalString_0+EvalString_1+EvalString_2+', "text": "'+EvalString_3+'"},\n'; +return code; +*/; + +fillBoldText_s + : '绘制描边文本' 'x' PosString 'y' PosString '样式' EvalString? Colour '字体' EvalString? BGNL? EvalString Newline + +/* fillBoldText_s +tooltip : fillBoldText:绘制一行描边文本 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=fillBoldText%ef%bc%9a%e7%bb%98%e5%88%b6%e6%8f%8f%e8%be%b9%e6%96%87%e6%9c%ac +colour : this.subColor +default : ["0","0","",'rgba(255,255,255,1)',"","绘制一行描边文本"] +var colorRe = MotaActionFunctions.pattern.colorRe; +var fontRe = MotaActionFunctions.pattern.fontRe; +if (EvalString_0) { + if (!colorRe.test(EvalString_0))throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1'); + EvalString_0 = ', "style": ['+EvalString_0+']'; +} +if (EvalString_1) { + if (!fontRe.test(EvalString_1)) throw new Error('字体必须是 [italic] [bold] 14px Verdana 这种形式或不填'); + EvalString_1 = ', "font": "' + EvalString_1 + '"'; +} +var code = '{"type": "fillBoldText", "x": '+PosString_0+', "y": '+PosString_1+EvalString_0+EvalString_1+', "text": "'+EvalString_2+'"},\n'; +return code; +*/; + +drawTextContent_s + : '绘制多行文本' EvalString BGNL? '起点像素' 'x' PosString 'y' PosString '最大宽度' EvalString? '颜色' EvalString? Colour BGNL? '对齐' TextAlign_List '字体大小' EvalString? '行距' EvalString? '粗体' Bool Newline + +/* drawTextContent_s +tooltip : drawTextContent:绘制多行文本 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=drawTextContent%ef%bc%9a%e7%bb%98%e5%88%b6%e5%a4%9a%e8%a1%8c%e6%96%87%e6%9c%ac +colour : this.subColor +default : ["绘制多行文本\\n可双击编辑","0","0","","",'rgba(255,255,255,1)',null,"","",false] +var colorRe = MotaActionFunctions.pattern.colorRe; +TextAlign_List_0 = TextAlign_List_0==='null'?'': ', "align": "'+TextAlign_List_0+'"'; +Bool_0 = Bool_0 ? (', "bold": true') : ''; +if (EvalString_1) { + if (!/^\d+$/.test(EvalString_1)) throw new Error('最大宽度必须是整数或不填'); + EvalString_1 = ', "maxWidth": ' + EvalString_1; +} +if (EvalString_2) { + if (!colorRe.test(EvalString_2))throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1'); + EvalString_2 = ', "color": ['+EvalString_2+']'; +} +if (EvalString_3) { + if (!/^\d+$/.test(EvalString_3)) throw new Error('字体大小必须是整数或不填'); + EvalString_3 = ', "fontSize": ' + EvalString_3; +} +if (EvalString_4) { + if (!/^\d+$/.test(EvalString_4)) throw new Error('行距必须是整数或不填'); + EvalString_4 = ', "lineHeight": ' + EvalString_4; +} +var code = '{"type": "drawTextContent", "text": "'+EvalString_0+'", "left": '+PosString_0+', "top": '+PosString_1+TextAlign_List_0+EvalString_1+EvalString_2+EvalString_3+EvalString_4+Bool_0+'},\n'; +return code; +*/; + +fillRect_s + : '绘制矩形' '起点像素' 'x' PosString 'y' PosString '宽' PosString '高' PosString '颜色' EvalString? Colour Newline + +/* fillRect_s +tooltip : fillRect:绘制矩形 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=fillRect%ef%bc%9a%e7%bb%98%e5%88%b6%e7%9f%a9%e5%bd%a2 +colour : this.subColor +default : ["0","0","flag:x","300","",null] +var colorRe = MotaActionFunctions.pattern.colorRe; +if (EvalString_0) { + if (!colorRe.test(EvalString_0))throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1'); + EvalString_0 = ', "style": ['+EvalString_0+']'; +} +var code = '{"type": "fillRect", "x": '+PosString_0+', "y": '+PosString_1+', "width": '+PosString_2+', "height": '+PosString_3+EvalString_0+'},\n'; +return code; +*/; + +strokeRect_s + : '绘制矩形边框' '起点像素' 'x' PosString 'y' PosString '宽' PosString '高' PosString '颜色' EvalString? Colour '线宽' EvalString? Newline + +/* strokeRect_s +tooltip : strokeRect:绘制矩形边框 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=strokeRect%ef%bc%9a%e7%bb%98%e5%88%b6%e7%9f%a9%e5%bd%a2%e8%be%b9%e6%a1%86 +colour : this.subColor +default : ["0","0","flag:x","300","",null,""] +var colorRe = MotaActionFunctions.pattern.colorRe; +if (EvalString_0) { + if (!colorRe.test(EvalString_0))throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1'); + EvalString_0 = ', "style": ['+EvalString_0+']'; +} +if (EvalString_1) { + if (!/^\d+$/.test(EvalString_1))throw new Error('线宽必须是整数或不填'); + EvalString_1 = ', "lineWidth": '+EvalString_1; +} +var code = '{"type": "strokeRect", "x": '+PosString_0+', "y": '+PosString_1+', "width": '+PosString_2+', "height": '+PosString_3+EvalString_0+EvalString_1+'},\n'; +return code; +*/; + +drawLine_s + : '绘制线段' '起点像素' 'x' PosString 'y' PosString '终点像素' 'x' PosString 'y' PosString '颜色' EvalString? Colour '线宽' EvalString? Newline + +/* drawLine_s +tooltip : drawLine:绘制线段 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=drawLine%ef%bc%9a%e7%bb%98%e5%88%b6%e7%ba%bf%e6%ae%b5 +colour : this.subColor +default : ["0","0","flag:x","300","",null,""] +var colorRe = MotaActionFunctions.pattern.colorRe; +if (EvalString_0) { + if (!colorRe.test(EvalString_0))throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1'); + EvalString_0 = ', "style": ['+EvalString_0+']'; +} +if (EvalString_1) { + if (!/^\d+$/.test(EvalString_1))throw new Error('线宽必须是整数或不填'); + EvalString_1 = ', "lineWidth": '+EvalString_1; +} +var code = '{"type": "drawLine", "x1": '+PosString_0+', "y1": '+PosString_1+', "x2": '+PosString_2+', "y2": '+PosString_3+EvalString_0+EvalString_1+'},\n'; +return code; +*/; + +drawArrow_s + : '绘制箭头' '起点像素' 'x' PosString 'y' PosString '终点像素' 'x' PosString 'y' PosString '颜色' EvalString? Colour '线宽' EvalString? Newline + +/* drawArrow_s +tooltip : drawArrow:绘制箭头 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=drawArrow%ef%bc%9a%e7%bb%98%e5%88%b6%e7%ae%ad%e5%a4%b4 +colour : this.subColor +default : ["0","0","flag:x","300","",null,""] +var colorRe = MotaActionFunctions.pattern.colorRe; +if (EvalString_0) { + if (!colorRe.test(EvalString_0))throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1'); + EvalString_0 = ', "style": ['+EvalString_0+']'; +} +if (EvalString_1) { + if (!/^\d+$/.test(EvalString_1))throw new Error('线宽必须是整数或不填'); + EvalString_1 = ', "lineWidth": '+EvalString_1; +} +var code = '{"type": "drawArrow", "x1": '+PosString_0+', "y1": '+PosString_1+', "x2": '+PosString_2+', "y2": '+PosString_3+EvalString_0+EvalString_1+'},\n'; +return code; +*/; + + +fillPolygon_s + : '绘制多边形' '顶点像素列表' 'x' EvalString 'y' EvalString '颜色' EvalString? Colour Newline + +/* fillPolygon_s +tooltip : fillPolygon:绘制多边形 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=fillPolygon%ef%bc%9a%e7%bb%98%e5%88%b6%e5%a4%9a%e8%be%b9%e5%bd%a2 +colour : this.subColor +default : ["0,0,100","0,100,0","",null] +var colorRe = MotaActionFunctions.pattern.colorRe; +var pattern2 = /^([+-]?\d+)(,[+-]?\d+)*$/; +if(!pattern2.test(EvalString_0) || !pattern2.test(EvalString_1))throw new Error('坐标格式错误,请右键点击帮助查看格式'); +EvalString_0=EvalString_0.split(','); +EvalString_1=EvalString_1.split(','); +if(EvalString_0.length!==EvalString_1.length)throw new Error('坐标格式错误,请右键点击帮助查看格式'); +for(var ii=0;ii 32) mh = per_height * editor.foldPerCol; } - editor.widthsX[img] = [img, sumWidth / 32, (sumWidth + images[img].width) / 32, images[img].height]; - sumWidth += images[img].width; - maxHeight = Math.max(maxHeight, images[img].height); + editor.widthsX[img] = [img, sumWidth / 32, (sumWidth + width) / 32, height]; + sumWidth += width; + maxHeight = Math.max(maxHeight, mh + 64); } var tilesets = images.tilesets; for (var ii in core.tilesets) { @@ -312,82 +328,75 @@ editor.prototype.drawInitData = function (icons) { if (fullWidth > edata.width) edata.style.width = (edata.width = fullWidth) / ratio + 'px'; edata.style.height = (edata.height = fullHeight) / ratio + 'px'; */ + var iconImages = document.getElementById('iconImages'); iconImages.style.width = (iconImages.width = fullWidth) / ratio + 'px'; iconImages.style.height = (iconImages.height = fullHeight) / ratio + 'px'; - var dc = {drawImage:function(){ - var image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight; - var a=Array.prototype.slice.call(arguments) - if(arguments.length==3){ - // [image, dx, dy]=arguments - // [sx, sy, sWidth, sHeight, dWidth, dHeight]=[0,0,image.width,image.height,image.width,image.height] - image=a[0] - a=[a[0],0,0,image.width,image.height,a[1],a[2],image.width,image.height] - } - if(arguments.length==5){ - // [image, dx, dy, dWidth, dHeight]=arguments - // [sx, sy, sWidth, sHeight]=[0,0,image.width,image.height] - image=a[0] - a=[a[0],0,0,image.width,image.height,a[1],a[2],a[3],a[4]] - } - if(arguments.length==9){ - // [image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight]=arguments - } - image=a[0]; - sx=a[1]; - sy=a[2]; - sWidth=a[3]; - sHeight=a[4]; - dx=a[5]; - dy=a[6]; - dWidth=a[7]; - dHeight=a[8]; - //放弃对 dWidth, dHeight 的支持, 始终画一样大的 - var dimg=new Image() - dimg.src = image.src; - dimg.style.clip=['rect(',sy,'px,',sx+sWidth,'px,',sy+sHeight,'px,',sx,'px)'].join('') - dimg.style.top=dy-sy+'px' - dimg.style.left=dx-sx+'px' - dimg.width=image.width/ratio - dimg.height=image.height/ratio - iconImages.appendChild(dimg) - }} - // var dc = edata.getContext('2d'); - var nowx = 0; - var nowy = 0; + var drawImage = function (image, x, y) { + image.style.left = x + 'px'; + image.style.top = y + 'px'; + iconImages.appendChild(image); + } + + var nowx = 0, nowy = 0; for (var ii = 0; ii < imgNames.length; ii++) { var img = imgNames[ii]; if (img == 'terrains') { - (function(image,dc,nowx){ + (function(image,nowx){ if (image.complete) { - dc.drawImage(image, nowx, 32); + drawImage(image, nowx, 32); core.material.images.airwall = image; delete(editor.airwallImg); } else image.onload = function () { - dc.drawImage(image, nowx, 32); + drawImage(image, nowx, 32); core.material.images.airwall = image; delete(editor.airwallImg); editor.updateMap(); } - })(editor.airwallImg,dc,nowx); - dc.drawImage(images[img], nowx, 32*2); - nowx += images[img].width; + })(editor.airwallImg,nowx); + if (editor.folded) { + // --- 单列 & 折行 + var subimgs = core.splitImage(images[img], 32, editor.foldPerCol * 32); + var frames = images[img].width / 32; + for (var i = 0; i < subimgs.length; i+=frames) { + drawImage(subimgs[i], nowx, i==0?2*32:0); + nowx += 32; + } + } + else { + drawImage(images[img], nowx, 32*2); + nowx += images[img].width; + } continue; } if (img == 'autotile') { var autotiles = images[img]; + var tempx = editor.folded ? 32 : 96; for (var im in autotiles) { - dc.drawImage(autotiles[im], 0, 0, 96, 128, nowx, nowy, 96, 128); + var subimgs = core.splitImage(autotiles[im], tempx, autotiles[im].height); + drawImage(subimgs[0], nowx, nowy); nowy += autotiles[im].height; } - nowx += 3 * 32; + nowx += tempx; continue; } - dc.drawImage(images[img], nowx, 0) - nowx += images[img].width; + if (editor.folded) { + // --- 单列 & 折行 + var per_height = img.endsWith('48') ? 48 : 32; + var subimgs = core.splitImage(images[img], 32, editor.foldPerCol * per_height); + var frames = images[img].width / 32; + for (var i = 0; i < subimgs.length; i+=frames) { + drawImage(subimgs[i], nowx, 0); + nowx += 32; + } + } + else { + drawImage(images[img], nowx, 0); + nowx += images[img].width; + } } for (var ii in core.tilesets) { var img = core.tilesets[ii]; - dc.drawImage(tilesets[img], nowx, 0) + drawImage(tilesets[img], nowx, 0); nowx += tilesets[img].width; } //editor.mapInit(); @@ -461,8 +470,12 @@ editor.prototype.setSelectBoxFromInfo=function(thisevent){ pos.x=editor.widthsX[thisevent.images][1]; pos.y=thisevent.y; if(thisevent.x)pos.x+=thisevent.x; - if(thisevent.images=='terrains')pos.y+=2; ysize = thisevent.images.endsWith('48') ? 48 : 32; + if (editor.folded && core.tilesets.indexOf(thisevent.images)==-1) { + pos.x += Math.floor(pos.y / editor.foldPerCol); + pos.y %= editor.foldPerCol; + } + if(pos.x == 0) pos.y+=2; } var dataSelection = document.getElementById('dataSelection'); dataSelection.style.left = pos.x * 32 + 'px'; @@ -484,4 +497,129 @@ editor.prototype.mobile_listen=function(){ // 移动至 editor_unsorted_1.js } +editor.prototype.copyFromPos = function (pos) { + var fields = Object.keys(editor.file.comment._data.floors._data.loc._data); + pos = pos || editor.pos; + var map = core.clone(editor.map[pos.y][pos.x]); + var events = {}; + fields.forEach(function(v){ + events[v] = core.clone(editor.currentFloorData[v][pos.x+','+pos.y]); + }) + return {map: map, events: events}; +} + +editor.prototype.pasteToPos = function (info, pos) { + if (info == null) return; + var fields = Object.keys(editor.file.comment._data.floors._data.loc._data); + pos = pos || editor.pos; + editor.map[pos.y][pos.x] = core.clone(info.map); + fields.forEach(function(v){ + if (info.events[v] == null) delete editor.currentFloorData[v][pos.x+","+pos.y]; + else editor.currentFloorData[v][pos.x+","+pos.y] = core.clone(info.events[v]); + }); +} + +editor.prototype.movePos = function (startPos, endPos, callback) { + if (!startPos || !endPos) return; + if (startPos.x == endPos.x && startPos.y == endPos.y) return; + var copyed = editor.copyFromPos(startPos); + editor.pasteToPos({map:0, events: {}}, startPos); + editor.pasteToPos(copyed, endPos); + editor.updateMap(); + editor.file.saveFloorFile(function (err) { + if (err) { + printe(err); + throw(err) + } + ;printf('移动事件成功'); + editor.drawPosSelection(); + if (callback) callback(); + }); +} + +editor.prototype.exchangePos = function (startPos, endPos, callback) { + if (!startPos || !endPos) return; + if (startPos.x == endPos.x && startPos.y == endPos.y) return; + var startInfo = editor.copyFromPos(startPos); + var endInfo = editor.copyFromPos(endPos); + editor.pasteToPos(startInfo, endPos); + editor.pasteToPos(endInfo, startPos); + editor.updateMap(); + editor.file.saveFloorFile(function (err) { + if (err) { + printe(err); + throw(err) + } + ;printf('交换事件成功'); + editor.drawPosSelection(); + if (callback) callback(); + }); +} + +editor.prototype.moveBgFg = function (startPos, endPos, name, callback) { + if (!startPos || !endPos || ["bgmap","fgmap"].indexOf(name)<0) return; + if (startPos.x == endPos.x && startPos.y == endPos.y) return; + editor[name][endPos.y][endPos.x] = editor[name][startPos.y][startPos.x]; + editor[name][startPos.y][startPos.x] = 0; + editor.updateMap(); + editor.file.saveFloorFile(function (err) { + if (err) { + printe(err); + throw(err) + } + ;printf('移动图块成功'); + editor.drawPosSelection(); + if (callback) callback(); + }); +} + +editor.prototype.exchangeBgFg = function (startPos, endPos, name, callback) { + if (!startPos || !endPos || ["bgmap","fgmap"].indexOf(name)<0) return; + if (startPos.x == endPos.x && startPos.y == endPos.y) return; + var value = editor[name][endPos.y][endPos.x]; + editor[name][endPos.y][endPos.x] = editor[name][startPos.y][startPos.x]; + editor[name][startPos.y][startPos.x] = value; + editor.updateMap(); + editor.file.saveFloorFile(function (err) { + if (err) { + printe(err); + throw(err) + } + ;printf('交换图块成功'); + editor.drawPosSelection(); + if (callback) callback(); + }); + +} + +editor.prototype.clearPos = function (clearPos, pos, callback) { + var fields = Object.keys(editor.file.comment._data.floors._data.loc._data); + pos = pos || editor.pos; + editor.hideMidMenu(); + editor.preMapData = null; + editor.info = 0; + editor_mode.onmode(''); + if (clearPos) + editor.map[pos.y][pos.x]=editor.info; + editor.updateMap(); + fields.forEach(function(v){ + delete editor.currentFloorData[v][pos.x+','+pos.y]; + }) + editor.file.saveFloorFile(function (err) { + if (err) { + printe(err); + throw(err) + } + ;printf(clearPos?'清空该点和事件成功':'只清空该点事件成功'); + editor.drawPosSelection(); + if (callback) callback(); + }); +} + +editor.prototype.addUsedFlags = function (s) { + s.replace(/flag:([a-zA-Z0-9_\u4E00-\u9FCC]+)/g, function (s0, s1) { + editor.used_flags[s1] = true; return s0; + }); +} + editor = new editor(); \ No newline at end of file diff --git a/_server/editor_blockly.js b/_server/editor_blockly.js index b81d675a..82d3b9f8 100644 --- a/_server/editor_blockly.js +++ b/_server/editor_blockly.js @@ -76,9 +76,9 @@ editor_blockly = function () { MotaActionBlocks['confirm_s'].xmlText(), MotaActionBlocks['choices_s'].xmlText([ '选择剑或者盾','流浪者','man',MotaActionBlocks['choicesContext'].xmlText([ - '剑','','',null,MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [3,3]}]), + '剑','','',null,'',MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [3,3]}]), MotaActionBlocks['choicesContext'].xmlText([ - '盾','','',null,MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [9,3]}]), + '盾','','',null,'',MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [9,3]}]), ]) ]) ]), @@ -150,8 +150,12 @@ editor_blockly = function () { MotaActionBlocks['waitAsync_s'].xmlText(), MotaActionBlocks['vibrate_s'].xmlText(), MotaActionBlocks['animate_s'].xmlText(), + MotaActionBlocks['setViewport_s'].xmlText(), + MotaActionBlocks['moveViewport_s'].xmlText(), MotaActionBlocks['showStatusBar_s'].xmlText(), MotaActionBlocks['hideStatusBar_s'].xmlText(), + MotaActionBlocks['showHero_s'].xmlText(), + MotaActionBlocks['hideHero_s'].xmlText(), MotaActionBlocks['setCurtain_0_s'].xmlText(), MotaActionBlocks['setCurtain_1_s'].xmlText(), MotaActionBlocks['screenFlash_s'].xmlText(), @@ -169,6 +173,29 @@ editor_blockly = function () { MotaActionBlocks['autoSave_s'].xmlText(), MotaActionBlocks['callLoad_s'].xmlText(), ], + 'UI绘制':[ + MotaActionBlocks['previewUI_s'].xmlText(), + MotaActionBlocks['clearMap_s'].xmlText(), + MotaActionBlocks['clearMap_1_s'].xmlText(), + MotaActionBlocks['setAttribute_s'].xmlText(), + MotaActionBlocks['fillText_s'].xmlText(), + MotaActionBlocks['fillBoldText_s'].xmlText(), + MotaActionBlocks['drawTextContent_s'].xmlText(), + MotaActionBlocks['fillRect_s'].xmlText(), + MotaActionBlocks['strokeRect_s'].xmlText(), + MotaActionBlocks['drawLine_s'].xmlText(), + MotaActionBlocks['drawArrow_s'].xmlText(), + MotaActionBlocks['fillPolygon_s'].xmlText(), + MotaActionBlocks['strokePolygon_s'].xmlText(), + MotaActionBlocks['fillCircle_s'].xmlText(), + MotaActionBlocks['strokeCircle_s'].xmlText(), + MotaActionBlocks['drawImage_s'].xmlText(), + MotaActionBlocks['drawImage_1_s'].xmlText(), + MotaActionBlocks['drawIcon_s'].xmlText(), + MotaActionBlocks['drawBackground_s'].xmlText(), + MotaActionBlocks['drawSelector_s'].xmlText(), + MotaActionBlocks['drawSelector_1_s'].xmlText(), + ], '原生脚本':[ MotaActionBlocks['function_s'].xmlText(), MotaActionBlocks['unknown_s'].xmlText(), @@ -366,7 +393,7 @@ function omitedcheckUpdateFunction(event) { } } try { - var code = Blockly.JavaScript.workspaceToCode(workspace).replace(/\\\\i/g, '\\\\\\\\i'); + var code = Blockly.JavaScript.workspaceToCode(workspace).replace(/\\\\(i|c|d|e)/g, '\\\\\\\\$1'); codeAreaHL.setValue(code); } catch (error) { codeAreaHL.setValue(String(error)); @@ -509,8 +536,7 @@ function omitedcheckUpdateFunction(event) { MotaActionFunctions.parse( eval('obj=' + codeAreaHL.getValue().replace(/[<>&]/g, function (c) { return {'<': '<', '>': '>', '&': '&'}[c]; - }).replace(/\\r/g, '\\\\r').replace(/\\f/g, '\\\\f') - .replace(/\\i/,'\\\\i')), + }).replace(/\\(r|f|i|c|d|e)/g,'\\\\$1')), document.getElementById('entryType').value ); } @@ -584,14 +610,44 @@ function omitedcheckUpdateFunction(event) { return; } var code = Blockly.JavaScript.workspaceToCode(editor_blockly.workspace); - code = code.replace(/\\i/g, '\\\\i'); + code = code.replace(/\\(i|c|d|e)/g, '\\\\$1'); eval('var obj=' + code); setvalue(JSON.stringify(obj)); } + var previewBlock = function (b) { + var types = [ + "previewUI_s", "clearMap_s", "clearMap_1_s", "setAttribute_s", "fillText_s", + "fillBoldText_s", "drawTextContent_s", "fillRect_s", "strokeRect_s", "drawLine_s", + "drawArrow_s", "fillPolygon_s", "strokePolygon_s", "fillCircle_s", "strokeCircle_s", + "drawImage_s", "drawImage_1_s", "drawIcon_s", "drawBackground_s", "drawSelector_s", "drawSelector_1_s" + ]; + if (b && types.indexOf(b.type)>=0) { + try { + var code = "[" + Blockly.JavaScript.blockToCode(b).replace(/\\(i|c|d|e)/g, '\\\\$1') + "]"; + eval("var obj="+code); + // console.log(obj); + if (obj.length > 0 && b.type.startsWith(obj[0].type)) { + if (b.type == 'previewUI_s') + uievent.previewUI(obj[0].action); + else uievent.previewUI([obj[0]]); + } + } catch (e) {main.log(e);} + return true; + } + return false; + } + editor_blockly.doubleClickBlock = function (blockId) { var b = editor_blockly.workspace.getBlockById(blockId); - //console.log(b); + + if (previewBlock(b)) return; + + if (b && b.type in selectPointBlocks) { // selectPoint + this.selectPoint(); + return; + } + var textStringDict = { 'text_0_s': 'EvalString_0', 'text_1_s': 'EvalString_2', @@ -603,6 +659,7 @@ function omitedcheckUpdateFunction(event) { 'function_s': 'RawEvalString_0', 'shopsub': 'EvalString_3', 'confirm_s': 'EvalString_0', + 'drawTextContent_s': 'EvalString_0', } var f = b ? textStringDict[b.type] : null; if (f) { @@ -650,40 +707,26 @@ function omitedcheckUpdateFunction(event) { // Index from 1 - 9 editor_blockly.openToolbox = function(index) { - // var element = document.getElementById(':'+index); - // if (element == null || element.getAttribute("aria-selected")=="true") return; - // element.click(); - editor_blockly.workspace.toolbox_.tree_.setSelectedItem(editor_blockly.workspace.toolbox_.tree_.children_[index-1]); + if (index < 0) index += editor_blockly.workspace.toolbox_.tree_.children_.length; + editor_blockly.workspace.toolbox_.tree_.setSelectedItem(editor_blockly.workspace.toolbox_.tree_.children_[index]); } editor_blockly.reopenToolbox = function(index) { - // var element = document.getElementById(':'+index); - // if (element == null) return; - // if (element.getAttribute("aria-selected")=="true") element.click(); - // element.click(); - editor_blockly.workspace.toolbox_.tree_.setSelectedItem(editor_blockly.workspace.toolbox_.tree_.children_[index-1]); - editor_blockly.workspace.getFlyout_().show(editor_blockly.workspace.toolbox_.tree_.children_[index-1].blocks); + if (index < 0) index += editor_blockly.workspace.toolbox_.tree_.children_.length; + editor_blockly.workspace.toolbox_.tree_.setSelectedItem(editor_blockly.workspace.toolbox_.tree_.children_[index]); + editor_blockly.workspace.getFlyout_().show(editor_blockly.workspace.toolbox_.tree_.children_[index].blocks); } editor_blockly.closeToolbox = function() { - /* - for (var i=1; i<=10; i++) { - var element = document.getElementById(':'+i); - if (element && element.getAttribute("aria-selected")=="true") { - element.click(); - return; - } - } - */ editor_blockly.workspace.toolbox_.clearSelection(); } var searchInput = document.getElementById("searchBlock"); searchInput.onfocus = function () { - editor_blockly.reopenToolbox(10); + editor_blockly.reopenToolbox(-1); } searchInput.oninput = function () { - editor_blockly.reopenToolbox(10); + editor_blockly.reopenToolbox(-1); } editor_blockly.searchBlock = function (value) { @@ -708,6 +751,290 @@ function omitedcheckUpdateFunction(event) { return results.length == 0 ? editor_blockly.lastUsedType : results; } + // ------ select point ------ + + // id: [x, y, floorId, forceFloor] + var selectPointBlocks = { + "changeFloor_m": ["Number_0", "Number_1", "IdString_0", true], + "jumpHero_s": ["PosString_0", "PosString_1"], + "changeFloor_s": ["PosString_0", "PosString_1", "IdString_0", true], + "changePos_0_s": ["PosString_0", "PosString_1"], + "battle_1_s": ["PosString_0", "PosString_1"], + "openDoor_s": ["PosString_0", "PosString_1", "IdString_0"], + "closeDoor_s": ["PosString_0", "PosString_1"], + "show_s": ["EvalString_0", "EvalString_1", "IdString_0"], + "hide_s": ["EvalString_0", "EvalString_1", "IdString_0"], + "setBlock_s": ["EvalString_1", "EvalString_2", "IdString_0"], + "move_s": ["PosString_0", "PosString_1"], + "jump_s": ["PosString_2", "PosString_3"], // 跳跃暂时只考虑终点 + "showBgFgMap_s": ["EvalString_0", "EvalString_1", "IdString_0"], + "hideBgFgMap_s": ["EvalString_0", "EvalString_1", "IdString_0"], + "setBgFgBlock_s": ["PosString_0", "PosString_1", "IdString_0"], + "showFloorImg_s": ["EvalString_0", "EvalString_1", "IdString_0"], + "hideFloorImg_s": ["EvalString_0", "EvalString_1", "IdString_0"], + "trigger_s": ["PosString_0", "PosString_1"], + "insert_2_s": ["PosString_0", "PosString_1", "IdString_0"], + "animate_s": ["EvalString_0", "EvalString_0"], + "setViewport_s": ["PosString_0", "PosString_1"] + } + + editor_blockly.selectPoint = function () { + var block = Blockly.selected, arr = null; + var floorId = editor.currentFloorId, pos = editor.pos, x = pos.x, y = pos.y; + if (block != null && block.type in selectPointBlocks) { + arr = selectPointBlocks[block.type]; + var xv = parseInt(block.getFieldValue(arr[0])), yv = parseInt(block.getFieldValue(arr[1])); + if (block.type == 'animate_s') { + var v = block.getFieldValue(arr[0]).split(","); + xv = parseInt(v[0]); yv = parseInt(v[1]); + } + if (!isNaN(xv)) x = xv; + if (!isNaN(yv)) y = yv; + if (arr[2] != null) floorId = block.getFieldValue(arr[2]) || floorId; + } + uievent.selectPoint(floorId, x, y, arr && arr[2] == null, function (fv, xv, yv) { + if (!arr) return; + if (arr[2] != null) { + if (fv != editor.currentFloorId) block.setFieldValue(fv, arr[2]); + else block.setFieldValue(arr[3] ? fv : "", arr[2]); + } + if (block.type == 'animate_s') { + block.setFieldValue(xv+","+yv, arr[0]); + } + else { + block.setFieldValue(xv+"", arr[0]); + block.setFieldValue(yv+"", arr[1]); + } + if (block.type == 'changeFloor_m') { + block.setFieldValue("floorId", "Floor_List_0"); + block.setFieldValue("loc", "Stair_List_0"); + } + }); + } + + editor_blockly.getAutoCompletions = function (content) { + // --- content为当前框中输入内容;将返回一个列表,为后续所有可补全内容 + + // 检查 flag:xxx,item:xxx和flag:xxx + var index = content.lastIndexOf(":"); + if (index >= 0) { + var before = content.substring(0, index), token = content.substring(index+1); + if (/^[a-zA-Z0-9_\u4E00-\u9FCC]*$/.test(token)) { + if (before.endsWith("status")) { + return Object.keys(core.status.hero).filter(function (one) { + return one != token && one.startsWith(token); + }).sort(); + } + else if (before.endsWith("item")) { + return Object.keys(core.material.items).filter(function (one) { + return one != token && one.startsWith(token); + }).sort(); + } + else if (before.endsWith("flag")) { + return Object.keys(editor.used_flags || {}).filter(function (one) { + return one != token && one.startsWith(token); + }).sort(); + } + } + } + + // 提供 core.xxx 的补全 + index = content.lastIndexOf("core."); + if (index >= 0) { + var s = content.substring(index + 5); + if (/^[\w.]*$/.test(s)) { + var tokens = s.split("."); + var now = core, prefix = tokens[tokens.length - 1]; + for (var i = 0; i < tokens.length - 1; ++i) { + now = now[tokens[i]]; + if (now == null) break; + } + if (now != null) { + var candidates = []; + for (var i in now) { + candidates.push(i); + } + return candidates.filter(function (one) { + return one != prefix && one.startsWith(prefix); + }).sort(); + } + } + } + + return []; + } + + editor_blockly.completeItems = []; return editor_blockly; } -//editor_blockly=editor_blockly(); \ No newline at end of file + +// --- modify Blockly + +Blockly.FieldColour.prototype.createWidget_ = function() { + Blockly.WidgetDiv.hide(); + + // console.log('here') + var self=this; + var pb=self.sourceBlock_ + var args = MotaActionBlocks[pb.type].args + var targetf=args[args.indexOf(self.name)-1] + + var getValue=function(){ + // return self.getValue() // css颜色 + var f = pb.getFieldValue(targetf); + if (/^(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)?$/.test(f)) { + return f; + } + return ""; + // 也可以用 pb.getFieldValue(targetf) 获得颜色块左边的域的内容 + } + + var setValue=function(newValue){ // css颜色 + self.setValue(newValue) + var c=new Colors(); + c.setColor(newValue) + var rgbatext = [c.colors.webSmart.r,c.colors.webSmart.g,c.colors.webSmart.b,c.colors.alpha].join(","); + pb.setFieldValue(rgbatext, targetf) // 放在颜色块左边的域中 + } + + setTimeout(function () { + document.getElementById("colorPicker").value = getValue(); + window.jsColorPicker.confirm = setValue; + // 设置位置 + triggerColorPicker(Blockly.WidgetDiv.DIV.style.left, Blockly.WidgetDiv.DIV.style.top); + }); + + return document.createElement('table'); +}; + +Blockly.FieldTextInput.prototype.showInlineEditor_ = function(quietInput) { + Blockly.WidgetDiv.show(this, this.sourceBlock_.RTL, this.widgetDispose_()); + var div = Blockly.WidgetDiv.DIV; + // Create the input. + var htmlInput = + goog.dom.createDom(goog.dom.TagName.INPUT, 'blocklyHtmlInput'); + htmlInput.setAttribute('spellcheck', this.spellcheck_); + var fontSize = + (Blockly.FieldTextInput.FONTSIZE * this.workspace_.scale) + 'pt'; + div.style.fontSize = fontSize; + htmlInput.style.fontSize = fontSize; + + Blockly.FieldTextInput.htmlInput_ = htmlInput; + div.appendChild(htmlInput); + + htmlInput.value = htmlInput.defaultValue = this.text_; + htmlInput.oldValue_ = null; + + // console.log('here') + var self=this; + var pb=self.sourceBlock_ + var args = MotaActionBlocks[pb.type].args + var targetf=args[args.indexOf(self.name)+1] + + // ------ colour + + if(targetf && targetf.slice(0,7)==='Colour_'){ + var inputDom = htmlInput; + // var getValue=function(){ // 获得自己的字符串 + // return pb.getFieldValue(self.name); + // } + var setValue = function(newValue){ // 设置右边颜色块的css颜色 + pb.setFieldValue(newValue, targetf) + } + // 给inputDom绑事件 + inputDom.oninput=function(){ + var value=inputDom.value + if(/[0-9 ]+,[0-9 ]+,[0-9 ]+(,[0-9. ]+)?/.test(value)){ + setValue('rgba('+value+')') + } + } + } + else { + + htmlInput.onkeydown = function (e) { + if (e.keyCode == 13 && awesomplete.opened && awesomplete.selected) { + e.stopPropagation(); + e.stopImmediatePropagation(); + e.preventDefault(); + awesomplete.select(); + return false; + } + } + + // --- awesomplete + var awesomplete = new Awesomplete(htmlInput, { + minChars: 4, + maxItems: 12, + autoFirst: true, + replace: function (text) { + text = text.toString(); + var value = this.input.value, index = this.input.selectionEnd; + if (index == null) index = value.length; + if (index < awesomplete.prefix.length) index = awesomplete.prefix.length; + var str = value.substring(0, index - awesomplete.prefix.length) + text + value.substring(index); + this.input.value = str; + pb.setFieldValue(str, self.name); + index += text.length - awesomplete.prefix.length; + this.input.setSelectionRange(index, index); + + editor_blockly.completeItems = editor_blockly.completeItems.filter(function (x) { + return x != text; + }); + editor_blockly.completeItems.unshift(text); + }, + filter: function () {return true;}, + item: function (text, input) { + var li = document.createElement("li"); + li.setAttribute("role", "option"); + li.setAttribute("aria-selected", "false"); + input = awesomplete.prefix.trim(); + if (input != "") text = text.replace(new RegExp("^"+input, "i"), "$&"); + li.innerHTML = text; + return li; + }, + sort: function (a, b) { + a = a.toString(); b = b.toString(); + var ia = editor_blockly.completeItems.indexOf(a), ib = editor_blockly.completeItems.indexOf(b); + if (ia < 0) ia = editor_blockly.completeItems.length; + if (ib < 0) ib = editor_blockly.completeItems.length; + if (ia != ib) return ia - ib; + if (a.length != b.length) return a.length - b.length; + return a < b ? -1 : 1; + } + }); + + htmlInput.oninput = function () { + var value = htmlInput.value, index = htmlInput.selectionEnd; + if (index == null) index = value.length; + value = value.substring(0, index); + // cal prefix + awesomplete.prefix = ""; + for (var i = index - 1; i>=0; i--) { + var c = value.charAt(i); + if (!/^[a-zA-Z0-9_\u4E00-\u9FCC]$/.test(c)) { + awesomplete.prefix = value.substring(i+1); + break; + } + } + + var list = editor_blockly.getAutoCompletions(value); + awesomplete.list = list; + awesomplete.ul.style.marginLeft = getCaretCoordinates(htmlInput, htmlInput.selectionStart).left - + htmlInput.scrollLeft - 20 + "px"; + awesomplete.evaluate(); + } + + awesomplete.container.style.width = "100%"; + + window.awesomplete = awesomplete; + } + + if (!quietInput) { + htmlInput.focus(); + htmlInput.select(); + } + this.validate_(); + this.resizeEditor_(); + + this.bindEvents_(htmlInput); +}; \ No newline at end of file diff --git a/_server/editor_file_unsorted.js b/_server/editor_file_unsorted.js index 04c46d99..cbf79655 100644 --- a/_server/editor_file_unsorted.js +++ b/_server/editor_file_unsorted.js @@ -15,13 +15,15 @@ editor_file = function (editor, callback) { var filename = 'project/floors/' + editor.currentFloorId + '.js'; var datastr = ['main.floors.', editor.currentFloorId, '=\n']; - for(var ii=0,name;name=['map','bgmap','fgmap'][ii];ii++){ - var mapArray=editor[name].map(function (v) { - return v.map(function (v) { - return v.idnum || v || 0 - }) - }); - editor.currentFloorData[name]=mapArray; + if (core.floorIds.indexOf(editor.currentFloorId) >= 0) { + for(var ii=0,name;name=['map','bgmap','fgmap'][ii];ii++){ + var mapArray=editor[name].map(function (v) { + return v.map(function (v) { + return v.idnum || v || 0 + }) + }); + editor.currentFloorData[name]=mapArray; + } } // format 更改实现方式以支持undefined删除 @@ -39,6 +41,7 @@ editor_file = function (editor, callback) { datastr = datastr.join(''); alertWhenCompress(); fs.writeFile(filename, encode(datastr), 'base64', function (err, data) { + editor.addUsedFlags(datastr); callback(err); }); } @@ -56,8 +59,8 @@ editor_file = function (editor, callback) { title = "主塔 "+name+" 层"; } - var width = parseInt(document.getElementById('newMapsWidth').value); - var height = parseInt(document.getElementById('newMapsHeight').value); + var width = parseInt(document.getElementById('newMapWidth').value); + var height = parseInt(document.getElementById('newMapHeight').value); var row = [], map = []; for (var i=0;i 0; + } editor_multi.import = function (id_, args) { var thisTr = document.getElementById(id_); @@ -94,6 +100,8 @@ editor_multi = function () { editor_multi.lintAutocomplete = false; if (args.lint === true) editor_multi.lintAutocomplete = true; if (field.indexOf('Effect') !== -1) editor_multi.lintAutocomplete = true; + if ((!input.value || input.value == 'null') && editor_mode.mode == 'plugins') + input.value = '"function () {\\n\\t// 在此增加新插件\\n\\t\\n}"'; if (input.value.slice(0, 1) === '"' || args.string) { editor_multi.isString = true; codeEditor.setValue(JSON.parse(input.value) || ''); @@ -124,6 +132,11 @@ editor_multi = function () { } editor_multi.confirm = function () { + if (editor_multi.hasError()) { + alert("当前好像存在严重的语法错误,请处理后再保存。\n严重的语法错误可能会导致整个编辑器的崩溃。"); + return; + } + if (!editor_multi.id) { editor_multi.id = ''; return; diff --git a/_server/editor_unsorted_1.js b/_server/editor_unsorted_1.js index 0d3861d8..2ff64a08 100644 --- a/_server/editor_unsorted_1.js +++ b/_server/editor_unsorted_1.js @@ -104,6 +104,7 @@ editor.constructor.prototype.listen=function () { holdingPath = 0; stepPostfix = []; uc.clearRect(0, 0, core.__PIXELS__, core.__PIXELS__); + startPos = endPos = null; }//用于鼠标移出canvas时的自动清除状态 eui.oncontextmenu=function(e){e.preventDefault()} @@ -116,12 +117,13 @@ editor.constructor.prototype.listen=function () { return; } + var startPos=null, endPos=null; eui.onmousedown = function (e) { if (e.button==2){ var loc = eToLoc(e); var pos = locToPos(loc,true); editor.showMidMenu(e.clientX,e.clientY); - return; + return false; } if (!selectBox.isSelected()) { var loc = eToLoc(e); @@ -130,34 +132,58 @@ editor.constructor.prototype.listen=function () { editor_mode.onmode('loc'); //editor_mode.loc(); //tip.whichShow(1); + tip.showHelp(6); + startPos = pos; + uc.strokeStyle = '#FF0000'; + uc.lineWidth = 3; if(editor.isMobile)editor.showMidMenu(e.clientX,e.clientY); - return; + return false; } - holdingPath = 1; mouseOutCheck = 2; setTimeout(clear1); - e.stopPropagation(); uc.clearRect(0, 0, core.__PIXELS__, core.__PIXELS__); var loc = eToLoc(e); var pos = locToPos(loc,true); stepPostfix = []; stepPostfix.push(pos); fillPos(pos); + return false; } eui.onmousemove = function (e) { if (!selectBox.isSelected()) { + if (startPos == null) return; //tip.whichShow(1); - return; + var loc = eToLoc(e); + var pos = locToPos(loc,true); + if (endPos != null && endPos.x == pos.x && endPos.y == pos.y) return; + if (endPos != null) { + uc.clearRect(Math.min(32 * startPos.x - core.bigmap.offsetX, 32 * endPos.x - core.bigmap.offsetX), + Math.min(32 * startPos.y - core.bigmap.offsetY, 32 * endPos.y - core.bigmap.offsetY), + (Math.abs(startPos.x - endPos.x) + 1) * 32, (Math.abs(startPos.y - endPos.y) + 1) * 32) + } + endPos = pos; + if (startPos != null) { + if (startPos.x != endPos.x || startPos.y != endPos.y) { + core.drawArrow('eui', + 32 * startPos.x + 16 - core.bigmap.offsetX, 32 * startPos.y + 16 - core.bigmap.offsetY, + 32 * endPos.x + 16 - core.bigmap.offsetX, 32 * endPos.y + 16 - core.bigmap.offsetY); + } + } + // editor_mode.onmode('nextChange'); + // editor_mode.onmode('loc'); + //editor_mode.loc(); + //tip.whichShow(1); + // tip.showHelp(6); + return false; } if (holdingPath == 0) { - return; + return false; } mouseOutCheck = 2; - e.stopPropagation(); var loc = eToLoc(e); var pos = locToPos(loc,true); var pos0 = stepPostfix[stepPostfix.length - 1] @@ -176,15 +202,22 @@ editor.constructor.prototype.listen=function () { stepPostfix.push(pos); fillPos(pos); } + return false; } eui.onmouseup = function (e) { if (!selectBox.isSelected()) { //tip.whichShow(1); - return; + // editor.movePos(startPos, endPos); + if (editor.layerMod == 'map') + editor.exchangePos(startPos, endPos); + else + editor.exchangeBgFg(startPos, endPos, editor.layerMod); + startPos = endPos = null; + uc.clearRect(0, 0, core.__PIXELS__, core.__PIXELS__); + return false; } holdingPath = 0; - e.stopPropagation(); if (stepPostfix && stepPostfix.length) { editor.preMapData = JSON.parse(JSON.stringify({map:editor.map,fgmap:editor.fgmap,bgmap:editor.bgmap})); if(editor.brushMod!=='line'){ @@ -227,6 +260,7 @@ editor.constructor.prototype.listen=function () { stepPostfix = []; uc.clearRect(0, 0, core.__PIXELS__, core.__PIXELS__); } + return false; } /* @@ -248,7 +282,6 @@ editor.constructor.prototype.listen=function () { */ document.getElementById('mid').onmousewheel = function (e) { - e.preventDefault(); var wheel = function (direct) { var index=editor.core.floorIds.indexOf(editor.currentFloorId); var toId = editor.currentFloorId; @@ -274,6 +307,7 @@ editor.constructor.prototype.listen=function () { catch (ee) { console.log(ee); } + return false; } editor.preMapData = null; @@ -283,8 +317,21 @@ editor.constructor.prototype.listen=function () { }; var reDo = null; var shortcut = core.getLocalStorage('shortcut',{48: 0, 49: 0, 50: 0, 51: 0, 52: 0, 53: 0, 54: 0, 55: 0, 56: 0, 57: 0}); + var copyedInfo = null; document.body.onkeydown = function (e) { + // UI预览 & 地图选点 + if (uievent && uievent.isOpen) { + e.preventDefault(); + if (e.keyCode == 27) uievent.close(); + else if (e.keyCode == 13) uievent.confirm(); + else if (e.keyCode==87) uievent.move(0,-1) + else if (e.keyCode==65) uievent.move(-1,0) + else if (e.keyCode==83) uievent.move(0,1); + else if (e.keyCode==68) uievent.move(1,0); + return; + } + // 监听Ctrl+S保存 if (e.ctrlKey && e.keyCode == 83) { e.preventDefault(); @@ -318,6 +365,7 @@ editor.constructor.prototype.listen=function () { reDo = JSON.parse(JSON.stringify(currDrawData)); currDrawData = {pos: [], info: {}}; editor.preMapData = null; + return; } //Ctrl+y 重做一步redo if (e.keyCode == 89 && e.ctrlKey && reDo && reDo.pos.length && selectBox.isSelected()) { @@ -328,34 +376,27 @@ editor.constructor.prototype.listen=function () { editor.updateMap(); currDrawData = JSON.parse(JSON.stringify(reDo)); reDo = null; + return; } // PGUP和PGDOWN切换楼层 - if (e.keyCode==33) { + if (e.keyCode==33 || e.keyCode==34) { e.preventDefault(); var index=editor.core.floorIds.indexOf(editor.currentFloorId); - if (index0) { - var toId = editor.core.floorIds[index-1]; + var nextIndex = index + (e.keyCode==33?1:-1); + if (nextIndex>=0 && nextIndex=((core.__SIZE__==13?630:655) - scrollBarHeight)) return; + if (!editor.isMobile && e.clientY>=iconLib.offsetHeight - scrollBarHeight) return; var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft; var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; var loc = { @@ -421,11 +556,11 @@ editor.constructor.prototype.listen=function () { var pos = locToPos(loc); for (var spriter in editor.widthsX) { if (pos.x >= editor.widthsX[spriter][1] && pos.x < editor.widthsX[spriter][2]) { - var ysize = spriter.indexOf('48') === -1 ? 32 : 48; + var ysize = spriter.endsWith('48') ? 48 : 32; loc.ysize = ysize; pos.images = editor.widthsX[spriter][0]; pos.y = ~~(loc.y / loc.ysize); - if(core.tilesets.indexOf(pos.images)==-1)pos.x = editor.widthsX[spriter][1]; + if(!editor.folded && core.tilesets.indexOf(pos.images)==-1) pos.x = editor.widthsX[spriter][1]; var autotiles = core.material.images['autotile']; if (pos.images == 'autotile') { var imNames = Object.keys(autotiles); @@ -439,8 +574,15 @@ editor.constructor.prototype.listen=function () { } } } - } else if ((pos.y + 1) * ysize > editor.widthsX[spriter][3]) - pos.y = ~~(editor.widthsX[spriter][3] / ysize) - 1; + } + else { + var height = editor.widthsX[spriter][3], col = height / ysize; + if (editor.folded && core.tilesets.indexOf(pos.images)==-1) { + col = (pos.x == editor.widthsX[spriter][2] - 1) ? ((col - 1) % editor.foldPerCol + 1) : editor.foldPerCol; + } + if (spriter == 'terrains' && pos.x == editor.widthsX[spriter][1]) col += 2; + pos.y = Math.min(pos.y, col - 1); + } selectBox.isSelected(true); // console.log(pos,core.material.images[pos.images].height) @@ -454,10 +596,16 @@ editor.constructor.prototype.listen=function () { } else if(pos.x == 0 && pos.y == 1){ editor.info = editor.ids[editor.indexs[17]]; } else { - if (Object.prototype.hasOwnProperty.call(autotiles, pos.images)) editor.info = {'images': pos.images, 'y': 0}; - else if (pos.images == 'terrains') editor.info = {'images': pos.images, 'y': pos.y - 2}; + if (autotiles[pos.images]) editor.info = {'images': pos.images, 'y': 0}; else if (core.tilesets.indexOf(pos.images)!=-1) editor.info = {'images': pos.images, 'y': pos.y, 'x': pos.x-editor.widthsX[spriter][1]}; - else editor.info = {'images': pos.images, 'y': pos.y}; + else { + var y = pos.y; + if (editor.folded) { + y += editor.foldPerCol * (pos.x-editor.widthsX[spriter][1]); + } + if (pos.images == 'terrains' && pos.x == 0) y -= 2; + editor.info = {'images': pos.images, 'y': y} + } for (var ii = 0; ii < editor.ids.length; ii++) { if ((core.tilesets.indexOf(pos.images)!=-1 && editor.info.images == editor.ids[ii].images @@ -484,10 +632,13 @@ editor.constructor.prototype.listen=function () { var midMenu=document.getElementById('midMenu'); midMenu.oncontextmenu=function(e){e.preventDefault()} editor.lastRightButtonPos=[{x:0,y:0},{x:0,y:0}]; + editor.lastCopyedInfo = [null, null]; editor.showMidMenu=function(x,y){ editor.lastRightButtonPos=JSON.parse(JSON.stringify( [editor.pos,editor.lastRightButtonPos[0]] )); + // --- copy + editor.lastCopyedInfo = [editor.copyFromPos(), editor.lastCopyedInfo[0]]; var locStr='('+editor.lastRightButtonPos[1].x+','+editor.lastRightButtonPos[1].y+')'; var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft; var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; @@ -502,6 +653,10 @@ editor.constructor.prototype.listen=function () { addFloorEvent.style.display='block'; addFloorEvent.children[0].innerHTML='绑定下楼事件'; } + else if (['leftPortal','rightPortal','downPortal','upPortal'].indexOf(thisevent.id)>=0) { + addFloorEvent.style.display='block'; + addFloorEvent.children[0].innerHTML='绑定楼传事件'; + } else addFloorEvent.style.display='none'; chooseThis.children[0].innerHTML='选中此点'+'('+editor.pos.x+','+editor.pos.y+')' @@ -524,20 +679,27 @@ editor.constructor.prototype.listen=function () { editor.hideMidMenu(); e.stopPropagation(); var thisevent = editor.map[editor.pos.y][editor.pos.x]; + var loc = editor.pos.x+","+editor.pos.y; if (thisevent.id=='upFloor') { - editor.currentFloorData.changeFloor[editor.pos.x+","+editor.pos.y] = {"floorId": ":next", "stair": "downFloor"}; + editor.currentFloorData.changeFloor[loc] = {"floorId": ":next", "stair": "downFloor"}; } else if (thisevent.id=='downFloor') { - editor.currentFloorData.changeFloor[editor.pos.x+","+editor.pos.y] = {"floorId": ":before", "stair": "upFloor"}; + editor.currentFloorData.changeFloor[loc] = {"floorId": ":before", "stair": "upFloor"}; + } + else if (thisevent.id=='leftPortal' || thisevent.id=='rightPortal') { + editor.currentFloorData.changeFloor[loc] = {"floorId": ":next", "stair": ":symmetry_x"} + } + else if (thisevent.id=='upPortal' || thisevent.id=='downPortal') { + editor.currentFloorData.changeFloor[loc] = {"floorId": ":next", "stair": ":symmetry_y"} } editor.file.saveFloorFile(function (err) { if (err) { printe(err); throw(err) } - ;printf('添加楼梯事件成功'); editor.drawPosSelection(); editor_mode.showMode('loc'); + printf('添加楼梯事件成功'); }); } @@ -562,8 +724,6 @@ editor.constructor.prototype.listen=function () { editor.setSelectBoxFromInfo(thisevent); } - var fields = Object.keys(editor.file.comment._data.floors._data.loc._data); - var copyLoc = document.getElementById('copyLoc'); copyLoc.onmousedown = function(e){ editor.hideMidMenu(); @@ -571,22 +731,10 @@ editor.constructor.prototype.listen=function () { editor.preMapData = null; reDo = null; editor_mode.onmode(''); - var now = editor.pos; - var last = editor.lastRightButtonPos[1]; - var lastevent = editor.map[last.y][last.x]; - var lastinfo = 0; - if(lastevent==0){ - lastinfo = 0; - } else { - var ids=editor.indexs[lastevent.idnum]; - ids=ids[0]?ids[0]:ids; - lastinfo=editor.ids[ids]; - } - editor.map[now.y][now.x]=lastinfo; + var now = editor.pos, last = editor.lastRightButtonPos[1]; + if (now.x == last.x && now.y == last.y) return; + editor.pasteToPos(editor.lastCopyedInfo[1]); editor.updateMap(); - fields.forEach(function(v){ - editor.currentFloorData[v][now.x+','+now.y]=editor.currentFloorData[v][last.x+','+last.y] - }) editor.file.saveFloorFile(function (err) { if (err) { printe(err); @@ -603,79 +751,22 @@ editor.constructor.prototype.listen=function () { e.stopPropagation(); editor.preMapData = null; reDo = null; - var thisevent = editor.map[editor.pos.y][editor.pos.x]; - if(thisevent==0){ - editor.info = 0; - } else { - var ids=editor.indexs[thisevent.idnum]; - ids=ids[0]?ids[0]:ids; - editor.info=editor.ids[ids]; - } editor_mode.onmode(''); - var now = editor.pos; - var last = editor.lastRightButtonPos[1]; - - var lastevent = editor.map[last.y][last.x]; - var lastinfo = 0; - if(lastevent==0){ - lastinfo = 0; - } else { - var ids=editor.indexs[lastevent.idnum]; - ids=ids[0]?ids[0]:ids; - lastinfo=editor.ids[ids]; - } - editor.map[last.y][last.x]=editor.info; - editor.map[now.y][now.x]=lastinfo; - editor.updateMap(); - - fields.forEach(function(v){ - var temp_atsfcytaf=editor.currentFloorData[v][now.x+','+now.y]; - editor.currentFloorData[v][now.x+','+now.y]=editor.currentFloorData[v][last.x+','+last.y]; - editor.currentFloorData[v][last.x+','+last.y]=temp_atsfcytaf; - }) - editor.file.saveFloorFile(function (err) { - if (err) { - printe(err); - throw(err) - } - ;printf('两位置的事件已互换'); - editor.drawPosSelection(); - }); - } - - var _clearPoint = function (clearPoint) { - editor.hideMidMenu(); - editor.preMapData = null; - reDo = null; - editor.info = 0; - editor_mode.onmode(''); - var now = editor.pos; - if (clearPoint) - editor.map[now.y][now.x]=editor.info; - editor.updateMap(); - fields.forEach(function(v){ - delete editor.currentFloorData[v][now.x+','+now.y]; - }) - editor.file.saveFloorFile(function (err) { - if (err) { - printe(err); - throw(err) - } - ;printf(clearPoint?'清空该点和事件成功':'只清空该点事件成功'); - editor.drawPosSelection(); - }); + editor.exchangePos(editor.pos, editor.lastRightButtonPos[1]); } var clearEvent = document.getElementById('clearEvent'); clearEvent.onmousedown = function (e) { e.stopPropagation(); - _clearPoint(false); + reDo = null; + editor.clearPos(false); } var clearLoc = document.getElementById('clearLoc'); clearLoc.onmousedown = function(e){ e.stopPropagation(); - _clearPoint(true); + reDo = null; + editor.clearPos(true); } var brushMod=document.getElementById('brushMod'); @@ -689,8 +780,14 @@ editor.constructor.prototype.listen=function () { } var brushMod3=document.getElementById('brushMod3'); - if(brushMod3)brushMod3.onchange=function(){ - editor.brushMod=brushMod3.value; + if(brushMod3) { + brushMod3.onchange=function(){ + // tip.showHelp(5) + tip.isSelectedBlock(false) + tip.msgs[11] = String('tileset贴图模式下可以按选中tileset素材,并在地图上拖动来一次绘制一个区域'); + tip.whichShow(12); + editor.brushMod=brushMod3.value; + } } var bgc = document.getElementById('bg'), fgc = document.getElementById('fg'), @@ -737,10 +834,31 @@ editor.constructor.prototype.listen=function () { } var viewportButtons=document.getElementById('viewportButtons'); + var pressTimer = null; for(var ii=0,node;node=viewportButtons.children[ii];ii++){ (function(x,y){ - node.onclick=function(){ - editor.moveViewport(x,y); + var move = function () { + editor.moveViewport(x, y); + } + node.onmousedown = function () { + clearTimeout(pressTimer); + pressTimer = setTimeout(function () { + pressTimer = -1; + var f = function () { + if (pressTimer != null) { + move(); + setTimeout(f, 150); + } + } + f(); + }, 500); + }; + node.onmouseup = function () { + if (pressTimer > 0) { + clearTimeout(pressTimer); + move(); + } + pressTimer = null; } })([-1,0,0,1][ii],[0,-1,1,0][ii]); } diff --git a/_server/editor_unsorted_2.js b/_server/editor_unsorted_2.js index 17b8092e..042b617b 100644 --- a/_server/editor_unsorted_2.js +++ b/_server/editor_unsorted_2.js @@ -568,11 +568,14 @@ editor_unsorted_2_wrapper=function(editor_mode){ }); } + editor_mode.change = function (value) { + editor_mode.onmode('nextChange'); + editor_mode.onmode(value); + if(editor.isMobile)editor.showdataarea(false); + } var editModeSelect = document.getElementById('editModeSelect'); editModeSelect.onchange = function () { - editor_mode.onmode('nextChange'); - editor_mode.onmode(editModeSelect.value); - if(editor.isMobile)editor.showdataarea(false); + editor_mode.change(editModeSelect.value); } editor_mode.checkUnique = function (thiseval) { diff --git a/_server/editor_unsorted_3.js b/_server/editor_unsorted_3.js index 170238e9..7f1d0edc 100644 --- a/_server/editor_unsorted_3.js +++ b/_server/editor_unsorted_3.js @@ -206,13 +206,20 @@ printf = function (str_, type) { printe = function (str_) { printf(str_, 'error') } -tip_in_showMode = [ - '涉及图片的更改需要F5刷新浏览器来生效', - '文本域可以通过双击,在文本编辑器或事件编辑器中编辑', - '事件编辑器中的显示文本和自定义脚本的方块也可以双击', - "画出的地图要点击\"保存地图\"才会写入到文件中", -]; tip=document.getElementById('tip') +tip.showHelp = function(value) { + var tips = [ + '表格的文本域可以双击进行编辑', + '双击地图可以选中素材,右键可以弹出菜单', + '双击事件编辑器的图块可以进行长文本编辑/脚本编辑/地图选点/UI绘制预览等操作', + 'ESC或点击空白处可以自动保存当前修改', + 'H键可以打开操作帮助哦', + 'tileset贴图模式下可以按选中tileset素材,并在地图上拖动来一次绘制一个区域', + '可以拖动地图上的图块和事件,或按Ctrl+C, Ctrl+X和Ctrl+V进行复制,剪切和粘贴,Delete删除' + ]; + if (value == null) value = Math.floor(Math.random() * tips.length); + printf('tips: ' + tips[value]) +} tip._infos= {} tip.infos=function(value){ if(value!=null){ @@ -367,3 +374,201 @@ selectBox.isSelected=function(value){ return selectBox._isSelected } +// ------ UI预览 & 地图选点相关 ------ // + +uievent = { + elements: {}, + values: {}, + isOpen: false, + mode: "" +}; + +uievent.elements.div = document.getElementById('uieventDiv'); +uievent.elements.title = document.getElementById('uieventTitle'); +uievent.elements.yes = document.getElementById('uieventYes'); +uievent.elements.no = document.getElementById('uieventNo'); +uievent.elements.selectBackground = document.getElementById('uieventBackground'); +uievent.elements.selectPoint = document.getElementById('selectPoint'); +uievent.elements.selectFloor = document.getElementById('selectPointFloor'); +uievent.elements.selectPointBox = document.getElementById('selectPointBox'); +uievent.elements.body = document.getElementById('uieventBody'); +uievent.elements.selectPointButtons = document.getElementById('selectPointButtons'); + +uievent.confirm = function () { + var callback = uievent.values.callback, floorId = uievent.values.floorId, + x = uievent.values.x, y = uievent.values.y; + uievent.close(); + if (callback) { + callback(floorId, x, y); + } +} +uievent.elements.yes.onclick = uievent.confirm; + +uievent.close = function () { + uievent.isOpen = false; + uievent.elements.div.style.display = 'none'; + uievent.values = {}; +} +uievent.elements.no.onclick = uievent.close; + +uievent.elements.selectBackground.onchange = function () { + uievent.drawPreviewUI(); +} + +uievent.drawPreviewUI = function () { + core.setAlpha('uievent', 1); + core.clearMap('uievent'); + + // 绘制UI + var background = uievent.elements.selectBackground.value; + if (background == 'thumbnail') { + core.drawThumbnail(editor.currentFloorId, null, {}, 'uievent'); + } + else { + core.fillRect('uievent', 0, 0, core.__PIXELS__, core.__PIXELS__, background); + } + + if (uievent.values.list instanceof Array) { + uievent.values.list.forEach(function (data) { + var type = data.type; + if (!type || !core.ui["_uievent_"+type]) return; + core.ui["_uievent_"+type](data); + }) + } +} + +uievent.previewUI = function (list) { + uievent.isOpen = true; + uievent.elements.div.style.display = 'block'; + uievent.mode = 'previewUI'; + uievent.elements.selectPoint.style.display = 'none'; + uievent.elements.yes.style.display = 'none'; + uievent.elements.title.innerText = 'UI绘制预览'; + uievent.elements.selectBackground.style.display = 'inline'; + uievent.elements.selectBackground.value = 'thumbnail'; + uievent.elements.selectPointBox.style.display = 'none'; + + uievent.values.list = list; + uievent.drawPreviewUI(); +} + +uievent.selectPoint = function (floorId, x, y, hideFloor, callback) { + uievent.values.hideFloor = hideFloor; + uievent.values.callback = callback; + uievent.values.size = editor.isMobile ? window.innerWidth / core.__SIZE__ : 32; + uievent.elements.selectPointBox.style.width = (uievent.values.size - 6) + "px"; + uievent.elements.selectPointBox.style.height = (uievent.values.size - 6) + "px"; + + uievent.isOpen = true; + uievent.elements.div.style.display = 'block'; + uievent.mode = 'selectPoint'; + uievent.elements.selectPoint.style.display = 'block'; + uievent.elements.yes.style.display = 'inline'; + uievent.elements.selectBackground.style.display = 'none'; + uievent.elements.selectFloor.style.display = hideFloor ? 'none': 'inline'; + uievent.elements.selectPointBox.style.display = 'block'; + + // Append children + var floors = ""; + core.floorIds.forEach(function (f) { + floors += ""; + }) + uievent.elements.selectFloor.innerHTML = floors; + + this.setPoint(floorId || editor.currentFloorId, core.calValue(x) || 0, core.calValue(y) || 0); +} + +uievent.updateSelectPoint = function (redraw) { + uievent.elements.title.innerText = '地图选点 ('+uievent.values.x+","+uievent.values.y+')'; + if (redraw) { + core.setAlpha('uievent', 1); + core.clearMap('uievent'); + core.drawThumbnail(uievent.values.floorId, null, null, + {ctx: 'uievent', centerX: uievent.values.left + core.__HALF_SIZE__, + centerY: uievent.values.top + core.__HALF_SIZE__}); + } + uievent.elements.selectPointBox.style.left = uievent.values.size * (uievent.values.x - uievent.values.left) + "px"; + uievent.elements.selectPointBox.style.top = uievent.values.size * (uievent.values.y - uievent.values.top) + "px"; +} + +uievent.setPoint = function (floorId, x, y) { + if (core.floorIds.indexOf(floorId) == -1) floorId = editor.currentFloorId; + uievent.values.floorId = floorId; + uievent.elements.selectFloor.value = floorId; + uievent.values.x = x != null ? x : ( uievent.values.x || 0); + uievent.values.y = y != null ? y : ( uievent.values.y || 0); + uievent.values.width = core.floors[uievent.values.floorId].width || core.__SIZE__; + uievent.values.height = core.floors[uievent.values.floorId].height || core.__SIZE__; + uievent.values.left = core.clamp(uievent.values.x - core.__HALF_SIZE__, 0, uievent.values.width - core.__SIZE__); + uievent.values.top = core.clamp(uievent.values.y - core.__HALF_SIZE__, 0, uievent.values.height - core.__SIZE__); + uievent.updateSelectPoint(true); +} + +uievent.elements.selectFloor.onchange = function () { + uievent.setPoint(uievent.elements.selectFloor.value); +} + +uievent.elements.selectPointBox.onclick = function (e) { + e.stopPropagation(); +} + +uievent.elements.body.onclick = function (e) { + if (uievent.mode != 'selectPoint') return; + uievent.values.x = uievent.values.left + Math.floor(e.offsetX / uievent.values.size); + uievent.values.y = uievent.values.top + Math.floor(e.offsetY / uievent.values.size); + uievent.updateSelectPoint(false); +} + +uievent.move = function (dx, dy) { + if (uievent.mode != 'selectPoint') return; + uievent.values.left = core.clamp(uievent.values.left + dx, 0, uievent.values.width - core.__SIZE__); + uievent.values.top = core.clamp(uievent.values.top + dy, 0, uievent.values.height - core.__SIZE__); + this.updateSelectPoint(true); +}; + +(function() { + + var viewportButtons = uievent.elements.selectPointButtons; + var pressTimer = null; + for(var ii=0,node;node=viewportButtons.children[ii];ii++){ + (function(x,y){ + var move = function () { + uievent.move(x, y); + } + node.onmousedown = function () { + clearTimeout(pressTimer); + pressTimer = setTimeout(function () { + pressTimer = -1; + var f = function () { + if (pressTimer != null) { + move(); + setTimeout(f, 150); + } + } + f(); + }, 500); + }; + node.onmouseup = function () { + if (pressTimer > 0) { + clearTimeout(pressTimer); + move(); + } + pressTimer = null; + } + })([-1,0,0,1][ii],[0,-1,1,0][ii]); + } +})(); + +uievent.elements.div.onmousewheel = function (e) { + if (uievent.mode != 'selectPoint' || uievent.values.hideFloor) return; + var index = core.floorIds.indexOf(uievent.values.floorId); + try { + if (e.wheelDelta) + index+=Math.sign(e.wheelDelta); + else if (e.detail) + index+=Math.sign(e.detail); + } catch (ee) { main.log(ee); } + index = core.clamp(index, 0, core.floorIds.length - 1); + uievent.setPoint(core.floorIds[index]); +} + diff --git a/_server/table/comment.js b/_server/table/comment.js index ef03953d..abbf3b7d 100644 --- a/_server/table/comment.js +++ b/_server/table/comment.js @@ -225,6 +225,12 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_range": "false", "_data": "图块类别" }, + "name": { + "_leaf": true, + "_type": "textarea", + "_string": true, + "_data": "图块名称" + }, "trigger": { "_leaf": true, "_type": "select", diff --git a/_server/table/data.comment.js b/_server/table/data.comment.js index 2a2addfd..74237a8f 100644 --- a/_server/table/data.comment.js +++ b/_server/table/data.comment.js @@ -63,6 +63,12 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_string": true, "_data": "标题样式:可以改变颜色,也可以写\"display: none\"来隐藏标题" }, + "startButtonsStyle": { + "_leaf": true, + "_type": "textarea", + "_string": true, + "_data": "标题界面按钮的样式;caret-color指的是当前选中项的边框颜色" + }, "levelChoose": { "_leaf": true, "_type": "textarea", @@ -515,7 +521,13 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_leaf": true, "_type": "checkbox", "_bool": "bool", - "_data": "是否需要在楼梯边使用传送器" + "_data": "传送器是否需要在楼梯边使用;如果flyRecordPosition开启,则此项对箭头也有效。" + }, + "flyRecordPosition": { + "_leaf": true, + "_type": "checkbox", + "_bool": "bool", + "_data": "传送器平面塔模式;此模式下楼层传送器将飞到上次离开该楼层的位置。" }, "pickaxeFourDirections": { "_leaf": true, @@ -542,11 +554,17 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_data": "如果此项为true,则视为钥匙盒,红黄蓝钥匙+1;若为false,则视为大黄门钥匙" }, "steelDoorWithoutKey": { - "_left": true, + "_leaf": true, "_type": "checkbox", "_bool": "bool", "_data": "铁门是否不需要钥匙开启。如果此项为true,则无需钥匙也可以开铁门。" }, + "itemFirstText": { + "_leaf": true, + "_type": "checkbox", + "_bool": "bool", + "_data": "首次获得道具是否提示" + }, "equipment": { "_leaf": true, "_type": "checkbox", @@ -685,6 +703,12 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_bool": "bool", "_data": "是否在经过领域/夹击/路障等伤害后禁用快捷商店。" }, + "blurFg": { + "_leaf": true, + "_type": "checkbox", + "_bool": "bool", + "_data": "是否虚化前景层;如果此项开启,则在游戏中事件层有东西(如宝石等)时虚化前景层。" + }, "checkConsole": { "_leaf": true, "_type": "checkbox", diff --git a/_server/thirdparty/LICENSE.md b/_server/thirdparty/LICENSE.md new file mode 100644 index 00000000..8867f3df --- /dev/null +++ b/_server/thirdparty/LICENSE.md @@ -0,0 +1,60 @@ +/* jsColor */ + +The MIT License (MIT) + +Copyright (c) 2014 Peter Dematté + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +/* awesomplete */ + +The MIT License (MIT) + +Copyright (c) 2015 Lea Verou + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +/* caret-position */ + +The MIT License (MIT) + +Copyright (c) 2015 Jonathan Ong me@jongleberry.com + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/_server/thirdparty/awesomplete.css b/_server/thirdparty/awesomplete.css new file mode 100644 index 00000000..b36a7035 --- /dev/null +++ b/_server/thirdparty/awesomplete.css @@ -0,0 +1,104 @@ +.awesomplete [hidden] { + display: none; +} + +.awesomplete .visually-hidden { + position: absolute; + clip: rect(0, 0, 0, 0); +} + +.awesomplete { + display: inline-block; + position: relative; +} + +.awesomplete > input { + display: block; +} + +.awesomplete > ul { + position: absolute; + left: 0; + z-index: 1; + box-sizing: border-box; + list-style: none; + padding: 0; + margin: 0; + background: #fff; +} + +.awesomplete > ul:empty { + display: none; +} + +.awesomplete > ul { + border-radius: .3em; + margin: .8em 0 0; + background: hsla(0,0%,100%,.9); + background: linear-gradient(to bottom right, white, hsla(0,0%,100%,.8)); + border: 1px solid rgba(0,0,0,.3); + box-shadow: .05em .2em .6em rgba(0,0,0,.2); + text-shadow: none; +} + +@supports (transform: scale(0)) { + .awesomplete > ul { + transition: .3s cubic-bezier(.4,.2,.5,1.4); + transform-origin: 1.43em -.43em; + } + + .awesomplete > ul[hidden], + .awesomplete > ul:empty { + opacity: 0; + transform: scale(0); + display: block; + transition-timing-function: ease; + } +} + +/* Pointer */ +.awesomplete > ul:before { + content: ""; + position: absolute; + top: -.43em; + left: 1em; + width: 0; height: 0; + padding: .4em; + background: white; + border: inherit; + border-right: 0; + border-bottom: 0; + -webkit-transform: rotate(45deg); + transform: rotate(45deg); +} + +.awesomplete > ul > li { + position: relative; + padding: .2em .5em; + cursor: pointer; + word-break: keep-all; +} + +.awesomplete > ul > li:hover { + background: hsl(200, 40%, 80%); + color: black; +} + +.awesomplete > ul > li[aria-selected="true"] { + background: hsl(205, 40%, 40%); + color: white; +} + +.awesomplete mark { + background: hsl(65, 100%, 50%); +} + +.awesomplete li:hover mark { + background: hsl(68, 100%, 41%); +} + +.awesomplete li[aria-selected="true"] mark { + background: hsl(86, 100%, 21%); + color: inherit; +} +/*# sourceMappingURL=awesomplete.css.map */ \ No newline at end of file diff --git a/_server/thirdparty/awesomplete.min.js b/_server/thirdparty/awesomplete.min.js new file mode 100644 index 00000000..5328bd9b --- /dev/null +++ b/_server/thirdparty/awesomplete.min.js @@ -0,0 +1,3 @@ +// Awesomplete - Lea Verou - MIT license +!function(){function t(t){var e=Array.isArray(t)?{label:t[0],value:t[1]}:"object"==typeof t&&"label"in t&&"value"in t?t:{label:t,value:t};this.label=e.label||e.value,this.value=e.value}function e(t,e,i){for(var n in e){var s=e[n],r=t.input.getAttribute("data-"+n.toLowerCase());"number"==typeof s?t[n]=parseInt(r):!1===s?t[n]=null!==r:s instanceof Function?t[n]=null:t[n]=r,t[n]||0===t[n]||(t[n]=n in i?i[n]:s)}}function i(t,e){return"string"==typeof t?(e||document).querySelector(t):t||null}function n(t,e){return o.call((e||document).querySelectorAll(t))}function s(){n("input.awesomplete").forEach(function(t){new r(t)})}var r=function(t,n){var s=this;r.count=(r.count||0)+1,this.count=r.count,this.isOpened=!1,this.input=i(t),this.input.setAttribute("autocomplete","off"),this.input.setAttribute("aria-expanded","false"),this.input.setAttribute("aria-owns","awesomplete_list_"+this.count),this.input.setAttribute("role","combobox"),this.options=n=n||{},e(this,{minChars:2,maxItems:10,autoFirst:!1,data:r.DATA,filter:r.FILTER_CONTAINS,sort:!1!==n.sort&&r.SORT_BYLENGTH,container:r.CONTAINER,item:r.ITEM,replace:r.REPLACE,tabSelect:!1},n),this.index=-1,this.container=this.container(t),this.ul=i.create("ul",{hidden:"hidden",role:"listbox",id:"awesomplete_list_"+this.count,inside:this.container}),this.status=i.create("span",{className:"visually-hidden",role:"status","aria-live":"assertive","aria-atomic":!0,inside:this.container,textContent:0!=this.minChars?"Type "+this.minChars+" or more characters for results.":"Begin typing for results."}),this._events={input:{input:this.evaluate.bind(this),blur:this.close.bind(this,{reason:"blur"}),keydown:function(t){var e=t.keyCode;s.opened&&(13===e&&s.selected?(t.preventDefault(),s.select()):9===e&&s.selected&&s.tabSelect?s.select():27===e?s.close({reason:"esc"}):38!==e&&40!==e||(t.preventDefault(),s[38===e?"previous":"next"]()))}},form:{submit:this.close.bind(this,{reason:"submit"})},ul:{mousedown:function(t){t.preventDefault()},click:function(t){var e=t.target;if(e!==this){for(;e&&!/li/i.test(e.nodeName);)e=e.parentNode;e&&0===t.button&&(t.preventDefault(),s.select(e,t.target))}}}},i.bind(this.input,this._events.input),i.bind(this.input.form,this._events.form),i.bind(this.ul,this._events.ul),this.input.hasAttribute("list")?(this.list="#"+this.input.getAttribute("list"),this.input.removeAttribute("list")):this.list=this.input.getAttribute("data-list")||n.list||[],r.all.push(this)};r.prototype={set list(t){if(Array.isArray(t))this._list=t;else if("string"==typeof t&&t.indexOf(",")>-1)this._list=t.split(/\s*,\s*/);else if((t=i(t))&&t.children){var e=[];o.apply(t.children).forEach(function(t){if(!t.disabled){var i=t.textContent.trim(),n=t.value||i,s=t.label||i;""!==n&&e.push({label:s,value:n})}}),this._list=e}document.activeElement===this.input&&this.evaluate()},get selected(){return this.index>-1},get opened(){return this.isOpened},close:function(t){this.opened&&(this.input.setAttribute("aria-expanded","false"),this.ul.setAttribute("hidden",""),this.isOpened=!1,this.index=-1,this.status.setAttribute("hidden",""),i.fire(this.input,"awesomplete-close",t||{}))},open:function(){this.input.setAttribute("aria-expanded","true"),this.ul.removeAttribute("hidden"),this.isOpened=!0,this.status.removeAttribute("hidden"),this.autoFirst&&-1===this.index&&this.goto(0),i.fire(this.input,"awesomplete-open")},destroy:function(){if(i.unbind(this.input,this._events.input),i.unbind(this.input.form,this._events.form),!this.options.container){var t=this.container.parentNode;t.insertBefore(this.input,this.container),t.removeChild(this.container)}this.input.removeAttribute("autocomplete"),this.input.removeAttribute("aria-autocomplete");var e=r.all.indexOf(this);-1!==e&&r.all.splice(e,1)},next:function(){var t=this.ul.children.length;this.goto(this.index-1&&e.length>0&&(e[t].setAttribute("aria-selected","true"),this.status.textContent=e[t].textContent+", list item "+(t+1)+" of "+e.length,this.input.setAttribute("aria-activedescendant",this.ul.id+"_item_"+this.index),this.ul.scrollTop=e[t].offsetTop-this.ul.clientHeight+e[t].clientHeight,i.fire(this.input,"awesomplete-highlight",{text:this.suggestions[this.index]}))},select:function(t,e){if(t?this.index=i.siblingIndex(t):t=this.ul.children[this.index],t){var n=this.suggestions[this.index];i.fire(this.input,"awesomplete-select",{text:n,origin:e||t})&&(this.replace(n),this.close({reason:"select"}),i.fire(this.input,"awesomplete-selectcomplete",{text:n}))}},evaluate:function(){var e=this,i=this.input.value;i.length>=this.minChars&&this._list&&this._list.length>0?(this.index=-1,this.ul.innerHTML="",this.suggestions=this._list.map(function(n){return new t(e.data(n,i))}).filter(function(t){return e.filter(t,i)}),!1!==this.sort&&(this.suggestions=this.suggestions.sort(this.sort)),this.suggestions=this.suggestions.slice(0,this.maxItems),this.suggestions.forEach(function(t,n){e.ul.appendChild(e.item(t,i,n))}),0===this.ul.children.length?(this.status.textContent="No results found",this.close({reason:"nomatches"})):(this.open(),this.status.textContent=this.ul.children.length+" results found")):(this.close({reason:"nomatches"}),this.status.textContent="No results found")}},r.all=[],r.FILTER_CONTAINS=function(t,e){return RegExp(i.regExpEscape(e.trim()),"i").test(t)},r.FILTER_STARTSWITH=function(t,e){return RegExp("^"+i.regExpEscape(e.trim()),"i").test(t)},r.SORT_BYLENGTH=function(t,e){return t.length!==e.length?t.length-e.length:t$&"),role:"option","aria-selected":"false",id:"awesomplete_list_"+this.count+"_item_"+n})},r.REPLACE=function(t){this.input.value=t.value},r.DATA=function(t){return t},Object.defineProperty(t.prototype=Object.create(String.prototype),"length",{get:function(){return this.label.length}}),t.prototype.toString=t.prototype.valueOf=function(){return""+this.label};var o=Array.prototype.slice;i.create=function(t,e){var n=document.createElement(t);for(var s in e){var r=e[s];if("inside"===s)i(r).appendChild(n);else if("around"===s){var o=i(r);o.parentNode.insertBefore(n,o),n.appendChild(o),null!=o.getAttribute("autofocus")&&o.focus()}else s in n?n[s]=r:n.setAttribute(s,r)}return n},i.bind=function(t,e){if(t)for(var i in e){var n=e[i];i.split(/\s+/).forEach(function(e){t.addEventListener(e,n)})}},i.unbind=function(t,e){if(t)for(var i in e){var n=e[i];i.split(/\s+/).forEach(function(e){t.removeEventListener(e,n)})}},i.fire=function(t,e,i){var n=document.createEvent("HTMLEvents");n.initEvent(e,!0,!0);for(var s in i)n[s]=i[s];return t.dispatchEvent(n)},i.regExpEscape=function(t){return t.replace(/[-\\^$*+?.()|[\]{}]/g,"\\$&")},i.siblingIndex=function(t){for(var e=0;t=t.previousElementSibling;e++);return e},"undefined"!=typeof self&&(self.Awesomplete=r),"undefined"!=typeof Document&&("loading"!==document.readyState?s():document.addEventListener("DOMContentLoaded",s)),r.$=i,r.$$=n,"object"==typeof module&&module.exports&&(module.exports=r)}(); +//# sourceMappingURL=awesomplete.min.js.map \ No newline at end of file diff --git a/_server/thirdparty/caret-position.js b/_server/thirdparty/caret-position.js new file mode 100644 index 00000000..a46ddb78 --- /dev/null +++ b/_server/thirdparty/caret-position.js @@ -0,0 +1,155 @@ +/* jshint browser: true */ + +(function () { + +// We'll copy the properties below into the mirror div. +// Note that some browsers, such as Firefox, do not concatenate properties +// into their shorthand (e.g. padding-top, padding-bottom etc. -> padding), +// so we have to list every single property explicitly. + var properties = [ + 'direction', // RTL support + 'boxSizing', + 'width', // on Chrome and IE, exclude the scrollbar, so the mirror div wraps exactly as the textarea does + 'height', + 'overflowX', + 'overflowY', // copy the scrollbar for IE + + 'borderTopWidth', + 'borderRightWidth', + 'borderBottomWidth', + 'borderLeftWidth', + 'borderStyle', + + 'paddingTop', + 'paddingRight', + 'paddingBottom', + 'paddingLeft', + + // https://developer.mozilla.org/en-US/docs/Web/CSS/font + 'fontStyle', + 'fontVariant', + 'fontWeight', + 'fontStretch', + 'fontSize', + 'fontSizeAdjust', + 'lineHeight', + 'fontFamily', + + 'textAlign', + 'textTransform', + 'textIndent', + 'textDecoration', // might not make a difference, but better be safe + + 'letterSpacing', + 'wordSpacing', + + 'tabSize', + 'MozTabSize' + + ]; + + var isBrowser = (typeof window !== 'undefined'); + var isFirefox = (isBrowser && window.mozInnerScreenX != null); + + function getCaretCoordinates(element, position, options) { + if (!isBrowser) { + throw new Error('textarea-caret-position#getCaretCoordinates should only be called in a browser'); + } + + var debug = options && options.debug || false; + if (debug) { + var el = document.querySelector('#input-textarea-caret-position-mirror-div'); + if (el) el.parentNode.removeChild(el); + } + + // The mirror div will replicate the textarea's style + var div = document.createElement('div'); + div.id = 'input-textarea-caret-position-mirror-div'; + document.body.appendChild(div); + + var style = div.style; + var computed = window.getComputedStyle ? window.getComputedStyle(element) : element.currentStyle; // currentStyle for IE < 9 + var isInput = element.nodeName === 'INPUT'; + + // Default textarea styles + style.whiteSpace = 'nowrap'; + if (!isInput) + style.wordWrap = 'break-word'; // only for textarea-s + + // Position off-screen + style.position = 'absolute'; // required to return coordinates properly + if (!debug) + style.visibility = 'hidden'; // not 'display: none' because we want rendering + + // Transfer the element's properties to the div + properties.forEach(function (prop) { + if (isInput && prop === 'lineHeight') { + // Special case for s because text is rendered centered and line height may be != height + if (computed.boxSizing === "border-box") { + var height = parseInt(computed.height); + var outerHeight = + parseInt(computed.paddingTop) + + parseInt(computed.paddingBottom) + + parseInt(computed.borderTopWidth) + + parseInt(computed.borderBottomWidth); + var targetHeight = outerHeight + parseInt(computed.lineHeight); + if (height > targetHeight) { + style.lineHeight = height - outerHeight + "px"; + } else if (height === targetHeight) { + style.lineHeight = computed.lineHeight; + } else { + style.lineHeight = 0; + } + } else { + style.lineHeight = computed.height; + } + } else { + style[prop] = computed[prop]; + } + }); + + if (isFirefox) { + // Firefox lies about the overflow property for textareas: https://bugzilla.mozilla.org/show_bug.cgi?id=984275 + if (element.scrollHeight > parseInt(computed.height)) + style.overflowY = 'scroll'; + } else { + style.overflow = 'hidden'; // for Chrome to not render a scrollbar; IE keeps overflowY = 'scroll' + } + + div.textContent = element.value.substring(0, position); + // The second special handling for input type="text" vs textarea: + // spaces need to be replaced with non-breaking spaces - http://stackoverflow.com/a/13402035/1269037 + if (isInput) + div.textContent = div.textContent.replace(/\s/g, '\u00a0'); + + var span = document.createElement('span'); + // Wrapping must be replicated *exactly*, including when a long word gets + // onto the next line, with whitespace at the end of the line before (#7). + // The *only* reliable way to do that is to copy the *entire* rest of the + // textarea's content into the created at the caret position. + // For inputs, just '.' would be enough, but no need to bother. + span.textContent = element.value.substring(position) || '.'; // || because a completely empty faux span doesn't render at all + div.appendChild(span); + + var coordinates = { + top: span.offsetTop + parseInt(computed['borderTopWidth']), + left: span.offsetLeft + parseInt(computed['borderLeftWidth']), + height: parseInt(computed['lineHeight']) + }; + + if (debug) { + span.style.backgroundColor = '#aaa'; + } else { + document.body.removeChild(div); + } + + return coordinates; + } + + if (typeof module != 'undefined' && typeof module.exports != 'undefined') { + module.exports = getCaretCoordinates; + } else if(isBrowser) { + window.getCaretCoordinates = getCaretCoordinates; + } + +}()); \ No newline at end of file diff --git a/_server/colorPicker/color.all.min.js b/_server/thirdparty/color.all.min.js similarity index 100% rename from _server/colorPicker/color.all.min.js rename to _server/thirdparty/color.all.min.js diff --git a/_server/colorPicker/jsColor.js b/_server/thirdparty/jsColor.js similarity index 84% rename from _server/colorPicker/jsColor.js rename to _server/thirdparty/jsColor.js index b3ca28ea..cbd9dee6 100644 --- a/_server/colorPicker/jsColor.js +++ b/_server/thirdparty/jsColor.js @@ -1,3 +1,5 @@ +// ------ ColorPicker ------ // + (function (window) { window.jsColorPicker = function(selectors, config) { var renderCallback = function(colors, mode) { @@ -254,7 +256,7 @@ })(this); // Added -var colors = jsColorPicker('input.color', { +jsColorPicker('input.color', { customBG: '#222', readOnly: false, // patch: false, @@ -303,85 +305,5 @@ function triggerColorPicker(left, top) { } } -Blockly.FieldColour.prototype.createWidget_ = function() { - Blockly.WidgetDiv.hide(); +// ------ AutoCompletion ------ - // console.log('here') - var self=this; - var pb=self.sourceBlock_ - var args = MotaActionBlocks[pb.type].args - var targetf=args[args.indexOf(self.name)-1] - - var getValue=function(){ - // return self.getValue() // css颜色 - return pb.getFieldValue(targetf); - // 也可以用 pb.getFieldValue(targetf) 获得颜色块左边的域的内容 - } - - var setValue=function(newValue){ // css颜色 - self.setValue(newValue) - var c=new Colors(); - c.setColor(newValue) - var rgbatext = [c.colors.webSmart.r,c.colors.webSmart.g,c.colors.webSmart.b,c.colors.alpha].join(","); - pb.setFieldValue(rgbatext, targetf) // 放在颜色块左边的域中 - } - - setTimeout(function () { - document.getElementById("colorPicker").value = getValue(); - window.jsColorPicker.confirm = setValue; - // 设置位置 - triggerColorPicker(Blockly.WidgetDiv.DIV.style.left, Blockly.WidgetDiv.DIV.style.top); - }); - - return document.createElement('table'); -}; - -Blockly.FieldTextInput.prototype.showInlineEditor_ = function(quietInput) { - Blockly.WidgetDiv.show(this, this.sourceBlock_.RTL, this.widgetDispose_()); - var div = Blockly.WidgetDiv.DIV; - // Create the input. - var htmlInput = - goog.dom.createDom(goog.dom.TagName.INPUT, 'blocklyHtmlInput'); - htmlInput.setAttribute('spellcheck', this.spellcheck_); - var fontSize = - (Blockly.FieldTextInput.FONTSIZE * this.workspace_.scale) + 'pt'; - div.style.fontSize = fontSize; - htmlInput.style.fontSize = fontSize; - - Blockly.FieldTextInput.htmlInput_ = htmlInput; - div.appendChild(htmlInput); - - htmlInput.value = htmlInput.defaultValue = this.text_; - htmlInput.oldValue_ = null; - this.validate_(); - this.resizeEditor_(); - if (!quietInput) { - htmlInput.focus(); - htmlInput.select(); - } - - // console.log('here') - var self=this; - var pb=self.sourceBlock_ - var args = MotaActionBlocks[pb.type].args - var targetf=args[args.indexOf(self.name)+1] - - if(targetf && targetf.slice(0,7)==='Colour_'){ - var inputDom = htmlInput; - // var getValue=function(){ // 获得自己的字符串 - // return pb.getFieldValue(self.name); - // } - var setValue = function(newValue){ // 设置右边颜色块的css颜色 - pb.setFieldValue(newValue, targetf) - } - // 给inputDom绑事件 - inputDom.oninput=function(){ - var value=inputDom.value - if(/[0-9 ]+,[0-9 ]+,[0-9 ]+(,[0-9. ]+)?/.test(value)){ - setValue('rgba('+value+')') - } - } - } - - this.bindEvents_(htmlInput); -}; \ No newline at end of file diff --git a/_server/vendor/polyfill.min.js b/_server/vendor/polyfill.min.js deleted file mode 100644 index 80fe8dc8..00000000 --- a/_server/vendor/polyfill.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n():"function"==typeof define&&define.amd?define(n):n()}(0,function(){"use strict";function e(){}function n(e,n){for(;3===e._state;)e=e._value;0!==e._state?(e._handled=!0,f._immediateFn(function(){var i=1===e._state?n.onFulfilled:n.onRejected;if(null!==i){var r;try{r=i(e._value)}catch(e){return void o(n.promise,e)}t(n.promise,r)}else(1===e._state?t:o)(n.promise,e._value)})):e._deferreds.push(n)}function t(e,n){try{if(n===e)throw new TypeError("A promise cannot be resolved with itself.");if(n&&("object"==typeof n||"function"==typeof n)){var t=n.then;if(n instanceof f)return e._state=3,e._value=n,void i(e);if("function"==typeof t)return void r(function(e,n){return function(){e.apply(n,arguments)}}(t,n),e)}e._state=1,e._value=n,i(e)}catch(n){o(e,n)}}function o(e,n){e._state=2,e._value=n,i(e)}function i(e){2===e._state&&0===e._deferreds.length&&f._immediateFn(function(){e._handled||f._unhandledRejectionFn(e._value)});for(var t=0,o=e._deferreds.length;o>t;t++)n(e,e._deferreds[t]);e._deferreds=null}function r(e,n){var i=!1;try{e(function(e){i||(i=!0,t(n,e))},function(e){i||(i=!0,o(n,e))})}catch(e){if(i)return;i=!0,o(n,e)}}function f(e){if(!(this instanceof f))throw new TypeError("Promises must be constructed via new");if("function"!=typeof e)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=void 0,this._deferreds=[],r(e,this)}var u=setTimeout,c=f.prototype;c.catch=function(e){return this.then(null,e)},c.then=function(t,o){var i=new this.constructor(e);return n(this,new function(e,n,t){this.onFulfilled="function"==typeof e?e:null,this.onRejected="function"==typeof n?n:null,this.promise=t}(t,o,i)),i},f.all=function(e){return new f(function(n,t){function o(e,f){try{if(f&&("object"==typeof f||"function"==typeof f)){var u=f.then;if("function"==typeof u)return void u.call(f,function(n){o(e,n)},t)}i[e]=f,0==--r&&n(i)}catch(e){t(e)}}if(!e||void 0===e.length)throw new TypeError("Promise.all accepts an array");var i=Array.prototype.slice.call(e);if(0===i.length)return n([]);for(var r=i.length,f=0;i.length>f;f++)o(f,i[f])})},f.resolve=function(e){return e&&"object"==typeof e&&e.constructor===f?e:new f(function(n){n(e)})},f.reject=function(e){return new f(function(n,t){t(e)})},f.race=function(e){return new f(function(n,t){for(var o=0,i=e.length;i>o;o++)e[o].then(n,t)})},f._immediateFn="function"==typeof setImmediate&&function(e){setImmediate(e)}||function(e){u(e,0)},f._unhandledRejectionFn=function(e){void 0!==console&&console&&console.warn("Possible Unhandled Promise Rejection:",e)};var a=function(){if("undefined"!=typeof self)return self;if("undefined"!=typeof window)return window;if(void 0!==a)return a;throw Error("unable to locate global object")}();a.Promise||(a.Promise=f)}); diff --git a/_server/vendor/vue.min.js b/_server/vendor/vue.min.js deleted file mode 100644 index 4eb55b79..00000000 --- a/_server/vendor/vue.min.js +++ /dev/null @@ -1,6 +0,0 @@ -/*! - * Vue.js v2.5.11 - * (c) 2014-2017 Evan You - * Released under the MIT License. - */ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.Vue=e()}(this,function(){"use strict";function t(t){return void 0===t||null===t}function e(t){return void 0!==t&&null!==t}function n(t){return!0===t}function r(t){return"string"==typeof t||"number"==typeof t||"boolean"==typeof t}function i(t){return null!==t&&"object"==typeof t}function o(t){return"[object Object]"===Nn.call(t)}function a(t){var e=parseFloat(String(t));return e>=0&&Math.floor(e)===e&&isFinite(t)}function s(t){return null==t?"":"object"==typeof t?JSON.stringify(t,null,2):String(t)}function c(t){var e=parseFloat(t);return isNaN(e)?t:e}function u(t,e){for(var n=Object.create(null),r=t.split(","),i=0;i-1)return t.splice(n,1)}}function f(t,e){return Mn.call(t,e)}function d(t){var e=Object.create(null);return function(n){return e[n]||(e[n]=t(n))}}function p(t,e){function n(n){var r=arguments.length;return r?r>1?t.apply(e,arguments):t.call(e,n):t.call(e)}return n._length=t.length,n}function v(t,e){e=e||0;for(var n=t.length-e,r=new Array(n);n--;)r[n]=t[n+e];return r}function h(t,e){for(var n in e)t[n]=e[n];return t}function m(t){for(var e={},n=0;n0&&(tt((s=et(s,(o||"")+"_"+a))[0])&&tt(u)&&(l[c]=x(u.text+s[0].text),s.shift()),l.push.apply(l,s)):r(s)?tt(u)?l[c]=x(u.text+s):""!==s&&l.push(x(s)):tt(s)&&tt(u)?l[c]=x(u.text+s.text):(n(i._isVList)&&e(s.tag)&&t(s.key)&&e(o)&&(s.key="__vlist"+o+"_"+a+"__"),l.push(s)));return l}function nt(t,e){return(t.__esModule||fr&&"Module"===t[Symbol.toStringTag])&&(t=t.default),i(t)?e.extend(t):t}function rt(t){return t.isComment&&t.asyncFactory}function it(t){if(Array.isArray(t))for(var n=0;n=0||n.indexOf(t[i])<0)&&r.push(t[i]);return r}return t}}(n[o],r[o],i[o]));return e}(t);r&&h(t.extendOptions,r),(e=t.options=F(n,t.extendOptions)).name&&(e.components[e.name]=t)}}return e}function Rt(t){this._init(t)}function Ht(t){t.cid=0;var e=1;t.extend=function(t){t=t||{};var n=this,r=n.cid,i=t._Ctor||(t._Ctor={});if(i[r])return i[r];var o=t.name||n.options.name,a=function(t){this._init(t)};return a.prototype=Object.create(n.prototype),a.prototype.constructor=a,a.cid=e++,a.options=F(n.options,t),a.super=n,a.options.props&&function(t){var e=t.options.props;for(var n in e)mt(t.prototype,"_props",n)}(a),a.options.computed&&function(t){var e=t.options.computed;for(var n in e)gt(t.prototype,n,e[n])}(a),a.extend=n.extend,a.mixin=n.mixin,a.use=n.use,zn.forEach(function(t){a[t]=n[t]}),o&&(a.options.components[o]=a),a.superOptions=n.options,a.extendOptions=t,a.sealedOptions=h({},a.options),i[r]=a,a}}function Bt(t){return t&&(t.Ctor.options.name||t.tag)}function Ut(t,e){return Array.isArray(t)?t.indexOf(e)>-1:"string"==typeof t?t.split(",").indexOf(e)>-1:!!function(t){return"[object RegExp]"===Nn.call(t)}(t)&&t.test(e)}function Vt(t,e){var n=t.cache,r=t.keys,i=t._vnode;for(var o in n){var a=n[o];if(a){var s=Bt(a.componentOptions);s&&!e(s)&&zt(n,o,r,i)}}}function zt(t,e,n,r){var i=t[e];!i||r&&i.tag===r.tag||i.componentInstance.$destroy(),t[e]=null,l(n,e)}function Kt(t){for(var n=t.data,r=t,i=t;e(i.componentInstance);)(i=i.componentInstance._vnode)&&i.data&&(n=Jt(i.data,n));for(;e(r=r.parent);)r&&r.data&&(n=Jt(n,r.data));return function(t,n){if(e(t)||e(n))return qt(t,Wt(n));return""}(n.staticClass,n.class)}function Jt(t,n){return{staticClass:qt(t.staticClass,n.staticClass),class:e(t.class)?[t.class,n.class]:n.class}}function qt(t,e){return t?e?t+" "+e:t:e||""}function Wt(t){return Array.isArray(t)?function(t){for(var n,r="",i=0,o=t.length;i=0&&" "===(m=t.charAt(h));h--);m&&Ii.test(m)||(l=!0)}}else void 0===o?(v=i+1,o=t.slice(0,i).trim()):e();if(void 0===o?o=t.slice(0,i).trim():0!==v&&e(),a)for(i=0;i-1?{exp:t.slice(0,ii),key:'"'+t.slice(ii+1)+'"'}:{exp:t,key:null};ni=t,ii=oi=ai=0;for(;!ge();)_e(ri=ye())?be(ri):91===ri&&function(t){var e=1;oi=ii;for(;!ge();)if(t=ye(),_e(t))be(t);else if(91===t&&e++,93===t&&e--,0===e){ai=ii;break}}(ri);return{exp:t.slice(0,oi),key:t.slice(oi+1,ai)}}(t);return null===n.key?t+"="+e:"$set("+n.exp+", "+n.key+", "+e+")"}function ye(){return ni.charCodeAt(++ii)}function ge(){return ii>=ei}function _e(t){return 34===t||39===t}function be(t){for(var e=t;!ge()&&(t=ye())!==e;);}function $e(t,e,n,r,i){e=function(t){return t._withTask||(t._withTask=function(){Er=!0;var e=t.apply(null,arguments);return Er=!1,e})}(e),n&&(e=function(t,e,n){var r=si;return function i(){null!==t.apply(null,arguments)&&Ce(e,i,n,r)}}(e,t,r)),si.addEventListener(t,e,or?{capture:r,passive:i}:r)}function Ce(t,e,n,r){(r||si).removeEventListener(t,e._withTask||e,n)}function we(n,r){if(!t(n.data.on)||!t(r.data.on)){var i=r.data.on||{},o=n.data.on||{};si=r.elm,function(t){if(e(t[Li])){var n=Qn?"change":"input";t[n]=[].concat(t[Li],t[n]||[]),delete t[Li]}e(t[Mi])&&(t.change=[].concat(t[Mi],t.change||[]),delete t[Mi])}(i),X(i,o,$e,Ce,r.context),si=void 0}}function xe(n,r){if(!t(n.data.domProps)||!t(r.data.domProps)){var i,o,a=r.elm,s=n.data.domProps||{},u=r.data.domProps||{};e(u.__ob__)&&(u=r.data.domProps=h({},u));for(i in s)t(u[i])&&(a[i]="");for(i in u){if(o=u[i],"textContent"===i||"innerHTML"===i){if(r.children&&(r.children.length=0),o===s[i])continue;1===a.childNodes.length&&a.removeChild(a.childNodes[0])}if("value"===i){a._value=o;var l=t(o)?"":String(o);(function(t,n){return!t.composing&&("OPTION"===t.tagName||function(t,e){var n=!0;try{n=document.activeElement!==t}catch(t){}return n&&t.value!==e}(t,n)||function(t,n){var r=t.value,i=t._vModifiers;if(e(i)){if(i.lazy)return!1;if(i.number)return c(r)!==c(n);if(i.trim)return r.trim()!==n.trim()}return r!==n}(t,n))})(a,l)&&(a.value=l)}else a[i]=o}}}function ke(t){var e=Ae(t.style);return t.staticStyle?h(t.staticStyle,e):e}function Ae(t){return Array.isArray(t)?m(t):"string"==typeof t?Fi(t):t}function Oe(n,r){var i=r.data,o=n.data;if(!(t(i.staticStyle)&&t(i.style)&&t(o.staticStyle)&&t(o.style))){var a,s,c=r.elm,u=o.staticStyle,l=o.normalizedStyle||o.style||{},f=u||l,d=Ae(r.data.style)||{};r.data.normalizedStyle=e(d.__ob__)?h({},d):d;var p=function(t,e){var n,r={};if(e)for(var i=t;i.componentInstance;)(i=i.componentInstance._vnode)&&i.data&&(n=ke(i.data))&&h(r,n);(n=ke(t.data))&&h(r,n);for(var o=t;o=o.parent;)o.data&&(n=ke(o.data))&&h(r,n);return r}(r,!0);for(s in f)t(p[s])&&Bi(c,s,"");for(s in p)(a=p[s])!==f[s]&&Bi(c,s,null==a?"":a)}}function Se(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.split(/\s+/).forEach(function(e){return t.classList.add(e)}):t.classList.add(e);else{var n=" "+(t.getAttribute("class")||"")+" ";n.indexOf(" "+e+" ")<0&&t.setAttribute("class",(n+e).trim())}}function Te(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.split(/\s+/).forEach(function(e){return t.classList.remove(e)}):t.classList.remove(e),t.classList.length||t.removeAttribute("class");else{for(var n=" "+(t.getAttribute("class")||"")+" ",r=" "+e+" ";n.indexOf(r)>=0;)n=n.replace(r," ");(n=n.trim())?t.setAttribute("class",n):t.removeAttribute("class")}}function Ee(t){if(t){if("object"==typeof t){var e={};return!1!==t.css&&h(e,Ki(t.name||"v")),h(e,t),e}return"string"==typeof t?Ki(t):void 0}}function je(t){Qi(function(){Qi(t)})}function Ne(t,e){var n=t._transitionClasses||(t._transitionClasses=[]);n.indexOf(e)<0&&(n.push(e),Se(t,e))}function Ie(t,e){t._transitionClasses&&l(t._transitionClasses,e),Te(t,e)}function Le(t,e,n){var r=Me(t,e),i=r.type,o=r.timeout,a=r.propCount;if(!i)return n();var s=i===qi?Zi:Yi,c=0,u=function(){t.removeEventListener(s,l),n()},l=function(e){e.target===t&&++c>=a&&u()};setTimeout(function(){c0&&(n=qi,l=a,f=o.length):e===Wi?u>0&&(n=Wi,l=u,f=c.length):f=(n=(l=Math.max(a,u))>0?a>u?qi:Wi:null)?n===qi?o.length:c.length:0;return{type:n,timeout:l,propCount:f,hasTransform:n===qi&&to.test(r[Gi+"Property"])}}function De(t,e){for(;t.length1}function Ue(t,e){!0!==e.data.show&&Fe(e)}function Ve(t,e,n){ze(t,e,n),(Qn||er)&&setTimeout(function(){ze(t,e,n)},0)}function ze(t,e,n){var r=e.value,i=t.multiple;if(!i||Array.isArray(r)){for(var o,a,s=0,c=t.options.length;s-1,a.selected!==o&&(a.selected=o);else if(g(Je(a),r))return void(t.selectedIndex!==s&&(t.selectedIndex=s));i||(t.selectedIndex=-1)}}function Ke(t,e){return e.every(function(e){return!g(e,t)})}function Je(t){return"_value"in t?t._value:t.value}function qe(t){t.target.composing=!0}function We(t){t.target.composing&&(t.target.composing=!1,Ge(t.target,"input"))}function Ge(t,e){var n=document.createEvent("HTMLEvents");n.initEvent(e,!0,!0),t.dispatchEvent(n)}function Ze(t){return!t.componentInstance||t.data&&t.data.transition?t:Ze(t.componentInstance._vnode)}function Xe(t){var e=t&&t.componentOptions;return e&&e.Ctor.options.abstract?Xe(it(e.children)):t}function Ye(t){var e={},n=t.$options;for(var r in n.propsData)e[r]=t[r];var i=n._parentListeners;for(var o in i)e[Pn(o)]=i[o];return e}function Qe(t,e){if(/\d-keep-alive$/.test(e.tag))return t("keep-alive",{props:e.componentOptions.propsData})}function tn(t){t.elm._moveCb&&t.elm._moveCb(),t.elm._enterCb&&t.elm._enterCb()}function en(t){t.data.newPos=t.elm.getBoundingClientRect()}function nn(t){var e=t.data.pos,n=t.data.newPos,r=e.left-n.left,i=e.top-n.top;if(r||i){t.data.moved=!0;var o=t.elm.style;o.transform=o.WebkitTransform="translate("+r+"px,"+i+"px)",o.transitionDuration="0s"}}function rn(t,e){var n=e?zo:Vo;return t.replace(n,function(t){return Uo[t]})}function on(t,e,n){return{type:1,tag:t,attrsList:e,attrsMap:function(t){for(var e={},n=0,r=t.length;n=0&&a[i].lowerCasedTag!==s;i--);else i=0;if(i>=0){for(var c=a.length-1;c>=i;c--)e.end&&e.end(a[c].tag,n,r);a.length=i,o=i&&a[i-1].tag}else"br"===s?e.start&&e.start(t,[],!0,n,r):"p"===s&&(e.start&&e.start(t,[],!1,n,r),e.end&&e.end(t,n,r))}for(var i,o,a=[],s=e.expectHTML,c=e.isUnaryTag||Bn,u=e.canBeLeftOpenTag||Bn,l=0;t;){if(i=t,o&&Ho(o)){var f=0,d=o.toLowerCase(),p=Bo[d]||(Bo[d]=new RegExp("([\\s\\S]*?)(]*>)","i")),v=t.replace(p,function(t,n,r){return f=r.length,Ho(d)||"noscript"===d||(n=n.replace(//g,"$1").replace(//g,"$1")),Jo(d,n)&&(n=n.slice(1)),e.chars&&e.chars(n),""});l+=t.length-v.length,t=v,r(d,l-f,l)}else{var h=t.indexOf("<");if(0===h){if(Ao.test(t)){var m=t.indexOf("--\x3e");if(m>=0){e.shouldKeepComment&&e.comment(t.substring(4,m)),n(m+3);continue}}if(Oo.test(t)){var y=t.indexOf("]>");if(y>=0){n(y+2);continue}}var g=t.match(ko);if(g){n(g[0].length);continue}var _=t.match(xo);if(_){var b=l;n(_[0].length),r(_[1],b,l);continue}var $=function(){var e=t.match(Co);if(e){var r={tagName:e[1],attrs:[],start:l};n(e[0].length);for(var i,o;!(i=t.match(wo))&&(o=t.match(_o));)n(o[0].length),r.attrs.push(o);if(i)return r.unarySlash=i[1],n(i[0].length),r.end=l,r}}();if($){!function(t){var n=t.tagName,i=t.unarySlash;s&&("p"===o&&go(n)&&r(o),u(n)&&o===n&&r(n));for(var l=c(n)||!!i,f=t.attrs.length,d=new Array(f),p=0;p=0){for(w=t.slice(h);!(xo.test(w)||Co.test(w)||Ao.test(w)||Oo.test(w)||(x=w.indexOf("<",1))<0);)h+=x,w=t.slice(h);C=t.substring(0,h),n(h)}h<0&&(C=t,t=""),e.chars&&C&&e.chars(C)}if(t===i){e.chars&&e.chars(t);break}}r()}(t,{warn:To,expectHTML:e.expectHTML,isUnaryTag:e.isUnaryTag,canBeLeftOpenTag:e.canBeLeftOpenTag,shouldDecodeNewlines:e.shouldDecodeNewlines,shouldDecodeNewlinesForHref:e.shouldDecodeNewlinesForHref,shouldKeepComment:e.comments,start:function(t,a,u){var l=i&&i.ns||Do(t);Qn&&"svg"===l&&(a=function(t){for(var e=[],n=0;na&&o.push(JSON.stringify(t.slice(a,i)));var s=ae(r[1].trim());o.push("_s("+s+")"),a=i+r[0].length}return a':'
',Ro.innerHTML.indexOf(" ")>0}var jn=Object.freeze({}),Nn=Object.prototype.toString,In=u("slot,component",!0),Ln=u("key,ref,slot,slot-scope,is"),Mn=Object.prototype.hasOwnProperty,Dn=/-(\w)/g,Pn=d(function(t){return t.replace(Dn,function(t,e){return e?e.toUpperCase():""})}),Fn=d(function(t){return t.charAt(0).toUpperCase()+t.slice(1)}),Rn=/\B([A-Z])/g,Hn=d(function(t){return t.replace(Rn,"-$1").toLowerCase()}),Bn=function(t,e,n){return!1},Un=function(t){return t},Vn="data-server-rendered",zn=["component","directive","filter"],Kn=["beforeCreate","created","beforeMount","mounted","beforeUpdate","updated","beforeDestroy","destroyed","activated","deactivated","errorCaptured"],Jn={optionMergeStrategies:Object.create(null),silent:!1,productionTip:!1,devtools:!1,performance:!1,errorHandler:null,warnHandler:null,ignoredElements:[],keyCodes:Object.create(null),isReservedTag:Bn,isReservedAttr:Bn,isUnknownElement:Bn,getTagNamespace:y,parsePlatformTagName:Un,mustUseProp:Bn,_lifecycleHooks:Kn},qn=/[^\w.$]/,Wn="__proto__"in{},Gn="undefined"!=typeof window,Zn="undefined"!=typeof WXEnvironment&&!!WXEnvironment.platform,Xn=Zn&&WXEnvironment.platform.toLowerCase(),Yn=Gn&&window.navigator.userAgent.toLowerCase(),Qn=Yn&&/msie|trident/.test(Yn),tr=Yn&&Yn.indexOf("msie 9.0")>0,er=Yn&&Yn.indexOf("edge/")>0,nr=Yn&&Yn.indexOf("android")>0||"android"===Xn,rr=Yn&&/iphone|ipad|ipod|ios/.test(Yn)||"ios"===Xn,ir=(Yn&&/chrome\/\d+/.test(Yn),{}.watch),or=!1;if(Gn)try{var ar={};Object.defineProperty(ar,"passive",{get:function(){or=!0}}),window.addEventListener("test-passive",null,ar)}catch(t){}var sr,cr,ur=function(){return void 0===sr&&(sr=!Gn&&"undefined"!=typeof global&&"server"===global.process.env.VUE_ENV),sr},lr=Gn&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__,fr="undefined"!=typeof Symbol&&w(Symbol)&&"undefined"!=typeof Reflect&&w(Reflect.ownKeys);cr="undefined"!=typeof Set&&w(Set)?Set:function(){function t(){this.set=Object.create(null)}return t.prototype.has=function(t){return!0===this.set[t]},t.prototype.add=function(t){this.set[t]=!0},t.prototype.clear=function(){this.set=Object.create(null)},t}();var dr=y,pr=0,vr=function(){this.id=pr++,this.subs=[]};vr.prototype.addSub=function(t){this.subs.push(t)},vr.prototype.removeSub=function(t){l(this.subs,t)},vr.prototype.depend=function(){vr.target&&vr.target.addDep(this)},vr.prototype.notify=function(){for(var t=this.subs.slice(),e=0,n=t.length;eVr&&Fr[n].id>t.id;)n--;Fr.splice(n+1,0,t)}else Fr.push(t);Br||(Br=!0,q(ht))}}(this)},Kr.prototype.run=function(){if(this.active){var t=this.get();if(t!==this.value||i(t)||this.deep){var e=this.value;if(this.value=t,this.user)try{this.cb.call(this.vm,t,e)}catch(t){V(t,this.vm,'callback for watcher "'+this.expression+'"')}else this.cb.call(this.vm,t,e)}}},Kr.prototype.evaluate=function(){this.value=this.get(),this.dirty=!1},Kr.prototype.depend=function(){for(var t=this.deps.length;t--;)this.deps[t].depend()},Kr.prototype.teardown=function(){if(this.active){this.vm._isBeingDestroyed||l(this.vm._watchers,this);for(var t=this.deps.length;t--;)this.deps[t].removeSub(this);this.active=!1}};var Jr={enumerable:!0,configurable:!0,get:y,set:y},qr={lazy:!0};Nt(It.prototype);var Wr={init:function(t,n,r,i){if(!t.componentInstance||t.componentInstance._isDestroyed){(t.componentInstance=function(t,n,r,i){var o={_isComponent:!0,parent:n,_parentVnode:t,_parentElm:r||null,_refElm:i||null},a=t.data.inlineTemplate;return e(a)&&(o.render=a.render,o.staticRenderFns=a.staticRenderFns),new t.componentOptions.Ctor(o)}(t,Pr,r,i)).$mount(n?t.elm:void 0,n)}else if(t.data.keepAlive){var o=t;Wr.prepatch(o,o)}},prepatch:function(t,e){var n=e.componentOptions;!function(t,e,n,r,i){var o=!!(i||t.$options._renderChildren||r.data.scopedSlots||t.$scopedSlots!==jn);if(t.$options._parentVnode=r,t.$vnode=r,t._vnode&&(t._vnode.parent=r),t.$options._renderChildren=i,t.$attrs=r.data&&r.data.attrs||jn,t.$listeners=n||jn,e&&t.$options.props){Cr.shouldConvert=!1;for(var a=t._props,s=t.$options._propKeys||[],c=0;c1?v(n):n;for(var r=v(arguments,1),i=0,o=n.length;iparseInt(this.max)&&zt(a,s[0],s,this._vnode)),e.data.keepAlive=!0}return e||t&&t[0]}}};!function(t){var e={};e.get=function(){return Jn},Object.defineProperty(t,"config",e),t.util={warn:dr,extend:h,mergeOptions:F,defineReactive:E},t.set=j,t.delete=N,t.nextTick=q,t.options=Object.create(null),zn.forEach(function(e){t.options[e+"s"]=Object.create(null)}),t.options._base=t,h(t.options.components,ti),function(t){t.use=function(t){var e=this._installedPlugins||(this._installedPlugins=[]);if(e.indexOf(t)>-1)return this;var n=v(arguments,1);return n.unshift(this),"function"==typeof t.install?t.install.apply(t,n):"function"==typeof t&&t.apply(null,n),e.push(t),this}}(t),function(t){t.mixin=function(t){return this.options=F(this.options,t),this}}(t),Ht(t),function(t){zn.forEach(function(e){t[e]=function(t,n){return n?("component"===e&&o(n)&&(n.name=n.name||t,n=this.options._base.extend(n)),"directive"===e&&"function"==typeof n&&(n={bind:n,update:n}),this.options[e+"s"][t]=n,n):this.options[e+"s"][t]}})}(t)}(Rt),Object.defineProperty(Rt.prototype,"$isServer",{get:ur}),Object.defineProperty(Rt.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),Rt.version="2.5.11";var ei,ni,ri,ii,oi,ai,si,ci,ui=u("style,class"),li=u("input,textarea,option,select,progress"),fi=function(t,e,n){return"value"===n&&li(t)&&"button"!==e||"selected"===n&&"option"===t||"checked"===n&&"input"===t||"muted"===n&&"video"===t},di=u("contenteditable,draggable,spellcheck"),pi=u("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,translate,truespeed,typemustmatch,visible"),vi="http://www.w3.org/1999/xlink",hi=function(t){return":"===t.charAt(5)&&"xlink"===t.slice(0,5)},mi=function(t){return hi(t)?t.slice(6,t.length):""},yi=function(t){return null==t||!1===t},gi={svg:"http://www.w3.org/2000/svg",math:"http://www.w3.org/1998/Math/MathML"},_i=u("html,body,base,head,link,meta,style,title,address,article,aside,footer,header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,s,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,output,progress,select,textarea,details,dialog,menu,menuitem,summary,content,element,shadow,template,blockquote,iframe,tfoot"),bi=u("svg,animate,circle,clippath,cursor,defs,desc,ellipse,filter,font-face,foreignObject,g,glyph,image,line,marker,mask,missing-glyph,path,pattern,polygon,polyline,rect,switch,symbol,text,textpath,tspan,use,view",!0),$i=function(t){return _i(t)||bi(t)},Ci=Object.create(null),wi=u("text,number,password,search,email,tel,url"),xi=Object.freeze({createElement:function(t,e){var n=document.createElement(t);return"select"!==t?n:(e.data&&e.data.attrs&&void 0!==e.data.attrs.multiple&&n.setAttribute("multiple","multiple"),n)},createElementNS:function(t,e){return document.createElementNS(gi[t],e)},createTextNode:function(t){return document.createTextNode(t)},createComment:function(t){return document.createComment(t)},insertBefore:function(t,e,n){t.insertBefore(e,n)},removeChild:function(t,e){t.removeChild(e)},appendChild:function(t,e){t.appendChild(e)},parentNode:function(t){return t.parentNode},nextSibling:function(t){return t.nextSibling},tagName:function(t){return t.tagName},setTextContent:function(t,e){t.textContent=e},setAttribute:function(t,e,n){t.setAttribute(e,n)}}),ki={create:function(t,e){Xt(e)},update:function(t,e){t.data.ref!==e.data.ref&&(Xt(t,!0),Xt(e))},destroy:function(t){Xt(t,!0)}},Ai=new mr("",{},[]),Oi=["create","activate","update","remove","destroy"],Si={create:te,update:te,destroy:function(t){te(t,Ai)}},Ti=Object.create(null),Ei=[ki,Si],ji={create:re,update:re},Ni={create:oe,update:oe},Ii=/[\w).+\-_$\]]/,Li="__r",Mi="__c",Di={create:we,update:we},Pi={create:xe,update:xe},Fi=d(function(t){var e={},n=/:(.+)/;return t.split(/;(?![^(]*\))/g).forEach(function(t){if(t){var r=t.split(n);r.length>1&&(e[r[0].trim()]=r[1].trim())}}),e}),Ri=/^--/,Hi=/\s*!important$/,Bi=function(t,e,n){if(Ri.test(e))t.style.setProperty(e,n);else if(Hi.test(n))t.style.setProperty(e,n.replace(Hi,""),"important");else{var r=Vi(e);if(Array.isArray(n))for(var i=0,o=n.length;ip?v(n,t(i[g+1])?null:i[g+1].elm,i,d,g,o):d>g&&m(0,r,f,p)}function _(r,i,o,a){if(r!==i){var s=i.elm=r.elm;if(n(r.isAsyncPlaceholder))e(i.asyncFactory.resolved)?$(r.elm,i,o):i.isAsyncPlaceholder=!0;else if(n(i.isStatic)&&n(r.isStatic)&&i.key===r.key&&(n(i.isCloned)||n(i.isOnce)))i.componentInstance=r.componentInstance;else{var c,u=i.data;e(u)&&e(c=u.hook)&&e(c=c.prepatch)&&c(r,i);var l=r.children,d=i.children;if(e(u)&&f(i)){for(c=0;c-1?Ci[t]=e.constructor===window.HTMLUnknownElement||e.constructor===window.HTMLElement:Ci[t]=/HTMLUnknownElement/.test(e.toString())},h(Rt.options.directives,ro),h(Rt.options.components,so),Rt.prototype.__patch__=Gn?eo:y,Rt.prototype.$mount=function(t,e){return t=t&&Gn?Zt(t):void 0,function(t,e,n){t.$el=e,t.$options.render||(t.$options.render=gr),vt(t,"beforeMount");var r;return r=function(){t._update(t._render(),n)},new Kr(t,r,y,null,!0),n=!1,null==t.$vnode&&(t._isMounted=!0,vt(t,"mounted")),t}(this,t,e)},Rt.nextTick(function(){Jn.devtools&&lr&&lr.emit("init",Rt)},0);var co,uo=/\{\{((?:.|\n)+?)\}\}/g,lo=/[-.*+?^${}()|[\]\/\\]/g,fo=d(function(t){var e=t[0].replace(lo,"\\$&"),n=t[1].replace(lo,"\\$&");return new RegExp(e+"((?:.|\\n)+?)"+n,"g")}),po={staticKeys:["staticClass"],transformNode:function(t,e){e.warn;var n=ve(t,"class");n&&(t.staticClass=JSON.stringify(n));var r=pe(t,"class",!1);r&&(t.classBinding=r)},genData:function(t){var e="";return t.staticClass&&(e+="staticClass:"+t.staticClass+","),t.classBinding&&(e+="class:"+t.classBinding+","),e}},vo={staticKeys:["staticStyle"],transformNode:function(t,e){e.warn;var n=ve(t,"style");n&&(t.staticStyle=JSON.stringify(Fi(n)));var r=pe(t,"style",!1);r&&(t.styleBinding=r)},genData:function(t){var e="";return t.staticStyle&&(e+="staticStyle:"+t.staticStyle+","),t.styleBinding&&(e+="style:("+t.styleBinding+"),"),e}},ho=function(t){return co=co||document.createElement("div"),co.innerHTML=t,co.textContent},mo=u("area,base,br,col,embed,frame,hr,img,input,isindex,keygen,link,meta,param,source,track,wbr"),yo=u("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr,source"),go=u("address,article,aside,base,blockquote,body,caption,col,colgroup,dd,details,dialog,div,dl,dt,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,legend,li,menuitem,meta,optgroup,option,param,rp,rt,source,style,summary,tbody,td,tfoot,th,thead,title,tr,track"),_o=/^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/,bo="[a-zA-Z_][\\w\\-\\.]*",$o="((?:"+bo+"\\:)?"+bo+")",Co=new RegExp("^<"+$o),wo=/^\s*(\/?)>/,xo=new RegExp("^<\\/"+$o+"[^>]*>"),ko=/^]+>/i,Ao=/^ + @@ -567,9 +600,11 @@ - - - + + + + + diff --git a/editor.html b/editor.html index 4ea3654f..116d8de4 100644 --- a/editor.html +++ b/editor.html @@ -4,6 +4,7 @@ + @@ -211,6 +212,7 @@
+ @@ -292,7 +294,7 @@ - +
@@ -351,6 +353,7 @@
+ -

请输入文字...

- +
diff --git a/libs/actions.js b/libs/actions.js index 75a43b8b..648b8dd6 100644 --- a/libs/actions.js +++ b/libs/actions.js @@ -112,8 +112,8 @@ actions.prototype.doRegisteredAction = function (action) { } actions.prototype._checkReplaying = function () { - if (core.isReplaying() && core.status.event.id != 'save' - && (core.status.event.id || "").indexOf('book') != 0 && core.status.event.id != 'viewMaps') + if (core.isReplaying() && + ['save','book','book-detail','viewMaps','toolbox','equipbox','text'].indexOf(core.status.event.id)<0) return true; return false; } @@ -137,6 +137,7 @@ actions.prototype._sys_onkeyDown = function (e) { return; } } + if (e.preventDefault) e.preventDefault(); core.status.holdingKeys.push(e.keyCode); this.pressKey(e.keyCode); } else { @@ -170,6 +171,12 @@ actions.prototype._sys_onkeyUp_replay = function (e) { core.viewMapReplay(); else if (e.keyCode == 78) // N core.stepReplay(); + else if (e.keyCode == 84) // T + core.toolboxReplay(); + else if (e.keyCode == 81) // Q + core.equipboxReplay(); + else if (e.keyCode == 66) // B + core.drawStatistics(); else if (e.keyCode >= 49 && e.keyCode <= 51) // 1-3 core.setReplaySpeed(e.keyCode - 48); else if (e.keyCode == 52) // 4 @@ -192,6 +199,7 @@ actions.prototype._sys_onkeyUp = function (e) { break; } } + if (e.preventDefault) e.preventDefault(); this.keyUp(e.keyCode, e.altKey); } else { if (e.keyCode == 17) core.status.ctrlDown = false; @@ -712,6 +720,16 @@ actions.prototype._sys_onmousewheel = function (direct) { return; } + // wait事件 + if (core.status.lockControl && core.status.event.id == 'action' && core.status.event.data.type == 'wait') { + core.setFlag('type', 0); + var keycode = direct == 1 ? 33 : 34; + core.setFlag('keycode', keycode); + core.status.route.push("input:" + keycode); + core.doAction(); + return; + } + } ////// 长按Ctrl键时 ////// @@ -1253,7 +1271,7 @@ actions.prototype._clickShop = function (x, y) { actions.prototype._keyDownShop = function (keycode) { // 商店界面长按空格连续购买 - if (keycode == 32) { + if (keycode == 32 && core.status.event.selection != core.status.event.data.shop.choices.length) { this._selectChoices(core.status.event.data.shop.choices.length + 1, keycode, this._clickShop); return; } @@ -1266,7 +1284,7 @@ actions.prototype._keyUpShop = function (keycode) { core.events._exitShop(); return; } - if (keycode != 32) { + if (keycode != 32 || core.status.event.selection == core.status.event.data.shop.choices.length) { this._selectChoices(core.status.event.data.shop.choices.length + 1, keycode, this._clickShop); return; } @@ -1317,7 +1335,10 @@ actions.prototype._clickToolbox = function (x, y) { // 装备栏 if (x >= this.LAST - 2 && y == 0) { core.ui.closePanel(); - core.openEquipbox(); + if (core.isReplaying()) + core.equipboxReplay(); + else + core.openEquipbox(); return; } if (x >= this.LAST - 2 && y == this.LAST) { @@ -1376,6 +1397,7 @@ actions.prototype._clickToolboxIndex = function (index) { if (select >= items.length) return; var itemId = items[select]; if (itemId == core.status.event.data.selectId) { + if (core.isReplaying()) return; core.events.tryUseItem(itemId); } else { @@ -1478,7 +1500,10 @@ actions.prototype._keyDownToolbox = function (keycode) { actions.prototype._keyUpToolbox = function (keycode) { if (keycode == 81) { core.ui.closePanel(); - core.openEquipbox(); + if (core.isReplaying()) + core.equipboxReplay(); + else + core.openEquipbox(); return; } if (keycode == 84 || keycode == 27 || keycode == 88) { @@ -1498,7 +1523,10 @@ actions.prototype._clickEquipbox = function (x, y) { // 道具栏 if (x >= this.LAST - 2 && y == 0) { core.ui.closePanel(); - core.openToolbox(); + if (core.isReplaying()) + core.toolboxReplay(); + else + core.openToolbox(); return; } // 返回 @@ -1547,6 +1575,7 @@ actions.prototype._clickEquipboxIndex = function (index) { if (index < this.LAST) { if (index >= core.status.globalAttribute.equipName.length) return; if (index == core.status.event.selection && core.status.hero.equipment[index]) { + if (core.isReplaying()) return; core.unloadEquip(index); core.status.route.push("unEquip:" + index); } @@ -1554,6 +1583,7 @@ actions.prototype._clickEquipboxIndex = function (index) { else { var equips = Object.keys(core.status.hero.items.equips || {}).sort(); if (index == core.status.event.selection) { + if (core.isReplaying()) return; var equipId = equips[index - this.LAST + (core.status.event.data.page - 1) * this.LAST]; core.loadEquip(equipId); core.status.route.push("equip:" + equipId); @@ -1645,7 +1675,10 @@ actions.prototype._keyUpEquipbox = function (keycode, altKey) { } if (keycode == 84) { core.ui.closePanel(); - core.openToolbox(); + if (core.isReplaying()) + core.toolboxReplay(); + else + core.openToolbox(); return; } if (keycode == 81 || keycode == 27 || keycode == 88) { @@ -1838,6 +1871,11 @@ actions.prototype._keyUpSL = function (keycode) { this._clickSL(this.LAST, this.LAST); return; } + if (keycode >= 48 && keycode <= 57) { + if (keycode == 48) keycode = 58; + core.ui.drawSLPanel((keycode - 49) * 1000 + 1); + return; + } if (keycode == 13 || keycode == 32 || keycode == 67) { if (offset == 0) core.doSL("autoSave", core.status.event.id); @@ -1896,8 +1934,6 @@ actions.prototype._clickSwitchs = function (x, y) { case 7: return this._clickSwitchs_clickMove(); case 8: - return this._clickSwitchs_ExtendKeyboard(); - case 9: core.status.event.selection = 0; core.ui.drawSettings(); break; @@ -1962,13 +1998,6 @@ actions.prototype._clickSwitchs_clickMove = function () { core.ui.drawSwitchs(); } -actions.prototype._clickSwitchs_ExtendKeyboard = function () { - core.platform.extendKeyboard = !core.platform.extendKeyboard; - core.setLocalStorage('extendKeyboard', core.platform.extendKeyboard); - core.updateStatusBar(); - core.ui.drawSwitchs(); -} - ////// 系统设置界面时,放开某个键的操作 ////// actions.prototype._keyUpSwitchs = function (keycode) { if (keycode == 27 || keycode == 88) { @@ -2078,13 +2107,7 @@ actions.prototype._clickSyncSave_readFile = function () { } actions.prototype._clickSyncSave_replay = function () { - if (core.hasFlag('debug')) { - core.drawText("\t[系统提示]调试模式下无法回放录像"); - } - else { - core.status.event.selection = 0; - core.ui.drawReplay(); - } + core.ui.drawReplay(); } ////// 同步存档界面时,放开某个键的操作 ////// @@ -2311,7 +2334,7 @@ actions.prototype._clickReplay_replayRemain = function () { } actions.prototype._clickReplay_download = function () { - if (core.hasFlag('debug')) return core.drawText("\t[系统提示]调试模式下无法下载录像"); + // if (core.hasFlag('debug')) return core.drawText("\t[系统提示]调试模式下无法下载录像"); core.download(core.firstData.name + "_" + core.formatDate2() + ".h5route", JSON.stringify({ 'name': core.firstData.name, 'hard': core.status.hard, diff --git a/libs/control.js b/libs/control.js index d3289e37..9a981c78 100644 --- a/libs/control.js +++ b/libs/control.js @@ -19,7 +19,6 @@ control.prototype._init = function () { this.registerAnimationFrame("totalTime", false, this._animationFrame_totalTime); this.registerAnimationFrame("autoSave", true, this._animationFrame_autoSave); this.registerAnimationFrame("globalAnimate", true, this._animationFrame_globalAnimate); - this.registerAnimationFrame("selector", false, this._animationFrame_selector); this.registerAnimationFrame("animate", true, this._animationFrame_animate); this.registerAnimationFrame("heroMoving", true, this._animationFrame_heroMoving); this.registerAnimationFrame("weather", true, this._animationFrame_weather); @@ -151,19 +150,6 @@ control.prototype._animationFrame_globalAnimate = function (timestamp) { core.animateFrame.globalTime = timestamp; } -control.prototype._animationFrame_selector = function (timestamp) { - if (timestamp - core.animateFrame.selectorTime <= 20 || !core.dymCanvas._selector) return; - var opacity = parseFloat(core.dymCanvas._selector.canvas.style.opacity); - if (core.animateFrame.selectorUp) - opacity += 0.02; - else - opacity -= 0.02; - if (opacity > 0.95 || opacity < 0.55) - core.animateFrame.selectorUp = !core.animateFrame.selectorUp; - core.setOpacity("_selector", opacity); - core.animateFrame.selectorTime = timestamp; -} - control.prototype._animationFrame_animate = function (timestamp) { if (timestamp - core.animateFrame.animateTime < 50 || !core.status.animateObjs || core.status.animateObjs.length == 0) return; core.clearMap('animate'); @@ -333,6 +319,8 @@ control.prototype._showStartAnimate_resetDom = function () { control.prototype._showStartAnimate_finished = function (start, callback) { core.dom.startTop.style.display = 'none'; core.dom.startButtonGroup.style.display = 'block'; + main.selectedButton = null; + main.selectButton(0); if (start) core.startGame(); if (callback) callback(); } @@ -566,6 +554,12 @@ control.prototype.setAutoHeroMove = function (steps) { ////// 设置行走的效果动画 ////// control.prototype.setHeroMoveInterval = function (callback) { if (core.status.heroMoving > 0) return; + if (core.status.replay.speed == 24) { + core.moveOneStep(core.nextX(), core.nextY()); + if (callback) callback(); + return; + } + core.status.heroMoving=1; var toAdd = 1; @@ -741,25 +735,28 @@ control.prototype.turnHero = function(direction) { } ////// 瞬间移动 ////// -control.prototype.moveDirectly = function (destX, destY) { - return this.controldata.moveDirectly(destX, destY); +control.prototype.moveDirectly = function (destX, destY, ignoreSteps) { + return this.controldata.moveDirectly(destX, destY, ignoreSteps); } ////// 尝试瞬间移动 ////// control.prototype.tryMoveDirectly = function (destX, destY) { if (this.nearHero(destX, destY)) return false; var canMoveArray = core.maps.generateMovableArray(); - var testMove = function (dx, dy, dir) { - if (dx<0 || dx>=core.bigmap.width|| dy<0 || dy>=core.bigmap.height) return false; - if (dir && !core.inArray(canMoveArray[dx][dy],dir)) return false; - if (core.control.moveDirectly(dx, dy)) { + var dirs = [[destX,destY],[destX-1,destY,"right"],[destX,destY-1,"down"],[destX,destY+1,"up"],[destX+1,destY,"left"]]; + var canMoveDirectlyArray = core.canMoveDirectlyArray(dirs); + + for (var i = 0; i < dirs.length; ++i) { + var d = dirs[i], dx = d[0], dy = d[1], dir = d[2]; + if (dx<0 || dx>=core.bigmap.width|| dy<0 || dy>=core.bigmap.height) continue; + if (dir && !core.inArray(canMoveArray[dx][dy],dir)) continue; + if (canMoveDirectlyArray[i]<0) continue; + if (core.control.moveDirectly(dx, dy, canMoveDirectlyArray[i])) { if (dir) core.moveHero(dir, function() {}); return true; } - return false; } - return testMove(destX,destY) || testMove(destX-1, destY, "right") || testMove(destX,destY-1,"down") - || testMove(destX,destY+1,"up") || testMove(destX+1,destY,"left"); + return false; } ////// 绘制勇士 ////// @@ -775,13 +772,16 @@ control.prototype.drawHero = function (status, offset) { core.clearAutomaticRouteNode(x+dx, y+dy); core.clearMap('hero'); - this._drawHero_getDrawObjs(direction, x, y, status, offset).forEach(function (block) { - core.drawImage('hero', block.img, block.heroIcon[block.status]*block.width, - block.heroIcon.loc * block.height, block.width, block.height, - block.posx+(32-block.width)/2, block.posy+32-block.height, block.width, block.height); - }); + if (!core.hasFlag('hideHero')) { + this._drawHero_getDrawObjs(direction, x, y, status, offset).forEach(function (block) { + core.drawImage('hero', block.img, block.heroIcon[block.status]*block.width, + block.heroIcon.loc * block.height, block.width, block.height, + block.posx+(32-block.width)/2, block.posy+32-block.height, block.width, block.height); + }); + } core.control.updateViewport(); + core.setGameCanvasTranslate('hero', 0, 0); } control.prototype._drawHero_getDrawObjs = function (direction, x, y, status, offset) { @@ -855,6 +855,48 @@ control.prototype.updateViewport = function() { core.relocateCanvas('route', core.status.automaticRoute.offsetX - core.bigmap.offsetX, core.status.automaticRoute.offsetY - core.bigmap.offsetY); } +////// 设置视野范围 ////// +control.prototype.setViewport = function (x, y) { + core.bigmap.offsetX = core.clamp(x, 0, 32 * core.bigmap.width - core.__PIXELS__); + core.bigmap.offsetY = core.clamp(y, 0, 32 * core.bigmap.height - core.__PIXELS__); + this.updateViewport(); + // ------ hero层也需要! + var hero_x = core.clamp((core.getHeroLoc('x') - core.__HALF_SIZE__) * 32, 0, 32*core.bigmap.width-core.__PIXELS__); + var hero_y = core.clamp((core.getHeroLoc('y') - core.__HALF_SIZE__) * 32, 0, 32*core.bigmap.height-core.__PIXELS__); + core.control.setGameCanvasTranslate('hero', hero_x - core.bigmap.offsetX, hero_y - core.bigmap.offsetY); +} + +////// 移动视野范围 ////// +control.prototype.moveViewport = function (steps, time, callback) { + time = time || core.values.moveSpeed || 300; + var step = 0, moveSteps = (steps||[]).filter(function (t) { + return ['up','down','left','right'].indexOf(t)>=0; + }); + var animate=window.setInterval(function() { + if (moveSteps.length==0) { + delete core.animateFrame.asyncId[animate]; + clearInterval(animate); + if (callback) callback(); + } + else { + if (core.control._moveViewport_moving(++step, moveSteps)) + step = 0; + } + }, time / 16 / core.status.replay.speed); + + core.animateFrame.asyncId[animate] = true; +} + +control.prototype._moveViewport_moving = function (step, moveSteps) { + var direction = moveSteps[0], scan = core.utils.scan[direction]; + core.setViewport(core.bigmap.offsetX + 2 * scan.x, core.bigmap.offsetY + 2 * scan.y); + if (step == 16) { + moveSteps.shift(); + return true; + } + return false; +} + ////// 获得勇士面对位置的x坐标 ////// control.prototype.nextX = function(n) { if (n == null) n = 1; @@ -919,7 +961,7 @@ control.prototype.checkBlock = function () { if (damage) { core.status.hero.hp -= damage; core.drawTip("受到"+(core.status.checkBlock.type[loc]||"伤害")+damage+"点"); - this._checkBlock_soundAndAnimate(x, y); + core.drawAnimate("zone", x, y); this._checkBlock_disableQuickShop(); core.status.hero.statistics.extraDamage += damage; if (core.status.hero.hp <= 0) { @@ -933,11 +975,6 @@ control.prototype.checkBlock = function () { this._checkBlock_ambush(core.status.checkBlock.ambush[loc]); } -control.prototype._checkBlock_soundAndAnimate = function (x,y) { - core.playSound('zone.mp3'); - core.drawAnimate("zone", x, y); -} - control.prototype._checkBlock_disableQuickShop = function () { // 禁用快捷商店 if (core.flags.disableShopOnDamage) { @@ -1197,10 +1234,11 @@ control.prototype.bookReplay = function () { if (core.isMoving() || core.status.replay.animate || (core.status.event.id && core.status.event.id != 'viewMaps')) return core.drawTip("请等待当前事件的处理结束"); + if (!core.hasItem('book')) return core.drawTip('你没有怪物手册'); // 从“浏览地图”页面打开 if (core.status.event.id=='viewMaps') - core.status.event.selection = core.status.event.data; + core.status.event.ui = core.status.event.data; core.lockControl(); core.status.event.id='book'; @@ -1219,6 +1257,28 @@ control.prototype.viewMapReplay = function () { core.ui.drawMaps(); } +control.prototype.toolboxReplay = function () { + if (!core.isPlaying() || !core.isReplaying()) return; + if (!core.status.replay.pausing) return core.drawTip("请先暂停录像"); + if (core.isMoving() || core.status.replay.animate || core.status.event.id) + return core.drawTip("请等待当前事件的处理结束"); + + core.lockControl(); + core.status.event.id='toolbox'; + core.ui.drawToolbox(); +} + +control.prototype.equipboxReplay = function () { + if (!core.isPlaying() || !core.isReplaying()) return; + if (!core.status.replay.pausing) return core.drawTip("请先暂停录像"); + if (core.isMoving() || core.status.replay.animate || core.status.event.id) + return core.drawTip("请等待当前事件的处理结束"); + + core.lockControl(); + core.status.event.id='equipbox'; + core.ui.drawEquipbox(); +} + ////// 是否正在播放录像 ////// control.prototype.isReplaying = function () { return (core.status.replay||{}).replaying; @@ -1286,7 +1346,7 @@ control.prototype._replay_finished = function () { control.prototype._replay_save = function () { core.status.replay.steps++; - if (core.status.replay.steps%50==0) { + if (core.status.replay.steps%40==1) { if (core.status.replay.save.length == 30) core.status.replay.save.shift(); core.status.replay.save.push({"data": core.saveData(), "replay": { @@ -1325,6 +1385,7 @@ control.prototype._replay_error = function (action) { } control.prototype.__replay_getTimeout = function () { + if (core.status.replay.speed == 24) return 0; return 750 / Math.max(1, core.status.replay.speed); } @@ -1982,7 +2043,7 @@ control.prototype.unLockControl = function () { ////// 开启debug模式 ////// control.prototype.debug = function() { core.setFlag('debug', true); - core.drawText("\t[调试模式开启]此模式下按住Ctrl键(或Ctrl+Shift键)可以穿墙并忽略一切事件。\n同时,录像将失效,也无法上传成绩。"); + core.drawText("\t[调试模式开启]此模式下按住Ctrl键(或Ctrl+Shift键)可以穿墙并忽略一切事件。\n此模式下将无法上传成绩。"); } // ------ 天气,色调,BGM ------ // @@ -2309,6 +2370,7 @@ control.prototype._updateStatusBar_setToolboxIcon = function () { } control.prototype.showStatusBar = function () { + if (main.mode == 'editor') return; if (core.domStyle.showStatusBar) return; var statusItems = core.dom.status; core.domStyle.showStatusBar = true; @@ -2321,9 +2383,12 @@ control.prototype.showStatusBar = function () { } control.prototype.hideStatusBar = function (showToolbox) { + if (main.mode == 'editor') return; + // 如果原本就是隐藏的,则先显示 if (!core.domStyle.showStatusBar) this.showStatusBar(); + if (core.isReplaying()) showToolbox = true; var statusItems = core.dom.status, toolItems = core.dom.tools; core.domStyle.showStatusBar = false; @@ -2431,7 +2496,7 @@ control.prototype.setToolbarButton = function (useButton) { } if (useButton == null) useButton = core.domStyle.toolbarBtn; - if (!core.domStyle.isVertical || !core.platform.extendKeyboard) useButton = false; + if (!core.domStyle.isVertical || core.isReplaying()) useButton = false; core.domStyle.toolbarBtn = useButton; if (useButton) { @@ -2614,6 +2679,11 @@ control.prototype._resize_canvas = function (obj) { canvas.style.left = parseFloat(canvas.getAttribute("_left")) * core.domStyle.scale + "px"; canvas.style.top = parseFloat(canvas.getAttribute("_top")) * core.domStyle.scale + "px"; } + // resize next + main.dom.next.style.width = main.dom.next.style.height = 5 * core.domStyle.scale + "px"; + main.dom.next.style.borderBottomWidth = main.dom.next.style.borderRightWidth = 4 * core.domStyle.scale + "px"; + + } control.prototype._resize_statusBar = function (obj) { diff --git a/libs/core.js b/libs/core.js index be98ccfe..a9e571bc 100644 --- a/libs/core.js +++ b/libs/core.js @@ -72,7 +72,6 @@ function core() { 'isChrome': false, // 是否是Chrome 'supportCopy': false, // 是否支持复制到剪切板 'useLocalForage': true, - 'extendKeyboard': false, 'fileInput': null, // FileInput 'fileReader': null, // 是否支持FileReader @@ -278,14 +277,13 @@ core.prototype._init_platform = function () { } }); core.platform.string = core.platform.isPC ? "PC" : core.platform.isAndroid ? "Android" : core.platform.isIOS ? "iOS" : ""; - core.platform.supportCopy = document.queryCommandSupported || document.queryCommandSupported("copy"); + core.platform.supportCopy = document.queryCommandSupported && document.queryCommandSupported("copy"); var chrome = /Chrome\/(\d+)\./i.exec(navigator.userAgent); if (chrome && parseInt(chrome[1]) >= 50) core.platform.isChrome = true; core.platform.isSafari = /Safari/i.test(navigator.userAgent) && !/Chrome/i.test(navigator.userAgent); core.platform.isQQ = /QQ/i.test(navigator.userAgent); core.platform.isWeChat = /MicroMessenger/i.test(navigator.userAgent); this._init_checkLocalForage(); - core.platform.extendKeyboard = core.getLocalStorage("extendKeyboard", false); if (window.FileReader) { core.platform.fileReader = new FileReader(); core.platform.fileReader.onload = function () { diff --git a/libs/events.js b/libs/events.js index 8c72173f..4d786341 100644 --- a/libs/events.js +++ b/libs/events.js @@ -434,7 +434,7 @@ events.prototype._openDoor_animate = function (id, x, y, callback) { return; } core.drawImage('event', core.material.images.animates, 32 * state, 32 * door, 32, 32, 32 * x, 32 * y, 32, 32); - }, speed / Math.max(core.status.replay.speed, 1)); + }, core.status.replay.speed == 24 ? 1 : speed / Math.max(core.status.replay.speed, 1)); core.animateFrame.asyncId[animate] = true; } @@ -458,6 +458,24 @@ events.prototype.getItem = function (id, num, x, y, callback) { if (num > 1) text += "x" + num; if (itemCls === 'items') text += core.items.getItemEffectTip(id); core.drawTip(text, id); + + // --- 首次获得道具的提示 + if (!core.hasFlag("__itemHint__")) core.setFlag("__itemHint__", []); + var itemHint = core.getFlag("__itemHint__"); + if (core.flags.itemFirstText && itemHint.indexOf(id) < 0 && itemCls != 'items') { + var hint = core.material.items[id].text || "该道具暂无描述"; + try { + hint = core.replaceText(hint); + } catch (e) {} + core.insertAction("\t["+core.material.items[id].name+","+id+"]" + hint + "\n" + + (itemCls == 'keys' || id == 'greenKey' || id == 'steelKey' ? "(钥匙类道具,遇到对应的门时自动打开)" + : itemCls == 'tools' ? "(消耗类道具,请按T在道具栏使用)" + : itemCls == 'constants' ? "(永久类道具,请按T在道具栏使用)" + : itemCls == 'equips' ? "(装备类道具,请按Q在装备栏进行装备)" : "")) + itemHint.push(id); + } + + core.updateStatusBar(); this.afterGetItem(id, x, y, callback); @@ -510,6 +528,8 @@ events.prototype.changeFloor = function (floorId, stair, heroLoc, time, callback core.stopAutomaticRoute(); core.clearContinueAutomaticRoute(); core.status.replay.animate = true; + clearInterval(core.interval.onDownInterval); + core.interval.onDownInterval = 'tmp'; this._changeFloor_beforeChange(info, callback); } @@ -548,8 +568,19 @@ events.prototype._changeFloor_getHeroLoc = function (floorId, stair, heroLoc) { if (!heroLoc) heroLoc = core.clone(core.status.hero.loc); if (stair) { + // --- 对称 + if (stair == ':now') + heroLoc = core.clone(core.status.hero.loc); + else if (stair == ':symmetry') { + heroLoc.x = core.bigmap.width - 1 - core.getHeroLoc('x'); + heroLoc.y = core.bigmap.height - 1 - core.getHeroLoc('y'); + } + else if (stair == ':symmetry_x') + heroLoc.x = core.bigmap.width - 1 - core.getHeroLoc('x'); + else if (stair == ':symmetry_y') + heroLoc.y = core.bigmap.height - 1 - core.getHeroLoc('y'); // 检查该层地图的 upFloor & downFloor - if (core.status.maps[floorId][stair]) { + else if (core.status.maps[floorId][stair]) { heroLoc.x = core.status.maps[floorId][stair][0]; heroLoc.y = core.status.maps[floorId][stair][1]; } @@ -759,7 +790,7 @@ events.prototype.doEvent = function (data, x, y, prefix) { } if (this["_action_" + type]) return this["_action_" + type](data, x, y, prefix); core.insertAction("未知的自定义事件: " + type + "!"); - core.doAction(); + setTimeout(core.doAction); } events.prototype.setEvents = function (list, x, y, callback) { @@ -783,16 +814,18 @@ events.prototype.startEvents = function (list, x, y, callback) { // 停止勇士 core.waitHeroToStop(function () { core.lockControl(); - core.doAction(); + setTimeout(core.doAction); }); } ////// 执行当前自定义事件列表中的下一个事件 ////// -events.prototype.doAction = function () { - // 清空boxAnimate和UI层 - core.clearUI(); - clearInterval(core.status.event.interval); - core.status.event.interval = null; +events.prototype.doAction = function (keepUI) { + if (!keepUI) { + // 清空boxAnimate和UI层 + core.clearUI(); + clearInterval(core.status.event.interval); + core.status.event.interval = null; + } // 判定是否执行完毕 if (this._doAction_finishEvents()) return; // 当前点坐标和前缀 @@ -830,7 +863,7 @@ events.prototype._popEvents = function (current, prefix) { else { core.status.event.data.list.shift(); // remove stack } - core.doAction(); + setTimeout(core.doAction); return true; } return false; @@ -875,7 +908,7 @@ events.prototype.recoverEvents = function (data) { core.status.event.id = 'action'; core.status.event.data = data; setTimeout(function () { - core.doAction(); + setTimeout(core.doAction); }, 30); return true; } @@ -886,7 +919,7 @@ events.prototype.recoverEvents = function (data) { events.prototype.__action_checkReplaying = function () { if (core.isReplaying()) { - core.doAction(); + setTimeout(core.doAction); return true; } return false; @@ -914,7 +947,7 @@ events.prototype.__action_doAsyncFunc = function (isAsync, func) { var parameters = Array.prototype.slice.call(arguments, 2); if (isAsync) { func.apply(this, parameters); - core.doAction(); + setTimeout(core.doAction); } else { func.apply(this, parameters.concat(core.doAction)); @@ -938,7 +971,7 @@ events.prototype._action_scrollText = function (data, x, y, prefix) { } events.prototype._action_comment = function (data, x, y, prefix) { - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_setText = function (data, x, y, prefix) { @@ -959,12 +992,12 @@ events.prototype._action_setText = function (data, x, y, prefix) { } }); core.setFlag('textAttribute', core.status.textAttribute); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_tip = function (data, x, y, prefix) { core.drawTip(core.replaceText(data.text), data.icon); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_show = function (data, x, y, prefix) { @@ -976,7 +1009,7 @@ events.prototype._action_show = function (data, x, y, prefix) { data.loc.forEach(function (t) { core.showBlock(t[0], t[1], data.floorId); }); - core.doAction(); + setTimeout(core.doAction); } } @@ -992,14 +1025,16 @@ events.prototype._action_hide = function (data, x, y, prefix) { data.loc.forEach(function (t) { core.removeBlock(t[0], t[1], data.floorId) }); - core.doAction(); + setTimeout(core.doAction); } } events.prototype._action_setBlock = function (data, x, y, prefix) { - var loc = this.__action_getLoc(data.loc, x, y, prefix); - core.setBlock(data.number, loc[0], loc[1], data.floorId); - core.doAction(); + data.loc = this.__action_getLoc2D(data.loc, x, y, prefix); + data.loc.forEach(function (t) { + core.setBlock(data.number, t[0], t[1], data.floorId); + }); + setTimeout(core.doAction); } events.prototype._action_showFloorImg = function (data, x, y, prefix) { @@ -1019,19 +1054,21 @@ events.prototype._action_hideBgFgMap = function (data, x, y, prefix) { } events.prototype._action_setBgFgBlock = function (data, x, y, prefix) { - var loc = this.__action_getLoc(data.loc, x, y, prefix); - core.setBgFgBlock(data.name, data.number, loc[0], loc[1], data.floorId); - core.doAction(); + data.loc = this.__action_getLoc2D(data.loc, x, y, prefix); + data.loc.forEach(function (t) { + core.setBgFgBlock(data.name, data.number, t[0], t[1], data.floorId); + }); + setTimeout(core.doAction); } events.prototype._action_follow = function (data, x, y, prefix) { this.follow(data.name); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_unfollow = function (data, x, y, prefix) { this.unfollow(data.name); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_animate = function (data, x, y, prefix) { @@ -1040,6 +1077,21 @@ events.prototype._action_animate = function (data, x, y, prefix) { this.__action_doAsyncFunc(data.async, core.drawAnimate, data.name, data.loc[0], data.loc[1]); } +events.prototype._action_setViewport = function (data, x, y, prefix) { + if (data.loc == null) { + core.drawHero(); + } + else { + var loc = this.__action_getLoc(data.loc, x, y, prefix); + core.setViewport(32 * loc[0], 32 * loc[1]); + } + setTimeout(core.doAction); +} + +events.prototype._action_moveViewport = function (data, x, y, prefix) { + this.__action_doAsyncFunc(data.async, core.moveViewport, data.steps, data.time); +} + events.prototype._action_move = function (data, x, y, prefix) { var loc = this.__action_getLoc(data.loc, x, y, prefix); this.__action_doAsyncFunc(data.async, core.moveBlock, loc[0], loc[1], data.steps, data.time, data.keep); @@ -1073,7 +1125,7 @@ events.prototype._action_changePos = function (data, x, y, prefix) { core.setHeroLoc('y', loc[1]); if (data.direction) core.setHeroLoc('direction', data.direction); core.drawHero(); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_showImage = function (data, x, y, prefix) { @@ -1086,7 +1138,7 @@ events.prototype._action_showTextImage = function (data, x, y, prefix) { var loc = this.__action_getLoc(data.loc, 0, 0, prefix); if (core.isReplaying()) data.time = 0; this.__action_doAsyncFunc(data.async || data.time == 0, core.showImage, - data.code, core.ui.textImage(data.text), loc[0], loc[1], 100, 100, data.opacity, data.time); + data.code, core.ui.textImage(data.text), null, loc, data.opacity, data.time); } events.prototype._action_hideImage = function (data, x, y, prefix) { @@ -1097,7 +1149,7 @@ events.prototype._action_hideImage = function (data, x, y, prefix) { events.prototype._action_showGif = function (data, x, y, prefix) { var loc = this.__action_getLoc(data.loc, 0, 0, prefix); this.showGif(data.name, loc[0], loc[1]); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_moveImage = function (data, x, y, prefix) { @@ -1113,12 +1165,12 @@ events.prototype._action_setCurtain = function (data, x, y, prefix) { if (data.async) { core.setCurtain(data.color, data.time); core.setFlag('__color__', data.color || null); - core.doAction(); + setTimeout(core.doAction); } else { core.setCurtain(data.color, data.time, function () { core.setFlag('__color__', data.color || null); - core.doAction(); + setTimeout(core.doAction); }); } } @@ -1132,7 +1184,7 @@ events.prototype._action_setWeather = function (data, x, y, prefix) { if (data.name == 'rain' || data.name == 'snow' || data.name == 'fog') core.setFlag('__weather__', [data.name, data.level]); else core.removeFlag('__weather__'); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_openDoor = function (data, x, y, prefix) { @@ -1143,7 +1195,7 @@ events.prototype._action_openDoor = function (data, x, y, prefix) { } else { core.removeBlock(loc[0], loc[1], floorId); - core.doAction(); + setTimeout(core.doAction); } } @@ -1159,7 +1211,7 @@ events.prototype._action_useItem = function (data, x, y, prefix) { } else { core.drawTip("当前无法使用" + ((core.material.items[data.id] || {}).name || "未知道具")); - core.doAction(); + setTimeout(core.doAction); } } @@ -1169,12 +1221,12 @@ events.prototype._action_openShop = function (data, x, y, prefix) { if (!core.isReplaying()) this.openShop(data.id); if (core.status.event.id == 'action') - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_disableShop = function (data, x, y, prefix) { this.disableQuickShop(data.id); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_battle = function (data, x, y, prefix) { @@ -1200,7 +1252,7 @@ events.prototype._action_trigger = function (data, x, y, prefix) { return; } } - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_insert = function (data, x, y, prefix) { @@ -1225,43 +1277,44 @@ events.prototype._action_insert = function (data, x, y, prefix) { var event = (core.floors[floorId][which]||[])[loc[0] + "," + loc[1]]; if (event) this.insertAction(event.data || event); } - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_playBgm = function (data, x, y, prefix) { core.playBgm(data.name); - core.doAction(); + core.setFlag("__bgm__", data.keep ? data.name : null); + setTimeout(core.doAction); } events.prototype._action_pauseBgm = function (data, x, y, prefix) { core.pauseBgm(); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_resumeBgm = function (data, x, y, prefix) { core.resumeBgm(); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_loadBgm = function (data, x, y, prefix) { core.loadBgm(data.name); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_freeBgm = function (data, x, y, prefix) { core.freeBgm(data.name); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_playSound = function (data, x, y, prefix) { if (data.stop) core.stopSound(); core.playSound(data.name); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_stopSound = function (data, x, y, prefix) { core.stopSound(); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_setVolume = function (data, x, y, prefix) { @@ -1272,7 +1325,7 @@ events.prototype._action_setVolume = function (data, x, y, prefix) { events.prototype._action_setValue = function (data, x, y, prefix) { this.setValue(data.name, data.value, prefix); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_setValue2 = function (data, x, y, prefix) { @@ -1281,32 +1334,32 @@ events.prototype._action_setValue2 = function (data, x, y, prefix) { events.prototype._action_addValue = function (data, x, y, prefix) { this.addValue(data.name, data.value, prefix); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_setFloor = function (data, x, y, prefix) { this.setFloorInfo(data.name, data.value, data.floorId, prefix); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_setGlobalAttribute = function (data, x, y, prefix) { this.setGlobalAttribute(data.name, data.value); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_setGlobalValue = function (data, x, y, prefix) { core.values[data.name] = data.value; - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_setGlobalFlag = function (data, x, y, prefix) { this.setGlobalFlag(data.name, data.value); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_setHeroIcon = function (data, x, y, prefix) { this.setHeroIcon(data.name); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_input = function (data, x, y, prefix) { @@ -1314,7 +1367,7 @@ events.prototype._action_input = function (data, x, y, prefix) { value = Math.abs(parseInt(value) || 0); core.status.route.push("input:" + value); core.setFlag("input", value); - core.doAction(); + setTimeout(core.doAction); }); } @@ -1323,7 +1376,7 @@ events.prototype._action_input2 = function (data, x, y, prefix) { value = value || ""; core.status.route.push("input2:" + core.encodeBase64(value)); core.setFlag("input", value); - core.doAction(); + setTimeout(core.doAction); }); } @@ -1353,7 +1406,7 @@ events.prototype._action_if = function (data, x, y, prefix) { core.events.insertAction(data["true"]) else core.events.insertAction(data["false"]) - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_switch = function (data, x, y, prefix) { @@ -1368,10 +1421,15 @@ events.prototype._action_switch = function (data, x, y, prefix) { } } core.insertAction(list); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_choices = function (data, x, y, prefix) { + data.choices = data.choices.filter(function (x) { + if (x.condition == null || x.condition == '') return true; + try { return core.calValue(x.condition, prefix); } catch (e) { return true; } + }) + if (data.choices.length == 0) return this.doAction(); if (core.isReplaying()) { var action = core.status.replay.toReplay.shift(), index; // --- 忽略可能的turn事件 @@ -1381,8 +1439,8 @@ events.prototype._action_choices = function (data, x, y, prefix) { setTimeout(function () { core.status.route.push("choices:" + index); core.insertAction(data.choices[index].action); - core.doAction(); - }, 750 / Math.max(1, core.status.replay.speed)) + setTimeout(core.doAction); + }, core.status.replay.speed == 24 ? 1 : 750 / Math.max(1, core.status.replay.speed)) } else { core.control._replay_error(action); @@ -1404,8 +1462,8 @@ events.prototype._action_confirm = function (data, x, y, prefix) { core.status.route.push("choices:" + index); if (index == 0) core.insertAction(data.yes); else core.insertAction(data.no); - core.doAction(); - }, 750 / Math.max(1, core.status.replay.speed)) + setTimeout(core.doAction); + }, core.status.replay.speed == 24 ? 1 : 750 / Math.max(1, core.status.replay.speed)) } else { core.control._replay_error(action); @@ -1424,19 +1482,19 @@ events.prototype._action_while = function (data, x, y, prefix) { {"todo": core.clone(data.data), "total": core.clone(data.data), "condition": data.condition} ); } - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_dowhile = function (data, x, y, prefix) { core.unshift(core.status.event.data.list, {"todo": core.clone(data.data), "total": core.clone(data.data), "condition": data.condition} ); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_break = function (data, x, y, prefix) { core.status.event.data.list.shift(); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_continue = function (data, x, y, prefix) { @@ -1446,7 +1504,7 @@ events.prototype._action_continue = function (data, x, y, prefix) { else { core.status.event.data.list.shift(); } - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_win = function (data, x, y, prefix) { @@ -1471,28 +1529,40 @@ events.prototype._action_function = function (data, x, y, prefix) { main.log(e); } if (!data.async) - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_update = function (data, x, y, prefix) { core.updateStatusBar(); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_showStatusBar = function (data, x, y, prefix) { core.showStatusBar(); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_hideStatusBar = function (data, x, y, prefix) { core.hideStatusBar(data.toolbox); - core.doAction(); + setTimeout(core.doAction); +} + +events.prototype._action_showHero = function (data, x, y, prefix) { + core.removeFlag('hideHero'); + core.drawHero(); + setTimeout(core.doAction); +} + +events.prototype._action_hideHero = function (data, x, y, prefix) { + core.setFlag('hideHero', true); + core.drawHero(); + setTimeout(core.doAction); } events.prototype._action_updateEnemys = function (data, x, y, prefix) { core.enemys.updateEnemys(); core.updateStatusBar(); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_vibrate = function (data, x, y, prefix) { @@ -1502,7 +1572,7 @@ events.prototype._action_vibrate = function (data, x, y, prefix) { events.prototype._action_sleep = function (data, x, y, prefix) { core.timeout.sleepTimeout = setTimeout(function () { core.timeout.sleepTimeout = null; - core.doAction(); + setTimeout(core.doAction); }, core.isReplaying() ? Math.min(data.time, 20) : data.time); } @@ -1519,7 +1589,7 @@ events.prototype._action_wait = function (data, x, y, prefix) { core.stopReplay(); core.insertAction(["录像文件出错,请在控制台查看报错信息。", {"type": "exit"}]); } - core.doAction(); + setTimeout(core.doAction); return; } } @@ -1551,7 +1621,7 @@ events.prototype._action_waitAsync = function (data, x, y, prefix) { var test = window.setInterval(function () { if (!core.hasAsync()) { clearInterval(test); - core.doAction(); + setTimeout(core.doAction); } }, 50); } @@ -1560,12 +1630,12 @@ events.prototype._action_revisit = function (data, x, y, prefix) { var block = core.getBlock(x, y); if (block != null && block.block.event.trigger == 'action') this.setEvents(block.block.event.data); - core.doAction(); + setTimeout(core.doAction); } events.prototype._action_callBook = function (data, x, y, prefix) { if (core.isReplaying() || !core.hasItem('book')) { - core.doAction(); + setTimeout(core.doAction); } else { var e = core.clone(core.status.event.data); @@ -1578,7 +1648,7 @@ events.prototype._action_callBook = function (data, x, y, prefix) { events.prototype._action_callSave = function (data, x, y, prefix) { if (core.isReplaying() || core.hasFlag("__events__")) { core.removeFlag("__events__"); - core.doAction(); + setTimeout(core.doAction); } else { var e = core.clone(core.status.event.data); @@ -1590,8 +1660,8 @@ events.prototype._action_callSave = function (data, x, y, prefix) { events.prototype._action_autoSave = function (data, x, y, prefix) { core.autosave(); - core.drawTip("已自动存档"); - core.doAction(); + if (!data.nohint) core.drawTip("已自动存档"); + setTimeout(core.doAction); } events.prototype._action_callLoad = function (data, x, y, prefix) { @@ -1604,7 +1674,97 @@ events.prototype._action_callLoad = function (data, x, y, prefix) { events.prototype._action_exit = function (data, x, y, prefix) { this.setEvents([]); - core.doAction(); + setTimeout(core.doAction); +} + +events.prototype._action_previewUI = function (data, x, y, prefix) { + this.insertAction(data.action); + setTimeout(core.doAction); +} + +events.prototype._action_clearMap = function (data, x, y, prefix) { + core.ui._uievent_clearMap(data); + setTimeout(core.doAction); +} + +events.prototype._action_fillText = function (data, x, y, prefix) { + core.ui._uievent_fillText(data); + setTimeout(core.doAction); +} + +events.prototype._action_fillBoldText = function (data, x, y, prefix) { + core.ui._uievent_fillBoldText(data); + setTimeout(core.doAction); +} + +events.prototype._action_fillRect = function (data, x, y, prefix) { + core.ui._uievent_fillRect(data); + setTimeout(core.doAction); +} + +events.prototype._action_fillPolygon = function (data, x, y, prefix) { + core.ui._uievent_fillPolygon(data); + setTimeout(core.doAction); +} + +events.prototype._action_strokeRect = function (data, x, y, prefix) { + core.ui._uievent_strokeRect(data); + setTimeout(core.doAction); +} + +events.prototype._action_strokePolygon = function (data, x, y, prefix) { + core.ui._uievent_strokePolygon(data); + setTimeout(core.doAction); +} + +events.prototype._action_fillCircle = function (data, x, y, prefix) { + core.ui._uievent_fillCircle(data); + setTimeout(core.doAction); +} + +events.prototype._action_strokeCircle = function (data, x, y, prefix) { + core.ui._uievent_strokeCircle(data); + setTimeout(core.doAction); +} + +events.prototype._action_drawLine = function (data, x, y, prefix) { + core.ui._uievent_drawLine(data); + setTimeout(core.doAction); +} + +events.prototype._action_drawArrow = function (data, x, y, prefix) { + core.ui._uievent_drawArrow(data); + setTimeout(core.doAction); +} + +events.prototype._action_setAttribute = function (data, x, y, prefix) { + core.ui._uievent_setAttribute(data); + setTimeout(core.doAction); +} + +events.prototype._action_drawImage = function (data, x, y, prefix) { + core.ui._uievent_drawImage(data); + setTimeout(core.doAction); +} + +events.prototype._action_drawIcon = function (data, x, y, prefix) { + core.ui._uievent_drawIcon(data); + setTimeout(core.doAction); +} + +events.prototype._action_drawSelector = function (data, x, y, prefix) { + core.ui._uievent_drawSelector(data); + setTimeout(core.doAction); +} + +events.prototype._action_drawBackground = function (data, x, y, prefix) { + core.ui._uievent_drawBackground(data); + setTimeout(core.doAction); +} + +events.prototype._action_drawTextContent = function (data, x, y, prefix) { + core.ui._uievent_drawTextContent(data); + setTimeout(core.doAction); } // ------ 点击状态栏图标所进行的一些操作 ------ // @@ -1693,6 +1853,25 @@ events.prototype.openToolbox = function (fromUserAction) { ////// 点击快捷商店按钮时的打开操作 ////// events.prototype.openQuickShop = function (fromUserAction) { if (core.isReplaying()) return; + + if (Object.keys(core.status.shops).length == 0) { + core.drawTip("本塔没有快捷商店!"); + return; + } + + // --- 如果只有一个商店,则直接打开之 + if (Object.keys(core.status.shops).length == 1) { + var shopId = Object.keys(core.status.shops)[0]; + if (core.status.event.id != null || !this._checkStatus('shop', false)) return; + var reason = core.events.canUseQuickShop(shopId); + if (!core.flags.enableDisabledShop && reason) { + core.drawText(reason); + return; + } + core.events.openShop(shopId, true); + return; + } + if (!this._checkStatus('selectShop', fromUserAction)) return; core.ui.drawQuickShop(); } @@ -1842,7 +2021,7 @@ events.prototype.doEffect = function (effect, need, times) { ////// 设置楼层属性 ////// events.prototype.setFloorInfo = function (name, value, floorId, prefix) { - floorId = floorId || data.floorId; + floorId = floorId || core.status.floorId; core.status.maps[floorId][name] = core.calValue(value, prefix); core.updateStatusBar(); } @@ -1869,12 +2048,14 @@ events.prototype.setGlobalFlag = function (name, value) { core.flags[name] = value; core.setFlag("globalFlags", flags); core.resize(); + if (name == 'blurFg') + core.drawMap(); } events.prototype.closeDoor = function (x, y, id, callback) { id = id || ""; if (!(id.endsWith("Door") || id.endsWith("Wall")) - || !core.material.icons.animates[id] || core.getBlock(x, y) != null) { + || core.material.icons.animates[id] == null || core.getBlock(x, y) != null) { if (callback) callback(); return; } @@ -1893,7 +2074,7 @@ events.prototype.closeDoor = function (x, y, id, callback) { } core.clearMap('event', 32 * x, 32 * y, 32, 32); core.drawImage('event', core.material.images.animates, 32 * (4-state), 32 * door, 32, 32, 32 * x, 32 * y, 32, 32); - }, speed / Math.max(core.status.replay.speed, 1)); + }, core.status.replay.speed == 24 ? 1 : speed / Math.max(core.status.replay.speed, 1)); core.animateFrame.asyncId[animate] = true; } @@ -2101,7 +2282,7 @@ events.prototype.eventMoveHero = function(steps, time, callback) { if (core.events._eventMoveHero_moving(++step, moveSteps)) step = 0; } - }, time / 8 / core.status.replay.speed); + }, core.status.replay.speed == 24 ? 1 : time / 8 / core.status.replay.speed); core.animateFrame.asyncId[animate] = true; } @@ -2185,6 +2366,7 @@ events.prototype.openShop = function (shopId, needVisited) { if (!core.flags.enableDisabledShop || shop.commonEvent) { if (shop.times == 0) core.drawTip("该项尚未开启"); else core.drawTip("该项已失效"); + core.ui.closePanel(); return; } else { diff --git a/libs/items.js b/libs/items.js index 13030de5..b4770490 100644 --- a/libs/items.js +++ b/libs/items.js @@ -125,10 +125,8 @@ items.prototype._afterUseItem = function (itemId) { if (core.status.hero.items[itemCls][itemId] <= 0) delete core.status.hero.items[itemCls][itemId]; - if (!core.status.event.id) { - core.status.event.data = null; + if (!core.status.event.id) core.status.event.ui = null; - } core.updateStatusBar(); } @@ -354,7 +352,7 @@ items.prototype._realLoadEquip = function (type, loadId, unloadId, callback) { } // --- 音效 - core.playSound('equip.mp3'); + this._realLoadEquip_playSound(); // --- 实际换装 this._loadEquipEffect(loadId, unloadId, loadPercentage == null ? unloadPercentage : loadPercentage); @@ -371,6 +369,12 @@ items.prototype._realLoadEquip = function (type, loadId, unloadId, callback) { if (callback) callback(); } +items.prototype._realLoadEquip_playSound = function () { + if (core.hasFlag("__quickLoadEquip__")) return; + core.stopSound(); + core.playSound('equip.mp3'); +} + ////// 保存装备 ////// items.prototype.quickSaveEquip = function (index) { var saveEquips = core.getFlag("saveEquips", []); @@ -393,20 +397,30 @@ items.prototype.quickLoadEquip = function (index) { if (v && !this.canEquip(v, true)) return; } + core.setFlag("__quickLoadEquip__", true); // 快速换装 + var toEquip = []; for (var i = 0; i < equipSize; i++) { var now = core.status.hero.equipment[i]; - if (now) { - this.unloadEquip(i); - core.status.route.push("unEquip:" + i); + // --- 只考虑diff的装备 + var to = current[i]; + if (now != to) { + toEquip.push(to || null); + if (now) { + this.unloadEquip(i); + core.status.route.push("unEquip:" + i); + } } } - for (var i = 0; i < equipSize; i++) { - var to = current[i]; + for (var i in toEquip) { + var to = toEquip[i]; if (to) { this.loadEquip(to); core.status.route.push("equip:" + to); } } + core.removeFlag("__quickLoadEquip__"); + this._realLoadEquip_playSound(); + core.drawTip("成功换上" + index + "号套装"); } diff --git a/libs/maps.js b/libs/maps.js index fe9fd6bf..e700f469 100644 --- a/libs/maps.js +++ b/libs/maps.js @@ -62,6 +62,12 @@ maps.prototype._mapIntoBlocks = function (map, floor, floorId) { ////// 从ID获得数字 ////// maps.prototype.getNumberById = function (id) { + core.status.id2number = core.status.id2number || {}; + if (core.status.id2number[id] != null) return core.status.id2number[id]; + return core.status.id2number[id] = this._getNumberById(id); +} + +maps.prototype._getNumberById = function (id) { for (var number in this.blocksInfo) { if ((this.blocksInfo[number] || {}).id == id) return parseInt(number) || 0; @@ -76,6 +82,12 @@ maps.prototype.getNumberById = function (id) { return 0; } +maps.prototype.getBlockByNumber = function (number) { + core.status.number2Block = core.status.number2Block || {}; + if (core.status.number2Block[number] != null) return core.status.number2Block[number]; + return core.status.number2Block[number] = this.initBlock(null, null, number, true); +} + ////// 数字和ID的对应关系 ////// maps.prototype.initBlock = function (x, y, id, addInfo, eventFloor) { var disable = null; @@ -357,7 +369,8 @@ maps.prototype._getBgFgMapArray = function (name, floorId, noCache) { return core.status[name + "maps"][floorId]; var arr = core.clone(core.floors[floorId][name + "map"] || []); - if (main.mode == 'editor') arr = core.clone(editor[name + "map"]) || arr; + if (main.mode == 'editor' && !(uievent && uievent.isOpen)) + arr = core.clone(editor[name + "map"]) || arr; for (var x = 0; x < width; x++) { for (var y = 0; y < height; y++) { arr[y] = arr[y] || []; @@ -474,19 +487,44 @@ maps.prototype._canMoveHero_checkCannotInOut = function (number, name, direction } return false; } - return core.inArray((this.initBlock(0, 0, number).event || {})[name], direction); + return core.inArray((this.getBlockByNumber(number).event || {})[name], direction); } ////// 能否瞬间移动 ////// maps.prototype.canMoveDirectly = function (destX, destY) { - if (!this._canMoveDirectly_checkGlobal()) return -1; + return this.canMoveDirectlyArray([[destX,destY]])[0]; +} + +maps.prototype.canMoveDirectlyArray = function (locs) { + var ans = [], number = locs.length; var fromX = core.getHeroLoc('x'), fromY = core.getHeroLoc('y'); - if (fromX == destX && fromY == destY) return 0; - // 检查起点事件 - if (!this._canMoveDirectly_checkStartPoint(fromX, fromY)) return -1; + if (!this._canMoveDirectly_checkGlobal()) { + for (var i = 0; i < number; ++i) ans.push(-1); + return ans; + } + for (var i = 0; i < number; ++i) { + if (locs[i][0] == fromX && locs[i][1] == fromY) { + ans.push(0); + number--; + } + else if (locs[i][0] < 0 || locs[i][0] >= core.bigmap.width || locs[i][1] < 0 || locs[i][1] >= core.bigmap.height) { + ans.push(-1); + number--; + } + else ans.push(null); + } + if (number == 0) return ans; - return this._canMoveDirectly_bfs(fromX, fromY, destX, destY); + // 检查起点事件 + if (!this._canMoveDirectly_checkStartPoint(fromX, fromY)) { + for (var i in ans) { + if (ans[i] == null) ans[i] = -1; + } + return ans; + } + + return this._canMoveDirectly_bfs(fromX, fromY, locs, number, ans); } maps.prototype._canMoveDirectly_checkGlobal = function () { @@ -512,7 +550,7 @@ maps.prototype._canMoveDirectly_checkStartPoint = function (sx, sy) { return true; } -maps.prototype._canMoveDirectly_bfs = function (sx, sy, ex, ey) { +maps.prototype._canMoveDirectly_bfs = function (sx, sy, locs, number, ans) { var canMoveArray = this.generateMovableArray(); var blocksObj = this.getMapBlocksObj(core.status.floorId); // 滑冰 @@ -531,12 +569,22 @@ maps.prototype._canMoveDirectly_bfs = function (sx, sy, ex, ey) { if (bgMap[ny][nx] == 167) continue; if (!this._canMoveDirectly_checkNextPoint(blocksObj, nx, ny)) continue; visited[nindex] = visited[now] + 1; - if (nx == ex && ny == ey) return visited[nindex]; + // if (nx == ex && ny == ey) return visited[nindex]; + for (var i in ans) { + if (locs[i][0] == nx && locs[i][1] == ny && ans[i] == null) { + ans[i] = visited[nindex]; + number--; + if (number == 0) return ans; + } + } queue.push(nindex); } } - return -1; + for (var i in ans) { + if (ans[i] == null) ans[i] = -1; + } + return ans; } maps.prototype._canMoveDirectly_checkNextPoint = function (blocksObj, x, y) { @@ -732,6 +780,7 @@ maps.prototype.drawBg = function (floorId, ctx) { if (onMap) { ctx = core.canvas.bg; core.clearMap(ctx); + core.status.floorAnimateObjs = this._getFloorImages(floorId); } core.maps._drawBg_drawBackground(floorId, ctx); // ------ 调整这两行的顺序来控制是先绘制贴图还是先绘制背景图块;后绘制的覆盖先绘制的。 @@ -771,7 +820,10 @@ maps.prototype.drawEvents = function (floorId, blocks, ctx) { maps.prototype.drawFg = function (floorId, ctx) { floorId = floorId || core.status.floorId; var onMap = ctx == null; - if (onMap) ctx = core.canvas.fg; + if (onMap) { + ctx = core.canvas.fg; + core.status.floorAnimateObjs = this._getFloorImages(floorId); + } // ------ 调整这两行的顺序来控制是先绘制贴图还是先绘制背景图块;后绘制的覆盖先绘制的。 this._drawFloorImages(floorId, ctx, 'fg'); this._drawBgFgMap(floorId, ctx, 'fg', onMap); @@ -789,7 +841,7 @@ maps.prototype._drawBgFgMap = function (floorId, ctx, name, onMap) { var arr = this._getBgFgMapArray(name, floorId, true); var eventArr = null; - if (main.mode == 'editor' && name == 'fg' && onMap) { + if (name == 'fg' && onMap && this._drawBgFgMap_shouldBlurFg()) { eventArr = this.getMapArray(floorId); } @@ -814,12 +866,16 @@ maps.prototype._drawBgFgMap = function (floorId, ctx, name, onMap) { core.status.autotileAnimateObjs[name + "map"] = core.clone(arr); } +////// 是否应当存在事件时虚化前景层 ////// +maps.prototype._drawBgFgMap_shouldBlurFg = function () { + return main.mode == 'editor' || core.flags.blurFg; +} + ////// 绘制楼层贴图 ////// maps.prototype._drawFloorImages = function (floorId, ctx, name, images, currStatus) { floorId = floorId || core.status.floorId; if (!images) images = this._getFloorImages(floorId); var redraw = currStatus != null; - if (!redraw) core.status.floorAnimateObjs = core.clone(images); images.forEach(function (t) { if (typeof t == 'string') t = [0, 0, t]; var dx = parseInt(t[0]), dy = parseInt(t[1]), imageName = t[2], frame = core.clamp(parseInt(t[4]), 1, 8); @@ -893,55 +949,118 @@ maps.prototype._drawFloorImage = function (ctx, name, type, image, offsetX, widt } ////// 绘制Autotile ////// + + maps.prototype._drawAutotile = function (ctx, mapArr, block, size, left, top, status) { - var indexArrs = [ //16种组合的图块索引数组; // 将autotile分割成48块16*16的小块; 数组索引即对应各个小块 - // +----+----+----+----+----+----+ - [10, 9, 4, 3], //0 bin:0000 | 1 | 2 | 3 | 4 | 5 | 6 | - [10, 9, 4, 13], //1 bin:0001 +----+----+----+----+----+----+ - [10, 9, 18, 3], //2 bin:0010 | 7 | 8 | 9 | 10 | 11 | 12 | - [10, 9, 16, 15], //3 bin:0011 +----+----+----+----+----+----+ - [10, 43, 4, 3], //4 bin:0100 | 13 | 14 | 15 | 16 | 17 | 18 | - [10, 31, 4, 25], //5 bin:0101 +----+----+----+----+----+----+ - [10, 7, 2, 3], //6 bin:0110 | 19 | 20 | 21 | 22 | 23 | 24 | - [10, 31, 16, 5], //7 bin:0111 +----+----+----+----+----+----+ - [48, 9, 4, 3], //8 bin:1000 | 25 | 26 | 27 | 28 | 29 | 30 | - [8, 9, 4, 1], //9 bin:1001 +----+----+----+----+----+----+ - [36, 9, 30, 3], //10 bin:1010 | 31 | 32 | 33 | 34 | 35 | 36 | - [36, 9, 6, 15], //11 bin:1011 +----+----+----+----+----+----+ - [46, 45, 4, 3], //12 bin:1100 | 37 | 38 | 39 | 40 | 41 | 42 | - [46, 11, 4, 25], //13 bin:1101 +----+----+----+----+----+----+ - [12, 45, 30, 3], //14 bin:1110 | 43 | 44 | 45 | 46 | 47 | 48 | - [34, 33, 28, 27] //15 bin:1111 +----+----+----+----+----+----+ + var xx = block.x, yy = block.y; + var autotile = core.material.images['autotile'][block.event.id]; + status = status || 0; + status %= parseInt(autotile.width / 96); + var done = {}; + var isGrass = function(x,y){ + if(core.maps._drawAutotile_getAutotileAroundId(mapArr[yy][xx],x,y,mapArr)){ + return 1; + }else{ + return 0; + } + } + var iG = []; + [-1,0,1].forEach(function(_x){ + iG[_x] = []; + [-1,0,1].forEach(function(_y){ + iG[_x][_y] = isGrass(xx + _x, yy + _y); + })}); + if(iG[-1][-1] + iG[0][-1] + iG[0][0] + iG[-1][0] == 3 && !iG[-1][-1]){ + this._drawAutotile_render(ctx, xx * size + left, yy * size + top, size, autotile, status, 16); + done[0] = true; + } + if(iG[0][-1] + iG[1][-1] + iG[1][0] + iG[0][0] == 3 && !iG[1][-1]){ + this._drawAutotile_render(ctx, xx * size + left + size/2, yy * size + top, size, autotile, status, 17); + done[1] = true; + } + if(iG[0][0] + iG[1][0] + iG[1][1] + iG[0][1] == 3 && !iG[1][1]){ + this._drawAutotile_render(ctx, xx * size + left+size/2, yy * size + top + size/2, size, autotile, status, 18); + done[3] = true; + } + if(iG[0-1][0] + iG[0][0] + iG[0][1] + iG[-1][1] == 3 && !iG[-1][1]){ + this._drawAutotile_render(ctx, xx * size + left, yy * size + top + size/2, size, autotile, status, 19); + done[2] = true; + } + var _id = iG[0][-1] + 2 * iG[-1][0] + 4 * iG[0][1] + 8 * iG[1][0]; + this._drawAutotile_render(ctx, xx * size, yy * size, size, autotile, status, _id, done); +} + + +maps.prototype._drawAutotile_render = function(canvas, x, y, size, autotile, status, index, done) { + var indexData = [[[96 * status, 0, 32, 32, x, y, size, size],], + [[96 * status, 3 * 32, 16, 32, x, y, size / 2, size],[96 * status + 2 * 32 + 16, 3 * 32, 16, 32, x + size / 2, y, size / 2, size],], + [[96 * status + 2 * 32, 32, 32, 16, x, y, size, size / 2],[96 * status + 2 * 32, 3 * 32 + 16, 32, 16, x, y + size / 2, size, size / 2],], + [[96 * status + 2 * 32, 3 * 32, 32, 32, x, y, size, size],], + [[96 * status, 32, 16, 32, x, y, size / 2, size],[96 * status + 2 * 32 + 16, 32, 16, 32, x + size / 2, y, size / 2, size],], + [[96 * status, 2 * 32, 16, 32, x, y, size / 2, size],[96 * status + 2 * 32 + 16, 2 * 32, 16, 32, x + size / 2, y, size / 2, size],], + [[96 * status + 2 * 32, 32, 32, 32, x, y, size, size],], + [[96 * status + 2 * 32, 2 * 32, 32, 32, x, y, size, size],], + [[96 * status, 32, 32, 16, x, y, size, size / 2],[96 * status, 3 * 32 + 16, 32, 16, x, y + size / 2, size, size / 2],], + [[96 * status, 3 * 32, 32, 32, x, y, size, size],], + [[96 * status + 32, 32, 32, 16, x, y, size, size / 2],[96 * status + 32, 3 * 32 + 16, 32, 16, x, y + size / 2, size, size / 2],], + [[96 * status + 32, 3 * 32, 32, 32, x, y, size, size],], + [[96 * status, 32, 32, 32, x, y, size, size],], + [[96 * status, 2 * 32, 32, 32, x, y, size, size],], + [[96 * status + 32, 32, 32, 32, x, y, size, size],], + [[96 * status + 32, 2 * 32, 32, 32, x, y, size, size],], + [[96 * status + 2 * 32, 0, 16, 16, x, y, size / 2, size / 2],], + [[96 * status + 2 * 32 + 16, 0, 16, 16, x, y, size / 2, size / 2],], + [[96 * status + 2 * 32 + 16, 16, 16, 16, x, y, size / 2, size / 2],], + [[96 * status + 2 * 32, 16, 16, 16, x, y, size / 2, size / 2],], ]; - - // 开始绘制autotile - var x = block.x, y = block.y; - var pieceIndexs = this._drawAutotile_getAutotileIndexs(x, y, mapArr, indexArrs); - - //修正四个边角的固定搭配 - if (pieceIndexs[0] == 13) { - if (pieceIndexs[1] == 16) pieceIndexs[1] = 14; - if (pieceIndexs[2] == 31) pieceIndexs[2] = 19; - } - if (pieceIndexs[1] == 18) { - if (pieceIndexs[0] == 15) pieceIndexs[0] = 17; - if (pieceIndexs[3] == 36) pieceIndexs[3] = 24; - } - if (pieceIndexs[2] == 43) { - if (pieceIndexs[0] == 25) pieceIndexs[0] = 37; - if (pieceIndexs[3] == 46) pieceIndexs[3] = 44; - } - if (pieceIndexs[3] == 48) { - if (pieceIndexs[1] == 30) pieceIndexs[1] = 42; - if (pieceIndexs[2] == 45) pieceIndexs[2] = 47; - } - for (var i = 0; i < 4; i++) { - var index = pieceIndexs[i]; - var dx = x * size + size / 2 * (i % 2), dy = y * size + size / 2 * (~~(i / 2)); - this._drawAutotile_drawBlockByIndex(ctx, dx + left, dy + top, core.material.images['autotile'][block.event.id], index, size, status); + var data = indexData[index]; + if(index>=16){ // 拐角直接绘制 + canvas.drawImage(autotile, data[0][0], data[0][1], data[0][2], data[0][3], data[0][4], data[0][5], size/2, size/2); + }else{ // 非拐角要根据是否已经绘制进行切分后绘制 + this._drawAutotile_renderCut(canvas, autotile, x, y, size, data, done); } } +maps.prototype._drawAutotile_renderCut = function(canvas, autotile, x, y, size, data, done){ + var drawData = []; + done = done || {}; + if(data.length == 2){ + var idx = 0; + var cut = 0; + for(var i in data){ + if(data[i][2] % 32){ // 是否纵切 + cut = 0; + } + else if(data[i][3] % 32){ // 是否横切 + cut = 1; + } + if(data[i][0] % 32 || data[i][1] % 32){ // right down + idx = 1; + }else{ // left top + idx = 0; + } + if(cut){ + idx *= 2; + if(!done[idx])drawData[idx] = [data[i][0], data[i][1]]; + if(!done[idx + 1])drawData[idx + 1] = [parseInt(data[i][0]) + 16, data[i][1]]; + }else{ + if(!done[idx])drawData[idx] = [data[i][0], data[i][1]]; + if(!done[idx + 2])drawData[idx + 2] = [data[i][0], parseInt(data[i][1]) + 16]; + } + } + }else{ + if(!done[0])drawData[0] = [data[0][0], data[0][1]]; + if(!done[1])drawData[1] = [data[0][0] + 16, data[0][1]]; + if(!done[2])drawData[2] = [data[0][0], data[0][1] + 16]; + if(!done[3])drawData[3] = [data[0][0] + 16, data[0][1] + 16]; + } + for(var i = 0; i<4; i++){ + var dt = drawData[i];if(!dt)continue; + canvas.drawImage(autotile, dt[0], dt[1], 16, 16, x + (i % 2) * size / 2, y + parseInt(i / 2) * size / 2, size/2, size/2); + }; +} + + maps.prototype._drawAutotile_drawBlockByIndex = function (ctx, dx, dy, autotileImg, index, size, status) { //index为autotile的图块索引1-48 var sx = 16 * ((index - 1) % 6), sy = 16 * (~~((index - 1) / 6)); @@ -1163,9 +1282,12 @@ maps.prototype.terrainExists = function (x, y, id, floorId) { ////// 某个点是否存在楼梯 ////// maps.prototype.stairExists = function (x, y, floorId) { - var block = this.getBlock(x, y, floorId); - if (block == null) return false; - return block.block.event.cls == 'terrains' && (block.block.event.id == 'upFloor' || block.block.event.id == 'downFloor'); + var blockId = this.getBlockId(x, y, floorId); + if (blockId == null) return false; + var ids = ['upFloor','downFloor']; + if (core.flags.flyRecordPosition) + ids = ids.concat(['leftPortal','rightPortal','upPortal','downPortal']); + return ids.indexOf(blockId)>=0; } ////// 当前位置是否在楼梯边 ////// @@ -1215,9 +1337,9 @@ maps.prototype.getBlockInfo = function (block) { } if (typeof block == 'number') { // 参数是数字 if (block == 0) return null; - block = this.initBlock(0, 0, block, true); + block = this.getBlockByNumber(block); } - var number = block.id, id = block.event.id, cls = block.event.cls, + var number = block.id, id = block.event.id, cls = block.event.cls, name = block.event.name, image = null, posX = 0, posY = 0, animate = block.event.animate, height = block.event.height || 32, faceIds = {}; @@ -1225,6 +1347,7 @@ maps.prototype.getBlockInfo = function (block) { else if (id == 'airwall') { if (!core.material.images.airwall) return null; image = core.material.images.airwall; + name = "空气墙"; } else if (cls == 'tileset') { var offset = core.icons.getTilesetOffset(id); @@ -1240,14 +1363,17 @@ maps.prototype.getBlockInfo = function (block) { image = core.material.images[cls]; posY = core.material.icons[cls][id]; faceIds = block.event.faceIds || {}; + if (core.material.enemys[id]) { + name = core.material.enemys[id].name; + } } - return {number: number, id: id, cls: cls, image: image, posX: posX, posY: posY, height: height, faceIds: faceIds, animate: animate}; + return {number: number, id: id, cls: cls, name: name, image: image, posX: posX, posY: posY, height: height, faceIds: faceIds, animate: animate}; } ////// 搜索某个图块出现的所有位置 ////// maps.prototype.searchBlock = function (id, floorId, showDisable) { - if (typeof id == 'number') id = this.initBlock(0, 0, id).event.id; + if (typeof id == 'number') id = this.getBlockByNumber(id).event.id; floorId = floorId || core.status.floorId; var result = []; if (floorId instanceof Array) { @@ -1490,7 +1616,7 @@ maps.prototype.replaceBlock = function (fromNumber, toNumber, floorId) { }); return; } - var toBlock = this.initBlock(0, 0, toNumber, true); + var toBlock = this.getBlockByNumber(toNumber, true); core.status.maps[floorId].blocks.forEach(function (block) { if (block.id == fromNumber) { block.id = toNumber; diff --git a/libs/ui.js b/libs/ui.js index 6f990152..ae81e542 100644 --- a/libs/ui.js +++ b/libs/ui.js @@ -37,6 +37,13 @@ ui.prototype.getContextByName = function (name) { return null; } +ui.prototype._createUIEvent = function () { + if (main.mode == 'editor') return; + if (!core.dymCanvas['uievent']) { + core.createCanvas('uievent', 0, 0, this.PIXEL, this.PIXEL, 135); + } +} + ////// 清除地图 ////// ui.prototype.clearMap = function (name, x, y, width, height) { if (name == 'all') { @@ -52,12 +59,45 @@ ui.prototype.clearMap = function (name, x, y, width, height) { } } +ui.prototype._uievent_clearMap = function (data) { + if (main.mode != 'editor' && (data.x == null || data.y == null || data.width == null || data.height == null)) { + this.deleteCanvas('uievent'); + return; + } + this._createUIEvent(); + this.clearMap('uievent', core.calValue(data.x), core.calValue(data.y), core.calValue(data.width), core.calValue(data.height)); +} + ////// 在某个canvas上绘制一段文字 ////// -ui.prototype.fillText = function (name, text, x, y, style, font) { +ui.prototype.fillText = function (name, text, x, y, style, font, maxWidth) { if (style) core.setFillStyle(name, style); if (font) core.setFont(name, font); var ctx = this.getContextByName(name); - if (ctx) ctx.fillText(text, x, y); + if (ctx) { + // 如果存在最大宽度 + if (maxWidth != null) + this._fillTextWithMaxWidth(ctx, text, x, y, maxWidth); + else + ctx.fillText(text, x, y); + } +} + +ui.prototype._uievent_fillText = function (data) { + this._createUIEvent(); + this.fillText('uievent', core.replaceText(data.text), core.calValue(data.x), core.calValue(data.y), data.style, data.font, data.maxWidth); +} + +////// 自适配字体大小 +ui.prototype._fillTextWithMaxWidth = function (ctx, text, x, y, maxWidth) { + // 获得当前字体 + var font = ctx.font, u = /(\d+)px/.exec(font); + if (u == null) return ctx.fillText(text, x, y); + for (var font_size = parseInt(u[1]); font_size >= 8; font_size--) { + ctx.font = font.replace(/(\d+)px/, font_size+"px"); + if (ctx.measureText(text).width <= maxWidth) break; + } + ctx.fillText(text, x, y); + ctx.font = font; } ////// 在某个canvas上绘制粗体 ////// @@ -66,6 +106,7 @@ ui.prototype.fillBoldText = function (name, text, x, y, style, font) { if (!ctx) return; if (font) ctx.font = font; if (!style) style = ctx.fillStyle; + if (style instanceof Array) style = core.arrayToRGBA(style); ctx.fillStyle = '#000000'; ctx.fillText(text, x-1, y-1); ctx.fillText(text, x-1, y+1); @@ -75,6 +116,11 @@ ui.prototype.fillBoldText = function (name, text, x, y, style, font) { ctx.fillText(text, x, y); } +ui.prototype._uievent_fillBoldText = function (data) { + this._createUIEvent(); + this.fillBoldText('uievent', core.replaceText(data.text), core.calValue(data.x), core.calValue(data.y), data.style, data.font); +} + ////// 在某个canvas上绘制一个矩形 ////// ui.prototype.fillRect = function (name, x, y, width, height, style) { if (style) core.setFillStyle(name, style); @@ -82,6 +128,32 @@ ui.prototype.fillRect = function (name, x, y, width, height, style) { if (ctx) ctx.fillRect(x, y, width, height); } +ui.prototype._uievent_fillRect = function (data) { + this._createUIEvent(); + this.fillRect('uievent', core.calValue(data.x), core.calValue(data.y), core.calValue(data.width), core.calValue(data.height), data.style); +} + +////// 在某个canvas上绘制一个多边形 ////// +ui.prototype.fillPolygon = function (name, nodes, style) { + if (style) core.setFillStyle(name, style); + var ctx = this.getContextByName(name); + if (!ctx) return; + if (!nodes || nodes.length<3) return; + ctx.beginPath(); + for (var i = 0; i < nodes.length; ++i) { + var x = core.calValue(nodes[i][0]), y = core.calValue(nodes[i][1]); + if (i == 0) ctx.moveTo(x, y); + else ctx.lineTo(x, y); + } + ctx.closePath(); + ctx.fill(); +} + +ui.prototype._uievent_fillPolygon = function (data) { + this._createUIEvent(); + this.fillPolygon('uievent', data.nodes, data.style); +} + ////// 在某个canvas上绘制一个矩形的边框 ////// ui.prototype.strokeRect = function (name, x, y, width, height, style, lineWidth) { if (style) core.setStrokeStyle(name, style); @@ -90,6 +162,64 @@ ui.prototype.strokeRect = function (name, x, y, width, height, style, lineWidth) if (ctx) ctx.strokeRect(x, y, width, height); } +ui.prototype._uievent_strokeRect = function (data) { + this._createUIEvent(); + this.strokeRect('uievent', core.calValue(data.x), core.calValue(data.y), core.calValue(data.width), core.calValue(data.height), data.style, data.lineWidth); +} + +////// 在某个canvas上绘制一个多边形的边框 ////// +ui.prototype.strokePolygon = function (name, nodes, style, lineWidth) { + if (style) core.setStrokeStyle(name, style); + if (lineWidth) core.setLineWidth(name, lineWidth); + var ctx = this.getContextByName(name); + if (!ctx) return; + if (!nodes || nodes.length<3) return; + ctx.beginPath(); + for (var i = 0; i < nodes.length; ++i) { + var x = core.calValue(nodes[i][0]), y = core.calValue(nodes[i][1]); + if (i == 0) ctx.moveTo(x, y); + else ctx.lineTo(x, y); + } + ctx.closePath(); + ctx.stroke(); +} + +ui.prototype._uievent_strokePolygon = function (data) { + this._createUIEvent(); + this.strokePolygon('uievent', data.nodes, data.style, data.lineWidth); +} + +////// 在某个canvas上绘制一个圆 ////// +ui.prototype.fillCircle = function (name, x, y, r, style) { + if (style) core.setFillStyle(name, style); + var ctx = this.getContextByName(name); + if (!ctx) return; + ctx.beginPath(); + ctx.arc(x, y, r, 0, 2*Math.PI); + ctx.fill(); +} + +ui.prototype._uievent_fillCircle = function (data) { + this._createUIEvent(); + this.fillCircle('uievent', core.calValue(data.x), core.calValue(data.y), core.calValue(data.r), data.style); +} + +////// 在某个canvas上绘制一个圆的边框 ////// +ui.prototype.strokeCircle = function (name, x, y, r, style, lineWidth) { + if (style) core.setStrokeStyle(name, style); + if (lineWidth) core.setLineWidth(name, lineWidth); + var ctx = this.getContextByName(name); + if (!ctx) return; + ctx.beginPath(); + ctx.arc(x, y, r, 0, 2*Math.PI); + ctx.stroke(); +} + +ui.prototype._uievent_strokeCircle = function (data) { + this._createUIEvent(); + this.strokeCircle('uievent', core.calValue(data.x), core.calValue(data.y), core.calValue(data.r), data.style, data.lineWidth); +} + ////// 在某个canvas上绘制一条线 ////// ui.prototype.drawLine = function (name, x1, y1, x2, y2, style, lineWidth) { if (style) core.setStrokeStyle(name, style); @@ -102,6 +232,11 @@ ui.prototype.drawLine = function (name, x1, y1, x2, y2, style, lineWidth) { ctx.stroke(); } +ui.prototype._uievent_drawLine = function (data) { + this._createUIEvent(); + this.drawLine('uievent', core.calValue(data.x1), core.calValue(data.y1), core.calValue(data.x2), core.calValue(data.y2), data.style, data.lineWidth); +} + ////// 在某个canvas上绘制一个箭头 ////// ui.prototype.drawArrow = function (name, x1, y1, x2, y2, style, lineWidth) { if (x1==x2 && y1==y2) return; @@ -121,6 +256,11 @@ ui.prototype.drawArrow = function (name, x1, y1, x2, y2, style, lineWidth) { ctx.stroke(); } +ui.prototype._uievent_drawArrow = function (data) { + this._createUIEvent(); + this.drawArrow('uievent', core.calValue(data.x1), core.calValue(data.y1), core.calValue(data.x2), core.calValue(data.y2), data.style, data.lineWidth); +} + ////// 设置某个canvas的文字字体 ////// ui.prototype.setFont = function (name, font) { var ctx = this.getContextByName(name); @@ -160,12 +300,14 @@ ui.prototype.setOpacity = function (name, opacity) { ////// 设置某个canvas的绘制属性(如颜色等) ////// ui.prototype.setFillStyle = function (name, style) { var ctx = this.getContextByName(name); + if (style instanceof Array) style = core.arrayToRGBA(style); if (ctx) ctx.fillStyle = style; } ////// 设置某个canvas边框属性 ////// ui.prototype.setStrokeStyle = function (name, style) { var ctx = this.getContextByName(name); + if (style instanceof Array) style = core.arrayToRGBA(style); if (ctx) ctx.strokeStyle = style; } @@ -181,6 +323,23 @@ ui.prototype.setTextBaseline = function (name, baseline) { if (ctx) ctx.textBaseline = baseline; } +ui.prototype._uievent_setAttribute = function (data) { + this._createUIEvent(); + if (data.font) this.setFont('uievent', data.font); + if (data.lineWidth) this.setLineWidth('uievent', data.lineWidth); + if (data.alpha != null) this.setAlpha('uievent', data.alpha); + if (data.fillStyle) this.setFillStyle('uievent', data.fillStyle); + if (data.strokeStyle) this.setStrokeStyle('uievent', data.strokeStyle); + if (data.align) this.setTextAlign('uievent', data.align); + if (data.baseline) this.setTextBaseline('uievent', data.baseline); + if (data.z != null && main.mode != 'editor') { + var z = parseInt(data.z) || 135; + core.dymCanvas.uievent.canvas.style.zIndex = z; + if (core.dymCanvas._uievent_selector) + core.dymCanvas._uievent_selector.canvas.style.zIndex = z + 1; + } +} + ////// 计算某段文字的宽度 ////// ui.prototype.calWidth = function (name, text, font) { var ctx = this.getContextByName(name); @@ -194,7 +353,7 @@ ui.prototype.calWidth = function (name, text, font) { ////// 字符串自动换行的分割 ////// ui.prototype.splitLines = function (name, text, maxWidth, font) { var ctx = this.getContextByName(name); - if (!ctx) return; + if (!ctx) return [text]; if (font) core.setFont(name, font); var contents = []; @@ -232,9 +391,9 @@ ui.prototype.drawImage = function (name, image, x, y, w, h, x1, y1, w1, h1) { } // 只能接受2, 4, 8个参数 - if (core.isset(x) && core.isset(y)) { - if (core.isset(w) && core.isset(h)) { - if (core.isset(x1) && core.isset(y1) && core.isset(w1) && core.isset(h1)) { + if (x != null && y != null) { + if (w != null && h != null) { + if (x1 != null && y1 != null && w1 != null && h1 != null) { ctx.drawImage(image, x, y, w, h, x1, y1, w1, h1); return; } @@ -246,6 +405,35 @@ ui.prototype.drawImage = function (name, image, x, y, w, h, x1, y1, w1, h1) { } } +ui.prototype._uievent_drawImage = function (data) { + this._createUIEvent(); + this.drawImage('uievent', data.image, core.calValue(data.x), core.calValue(data.y), core.calValue(data.w), core.calValue(data.h), + core.calValue(data.x1), core.calValue(data.y1), core.calValue(data.w1), core.calValue(data.h1)); +} + +ui.prototype.drawIcon = function (name, id, x, y, w, h) { + var ctx = this.getContextByName(name); + if (!ctx) return; + var info = core.getBlockInfo(id); + if (!info) { + // 检查状态栏图标 + if (core.statusBar.icons[id] instanceof Image) + info = {image: core.statusBar.icons[id], posX: 0, posY: 0, height: 32}; + else return; + } + ctx.drawImage(info.image, 32 * info.posX, info.height * info.posY, 32, info.height, x, y, w || 32, h || info.height); +} + +ui.prototype._uievent_drawIcon = function (data) { + this._createUIEvent(); + var id; + try { + id = core.calValue(data.id); + if (typeof id !== 'string') id = data.id; + } catch (e) { id = data.id; } + this.drawIcon('uievent', id, core.calValue(data.x), core.calValue(data.y), core.calValue(data.width), core.calValue(data.height)); +} + ///////////////// UI绘制 ////// 结束一切事件和绘制,关闭UI窗口,返回游戏进程 ////// @@ -264,6 +452,7 @@ ui.prototype.closePanel = function () { ui.prototype.clearUI = function () { core.status.boxAnimateObjs = []; if (core.dymCanvas._selector) core.deleteCanvas("_selector"); + main.dom.next.style.display = 'none'; core.clearMap('ui'); core.setAlpha('ui', 1); } @@ -351,7 +540,8 @@ ui.prototype.drawText = function (contents, callback) { ui.prototype._drawText_setContent = function (contents, callback) { // 合并进 insertAction - if ((core.status.event && core.status.event.id=='action') || core.isReplaying()) { + if ((core.status.event && core.status.event.id=='action') + || (!core.hasFlag('__replayText__') && core.isReplaying())) { core.insertAction(contents,null,null,callback); return; } @@ -383,7 +573,7 @@ ui.prototype._getTitleAndIcon = function (content) { else { var blockInfo = core.getBlockInfo(s4); if (blockInfo != null) { - if (core.material.enemys[s4]) title = core.material.enemys[s4].name; + if (blockInfo.name) title = blockInfo.name; image = blockInfo.image; icon = blockInfo.posY; height = blockInfo.height; @@ -392,7 +582,10 @@ ui.prototype._getTitleAndIcon = function (content) { else title = s4; } } - if (s3) title = s3; + if (s3 != null) { + title = s3; + if (title == 'null') title = null; + } return ""; }); return { @@ -446,23 +639,52 @@ ui.prototype._getPosition = function (content) { ////// 绘制选择光标 ui.prototype.drawWindowSelector = function(background, x, y, w, h) { + w = Math.round(w), h = Math.round(h); + var ctx = core.ui.createCanvas("_selector", x, y, w, h, 165); + this._drawSelector(ctx, background, w, h); +} + +ui.prototype._uievent_drawSelector = function (data) { + if (data.image == null) { + if (main.mode != 'editor') + core.deleteCanvas('_uievent_selector'); + return; + } + + var background = data.image || core.status.textAttribute.background; + if (typeof background != 'string') return; + var x = core.calValue(data.x), y = core.calValue(data.y), w = core.calValue(data.width), h = core.calValue(data.height); + w = Math.round(w); h = Math.round(h); + if (main.mode == 'editor') { + this._drawSelector('uievent', background, w, h, x, y); + return; + } + var z = 136; + if (core.dymCanvas.uievent) z = (parseInt(core.dymCanvas.uievent.canvas.style.zIndex) || 135) + 1; + var ctx = core.createCanvas('_uievent_selector', x, y, w, h, z); + this._drawSelector(ctx, background, w, h); +} + +ui.prototype._drawSelector = function (ctx, background, w, h, left, top) { + left = left || 0; + top = top || 0; + ctx = this.getContextByName(ctx); + if (!ctx) return; if (typeof background == 'string') background = core.material.images.images[background]; - w = Math.round(w), h = Math.round(h); - var dstImage = core.ui.createCanvas("_selector", x, y, w, h, 165); - core.setOpacity("_selector", 0.8); + if (!(background instanceof Image)) return; // back - dstImage.drawImage(background, 130, 66, 28, 28, 2, 2,w-4,h-4); + ctx.drawImage(background, 130, 66, 28, 28, left+2, top+2, w-4, h-4); // corner - dstImage.drawImage(background, 128, 64, 2, 2, 0, 0, 2, 2); - dstImage.drawImage(background, 158, 64, 2, 2,w-2, 0, 2, 2); - dstImage.drawImage(background, 128, 94, 2, 2, 0,h-2, 2, 2); - dstImage.drawImage(background, 158, 94, 2, 2,w-2,h-2, 2, 2); + ctx.drawImage(background, 128, 64, 2, 2, left, top, 2, 2); + ctx.drawImage(background, 158, 64, 2, 2, left+w-2, top, 2, 2); + ctx.drawImage(background, 128, 94, 2, 2, left, top+h-2, 2, 2); + ctx.drawImage(background, 158, 94, 2, 2, left+w-2, top+h-2, 2, 2); // border - dstImage.drawImage(background, 130, 64, 28, 2, 2, 0,w-4, 2); - dstImage.drawImage(background, 130, 94, 28, 2, 2,h-2,w-4, 2); - dstImage.drawImage(background, 128, 66, 2, 28, 0, 2, 2,h-4); - dstImage.drawImage(background, 158, 66, 2, 28,w-2, 2, 2,h-4); + ctx.drawImage(background, 130, 64, 28, 2, left+2, top, w-4, 2); + ctx.drawImage(background, 130, 94, 28, 2, left+2, top+h-2, w-4, 2); + ctx.drawImage(background, 128, 66, 2, 28, left, top+2, 2,h-4); + ctx.drawImage(background, 158, 66, 2, 28, left+w-2, top+2, 2,h-4); } ////// 绘制 WindowSkin @@ -524,6 +746,19 @@ ui.prototype.drawBackground = function (left, top, right, bottom, posInfo) { return false; } +ui.prototype._uievent_drawBackground = function (data) { + this._createUIEvent(); + var background = data.background || core.status.textAttribute.background; + var x = core.calValue(data.x), y = core.calValue(data.y), w = core.calValue(data.width), h = core.calValue(data.height); + if (typeof background == 'string') { + this.drawWindowSkin(background, 'uievent', x, y, w, h); + } + else if (background instanceof Array) { + this.fillRect('uievent', x, y, w, h, core.arrayToRGBA(background)); + this.strokeRect('uievent', x, y, w, h); + } +} + ui.prototype._drawWindowSkin_getOpacity = function () { return core.getFlag("__winskin_opacity__", 0.85); } @@ -611,30 +846,31 @@ ui.prototype._getDrawableIconInfo = function (id) { return [image,icon]; } -ui.prototype._buildFont = function (fontSize, bold) { +ui.prototype._buildFont = function (fontSize, bold, italic) { var textAttribute = core.status.textAttribute || core.initStatus.textAttribute, globalAttribute = core.status.globalAttribute || core.initStatus.globalAttribute; if (bold == null) bold = textAttribute.bold; - return (bold?"bold ":"") + (fontSize || textAttribute.textfont) + "px " + globalAttribute.font; + return (bold?"bold ":"") + (italic?"italic ":"") + (fontSize || textAttribute.textfont) + "px " + globalAttribute.font; } ////// 绘制一段文字到某个画布上面 // ctx:要绘制到的画布 -// content:要绘制的内容;转义字符目前只允许留 \n, \r[...] 和 \i[...] +// content:要绘制的内容;转义字符目前只允许留 \n, \r[...], \i[...], \c[...], \d, \e // config:绘制配置项,目前暂时包含如下内容(均为可选) // left, top:起始点位置;maxWidth:单行最大宽度;color:默认颜色;align:左中右 // fontSize:字体大小;lineHeight:行高;time:打字机间隔 ui.prototype.drawTextContent = function (ctx, content, config) { ctx = core.getContextByName(ctx); - if (!ctx) return; // 设置默认配置项 var textAttribute = core.status.textAttribute || core.initStatus.textAttribute; config = core.clone(config || {}); config.left = config.left || 0; - config.right = config.left + (config.maxWidth == null ? ctx.canvas.width : config.maxWidth); + config.right = config.left + (config.maxWidth == null ? (ctx != null ? ctx.canvas.width : core.__PIXELS__) : config.maxWidth) config.top = config.top || 0; - config.color = config.color || core.arrayToRGBA(textAttribute.text); + config.color = config.color || textAttribute.text; + if (config.color instanceof Array) config.color = core.arrayToRGBA(config.color); if (config.bold == null) config.bold = textAttribute.bold; + config.italic = false; config.align = config.align || textAttribute.align || "left"; config.fontSize = config.fontSize || textAttribute.textfont; config.lineHeight = config.lineHeight || (config.fontSize * 1.3); @@ -642,21 +878,30 @@ ui.prototype.drawTextContent = function (ctx, content, config) { config.index = 0; config.currcolor = config.color; + config.currfont = config.fontSize; + config.lineMargin = Math.max(0, config.lineHeight - config.fontSize); + config.topMargin = parseInt(config.lineMargin / 2); + config.lineMaxHeight = config.lineMargin + config.fontSize; config.offsetX = 0; config.offsetY = 0; config.line = 0; config.blocks = []; // 创建一个新的临时画布 - var tempCtx = core.bigmap.tempCanvas; - tempCtx.canvas.height = ctx.canvas.height; - tempCtx.canvas.width = ctx.canvas.width; - var _textBaseLine = tempCtx.textBaseline; + var tempCtx = core.createCanvas('__temp__', 0, 0, ctx==null?1:ctx.canvas.width, ctx==null?1:ctx.canvas.height, -1); tempCtx.textBaseline = 'top'; - tempCtx.font = this._buildFont(config.fontSize, config.bold); + tempCtx.font = this._buildFont(config.fontSize, config.bold, config.italic); tempCtx.fillStyle = config.color; - this._drawTextContent_draw(ctx, tempCtx, content, config); - tempCtx.textBaseline = _textBaseLine; + config = this._drawTextContent_draw(ctx, tempCtx, content, config); + core.deleteCanvas('__temp__'); + return config; +} + +ui.prototype._uievent_drawTextContent = function (data) { + this._createUIEvent(); + data.left = core.calValue(data.left); + data.top = core.calValue(data.top); + this.drawTextContent('uievent', core.replaceText(data.text), data); } // 绘制的基本逻辑: @@ -667,13 +912,16 @@ ui.prototype._drawTextContent_draw = function (ctx, tempCtx, content, config) { // Step 1: 绘制到tempCtx上,并记录下图块信息 while (this._drawTextContent_next(tempCtx, content, config)); + if (ctx == null) return config; + // Step 2: 从tempCtx绘制到画布上 config.index = 0; var _drawNext = function () { if (config.index >= config.blocks.length) return false; var block = config.blocks[config.index++]; ctx.drawImage(tempCtx.canvas, block.left, block.top, block.width, block.height, - config.left + block.left + block.marginLeft, config.top + block.top, block.width, block.height); + config.left + block.left + block.marginLeft, config.top + block.top + block.marginTop, + block.width, block.height); return true; } if (config.time == 0) { @@ -687,6 +935,8 @@ ui.prototype._drawTextContent_draw = function (ctx, tempCtx, content, config) { } }, config.time); } + + return config; } ui.prototype._drawTextContent_next = function (tempCtx, content, config) { @@ -712,9 +962,22 @@ ui.prototype._drawTextContent_drawChar = function (tempCtx, content, config, ch) if (ch == '\\') config.index++; return this._drawTextContent_changeColor(tempCtx, content, config); } - // \\i 绘制图标 - if (ch == '\\' && content.charAt(config.index)=='i') { - return this._drawTextContent_drawIcon(tempCtx, content, config); + if (ch == '\\') { + var c = content.charAt(config.index); + if (c == 'i') return this._drawTextContent_drawIcon(tempCtx, content, config); + if (c == 'c') return this._drawTextContent_changeFont(tempCtx, content, config); + if (c == 'd' || c == 'e') { + config.index++; + if (c == 'd') config.bold = !config.bold; + if (c == 'e') config.italic = !config.italic; + tempCtx.font = this._buildFont(config.currfont, config.bold, config.italic); + return true; + } + } + // \\e 斜体切换 + if (ch == '\\' && content.charAt(config.index)=='e') { + config.italic = !config.italic; + tempCtx.font = this._buildFont(config.fontSize, config.bold, config.italic); } // 检查是不是自动换行 var charwidth = core.calWidth(tempCtx, ch); @@ -724,10 +987,11 @@ ui.prototype._drawTextContent_drawChar = function (tempCtx, content, config, ch) return this._drawTextContent_next(tempCtx, content, config); } // 输出 - var left = config.offsetX, top = config.offsetY + (config.lineHeight - config.fontSize) / 2; + var left = config.offsetX, top = config.offsetY + config.topMargin; core.fillText(tempCtx, ch, left, top); config.blocks.push({left: config.offsetX, top: config.offsetY, - width: charwidth, height: config.lineHeight, line: config.line, marginLeft: 0}); + width: charwidth, height: config.currfont + config.lineMargin, + line: config.line, marginLeft: 0}); config.offsetX += charwidth; return true; } @@ -742,12 +1006,17 @@ ui.prototype._drawTextContent_newLine = function (tempCtx, config) { marginLeft = totalWidth - width; config.blocks.forEach(function (b) { - if (b.line == config.line) + if (b.line == config.line) { b.marginLeft = marginLeft; + // b.marginTop = 0; // 上对齐 + b.marginTop = (config.lineMaxHeight - b.height) / 2; // 居中对齐 + // b.marginTop = config.lineMaxHeight - b.height; // 下对齐 + } }); config.offsetX = 0; - config.offsetY += config.lineHeight; + config.offsetY += config.lineMaxHeight; + config.lineMaxHeight = config.currfont + config.lineMargin; config.line++; } @@ -765,6 +1034,22 @@ ui.prototype._drawTextContent_changeColor = function (tempCtx, content, config) return this._drawTextContent_next(tempCtx, content, config); } +ui.prototype._drawTextContent_changeFont = function (tempCtx, content, config) { + config.index++; + // 检查是不是 [] + var index = config.index, index2; + if (content.charAt(index) == '[' && ((index2=content.indexOf(']', index))>=0)) { + var str = content.substring(index+1, index2); + if (!/^\d+$/.test(str)) config.currfont = config.fontSize; + else config.currfont = parseInt(str); + config.index = index2 + 1; + } + else config.currfont = config.fontSize; + config.lineMaxHeight = Math.max(config.lineMaxHeight, config.currfont + config.lineMargin); + tempCtx.font = this._buildFont(config.currfont, config.bold, config.italic); + return this._drawTextContent_next(tempCtx, content, config); +} + ui.prototype._drawTextContent_drawIcon = function (tempCtx, content, config) { // 绘制一个 \i 效果 var index = config.index, index2; @@ -774,17 +1059,18 @@ ui.prototype._drawTextContent_drawIcon = function (tempCtx, content, config) { var iconInfo = core.ui._getDrawableIconInfo(str), image = iconInfo[0], icon = iconInfo[1]; if (image == null) return this._drawTextContent_next(tempCtx, content, config); // 检查自动换行 - var width = config.fontSize + 2, left = config.offsetX + 2, top = config.offsetY + (config.lineHeight - width) / 2 - 1; + var width = config.currfont + 2, left = config.offsetX + 2, top = config.offsetY + config.topMargin - 1; if (config.maxWidth != null && left + width > config.maxWidth) { this._drawTextContent_newLine(tempCtx, config); config.index--; - this._drawTextContent_next(tempCtx, content, config); + return this._drawTextContent_next(tempCtx, content, config); } // 绘制到画布上 core.drawImage(tempCtx, image, 0, 32*icon, 32, 32, left, top, width, width); config.blocks.push({left: left, top: config.offsetY, - width: config.lineHeight, height: config.lineHeight, line: config.line, marginLeft: 0}); + width: width, height: width + config.lineMargin, + line: config.line, marginLeft: 0}); config.offsetX += width + 6; config.index = index2 + 1; @@ -793,8 +1079,12 @@ ui.prototype._drawTextContent_drawIcon = function (tempCtx, content, config) { return this._drawTextContent_next(tempCtx, content, config); } +ui.prototype.getTextContentHeight = function (content, config) { + return this.drawTextContent(null, content, config).offsetY; +} + ui.prototype._getRealContent = function (content) { - return content.replace(/(\r|\\r)(\[.*?])?/g, "").replace(/(\\i)(\[.*?])?/g, "占1"); + return content.replace(/(\r|\\(r|c|d|e))(\[.*?])?/g, "").replace(/(\\i)(\[.*?])?/g, "占1"); } ////// 绘制一个对话框 ////// @@ -828,10 +1118,20 @@ ui.prototype.drawTextBox = function(content, showAll) { var content_top = this._drawTextBox_drawTitleAndIcon(titleInfo, hPos, vPos, alpha); // Step 5: 绘制正文 - this.drawTextContent('ui', content, { + var config = this.drawTextContent('ui', content, { left: hPos.content_left, top: content_top, maxWidth: hPos.validWidth, lineHeight: vPos.lineHeight, time: (showAll || textAttribute.time<=0 || core.status.event.id!='action')?0:textAttribute.time }); + + // Step 6: 绘制光标 + main.dom.next.style.display = 'block'; + main.dom.next.style.borderRightColor = main.dom.next.style.borderBottomColor = core.arrayToRGB(textAttribute.text); + main.dom.next.style.top = (vPos.bottom - 20) * core.domStyle.scale + "px"; + var left = (hPos.left + hPos.right) / 2; + if (pInfo.position == 'up' && pInfo.px != null && Math.abs(pInfo.px * 32 + 16 - left) < 50) + left = hPos.right - 64; + main.dom.next.style.left = left * core.domStyle.scale + "px"; + return config; } ui.prototype._drawTextBox_drawImages = function (content) { @@ -846,8 +1146,11 @@ ui.prototype._drawTextBox_drawImages = function (content) { core.drawImage('ui', img, parseFloat(ss[1]), parseFloat(ss[2])); else if (ss.length==5) core.drawImage('ui', img, 0, 0, img.width, img.height, parseFloat(ss[1]), parseFloat(ss[2]), parseFloat(ss[3]), parseFloat(ss[4])); - else if (ss.length==9) + else if (ss.length==9 || ss.length==10) { + if (ss.length==10) core.setAlpha('ui', parseFloat(ss[9])); core.drawImage('ui', img, parseFloat(ss[1]), parseFloat(ss[2]), parseFloat(ss[3]), parseFloat(ss[4]), parseFloat(ss[5]), parseFloat(ss[6]), parseFloat(ss[7]), parseFloat(ss[8])); + core.setAlpha('ui', 1); + } return ""; }); } @@ -875,9 +1178,10 @@ ui.prototype._drawTextBox_getHorizontalPosition = function (content, titleInfo, ui.prototype._drawTextBox_getVerticalPosition = function (content, titleInfo, posInfo, validWidth) { var textAttribute = core.status.textAttribute || core.initStatus.textAttribute; - var lineHeight = textAttribute.textfont + 5; - var realContent = this._getRealContent(content); - var height = 30 + lineHeight * core.splitLines("ui", realContent, validWidth, this._buildFont()).length; + var lineHeight = textAttribute.textfont + 6; + var height = 45 + this.getTextContentHeight(content, { + lineHeight: lineHeight, maxWidth: validWidth + }); if (titleInfo.title) height += textAttribute.titlefont + 5; if (titleInfo.icon != null) { if (titleInfo.title) height = Math.max(height, titleInfo.height+50); @@ -958,9 +1262,7 @@ ui.prototype._drawTextBox_drawTitleAndIcon = function (titleInfo, hPos, vPos, al } ui.prototype._createTextCanvas = function (content, lineHeight) { - var realContent = this._getRealContent(content); - var lines = core.splitLines('ui', realContent, null, this._buildFont()); - var width = this.PIXEL, height = lines.length * lineHeight; + var width = this.PIXEL, height = 30 + this.getTextContentHeight(content, {lineHeight: lineHeight}); var ctx = document.createElement('canvas').getContext('2d'); ctx.canvas.width = width; ctx.canvas.height = height; @@ -1060,10 +1362,10 @@ ui.prototype._drawChoices_getVerticalPosition = function (titleInfo, choices, hP var choice_top = bottom - height + 56; if (titleInfo.content) { var headHeight = 0; - var realContent = this._getRealContent(titleInfo.content); - var lines = core.splitLines('ui', realContent, hPos.validWidth, this._buildFont(15, true)); if (titleInfo.title) headHeight += 25; - headHeight += lines.length * 20; + headHeight += this.getTextContentHeight(titleInfo.content, { + lineHeight: 20, maxWidth: hPos.validWidth, fontSize: 15, bold: true + }); height += headHeight; if (bottom - height <= 32) { offset = Math.floor(headHeight / 64); @@ -1214,7 +1516,6 @@ ui.prototype.drawSwitchs = function() { "领域显伤: "+(core.flags.displayExtraDamage ? "[ON]" : "[OFF]"), "新版存档: "+(core.platform.useLocalForage ? "[ON]":"[OFF]"), "单击瞬移: "+(!core.hasFlag("__noClickMove__") ? "[ON]":"[OFF]"), - "拓展键盘: "+(core.platform.extendKeyboard ? "[ON]":"[OFF]"), "返回主菜单" ]; this.drawChoices(null, choices); @@ -1623,11 +1924,19 @@ ui.prototype._drawBookDetail_turnAndCriticals = function (enemy, floorId, texts) var damageInfo = core.getDamageInfo(enemy, null, null, null, floorId); texts.push("战斗回合数:"+((damageInfo||{}).turn||0)); // 临界表 - var criticals = core.enemys.nextCriticals(enemy, 10, null, null, floorId).map(function (v) { + var criticals = core.enemys.nextCriticals(enemy, 8, null, null, floorId).map(function (v) { return core.formatBigNumber(v[0])+":"+core.formatBigNumber(v[1]); }); while (criticals[0]=='0:0') criticals.shift(); - texts.push("临界表:"+JSON.stringify(criticals)) + texts.push("临界表:"+JSON.stringify(criticals)); + var prevInfo = core.getDamageInfo(enemy, {atk: core.status.hero.atk-1}, null, null, floorId); + if (prevInfo != null && damageInfo != null) { + if (damageInfo.damage != null) damageInfo = damageInfo.damage; + if (prevInfo.damage != null) prevInfo = prevInfo.damage; + if (prevInfo > damageInfo) { + texts.push("(当前攻击力正位于临界点上)") + } + } } ui.prototype._drawBookDetail_drawContent = function (enemy, contents, pos) { @@ -1664,8 +1973,19 @@ ui.prototype.drawFly = function(page) { core.setTextAlign('ui', 'center'); core.fillText('ui', '楼层跳跃', this.HPIXEL, 60, '#FFFFFF', this._buildFont(28, true)); core.fillText('ui', '返回游戏', this.HPIXEL, this.PIXEL - 13, null, this._buildFont(15, true)) - core.fillText('ui', title, this.PIXEL - 60, this.HPIXEL + 39, null, this._buildFont(19, true)); + var middle = this.HPIXEL + 39; + + // 换行 + var lines = core.splitLines('ui', title, 120, this._buildFont(19, true)); + var start_y = middle - (lines.length - 1) * 11; + for (var i in lines) { + core.fillText('ui', lines[i], this.PIXEL - 60, start_y); + start_y += 22; + } + + // core.fillText('ui', title, this.PIXEL - 60, this.HPIXEL + 39, null, this._buildFont(19, true)); + if (core.actions._getNextFlyFloor(1) != page) { core.fillText('ui', '▲', this.PIXEL - 60, middle - 64, null, this._buildFont(17, false)); core.fillText('ui', '▲', this.PIXEL - 60, middle - 96); @@ -1913,9 +2233,12 @@ ui.prototype._drawToolbox_drawDescription = function (info, max_height) { // 检查能否eval text = core.replaceText(text); } catch (e) {} - var lines = core.splitLines('ui', text, this.PIXEL - 15, this._buildFont(17, false)); - // --- 开始逐行绘制 - var curr = 62, line_height = 25; + + for (var font_size = 17; font_size >= 14; font_size -= 3) { + var lines = core.splitLines('ui', text, this.PIXEL - 15, this._buildFont(font_size, false)); + var line_height = parseInt(font_size * 1.4), curr = 37 + line_height; + if (curr + lines.length * line_height < max_height) break; + } core.setFillStyle('ui', '#FFFFFF'); for (var i=0;i= 11; font_size -= 3) { + var lines = core.splitLines('ui', text, this.PIXEL - 15, this._buildFont(font_size, false)); + var line_height = parseInt(font_size * 1.4), curr = 37 + line_height; + if (curr + lines.length * line_height < max_height) break; + } core.setFillStyle('ui', '#FFFFFF'); for (var i = 0; i < lines.length; ++i) { core.fillText('ui', lines[i], 10, curr); @@ -2032,7 +2359,7 @@ ui.prototype._drawEquipbox_description = function (info, max_height) { this._drawEquipbox_drawStatusChanged(info, curr, equip, equipType); } -ui.prototype._drawEquipbox_getStatusChanged = function (info, equip, equipType) { +ui.prototype._drawEquipbox_getStatusChanged = function (info, equip, equipType, y) { var compare, differentMode = null; if (info.index < this.LAST) compare = core.compareEquipment(null, info.selectId); else { @@ -2053,7 +2380,7 @@ ui.prototype._drawEquipbox_getStatusChanged = function (info, equip, equipType) } ui.prototype._drawEquipbox_drawStatusChanged = function (info, y, equip, equipType) { - var compare = this._drawEquipbox_getStatusChanged(info, equip, equipType); + var compare = this._drawEquipbox_getStatusChanged(info, equip, equipType, y); if (compare == null) return; var obj = { drawOffset: 10, y: y }; @@ -2210,7 +2537,7 @@ ui.prototype._drawSLPanel_drawRecord = function(title, data, x, y, size, cho, hi var v2 = "/"+core.formatBigNumber(data.hero.mdef,true); if (core.calWidth('ui', v + v2, this._buildFont(10, false)) <= size) v += v2; core.fillText('ui', v, x, y+30+size, '#FFD700'); - core.fillText('ui', core.formatDate(new Date(data.time)), x, y+43+size, data.hero.flags.__consoleOpened__?'#FF6A6A':'#FFFFFF'); + core.fillText('ui', core.formatDate(new Date(data.time)), x, y+43+size, data.hero.flags.__consoleOpened__||data.hero.flags.debug?'#FF6A6A':'#FFFFFF'); } else { core.fillRect('ui', x-size/2, y+15, size, size, '#333333', 2); @@ -2303,6 +2630,7 @@ ui.prototype.drawStatistics = function (floorIds) { core.ui._drawStatistics_floorId(floorId, obj); }); var statistics = core.status.hero.statistics; + core.setFlag("__replayText__", true); core.drawText([ this._drawStatistics_generateText(obj, "全塔", obj.total), this._drawStatistics_generateText(obj, "当前", obj.current), @@ -2320,6 +2648,7 @@ ui.prototype.drawStatistics = function (floorIds) { "4. 在自定义道具(例如其他宝石)后,需在脚本编辑的drawStatistics中注册,不然不会进行统计。\n"+ "5. 所有统计信息仅供参考,如有错误,概不负责。" ]) + core.removeFlag("__replayText__"); } ui.prototype._drawStatistics_buildObj = function () { @@ -2590,15 +2919,15 @@ ui.prototype.relocateCanvas = function (name, x, y) { } ////// canvas重置 ////// -ui.prototype.resizeCanvas = function (name, width, height) { +ui.prototype.resizeCanvas = function (name, width, height, styleOnly) { var ctx = core.dymCanvas[name]; if (!core.isset(ctx)) return null; if (core.isset(width)) { - ctx.canvas.width = width; + if (!styleOnly) ctx.canvas.width = width; ctx.canvas.style.width = width * core.domStyle.scale + 'px'; } if (core.isset(height)) { - ctx.canvas.height = height; + if (!styleOnly) ctx.canvas.height = height; ctx.canvas.style.height = height * core.domStyle.scale + 'px'; } return ctx; diff --git a/libs/utils.js b/libs/utils.js index b5107087..9fa75957 100644 --- a/libs/utils.js +++ b/libs/utils.js @@ -317,16 +317,15 @@ utils.prototype.splitImage = function (image, width, height) { height = height || width; var canvas = document.createElement("canvas"); var context = canvas.getContext("2d"); - canvas.width = width; - canvas.height = height; var ans = []; for (var j = 0; j < image.height; j += height) { for (var i = 0; i < image.width; i += width) { - context.drawImage(image, i, j, width, height, 0, 0, width, height); + var w = Math.min(width, image.width - i), h = Math.min(height, image.height - j); + canvas.width = w; canvas.height = h; + context.drawImage(image, i, j, w, h, 0, 0, w, h); var img = new Image(); img.src = canvas.toDataURL("image/png"); ans.push(img); - context.clearRect(0, 0, width, height); } } return ans; @@ -915,7 +914,9 @@ utils.prototype.myconfirm = function (hint, yesCallback, noCallback) { main.dom.inputDiv.style.display = 'block'; main.dom.inputMessage.innerHTML = hint.replace(/\n/g, '
'); main.dom.inputBox.style.display = 'none'; - main.dom.inputYes.focus(); + main.dom.inputYes.blur(); + main.dom.inputNo.blur(); + core.status.holdingKeys = []; core.platform.successCallback = yesCallback; core.platform.errorCallback = noCallback; @@ -927,9 +928,12 @@ utils.prototype.myprompt = function (hint, value, callback) { main.dom.inputMessage.innerHTML = hint.replace(/\n/g, '
'); main.dom.inputBox.style.display = 'block'; main.dom.inputBox.value = value==null?"":value; + main.dom.inputYes.blur(); + main.dom.inputNo.blur(); setTimeout(function () { main.dom.inputBox.focus(); }); + core.status.holdingKeys = []; core.platform.successCallback = core.platform.errorCallback = callback; } @@ -937,7 +941,7 @@ utils.prototype.myprompt = function (hint, value, callback) { ////// 动画显示某对象 ////// utils.prototype.showWithAnimate = function (obj, speed, callback) { obj.style.display = 'block'; - if (!speed && main.mode != 'play') { + if (!speed || main.mode != 'play') { obj.style.opacity = 1; if (callback) callback(); return; @@ -1085,11 +1089,11 @@ utils.prototype._export = function (floorIds) { // map var content = floorIds.length + "\n" + core.__SIZE__ + " " + core.__SIZE__ + "\n\n"; floorIds.forEach(function (floorId) { - var arr = core.maps._getMapArrayFromBlocks(core.status.maps[floorId].blocks); + var arr = core.maps._getMapArrayFromBlocks(core.status.maps[floorId].blocks, core.__SIZE__, core.__SIZE__); content += arr.map(function (x) { // check monster x.forEach(function (t) { - var block = core.maps.initBlock(null, null, t); + var block = core.maps.getBlockByNumber(t); if (block.event.cls.indexOf("enemy") == 0) { monsterMap[t] = block.event.id; } @@ -1101,7 +1105,7 @@ utils.prototype._export = function (floorIds) { // values content += ["redJewel", "blueJewel", "greenJewel", "redPotion", "bluePotion", "yellowPotion", "greenPotion", "sword1", "shield1"].map(function (x) { - return core.values[x] + return core.values[x] || 0; }).join(" ") + "\n\n"; // monster diff --git a/main.js b/main.js index 5ecac76f..e2c8cf15 100644 --- a/main.js +++ b/main.js @@ -2,7 +2,7 @@ function main() { //------------------------ 用户修改内容 ------------------------// - this.version = "2.6.1"; // 游戏版本号;如果更改了游戏内容建议修改此version以免造成缓存问题。 + this.version = "2.6.3"; // 游戏版本号;如果更改了游戏内容建议修改此version以免造成缓存问题。 this.useCompress = false; // 是否使用压缩文件 // 当你即将发布你的塔时,请使用“JS代码压缩工具”将所有js代码进行压缩,然后将这里的useCompress改为true。 @@ -74,7 +74,8 @@ function main() { 'inputMessage': document.getElementById('inputMessage'), 'inputBox': document.getElementById('inputBox'), 'inputYes': document.getElementById('inputYes'), - 'inputNo': document.getElementById('inputNo') + 'inputNo': document.getElementById('inputNo'), + 'next': document.getElementById('next') }; this.mode = 'play'; this.loadList = [ @@ -188,8 +189,8 @@ function main() { this.floors = {} this.canvas = {}; - this.__VERSION__ = "2.6.1"; - this.__VERSION_CODE__ = 36; + this.__VERSION__ = "2.6.3"; + this.__VERSION_CODE__ = 63; } main.prototype.init = function (mode, callback) { @@ -204,6 +205,7 @@ main.prototype.init = function (mode, callback) { main.dom.startBackground.src="project/images/"+main.startBackground; main.dom.startLogo.style=main.startLogoStyle; + main.dom.startButtonGroup.style = main.startButtonsStyle; main.levelChoose.forEach(function(value){ var span = document.createElement('span'); span.setAttribute('class','startButton'); @@ -215,6 +217,7 @@ main.prototype.init = function (mode, callback) { })(span,value[1]); main.dom.levelChooseButtons.appendChild(span); }); + main.createOnChoiceAnimation(); main.loadJs('libs', main.loadList, function () { main.core = core; @@ -327,6 +330,49 @@ main.prototype.log = function (e) { } } +main.prototype.createOnChoiceAnimation = function () { + var borderColor = main.dom.startButtonGroup.style.caretColor || "rgb(255, 215, 0)"; + // get rgb value + var rgb = /^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*\d+\s*)?\)$/.exec(borderColor); + if (rgb != null) { + var value = rgb[1] + ", " + rgb[2] + ", " + rgb[3]; + var style = document.createElement("style"); + style.type = 'text/css'; + var keyFrames = "onChoice { " + + "0% { border-color: rgba("+value+", 0.9); } " + + "50% { border-color: rgba("+value+", 0.3); } " + + "100% { border-color: rgba("+value+", 0.9); } " + + "}"; + style.innerHTML = "@-webkit-keyframes " + keyFrames + " @keyframes " + keyFrames; + document.body.appendChild(style); + } +} + +////// 选项 ////// +main.prototype.selectButton = function (index) { + var select = function (children) { + index = (index + children.length) % children.length; + for (var i = 0;i < children.length; ++i) { + children[i].classList.remove("onChoiceAnimate"); + } + children[index].classList.add("onChoiceAnimate"); + if (main.selectedButton == index) { + children[index].click(); + } + else { + main.selectedButton = index; + } + } + + if (core.dom.startPanel.style.display != 'block') return; + + if (main.dom.startButtons.style.display == 'block') { + select(main.dom.startButtons.children); + } + else if (main.dom.levelChooseButtons.style.display == 'block') { + select(main.dom.levelChooseButtons.children); + } +} main.prototype.listen = function () { @@ -349,8 +395,35 @@ main.dom.body.onkeydown = function(e) { ////// 在界面上放开某按键时 ////// main.dom.body.onkeyup = function(e) { try { - if (main.dom.inputDiv.style.display == 'block') return; - if (main.core && (main.core.isPlaying() || main.core.status.lockControl)) + if (main.dom.startPanel.style.display == 'block' && + (main.dom.startButtons.style.display == 'block' || main.dom.levelChooseButtons.style.display == 'block')) { + if (e.keyCode == 38 || e.keyCode == 33) // up/pgup + main.selectButton((main.selectedButton||0) - 1); + else if (e.keyCode == 40 || e.keyCode == 34) // down/pgdn + main.selectButton((main.selectedButton||0) + 1); + else if (e.keyCode == 67 || e.keyCode == 13 || e.keyCode == 32) // C/Enter/Space + main.selectButton(main.selectedButton); + else if (e.keyCode == 27 && main.dom.levelChooseButtons.style.display == 'block') { // ESC + main.core.showStartAnimate(true); + } + e.stopPropagation(); + return; + } + if (main.dom.inputDiv.style.display == 'block') { + if (e.keyCode == 13) { + setTimeout(function () { + main.dom.inputYes.click(); + }, 50); + } + else if (e.keyCode == 27) { + setTimeout(function () { + main.dom.inputNo.click(); + }, 50); + } + return; + } + if (main.core && main.core.isPlaying && main.core.status && + (main.core.isPlaying() || main.core.status.lockControl)) main.core.onkeyUp(e); } catch (ee) { main.log(ee); } } @@ -592,7 +665,7 @@ main.statusBar.image.settings.onclick = function (e) { } ////// 点击工具栏时 ////// -main.dom.toolBar.onclick = function () { +main.dom.hard.onclick = function () { if (core.isReplaying()) return; main.core.control.setToolbarButton(!core.domStyle.toolbarBtn); @@ -649,6 +722,8 @@ main.dom.playGame.onclick = function () { } else { main.dom.levelChooseButtons.style.display='block'; + main.selectedButton = null; + main.selectButton(0); } } @@ -693,19 +768,6 @@ main.dom.inputNo.onclick = function () { if (func) func(null); } -main.dom.inputDiv.onkeyup = function (e) { - if (e.keyCode == 13) { - setTimeout(function () { - main.dom.inputYes.click(); - }, 50); - } - else if (e.keyCode == 27) { - setTimeout(function () { - main.dom.inputNo.click(); - }, 50); - } -} - }//listen end var main = new main(); \ No newline at end of file diff --git a/project/animates/hand.animate b/project/animates/hand.animate index bffc26d1..09c95147 100644 --- a/project/animates/hand.animate +++ b/project/animates/hand.animate @@ -1 +1 @@ -{"ratio":2,"bitmaps":["data:image/png;base64,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","data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAlCSURBVHhe7dxrbBTXFQdw2qSJokRKhUSFoEJNU7UfWj5RVapUNVKlSFGTfEirlqoqFLDr1DwLGEEgBRIgFFqXp0l5FBNQwTbg4EeMn/ELjI3XD2yvX9g4NnaN32t7HzM7e86/d5eLVcc27NrG3tncnzTi3DtrI8+ZmXvu7MzMURRFURRFURRFURRFURTlK4R7oqJkOCnICF8iQ2UyqDsqU4aTQjkRh2WoTAY6ti7i7s0/l82AcNGaxZT7bp9sKpNFPZsKZBgQLl27FoWrIZvKZHHPlgXctvEF2fQbVaxLQvEalYDpQN1bEmXoN6re4ETZRnDRxoWyy2+cFPY9GSpe6Nz6HRn6DQ3bgOqtoNubo2WX3/jqil/IUHmEB7a/I0O/4N6HQP1O4M6OgE5DSPjNMzJUJosfRC/G/YNA8wGRhI8CSgAlRyTJ0C98bXlAO8ZXAvV+nIrOj4H2GKDliEjC4Z/JVSM4f/ubMhyFPlvtdwIo6Y+XZWguyH3tWRkGDEh44ikC/ReAXrF0nQM6YkEt/xozH+Dij5bJcARnbtqArPVjkjUeSl2VyOlhc2XTfLyVBqcsD7xCcZx67CEPe+p8DCcDtiSg/1Og5wrwIAGoSXhOfmQOrCdsfOfoFtkcgbxtfp+uxMZ/XYbmhdTwCLq+Kkc2/UbOiydkOAY5sofhzAUcYhkWiy1bJCJDJCJNHBEiOe1X8tByEdRw7rr8ER8u3R+Jkj1+JYDTVs6ToflRRngRciNFvb7a79qbnCke0tOOyeYI1m8vg24BtDKxlAMuETtui0TcAgaLgIECkQiRkAciGe3XRm1s1Ijx4s4/n5gALoh8TYahgwrWeVCyEVSxtV52PRbpnyfCXQjSip3sKVsKd9USuK3nyKj7kI3G19lRtwDAM8yVL7Jet5hddSvJXnWRhsp1DJWKRIiE9OSLIyL3Jd/va41rxb0L4qg45fH9BxNAyYYVMgwt3tobZVsA6/tA0z7g/j8i5Kpxkbs0CUYlyKg5JE7uvo0YCLbXvkXDlVbYSkB9+e3ozgL+mwxqi2uVHxmDqrfvR82ukXEk5HDV9jfRuBdojQY6Y0DdZzzcFj/uNSD2WMdUMJPB3PYCDd9JxmAJ0JcP6kl3ylWjoOmAhe/uWSqboYvu/b3bV7t3x4rTRDwwlALYs/Pk6qeGXY2v0mB5F4ZujR4XumLno+M0qP1ou+wKfb7avf+y2PifPaxkNLF36pVgbvqW/MhTQ07rURqyOGkw/yQG0sVRIcrY3kt+l6YhgfriEh9u/DxRxYhztLumVq6aEeysXQ6nqKCGb4idIAtkuxYrV02aGOPMNXbAISoUVynIVV0mu2YUa41vw1UpdoKbU9r7OXnFJmDO12TTPLz1O+nWTtmcFaw3LIdWOZIA2BPmy/CJOC1sB2f84UXZNB9R04syHl+XzVlDev1Rb5krlieeQrho41zKjrzFWeHfl13mxFrVTjaaguYSL+m1XeS0THiFFDV/3UbFmxxcuC7KVKcbfnD4HfSdBmwXRamZYoOrQFQ7FWJy1VgoPxIU2NX6KvQasKvY9y0Z2+Ln8oNPdqLtuJg5H3Rx9W4xgzThef4RGkz0wJkjNn4p4K4V5WZn0J07yV2fDK1C7CiFYocRFVr3JdD9k+1oOfRN+RFzgyZKPlHrk96ULruCinfGDL1WVEWiLB64blDvlQtijDLvXv9lrJVsgiH+QHQskl1Bh9x3rWQvd/NQ3q9kV2iBpymoZ5xsfPEWadVZshla2FX5ChlfxMhm0GK99kcyDB3eGhuGVQy+rT+UXUELaAmNQfcRcmXsh7sE8NSZ4oIXO1oXyDB0wH0bMBrMkQC95XcyDA3iCPiPuRLQtpic1loxKXtFdpkLd+79CfUePoGhs6KmvgxoGWLyZaJTkJgkeucDNFzENJDeQ93xxdxx5k/cFr0QubvGvdfJO0v2Lpy27nnZ9fTwtVU/oJRVVqSHgXLC2/lm5Ji7z7gv+g0MnrHAHi8ScN1UCfB+0Q+9DnAWA0OZQJ/YiTr/DWqJvk8Ne2K46v3f4vZfvis/HvygpeZBvylOQTUmOQJaF/iOAEdxJtvSzXtX3P9jLW8njDvmSIC7LfTuCfKCZrHJMKix0Wz+2xHHw3rRYhkGNTKaymUYethTvlyGQctbLpNumdKjs0GLjOKg3rt8l6QNq6jaikFa5qx+Xz3t2JUWCT0/qAdiMhqj2V2xBe7CJUDCc3AkLGHb+dB4mA9aIqBngt03V8suZaaw8+xSuOJEAlLEkmOKcjRkALueI3uMh7UL4z6vpTxlbIsO+tkkGTX7yCipkk1lJjE3LIRRJiqfG6L8zNgvu0Mfc/xcdmdO6V1B0wFGhdj4N8XYlAVoSSBH3AdyVWgjLS4WehJYy561O+TIqKyFu0hs/Gyx8UWB4EwAHJ+AhmMCfm+F6UA7L/7oy77KiLWMGU8CGxUjRQHcqUvYEb+B7OfqYT8FDB0BBg6a4trVpPDQkXlwnRaH+wW7SEIeaynvsZ45I9eKvDdbiT3/rGxOiHv37kDvbqB/68uyK3TQcHQL7MfF8X7yG7JrRrBR8wbc5WKwvTHq+eEnQc3qgB8SDGpkP/DY18uwVjCtt38zNz5PWlXhw+eLbwCurElNBr1PenLpmnDZNCfu/+BtGU4IyHqZtII+NizT8k4fcpfHQS8RG75ALBlioE1CIA9jfBnnRyzlnLBIWCJm9AieMUDus6JE/bFsBsT7s2TcPSSbI0T/S3BeFxs+UQyyl0C22GG5atK8341T0sqAXxY1K7xvR5ThlLBeGQZ3jajda8VSL5YG778WudrHl0Ct9JeyOQps5y3oPwP0nQB3RU/5SicnL/spJa74XDaDE5rXL0LX9A1k0IrFubzUt5DTMiS7R3ncK2+459jv8SAaaN8X+hcGYVm/iKxrp/UwpeEsDxw5YsKUzeTIOSC7A8KN++aheSeo8b2Tsiv0oDBiERX9WZfNaUO2qwdh+xTUf8090asO/EXVUR6u3Gzepx0fh7LDqp7GC/LYdnoues+Bes53y64poeL1p2Wo+Asdx0H3j2XIpjLT0Pw3cPPBX8umMtOoevctbpyBm2GV8XF5VNDfYxTSkBtiF8gURTEb070kKdTw1fBvy1CZDRM9s6UoiqIoiqIoiqIoiqIowWXOnP8B5gGFQj7+hj8AAAAASUVORK5CYII=","data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAgMSURBVHhe7d17bFvVHQfwwkZHN1CnAlJHJzY0aSDGY9qDSWhoD+2PbWh/7I8hjQlp2qRKpaWhY6ElXUlH24UupKWBDNKVhpJSiGFpmyYN5OXm5cSJY+fhPJqH0yTOw0kTu3Zsx3Z+v998ox/TXNuxr+W3z0eK9P2dm0rVPb73nnty7/EGQRAEQUhVVLt3M0chEbB17885ComAnQf3cBRiBbsP/4ajH+jLf5ejECswcGyJox8YLurkKMQKGU4SRz9gPOPgKMhFytwvclwXTZcG7QCa/zjoNiEEbMn+Gcd1kSn4TibzpYg7gGjDLRwzE3bmfA1VBZu4DAoWLzrIXPldLn2QrSaiDvAefbdnfAcQ0S2kPbKPy6DQcnkHWmv2c+mDHI2RdYD2sIYo91YuMxf05jfR4PFvchkULSuvcPRBK62yOwAH38oBff689AHgpsyF/cf/BCNvT5Om+DZuCogcgXc0uTtkdwCMveuAkXeOcZnZpJEQGE7bYKr0LDcFBK72PI4+yNMlqwPQdP4lmPrQhrPvf4WbBJgsrQBjmQfny7/NTWEjT4+sDoDFKhMsVFRzKUhwsmwLzFVYvTvnIjeFDdz9Qe+SAwFL4ypa6x7iMr1g/Y4nOMrm3fknYKnOe2FUfIGbwgKegX9yDAmdHTvBphpL64sv1O1cxfrnn+YybESa28DaaEZ724+4KSxEQ3dzDAlcumvo0P6ey4BCDU1RtWcbx+RFDbsJGrIcpPidvE+zre0dcHRc4jLqYEUv+wj7HPYczYLOV/u5TG6kyN1ITX8laN1rJk3ul7k5LODULRIpw5ojkgNx8E7wXD3KpSww/C8XDZyQPdxNKOnTD6oDCF2HmoKdcwMd7ujueRLdAz/hMmrAM1okt2Nx7vwzNF1GYDhjD3fiMOlAd94q6k/s5dJH0I7xXD3IMWoIJhQcwwLm+mpa+pTAVG6g8ZLbuTk1wdW3DcEubmhX/5ZjTMkZ+YBd3Q83WlbB0vCftBkx4cS5ezn6AVffZY4xgTj8JY4hkbN3O9g1BrS1PcpN6Y9Iv5HcYyFnRWNN+n947ysORTpSSnnkMgac848XqQM4CoLwP+DsykO7Ki6DBeH/gKe/F9x6I5fJg2q3b4a654qxYddT3JRW0D3xA3CPAHqGkvuxR2zcdT81/oWo9WXC9oN/5uaURjR9N8C1D7lMDaj62yPU6R299bxO3puuDlJGfy4nHlL+pov0b/yYhv9NYDiLMHPhXNrcRaYanCm7B2YuzcCSskp0QoKhrStzbumFxMJrJ+/HwcJs0B1tJE3ug9wsxBIuVT9LpgtExo8IRk/pYKiwGLvzH+bN8YWG0gc4ComE1+u2gbXtA1jWnUNX/3e4WRAEQRDSGo2/tZWjEGveu/xb0V5zL12veg1mPzHC+PtIoycJ9AWrpDtiAfWBEWzJ/gP/uhBrYtpFEARBEARBiCJpeCk92i6N+7lJSARE/RZw9hSAQ6Mlk/IObk5NROOp/cx9vEmHIU4WbIpkfYW1f4uTmxBnH0Y0fYubhXBg6/5vUEeughTyH9mW3nxE99VdsGqolx544mYhHKjaswWaXgy4PEA4wKkth5XeZi5TFq4MPySdLuM6z0MNu7/PUTa8Uf8ALLe9yWVaQM/Qr8CpmwWHWg021Wm01D+NxvK7eHPywMXKX3JMS2BtrybLFaLFGqI5fhLCUFLLm4V4AVPVBM18QjRRSjRykmigkEB7tIA3C/FAJsUdMHK6koaKiHpfJ9IeJu9ghVD1ctTfcY4YWpvSc1WSm6D2yD2k+fs+aMkZoeaXiK5kWXhTYtCSYjOZqv/IpRBPYHivXno6msu0gfNVWRyTE+peexwGjtu4TJhYTpjhZNnjOFYScPXGhAL1K0boerWSy4SSpjw4Rkx6UVu6i+fSD+nfsKA2Pzmub9Sc7b3y70ua8T/RtKzlcYKhpdrN670xj52Hn4L2nEW5ayJFFdTtrsTLz4e9DkM8SG+7R+MokOBsdcgHi6HpRTUoX/iIy/ih3OisOotO3U6OUSFdA3B1MuDDUERjsr/uhIxnQy6fsLY2Ut1z8/jZztR6mRuW23o5+pCzZkOgSTJYndBx9IHukSciWQ8Ch4p/yDEk+GxHnvQeNZfJC5dq9qO58Xtc+pD+8sQxJOmcf3MngGdUz9EH2nu+Ds6+vog6oS/vMY6pb22d0IXLC1z6AHd3CcewoGvwkZvP+eAc6uLoQ9rx4Ogwg0MT0dub2JJ9J8fUBlNlEGgH0LJ6Kyy3y5rUQlf/s+Ts+ymXa8DRcwKxO+DSxGBrNdCNZgJLcyM3ZRYcLs7C8fdyuPQBNqUaF1pkfcpgpftNWun2WewJUbWJnB2/4NIHWpQHyFxP3mFmaq2CGC0wUDjF0QeZKreCuXaSy7CBvaPe++P3lzuwNpdy9ANzFUjzlwjnypN7eiHaSJ+7Mdjyj2A6fwHmK2Wv6wnWlmG40eTfAQufHuLoh6YV95GxjGDqbGZ9ARCpcwO+PSI9aUHGDyw0XSHrLla6joC5btJ7OpG93hyNllyh0VOZeRq6GQ0VPwhjpwKO3dcjTRV4j5rrOHsxoqVyaLDQ24cZskDfel+6if3HnsShorBvdj4nLagKUx/bcOpcRAsroa5gG+nytnOZubD3H7/mKIv0LRgwdtpBY2fu4ybZUP1K8k0vx1skN0US7PZ2wHCRi0sh3tauAfoCD5dCIoD2kJujkAjQfqCVo5AIpMz6KkdBEARBEARBEIQUsGHDfwG4Vu3FAK5xRgAAAABJRU5ErkJggg==","","","","","","",""],"frame_max":8,"frames":[[[0,0,0,30,120]],[[0,0,0,50,255]],[[0,0,0,70,255]],[[1,0,0,80,255]],[[1,0,0,90,255]],[[2,0,0,90,120]],[],[]]} \ No newline at end of file +{"ratio":2,"se":"attack.mp3","bitmaps":["data:image/png;base64,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","data:image/png;base64,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","data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAgMSURBVHhe7d17bFvVHQfwwkZHN1CnAlJHJzY0aSDGY9qDSWhoD+2PbWh/7I8hjQlp2qRKpaWhY6ElXUlH24UupKWBDNKVhpJSiGFpmyYN5OXm5cSJY+fhPJqH0yTOw0kTu3Zsx3Z+v998ox/TXNuxr+W3z0eK9P2dm0rVPb73nnty7/EGQRAEQUhVVLt3M0chEbB17885ComAnQf3cBRiBbsP/4ajH+jLf5ejECswcGyJox8YLurkKMQKGU4SRz9gPOPgKMhFytwvclwXTZcG7QCa/zjoNiEEbMn+Gcd1kSn4TibzpYg7gGjDLRwzE3bmfA1VBZu4DAoWLzrIXPldLn2QrSaiDvAefbdnfAcQ0S2kPbKPy6DQcnkHWmv2c+mDHI2RdYD2sIYo91YuMxf05jfR4PFvchkULSuvcPRBK62yOwAH38oBff689AHgpsyF/cf/BCNvT5Om+DZuCogcgXc0uTtkdwCMveuAkXeOcZnZpJEQGE7bYKr0LDcFBK72PI4+yNMlqwPQdP4lmPrQhrPvf4WbBJgsrQBjmQfny7/NTWEjT4+sDoDFKhMsVFRzKUhwsmwLzFVYvTvnIjeFDdz9Qe+SAwFL4ypa6x7iMr1g/Y4nOMrm3fknYKnOe2FUfIGbwgKegX9yDAmdHTvBphpL64sv1O1cxfrnn+YybESa28DaaEZ724+4KSxEQ3dzDAlcumvo0P6ey4BCDU1RtWcbx+RFDbsJGrIcpPidvE+zre0dcHRc4jLqYEUv+wj7HPYczYLOV/u5TG6kyN1ITX8laN1rJk3ul7k5LODULRIpw5ojkgNx8E7wXD3KpSww/C8XDZyQPdxNKOnTD6oDCF2HmoKdcwMd7ujueRLdAz/hMmrAM1okt2Nx7vwzNF1GYDhjD3fiMOlAd94q6k/s5dJH0I7xXD3IMWoIJhQcwwLm+mpa+pTAVG6g8ZLbuTk1wdW3DcEubmhX/5ZjTMkZ+YBd3Q83WlbB0vCftBkx4cS5ezn6AVffZY4xgTj8JY4hkbN3O9g1BrS1PcpN6Y9Iv5HcYyFnRWNN+n947ysORTpSSnnkMgac848XqQM4CoLwP+DsykO7Ki6DBeH/gKe/F9x6I5fJg2q3b4a654qxYddT3JRW0D3xA3CPAHqGkvuxR2zcdT81/oWo9WXC9oN/5uaURjR9N8C1D7lMDaj62yPU6R299bxO3puuDlJGfy4nHlL+pov0b/yYhv9NYDiLMHPhXNrcRaYanCm7B2YuzcCSskp0QoKhrStzbumFxMJrJ+/HwcJs0B1tJE3ug9wsxBIuVT9LpgtExo8IRk/pYKiwGLvzH+bN8YWG0gc4ComE1+u2gbXtA1jWnUNX/3e4WRAEQRDSGo2/tZWjEGveu/xb0V5zL12veg1mPzHC+PtIoycJ9AWrpDtiAfWBEWzJ/gP/uhBrYtpFEARBEARBiCJpeCk92i6N+7lJSARE/RZw9hSAQ6Mlk/IObk5NROOp/cx9vEmHIU4WbIpkfYW1f4uTmxBnH0Y0fYubhXBg6/5vUEeughTyH9mW3nxE99VdsGqolx544mYhHKjaswWaXgy4PEA4wKkth5XeZi5TFq4MPySdLuM6z0MNu7/PUTa8Uf8ALLe9yWVaQM/Qr8CpmwWHWg021Wm01D+NxvK7eHPywMXKX3JMS2BtrybLFaLFGqI5fhLCUFLLm4V4AVPVBM18QjRRSjRykmigkEB7tIA3C/FAJsUdMHK6koaKiHpfJ9IeJu9ghVD1ctTfcY4YWpvSc1WSm6D2yD2k+fs+aMkZoeaXiK5kWXhTYtCSYjOZqv/IpRBPYHivXno6msu0gfNVWRyTE+peexwGjtu4TJhYTpjhZNnjOFYScPXGhAL1K0boerWSy4SSpjw4Rkx6UVu6i+fSD+nfsKA2Pzmub9Sc7b3y70ua8T/RtKzlcYKhpdrN670xj52Hn4L2nEW5ayJFFdTtrsTLz4e9DkM8SG+7R+MokOBsdcgHi6HpRTUoX/iIy/ih3OisOotO3U6OUSFdA3B1MuDDUERjsr/uhIxnQy6fsLY2Ut1z8/jZztR6mRuW23o5+pCzZkOgSTJYndBx9IHukSciWQ8Ch4p/yDEk+GxHnvQeNZfJC5dq9qO58Xtc+pD+8sQxJOmcf3MngGdUz9EH2nu+Ds6+vog6oS/vMY6pb22d0IXLC1z6AHd3CcewoGvwkZvP+eAc6uLoQ9rx4Ogwg0MT0dub2JJ9J8fUBlNlEGgH0LJ6Kyy3y5rUQlf/s+Ts+ymXa8DRcwKxO+DSxGBrNdCNZgJLcyM3ZRYcLs7C8fdyuPQBNqUaF1pkfcpgpftNWun2WewJUbWJnB2/4NIHWpQHyFxP3mFmaq2CGC0wUDjF0QeZKreCuXaSy7CBvaPe++P3lzuwNpdy9ANzFUjzlwjnypN7eiHaSJ+7Mdjyj2A6fwHmK2Wv6wnWlmG40eTfAQufHuLoh6YV95GxjGDqbGZ9ARCpcwO+PSI9aUHGDyw0XSHrLla6joC5btJ7OpG93hyNllyh0VOZeRq6GQ0VPwhjpwKO3dcjTRV4j5rrOHsxoqVyaLDQ24cZskDfel+6if3HnsShorBvdj4nLagKUx/bcOpcRAsroa5gG+nytnOZubD3H7/mKIv0LRgwdtpBY2fu4ybZUP1K8k0vx1skN0US7PZ2wHCRi0sh3tauAfoCD5dCIoD2kJujkAjQfqCVo5AIpMz6KkdBEARBEARBEIQUsGHDfwG4Vu3FAK5xRgAAAABJRU5ErkJggg==","","","","","","",""],"frame_max":8,"frames":[[[0,0,0,30,120]],[[0,0,0,50,255]],[[0,0,0,70,255]],[[1,0,0,80,255]],[[1,0,0,90,255]],[[2,0,0,90,120]],[],[]]} \ No newline at end of file diff --git a/project/animates/zone.animate b/project/animates/zone.animate index f13a6b20..8c2b604c 100644 --- a/project/animates/zone.animate +++ b/project/animates/zone.animate @@ -1 +1 @@ -{"ratio":2,"bitmaps":["data:image/png;base64,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","data:image/png;base64,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","","","","","","","",""],"frame_max":6,"frames":[[[0,0,32,30,100]],[[0,0,16,50,130]],[[0,0,0,80,150]],[[0,0,-8,90,180],[1,24,24,100,255]],[[0,0,-8,100,200],[1,24,8,100,255]],[[0,0,-8,100,255]]]} \ No newline at end of file +{"ratio":2,"se":"zone.mp3","bitmaps":["data:image/png;base64,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","data:image/png;base64,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","","","","","","","",""],"frame_max":6,"frames":[[[0,0,32,30,100]],[[0,0,16,50,130]],[[0,0,0,80,150]],[[0,0,-8,90,180],[1,24,24,100,255]],[[0,0,-8,100,200],[1,24,8,100,255]],[[0,0,-8,100,255]]]} \ No newline at end of file diff --git a/project/data.js b/project/data.js index aa989629..247584ff 100644 --- a/project/data.js +++ b/project/data.js @@ -72,12 +72,13 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = "hardLabelColor": "red", "floorChangingBackground": "black", "floorChangingTextColor": "white", - "font": "Verdana" + "font": "Verdana", + "startButtonsStyle": "background-color: #32369F; opacity: 0.85; color: #FFFFFF; border: #FFFFFF 2px solid; caret-color: #FFD700;" }, "firstData": { "title": "魔塔样板", "name": "template", - "version": "Ver 2.6.1", + "version": "Ver 2.6.3", "floorId": "sample0", "hero": { "name": "阳光", @@ -389,11 +390,13 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = "enableDebuff": false, "enableSkill": false, "flyNearStair": true, + "flyRecordPosition": false, "pickaxeFourDirections": false, "bombFourDirections": false, "snowFourDirections": false, "bigKeyIsBox": false, "steelDoorWithoutKey": false, + "itemFirstText": true, "equipment": false, "equipboxButton": false, "iconInEquipbox": false, @@ -417,6 +420,7 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = "enableMoveDirectly": true, "enableDisabledShop": true, "disableShopOnDamage": false, + "blurFg": false, "checkConsole": false } } \ No newline at end of file diff --git a/project/functions.js b/project/functions.js index 13cf4cfc..f09b5bda 100644 --- a/project/functions.js +++ b/project/functions.js @@ -15,6 +15,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = core.status.played = true; // 初始化人物,图标,统计信息 core.status.hero = core.clone(hero); + window.flags = core.status.hero.flags; core.events.setHeroIcon(core.getFlag('heroIcon', 'hero.png'), true); core.control._initStatistics(core.animateFrame.totalTime); core.status.hero.statistics.totalTime = core.animateFrame.totalTime = @@ -112,16 +113,19 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // ---------- 此时还没有进行切换,当前floorId还是原来的 ---------- // var currentId = core.status.floorId || null; // 获得当前的floorId,可能为null + if (!core.hasFlag("__leaveLoc__")) core.setFlag("__leaveLoc__", {}); + if (currentId != null) core.getFlag("__leaveLoc__")[currentId] = core.status.hero.loc; + // 可以对currentId进行判定,比如删除某些自定义图层等 // if (currentId == 'MT0') { // core.deleteAllCanvas(); // } - + // 重置画布尺寸 core.maps.resizeMap(floorId); // 检查重生怪并重置 if (!fromLoad) { - core.status.maps[floorId].blocks.forEach(function(block) { + core.status.maps[floorId].blocks.forEach(function (block) { if (block.disable && core.enemys.hasSpecial(block.event.id, 23)) { block.disable = false; } @@ -133,12 +137,12 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // ---------- 重绘新地图;这一步将会设置core.status.floorId ---------- // core.drawMap(floorId); - + // 切换楼层BGM if (core.status.maps[floorId].bgm) { var bgm = core.status.maps[floorId].bgm; if (bgm instanceof Array) bgm = bgm[0]; - core.playBgm(bgm); + if (!core.hasFlag("__bgm__")) core.playBgm(bgm); } // 更改画面色调 var color = core.getFlag('__color__', null); @@ -184,22 +188,31 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = var fromId = core.status.floorId; // 检查能否飞行 - if (!core.status.maps[fromId].canFlyTo || !core.status.maps[toId].canFlyTo) { + if (!core.status.maps[fromId].canFlyTo || !core.status.maps[toId].canFlyTo || !core.hasVisitedFloor(toId)) { core.drawTip("无法飞往" + core.status.maps[toId].title + "!"); return false; } - // 获得两个楼层的索引,以决定是上楼梯还是下楼梯 - var fromIndex = core.floorIds.indexOf(fromId), - toIndex = core.floorIds.indexOf(toId); - var stair = fromIndex <= toIndex ? "downFloor" : "upFloor"; - // 地下层:同层传送至上楼梯 - if (fromIndex == toIndex && core.status.maps[fromId].underGround) stair = "upFloor"; + // 平面塔模式 + var stair = null, + loc = null; + if (core.flags.flyRecordPosition) { + loc = core.getFlag("__leaveLoc__", {})[toId] || null; + } + if (loc == null) { + // 获得两个楼层的索引,以决定是上楼梯还是下楼梯 + var fromIndex = core.floorIds.indexOf(fromId), + toIndex = core.floorIds.indexOf(toId); + var stair = fromIndex <= toIndex ? "downFloor" : "upFloor"; + // 地下层:同层传送至上楼梯 + if (fromIndex == toIndex && core.status.maps[fromId].underGround) stair = "upFloor"; + } + // 记录录像 core.status.route.push("fly:" + toId); // 传送 core.ui.closePanel(); - core.changeFloor(toId, stair, null, null, callback); + core.changeFloor(toId, stair, loc, null, callback); return true; }, @@ -513,64 +526,72 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = mon_def = hero_atk - 1; } - // 光环检查 - // 从V2.5.4开始,对光环效果增加缓存,以解决多次重复计算的问题,从而大幅提升运行效率。 - // 检查当前楼层所有光环怪物(数字25) - var hp_buff = 0, - atk_buff = 0, - def_buff = 0, - cnt = 0; // ------ 支援 ------ var guards = []; - // 检查光环缓存 - var index = x != null && y != null ? (x + "," + y) : "floor"; - if (!core.status.checkBlock) core.status.checkBlock = {}; - if (!core.status.checkBlock.cache) core.status.checkBlock.cache = {}; - var cache = core.status.checkBlock.cache[index]; - if (!cache) { - // 没有该点的缓存,则遍历每个图块 - core.status.maps[floorId].blocks.forEach(function (block) { - if (!block.disable) { - // 获得该图块的ID - var id = block.event.id, - enemy = core.material.enemys[id]; - // 检查是不是怪物,且是否拥有该特殊属性 - if (enemy && core.hasSpecial(enemy.special, 25)) { - // 检查是否可叠加 - if (enemy.add || cnt == 0) { - hp_buff += enemy.value || 0; - atk_buff += enemy.atkValue || 0; - def_buff += enemy.defValue || 0; - cnt++; - } - } - // 检查【支援】技能 - if (enemy && core.hasSpecial(enemy.special, 26) && - // 检查支援条件,坐标存在,距离为1,且不能是自己 - // 其他类型的支援怪,比如十字之类的话.... 看着做是一样的 - x != null && y != null && Math.abs(block.x - x) <= 1 && Math.abs(block.y - y) <= 1 && !(x == block.x && y == block.y)) { - // 记录怪物的x,y,ID - guards.push([block.x, block.y, id]); - } - // TODO:如果有其他类型光环怪物在这里仿照添加检查 - } - }); - - core.status.checkBlock.cache[index] = { "hp_buff": hp_buff, "atk_buff": atk_buff, "def_buff": def_buff, "guards": guards }; - } else { - // 直接使用缓存数据 - hp_buff = cache.hp_buff; - atk_buff = cache.atk_buff; - def_buff = cache.def_buff; - guards = cache.guards; + // 光环检查 + // 在这里判定是否需要遍历全图(由于光环需要遍历全图,应尽可能不需要以减少计算量,尤其是大地图) + var query = function () { + var floorIds = ["MTx"]; // 在这里给出所有需要遍历的楼层(即有光环或支援等) + return core.inArray(floorIds, floorId); // 也可以写其他的判定条件 } - // 增加比例;如果要增加数值可以直接在这里修改 - mon_hp *= (1 + hp_buff / 100); - mon_atk *= (1 + atk_buff / 100); - mon_def *= (1 + def_buff / 100); + if (query()) { + // 从V2.5.4开始,对光环效果增加缓存,以解决多次重复计算的问题,从而大幅提升运行效率。 + // 检查当前楼层所有光环怪物(数字25) + var hp_buff = 0, + atk_buff = 0, + def_buff = 0, + cnt = 0; + // 检查光环缓存 + var index = x != null && y != null ? (x + "," + y) : "floor"; + if (!core.status.checkBlock) core.status.checkBlock = {}; + if (!core.status.checkBlock.cache) core.status.checkBlock.cache = {}; + var cache = core.status.checkBlock.cache[index]; + if (!cache) { + // 没有该点的缓存,则遍历每个图块 + core.status.maps[floorId].blocks.forEach(function (block) { + if (!block.disable) { + // 获得该图块的ID + var id = block.event.id, + enemy = core.material.enemys[id]; + // 检查是不是怪物,且是否拥有该特殊属性 + if (enemy && core.hasSpecial(enemy.special, 25)) { + // 检查是否可叠加 + if (enemy.add || cnt == 0) { + hp_buff += enemy.value || 0; + atk_buff += enemy.atkValue || 0; + def_buff += enemy.defValue || 0; + cnt++; + } + } + // 检查【支援】技能 + if (enemy && core.hasSpecial(enemy.special, 26) && + // 检查支援条件,坐标存在,距离为1,且不能是自己 + // 其他类型的支援怪,比如十字之类的话.... 看着做是一样的 + x != null && y != null && Math.abs(block.x - x) <= 1 && Math.abs(block.y - y) <= 1 && !(x == block.x && y == block.y)) { + // 记录怪物的x,y,ID + guards.push([block.x, block.y, id]); + } + // TODO:如果有其他类型光环怪物在这里仿照添加检查 + } + }); + + core.status.checkBlock.cache[index] = { "hp_buff": hp_buff, "atk_buff": atk_buff, "def_buff": def_buff, "guards": guards }; + } else { + // 直接使用缓存数据 + hp_buff = cache.hp_buff; + atk_buff = cache.atk_buff; + def_buff = cache.def_buff; + guards = cache.guards; + } + + // 增加比例;如果要增加数值可以直接在这里修改 + mon_hp *= (1 + hp_buff / 100); + mon_atk *= (1 + atk_buff / 100); + mon_def *= (1 + def_buff / 100); + } // TODO:可以在这里新增其他的怪物数据变化 // 比如仿攻(怪物攻击不低于勇士攻击): @@ -913,9 +934,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = "saveData": function () { // 存档操作,此函数应该返回“具体要存档的内容” - // 勇士和hash值(防改存档文件来作弊) - var hero = core.clone(core.status.hero), - hashCode = core.utils.hashCode(hero); // 差异化存储values var values = {}; for (var key in core.values) { @@ -926,16 +944,18 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // 要存档的内容 var data = { 'floorId': core.status.floorId, - 'hero': hero, + 'hero': core.clone(core.status.hero), 'hard': core.status.hard, 'maps': core.maps.saveMap(), 'route': core.encodeRoute(core.status.route), 'values': values, 'shops': {}, 'version': core.firstData.version, - "time": new Date().getTime(), - "hashCode": hashCode + "time": new Date().getTime() }; + if (core.flags.checkConsole) { + data.hashCode = core.utils.hashCode(data.hero); + } // 设置商店次数 for (var shopId in core.status.shops) { data.shops[shopId] = { @@ -972,7 +992,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = var icon = core.getFlag("heroIcon", "hero.png"); icon = core.getMappedName(icon); if (core.material.images.images[icon]) { - core.material.images.hero.src = core.material.images.images[icon].src; + core.material.images.hero = core.material.images.images[icon]; core.material.icons.hero.width = core.material.images.images[icon].width / 4; core.material.icons.hero.height = core.material.images.images[icon].height / 4; } @@ -984,7 +1004,9 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // 切换到对应的楼层 core.changeFloor(data.floorId, null, data.hero.loc, 0, function () { // TODO:可以在这里设置读档后播放BGM - // if (core.getFlag("bgm", 0)==1) core.playBgm("bgm.mp3"); + if (core.hasFlag("__bgm__")) { // 持续播放 + core.playBgm(core.getFlag("__bgm__")); + } if (callback) callback(); }, true); @@ -1222,8 +1244,10 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = if (enemyDamage != null && enemyDamage < value) value = enemyDamage; } - damage[loc] = (damage[loc] || 0) + value; - type[loc] = "夹击伤害"; + if (value > 0) { + damage[loc] = (damage[loc] || 0) + value; + type[loc] = "夹击伤害"; + } } } } @@ -1269,12 +1293,12 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = core.updateStatusBar(); }, - "moveDirectly": function (x, y) { - // 瞬间移动;x,y为要瞬间移动的点 + "moveDirectly": function (x, y, ignoreSteps) { + // 瞬间移动;x,y为要瞬间移动的点;ignoreSteps为减少的步数,可能之前已经被计算过 // 返回true代表成功瞬移,false代表没有成功瞬移 // 判定能否瞬移到该点 - var ignoreSteps = core.canMoveDirectly(x, y); + if (ignoreSteps == null) ignoreSteps = core.canMoveDirectly(x, y); if (ignoreSteps >= 0) { core.clearMap('hero'); // 获得勇士最后的朝向 diff --git a/project/items.js b/project/items.js index bc656898..1c5b4c7f 100644 --- a/project/items.js +++ b/project/items.js @@ -3,15 +3,18 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = "items": { "yellowKey": { "cls": "keys", - "name": "黄钥匙" + "name": "黄钥匙", + "text": "可以打开一扇黄门" }, "blueKey": { "cls": "keys", - "name": "蓝钥匙" + "name": "蓝钥匙", + "text": "可以打开一扇蓝门" }, "redKey": { "cls": "keys", - "name": "红钥匙" + "name": "红钥匙", + "text": "可以打开一扇红门" }, "redJewel": { "cls": "items", diff --git a/server.py b/server.py new file mode 100644 index 00000000..7302d2ad --- /dev/null +++ b/server.py @@ -0,0 +1,153 @@ +# -*- coding: utf-8 -*- + +# HTML5魔塔样板,启动服务Python版 +# 需要安装Python环境,并 pip install flask 安装Flask库 +# 运行方式:python server.py 或 python3 server.py + +import sys +import json +import os +import base64 + +isPy3 = sys.version_info > (3, 0) + +def p(s): # s is unicode in py2 and str in py3 + if isPy3: print(s) + else: print(s.decode('utf-8')) +p("") + +try: + from flask import Flask, request, Response, abort + import mimetypes + import socket +except: + p("需要flask才可使用本服务。\n安装方式:%s install flask" % ("pip3" if isPy3 else "pip")) + exit(1) + +app = Flask(__name__, static_folder='') +app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 0 + +@app.after_request +def add_header(r): + r.headers["Cache-Control"] = "no-cache, no-store, must-revalidate" + r.headers["Pragma"] = "no-cache" + r.headers["Expires"] = "0" + r.headers['Cache-Control'] = 'public, max-age=0' + return r + +def is_sub(filename): + try: + return (os.path.realpath(filename) + os.sep).startswith(os.path.realpath(".") + os.sep) + except: + return True + +def get_mimetype(path): + return mimetypes.guess_type(path)[0] or 'application/octet-stream' + +def get_file(path): + if not os.path.exists(path): + abort(404) + return None + if not is_sub(path): + abort(403) + return None + with open(path, 'rb') as f: + content = f.read() # str in py2 and bytes in py3 + return content + +@app.route('/', methods=['GET']) +def root(): + return static_file('index.html') + +@app.route('/', methods=['GET']) +def static_file(path): + return Response(get_file(path), mimetype = get_mimetype(path)) + +def process_request(): + data = request.get_data() # str in py2 and bytes in py3 + if isPy3: data = str(data, encoding = 'utf-8') + params = data.split("&") + d = {} + for one in params: + index = one.find("=") + if index >= 0: + d[one[:index]] = one[index+1:] + return d # str in py2 & py3 + +@app.route('/readFile', methods=['POST']) +def readFile(): + data = process_request() + tp = data.get('type', 'base64') + filename = data.get('name', None) + content = get_file(filename) + return content if tp == 'utf8' or content is None else base64.b64encode(content) + +@app.route('/writeFile', methods=['POST']) +def writeFile(): + data = process_request() + tp = data.get('type', 'base64') + filename = data.get('name', None) + if not is_sub(filename): + abort(403) + return + value = data.get('value', '') + if isPy3: value = value.encode('utf-8') + if tp == 'base64': value = base64.b64decode(value) + with open(filename, 'wb') as f: + f.write(value) # str in py2 and bytes in py3 + return str(len(value)) + +@app.route('/writeMultiFiles', methods=['POST']) +def writeMultiFiles(): + data = process_request() + filenames = data.get('name', '').split(';') + values = data.get('value', '').split(';') + l = 0 + for i in range(len(filenames)): + if i >= len(values): + break + filename = filenames[i] + value = values[i].encode('utf-8') if isPy3 else values[i] + value = base64.b64decode(value) + if not is_sub(filename): + abort(403) + return + with open(filename, 'wb') as f: + f.write(value) + l += len(value) + return str(l) + +@app.route('/listFile', methods=['POST']) +def listFile(): + data = process_request() + filename = data.get('name', None) + if filename is None or not os.path.isdir(filename): + abort(404) + return + if not is_sub(filename): + abort(403) + return + files = [f + for f in os.listdir(filename) + if os.path.isfile(os.path.join(filename, f))] + return "[" + ", ".join(['"'+f+'"' for f in files]) + "]" + +def port_used(port): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + result = True + try: + sock.bind(("0.0.0.0", port)) + result = False + except: + pass + sock.close() + return result + +if __name__ == '__main__': + port = 1055 + while port_used(port): + port += 1 + if port > 1055: + p("默认的1055端口已被占用,自动选择%d端口。请注意,不同端口下的存档等信息都是不共用的。\n" % port) + p("服务已启动...\n游戏地址:http://127.0.0.1:%d/\n编辑器地址:http://127.0.0.1:%d/editor.html\n" % (port, port)) + app.run(host = '0.0.0.0', port = port, debug = False) diff --git a/styles.css b/styles.css index a1d6649e..3a428992 100644 --- a/styles.css +++ b/styles.css @@ -117,16 +117,25 @@ } #startButtonGroup { - width: 100%; + width: auto; position: absolute; text-align: center; font-size: 1.4rem; - background-color: #000; - opacity: 0.85; display: none; z-index: 310; bottom: 0; - margin-bottom: 7%; + margin-bottom: 5%; + left: 50%; + transform: translateX(-50%); + padding: 15px 25px; + min-width: 20%; + /* default value */ + background-color: #32369F; + opacity: 0.85; + color: #FFFFFF; + border: #FFFFFF 2px solid; + caret-color: #FFD700; + border-radius: 10px; } #startButtons { @@ -139,15 +148,19 @@ .startButton { width: 100%; - margin: 20px 0; - color: #fff; + margin: 0; font-weight: bold; display: block; cursor: pointer; + padding: 4px 0; + border-color: transparent; + border-width: 2px; + border-style: solid; + border-radius: 6px; } -.startButton:hover { - color: #ff0000; +.onChoiceAnimate { + animation: onChoice 2s ease-in-out 0s infinite normal none running; } #floorMsgGroup { @@ -365,4 +378,49 @@ p#name { #inputNo { float:right; margin-right: 10%; +} + +#_selector, #_uievent_selector { + animation: selector 2s ease-in-out 0s infinite normal none running; +} + +@-webkit-keyframes selector { + 0% { opacity: 0.95; } + 50% { opacity: 0.55; } + 100% { opacity: 0.95; } +} + +@keyframes selector { + 0% { opacity: 0.95; } + 50% { opacity: 0.55; } + 100% { opacity: 0.95; } +} + +#next { + width: 5px; + height: 5px; + display: none; + position: absolute; + transform: rotate(45deg); + border-bottom-width: 4px; + border-bottom-style: solid; + border-right-width: 4px; + border-right-style: solid; + -webkit-animation: next .5s ease-in-out alternate infinite; + animation: next .5s ease-in-out alternate infinite; + left: 0; + top: 0; + opacity: 0.7; + z-index: 169; +} + +@-webkit-keyframes next { + 100% { + transform: rotate(45deg) translate(-3px, -3px); + } +} +@keyframes next { + 100% { + transform: rotate(45deg) translate(-3px, -3px); + } } \ No newline at end of file diff --git a/启动服务.exe b/启动服务.exe index f426d69b..2f6786f0 100644 Binary files a/启动服务.exe and b/启动服务.exe differ diff --git a/常用工具/便捷PS工具.exe b/常用工具/便捷PS工具.exe index 90959cf0..893fbfc8 100644 Binary files a/常用工具/便捷PS工具.exe and b/常用工具/便捷PS工具.exe differ diff --git a/常用工具/额外素材合并工具.exe b/常用工具/额外素材合并工具.exe new file mode 100644 index 00000000..169828b1 Binary files /dev/null and b/常用工具/额外素材合并工具.exe differ diff --git a/更新说明.txt b/更新说明.txt index c66b427b..8b3e2419 100644 --- a/更新说明.txt +++ b/更新说明.txt @@ -1,4 +1,41 @@ -HTML5魔塔样板V2.6.1 +HTML5魔塔样板V2.6.3 + +标题界面大幅美化,增加闪烁光标,支持键盘开始游戏 +事件编辑器支持自动补全,能对flag和API列表等进行补全 +剧情文本中\\c修改字体大小,\\d和\\e切换粗体和斜体 +事件:设置视角&移动视角 +可以指定显示选择项的出现条件并动态生成 +楼层传送器的平面传送模式(哪里离开飞回到哪里) +UI绘制事件增添绘制圆和绘制圆边框 +所有的UI绘制事件均可以双击预览 +播放BGM事件可以一直持续播放直到下次调用 +\f立绘支持alpha值 +支持在脚本编辑中直接flags.xxx调用自定义变量 +首次获得道具将给予提示 +等待用户操作支持滚轮,视为PgUp和PgDn +脚本编辑器语法错误将禁止保存 +录像播放时B键查看数据统计 +所有已知bug的修复,大量细节优化 + +----------------------------------------------------------------------- + +HTML5魔塔样板V2.6.2 + +可以拖动地图上的图块和事件,复制剪切和跨楼层粘贴 +新增事件的地图选点功能,可以在地图上选择落点 +现在素材区可以进行折叠与自动换列了 +新增UI绘制系列事件,并且可以进行预览 +显示文本事件的标题解析 +新增常用工具:额外素材合并工具 +进一步提升24倍速的播放速度 +楼层转换增加对称点 +增加编辑器快捷键说明,H键查看 +文档-事件增加事件编辑器截图 +大量细节优化,所有已知的Bug修复 + +----------------------------------------------------------------------- + +HTML5魔塔样板V2.6.1 区域优化的录像播放功能,R键使用 强制战斗可以指定怪物坐标,将自动隐藏并执行该点战后事件