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

This commit is contained in:
YouWei Zhao 2019-03-30 18:52:29 -04:00
commit 16930841ce
14 changed files with 147 additions and 218 deletions

View File

@ -3,5 +3,4 @@
- [元件说明](element)
- [事件](event)
- [个性化](personalization)
- [V2.0版本介绍](V2.0)
- [附录API列表](api)

View File

@ -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里指定传送点的目标。
![楼层转换](./img/changefloor.png)
!> **请注意这里的`"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**。
大地图在创建时可以指定宽高,要求**宽和高都不得小于1315x15版本则是不小于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魔塔一大亮点就是存在录像系统可以很方便进行录像回
## 操作说明
![](img/keyboard.png)
<!--
本塔主要支持鼠标(触摸屏)操作和键盘操作。
鼠标(触摸屏)操作说明如下:
@ -511,6 +469,7 @@ HTML5魔塔一大亮点就是存在录像系统可以很方便进行录像回
- **[Alt+0~9]** 快捷换装
以上快捷键也能在游戏菜单中的操作说明中看到。
-->
&nbsp;

BIN
_docs/img/keyboard.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

View File

@ -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的魔塔样板。

View File

@ -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, 右键等** 执行相应操作
## 报错处理

View File

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

View File

@ -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) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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