openDoor async & battle loc & trigger keep

This commit is contained in:
oc committed 2019-04-28 20:29:51 +08:00
1 parent ccee812af7
commit 9e9025e089
4 files changed
+83 -47

No files matched your search

+24 -27
View File
@@ -180,7 +180,7 @@
我们可以给文字加上标题或图标,只要以`\t[...]`开头就可以。
其一般写法是`\t[名字,ID]`,其中名字为你要显示的标题,ID为图块ID,只能为`hero`,或者NPC/怪物的图块ID。
其一般写法是`\t[名字,ID]`,其中名字为你要显示的标题,ID为图块ID,只能为open`hero`,或者NPC/怪物的图块ID。
如果不需要可以不写ID,则只会显示标题。
@@ -574,24 +574,22 @@ NPC对话事件结束后如果需要NPC消失也需要调用 `{"type": "hide"}`
`{"type":"trigger"}` 会立刻触发当层另一个地点的自定义事件。
上面我们说到,show事件会让一个禁用事件启用且可被交互;但是如果我想立刻让它执行应该怎么办呢?使用trigger就行。
其基本写法如下:
``` js
[
{"type": "trigger", "loc": [3,6]}, // 立即触发loc位置的事件,当前剩下的事件全部不再执行
"执行trigger后,这段文字将不会再被显示"
{"type": "trigger", "loc": [3,6], "keep": true}, // 触发loc位置的事件,不结束当前事件
]
```
其后面带有loc选项,代表另一个地点的坐标。
执行trigger事件后,当前事件将立刻被结束,剩下所有内容被忽略;然后重新启动另一个地点的action事件。
keep可选,如果此项为true则不会结束当前的事件列表,否则会中断当前的事件流。
例如上面这个例子,下面的文字将不会再被显示,而是直接跳转到`"3,6"`对应的事件列表从头执行。
从V2.5.4开始允许执行另一个点的系统事件,如打怪开门拾取道具等等,对应点的战后等事件也会被插入执行。
!> 从V2.5.4开始,允许执行另一个点的“系统事件”,如打怪、开门、拾取道具等等。对应点的战后事件等也会被执行。
值得注意的是,此事件会**改变当前点坐标**为目标点。
### insert:插入公共事件或另一个地点的事件并执行
@@ -619,11 +617,12 @@ NPC对话事件结束后如果需要NPC消失也需要调用 `{"type": "hide"}`
- floorId可选,代表另一个地点所在的楼层;如果不写则默认为当前层。
- 从V2.6开始,还可以传可选的which,可以为`afterBattle`/`afterGetItem`/`afterOpenDoor`,代表插入该点的战后/获得道具后/开门后事件。
和`type:trigger`不同的是,**`type:trigger`是立刻将当前事件结束(剩下所有内容都忽略),然后重新启动另一个地点的action事件。**
和`type:trigger`不同点如下:
- `type:trigger`只能指定当前楼层且会改变当前点坐标,`type:insert`可以跨楼层且不会改变当前点坐标。
- `type:trigger`如果不设置`keep:true`则还会结束当前事件,`type:insert`而是将另一个点的事件插入到当前事件列表中执行。
- `type:trigger`可以触发系统事件,`type:insert`只能触发该点的自定义事件或战后事件等。
但是`type:insert`不会结束当前事件,而是直接将另一个地点的事件列表“插入”到当前事件列表中执行。
**这个过程中,当前事件不会被结束,当前的楼层和事件坐标不会发生改变。** 插入的事件执行完毕后,会继续执行接下来的内容。
插入的事件执行完毕后,会继续执行接下来的内容。
从V2.6开始,插入事件允许传参。如果需要传参,则需要增加一个`args`数组。
@@ -840,28 +839,20 @@ name是可选的,代表目标行走图的文件名。
调用battle可强制与某怪物进行战斗(而无需去触碰到它)。
其基本写法是: `{"type": "battle", "id": xxx}`,其中xxx为怪物ID。
``` js
[
"\t[blackKing]你终于还是来了。",
"\t[hero]放开我们的公主!",
"\t[blackKing]如果我不愿意呢?",
"\t[hero]无需多说,拔剑吧!",
{"type": "battle", "id": "blackKing"}, // 强制战斗
// 如果战斗失败直接死亡,不会继续触发接下来的剧情。
{"type": "hide", "loc": [10,2]}, // 战斗后需要手动使怪物消失;战斗后不会引发afterBattle事件。
{"type": "openDoor", "loc": [8,7]}, // 开门口的机关门
"\t[blackKing]没想到你已经变得这么强大了... 算你厉害。\n公主就交给你了,请好好对她。",
{"type": "hide"} // 隐藏本事件
{"type": "battle", "id": "blackKing"}, // 强制战斗黑衣魔王
{"type": "battle", "loc": [2,3]}, // 强制战斗(2,3)点的怪物
],
```
上面就是样板层中右上角的强制战斗例子。
从V2.6开始,有两种写法:
- 写id,则视为和空降怪物进行强制战斗,不会执行一些战后事件,也不会隐藏任何点。
- 写loc(可选,不填默认当前点),则视为和某点怪物进行强制战斗,会隐藏该点并且插入该点战后事件执行。
如果强制战斗失败,则会立刻生命归0并死亡,调用lose函数,接下来的事件不会再被执行。
强制战斗不会自动存档,如果战斗失败则立刻死亡。
强制战斗没有指定loc的选项,因此战斗后需要调用hide使怪物消失(如果有必要)。
值得注意的是,如果是和某个点的怪物强制战斗,并且该点存在战后事件,执行时会**修改当前点坐标**为目标点。
### openDoor:开门
@@ -871,7 +862,7 @@ name是可选的,代表目标行走图的文件名。
[
{"type": "openDoor", "loc": [3,6], "floorId": "MT1"}, // 打开MT1层的[3,6]位置的门
{"type": "openDoor", "loc": [3,6]}, // 如果是本层则可省略floorId
{"type": "openDoor", "loc": [3,6], "needKey": true} // 打开此门需要钥匙
{"type": "openDoor", "loc": [3,6], "needKey": true, "async": true} // 打开此门需要钥匙,异步执行
]
```
@@ -883,8 +874,12 @@ loc指定门的坐标,floorId指定门所在的楼层ID。如果是当前层
needKey是可选的,如果设置为true则需要钥匙才能打开此门。如果没有钥匙则跳过此事件。
async可选,如果为true则会异步执行(即不等待当前事件执行完毕,立刻执行下一个事件)。
!> needKey仅对当前楼层开门有效!跨楼层的门仍然不需要钥匙即可打开,如有需求请自行判定。
值得注意的是,如果该点存在开门事件,执行时会**修改当前点坐标**为目标点。
### closeDoor:关门
从V2.6开始提供了关门事件`{"type": "closeDoor"}`,拥有关门动画和对应的音效。
@@ -907,6 +902,8 @@ yellowWall, blueWall, whiteWall
loc可选,为要关的位置,不填默认为当前点。
async可选,如果为true则会异步执行(即不等待当前事件执行完毕,立刻执行下一个事件)。
关门事件需要保证该点是空地,否则将无视此事件。
### changeFloor:楼层切换
+43 -14
View File
@@ -287,6 +287,7 @@ action
| wait_s
| waitAsync_s
| battle_s
| battle_1_s
| openDoor_s
| closeDoor_s
| changeFloor_s
@@ -643,15 +644,16 @@ return code;
*/;
trigger_s
: '触发事件' 'x' PosString ',' 'y' PosString Newline
: '触发事件' 'x' PosString ',' 'y' PosString '不结束当前事件' Bool Newline
/* trigger_s
tooltip : trigger: 立即触发另一个地点的事件
helpUrl : https://h5mota.com/games/template/docs/#/event?id=trigger%EF%BC%9A%E7%AB%8B%E5%8D%B3%E8%A7%A6%E5%8F%91%E5%8F%A6%E4%B8%80%E4%B8%AA%E5%9C%B0%E7%82%B9%E7%9A%84%E4%BA%8B%E4%BB%B6
default : ["0","0"]
default : ["0","0",false]
colour : this.eventColor
var code = '{"type": "trigger", "loc": ['+PosString_0+','+PosString_1+']},\n';
Bool_0 = Bool_0 ?', "keep": true':'';
var code = '{"type": "trigger", "loc": ['+PosString_0+','+PosString_1+']'+Bool_0+'},\n';
return code;
*/;
@@ -984,14 +986,32 @@ var code = '{"type": "battle", "id": "'+IdString_0+'"},\n';
return code;
*/;
battle_1_s
: '强制战斗' 'x' PosString? ',' 'y' PosString? Newline
/* battle_1_s
tooltip : battle: 强制战斗
helpUrl : https://h5mota.com/games/template/docs/#/event?id=battle%EF%BC%9A%E5%BC%BA%E5%88%B6%E6%88%98%E6%96%97
default : ["","",""]
colour : this.mapColor
var floorstr = '';
if (PosString_0 && PosString_1) {
floorstr = ', "loc": ['+PosString_0+','+PosString_1+']';
}
var code = '{"type": "battle"'+floorstr+'},\n';
return code;
*/;
openDoor_s
: '开门' 'x' PosString? ',' 'y' PosString? '楼层' IdString? '需要钥匙' Bool? Newline
: '开门' 'x' PosString? ',' 'y' PosString? '楼层' IdString? '需要钥匙' Bool? '不等待执行完毕' Bool Newline
/* openDoor_s
tooltip : openDoor: 开门,楼层可不填表示当前层
helpUrl : https://h5mota.com/games/template/docs/#/event?id=opendoor%EF%BC%9A%E5%BC%80%E9%97%A8
default : ["","","",false]
default : ["","","",false,false]
colour : this.mapColor
IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"');
var floorstr = '';
@@ -999,24 +1019,26 @@ if (PosString_0 && PosString_1) {
floorstr = ', "loc": ['+PosString_0+','+PosString_1+']';
}
Bool_0 = Bool_0 ? ', "needKey": true' : '';
var code = '{"type": "openDoor"'+floorstr+IdString_0+Bool_0+'},\n';
Bool_1 = Bool_1 ? ', "async": true' : '';
var code = '{"type": "openDoor"'+floorstr+IdString_0+Bool_0+Bool_1+'},\n';
return code;
*/;
closeDoor_s
: '关门' 'x' PosString? ',' 'y' PosString? 'ID' IdString Newline
: '关门' 'x' PosString? ',' 'y' PosString? 'ID' IdString '不等待执行完毕' Bool Newline
/* closeDoor_s
tooltip : closeDoor: 关门事件,需要该点本身无事件
helpUrl : https://h5mota.com/games/template/docs/#/event?id=opendoor%EF%BC%9A%E5%BC%80%E9%97%A8
default : ["","","yellowDoor"]
default : ["","","yellowDoor",false]
colour : this.mapColor
var floorstr = '';
if (PosString_0 && PosString_1) {
floorstr = ', "loc": ['+PosString_0+','+PosString_1+']';
}
var code = '{"type": "closeDoor", "id": "'+IdString_0+'"'+floorstr+'},\n';
Bool_0 = Bool_0 ? ', "async": true' : '';
var code = '{"type": "closeDoor", "id": "'+IdString_0+'"'+floorstr+Bool_0+'},\n';
return code;
*/;
@@ -2532,12 +2554,12 @@ ActionParser.prototype.parseAction = function() {
case "openDoor": // 开一个门, 包括暗墙
data.loc=data.loc||['','']
this.next = MotaActionBlocks['openDoor_s'].xmlText([
data.loc[0],data.loc[1],data.floorId||'',data.needKey||false,this.next]);
data.loc[0],data.loc[1],data.floorId||'',data.needKey||false,data.async||false,this.next]);
break;
case "closeDoor": // 关一个门,需要该点无事件
data.loc=data.loc||['','']
this.next = MotaActionBlocks['closeDoor_s'].xmlText([
data.loc[0],data.loc[1],data.id,this.next]);
data.loc[0],data.loc[1],data.id,data.async||false,this.next]);
break;
case "useItem": // 使用道具
this.next = MotaActionBlocks['useItem_s'].xmlText([
@@ -2552,12 +2574,19 @@ ActionParser.prototype.parseAction = function() {
data.id,this.next]);
break;
case "battle": // 强制战斗
this.next = MotaActionBlocks['battle_s'].xmlText([
data.id,this.next]);
if (data.id) {
this.next = MotaActionBlocks['battle_s'].xmlText([
data.id,this.next]);
}
else {
data.loc = data.loc || [];
this.next = MotaActionBlocks['battle_1_s'].xmlText([
data.loc[0],data.loc[1],this.next]);
}
break;
case "trigger": // 触发另一个事件;当前事件会被立刻结束。需要另一个地点的事件是有效的
this.next = MotaActionBlocks['trigger_s'].xmlText([
data.loc[0],data.loc[1],this.next]);
data.loc[0],data.loc[1],data.keep,this.next]);
break;
case "insert": // 强制插入另一个点的事件在当前事件列表执行,当前坐标和楼层不会改变
if (data.args instanceof Array) {
+1
View File
@@ -112,6 +112,7 @@ editor_blockly = function () {
MotaActionBlocks['unfollow_s'].xmlText(),
],
'地图处理':[
MotaActionBlocks['battle_1_s'].xmlText(),
MotaActionBlocks['openDoor_s'].xmlText(),
MotaActionBlocks['closeDoor_s'].xmlText(),
MotaActionBlocks['show_s'].xmlText(),
+15 -6
View File
@@ -419,20 +419,23 @@ events.prototype._openDoor_animate = function (id, x, y, callback) {
var locked = core.status.lockControl;
core.lockControl();
core.status.replay.animate = true;
core.removeBlock(x, y);
core.drawImage('event', core.material.images.animates, 0, 32 * door, 32, 32, 32 * x, 32 * y, 32, 32);
var state = 0;
var animate = window.setInterval(function () {
core.clearMap('event', 32 * x, 32 * y, 32, 32);
state++;
if (state == 4) {
clearInterval(animate);
core.removeBlock(x, y);
delete core.animateFrame.asyncId[animate];
if (!locked) core.unLockControl();
core.status.replay.animate = false;
core.events.afterOpenDoor(id, x, y, callback);
return;
}
core.clearMap('event', 32 * x, 32 * y, 32, 32);
core.drawImage('event', core.material.images.animates, 32 * state, 32 * door, 32, 32, 32 * x, 32 * y, 32, 32);
}, speed / Math.max(core.status.replay.speed, 1));
core.animateFrame.asyncId[animate] = true;
}
////// 开一个门后触发的事件 //////
@@ -1133,7 +1136,7 @@ events.prototype._action_openDoor = function (data, x, y, prefix) {
var loc = this.__action_getLoc(data.loc, x, y, prefix);
var floorId = data.floorId || core.status.floorId;
if (floorId == core.status.floorId) {
core.openDoor(loc[0], loc[1], data.needKey, core.doAction);
this.__action_doAsyncFunc(data.async, core.openDoor, loc[0], loc[1], data.needKey);
}
else {
core.removeBlock(loc[0], loc[1], floorId);
@@ -1172,7 +1175,13 @@ events.prototype._action_disableShop = function (data, x, y, prefix) {
}
events.prototype._action_battle = function (data, x, y, prefix) {
this.battle(data.id, null, null, true, core.doAction);
if (data.id) {
this.battle(data.id, null, null, true, core.doAction);
}
else {
var loc = this.__action_getLoc(data.loc, x, y, prefix);
this.battle(null, loc[0], loc[1], true, core.doAction);
}
}
events.prototype._action_trigger = function (data, x, y, prefix) {
@@ -1180,9 +1189,9 @@ events.prototype._action_trigger = function (data, x, y, prefix) {
var block = core.getBlock(loc[0], loc[1]);
if (block != null && block.block.event.trigger) {
block = block.block;
this.setEvents([], block.x, block.y);
this.setEvents(data.keep ? null : [], block.x, block.y);
if (block.event.trigger == 'action')
this.setEvents(block.event.data);
this.insertAction(block.event.data);
else {
core.doSystemEvent(block.event.trigger, block, core.doAction);
return;