mirror of
				https://github.com/unanmed/HumanBreak.git
				synced 2025-10-31 20:32:58 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			285 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			285 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import type { RenderAdapter } from '@/core/render/adapter';
 | ||
| import type { HeroRenderer } from '@/core/render/preset/hero';
 | ||
| import { hook } from '@/game/game';
 | ||
| 
 | ||
| interface Adapters {
 | ||
|     'hero-adapter'?: RenderAdapter<HeroRenderer>;
 | ||
| }
 | ||
| 
 | ||
| const adapters: Adapters = {};
 | ||
| 
 | ||
| export function init() {
 | ||
|     if (!main.replayChecking && main.mode === 'play') {
 | ||
|         const Adapter = Mota.require('module', 'Render').RenderAdapter;
 | ||
|         const hero = Adapter.get<HeroRenderer>('hero-adapter');
 | ||
| 
 | ||
|         adapters['hero-adapter'] = hero;
 | ||
|     }
 | ||
| 
 | ||
|     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;
 | ||
|             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 move(dir: Dir) {
 | ||
|         moveDir = dir;
 | ||
|     }
 | ||
| 
 | ||
|     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();
 | ||
|             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 { x, y } = core.status.hero.loc;
 | ||
|         const noPass = core.noPass(nx, ny);
 | ||
|         const canMove = core.canMoveHero(x, y, 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();
 | ||
|         core.status.route.push(direction);
 | ||
| 
 | ||
|         core.moveOneStep();
 | ||
|         core.checkRouteFolding();
 | ||
|         callback?.();
 | ||
|     }
 | ||
| 
 | ||
|     // ----- 勇士移动相关
 | ||
| 
 | ||
|     Mota.r(() => {
 | ||
|         control.prototype._moveAction_moving = function (
 | ||
|             callback?: () => void
 | ||
|         ) {};
 | ||
|         events.prototype.eventMoveHero = async function (
 | ||
|             steps: string[],
 | ||
|             time?: number,
 | ||
|             callback?: () => void
 | ||
|         ) {};
 | ||
| 
 | ||
|         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) {
 | ||
|             core.stopAutomaticRoute();
 | ||
|             core.clearContinueAutomaticRoute();
 | ||
|             moveEnding.then(() => {
 | ||
|                 callback?.();
 | ||
|             });
 | ||
|         };
 | ||
| 
 | ||
|         control.prototype.moveHero = async function (
 | ||
|             direction: Dir,
 | ||
|             callback: () => void
 | ||
|         ) {
 | ||
|             // 如果正在移动,直接return
 | ||
|             if (core.status.heroMoving != 0) return;
 | ||
|             if (core.isset(direction)) core.setHeroLoc('direction', direction);
 | ||
| 
 | ||
|             const nx = core.nextX();
 | ||
|             const ny = core.nextY();
 | ||
|             if (core.status.thisMap.enemy.mapDamage[`${nx},${ny}`]?.mockery) {
 | ||
|                 core.autosave();
 | ||
|             }
 | ||
| 
 | ||
|             console.trace();
 | ||
| 
 | ||
|             moveDir = direction;
 | ||
|             stepDir = direction;
 | ||
|             await readyMove();
 | ||
|             stopChian = true;
 | ||
| 
 | ||
|             callback?.();
 | ||
| 
 | ||
|             // if (callback) return this.moveAction(callback);
 | ||
|             // this._moveHero_moving();
 | ||
|         };
 | ||
| 
 | ||
|         hook.on('reset', () => {
 | ||
|             moveDir = core.status.hero.loc.direction;
 | ||
|             stepDir = moveDir;
 | ||
|         });
 | ||
|     });
 | ||
| 
 | ||
|     return { readyMove, endMove, move };
 | ||
| }
 |