Merge remote-tracking branch 'refs/remotes/ckcz123/v2.0' into refactoring-editor
This commit is contained in:
commit
16930841ce
@ -3,5 +3,4 @@
|
||||
- [元件说明](element)
|
||||
- [事件](event)
|
||||
- [个性化](personalization)
|
||||
- [V2.0版本介绍](V2.0)
|
||||
- [附录:API列表](api)
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# 元件说明
|
||||
|
||||
?> 目前版本**v2.5.5**,上次更新时间:* {docsify-updated} *
|
||||
?> 目前版本**v2.6**,上次更新时间:* {docsify-updated} *
|
||||
|
||||
在本章中,将对样板里的各个元件进行说明。各个元件主要包括道具、门、怪物、楼梯等等。
|
||||
|
||||
@ -56,6 +56,8 @@ type为该装备的类型,必填,和上面装备栏一一对应。例如,0
|
||||
|
||||
atk/def/mdef为该装备分别增加的攻防魔防数值(支持负数);如果不加也可省略不写。
|
||||
|
||||
从V2.6开始,可以拓展到任何勇士的属性,如hpmax, atk, def, mdef, experience等等;自行添加的属性包括攻速speed也能使用。
|
||||
|
||||
animate为该装备的攻击动画,仅对type为0时有效。具体可参见[动画和天气系统](#动画和天气系统)。
|
||||
|
||||
percentage为该装备是否按比例增加属性。
|
||||
@ -151,49 +153,13 @@ yellowWall, blueWall, whiteWall
|
||||
|
||||
怪物的特殊属性所对应的数字(special)在脚本编辑中的`getSpecials`中定义,请勿对已有的属性进行修改。
|
||||
|
||||
``` js
|
||||
function() {
|
||||
// 获得怪物的特殊属性,每一行定义一个特殊属性。
|
||||
// 分为三项,第一项为该特殊属性的数字,第二项为特殊属性的名字,第三项为特殊属性的描述
|
||||
// 可以直接写字符串,也可以写个function将怪物传进去
|
||||
return [
|
||||
[1, "先攻", "怪物首先攻击"],
|
||||
[2, "魔攻", "怪物无视勇士的防御"],
|
||||
[3, "坚固", "勇士每回合最多只能对怪物造成1点伤害"],
|
||||
[4, "2连击", "怪物每回合攻击2次"],
|
||||
[5, "3连击", "怪物每回合攻击3次"],
|
||||
[6, function(enemy) {return (enemy.n||4)+"连击";}, function(enemy) {return "怪物每回合攻击"+(enemy.n||4)+"次";}],
|
||||
[7, "破甲", "战斗前,怪物附加角色防御的"+Math.floor(100*core.values.breakArmor||0)+"%作为伤害"],
|
||||
[8, "反击", "战斗时,怪物每回合附加角色攻击的"+Math.floor(100*core.values.counterAttack||0)+"%作为伤害,无视角色防御"],
|
||||
[9, "净化", "战斗前,怪物附加勇士魔防的"+core.values.purify+"倍作为伤害"],
|
||||
[10, "模仿", "怪物的攻防和勇士攻防相等"],
|
||||
[11, "吸血", function (enemy) {return "战斗前,怪物首先吸取角色的"+Math.floor(100*enemy.value||0)+"%生命作为伤害"+(enemy.add?",并把伤害数值加到自身生命上":"");}],
|
||||
[12, "中毒", "战斗后,勇士陷入中毒状态,每一步损失生命"+core.values.poisonDamage+"点"],
|
||||
[13, "衰弱", "战斗后,勇士陷入衰弱状态,攻防暂时下降"+(core.values.weakValue>=1?core.values.weakValue+"点":parseInt(core.values.weakValue*100)+"%")],
|
||||
[14, "诅咒", "战斗后,勇士陷入诅咒状态,战斗无法获得金币和经验"],
|
||||
[15, "领域", function (enemy) {return "经过怪物周围"+(enemy.range||1)+"格时自动减生命"+(enemy.value||0)+"点";}],
|
||||
[16, "夹击", "经过两只相同的怪物中间,勇士生命值变成一半"],
|
||||
[17, "仇恨", "战斗前,怪物附加之前积累的仇恨值作为伤害"+(core.flags.hatredDecrease?";战斗后,释放一半的仇恨值":"")+"。(每杀死一个怪物获得"+(core.values.hatred||0)+"点仇恨值)"],
|
||||
[18, "阻击", function (enemy) {return "经过怪物的十字领域时自动减生命"+(enemy.value||0)+"点,同时怪物后退一格";}],
|
||||
[19, "自爆", "战斗后勇士的生命值变成1"],
|
||||
[20, "无敌", "勇士无法打败怪物,除非拥有十字架"],
|
||||
[21, "退化", function (enemy) {return "战斗后勇士永久下降"+(enemy.atkValue||0)+"点攻击和"+(enemy.defValue||0)+"点防御";}],
|
||||
[22, "固伤", function (enemy) {return "战斗前,怪物对勇士造成"+(enemy.damage||0)+"点固定伤害,无视勇士魔防。";}],
|
||||
[23, "重生", "怪物被击败后,角色转换楼层则怪物将再次出现"],
|
||||
[24, "激光", function (enemy) {return "经过怪物同行或同列时自动减生命"+(enemy.value||0)+"点";}]
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
多属性可采用数组的写法,比如`'special': [1,3]`视为同时拥有先攻和坚固属性;`'special': [5,10,14,18]`视为拥有3连击、魔防、诅咒、阻击四个属性。
|
||||
|
||||
怪物可以负伤,在`data.js`的全局变量`enableNegativeDamage`中指定。
|
||||
|
||||
下面的`getSpecialHint`函数则给定了每个特殊属性的详细描述。这个描述将在怪物手册中看到。
|
||||
怪物可以负伤,在全塔属性的全局变量`enableNegativeDamage`中指定。
|
||||
|
||||
打败怪物后可以进行加点操作。有关加点塔的制作可参见[加点事件](event#加点事件)。
|
||||
|
||||
如果`data.js`中的enableExperience为false,即不启用经验的话,怪物手册里将不显示怪物的经验值,打败怪物也不获得任何经验。
|
||||
如果全塔属性中的enableExperience为false,即不启用经验的话,怪物手册里将不显示怪物的经验值,打败怪物也不获得任何经验。
|
||||
|
||||
拿到幸运金币后,打怪获得的金币将翻倍。
|
||||
|
||||
@ -286,16 +252,12 @@ N连击怪物的special是6,且我们可以为它定义n代表实际连击数
|
||||
|
||||
## 路障,楼梯,传送门
|
||||
|
||||
血网的伤害数值、中毒后每步伤害数值、衰弱时暂时攻防下降的数值,都在 `data.js` 的values内定义。
|
||||
血网的伤害数值、中毒后每步伤害数值、衰弱时暂时攻防下降的数值,都在全塔属性的values内定义。
|
||||
|
||||
路障同样会尽量被自动寻路绕过。
|
||||
|
||||
有关楼梯和传送门,必须在该层样板的changeFloor里指定传送点的目标。
|
||||
|
||||

|
||||
|
||||
!> **请注意这里的`"x,y"`代表该点的横坐标为x,纵坐标为y;即从左到右第x列,从上到下的第y行(从0开始计算)。如(6,0)代表最上面一行的正中间一列。**
|
||||
|
||||
floorId指定的是目标楼层的唯一标识符(ID)。
|
||||
|
||||
也可以写`"floorId": ":before"`和`"floorId": ":next"`表示上一楼和下一楼。
|
||||
@ -347,7 +309,7 @@ floorId指定的是目标楼层的唯一标识符(ID)。
|
||||
|
||||
从V2.4开始,H5魔塔开始支持大地图。
|
||||
|
||||
大地图在创建时可以指定宽高,要求**宽和高都不得小于13,且宽高之积不超过1000**。
|
||||
大地图在创建时可以指定宽高,要求**宽和高都不得小于13(15x15版本则是不小于15),且宽高之积不超过1000**。
|
||||
|
||||
大地图一旦创建成功则不得修改宽高数值。
|
||||
|
||||
@ -355,13 +317,12 @@ floorId指定的是目标楼层的唯一标识符(ID)。
|
||||
|
||||
现在我们的H5魔塔支持播放动画,也支持天气系统了。
|
||||
|
||||
要播放动画,你需要先使用“RM动画导出器”将动画导出,放在animates目录下,然后再data.js中定义。
|
||||
要播放动画,你需要先使用“RM动画导出器”将动画导出,放在animates目录下,然后在全塔属性的animates中定义。
|
||||
|
||||
``` js
|
||||
"animates": [// 在此存放所有可能使用的动画,必须是animate格式,在这里不写后缀名
|
||||
// 动画必须放在animates目录下;文件名不能使用中文,不能带空格或特殊字符
|
||||
"hand", "sword", "zone", "yongchang", "thunder" // 根据需求自行添加
|
||||
]
|
||||
// 在此存放所有可能使用的动画,必须是animate格式,在这里不写后缀名
|
||||
// 动画必须放在animates目录下;文件名不能使用中文,不能带空格或特殊字符
|
||||
"animates": ["hand", "sword", "zone", "yongchang", "thunder"]
|
||||
```
|
||||
|
||||
!> 动画必须是animate格式,名称不能使用中文,不能带空格或特殊字符。
|
||||
@ -376,9 +337,9 @@ floorId指定的是目标楼层的唯一标识符(ID)。
|
||||
|
||||
!> 播放录像时,将默认忽略所有动画。
|
||||
|
||||
目前天气系统只支持雨和雪两种天气。
|
||||
目前天气系统支持雨和雪和雾两种天气。
|
||||
|
||||
在每层楼的剧本文件里存在一个weather选项,表示该层楼的默认天气。
|
||||
在每层楼的楼层属性中存在一个weather选项,表示该层楼的默认天气。
|
||||
|
||||
``` js
|
||||
// 该层的默认天气。本项可忽略表示晴天,如果写则第一项为"rain","snow"或"fog"代表雨雪雾,第二项为1-10之间的数代表强度。
|
||||
@ -394,24 +355,18 @@ floorId指定的是目标楼层的唯一标识符(ID)。
|
||||
要播放音乐和音效,你需要将对应的文件放在sounds目录下,然后在全塔属性中进行定义
|
||||
|
||||
``` js
|
||||
"bgms": [ // 在此存放所有的bgm,和文件名一致。
|
||||
// 音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好
|
||||
'bgm.mp3'
|
||||
];
|
||||
"sounds": [ // 在此存放所有的SE,和文件名一致
|
||||
// 音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好
|
||||
'floor.mp3', 'attack.mp3', 'door.mp3', 'item.mp3', 'zone.mp3'
|
||||
]
|
||||
// 在此存放所有的bgm,和文件名一致。
|
||||
// 音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好
|
||||
"bgms": ["bgm.mp3"]
|
||||
|
||||
// 在此存放所有的SE,和文件名一致
|
||||
"sounds": ["floor.mp3", "attack.mp3", "door.mp3", "item.mp3", "zone.mp3"]
|
||||
```
|
||||
|
||||
!> 音频名不能使用中文,不能带空格或特殊字符。
|
||||
|
||||
目前BGM支持主流的音乐格式,如mp3, ogg,格式等。不支持mid格式的播放。
|
||||
<!--
|
||||
!> mid格式是通过数学方法模拟出来的音乐效果,质量可能会和实际效果差距较大。
|
||||
目前BGM支持主流的音乐格式,如mp3, ogg等。不支持mid格式的播放。
|
||||
|
||||
!> **警告!** mid格式在手机端播放可能会特别卡,仍推荐直接使用mp3/ogg来播放。
|
||||
-->
|
||||
定义完毕后,我们可以调用`playBgm`/`playSound`事件来播放对应的音乐/音效,有关事件的详细介绍请参见[事件](event)。
|
||||
|
||||
**另外,考虑到用户的流量问题,将遵循如下规则:**
|
||||
@ -443,7 +398,7 @@ HTML5魔塔一大亮点就是存在录像系统,可以很方便进行录像回
|
||||
录像的回放主要有两种方式:
|
||||
|
||||
1. 保存成的录像文件(.h5route文件):在标题界面点录像回放,再选择文件即可。
|
||||
2. 游戏过程中时的当前录像:随时按R可以进行回放;手机端则长按任何位置3秒以上调出虚拟键盘,再按R。
|
||||
2. 游戏过程中时的当前录像:随时按R可以进行回放;手机端则可调出虚拟键盘,再按R。
|
||||
|
||||
录像播放过程中,可以进行如下操作:
|
||||
|
||||
@ -474,6 +429,9 @@ HTML5魔塔一大亮点就是存在录像系统,可以很方便进行录像回
|
||||
|
||||
## 操作说明
|
||||
|
||||

|
||||
|
||||
<!--
|
||||
本塔主要支持鼠标(触摸屏)操作和键盘操作。
|
||||
|
||||
鼠标(触摸屏)操作说明如下:
|
||||
@ -511,6 +469,7 @@ HTML5魔塔一大亮点就是存在录像系统,可以很方便进行录像回
|
||||
- **[Alt+0~9]** 快捷换装
|
||||
|
||||
以上快捷键也能在游戏菜单中的操作说明中看到。
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
BIN
_docs/img/keyboard.png
Normal file
BIN
_docs/img/keyboard.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 53 KiB |
@ -1,11 +1,10 @@
|
||||
# HTML5 魔塔样板说明文档
|
||||
|
||||
?> 目前版本**v2.5.5**,上次更新时间:* {docsify-updated} *
|
||||
?> 目前版本**v2.6**,上次更新时间:* {docsify-updated} *
|
||||
|
||||
众所周知,魔塔的趋势是向移动端发展,贴吧中也常常能见到“求手机魔塔”的帖子。然而现有的工具中,NekoRPG有着比较大的局限性,游戏感较差,更是完全没法在iOS上运行。而一些APP的魔塔虽然可用,但是必须要下载安装,对于Android和iOS还必须开发不同的版本,非常麻烦。
|
||||
|
||||
但是,现在我们有了HTML5。 HTML5的画布(canvas)以及它被Android/iOS内置浏览器所支持的特性,可以让我们做出真正意义上的全平台覆盖的魔塔。
|
||||
事实上,在贴吧的试水发布也证明了,H5魔塔确实是可以成功的。两部即使是复刻的魔塔也受到了不少人的追捧,其流畅的手感和全平台支持的特性,也让很多没办法打开电脑的人爱不释手。
|
||||
|
||||
然而,一般而言使用非RMXP制作魔塔往往需要一定的编程技术,HTML5魔塔自然也不例外。但是,为了能让大家更加注重于“做塔”本身,而不用考虑做塔以外的各种脚本问题,我特意制作了这样一部HTML5的魔塔样板。
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# 快速上手
|
||||
|
||||
?> 目前版本**v2.5.5**,上次更新时间:* {docsify-updated} *
|
||||
?> 目前版本**v2.6**,上次更新时间:* {docsify-updated} *
|
||||
|
||||
在这一节中,将详细介绍做一部塔的流程。现在,让我们来做一部单层塔!
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
* “地图编辑器”允许你以可视化的方式进行编辑地图。
|
||||
* “便捷PS工具”能让你很方便的对自定义素材进行添加。参见[自定义素材](personalization#自定义素材)。
|
||||
* “地图生成器”能让你从已有的截图(如RMXP项目)中立刻生成可被本样板识别的地图数据。
|
||||
* “怪物数据导出”能让你从RMXP中导出怪物数据而被H5魔塔使用。
|
||||
* “RM动画导出器”能让你从RMXP中导出动画而被H5魔塔使用。
|
||||
* “JS代码压缩工具”能对JS代码进行压缩,从而减少IO请求数和文件大小。
|
||||
* “伤害和临界值计算器”是一个很便捷的小工具,能对怪物的伤害和临界值进行计算。
|
||||
@ -54,6 +55,8 @@
|
||||
|
||||
### 从RMXP导入已有的地图
|
||||
|
||||
!> 注:现在已经不推荐此方法,如需从RM刻塔请使用 [RM转H5刻塔器使用教程](https://www.bilibili.com/video/av43125840) 进行操作。
|
||||
|
||||
如果我们想复刻一个现有的,已经被RMXP所制作的塔,也有很便捷的方式,那就是用到我们的“地图生成器”。
|
||||
|
||||
首先,我们打开RMXP和对应的项目,可以看到它的地图。
|
||||
@ -176,7 +179,7 @@
|
||||
|
||||
之后刷新编辑器即可。
|
||||
|
||||
对于怪物和道具,我们也可以进行自动注册,只需要点击“自动注册”按钮,将对该栏下所有未注册的素材进行自动注册(自动分配ID和数字)。
|
||||
也可以进行自动注册,只需要点击“自动注册”按钮,将对该栏下所有未注册的素材进行自动注册(自动分配ID和数字)。
|
||||
|
||||
素材注册完毕后,即可在游戏中正常使用,也可以被地图生成器所识别(需要重开地图生成器)。
|
||||
|
||||
@ -230,6 +233,18 @@ HTML5的塔都是可以进行控制台调试的。
|
||||
|
||||
更多API和详细参数介绍可参见[API列表](api)。
|
||||
|
||||
## 编辑器的基本操作
|
||||
|
||||
- **Alt+0~9, Ctrl+0~9** 保存和读取当前选中图块
|
||||
- **W/A/S/D** 移动大地图
|
||||
- **Ctrl+Z** 撤销上次绘图
|
||||
- **Ctrl+Y** 重做上次绘图
|
||||
- **PgUp/PgDn** 切换楼层
|
||||
- **Ctrl+S** 保存事件编辑器/脚本编辑器
|
||||
- **地图上单击** 选中该点
|
||||
- **地图上双击** 选中该点图块
|
||||
- **地图上右键** 弹出菜单栏,包括选中、复制、清除等操作
|
||||
- **事件编辑器中Ctrl+C, Ctrl+X, 右键等** 执行相应操作
|
||||
|
||||
## 报错处理
|
||||
|
||||
|
||||
@ -85,13 +85,25 @@ shopcommonevent
|
||||
tooltip : 全局商店, 执行一个公共事件
|
||||
helpUrl : https://h5mota.com/games/template/docs/#/
|
||||
default : ["shop1","回收钥匙商店",false,"回收钥匙商店",""]
|
||||
if (EvalString_2) {
|
||||
if (EvalString_2.indexOf('"')>=0)
|
||||
throw new Error('请勿在此处使用双引号!尝试使用单引号吧~');
|
||||
// 检查是不是数组
|
||||
try {
|
||||
EvalString_2 = JSON.parse(EvalString_2.replace(/'/g, '"'));
|
||||
if (!(EvalString_2 instanceof Array)) throw new Error();
|
||||
}
|
||||
catch (e) {
|
||||
throw new Error('参数列表必须是个有效的数组!');
|
||||
}
|
||||
}
|
||||
var code = {
|
||||
'id': IdString_0,
|
||||
'textInList': EvalString_0,
|
||||
'mustEnable': Bool_0,
|
||||
'commonEvent': EvalString_1,
|
||||
'args': EvalString_2
|
||||
'commonEvent': EvalString_1
|
||||
}
|
||||
if (EvalString_2) code.args = EvalString_2;
|
||||
code=JSON.stringify(code,null,2)+',\n';
|
||||
return code;
|
||||
*/;
|
||||
@ -322,7 +334,7 @@ action
|
||||
| callBook_s
|
||||
| callSave_s
|
||||
| callLoad_s
|
||||
| unknow_s
|
||||
| unknown_s
|
||||
| function_s
|
||||
| pass_s
|
||||
;
|
||||
@ -1746,17 +1758,19 @@ var code = '{"type": "callLoad"},\n';
|
||||
return code;
|
||||
*/;
|
||||
|
||||
unknow_s
|
||||
unknown_s
|
||||
: '自定义事件' BGNL? RawEvalString
|
||||
|
||||
/* unknow_s
|
||||
/* unknown_s
|
||||
tooltip : 通过脚本自定义的事件类型, 以及编辑器不识别的事件类型
|
||||
helpUrl : https://h5mota.com/games/template/docs/#/
|
||||
default : ['{"type":"eventType1"}']
|
||||
default : ['{"type":"test", "data": "这是自定义的参数"}']
|
||||
colour : this.dataColor
|
||||
var tempobj={};
|
||||
eval("tempobj='"+RawEvalString_0+"'");
|
||||
var code = tempobj +',\n';
|
||||
try {
|
||||
var tempobj = JSON.parse(RawEvalString_0);
|
||||
} catch (e) {throw new Error("不合法的JSON格式!");}
|
||||
if (!tempobj.type) throw new Error("自定义事件需要一个type:xxx");
|
||||
var code = JSON.stringify(tempobj) +',\n';
|
||||
return code;
|
||||
*/;
|
||||
|
||||
@ -2148,8 +2162,13 @@ ActionParser.prototype.parse = function (obj,type) {
|
||||
]);
|
||||
}
|
||||
var buildcommentevent = function(obj,parser,next){
|
||||
if (obj.args instanceof Array) {
|
||||
try { obj.args = JSON.stringify(obj.args).replace(/"/g, "'"); }
|
||||
catch (e) {obj.args = '';}
|
||||
}
|
||||
else obj.args = null;
|
||||
return MotaActionBlocks['shopcommonevent'].xmlText([
|
||||
obj.id,parser.EvalString(obj.textInList),obj.mustEnable,parser.EvalString(obj.commonEvent),parser.EvalString(obj.args),next
|
||||
obj.id,parser.EvalString(obj.textInList),obj.mustEnable,parser.EvalString(obj.commonEvent),obj.args,next
|
||||
]);
|
||||
}
|
||||
var next=null;
|
||||
@ -2651,13 +2670,8 @@ ActionParser.prototype.parseAction = function() {
|
||||
case "animateImage": // 兼容 animateImage
|
||||
break;
|
||||
default:
|
||||
var rawdata = JSON.stringify(data,function(k,v){
|
||||
if(typeof(v)=='string')return v.split('\n').join('\\n');
|
||||
else return v;
|
||||
},2);
|
||||
rawdata=rawdata.split('\n').join('\\n');
|
||||
this.next = MotaActionBlocks['unknow_s'].xmlText([
|
||||
rawdata,this.next]);
|
||||
this.next = MotaActionBlocks['unknown_s'].xmlText([
|
||||
JSON.stringify(data),this.next]);
|
||||
}
|
||||
this.parseAction();
|
||||
return;
|
||||
|
||||
@ -159,6 +159,7 @@ editor_blockly = function () {
|
||||
],
|
||||
'原生脚本':[
|
||||
MotaActionBlocks['function_s'].xmlText(),
|
||||
MotaActionBlocks['unknown_s'].xmlText(),
|
||||
],
|
||||
'值块':[
|
||||
MotaActionBlocks['setValue_s'].xmlText([
|
||||
@ -588,7 +589,6 @@ function omitedcheckUpdateFunction(event) {
|
||||
'showTextImage_s': 'EvalString_0',
|
||||
'function_s': 'RawEvalString_0',
|
||||
'shopsub': 'EvalString_3',
|
||||
'unknow_s': 'RawEvalString_0',
|
||||
}
|
||||
var f = b ? textStringDict[b.type] : null;
|
||||
if (f) {
|
||||
|
||||
@ -717,7 +717,7 @@ actions.prototype._sys_keyDownCtrl = function () {
|
||||
}
|
||||
if (core.status.event.id == 'action' && core.status.event.data.type == 'sleep'
|
||||
&& !core.status.event.data.current.noSkip) {
|
||||
if (core.timeout.sleepTimeout && Object.keys(core.animateFrame.asyncId).length == 0) {
|
||||
if (core.timeout.sleepTimeout && !core.hasAsync()) {
|
||||
clearTimeout(core.timeout.sleepTimeout);
|
||||
core.timeout.sleepTimeout = null;
|
||||
core.doAction();
|
||||
@ -752,7 +752,7 @@ actions.prototype._sys_longClick_lockControl = function (x, y) {
|
||||
// 长按可以跳过等待事件
|
||||
if (core.status.event.id == 'action' && core.status.event.data.type == 'sleep'
|
||||
&& !core.status.event.data.current.noSkip) {
|
||||
if (core.timeout.sleepTimeout && Object.keys(core.animateFrame.asyncId).length == 0) {
|
||||
if (core.timeout.sleepTimeout && !core.hasAsync()) {
|
||||
clearTimeout(core.timeout.sleepTimeout);
|
||||
core.timeout.sleepTimeout = null;
|
||||
core.doAction();
|
||||
@ -1198,35 +1198,21 @@ actions.prototype._keyUpShop = function (keycode) {
|
||||
|
||||
////// 快捷商店界面时的点击操作 //////
|
||||
actions.prototype._clickQuickShop = function (x, y) {
|
||||
var keys = [];
|
||||
if (core.flags.quickCommonEvents) {
|
||||
keys = core.getFlag("__commonEventList__", []);
|
||||
}
|
||||
else {
|
||||
keys = Object.keys(core.status.shops).filter(function (shopId) {
|
||||
return core.status.shops[shopId].visited || !core.status.shops[shopId].mustEnable
|
||||
});
|
||||
}
|
||||
var keys = Object.keys(core.status.shops).filter(function (shopId) {
|
||||
return core.status.shops[shopId].visited || !core.status.shops[shopId].mustEnable
|
||||
});
|
||||
|
||||
if (x >= this.CHOICES_LEFT && x <= this.CHOICES_RIGHT) {
|
||||
var topIndex = this.HSIZE - parseInt(keys.length / 2);
|
||||
if (y >= topIndex && y < topIndex + keys.length) {
|
||||
if (core.flags.quickCommonEvents) {
|
||||
var name = keys[y - topIndex];
|
||||
core.ui.closePanel();
|
||||
core.status.route.push("common:" + core.encodeBase64(name));
|
||||
core.insertAction(name);
|
||||
}
|
||||
else {
|
||||
var reason = core.events.canUseQuickShop(keys[y - topIndex]);
|
||||
if (!core.flags.enableDisabledShop && reason) {
|
||||
core.drawText(reason);
|
||||
return;
|
||||
}
|
||||
core.events.openShop(keys[y - topIndex], true);
|
||||
if (core.status.event.id == 'shop')
|
||||
core.status.event.data.fromList = true;
|
||||
var reason = core.events.canUseQuickShop(keys[y - topIndex]);
|
||||
if (!core.flags.enableDisabledShop && reason) {
|
||||
core.drawText(reason);
|
||||
return;
|
||||
}
|
||||
core.events.openShop(keys[y - topIndex], true);
|
||||
if (core.status.event.id == 'shop')
|
||||
core.status.event.data.fromList = true;
|
||||
}
|
||||
// 离开
|
||||
else if (y == topIndex + keys.length)
|
||||
@ -1240,17 +1226,10 @@ actions.prototype._keyUpQuickShop = function (keycode) {
|
||||
core.ui.closePanel();
|
||||
return;
|
||||
}
|
||||
var length = 0;
|
||||
if (core.flags.quickCommonEvents) {
|
||||
length = core.getFlag("__commonEventList__", []).length;
|
||||
}
|
||||
else {
|
||||
var shopList = core.status.shops, keys = Object.keys(shopList).filter(function (shopId) {
|
||||
return shopList[shopId].visited || !shopList[shopId].mustEnable
|
||||
});
|
||||
length = keys.length;
|
||||
}
|
||||
this._selectChoices(length + 1, keycode, this._clickQuickShop);
|
||||
var keys = Object.keys(core.status.shops).filter(function (shopId) {
|
||||
return core.status.shops[shopId].visited || !core.status.shops[shopId].mustEnable
|
||||
});
|
||||
this._selectChoices(keys.length + 1, keycode, this._clickQuickShop);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -33,7 +33,6 @@ control.prototype._init = function () {
|
||||
this.registerReplayAction("fly", this._replayAction_fly);
|
||||
this.registerReplayAction("shop", this._replayAction_shop);
|
||||
this.registerReplayAction("turn", this._replayAction_turn);
|
||||
this.registerReplayAction("common", this._replayAction_common);
|
||||
this.registerReplayAction("getNext", this._replayAction_getNext);
|
||||
this.registerReplayAction("moveDirectly", this._replayAction_moveDirectly);
|
||||
this.registerReplayAction("key", this._replayAction_key);
|
||||
@ -169,25 +168,22 @@ control.prototype._animationFrame_animate = function (timestamp) {
|
||||
if (timestamp - core.animateFrame.animateTime < 50 || !core.status.animateObjs || core.status.animateObjs.length == 0) return;
|
||||
core.clearMap('animate');
|
||||
// 更新帧
|
||||
var animateObjs = [];
|
||||
for (var i=0;i<core.status.animateObjs.length;i++) {
|
||||
for (var i = 0; i < core.status.animateObjs.length; i++) {
|
||||
var obj = core.status.animateObjs[i];
|
||||
if (obj.index == obj.animate.frames.length) {
|
||||
// 绘制完毕
|
||||
delete core.animateFrame.asyncId[obj.id];
|
||||
// 异步执行回调...
|
||||
(function(callback) {
|
||||
setTimeout(function() {
|
||||
(function (callback) {
|
||||
setTimeout(function () {
|
||||
if (callback) callback();
|
||||
});
|
||||
})(obj.callback);
|
||||
}
|
||||
else {
|
||||
core.maps._drawAnimateFrame(obj.animate, obj.centerX, obj.centerY, obj.index++);
|
||||
animateObjs.push(obj);
|
||||
}
|
||||
}
|
||||
core.status.animateObjs = animateObjs;
|
||||
core.status.animateObjs = core.status.animateObjs.filter(function (obj) {
|
||||
return obj.index < obj.animate.frames.length;
|
||||
});
|
||||
core.status.animateObjs.forEach(function (obj) {
|
||||
core.maps._drawAnimateFrame(obj.animate, obj.centerX, obj.centerY, obj.index++);
|
||||
});
|
||||
core.animateFrame.animateTime = timestamp;
|
||||
}
|
||||
|
||||
@ -1415,6 +1411,12 @@ control.prototype._replayAction_shop = function (action) {
|
||||
if (selections.length == 0) return false;
|
||||
var shop=core.status.shops[shopId];
|
||||
if (!shop || !shop.visited) return false;
|
||||
// --- 判定commonEvent
|
||||
if (shop.commonEvent) {
|
||||
core.openShop(shopId, false);
|
||||
setTimeout(core.replay);
|
||||
return true;
|
||||
}
|
||||
var choices = shop.choices;
|
||||
var topIndex = core.__HALF_SIZE__ - parseInt(choices.length / 2);
|
||||
core.status.event.selection = parseInt(selections.shift());
|
||||
@ -1446,16 +1448,6 @@ control.prototype._replayAction_turn = function (action) {
|
||||
return true;
|
||||
}
|
||||
|
||||
control.prototype._replayAction_common = function (action) {
|
||||
if (action.indexOf("common:") != 0) return false;
|
||||
var name = core.decodeBase64(action.substring(7));
|
||||
if (core.getFlag("__commonEventList__").indexOf(name) == -1) return false;
|
||||
core.status.route.push(action);
|
||||
core.insertAction(name);
|
||||
setTimeout(core.replay);
|
||||
return true;
|
||||
}
|
||||
|
||||
control.prototype._replayAction_getNext = function (action) {
|
||||
if (action != "getNext") return false;
|
||||
if (!core.getNextItem()) return false;
|
||||
@ -2187,7 +2179,7 @@ control.prototype.playSound = function (sound) {
|
||||
var source = core.musicStatus.audioContext.createBufferSource();
|
||||
source.buffer = core.material.sounds[sound];
|
||||
source.connect(core.musicStatus.gainNode);
|
||||
var id = parseInt(Math.random()*10000000);
|
||||
var id = setTimeout(null);
|
||||
source.onended = function () {
|
||||
delete core.musicStatus.playingSounds[id];
|
||||
}
|
||||
|
||||
@ -806,10 +806,7 @@ events.prototype.insertAction = function (action, x, y, callback, addToLast) {
|
||||
|
||||
// ------ 判定commonEvent
|
||||
var commonEvent = this.getCommonEvent(action);
|
||||
if (commonEvent instanceof Array) {
|
||||
this._addCommentEventToList(action, commonEvent);
|
||||
action = commonEvent;
|
||||
}
|
||||
if (commonEvent instanceof Array) action = commonEvent;
|
||||
if (!action) return;
|
||||
|
||||
if (core.status.event.id != 'action') {
|
||||
@ -830,22 +827,6 @@ events.prototype.getCommonEvent = function (name) {
|
||||
return this.commonEvent[name] || null;
|
||||
}
|
||||
|
||||
events.prototype._addCommentEventToList = function (name, list) {
|
||||
if (list == null) list = this.getCommonEvent(name);
|
||||
if (!list || !core.flags.quickCommonEvents) return;
|
||||
var addToList = false;
|
||||
for (var x in list) {
|
||||
if (list[x].type == 'addToList') {
|
||||
addToList = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!addToList) return;
|
||||
var obj = core.getFlag("__commonEventList__", []);
|
||||
if (obj.indexOf(name) == -1) obj.push(name);
|
||||
core.setFlag("__commonEventList__", obj);
|
||||
}
|
||||
|
||||
////// 恢复一个事件 //////
|
||||
events.prototype.recoverEvents = function (data) {
|
||||
if (data) {
|
||||
@ -1144,13 +1125,12 @@ events.prototype._action_useItem = function (data, x, y, prefix) {
|
||||
}
|
||||
|
||||
events.prototype._action_openShop = function (data, x, y, prefix) {
|
||||
if (core.isReplaying()) { // 正在播放录像,简单将visited置为true
|
||||
core.status.shops[data.id].visited = true;
|
||||
this.setEvents([]);
|
||||
core.doAction();
|
||||
}
|
||||
else
|
||||
core.status.shops[data.id].visited = true;
|
||||
this.setEvents([]);
|
||||
if (!core.isReplaying())
|
||||
this.openShop(data.id);
|
||||
if (core.status.event.id == 'action')
|
||||
core.doAction();
|
||||
}
|
||||
|
||||
events.prototype._action_disableShop = function (data, x, y, prefix) {
|
||||
@ -1207,10 +1187,6 @@ events.prototype._action_insert = function (data, x, y, prefix) {
|
||||
core.doAction();
|
||||
}
|
||||
|
||||
events.prototype._action_addToList = function (data, x, y, prefix) {
|
||||
core.doAction();
|
||||
}
|
||||
|
||||
events.prototype._action_playBgm = function (data, x, y, prefix) {
|
||||
core.playBgm(data.name);
|
||||
core.doAction();
|
||||
@ -1496,7 +1472,7 @@ events.prototype.__action_wait_getValue = function (value) {
|
||||
|
||||
events.prototype._action_waitAsync = function (data, x, y, prefix) {
|
||||
var test = window.setInterval(function () {
|
||||
if (Object.keys(core.animateFrame.asyncId).length == 0) {
|
||||
if (!core.hasAsync()) {
|
||||
clearInterval(test);
|
||||
core.doAction();
|
||||
}
|
||||
@ -1687,6 +1663,10 @@ events.prototype.openSettings = function (fromUserAction) {
|
||||
|
||||
// ------ 一些事件的具体执行过程 ------ //
|
||||
|
||||
events.prototype.hasAsync = function () {
|
||||
return Object.keys(core.animateFrame.asyncId).length > 0 || (core.status.animateObjs || []).length > 0;
|
||||
}
|
||||
|
||||
////// 跟随 //////
|
||||
events.prototype.follow = function (name) {
|
||||
core.status.hero.followers = core.status.hero.followers || [];
|
||||
@ -2105,9 +2085,9 @@ events.prototype.openShop = function (shopId, needVisited) {
|
||||
shop.times = shop.times || 0;
|
||||
if (shop.commonTimes) shop.times = core.getFlag('commonTimes', 0);
|
||||
if (needVisited && !shop.visited) {
|
||||
if (!core.flags.enableDisabledShop) {
|
||||
if (shop.times == 0) core.drawTip("该商店尚未开启");
|
||||
else core.drawTip("该商店已失效");
|
||||
if (!core.flags.enableDisabledShop || shop.commonEvent) {
|
||||
if (shop.times == 0) core.drawTip("该项尚未开启");
|
||||
else core.drawTip("该项已失效");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
@ -2115,6 +2095,13 @@ events.prototype.openShop = function (shopId, needVisited) {
|
||||
}
|
||||
}
|
||||
else shop.visited = true;
|
||||
|
||||
// --- 商店
|
||||
if (shop.commonEvent) {
|
||||
core.status.route.push("shop:"+shopId+":0");
|
||||
core.insertAction({"type": "insert", "name": shop.commonEvent, "args": shop.args});
|
||||
return;
|
||||
}
|
||||
core.ui.drawShop(shopId);
|
||||
}
|
||||
|
||||
|
||||
22
libs/maps.js
22
libs/maps.js
@ -30,12 +30,14 @@ maps.prototype.loadFloor = function (floorId, map) {
|
||||
map = {"map": map};
|
||||
}
|
||||
var content = {};
|
||||
var notCopy = ["firstArrive", "eachArrive", "parallelDo", "map", "bgmap", "fgmap",
|
||||
"events", "changeFloor", "afterBattle", "afterGetItem", "afterOpenDoor", "cannotMove"];
|
||||
for (var name in floor) {
|
||||
if (name != 'map' && name != 'bgmap' && name != 'fgmap' && floor[name] != null)
|
||||
if (notCopy.indexOf(name) == -1 && floor[name] != null)
|
||||
content[name] = core.clone(floor[name]);
|
||||
}
|
||||
for (var name in map) {
|
||||
if (name != 'map' && name != 'bgmap' && name != 'fgmap' && map[name] != null)
|
||||
if (notCopy.indexOf(name) == -1 && map[name] != null)
|
||||
content[name] = core.clone(map[name]);
|
||||
}
|
||||
map = this.decompressMap(map.map, floorId);
|
||||
@ -1832,18 +1834,17 @@ maps.prototype.drawAnimate = function (name, x, y, callback) {
|
||||
// 播放音效
|
||||
core.playSound(animate.se);
|
||||
|
||||
var animateId = parseInt(Math.random() * 100000000);
|
||||
var id = setTimeout(null);
|
||||
core.status.animateObjs.push({
|
||||
"id": id,
|
||||
"animate": animate,
|
||||
"centerX": centerX,
|
||||
"centerY": centerY,
|
||||
"index": 0,
|
||||
"id": animateId,
|
||||
"callback": callback
|
||||
});
|
||||
|
||||
core.animateFrame.asyncId[animateId] = true;
|
||||
return animateId;
|
||||
return id;
|
||||
}
|
||||
|
||||
////// 绘制动画的某一帧 //////
|
||||
@ -1881,7 +1882,6 @@ maps.prototype.stopAnimate = function (id, doCallback) {
|
||||
for (var i = 0; i < core.status.animateObjs.length; i++) {
|
||||
var obj = core.status.animateObjs[i];
|
||||
if (obj.id == id) {
|
||||
delete core.animateFrame.asyncId[obj.id];
|
||||
if (doCallback) {
|
||||
(function (callback) {
|
||||
setTimeout(function () {
|
||||
@ -1890,10 +1890,8 @@ maps.prototype.stopAnimate = function (id, doCallback) {
|
||||
})(obj.callback);
|
||||
}
|
||||
}
|
||||
core.status.animateObjs.splice(i, 1);
|
||||
if (core.status.animateObjs.length == 0) {
|
||||
core.clearMap('animate');
|
||||
}
|
||||
break;
|
||||
}
|
||||
core.status.animateObjs = core.status.animateObjs.filter(function (x) { return x.id != id });
|
||||
if (core.status.animateObjs.length == 0)
|
||||
core.clearMap('animate');
|
||||
}
|
||||
|
||||
18
libs/ui.js
18
libs/ui.js
@ -1118,18 +1118,12 @@ ui.prototype.drawSettings = function () {
|
||||
////// 绘制快捷商店选择栏 //////
|
||||
ui.prototype.drawQuickShop = function () {
|
||||
core.status.event.id = 'selectShop';
|
||||
var choices;
|
||||
if (core.flags.quickCommonEvents) {
|
||||
choices = core.clone(core.getFlag("__commonEventList__", []));
|
||||
}
|
||||
else {
|
||||
var shopList = core.status.shops, keys = Object.keys(shopList).filter(function (shopId) {
|
||||
return shopList[shopId].visited || !shopList[shopId].mustEnable
|
||||
});
|
||||
choices = keys.map(function (shopId) {
|
||||
return {"text": shopList[shopId].textInList, "color": shopList[shopId].visited?null:"#999999"};
|
||||
});
|
||||
}
|
||||
var shopList = core.status.shops, keys = Object.keys(shopList).filter(function (shopId) {
|
||||
return shopList[shopId].visited || !shopList[shopId].mustEnable
|
||||
});
|
||||
var choices = keys.map(function (shopId) {
|
||||
return {"text": shopList[shopId].textInList, "color": shopList[shopId].visited?null:"#999999"};
|
||||
});
|
||||
choices.push("返回游戏");
|
||||
this.drawChoices(null, choices);
|
||||
}
|
||||
|
||||
@ -467,8 +467,6 @@ utils.prototype._encodeRoute_encodeOne = function (t) {
|
||||
return "P" + t.substring(6);
|
||||
else if (t.indexOf('input2:') == 0)
|
||||
return "Q" + t.substring(7) + ":";
|
||||
else if (t.indexOf('common:') == 0)
|
||||
return "c" + t.substring(7) + ":";
|
||||
else if (t == 'no')
|
||||
return 'N';
|
||||
else if (t.indexOf('move:') == 0)
|
||||
@ -527,7 +525,7 @@ utils.prototype._decodeRoute_number2id = function (number) {
|
||||
}
|
||||
|
||||
utils.prototype._decodeRoute_decodeOne = function (decodeObj, c) {
|
||||
var nxt = (c == 'I' || c == 'e' || c == 'F' || c == 'S' || c == 'Q' || c == 't' || c == 'c') ?
|
||||
var nxt = (c == 'I' || c == 'e' || c == 'F' || c == 'S' || c == 'Q' || c == 't') ?
|
||||
this._decodeRoute_getString(decodeObj) : this._decodeRoute_getNumber(decodeObj);
|
||||
|
||||
var mp = {"U": "up", "D": "down", "L": "left", "R": "right"};
|
||||
@ -572,9 +570,6 @@ utils.prototype._decodeRoute_decodeOne = function (decodeObj, c) {
|
||||
case "Q":
|
||||
decodeObj.ans.push("input2:" + nxt);
|
||||
break;
|
||||
case "c":
|
||||
decodeObj.ans.push("common:" + nxt);
|
||||
break;
|
||||
case "N":
|
||||
decodeObj.ans.push("no");
|
||||
break;
|
||||
|
||||
@ -303,10 +303,9 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
|
||||
},
|
||||
{
|
||||
"id": "keyShop1",
|
||||
"textInList": "1F回收钥匙商店",
|
||||
"textInList": "回收钥匙商店",
|
||||
"mustEnable": false,
|
||||
"commonEvent": "回收钥匙商店",
|
||||
"args": ""
|
||||
"commonEvent": "回收钥匙商店"
|
||||
}
|
||||
],
|
||||
"levelUp": [
|
||||
@ -408,7 +407,6 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
|
||||
"enableMoveDirectly": true,
|
||||
"enableDisabledShop": true,
|
||||
"disableShopOnDamage": false,
|
||||
"quickCommonEvents": false,
|
||||
"checkConsole": false
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user