mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-04-07 04:47:06 +08:00
feat: 勇士移动
This commit is contained in:
parent
fdd4563f45
commit
b4159159a7
public/libs
src
core
game
plugin/game
@ -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');
|
||||
|
@ -3022,6 +3022,7 @@ control.prototype.removeSwitch = function (x, y, floorId, name) {
|
||||
|
||||
////// 锁定状态栏,常常用于事件处理 //////
|
||||
control.prototype.lockControl = function () {
|
||||
console.trace();
|
||||
core.status.lockControl = true;
|
||||
};
|
||||
|
||||
|
@ -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 //////
|
||||
|
@ -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<HotkeyEvent> {
|
||||
|
||||
// 真正开始触发按键
|
||||
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 (
|
||||
|
@ -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);
|
||||
|
@ -58,6 +58,7 @@ export class RenderAdapter<T> {
|
||||
*/
|
||||
all<R = any>(fn: string, ...params: any[]): Promise<R[]> {
|
||||
const execute = this.execute.get(fn);
|
||||
|
||||
if (!execute) {
|
||||
return Promise.reject();
|
||||
} else {
|
||||
@ -86,7 +87,7 @@ export class RenderAdapter<T> {
|
||||
* 对所有元素执行同步函数
|
||||
* @returns 包含每个元素运行结果的数组
|
||||
*/
|
||||
syncAll<R = any>(fn: string, ...params: any[]): R[] {
|
||||
sync<R = any>(fn: string, ...params: any[]): R[] {
|
||||
const execute = this.syncExecutes.get(fn);
|
||||
if (!execute) {
|
||||
return [];
|
||||
|
@ -196,7 +196,8 @@ export class BlockCacher<T> extends EventEmitter<BlockCacherEvent> {
|
||||
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<T> extends EventEmitter<BlockCacherEvent> {
|
||||
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<T> extends EventEmitter<BlockCacherEvent> {
|
||||
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);
|
||||
}
|
||||
|
@ -28,6 +28,8 @@ export class FloorDamageExtends implements ILayerGroupRenderExtends {
|
||||
group!: LayerGroup;
|
||||
sprite!: Damage;
|
||||
|
||||
static listenedDamage: Set<FloorDamageExtends> = 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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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<void>;
|
||||
/** endMove的Promise */
|
||||
private moveEnding?: Promise<void>;
|
||||
/**
|
||||
* 这一步的移动方向,与{@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<void> {
|
||||
if (this.status !== 'moving') return Promise.reject();
|
||||
return new Promise<void>(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<void>(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);
|
||||
});
|
||||
|
@ -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;
|
||||
|
@ -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<DamageEnemy> {
|
||||
interface EnemyCollectionEvent {
|
||||
extract: [];
|
||||
}
|
||||
|
||||
export class EnemyCollection
|
||||
extends EventEmitter<EnemyCollectionEvent>
|
||||
implements RangeCollection<DamageEnemy>
|
||||
{
|
||||
floorId: FloorIds;
|
||||
list: DamageEnemy[] = [];
|
||||
|
||||
@ -108,6 +116,7 @@ export class EnemyCollection implements RangeCollection<DamageEnemy> {
|
||||
translation: [number, number] = [0, 0];
|
||||
|
||||
constructor(floorId: FloorIds) {
|
||||
super();
|
||||
this.floorId = floorId;
|
||||
this.extract();
|
||||
}
|
||||
@ -129,6 +138,7 @@ export class EnemyCollection implements RangeCollection<DamageEnemy> {
|
||||
new DamageEnemy(enemy, v.x, v.y, this.floorId, this)
|
||||
);
|
||||
});
|
||||
this.emit('extract');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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<O, K extends SelectKey<O, _Func>, T = O>(
|
||||
* @param fn 要执行的函数,传入一个参数,表示所有的第三方库,也就是`Mota.Package.requireAll()`的内容
|
||||
* @param thisArg 函数的执行上下文,即函数中`this`指向
|
||||
*/
|
||||
function r<T = undefined>(
|
||||
fn: (this: T, packages: PackageInterface) => void,
|
||||
thisArg?: T
|
||||
) {
|
||||
if (!main.replayChecking && main.mode === 'play')
|
||||
fn.call(thisArg as T, MPackage.requireAll());
|
||||
function r<T = undefined>(fn: (this: T) => void, thisArg?: T) {
|
||||
if (!main.replayChecking && main.mode === 'play') fn.call(thisArg as T);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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<any[]>;
|
||||
|
||||
const pressedArrow: Set<Dir> = 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
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user