Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| aa2b8b3928 | |||
| a164811bb6 | |||
| 752b8375ab | |||
| 32b38d8efe | |||
| c3a62e3646 | |||
| 39f7bab4b6 | |||
| a3be4ceb03 | |||
| b275e777db | |||
| 035cfb8969 | |||
| 90a25f467b | |||
| ab85b98a5c | |||
| 1669edf757 | |||
| d1b5f7c39b | |||
| 24f1e78092 | |||
| 854903a314 | |||
| 232eca74de | |||
| 9c7d4ead50 | |||
| a91c3c1b8c | |||
| 99d057bffc |
@@ -1,3 +1,30 @@
|
||||
## 1.9.0
|
||||
### New features
|
||||
- On Gridless scenes, tokens can now snap to their speed limits, to make full usage of a token's movement speed easier. This feature can be temporarily disabled by pressing Shift during drag and can be disabled completely in the settings.
|
||||
|
||||
### Bugfixes
|
||||
- Non-square tokens (e.g. 2x1) now work correctly on square grids
|
||||
- When modifying difficult terrain that a token has already moved over, this the movement history of the token won't change anymore (this was a regression introduced in 1.8.0)
|
||||
- Fixed a bug that prevented pausing/unpausing the game when no scene was active
|
||||
|
||||
### API
|
||||
- Added `dragRuler.getColorForDistanceAndToken` API endpoint that allows other modules to receive the highlight color for a specified distance with a given token.
|
||||
|
||||
|
||||
## 1.8.2
|
||||
### Compatibility
|
||||
- The generic speed provider defaults have been updated for lance 1.0 (thanks to BoltsJ!)
|
||||
- Eliminated a deprecation warning when both Drag Ruler and Hex Size Support are enabled (thanks Argonius-Angelus!)
|
||||
|
||||
|
||||
## 1.8.1
|
||||
### Bugfixes
|
||||
- Fixed a bug where the function that was bound to the spacebar key wouldn't work correctly when the "Toggle Snap To Grid" module was enabled
|
||||
|
||||
### Translation
|
||||
- Updated Spanish translation (thanks to Viriato139ac#342)
|
||||
|
||||
|
||||
## 1.8.0
|
||||
### New features
|
||||
- Pressing escape during a drag now cancels the drag
|
||||
|
||||
@@ -37,10 +37,16 @@ Drag Ruler will work with all Foundry VTT game systems. However some game system
|
||||
|
||||
The game systems that offer Drag Ruler integration are:
|
||||
- Cypher System (starting with version 1.13.0)
|
||||
- GURPS 4th Edition Game Aid (Unofficial) (starting with version 0.9.1)
|
||||
- Ironclaw Second Edition (starting with version 0.2.2)
|
||||
- Lancer (via the module [Lancer Speed Provider](https://foundryvtt.com/packages/lancer-speed-provider))
|
||||
- Pathfinder 1 (starting with version 0.77.3)
|
||||
- Pathfinder 2e (via the module [PF2E Drag Ruler Integration](https://foundryvtt.com/packages/pf2e-dragruler/))
|
||||
- Shadowrun 5th Edition (via the module [Drag Ruler Integration for Shadowrun 5E](https://foundryvtt.com/packages/drag-ruler-integration-for-shadowrun-5e))
|
||||
- Starfinder (via the module [Starfinder Drag Ruler Integration](https://foundryvtt.com/packages/starfinder-drag-ruler))
|
||||
- Stargate RPG (starting with version 1.6.0)
|
||||
- Tagmar RPG (starting with version 1.1.4)
|
||||
- TheWitcherTRPG (starting with version 0.0.62)
|
||||
- Tormenta20 (starting with version 1.1.37)
|
||||
- Shadow of the Demon Lord (starting with version 1.7.15)
|
||||
- Wasteland Ventures (starting with version 0.1.0)
|
||||
|
||||
@@ -81,6 +81,10 @@
|
||||
"swapSpacebarRightClick": {
|
||||
"name": "Leertaste und Rechtsklick tauschen",
|
||||
"hint": "Die Funktionen der Leertaste und des Rechtsklicks sind, während eine Spielfigur bewegt wird, vertauscht. Wenn diese Option aktiviert wird können mit Rechtsklick Wegpunkte gesetzt werden und mit der Leertaste werden sie wieder gelöscht."
|
||||
},
|
||||
"useGridlessraster": {
|
||||
"name": "Geschwindigkeitsraster aktivieren",
|
||||
"hint": "Lässt Spielfiguren auf gitterlosen Szenen an deren Geschwindigkeitsgrenzen einrasten. Dies kann vorübergehend deaktiviert werden, indem während des ziehens die Umschalttaste gedrückt wird."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,6 +81,10 @@
|
||||
"swapSpacebarRightClick": {
|
||||
"name": "Swap spacebar and right click",
|
||||
"hint": "Swaps the functions of spacebar and right click during dragging. If enabled right click will place waypoints and spacebar will delete them"
|
||||
},
|
||||
"useGridlessRaster": {
|
||||
"name": "Use speed based snapping",
|
||||
"hint": "On Gridless scenes, this makes tokens snap to the token's speed ranges. This can be temporarily disabled by pressing Shift during drag."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,10 @@
|
||||
"name": "Mostrar velocidad de los PJs a todo el mundo",
|
||||
"hint": "Si se habilita, se mostrará a todo el mundo los códigos de colores de las rutas de los PJs, incluso si no tienen permisos de observador para ese personaje"
|
||||
},
|
||||
"autoStartMeasurement": {
|
||||
"name": "Comenzar a medir automáticamente",
|
||||
"hint": "Si se habilita, Drag Ruler comenzará a medir en cuanto se comience a arrastrar un icono. Si se deshabilita, Drag Ruler permanecerá inactivo y comenzará a medir únicamente cuando se presione el botón configurado para añadir un nuevo punto de ruta"
|
||||
},
|
||||
"enableMovementHistory": {
|
||||
"name": "Habilitar historial de movimiento durante el combate",
|
||||
"hint": "Si se habilita, Drag Ruler recordará la ruta que ha seguido un icono en su turno y la mostrará al seleccionarlo de nuevo"
|
||||
|
||||
+3
-3
@@ -2,9 +2,9 @@
|
||||
"name": "drag-ruler",
|
||||
"title": "Drag Ruler",
|
||||
"description": "When dragging a token displays a ruler showing how far you've moved that token.",
|
||||
"version": "1.8.0",
|
||||
"version": "1.9.0",
|
||||
"minimumCoreVersion" : "0.8.5",
|
||||
"compatibleCoreVersion" : "0.8.8",
|
||||
"compatibleCoreVersion" : "0.8.9",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Manuel Vögele",
|
||||
@@ -59,7 +59,7 @@
|
||||
],
|
||||
"socket": true,
|
||||
"url": "https://github.com/manuelVo/foundryvtt-drag-ruler",
|
||||
"download": "https://github.com/manuelVo/foundryvtt-drag-ruler/archive/v1.8.0.zip",
|
||||
"download": "https://github.com/manuelVo/foundryvtt-drag-ruler/archive/v1.9.0.zip",
|
||||
"manifest": "https://raw.githubusercontent.com/manuelVo/foundryvtt-drag-ruler/master/module.json",
|
||||
"readme": "https://github.com/manuelVo/foundryvtt-drag-ruler/blob/master/README.md",
|
||||
"changelog": "https://github.com/manuelVo/foundryvtt-drag-ruler/blob/master/CHANGELOG.md",
|
||||
|
||||
+16
-1
@@ -116,11 +116,26 @@ export function getCostFromSpeedProvider(token, area, options) {
|
||||
}
|
||||
}
|
||||
|
||||
export function getColorForDistanceAndToken(distance, token, ranges=null) {
|
||||
if (!ranges) {
|
||||
ranges = getRangesFromSpeedProvider(token);
|
||||
}
|
||||
if (ranges.length === 0)
|
||||
return this.color;
|
||||
const currentRange = ranges.reduce((minRange, currentRange) => {
|
||||
if (distance <= currentRange.range && currentRange.range < minRange.range)
|
||||
return currentRange;
|
||||
return minRange;
|
||||
}, {range: Infinity, color: getUnreachableColorFromSpeedProvider()});
|
||||
return currentRange.color;
|
||||
}
|
||||
|
||||
export function getMovedDistanceFromToken(token) {
|
||||
const terrainRulerAvailable = game.modules.get("terrain-ruler")?.active;
|
||||
const history = getMovementHistory(token);
|
||||
const segments = Ruler.dragRulerGetRaysFromWaypoints(history, {x: token.x, y: token.y}).map(ray => {return {ray}});
|
||||
const shape = getTokenShape(token);
|
||||
const distances = measureDistances(segments, token, shape);
|
||||
const distances = measureDistances(segments, token, shape, {enableTerrainRuler: terrainRulerAvailable});
|
||||
// Sum up the distances
|
||||
return distances.reduce((acc, val) => acc + val, 0);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {getCostFromSpeedProvider} from "./api.js";
|
||||
import {getColorForDistance} from "./main.js"
|
||||
import {settingsKey} from "./settings.js";
|
||||
import {getAreaFromPositionAndShape, highlightTokenShape} from "./util.js";
|
||||
|
||||
@@ -10,7 +9,7 @@ export function getHexSizeSupportTokenGridCenter(token) {
|
||||
|
||||
export function highlightMeasurementTerrainRuler(ray, startDistance, tokenShape=[{x: 0, y: 0}], alpha=1) {
|
||||
for (const space of ray.terrainRulerVisitedSpaces.reverse()) {
|
||||
const color = getColorForDistance.call(this, startDistance, space.distance)
|
||||
const color = this.dragRulerGetColorForDistance(startDistance + space.distance);
|
||||
highlightTokenShape.call(this, space, tokenShape, color, alpha)
|
||||
}
|
||||
}
|
||||
@@ -63,9 +62,6 @@ export function checkDependencies() {
|
||||
if (game.modules.get("enhanced-terrain-layer")?.active) {
|
||||
enabledTerrainModule = game.modules.get("enhanced-terrain-layer").data.title;
|
||||
}
|
||||
else if (game.modules.get("TerrainLayer")?.active) {
|
||||
enabledTerrainModule = game.modules.get("TerrainLayer").data.title;
|
||||
}
|
||||
if (enabledTerrainModule) {
|
||||
new Dialog({
|
||||
title: game.i18n.localize("drag-ruler.dependencies.terrain-ruler.title"),
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {highlightMeasurementTerrainRuler, measureDistances} from "./compatibility.js";
|
||||
import {getGridPositionFromPixels} from "./foundry_fixes.js";
|
||||
import {Line} from "./geometry.js";
|
||||
import {getColorForDistance} from "./main.js"
|
||||
import {trackRays} from "./movement_tracking.js"
|
||||
import {recalculate} from "./socket.js";
|
||||
import {applyTokenSizeOffset, getSnapPointForEntity, getSnapPointForToken, getTokenShape, highlightTokenShape, zip} from "./util.js";
|
||||
@@ -169,7 +168,7 @@ export function measure(destination, options={}) {
|
||||
options.ignoreGrid = false;
|
||||
}
|
||||
|
||||
options.enableTerrainRuler = isToken && game.modules.get("terrain-ruler")?.active && (!game.modules.get("TerrainLayer")?.active || canvas.grid.type !== CONST.GRID_TYPES.GRIDLESS);
|
||||
options.enableTerrainRuler = isToken && game.modules.get("terrain-ruler")?.active;
|
||||
|
||||
const waypoints = this.waypoints.concat([destination]);
|
||||
// Move the waypoints to the center of the grid if a size is used that measures from edge to edge
|
||||
@@ -229,7 +228,7 @@ export function measure(destination, options={}) {
|
||||
r.clear();
|
||||
let rulerColor
|
||||
if (!options.gridSpaces || canvas.grid.type === CONST.GRID_TYPES.GRIDLESS)
|
||||
rulerColor = getColorForDistance.call(this, totalDistance)
|
||||
rulerColor = this.dragRulerGetColorForDistance(totalDistance);
|
||||
else
|
||||
rulerColor = this.color
|
||||
for (const [s, cs] of zip(segments.reverse(), centeredSegments.reverse())) {
|
||||
@@ -301,7 +300,7 @@ export function highlightMeasurementNative(ray, startDistance, tokenShape=[{x: 0
|
||||
// Highlight the grid position
|
||||
let [xg, yg] = canvas.grid.grid.getPixelsFromGridPosition(x1, y1);
|
||||
const subDistance = canvas.grid.measureDistances([{ray: new Ray(ray.A, {x: xg, y: yg})}], {gridSpaces: true})[0]
|
||||
const color = dragRuler.getColorForDistance.call(this, startDistance, subDistance)
|
||||
const color = this.dragRulerGetColorForDistance(startDistance + subDistance);
|
||||
const snapPoint = getSnapPointForToken(...canvas.grid.getTopLeft(x, y), this.draggedEntity);
|
||||
const [snapX, snapY] = getGridPositionFromPixels(snapPoint.x + 1, snapPoint.y + 1);
|
||||
|
||||
@@ -314,7 +313,7 @@ export function highlightMeasurementNative(ray, startDistance, tokenShape=[{x: 0
|
||||
let [x1h, y1h] = canvas.grid.grid.getGridPositionFromPixels(x, y);
|
||||
let [xgh, ygh] = canvas.grid.grid.getPixelsFromGridPosition(x1h, y1h);
|
||||
const subDistance = canvas.grid.measureDistances([{ray: new Ray(ray.A, {x: xgh, y: ygh})}], {gridSpaces: true})[0]
|
||||
const color = dragRuler.getColorForDistance.call(this, startDistance, subDistance)
|
||||
const color = this.dragRulerGetColorForDistance(startDistance + subDistance);
|
||||
const snapPoint = getSnapPointForToken(...canvas.grid.getTopLeft(x, y), this.draggedEntity);
|
||||
const [snapX, snapY] = getGridPositionFromPixels(snapPoint.x + 1, snapPoint.y + 1);
|
||||
highlightTokenShape.call(this, {x: snapX, y: snapY}, tokenShape, color, alpha);
|
||||
|
||||
+71
-26
@@ -1,7 +1,7 @@
|
||||
"use strict"
|
||||
|
||||
import {currentSpeedProvider, getMovedDistanceFromToken, getRangesFromSpeedProvider, getUnreachableColorFromSpeedProvider, initApi, registerModule, registerSystem} from "./api.js"
|
||||
import {checkDependencies, getHexSizeSupportTokenGridCenter} from "./compatibility.js";
|
||||
import {currentSpeedProvider, getColorForDistanceAndToken, getMovedDistanceFromToken, getRangesFromSpeedProvider, initApi, registerModule, registerSystem} from "./api.js";
|
||||
import {checkDependencies, getHexSizeSupportTokenGridCenter, highlightMeasurementTerrainRuler} from "./compatibility.js";
|
||||
import {moveEntities, onMouseMove} from "./foundry_imports.js"
|
||||
import {performMigrations} from "./migration.js"
|
||||
import {DragRulerRuler} from "./ruler.js";
|
||||
@@ -22,7 +22,7 @@ Hooks.once("init", () => {
|
||||
Ruler = DragRulerRuler;
|
||||
|
||||
window.dragRuler = {
|
||||
getColorForDistance,
|
||||
getColorForDistanceAndToken,
|
||||
getMovedDistanceFromToken,
|
||||
registerModule,
|
||||
registerSystem,
|
||||
@@ -66,6 +66,8 @@ function hookDragHandlers(entityType) {
|
||||
|
||||
const originalDragLeftMoveHandler = entityType.prototype._onDragLeftMove
|
||||
entityType.prototype._onDragLeftMove = function (event) {
|
||||
if (entityType === Token)
|
||||
applyGridlessSnapping.call(this, event);
|
||||
originalDragLeftMoveHandler.call(this, event)
|
||||
onEntityLeftDragMove.call(this, event)
|
||||
}
|
||||
@@ -149,7 +151,8 @@ function onKeyShift(up) {
|
||||
|
||||
function onKeySpace(up) {
|
||||
const ruler = canvas.controls.ruler;
|
||||
if (!ruler.draggedEntity)
|
||||
// Ruler can end up being undefined here if no canvas is active
|
||||
if (!ruler?.draggedEntity)
|
||||
return false;
|
||||
|
||||
if (ruler._state !== Ruler.STATES.INACTIVE)
|
||||
@@ -266,28 +269,70 @@ function onEntityDragLeftCancel(event) {
|
||||
return true
|
||||
}
|
||||
|
||||
export function getColorForDistance(startDistance, subDistance=0) {
|
||||
if (!this.isDragRuler)
|
||||
return this.color
|
||||
if (!this.draggedEntity.actor) {
|
||||
return this.color;
|
||||
function applyGridlessSnapping(event) {
|
||||
const ruler = canvas.controls.ruler;
|
||||
if (!game.settings.get(settingsKey, "useGridlessRaster"))
|
||||
return;
|
||||
if (!ruler.isDragRuler)
|
||||
return;
|
||||
if (game.keyboard.isDown("Shift"))
|
||||
return;
|
||||
if (canvas.grid.type !== CONST.GRID_TYPES.GRIDLESS)
|
||||
return;
|
||||
|
||||
const rasterWidth = 35 / canvas.stage.scale.x;
|
||||
const tokenX = event.data.destination.x;
|
||||
const tokenY = event.data.destination.y;
|
||||
const destination = {x: tokenX + ruler.rulerOffset.x, y: tokenY + ruler.rulerOffset.y};
|
||||
const ranges = getRangesFromSpeedProvider(ruler.draggedEntity);
|
||||
|
||||
const terrainRulerAvailable = game.modules.get("terrain-ruler")?.active;
|
||||
if (terrainRulerAvailable) {
|
||||
const segments = Ruler.dragRulerGetRaysFromWaypoints(ruler.waypoints, destination).map(ray => {return {ray}});
|
||||
const pinpointDistances = new Map();
|
||||
for (const range of ranges) {
|
||||
pinpointDistances.set(range.range, null);
|
||||
}
|
||||
terrainRuler.measureDistances(segments, {pinpointDistances});
|
||||
const targetDistance = Array.from(pinpointDistances.entries())
|
||||
.filter(([_key, val]) => val)
|
||||
.reduce((value, current) => value[0] > current[0] ? value : current, [0, null]);
|
||||
const rasterLocation = targetDistance[1];
|
||||
if (rasterLocation) {
|
||||
const deltaX = destination.x - rasterLocation.x;
|
||||
const deltaY = destination.y - rasterLocation.y;
|
||||
const rasterDistance = Math.hypot(deltaX, deltaY);
|
||||
if (rasterDistance < rasterWidth) {
|
||||
event.data.destination.x = rasterLocation.x - ruler.rulerOffset.x;
|
||||
event.data.destination.y = rasterLocation.y - ruler.rulerOffset.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Don't apply colors if the current user doesn't have at least observer permissions
|
||||
if (this.draggedEntity.actor.permission < 2) {
|
||||
// If this is a pc and alwaysShowSpeedForPCs is enabled we show the color anyway
|
||||
if (!(this.draggedEntity.actor.data.type === "character" && game.settings.get(settingsKey, "alwaysShowSpeedForPCs")))
|
||||
return this.color
|
||||
else {
|
||||
let waypointDistance = 0;
|
||||
let origin = event.data.origin;
|
||||
if (ruler.waypoints.length > 1) {
|
||||
const segments = Ruler.dragRulerGetRaysFromWaypoints(ruler.waypoints, destination).map(ray => {return {ray}});
|
||||
origin = segments.pop().ray.A;
|
||||
waypointDistance = canvas.grid.measureDistances(segments).reduce((a, b) => a + b);
|
||||
origin = {x: origin.x - ruler.rulerOffset.x, y: origin.y - ruler.rulerOffset.y};
|
||||
}
|
||||
|
||||
const deltaX = tokenX - origin.x;
|
||||
const deltaY = tokenY - origin.y;
|
||||
const distance = Math.hypot(deltaX, deltaY);
|
||||
// targetRange will be the largest range that's still smaller than distance
|
||||
let targetDistance = ranges
|
||||
.map(range => range.range)
|
||||
.map(range => range - waypointDistance)
|
||||
.map(range => range * canvas.dimensions.size / canvas.dimensions.distance)
|
||||
.filter(range => range < distance)
|
||||
.reduce((a, b) => Math.max(a, b), 0);
|
||||
if (targetDistance) {
|
||||
if (distance < targetDistance + rasterWidth) {
|
||||
event.data.destination.x = origin.x + deltaX * targetDistance / distance;
|
||||
event.data.destination.y = origin.y + deltaY * targetDistance / distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
const distance = startDistance + subDistance
|
||||
if (!this.dragRulerRanges)
|
||||
this.dragRulerRanges = getRangesFromSpeedProvider(this.draggedEntity);
|
||||
const ranges = this.dragRulerRanges;
|
||||
if (ranges.length === 0)
|
||||
return this.color
|
||||
const currentRange = ranges.reduce((minRange, currentRange) => {
|
||||
if (distance <= currentRange.range && currentRange.range < minRange.range)
|
||||
return currentRange
|
||||
return minRange
|
||||
}, {range: Infinity, color: getUnreachableColorFromSpeedProvider()})
|
||||
return currentRange.color
|
||||
}
|
||||
|
||||
@@ -49,14 +49,14 @@ function calculateUpdate(combat, token, rays) {
|
||||
}
|
||||
|
||||
// Add the passed waypoints to the combatant
|
||||
const terrainRulerAvailable = game.modules.get("terrain-ruler")?.active && (!game.modules.get("TerrainLayer")?.active || canvas.grid.type !== CONST.GRID_TYPES.GRIDLESS);
|
||||
const terrainRulerAvailable = game.modules.get("terrain-ruler")?.active;
|
||||
const dragRulerFlags = combatant.data.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 (terrainRulerAvailable) {
|
||||
measureDistances([{ray}], token, getTokenShape(token), {terrainRulerInitialState: waypoints[waypoints.length - 1]?.dragRulerFinalState});
|
||||
measureDistances([{ray}], token, getTokenShape(token), {terrainRulerInitialState: waypoints[waypoints.length - 1]?.dragRulerFinalState, enableTerrainRuler: terrainRulerAvailable});
|
||||
ray.A.dragRulerVisitedSpaces = ray.terrainRulerVisitedSpaces;
|
||||
ray.A.dragRulerFinalState = ray.terrainRulerFinalState;
|
||||
}
|
||||
|
||||
+20
-1
@@ -1,3 +1,4 @@
|
||||
import {getColorForDistanceAndToken, getRangesFromSpeedProvider} from "./api.js";
|
||||
import {cancelScheduledMeasurement, measure} from "./foundry_imports.js"
|
||||
import {getMovementHistory} from "./movement_tracking.js";
|
||||
import {settingsKey} from "./settings.js";
|
||||
@@ -25,7 +26,7 @@ export class DragRulerRuler extends Ruler {
|
||||
return await super.moveToken(event);
|
||||
|
||||
let options = {};
|
||||
setSnapParameterOnOptions(this, event, options);
|
||||
setSnapParameterOnOptions(this, options);
|
||||
|
||||
if (!game.settings.get(settingsKey, "swapSpacebarRightClick")) {
|
||||
this.dragRulerAddWaypoint(this.destination, options);
|
||||
@@ -152,4 +153,22 @@ export class DragRulerRuler extends Ruler {
|
||||
return ray;
|
||||
});
|
||||
}
|
||||
|
||||
dragRulerGetColorForDistance(distance) {
|
||||
if (!this.isDragRuler)
|
||||
return this.color;
|
||||
if (!this.draggedEntity.actor) {
|
||||
return this.color;
|
||||
}
|
||||
// Don't apply colors if the current user doesn't have at least observer permissions
|
||||
if (this.draggedEntity.actor.permission < 2) {
|
||||
// If this is a pc and alwaysShowSpeedForPCs is enabled we show the color anyway
|
||||
if (!(this.draggedEntity.actor.data.type === "character" && game.settings.get(settingsKey, "alwaysShowSpeedForPCs")))
|
||||
return this.color;
|
||||
}
|
||||
distance = Math.round(distance * 100) / 100;
|
||||
if (!this.dragRulerRanges)
|
||||
this.dragRulerRanges = getRangesFromSpeedProvider(this.draggedEntity);
|
||||
return getColorForDistanceAndToken(distance, this.draggedEntity, this.dragRulerRanges);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,15 @@ export function registerSettings() {
|
||||
default: false,
|
||||
})
|
||||
|
||||
game.settings.register(settingsKey, "useGridlessRaster", {
|
||||
name: "drag-ruler.settings.useGridlessRaster.name",
|
||||
hint: "drag-ruler.settings.useGridlessRaster.hint",
|
||||
scope: "client",
|
||||
config: true,
|
||||
type: Boolean,
|
||||
default: true,
|
||||
});
|
||||
|
||||
game.settings.register(settingsKey, "alwaysShowSpeedForPCs", {
|
||||
name: "drag-ruler.settings.alwaysShowSpeedForPCs.name",
|
||||
hint: "drag-ruler.settings.alwaysShowSpeedForPCs.hint",
|
||||
|
||||
@@ -63,9 +63,9 @@ export class SpeedProvider {
|
||||
* (1 is regular cost, 2 costs double, 3 costs triple, ...)
|
||||
*
|
||||
* Parameters:
|
||||
* - options: An object used to configure TerrainLayer's cost calculation. Ex: If options.ignoreGrid is set to true, then Euclidean measurement can be forced on a gridded map.
|
||||
* - options: An object used to configure Enhanced Terrain Layer's cost calculation. Ex: If options.ignoreGrid is set to true, then Euclidean measurement can be forced on a gridded map.
|
||||
*
|
||||
* This function is only called if the TerrainLayer and TerrainRuler modules are enabled.
|
||||
* This function is only called if the Enhanced Terrain Layer and Terrain Ruler modules are enabled.
|
||||
*
|
||||
* Implementing this method is optional and only needs to be done if you want to provide a custom cost function (for example to allow tokens to ignore difficult terrain)
|
||||
*/
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ export function getDefaultSpeedAttribute() {
|
||||
case "dnd5e":
|
||||
return "actor.data.data.attributes.movement.walk"
|
||||
case "lancer":
|
||||
return "actor.data.data.mech.speed"
|
||||
return "actor.data.data.derived.speed"
|
||||
case "pf1":
|
||||
case "D35E":
|
||||
return "actor.data.data.attributes.speed.land.total"
|
||||
|
||||
+44
-16
@@ -10,33 +10,61 @@ export function getSnapPointForToken(x, y, token) {
|
||||
if (canvas.grid.type === CONST.GRID_TYPES.GRIDLESS) {
|
||||
return new PIXI.Point(x, y);
|
||||
}
|
||||
if (canvas.grid.isHex && game.modules.get("hex-size-support")?.active && CONFIG.hexSizeSupport.getAltSnappingFlag(token)) {
|
||||
if (token.getFlag("hex-size-support", "borderSize") % 2 === 0) {
|
||||
const snapPoint = CONFIG.hexSizeSupport.findVertexSnapPoint(x, y, token, canvas.grid.grid)
|
||||
return new PIXI.Point(snapPoint.x, snapPoint.y)
|
||||
if (canvas.grid.isHex) {
|
||||
if (game.modules.get("hex-size-support")?.active && CONFIG.hexSizeSupport.getAltSnappingFlag(token)) {
|
||||
if (token.document.getFlag("hex-size-support", "borderSize") % 2 === 0) {
|
||||
const snapPoint = CONFIG.hexSizeSupport.findVertexSnapPoint(x, y, token, canvas.grid.grid)
|
||||
return new PIXI.Point(snapPoint.x, snapPoint.y)
|
||||
}
|
||||
else {
|
||||
return new PIXI.Point(...canvas.grid.getCenter(x, y))
|
||||
}
|
||||
}
|
||||
else {
|
||||
return new PIXI.Point(...canvas.grid.getCenter(x, y))
|
||||
return new PIXI.Point(...canvas.grid.getCenter(x, y));
|
||||
}
|
||||
}
|
||||
|
||||
const [topLeftX, topLeftY] = canvas.grid.getTopLeft(x, y);
|
||||
let cellX, cellY;
|
||||
if (token.data.width % 2 === 0)
|
||||
cellX = x - canvas.grid.h / 2;
|
||||
else
|
||||
cellX = x;
|
||||
if (token.data.height % 2 === 0)
|
||||
cellY = y - canvas.grid.h / 2;
|
||||
else
|
||||
cellY = y;
|
||||
const [centerX, centerY] = canvas.grid.getCenter(cellX, cellY);
|
||||
let snapX, snapY;
|
||||
// Tiny tokens can snap to the cells corners
|
||||
if (!canvas.grid.isHex && token.data.width <= 0.5) {
|
||||
const [topLeftX, topLeftY] = canvas.grid.getTopLeft(x, y);
|
||||
if (token.data.width <= 0.5) {
|
||||
const offsetX = x - topLeftX;
|
||||
const offsetY = y - topLeftY;
|
||||
const subGridWidth = Math.floor(canvas.grid.w / 2);
|
||||
const subGridHeight = Math.floor(canvas.grid.h / 2);
|
||||
const subGridPosX = Math.floor(offsetX / subGridWidth);
|
||||
const subGridPosY = Math.floor(offsetY / subGridHeight);
|
||||
return new PIXI.Point(topLeftX + (subGridPosX + 0.5) * subGridWidth, topLeftY + (subGridPosY + 0.5) * subGridHeight);
|
||||
snapX = topLeftX + (subGridPosX + 0.5) * subGridWidth;
|
||||
}
|
||||
// Hex tokens, tokens with odd multipliers (1x1, 3x3, ...) and tokens smaller than 1x1 but bigger than 0.5x0.5 snap to the center of the grid cell
|
||||
if (canvas.grid.isHex || Math.round(token.data.width) % 2 === 1 || token.data.width < 1) {
|
||||
return new PIXI.Point(...canvas.grid.getCenter(x, y))
|
||||
// Tokens with odd multipliers (1x1, 3x3, ...) and tokens smaller than 1x1 but bigger than 0.5x0.5 snap to the center of the grid cell
|
||||
else if (Math.round(token.data.width) % 2 === 1 || token.data.width < 1) {
|
||||
snapX = centerX;
|
||||
}
|
||||
// All remaining tokens (those with even or fractional multipliers on square grids) snap to the intersection points of the grid
|
||||
const [snappedX, snappedY] = canvas.grid.getCenter(x - canvas.grid.w / 2, y - canvas.grid.h / 2)
|
||||
return new PIXI.Point(snappedX + canvas.grid.w / 2, snappedY + canvas.grid.h / 2)
|
||||
else {
|
||||
snapX = centerX + canvas.grid.w / 2;
|
||||
}
|
||||
if (token.data.height <= 0.5) {
|
||||
const offsetY = y - topLeftY;
|
||||
const subGridHeight = Math.floor(canvas.grid.h / 2);
|
||||
const subGridPosY = Math.floor(offsetY / subGridHeight);
|
||||
snapY = topLeftY + (subGridPosY + 0.5) * subGridHeight;
|
||||
}
|
||||
else if (Math.round(token.data.height) % 2 === 1 || token.data.height < 1) {
|
||||
snapY = centerY;
|
||||
}
|
||||
else {
|
||||
snapY = centerY + canvas.grid.h / 2;
|
||||
}
|
||||
return new PIXI.Point(snapX, snapY);
|
||||
}
|
||||
|
||||
export function getSnapPointForMeasuredTemplate(x, y) {
|
||||
|
||||
Reference in New Issue
Block a user