diff --git a/js/pathfinder.js b/js/pathfinder.js index 0ede27e..8c401df 100644 --- a/js/pathfinder.js +++ b/js/pathfinder.js @@ -1,7 +1,13 @@ import {cache, stepCollidesWithWall} from "./cache.js"; import {PriorityQueueSet} from "./data_structures.js"; import {getCenterFromGridPositionObj} from "./foundry_fixes.js"; -import {getAreaFromPositionAndShape, getTokenShapeForTokenData, nodeId} from "./util.js"; +import { + applyOffset, + buildOffset, + getAreaFromPositionAndShape, + getTokenShapeForTokenData, + nodeId, +} from "./util.js"; import * as GridlessPathfinding from "../wasm/gridless_pathfinding.js"; @@ -70,7 +76,7 @@ export class GriddedPathfinder { } let cost; if (window.terrainRuler && !this.ignoreTerrain) { - const offset = {x: neighbor.x - currentNode.node.x, y: neighbor.y - currentNode.node.y}; + const offset = buildOffset(currentNode.node, neighbor); cost = this.terrainCostForStep(tokenArea, offset, currentNode.cost); } else { // Count 5-10-5 diagonals as 1.5 (so two add up to 3) and 5-5-5 diagonals as 1.0001 (to discourage unnecessary diagonals) @@ -91,7 +97,7 @@ export class GriddedPathfinder { terrainCostForStep(tokenArea, offset, previousDistance = 0) { let distance = 0; for (const srcCell of tokenArea) { - const dstCell = {x: srcCell.x + offset.x, y: srcCell.y + offset.y}; + const dstCell = applyOffset(srcCell, offset); // TODO Cache the result of source->destination measurements to speed up the pathfinding for large tokens const ray = new Ray( getCenterFromGridPositionObj(srcCell), @@ -134,9 +140,9 @@ export class GriddedPathfinder { x: middleNode.x - startNode.x, y: middleNode.y - startNode.y, }; - const startEndOffset = {x: endNode.x - startNode.x, y: endNode.y - startNode.y}; + const startEndOffset = buildOffset(startNode, endNode); const middleArea = getAreaFromPositionAndShape(middleNode, this.tokenShape); - const middleEndOffset = {x: endNode.x - middleNode.x, y: endNode.y - middleNode.y}; + const middleEndOffset = buildOffset(middleNode, endNode); // TODO Cache the measurement for use in the next loop to improve performance - this can possibly be done withing terrainCostForStep const middleDistance = this.terrainCostForStep(startArea, startMiddleOffset); diff --git a/js/util.js b/js/util.js index 97c4b2a..f493ed3 100644 --- a/js/util.js +++ b/js/util.js @@ -161,3 +161,41 @@ export function getAreaFromPositionAndShape(position, shape) { return {x, y}; }); } + +export function buildOffset(startPos, endPos) { + const offset = {x: endPos.x - startPos.x, y: endPos.y - startPos.y}; + if (canvas.grid.isHex) { + if (canvas.grid.grid.columnar) { + offset.adjustmentNeeded = (startPos.x - endPos.x) % 2 !== 0; + offset.originEven = startPos.x % 2 === 0; + } else { + offset.adjustmentNeeded = (startPos.y - endPos.y) % 2 !== 0; + offset.originEven = startPos.y % 2 === 0; + } + } + return offset; +} + +export function applyOffset(origin, offset) { + const pos = {x: origin.x + offset.x, y: origin.y + offset.y}; + if (canvas.grid.isHex && offset.adjustmentNeeded) { + if (canvas.grid.grid.columnar) { + if ((origin.x % 2 === 0) !== offset.originEven) { + if (offset.originEven === canvas.grid.grid.even) { + pos.y -= 1; + } else { + pos.y += 1; + } + } + } else { + if ((origin.y % 2 === 0) !== offset.originEven) { + if (offset.originEven === canvas.grid.grid.even) { + pos.x -= 1; + } else { + pos.x += 1; + } + } + } + } + return pos; +}