From b4159159a7ba0760fc06db006f20f19908e05333 Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Wed, 21 Aug 2024 21:29:47 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=8B=87=E5=A3=AB=E7=A7=BB=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/libs/actions.js | 1 + public/libs/control.js | 1 + public/libs/maps.js | 8 ++ src/core/main/custom/hotkey.ts | 6 +- src/core/package.ts | 14 +- src/core/render/adapter.ts | 3 +- src/core/render/preset/block.ts | 8 +- src/core/render/preset/damage.ts | 20 ++- src/core/render/preset/floor.ts | 2 + src/core/render/preset/hero.ts | 63 ++++++-- src/core/render/preset/layer.ts | 12 +- src/game/enemy/damage.ts | 12 +- src/game/system.ts | 12 +- src/plugin/game/fallback.ts | 238 ++++++++++++++++++++++++++++++- 14 files changed, 355 insertions(+), 45 deletions(-) diff --git a/public/libs/actions.js b/public/libs/actions.js index 170b781..680d8d2 100644 --- a/public/libs/actions.js +++ b/public/libs/actions.js @@ -410,6 +410,7 @@ actions.prototype._sys_keyDown_lockControl = function (keyCode) { actions.prototype._sys_keyDown = function (keyCode) { if (!core.status.played) return true; + return true; switch (keyCode) { case 37: core.moveHero('left'); diff --git a/public/libs/control.js b/public/libs/control.js index feac06f..646c35e 100644 --- a/public/libs/control.js +++ b/public/libs/control.js @@ -3022,6 +3022,7 @@ control.prototype.removeSwitch = function (x, y, floorId, name) { ////// 锁定状态栏,常常用于事件处理 ////// control.prototype.lockControl = function () { + console.trace(); core.status.lockControl = true; }; diff --git a/public/libs/maps.js b/public/libs/maps.js index 0458eb7..46a9c5f 100644 --- a/public/libs/maps.js +++ b/public/libs/maps.js @@ -3146,6 +3146,14 @@ maps.prototype.removeBlockByIndex = function (index, floorId) { delete core.status.mapBlockObjs[floorId][block.x + ',' + block.y]; core.setMapBlockDisabled(floorId, block.x, block.y, true); this._updateMapArray(floorId, block.x, block.y); + Mota.require('var', 'hook').emit( + 'setBlock', + block.x, + block.y, + floorId, + 0, + block?.id ?? 0 + ); }; ////// 一次性删除多个block ////// diff --git a/src/core/main/custom/hotkey.ts b/src/core/main/custom/hotkey.ts index fbd48cc..0cb6b96 100644 --- a/src/core/main/custom/hotkey.ts +++ b/src/core/main/custom/hotkey.ts @@ -3,7 +3,7 @@ import { deleteWith, generateBinary, keycode, spliceBy } from '@/plugin/utils'; import { EventEmitter } from 'eventemitter3'; import { isNil } from 'lodash-es'; -// todo: 按下时触发,长按(单次/连续)触发,按下连续触发,按下节流触发,按下加速节流触发 +// todo: 按下加速节流触发 interface HotkeyEvent { set: [id: string, key: KeyCode, assist: number]; @@ -235,12 +235,15 @@ export class Hotkey extends EventEmitter { // 真正开始触发按键 let emitted = false; + toEmit.forEach(v => { if (ctrl === v.ctrl && shift === v.shift && alt === v.alt) { const data = v.emits.get(this.scope); if (!data) return; + if (type === 'up' && data.onUp) { data.onUp(v.id, key, ev); + emitted = true; return; } if (!this.canEmit(v.id, key, type, data)) return; @@ -419,6 +422,7 @@ document.addEventListener('keyup', e => { const code = keycode(e.keyCode); if (gameKey.emitKey(code, assist, 'up', e)) { e.preventDefault(); + deleteWith(core.status.holdingKeys, e.keyCode); } else { // polyfill样板 if ( diff --git a/src/core/package.ts b/src/core/package.ts index 4b354e7..adc0312 100644 --- a/src/core/package.ts +++ b/src/core/package.ts @@ -6,10 +6,10 @@ import * as lzstring from 'lz-string'; import * as animate from 'mutate-animate'; import * as vue from 'vue'; -Mota.Package.register('axios', axios); -Mota.Package.register('chart.js', chart); -Mota.Package.register('jszip', jszip); -Mota.Package.register('lodash', lodash); -Mota.Package.register('lz-string', lzstring); -Mota.Package.register('mutate-animate', animate); -Mota.Package.register('vue', vue); +// Mota.Package.register('axios', axios); +// Mota.Package.register('chart.js', chart); +// Mota.Package.register('jszip', jszip); +// Mota.Package.register('lodash', lodash); +// Mota.Package.register('lz-string', lzstring); +// Mota.Package.register('mutate-animate', animate); +// Mota.Package.register('vue', vue); diff --git a/src/core/render/adapter.ts b/src/core/render/adapter.ts index e879cc4..29d37ec 100644 --- a/src/core/render/adapter.ts +++ b/src/core/render/adapter.ts @@ -58,6 +58,7 @@ export class RenderAdapter { */ all(fn: string, ...params: any[]): Promise { const execute = this.execute.get(fn); + if (!execute) { return Promise.reject(); } else { @@ -86,7 +87,7 @@ export class RenderAdapter { * 对所有元素执行同步函数 * @returns 包含每个元素运行结果的数组 */ - syncAll(fn: string, ...params: any[]): R[] { + sync(fn: string, ...params: any[]): R[] { const execute = this.syncExecutes.get(fn); if (!execute) { return []; diff --git a/src/core/render/preset/block.ts b/src/core/render/preset/block.ts index 31209f5..d74f594 100644 --- a/src/core/render/preset/block.ts +++ b/src/core/render/preset/block.ts @@ -196,7 +196,8 @@ export class BlockCacher extends EventEmitter { deep: number = 2 ** 31 - 1 ) { const [bx, by] = this.getBlockXY(x, y); - const [ex, ey] = this.getBlockXY(x + width, y + height); + const [ex, ey] = this.getBlockXY(x + width - 1, y + height - 1); + return this.updateArea(bx, by, ex - bx, ey - by, deep); } @@ -213,6 +214,7 @@ export class BlockCacher extends EventEmitter { deep: number = 2 ** 31 - 1 ) { const blocks = this.getIndexOf(x, y, width, height); + blocks.forEach(v => { this.clearCache(v, deep); }); @@ -229,8 +231,8 @@ export class BlockCacher extends EventEmitter { const ex = Math.min(x + width, this.blockData.width); const ey = Math.min(y + height, this.blockData.height); - for (let nx = sx; nx < ex; nx++) { - for (let ny = sy; ny < ey; ny++) { + for (let nx = sx; nx <= ex; nx++) { + for (let ny = sy; ny <= ey; ny++) { const index = this.getIndex(nx, ny); res.add(index); } diff --git a/src/core/render/preset/damage.ts b/src/core/render/preset/damage.ts index 5e0152a..7a1e55b 100644 --- a/src/core/render/preset/damage.ts +++ b/src/core/render/preset/damage.ts @@ -28,6 +28,8 @@ export class FloorDamageExtends implements ILayerGroupRenderExtends { group!: LayerGroup; sprite!: Damage; + static listenedDamage: Set = new Set(); + /** * 立刻刷新伤害渲染 */ @@ -52,12 +54,16 @@ export class FloorDamageExtends implements ILayerGroupRenderExtends { } private onUpdate = (floor: FloorIds) => { - this.update(floor); + this.sprite.requestBeforeFrame(() => { + this.update(floor); + }); }; private onSetBlock = (x: number, y: number, floor: FloorIds) => { - if (floor !== this.sprite.enemy?.floorId) return; - this.sprite.updateEnemyOn(x, y); + this.sprite.enemy?.once('extract', () => { + if (floor !== this.sprite.enemy?.floorId) return; + this.sprite.updateEnemyOn(x, y); + }); }; /** @@ -83,12 +89,14 @@ export class FloorDamageExtends implements ILayerGroupRenderExtends { ); group.removeExtends('floor-damage'); } + FloorDamageExtends.listenedDamage.add(this); }); } onDestroy(group: LayerGroup): void { this.floorBinder.off('update', this.onUpdate); this.floorBinder.off('setBlock', this.onSetBlock); + FloorDamageExtends.listenedDamage.delete(this); } } @@ -242,15 +250,17 @@ export class Damage extends Sprite { } else { data.set(index, enemy); } + this.update(this); // 渲染懒更新,优化性能表现 if (!this.needUpdateBlock) { + this.needUpdateBlocks.add(block); this.requestBeforeFrame(() => { this.needUpdateBlock = false; this.needUpdateBlocks.forEach(v => this.updateBlock(v, false)); // todo: 阻击夹域等地图伤害检测是否必要更新,例如不包含阻击夹域的怪就不必要更新这个怪物信息 - this.extractAllMapDamage(); + // this.extractAllMapDamage(); }); this.needUpdateBlock = true; } @@ -264,8 +274,10 @@ export class Damage extends Sprite { private updateBlock(block: number, map: boolean = true) { const data = this.blockData.get(block); if (!data) return; + this.block.clearCache(block, 1); const renderable = this.renderable.get(block)!; + renderable.clear(); data.forEach(v => this.extract(v, renderable)); if (map) this.extractMapDamage(block, renderable); } diff --git a/src/core/render/preset/floor.ts b/src/core/render/preset/floor.ts index 416a42e..fbfd865 100644 --- a/src/core/render/preset/floor.ts +++ b/src/core/render/preset/floor.ts @@ -117,6 +117,8 @@ export class LayerGroupFloorBinder if (!ex) return; ex.setBlock(block, x, y); + console.log(block, x, y); + const floor = this.bindThisFloor ? core.status.floorId : this.floor!; this.emit('setBlock', x, y, floor, block); } diff --git a/src/core/render/preset/hero.ts b/src/core/render/preset/hero.ts index fdd704a..b47c633 100644 --- a/src/core/render/preset/hero.ts +++ b/src/core/render/preset/hero.ts @@ -6,6 +6,7 @@ import EventEmitter from 'eventemitter3'; import { texture } from '../cache'; import { TimingFn } from 'mutate-animate'; import { backDir } from '@/plugin/game/utils'; +import { isNil } from 'lodash-es'; type HeroMovingStatus = 'stop' | 'moving' | 'moving-as'; @@ -48,8 +49,10 @@ export class HeroRenderer private moveDir: Move2 = 'down'; /** 上一步走到格子上的时间 */ private lastStepTime: number = 0; - /** 是否已经执行了当前步移动 */ + /** 执行当前步移动的Promise */ private moveDetached?: Promise; + /** endMove的Promise */ + private moveEnding?: Promise; /** * 这一步的移动方向,与{@link moveDir}不同的是,在这一步走完之前,它都不会变, * 当这一步走完之后,才会将其设置为{@link moveDir}的值 @@ -157,8 +160,6 @@ export class HeroRenderer if (progress >= 1) { this.renderable.x = x + dx; this.renderable.y = y + dy; - console.log(x, y, dx, dy, this.renderable.x, this.renderable.y); - this.emit('stepEnd'); } else { const rx = dx * progress + x; @@ -212,15 +213,21 @@ export class HeroRenderer */ endMove(): Promise { if (this.status !== 'moving') return Promise.reject(); - return new Promise(resolve => { - this.once('stepEnd', () => { - this.status = 'stop'; - this.movingFrame = 0; - this.layer.removeTicker(this.moveId); - this.render(); - resolve(); + if (this.moveEnding) return this.moveEnding; + else { + const promise = new Promise(resolve => { + this.once('stepEnd', () => { + this.moveEnding = void 0; + this.status = 'stop'; + this.movingFrame = 0; + const { x, y } = core.status.hero.loc; + this.setHeroLoc(x, y); + this.render(); + resolve(); + }); }); - }); + return (this.moveEnding = promise); + } } /** @@ -242,11 +249,29 @@ export class HeroRenderer } } this.moveDir = dir; + this.stepDir = dir; + if (!this.renderable) return; this.renderable.render = this.getRenderFromDir(this.moveDir); this.layer.update(this.layer); } + /** + * 设置勇士的坐标 + * @param x 横坐标 + * @param y 纵坐标 + */ + setHeroLoc(x?: number, y?: number) { + if (!this.renderable) return; + if (!isNil(x)) { + this.renderable.x = x; + } + if (!isNil(y)) { + this.renderable.y = y; + } + this.layer.update(this.layer); + } + /** * 按照指定函数移动勇士 * @param x 目标横坐标 @@ -313,6 +338,7 @@ export class HeroRenderer this.moveId = layer.delegateTicker(() => { this.moveTick(Date.now()); }); + console.log(this); } onDestroy(layer: Layer): void { @@ -346,3 +372,18 @@ adapter.recieve('setMoveSpeed', (item, speed: number) => { item.setMoveSpeed(speed); return Promise.resolve(); }); +adapter.recieve('setHeroLoc', (item, x?: number, y?: number) => { + item.setHeroLoc(x, y); + return Promise.resolve(); +}); +adapter.recieve('turn', (item, dir: Dir2) => { + item.turn(dir); + return Promise.resolve(); +}); +// 同步fallback,用于适配现在的样板,之后会删除 +adapter.recieveSync('setHeroLoc', (item, x?: number, y?: number) => { + item.setHeroLoc(x, y); +}); +adapter.recieveSync('turn', (item, dir: Dir2) => { + item.turn(dir); +}); diff --git a/src/core/render/preset/layer.ts b/src/core/render/preset/layer.ts index 890a06d..e6baeb2 100644 --- a/src/core/render/preset/layer.ts +++ b/src/core/render/preset/layer.ts @@ -906,7 +906,7 @@ export class Layer extends Container { this.renderData.push(...data); } else if (data.length === 1) { // 特判单个图块的情况 - const index = x + y + this.mapWidth; + const index = x + y * this.mapWidth; this.renderData[index] = data[0]; } else { // 限定更新区域 @@ -929,7 +929,8 @@ export class Layer extends Container { if (calAutotile) this.calAutotiles(x, y, width, height); this.updateBlocks(x, y, width, height); this.updateBigImages(x, y, width, height); - this.update(this); + + // this.update(this); for (const ex of this.extend.values()) { ex.onDataPut?.(this, data, width, x, y, calAutotile); @@ -1099,6 +1100,7 @@ export class Layer extends Container { height, Layer.FRAME_ALL ); + this.update(this); for (const ex of this.extend.values()) { @@ -1195,7 +1197,7 @@ export class Layer extends Container { */ protected renderStatic(camera: Camera, need: NeedRenderData) { const cell = this.cellSize; - const frame = (RenderItem.animatedFrame % 4) + 1; + const frame = RenderItem.animatedFrame % 4; const { width } = this.block.blockData; const blockSize = this.block.blockSize; const { ctx } = this.staticMap; @@ -1210,7 +1212,7 @@ export class Layer extends Container { const y = Math.floor(v / width); const sx = x * blockSize; const sy = y * blockSize; - const index = v * 4 + frame - 1; + const index = v * 4 + frame; const cache = this.block.cache.get(index); if (cache) { @@ -1241,7 +1243,7 @@ export class Layer extends Container { if (num === 0 || num === 17) continue; const data = texture.getRenderable(num); if (!data || data.bigImage) continue; - const f = (frame - 1) % data.frame; + const f = frame % data.frame; const i = data.animate === -1 ? f : data.animate; const [isx, isy, w, h] = data.render[i]; const px = (nx - sx) * cell; diff --git a/src/game/enemy/damage.ts b/src/game/enemy/damage.ts index 4483e99..e972efc 100644 --- a/src/game/enemy/damage.ts +++ b/src/game/enemy/damage.ts @@ -7,6 +7,7 @@ import { has, manhattan } from '@/plugin/game/utils'; +import EventEmitter from 'eventemitter3'; // todo: 光环划分优先级,从而可以实现光环的多级运算 @@ -95,7 +96,14 @@ specialValue .set(27, ['fireCore']) .set(28, ['paleShield']); -export class EnemyCollection implements RangeCollection { +interface EnemyCollectionEvent { + extract: []; +} + +export class EnemyCollection + extends EventEmitter + implements RangeCollection +{ floorId: FloorIds; list: DamageEnemy[] = []; @@ -108,6 +116,7 @@ export class EnemyCollection implements RangeCollection { translation: [number, number] = [0, 0]; constructor(floorId: FloorIds) { + super(); this.floorId = floorId; this.extract(); } @@ -129,6 +138,7 @@ export class EnemyCollection implements RangeCollection { new DamageEnemy(enemy, v.x, v.y, this.floorId, this) ); }); + this.emit('extract'); } /** diff --git a/src/game/system.ts b/src/game/system.ts index 68969ce..9261b0a 100644 --- a/src/game/system.ts +++ b/src/game/system.ts @@ -186,7 +186,7 @@ export interface IMota { * 接口在渲染进程中引入,在游戏进程中不会polyfill,因此在游戏进程中使用时, * 应先使用main.replayChecking进行检查,保证该值不存在时才进行使用,否则会引起录像出错 */ - Package: IPackage; + // Package: IPackage; /** * 获取一个样板接口 @@ -409,7 +409,7 @@ class Mota { static r = r; static rf = rf; static Plugin = MPlugin; - static Package = MPackage; + // static Package = MPackage; constructor() { throw new Error(`System interface class cannot be constructed.`); @@ -548,12 +548,8 @@ function rewrite, T = O>( * @param fn 要执行的函数,传入一个参数,表示所有的第三方库,也就是`Mota.Package.requireAll()`的内容 * @param thisArg 函数的执行上下文,即函数中`this`指向 */ -function r( - fn: (this: T, packages: PackageInterface) => void, - thisArg?: T -) { - if (!main.replayChecking && main.mode === 'play') - fn.call(thisArg as T, MPackage.requireAll()); +function r(fn: (this: T) => void, thisArg?: T) { + if (!main.replayChecking && main.mode === 'play') fn.call(thisArg as T); } /** diff --git a/src/plugin/game/fallback.ts b/src/plugin/game/fallback.ts index d7fa116..8e473f4 100644 --- a/src/plugin/game/fallback.ts +++ b/src/plugin/game/fallback.ts @@ -15,9 +15,182 @@ export function init() { adapters['hero-adapter'] = hero; } - function onMoveEnd(callback?: () => void) { - core.setHeroLoc('x', core.nextX(), true); - core.setHeroLoc('y', core.nextY(), true); + let moving: boolean = false; + let stopChian: boolean = false; + let moveDir: Dir; + let stepDir: Dir; + let moveEnding: Promise; + + const pressedArrow: Set = new Set(); + Mota.r(() => { + const gameKey = Mota.require('var', 'gameKey'); + gameKey + .realize('moveUp', onMoveKeyDown('up'), { type: 'down' }) + .realize('moveUp', onMoveKeyUp('up')) + .realize('moveDown', onMoveKeyDown('down'), { type: 'down' }) + .realize('moveDown', onMoveKeyUp('down')) + .realize('moveLeft', onMoveKeyDown('left'), { type: 'down' }) + .realize('moveLeft', onMoveKeyUp('left')) + .realize('moveRight', onMoveKeyDown('right'), { type: 'down' }) + .realize('moveRight', onMoveKeyUp('right')); + }); + + function onMoveKeyDown(type: Dir) { + return () => { + pressedArrow.add(type); + moveDir = type; + if (!moving) { + stepDir = moveDir; + readyMove(); + } + if (moving && stopChian) { + stopChian = false; + } + }; + } + + function onMoveKeyUp(type: Dir) { + return () => { + pressedArrow.delete(type); + if (pressedArrow.size === 0) { + stopChian = true; + } else { + const arr = [...pressedArrow]; + moveDir = arr[0]; + if (!moving) { + stepDir = moveDir; + readyMove(); + } + } + }; + } + + async function readyMove() { + const adapter = adapters['hero-adapter']; + if (!adapter) { + return Promise.resolve(); + } else { + if (!checkCanMoveStatus()) { + continueAfterEnd(); + return Promise.resolve(); + } + await adapter.all('readyMove'); + moving = true; + stopChian = false; + return startHeroMoveChain(); + } + } + + async function endMove() { + const adapter = adapters['hero-adapter']; + if (!adapter) { + return Promise.resolve(); + } else { + if (moving) { + stopChian = true; + moveEnding = adapter.all('endMove'); + await moveEnding; + moving = false; + continueAfterEnd(); + } + return Promise.resolve(); + } + } + + function continueAfterEnd() { + requestAnimationFrame(() => { + if (pressedArrow.size === 0 || moving) { + stopChian = true; + return; + } + if (core.status.lockControl) { + pressedArrow.clear(); + stopChian = true; + return; + } + if (checkCanMoveStatus()) { + if (!moving) { + stepDir = moveDir; + readyMove(); + } + } else { + continueAfterEnd(); + } + }); + } + + async function startHeroMoveChain(callback?: () => void) { + const adapter = adapters['hero-adapter']; + if (!adapter) { + return Promise.resolve(); + } else { + while (moving || !stopChian) { + if (stopChian || core.status.lockControl) break; + stepDir = moveDir; + if (!checkCanMoveStatus(callback)) break; + + await adapter.all('move', moveDir); + onMoveEnd(false, callback); + } + endMove(); + stopChian = false; + } + } + + function checkCanMoveStatus(callback?: () => void) { + core.setHeroLoc('direction', stepDir); + const { noPass, canMove } = checkCanMove(); + + if (noPass || !canMove) { + onCannotMove(canMove, callback); + if (moving) endMove(); + // onMoveEnd(true); + return false; + } + return true; + } + + function getNextLoc() { + const { x: dx, y: dy } = core.utils.scan[stepDir]; + const { x, y } = core.status.hero.loc; + const nx = x + dx; + const ny = y + dy; + return { nx, ny }; + } + + /** + * 检查下一格是否可以移动 + */ + function checkCanMove() { + const { nx, ny } = getNextLoc(); + const noPass = core.noPass(nx, ny); + const canMove = core.canMoveHero(nx, ny, stepDir); + return { noPass, canMove }; + } + + function onCannotMove(canMove: boolean, callback?: () => void) { + const { nx, ny } = getNextLoc(); + core.status.route.push(core.getHeroLoc('direction')); + // @ts-ignore + core.status.automaticRoute.moveStepBeforeStop = []; + // @ts-ignore + core.status.automaticRoute.lastDirection = core.getHeroLoc('direction'); + if (canMove) core.trigger(nx, ny); + core.drawHero(); + + if (core.status.automaticRoute.moveStepBeforeStop.length == 0) { + core.clearContinueAutomaticRoute(); + core.stopAutomaticRoute(); + } + callback?.(); + } + + function onMoveEnd(noPass: boolean, callback?: () => void) { + if (!noPass) { + const { nx, ny } = getNextLoc(); + core.setHeroLoc('x', nx, true); + core.setHeroLoc('y', ny, true); + } var direction = core.getHeroLoc('direction'); core.control._moveAction_popAutomaticRoute(); @@ -31,11 +204,14 @@ export function init() { // ----- 勇士移动相关 control.prototype._moveAction_moving = function (callback?: () => void) { + return; const adapter = adapters['hero-adapter']; if (!adapter) { onMoveEnd(callback); return; } else { + core.status.heroMoving = 1; + adapter .all('readyMove') .then(() => { @@ -43,6 +219,7 @@ export function init() { }) .then(() => { onMoveEnd(callback); + core.status.heroMoving = 0; return adapter.all('endMove'); }); } @@ -64,6 +241,7 @@ export function init() { time?: number, callback?: () => void ) { + return; time = time || core.values.moveSpeed; // const render = Mota.require('module', 'Render').heroRender; @@ -127,6 +305,7 @@ export function init() { } }); await adapter.all('readyMove'); + core.status.heroMoving = 1; for (const dir of steps) { if (dir.startsWith('speed')) { const speed = parseInt(dir.slice(6)); @@ -196,7 +375,58 @@ export function init() { core.status.route.push('turn'); core.checkRouteFolding(); if (!main.replayChecking) { - adapters['hero-adapter']?.all('turn', direction); + // adapters['hero-adapter']?.sync('turn', direction); + } + }; + + control.prototype.setHeroLoc = function ( + name: 'x' | 'y' | 'direction', + value: number | Dir, + noGather?: boolean + ) { + if (!core.status.hero) return; + // @ts-ignore + core.status.hero.loc[name] = value; + if ((name === 'x' || name === 'y') && !noGather) { + this.gatherFollowers(); + } + if (name === 'direction') { + adapters['hero-adapter']?.sync('turn', value); + } else if (name === 'x') { + adapters['hero-adapter']?.sync('setHeroLoc', value); + } else { + adapters['hero-adapter']?.sync('setHeroLoc', void 0, value); + } + }; + + ////// 停止勇士的一切行动,等待勇士行动结束后,再执行callback ////// + control.prototype.waitHeroToStop = function (callback?: () => void) { + var lastDirection = core.status.automaticRoute.lastDirection; + core.stopAutomaticRoute(); + core.clearContinueAutomaticRoute(); + if (!main.replayChecking) { + moveEnding.then(() => { + callback?.(); + }); + return; + } + if (callback) { + // @ts-ignore + core.status.replay.animate = true; + core.lockControl(); + // @ts-ignore + core.status.automaticRoute.moveDirectly = false; + setTimeout( + function () { + // @ts-ignore + core.status.replay.animate = false; + if (core.isset(lastDirection)) + core.setHeroLoc('direction', lastDirection); + core.drawHero(); + callback(); + }, + core.status.replay.speed == 24 ? 1 : 30 + ); } }; }