import { ExtendedCharacter } from '../../utilities/types' import { AStar } from '../../utilities/character/aStar' import ZoneManager from '../../managers/zoneManager' import prisma from '../../utilities/prisma' import Rotation from '../../utilities/character/rotation' export class CharacterMoveService { private moveTokens: Map = new Map() public async updatePosition(character: ExtendedCharacter, position: { x: number; y: number }, newZoneId?: number): Promise { Object.assign(character, { positionX: position.x, positionY: position.y, rotation: Rotation.calculate(character.positionX, character.positionY, position.x, position.y), zoneId: newZoneId || character.zoneId }) await prisma.character.update({ where: { id: character.id }, data: { positionX: position.x, positionY: position.y, rotation: character.rotation, zoneId: newZoneId } }) } public async calculatePath(character: ExtendedCharacter, targetX: number, targetY: number): Promise | null> { const grid = await ZoneManager.getGrid(character.zoneId) if (!grid?.length) { console.error('character:move error', 'Grid not found or empty') return null } const start = { x: Math.floor(character.positionX), y: Math.floor(character.positionY) } const end = { x: Math.floor(targetX), y: Math.floor(targetY) } return AStar.findPath(start, end, grid) } public startMovement(characterId: number): void { this.moveTokens.set(characterId, Symbol('moveToken')) } public stopMovement(characterId: number): void { this.moveTokens.delete(characterId) } public isMoving(characterId: number): boolean { return this.moveTokens.has(characterId) } public async applyMovementDelay(): Promise { await new Promise((resolve) => setTimeout(resolve, 210)) // 50ms delay between steps } }