diff --git a/_docs/api.md b/_docs/api.md
index 3316e221..3f67bd85 100644
--- a/_docs/api.md
+++ b/_docs/api.md
@@ -377,6 +377,11 @@ getSaveIndexes: fn(callback?: fn())
getSaves: fn(ids?: ?, callback?: fn())
获得某些存档内容
+getSounds: fn(name?: string) -> [number]
+获得当前正在播放的所有(指定)音效的id列表
+name: 音效名,可用别名;不填代表返回正在播放的全部音效
+返回值: 一个列表,每一项为一个正在播放的音效id;可用core.stopSound立刻停止播放
+
getStatus: fn(name: string) -> number
读取主角的某个属性,不包括百分比修正
例如:core.getStatus('atk'); // 读取主角的攻击力
@@ -980,7 +985,7 @@ getNextItem: fn(noRoute?: bool)
noRoute: 若为true则不计入录像
hasAsync: fn() -> bool
-当前是否有未处理完毕的异步事件
+当前是否有未处理完毕的异步事件(不包含动画和音效)
hasVisitedFloor: fn(floorId?: string) -> bool
是否到达过某个楼层
@@ -1541,6 +1546,11 @@ generateMovableArray: fn(floorId?: string) -> [[[string]]]
floorId: 地图id,不填视为当前地图
返回值:从各点可移动方向的三维数组
+getAnimates: fn(name?: string) -> [number]
+获得当前正在播放的所有(指定)动画的id列表
+name: 动画名;不填代表返回全部正在播放的动画
+返回值: 一个数组,每一项为一个正在播放的动画;可用core.stopAnimate停止播放。
+
getBgMapArray: fn(floorId?: string, noCache?: bool) -> [[number]]
生成背景层矩阵
例如:core.getBgMapArray('MT0'); // 生成主塔0层的背景层矩阵,使用缓存
diff --git a/_server/CodeMirror/defs.js b/_server/CodeMirror/defs.js
index 1c64b918..58d33de5 100644
--- a/_server/CodeMirror/defs.js
+++ b/_server/CodeMirror/defs.js
@@ -2196,6 +2196,10 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [
"!doc": "停止播放音效。如果未指定id则停止所有音效,否则只停止指定的音效。",
"!type": "fn(id?: number)"
},
+ "getSounds": {
+ "!doc": "获得当前正在播放的所有(指定)音效的id列表
name: 音效名,可用别名;不填代表返回正在播放的全部音效
返回值: 一个列表,每一项为一个正在播放的音效id;可用core.stopSound立刻停止播放",
+ "!type": "fn(name?: string) -> [number]"
+ },
"addGameCanvasTranslate": {
"!doc": "加减画布偏移",
"!type": "fn(x?: number, y?: number)"
@@ -3085,6 +3089,10 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [
"!doc": "立刻停止一个动画播放
id: 播放动画的编号,即drawAnimate或drawHeroAnimate的返回值
doCallback: 是否执行该动画的回调函数",
"!type": "fn(id: number, doCallback?: bool)"
},
+ "getAnimates": {
+ "!doc": "获得当前正在播放的所有(指定)动画的id列表
name: 动画名;不填代表返回全部正在播放的动画
返回值: 一个数组,每一项为一个正在播放的动画;可用core.stopAnimate停止播放。",
+ "!type": "fn(name?: string) -> [number]"
+ },
"getBlockCls": {
"!doc": "判定某个点的图块类型
例如:if(core.getBlockCls(x1, y1) != 'enemys' && core.getBlockCls(x2, y2) != 'enemy48') core.openDoor(x3, y3); // 另一个简单的机关门事件,打败或炸掉这一对不同身高的敌人就开门
x: 横坐标
y: 纵坐标
floorId: 地图id,不填视为当前地图
showDisable: 隐藏点是否不返回null,true表示不返回null
返回值:图块类型,即“地形、四帧动画、矮敌人、高敌人、道具、矮npc、高npc、自动元件、额外地形”之一",
"!type": "fn(x: number, y: number, floorId?: string, showDisable?: bool) -> string"
@@ -3829,9 +3837,9 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [
"!type": "fn(noRoute?: bool)"
},
"hasAsync": {
- "!doc": "当前是否有未处理完毕的异步事件",
+ "!doc": "当前是否有未处理完毕的异步事件(不包含动画和音效)",
"!type": "fn() -> bool"
- },
+ },
"openEquipbox": {
"!doc": "点击装备栏时的打开操作",
"!type": "fn(fromUserAction?: bool)"
diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4
index 44414c27..f50b9dd8 100644
--- a/_server/MotaAction.g4
+++ b/_server/MotaAction.g4
@@ -2974,14 +2974,17 @@ return '';
waitAsync_s
- : '等待所有异步事件执行完毕'
+ : '等待所有异步事件执行完毕' '不等待动画' Bool '不等待音效' Bool
/* waitAsync_s
tooltip : waitAsync: 等待所有异步事件执行完毕
helpUrl : /_docs/#/instruction
+default : [false, false]
colour : this.soundColor
-var code = '{"type": "waitAsync"},\n';
+Bool_0 = Bool_0 ? ', "excludeAnimates": true' : '';
+Bool_1 = Bool_1 ? ', "excludeSounds": true' : '';
+var code = '{"type": "waitAsync"'+Bool_0+Bool_1+'},\n';
return code;
*/;
diff --git a/_server/MotaActionParser.js b/_server/MotaActionParser.js
index fa6e9ab5..af322813 100644
--- a/_server/MotaActionParser.js
+++ b/_server/MotaActionParser.js
@@ -951,7 +951,7 @@ ActionParser.prototype.parseAction = function() {
break;
case "waitAsync": // 等待所有异步事件执行完毕
this.next = MotaActionBlocks['waitAsync_s'].xmlText([
- this.next]);
+ data.excludeAnimates||false, data.excludeSounds||false, this.next]);
break;
case "callBook": // 呼出怪物手册
this.next = MotaActionBlocks['callBook_s'].xmlText([
diff --git a/libs/control.js b/libs/control.js
index 7aa570c6..dc0a8587 100644
--- a/libs/control.js
+++ b/libs/control.js
@@ -2868,6 +2868,7 @@ control.prototype.playSound = function (sound, pitch, callback) {
try {
if (core.musicStatus.audioContext != null) {
var source = core.musicStatus.audioContext.createBufferSource();
+ source.__name = sound;
source.buffer = core.material.sounds[sound];
source.connect(core.musicStatus.gainNode);
var id = setTimeout(null);
@@ -2915,6 +2916,14 @@ control.prototype.stopSound = function (id) {
delete core.musicStatus.playingSounds[id];
}
+////// 获得当前正在播放的所有(指定)音效的id列表 //////
+control.prototype.getSounds = function (name) {
+ name = core.getMappedName(name);
+ return Object.keys(core.musicStatus.playingSounds).filter(function (one){
+ return name == null || core.musicStatus.playingSounds[one].__name == name
+ });
+}
+
////// 检查bgm状态 //////
control.prototype.checkBgm = function() {
core.playBgm(core.musicStatus.playingBgm || main.startBgm);
diff --git a/libs/events.js b/libs/events.js
index 32d73248..391c1f34 100644
--- a/libs/events.js
+++ b/libs/events.js
@@ -2479,7 +2479,9 @@ events.prototype._precompile_wait = function (data) {
events.prototype._action_waitAsync = function (data, x, y, prefix) {
var test = window.setInterval(function () {
- if (!core.hasAsync()) {
+ if (!core.hasAsync()
+ && (data.excludeAnimates || core.getAnimates().length == 0)
+ && (data.excludeSounds || core.getSounds().length == 0)) {
clearInterval(test);
core.doAction();
}
@@ -2860,7 +2862,11 @@ events.prototype.openSettings = function (fromUserAction) {
// ------ 一些事件的具体执行过程 ------ //
events.prototype.hasAsync = function () {
- return Object.keys(core.animateFrame.asyncId).length > 0 || (core.status.animateObjs || []).length > 0;
+ return Object.keys(core.animateFrame.asyncId).length > 0;
+}
+
+events.prototype.hasAsyncAnimate = function () {
+ return (core.status.animateObjs || []).length > 0;
}
////// 跟随 //////
diff --git a/libs/maps.js b/libs/maps.js
index 4c6b7e6f..6711bf3c 100644
--- a/libs/maps.js
+++ b/libs/maps.js
@@ -2947,6 +2947,7 @@ maps.prototype.drawAnimate = function (name, x, y, alignWindow, callback) {
var id = setTimeout(null);
core.status.animateObjs.push({
+ "name": name,
"id": id,
"animate": animate,
"centerX": centerX,
@@ -2975,6 +2976,7 @@ maps.prototype.drawHeroAnimate = function (name, callback) {
var id = setTimeout(null);
core.status.animateObjs.push({
+ "name": name,
"id": id,
"animate": animate,
"hero": true,
@@ -2985,6 +2987,13 @@ maps.prototype.drawHeroAnimate = function (name, callback) {
return id;
}
+////// 获得当前正在播放的所有(指定)动画的id列表 //////
+maps.prototype.getAnimates = function (name) {
+ return (core.status.animateObjs || []).filter(function (one) {
+ return name == null || one.name == name;
+ }).map(function (one) { return one.id });
+}
+
////// 绘制动画的某一帧 //////
maps.prototype._drawAnimateFrame = function (name, animate, centerX, centerY, index) {
var ctx = core.getContextByName(name);
diff --git a/runtime.d.ts b/runtime.d.ts
index 9dfe2630..7d3cf68c 100644
--- a/runtime.d.ts
+++ b/runtime.d.ts
@@ -795,6 +795,9 @@ declare class control {
/** 停止(所有)音频 */
stopSound(id?: number): void
+ /** 获得正在播放的所有(指定)音效的id列表 */
+ getSounds(name?: string): Array
+
/** 检查bgm状态 */
checkBgm(): void
@@ -1227,7 +1230,7 @@ declare class events {
/** 点击设置按钮时的操作 */
openSettings(fromUserAction?: boolean): void
- /** 当前是否有未处理完毕的异步事件 */
+ /** 当前是否有未处理完毕的异步事件(不包含动画和音效) */
hasAsync(): boolean
/**
@@ -1778,6 +1781,9 @@ declare class maps {
*/
stopAnimate(id: number, doCallback?: boolean): void
+ /** 获得当前正在播放的所有(指定)动画的id列表 */
+ getAnimates(name?: string) : Array
+
/** 加载某个楼层(从剧本或存档中) */
loadFloor(floorId?: string, map?: any): any