openDoor async & battle loc & trigger keep

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

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楼层切换

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

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(),

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;