From 9787a41fd177bb5add3fece062dc88380e7b30e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20V=C3=B6gele?= Date: Mon, 12 Apr 2021 16:11:29 +0200 Subject: [PATCH] If Terran Ruler is enabled, store the length of the traveled path so changes to difficult terrain aren't reflected in the tokens movement history --- src/compatibility.js | 23 ++++++++++++++++++----- src/foundry_imports.js | 2 ++ src/movement_tracking.js | 15 +++++++++++++-- src/ruler.js | 2 +- 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/compatibility.js b/src/compatibility.js index c005d54..30985fd 100644 --- a/src/compatibility.js +++ b/src/compatibility.js @@ -14,10 +14,23 @@ export function highlightMeasurementTerrainRuler(ray, startDistance, tokenShape= } } -export function measureDistances(segments, token, shape, gridSpaces=true) { +export function measureDistances(segments, token, shape, gridSpaces=true, options={}) { + const opts = duplicate(options) + opts.gridSpaces = gridSpaces; const terrainRulerAvailable = game.modules.get("terrain-ruler")?.active && canvas.grid.type !== CONST.GRID_TYPES.GRIDLESS; - if (terrainRulerAvailable) - return terrainRuler.measureDistances(segments, {costFunction: (x, y) => getCostFromSpeedProvider(token, getAreaFromPositionAndShape({x, y}, shape), {x, y})}); - else - return canvas.grid.measureDistances(segments, { gridSpaces }); + if (terrainRulerAvailable) { + const firstNewSegmentIndex = segments.findIndex(segment => !segment.ray.dragRulerVisitedSpaces); + const previousSegments = segments.slice(0, firstNewSegmentIndex); + const newSegments = segments.slice(firstNewSegmentIndex); + const distances = previousSegments.map(segment => segment.ray.dragRulerVisitedSpaces[segment.ray.dragRulerVisitedSpaces.length - 1].distance); + previousSegments.forEach(segment => segment.ray.terrainRulerVisitedSpaces = duplicate(segment.ray.dragRulerVisitedSpaces)); + opts.costFunction = (x, y) => getCostFromSpeedProvider(token, getAreaFromPositionAndShape({x, y}, shape), {x, y}); + if (previousSegments.length > 0) + opts.terrainRulerInitialState = previousSegments[previousSegments.length - 1]; + return distances.concat(terrainRuler.measureDistances(newSegments, opts)); + } + else { + return canvas.grid.measureDistances(segments, options); + } } + diff --git a/src/foundry_imports.js b/src/foundry_imports.js index ac59be0..b5d1f36 100644 --- a/src/foundry_imports.js +++ b/src/foundry_imports.js @@ -136,6 +136,8 @@ export function measure(destination, {gridSpaces=true, snap=false} = {}) { const centeredRay = new Ray(centeredOrigin, centeredDest) ray.isPrevious = Boolean(origin.isPrevious); centeredRay.isPrevious = ray.isPrevious; + ray.dragRulerVisitedSpaces = origin.dragRulerVisitedSpaces; + centeredRay.dragRulerVisitedSpaces = ray.dragRulerVisitedSpaces; if (ray.distance < 10) { if (label) label.visible = false; continue; diff --git a/src/movement_tracking.js b/src/movement_tracking.js index 2d1ecaf..c27cc6a 100644 --- a/src/movement_tracking.js +++ b/src/movement_tracking.js @@ -1,3 +1,6 @@ +import {measureDistances} from "./compatibility.js"; +import {getTokenShape} from "./util.js"; + function initTrackingFlag(combatant) { const initialFlag = {passedWaypoints: [], trackedRound: 0}; let dragRulerFlag = combatant.flags?.dragRuler; @@ -37,11 +40,19 @@ export async function trackRays(token, rays) { } // Add the passed waypoints to the combatant - const waypoints = combatant.flags.dragRuler.passedWaypoints; + const terrainRulerAvailable = game.modules.get("terrain-ruler")?.active && canvas.grid.type !== CONST.GRID_TYPES.GRIDLESS; + const dragRulerFlags = combatant.flags.dragRuler; + const waypoints = dragRulerFlags.passedWaypoints; for (const ray of rays) { // Ignore rays that have the same start and end coordinates - if (ray.A.x !== ray.B.x || ray.A.y !== ray.B.y) + if (ray.A.x !== ray.B.x || ray.A.y !== ray.B.y) { + if (terrainRulerAvailable) { + measureDistances([{ray}], token, getTokenShape(token), true, {terrainRulerInitialState: dragRulerFlags.rulerState}); + ray.A.dragRulerVisitedSpaces = ray.terrainRulerVisitedSpaces; + dragRulerFlags.rulerState = ray.terrainRulerFinalState; + } waypoints.push(ray.A); + } } await combat.updateEmbeddedEntity("Combatant", {_id: combatant._id, flags: combatant.flags}, {diff: false}); } diff --git a/src/ruler.js b/src/ruler.js index 578696a..ce734e1 100644 --- a/src/ruler.js +++ b/src/ruler.js @@ -70,7 +70,7 @@ export class DragRulerRuler extends Ruler { } dragRulerAddWaypointHistory(waypoints) { - waypoints = waypoints.map(waypoint => {return {x: waypoint.x, y: waypoint.y, isPrevious: true}}); + waypoints.forEach(waypoint => waypoint.isPrevious = true); this.waypoints = this.waypoints.concat(waypoints); for (const waypoint of waypoints) { this.labels.addChild(new PreciseText("", CONFIG.canvasTextStyle));