Merge pull request #382 from ckcz123/v2.x

V2.x
This commit is contained in:
Zhang Chen 2019-07-05 00:52:16 +08:00 committed by GitHub
commit d678669dc0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 1018 additions and 241 deletions

View File

@ -1742,7 +1742,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 +1767,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 +1782,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 +1790,7 @@ showAll可选如果为true则不会使用打字机效果而全部显示
core.drawScrollText(content, time, lineHeight, callback)
绘制一个滚动字幕。content为绘制内容time为总时间默认为5000lineHeight为行距比例默认为1.4)。
滚动字幕将绘制在UI上支持所有的文字效果如\n${}\r\\i等但不支持\t和\b效果。
滚动字幕将绘制在UI上支持所有的文字效果如\n${}\r\\i\\c\\d\\e等),但不支持\t和\b效果。
可以通过剧情文本设置中的align控制是否居中绘制offset控制其距离左边的偏移量。
@ -1802,7 +1802,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的对象。

View File

@ -55,6 +55,19 @@ HTML5 canvas制作的魔塔样板支持全平台游戏
## 更新说明
### 2019.7.5 V2.6.3
* [x] 事件编辑器支持自动补全能对flag和API列表等进行补全
* [x] 剧情文本中\\c修改字体大小\\d和\\e切换粗体和斜体
* [x] 楼层传送器的平面传送模式(哪里离开飞回到哪里)
* [x] UI绘制事件增添绘制圆和绘制圆边框
* [x] 所有的UI绘制事件均可以双击预览
* [x] \f立绘支持alpha值
* [x] 等待用户操作支持滚轮视为PgUp和PgDn
* [x] 脚本编辑器语法错误将禁止保存
* [x] 录像播放时B键查看数据统计
* [x] 所有已知bug的修复大量细节优化
### 2019.6.7 V2.6.2
* [x] 可以拖动地图上的图块和事件,复制剪切和跨楼层粘贴

View File

@ -1,6 +1,6 @@
# V2.0版本介绍
?> 目前版本**v2.6.2**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.6.3*,上次更新时间:* {docsify-updated} *
目前样板已经更新到V2.0版本以上本章将对V2.0的一些内容进行介绍。

View File

@ -1,6 +1,6 @@
# 附录API列表
?> 目前版本**v2.6.2**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.6.3**,上次更新时间:* {docsify-updated} *
这里将列出所有被转发到core的API没有被转发的函数此处不会列出请自行在代码中查看。
@ -1721,7 +1721,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()插入剧情文本事件。
@ -1746,7 +1746,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',因此只需要考虑第一个字的左上角位置。
@ -1761,7 +1762,7 @@ config为绘制的配置项目前可以包括如下几项
core.drawTextBox(content, showAll)
绘制一个对话框。content为一个字符串或一个字符串数组。
支持所有的文字效果(如\n${}\r\\i等也支持\t和\b的语法。
支持所有的文字效果(如\n${}\r\\i\\c\\d\\e等),也支持\t和\b的语法。
该函数将使用用户在剧情文本设置中的配置项进行绘制。
实际执行时会计算文本框宽度并绘制背景绘制标题和头像再调用core.drawTextContent()绘制正文内容。
showAll可选如果为true则不会使用打字机效果而全部显示主要用于打字机效果的点击显示全部。
@ -1769,7 +1770,7 @@ showAll可选如果为true则不会使用打字机效果而全部显示
core.drawScrollText(content, time, lineHeight, callback)
绘制一个滚动字幕。content为绘制内容time为总时间默认为5000lineHeight为行距比例默认为1.4)。
滚动字幕将绘制在UI上支持所有的文字效果如\n${}\r\\i等但不支持\t和\b效果。
滚动字幕将绘制在UI上支持所有的文字效果如\n${}\r\\i\\c\\d\\e等),但不支持\t和\b效果。
可以通过剧情文本设置中的align控制是否居中绘制offset控制其距离左边的偏移量。
@ -1781,7 +1782,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的对象。

View File

@ -1,6 +1,6 @@
# 元件说明
?> 目前版本**v2.6.2**,上次更新时间:* {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显示一段文字剧情)中的说明。

View File

@ -1,6 +1,6 @@
# 事件
?> 目前版本**v2.6.2**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.6.3**,上次更新时间:* {docsify-updated} *
本章内将对样板所支持的事件进行介绍。
@ -258,6 +258,8 @@
其基本写法是`\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
@ -265,7 +267,8 @@
"\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",
]
```
@ -288,6 +291,18 @@
!> 注意,在事件块中,允许只写一个反斜杠`\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
@ -1998,7 +2013,7 @@ UI绘制事件。
]
```
text必填为要绘制的文本支持所有的文字效果如\n${}\r\\i等但不支持支持\t和\b的语法。
text必填为要绘制的文本支持所有的文字效果如\n${}\r\\i\\c\\d\\e等),但不支持支持\t和\b的语法。
left和top必填为要绘制的起始像素坐标。实际绘制时会将textBaseline设置为'top',因此只需要考虑第一个字的左上角位置。
@ -2088,6 +2103,26 @@ 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绘制事件。此事件可以绘制一个图片。

View File

@ -1,6 +1,6 @@
# HTML5 魔塔样板说明文档
?> 目前版本**v2.6.2**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.6.3**,上次更新时间:* {docsify-updated} *
众所周知魔塔的趋势是向移动端发展贴吧中也常常能见到“求手机魔塔”的帖子。然而现有的工具中NekoRPG有着比较大的局限性游戏感较差更是完全没法在iOS上运行。而一些APP的魔塔虽然可用但是必须要下载安装对于Android和iOS还必须开发不同的版本非常麻烦。

View File

@ -1,6 +1,6 @@
# 个性化
?> 目前版本**v2.6.2**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.6.3**,上次更新时间:* {docsify-updated} *
有时候只靠样板本身可能是不够的。我们需要一些个性化、自定义的素材,道具效果,怪物属性,等等。

View File

@ -1,6 +1,6 @@
# 脚本
?> 目前版本**v2.6.2**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.6.3**,上次更新时间:* {docsify-updated} *
在V2.6版本中,基本对整个项目代码进行了重写,更加方便造塔者的使用和复写函数。

View File

@ -1,6 +1,6 @@
# 快速上手
?> 目前版本**v2.6.2**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.6.3**,上次更新时间:* {docsify-updated} *
在这一节中,将详细介绍做一部塔的流程。现在,让我们来做一部单层塔!

View File

@ -354,6 +354,8 @@ action
| drawArrow_s
| fillPolygon_s
| strokePolygon_s
| fillCircle_s
| strokeCircle_s
| drawImage_s
| drawImage_1_s
| drawIcon_s
@ -2168,6 +2170,45 @@ var code = '{"type": "strokePolygon", "nodes": ['+EvalString_0+']'+EvalString_2+
return code;
*/;
fillCircle_s
: '绘制圆' '圆心' 'x' PosString 'y' PosString '半径' PosString '颜色' EvalString? Colour Newline
/* fillCircle_s
tooltip : fillCircle绘制圆
helpUrl : https://h5mota.com/games/template/_docs/#/event?id=fillCircle%ef%bc%9a%e7%bb%98%e5%88%b6%e5%9c%86
colour : this.subColor
default : ["0","0","100","",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": "fillCircle", "x": '+PosString_0+', "y": '+PosString_1+', "r": '+PosString_2+EvalString_0+'},\n';
return code;
*/;
strokeCircle_s
: '绘制圆边框' '圆心' 'x' PosString 'y' PosString '半径' PosString '颜色' EvalString? Colour '线宽' EvalString? Newline
/* strokeCircle_s
tooltip : strokeCircle绘制圆边框
helpUrl : https://h5mota.com/games/template/_docs/#/event?id=strokeCircle%ef%bc%9a%e7%bb%98%e5%88%b6%e5%9c%86%e8%be%b9%e6%a1%86
colour : this.subColor
default : ["0","0","100","",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": "strokeCircle", "x": '+PosString_0+', "y": '+PosString_1+', "r": '+PosString_2+EvalString_0+EvalString_1+'},\n';
return code;
*/;
drawImage_s
: '绘制图片' EvalString '起点像素' 'x' PosString 'y' PosString '宽' PosString? '高' PosString? Newline
@ -2495,8 +2536,8 @@ Global_Value_List
Global_Flag_List
: '显示当前楼层'|'显示勇士图标'|'显示当前等级'|'启用生命上限'|'显示魔力值'|'显示魔防值'|'显示金币值'|'显示经验值'|'允许等级提升'|'升级扣除模式'|'显示钥匙数量'|'显示破炸飞'|'显示毒衰咒'|'显示当前技能'|'楼梯边才能楼传'|'破墙镐四方向'|'炸弹四方向'|'冰冻徽章四方向'|'铁门不需要钥匙'|'开启加点'|'开启负伤'|'仇恨怪战后扣减一半'|'夹击是否上整'|'夹击不超伤害值'|'循环计算临界'|'允许轻按'|'寻路算法不绕血瓶'|'允许走到将死领域'|'允许瞬间移动'|'允许查看禁用商店'|'阻激夹域后禁用快捷商店'|'检查控制台'
/*Global_Flag_List ['enableFloor','enableName','enableLv', 'enableHPMax', 'enableMana', 'enableMDef', 'enableMoney', 'enableExperience', 'enableLevelUp', 'levelUpLeftMode', 'enableKeys', 'enablePZF', 'enableDebuff', 'enableSkill', 'flyNearStair', 'pickaxeFourDirections', 'bombFourDirections', 'snowFourDirections', 'steelDoorWithoutKey', 'enableAddPoint', 'enableNegativeDamage', 'hatredDecrease', 'betweenAttackCeil', 'betweenAttackMax', 'useLoop', 'enableGentleClick', 'potionWhileRouting', 'canGoDeadZone', 'enableMoveDirectly', 'enableDisabledShop', 'disableShopOnDamage', 'checkConsole']*/;
: '显示当前楼层'|'显示勇士图标'|'显示当前等级'|'启用生命上限'|'显示魔力值'|'显示魔防值'|'显示金币值'|'显示经验值'|'允许等级提升'|'升级扣除模式'|'显示钥匙数量'|'显示破炸飞'|'显示毒衰咒'|'显示当前技能'|'楼梯边才能楼传'|'楼传平面塔模式'|'破墙镐四方向'|'炸弹四方向'|'冰冻徽章四方向'|'铁门不需要钥匙'|'开启加点'|'开启负伤'|'仇恨怪战后扣减一半'|'夹击是否上整'|'夹击不超伤害值'|'循环计算临界'|'允许轻按'|'寻路算法不绕血瓶'|'允许走到将死领域'|'允许瞬间移动'|'允许查看禁用商店'|'阻激夹域后禁用快捷商店'|'检查控制台'
/*Global_Flag_List ['enableFloor','enableName','enableLv', 'enableHPMax', 'enableMana', 'enableMDef', 'enableMoney', 'enableExperience', 'enableLevelUp', 'levelUpLeftMode', 'enableKeys', 'enablePZF', 'enableDebuff', 'enableSkill', 'flyNearStair', 'flyRecordPosition', 'pickaxeFourDirections', 'bombFourDirections', 'snowFourDirections', 'steelDoorWithoutKey', 'enableAddPoint', 'enableNegativeDamage', 'hatredDecrease', 'betweenAttackCeil', 'betweenAttackMax', 'useLoop', 'enableGentleClick', 'potionWhileRouting', 'canGoDeadZone', 'enableMoveDirectly', 'enableDisabledShop', 'disableShopOnDamage', 'checkConsole']*/;
Colour
: 'sdeirughvuiyasdeb'+ //为了被识别为复杂词法规则
@ -3314,6 +3355,18 @@ ActionParser.prototype.parseAction = function() {
x_str.join(','), y_str.join(','), data.style, 'rgba('+data.style+')', data.lineWidth, this.next
]);
break;
case "fillCircle": // 绘制圆
data.style = this.Colour(data.style);
this.next = MotaActionBlocks['fillCircle_s'].xmlText([
data.x, data.y, data.r, data.style, 'rgba('+data.style+')', this.next
]);
break;
case "strokeCircle": // 绘制圆边框
data.style = this.Colour(data.style);
this.next = MotaActionBlocks['strokeCircle_s'].xmlText([
data.x, data.y, data.r, data.style, 'rgba('+data.style+')', data.lineWidth, this.next
]);
break;
case "drawImage": // 绘制图片
if (data.x1 != null && data.y1 != null && data.w1 != null && data.h1 != null) {
this.next = MotaActionBlocks['drawImage_1_s'].xmlText([

View File

@ -1,21 +0,0 @@
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.

View File

@ -98,6 +98,12 @@ editor.prototype.init = function (callback) {
editor_multi = editor_multi();
editor_blockly = editor_blockly();
// --- 所有用到的flags
editor.used_flags = {};
for (var floorId in editor.main.floors) {
editor.addUsedFlags(JSON.stringify(editor.main.floors[floorId]));
}
if (editor.useCompress == null) editor.useCompress = useCompress;
if (Boolean(callback)) callback();
@ -574,5 +580,10 @@ editor.prototype.clearPos = function (clearPos, pos, 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();

View File

@ -183,6 +183,8 @@ editor_blockly = function () {
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(),
@ -387,7 +389,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));
@ -530,8 +532,7 @@ function omitedcheckUpdateFunction(event) {
MotaActionFunctions.parse(
eval('obj=' + codeAreaHL.getValue().replace(/[<>&]/g, function (c) {
return {'<': '&lt;', '>': '&gt;', '&': '&amp;'}[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
);
}
@ -605,25 +606,39 @@ 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));
}
editor_blockly.doubleClickBlock = function (blockId) {
var b = editor_blockly.workspace.getBlockById(blockId);
// console.log(Blockly.JavaScript.blockToCode(b));
if (b && b.type == 'previewUI_s') { // previewUI
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/g, '\\\\i') + "]";
var code = "[" + Blockly.JavaScript.blockToCode(b).replace(/\\(i|c|d|e)/g, '\\\\$1') + "]";
eval("var obj="+code);
// console.log(obj);
if (obj.length > 0 && obj[0].type == 'previewUI') {
uievent.previewUI(obj[0].action);
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;
return true;
}
return false;
}
editor_blockly.doubleClickBlock = function (blockId) {
var b = editor_blockly.workspace.getBlockById(blockId);
if (previewBlock(b)) return;
if (b && b.type in selectPointBlocks) { // selectPoint
this.selectPoint();
return;
@ -782,6 +797,218 @@ function omitedcheckUpdateFunction(event) {
});
}
editor_blockly.getAutoCompletions = function (content) {
// --- content为当前框中输入内容将返回一个列表为后续所有可补全内容
// 检查 flag:xxxitem: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();
// --- 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 {
// --- 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"), "<mark>$&</mark>");
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);
};

View File

@ -41,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);
});
}

View File

@ -81,6 +81,12 @@ editor_multi = function () {
_format();
}
editor_multi.hasError = function () {
if (!editor_multi.lintAutocomplete) return false;
return JSHINT.errors.filter(function (e) {
return e.code.startsWith("E")
}).length > 0;
}
editor_multi.import = function (id_, args) {
var thisTr = document.getElementById(id_);
@ -126,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;

View File

@ -362,6 +362,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()) {
@ -372,6 +373,7 @@ editor.constructor.prototype.listen=function () {
editor.updateMap();
currDrawData = JSON.parse(JSON.stringify(reDo));
reDo = null;
return;
}
// PGUP和PGDOWN切换楼层

View File

@ -508,6 +508,10 @@ 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);

View File

@ -515,7 +515,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,

60
_server/thirdparty/LICENSE.md vendored Normal file
View File

@ -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.

104
_server/thirdparty/awesomplete.css vendored Normal file
View File

@ -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 */

3
_server/thirdparty/awesomplete.min.js vendored Normal file

File diff suppressed because one or more lines are too long

155
_server/thirdparty/caret-position.js vendored Normal file
View File

@ -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 <input>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 <span> 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;
}
}());

View File

@ -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,89 +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颜色
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;
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);
};

View File

@ -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)});

File diff suppressed because one or more lines are too long

View File

@ -5,6 +5,7 @@
<meta name="viewport" content="width=device-width,minimum-scale=1,maximum-scale=1,initial-scale=1,user-scalable=no" />
<link href="_server/css/editor_mobile.css" rel="stylesheet">
<link href="_server/CodeMirror/codemirror.css" rel="stylesheet">
<link href="_server/thirdparty/awesomplete.css" rel="stylesheet">
<link href="_server/css/editor_mode_mobile.css" rel="stylesheet">
</head>
<body>
@ -598,9 +599,11 @@
<script src="_server/CodeMirror/jshint.min.js"></script>
<script src="_server/CodeMirror/beautify.min.js"></script>
<script src="_server/CodeMirror/codeMirror.plugin.min.js"></script>
<!-- colorPicker -->
<script type="text/javascript" src="_server/colorPicker/color.all.min.js"></script>
<script type="text/javascript" src="_server/colorPicker/jsColor.js"></script>
<!-- thirdparty -->
<script src="_server/thirdparty/color.all.min.js"></script>
<script src="_server/thirdparty/awesomplete.min.js"></script>
<script src="_server/thirdparty/caret-position.js"></script>
<script src="_server/thirdparty/jsColor.js"></script>
</body>
</html>

View File

@ -4,6 +4,7 @@
<meta charset="utf-8">
<link href="_server/css/editor.css" rel="stylesheet">
<link href="_server/CodeMirror/codemirror.css" rel="stylesheet">
<link href="_server/thirdparty/awesomplete.css" rel="stylesheet">
<link href="_server/css/editor_mode.css" rel="stylesheet">
</head>
<body>
@ -582,9 +583,11 @@
<script src="_server/CodeMirror/jshint.min.js"></script>
<script src="_server/CodeMirror/beautify.min.js"></script>
<script src="_server/CodeMirror/codeMirror.plugin.min.js"></script>
<!-- colorPicker -->
<script type="text/javascript" src="_server/colorPicker/color.all.min.js"></script>
<script type="text/javascript" src="_server/colorPicker/jsColor.js"></script>
<!-- thirdparty -->
<script src="_server/thirdparty/color.all.min.js"></script>
<script src="_server/thirdparty/awesomplete.min.js"></script>
<script src="_server/thirdparty/caret-position.js"></script>
<script src="_server/thirdparty/jsColor.js"></script>
</body>
</html>

View File

@ -152,7 +152,7 @@
<div id='inputDiv'>
<div id='inputDialog'>
<p id="inputMessage">请输入文字...</p>
<input id='inputBox' type="text"/>
<input id='inputBox' type="text" autocomplete="off"/>
<button id='inputYes'>确定</button>
<button id='inputNo'>取消</button>
</div>

View File

@ -112,9 +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'
&& core.status.event.id != 'toolbox' && core.status.event.id != 'equipbox')
if (core.isReplaying() &&
['save','book','book-detail','viewMaps','toolbox','equipbox','text'].indexOf(core.status.event.id)<0)
return true;
return false;
}
@ -175,6 +174,8 @@ actions.prototype._sys_onkeyUp_replay = function (e) {
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
@ -717,6 +718,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键时 //////

View File

@ -751,25 +751,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;
}
////// 绘制勇士 //////
@ -1202,6 +1205,7 @@ 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')

View File

@ -1660,6 +1660,16 @@ events.prototype._action_strokePolygon = function (data, x, y, prefix) {
core.doAction();
}
events.prototype._action_fillCircle = function (data, x, y, prefix) {
core.ui._uievent_fillCircle(data);
core.doAction();
}
events.prototype._action_strokeCircle = function (data, x, y, prefix) {
core.ui._uievent_strokeCircle(data);
core.doAction();
}
events.prototype._action_drawLine = function (data, x, y, prefix) {
core.ui._uievent_drawLine(data);
core.doAction();

View File

@ -486,14 +486,39 @@ maps.prototype._canMoveHero_checkCannotInOut = function (number, 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 () {
@ -519,7 +544,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);
// 滑冰
@ -538,12 +563,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) {
@ -739,6 +774,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);
// ------ 调整这两行的顺序来控制是先绘制贴图还是先绘制背景图块;后绘制的覆盖先绘制的。
@ -778,7 +814,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);
@ -826,7 +865,6 @@ maps.prototype._drawFloorImages = function (floorId, ctx, name, images, currStat
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);
@ -1170,9 +1208,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;
}
////// 当前位置是否在楼梯边 //////

View File

@ -189,6 +189,37 @@ ui.prototype._uievent_strokePolygon = function (data) {
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);
@ -395,7 +426,12 @@ ui.prototype.drawIcon = function (name, id, x, y, w, h) {
ui.prototype._uievent_drawIcon = function (data) {
this._createUIEvent();
this.drawIcon('uievent', data.id, core.calValue(data.x), core.calValue(data.y), core.calValue(data.width), core.calValue(data.height));
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绘制
@ -503,7 +539,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;
}
@ -810,31 +847,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 || 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);
@ -842,21 +879,23 @@ 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) {
@ -874,13 +913,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) {
@ -894,6 +936,8 @@ ui.prototype._drawTextContent_draw = function (ctx, tempCtx, content, config) {
}
}, config.time);
}
return config;
}
ui.prototype._drawTextContent_next = function (tempCtx, content, config) {
@ -919,9 +963,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);
@ -931,10 +988,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;
}
@ -949,12 +1007,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++;
}
@ -972,6 +1035,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;
@ -981,17 +1060,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;
@ -1000,8 +1080,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");
}
////// 绘制一个对话框 //////
@ -1035,7 +1119,7 @@ ui.prototype.drawTextBox = function(content, showAll) {
var content_top = this._drawTextBox_drawTitleAndIcon(titleInfo, hPos, vPos, alpha);
// Step 5: 绘制正文
this.drawTextContent('ui', content, {
return 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
});
@ -1053,8 +1137,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 "";
});
}
@ -1083,8 +1170,9 @@ 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 + 6;
var realContent = this._getRealContent(content);
var height = 30 + lineHeight * core.splitLines("ui", realContent, validWidth, this._buildFont()).length;
var height = 30 + 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);
@ -1165,9 +1253,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;
@ -1267,10 +1353,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);
@ -1830,11 +1916,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) {
@ -2528,6 +2622,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),
@ -2545,6 +2640,7 @@ ui.prototype.drawStatistics = function (floorIds) {
"4. 在自定义道具例如其他宝石需在脚本编辑的drawStatistics中注册不然不会进行统计。\n"+
"5. 所有统计信息仅供参考,如有错误,概不负责。"
])
core.removeFlag("__replayText__");
}
ui.prototype._drawStatistics_buildObj = function () {

View File

@ -915,6 +915,7 @@ utils.prototype.myconfirm = function (hint, yesCallback, noCallback) {
main.dom.inputMessage.innerHTML = hint.replace(/\n/g, '<br/>');
main.dom.inputBox.style.display = 'none';
main.dom.inputYes.focus();
core.status.holdingKeys = [];
core.platform.successCallback = yesCallback;
core.platform.errorCallback = noCallback;
@ -929,6 +930,7 @@ utils.prototype.myprompt = function (hint, value, callback) {
setTimeout(function () {
main.dom.inputBox.focus();
});
core.status.holdingKeys = [];
core.platform.successCallback = core.platform.errorCallback = callback;
}
@ -1084,7 +1086,7 @@ 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) {
@ -1100,7 +1102,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

View File

@ -2,7 +2,7 @@ function main() {
//------------------------ 用户修改内容 ------------------------//
this.version = "2.6.2"; // 游戏版本号如果更改了游戏内容建议修改此version以免造成缓存问题。
this.version = "2.6.3"; // 游戏版本号如果更改了游戏内容建议修改此version以免造成缓存问题。
this.useCompress = false; // 是否使用压缩文件
// 当你即将发布你的塔时请使用“JS代码压缩工具”将所有js代码进行压缩然后将这里的useCompress改为true。
@ -188,8 +188,8 @@ function main() {
this.floors = {}
this.canvas = {};
this.__VERSION__ = "2.6.2";
this.__VERSION_CODE__ = 54;
this.__VERSION__ = "2.6.3";
this.__VERSION_CODE__ = 63;
}
main.prototype.init = function (mode, callback) {

View File

@ -77,7 +77,7 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
"firstData": {
"title": "魔塔样板",
"name": "template",
"version": "Ver 2.6.2",
"version": "Ver 2.6.3",
"floorId": "sample0",
"hero": {
"name": "阳光",
@ -389,6 +389,7 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
"enableDebuff": false,
"enableSkill": false,
"flyNearStair": true,
"flyRecordPosition": false,
"pickaxeFourDirections": false,
"bombFourDirections": false,
"snowFourDirections": false,

View File

@ -112,16 +112,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,7 +136,7 @@ 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;
@ -189,17 +192,26 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
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;
},
@ -1278,12 +1290,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');
// 获得勇士最后的朝向

View File

@ -1,4 +1,19 @@
HTML5魔塔样板V2.6.2
HTML5魔塔样板V2.6.3
事件编辑器支持自动补全能对flag和API列表等进行补全
剧情文本中\\c修改字体大小\\d和\\e切换粗体和斜体
楼层传送器的平面传送模式(哪里离开飞回到哪里)
UI绘制事件增添绘制圆和绘制圆边框
所有的UI绘制事件均可以双击预览
\f立绘支持alpha值
等待用户操作支持滚轮视为PgUp和PgDn
脚本编辑器语法错误将禁止保存
录像播放时B键查看数据统计
所有已知bug的修复大量细节优化
-----------------------------------------------------------------------
HTML5魔塔样板V2.6.2
可以拖动地图上的图块和事件,复制剪切和跨楼层粘贴
新增事件的地图选点功能,可以在地图上选择落点