Compare commits

..

22 Commits

Author SHA1 Message Date
Manuel Vögele 0588d3ef8b Pathfinding prerelease 2021-07-19 22:40:02 +02:00
Manuel Vögele b084d25cb6 Add an option to do pathfinding automatically 2021-07-19 22:39:48 +02:00
Manuel Vögele 654847563f Reduce broken caching 2021-07-19 22:04:25 +02:00
Manuel Vögele baca42a2f8 Broadcast pathfinding waypoints to other players 2021-07-19 22:04:25 +02:00
Manuel Vögele 68ee098e61 Penalize diagonals minimally to disincentivise using unnecessary diagonals 2021-07-19 22:04:25 +02:00
Manuel Vögele 3300007f93 Initial working pathfinding impl 2021-07-19 22:04:25 +02:00
Manuel Vögele 07d0c37fe9 Release v1.7.7 2021-07-08 22:02:57 +02:00
Manuel Vögele b8b97ac27a Update generic speed provider default for swade (resolves #93) 2021-07-08 22:01:29 +02:00
Manuel Vögele 0e9215e8bb Release v1.7.6 2021-07-08 21:58:01 +02:00
Manuel Vögele dc4355e0de Add spanish translation to readme 2021-07-08 21:57:23 +02:00
José E. Lozano cf7f84d9e4 Add spanish translation (#94) 2021-07-08 21:22:01 +02:00
Manuel Vögele fe8a3b7b39 Verified to work with 0.8.8 2021-07-08 17:37:59 +02:00
Manuel Vögele be9535acd3 Add korean translation to manifest and readme 2021-07-08 17:32:17 +02:00
José E. Lozano 530a16ca5d CoC support (#92) 2021-07-08 17:27:34 +02:00
drdwing 3b9fbac80d Korean translation (#88)
by KLO (discord : KLO#1490)
2021-07-08 10:39:50 +02:00
Manuel Vögele 0456fb0849 Release v1.7.5 2021-06-22 23:20:36 +02:00
Manuel Vögele 01d01f9887 Movement speeds can be floats (fixes #85) 2021-06-22 23:14:53 +02:00
Manuel Vögele 9042b79967 Release v1.7.4 2021-06-18 13:58:54 +02:00
Manuel Vögele 4159d20e18 Verified to work with Foundry 0.8.7 2021-06-18 13:39:10 +02:00
Manuel Vögele 3897577756 Allow the "Monk's Active Tile Triggers" module to interrupt a token movement early 2021-06-18 13:37:26 +02:00
irbian 5c29f401d6 Support D&D 3.5 (#76) 2021-05-27 01:09:12 +02:00
Manuel Vögele 1328d52f94 Send the info whether the dragged entity is a token or a template to the other players (fixes a snapping issue in other players clients) 2021-05-26 16:17:23 +02:00
14 changed files with 401 additions and 12 deletions
+28
View File
@@ -1,3 +1,31 @@
## 1.7.7
### Compatibility
- Updated the default settings for the swade game system. The new default speed attribute points to a speed value that gets adjusted for wounds.
## 1.7.6
### Translation
- Added Korean translation (thanks to KLO#1490)
- Added Spanish translation (thanks to Viriato139ac#342)
### Compatibility
- Drag Ruler's Generic Speed Provider is now awar of good default values for the "Call of Cthulhu 7th edition (Unofficial)" game system
- Drag Ruler is now compatible with Foundry 0.8.8
## 1.7.5
### Bugfixes
- Decimal speeds (as often used in metric game systems) are no longer being rounded down (thanks to DarKDinDoN for diagnosing this bug)
## 1.7.4
### Bugfixes
- Fixed a bug where the ruler would wrongly snap to the grid center for other players when dragging a measurement template
### Compatibility
- Drag Ruler is now compatiblie with the "Monk's Active Tile Triggers" module
- Drag Ruler's Generic Speed Provider is now aware of good default values for the D&D 3.5 game system
- Drag Ruler is now compatible with Foundry 0.8.7
## 1.7.3
### Compatibility
- Drag Ruler is now compatible with Foundry 0.8.5
+2
View File
@@ -53,6 +53,8 @@ Drag Ruler is available in the follwing languages:
- English
- German
- Japanese (thanks to touge)
- Korean (thanks to KLO#1490)
- Spanish (thanks to Viriato139ac#342)
## API
*Audience: This paragraph is intended for module and system devleopers that want to add more complex behavior to Drag Ruler. If you just want to use this plugins features skip this paragraph.*
+4
View File
@@ -34,6 +34,10 @@
"name": "Show PC speed to everyone",
"hint": "If enabled the coloring based on actor speed for player characters will shown to everyone, even if they don't have observer permission for the character sheet."
},
"autoPathfinding": {
"name": "Pathfinding by default",
"hint": "If enabled, dragging a token will automatically use a pathfinding ruler"
},
"enableMovementHistory": {
"name": "Enable movement history during combat",
"hint": "If enabled, Drag Ruler will remember the path a token took during it's turn in combat and will display it when you pick the token back up."
+87
View File
@@ -0,0 +1,87 @@
{
"drag-ruler": {
"I18N": {
"LANGUAGE": "Español",
"MAINTAINERS": "@Viriato139ac#0342"
},
"dependencies": {
"ok": "OK",
"terrain-ruler": {
"title": "Cómo medir a través de terreno difícil con Drag Ruler",
"text": "You have the {moduleName} module enabled. Drag Ruler is able to measure difficult terrain that was placed down using that module. To make this possible Drag Ruler utilizes the Terrain Ruler module. If Terrain Ruler is installed and activated Drag Ruler will automatically start to respect difficult terrain in it's measurements.",
"neverShowAgain": "No volver a mostrar"
},
"socketlib": {
"title": "El módulo Socketlib no está instalado",
"text": "Drag Ruler necesita para su funcionamiento correcto que instale socketlib. Por favor, active socketlib en este mundo"
}
},
"resetMovementHistory": "Reiniciar historial de movimiento",
"genericSpeedProvider": {
"settings": {
"dashMultiplier": {
"name": "Multiplicador por correr",
"hint": "Se puede usar para aplicar a los iconos una velocidad secundaria que use un color distinto en la medición de la ruta a seguir. Establece el valor a 0 para deshabilitar esta velocidad secundaria"
},
"speedAttribute": {
"name": "Attributo de velocidad",
"hint": "El atributo que define la velocidad de movimiento andando del icono. Se usa para los códigos de colores al medir la ruta a seguir"
}
},
"speeds": {
"walk": "caminar",
"dash": "correr"
}
},
"settings": {
"alwaysShowSpeedForPCs": {
"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"
},
"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"
},
"showGMRulerToPlayers": {
"name": "Mostrar regla del GM a los jugadores",
"hint": "Si se deshabilita, no se mostrará la regla de medición de los GMs al resto de usuarios"
},
"speedProviderSettings": {
"name": "Proveedor de configuración de velocidad",
"hint": "El proveedor de ajustes de velocidad contiene todos los ajustes específicos de cada sistema",
"button": "Proveedor de configuración de velocidad",
"windowTitle": "Proveedor de configuración de velocidad",
"headers": {
"speedProvider": "Proveedor de velocidad",
"speedProviderSettings": "Configuraciones específicas del proveedor de velocidad"
},
"activeProvider": {
"name": "Proveedor de velocidad actualmente activo",
"hint": "La configuración que se muestra más abajo depende del proveedor de velocidad activo. Si el GM selecciona un proveedor distinto, los ajustes disponibles puede que cambien"
},
"noSettings": "Este proveedor de velocidad no dispone de ninguna opción de configuración",
"color": {
"name": "Color para {colorName}",
"hint": "Color que se usará para establecer el tono de las cuadrículas que se encuentran dentro del rango {colorName}",
"unreachable": {
"name": "inalcanzable",
"hint": "Color que se usará para las cuadrículas más allá de la distancia máxima de movimiento del icono"
}
},
"speedProvider": {
"name": "Proveedor de configuración de velocidad",
"hint": "Seleccione quien suministra la información de la velocidad de los iconos a la hora de colorear la ruta a seguir. Drag Ruler incluye un proveedor genérico que ofrece una funcionalidad básica y que probablemente funcione para casi todos los sistemas si se usa de forma correcta. Se pueden añadir otros proveedores de velocidad al instalar sistemas o módulos. Seleccionar un proveedor distinto al genérico asegurará una mejor integración con las reglas del sistema que está usando. Las opciones siguientes dependerán del proveedor que seleccione",
"choices": {
"module": "Módulo {name}",
"native": "Genérico",
"system": "Sistema {name}"
}
}
},
"swapSpacebarRightClick": {
"name": "Intercambiar barra espaciadora y clic-derecho",
"hint": "Cambia el funcionamiento de la barra espaciadora y el clic-derecho del ratón mientras se arrastra un icono. Si está habilitado, clic-derecho establecerá puntos en la ruta y la barra espaciadora los borrará"
}
}
}
}
+83
View File
@@ -0,0 +1,83 @@
{
"drag-ruler": {
"dependencies": {
"ok": "OK",
"terrain-ruler": {
"title": "Drag Ruler를 사용한 험지 측정 방법",
"text": "{moduleName} 모듈을 활성화했습니다. Drag Ruler는 해당 모듈을 사용하여 험지를 측정할 수 있습니다. 이렇게 하려면 Terrain Ruler 모듈을 활성화하십시오. Terrain Ruler 모듈을 설치하고 Drag Ruler를 활성화하면 자동적으로 험지를 측정합니다.",
"neverShowAgain": "다시 표시하지 않음"
},
"socketlib": {
"title": "Socketlib 모듈 비탐지",
"text": "Drag Ruler는 Socketlib 모듈이 있어야 합니다. 이 월드에서 해당 모듈을 활성화하십시오."
}
},
"resetMovementHistory": "이동 내역 리셋",
"genericSpeedProvider": {
"settings": {
"dashMultiplier": {
"name": "질주 승수",
"hint": "측정된 경로에 색을 입힐 때 추가 속도를 제공하는 데 사용할 수 있다. 추가 속도를 비활성화하려면 이 값을 0으로 설정한다."
},
"speedAttribute": {
"name": "속도 어트리뷰트",
"hint": "토큰의 이동속도를 정의하는 속성이다. 측정 경로에 색을 입힐 때 사용한다."
}
},
"speeds": {
"walk": "보행",
"dash": "질주"
}
},
"settings": {
"alwaysShowSpeedForPCs": {
"name": "PC 속도를 모두에게 표시",
"hint": "활성화시 플레이어 캐릭터에 대한 관찰자 권한이 없더라도 액터 속도에 따라 색상이 모든 유저에게 표시된다."
},
"enableMovementHistory": {
"name": "전투 중 이동 기록 사용",
"hint": "활성화시 Drag Ruler는 해당 턴에 토큰이 이동한 경로를 기억하고 다시 이동시킬 때 표시한다."
},
"showGMRulerToPlayers": {
"name": "GM 측정자를 플레이어에게 표시",
"hint": "비활성화 시 GM이 아닌 유저에게는 GM의 측정자가 표시되지 않는다."
},
"speedProviderSettings": {
"name": "속도 공급자 설정",
"hint": "속도 공급자 설정은 게임 시스템별 설정을 모두 포함한다.",
"button": "속도 공급자 설정",
"windowTitle": "속도 공급자 설정",
"headers": {
"speedProvider": "속도 공급자",
"speedProviderSettings": "속도 공급자 관련 설정"
},
"activeProvider": {
"name": "현재 활성화된 속도 공급자",
"hint": "아래에 표시된 설정은 활성화된 속도 공급자를 보여준다. GM이 다른 속도 공급자를 선택하면 사용 가능한 설정이 변경될 수 있다."
},
"noSettings": "이 속도 공급자는 구성 옵션을 제공하지 않습니다.",
"color": {
"name": "{colorName} 색상",
"hint": "{colorName} 범위 내에서의 칸의 색상을 지정하는데 사용할 색상.",
"unreachable": {
"name": "도달 불가",
"hint": "드래그한 토큰으로 도달할 수 없는 공간의 색상"
}
},
"speedProvider": {
"name": "속도 설정 공급자",
"hint": "색을 입힐 동안 사용할 토큰에 대한 속도 정보 제공자를 선택한다. Drag Ruler는 기본 기능을 제공하며 올바르게 구성된 경우 모든 게임 시스템에서 작동하는 일반적 속도 공급자를 제공한다. 게임 시스템과 설치된 모듈을 통해 더 많은 속도 공급자를 이용할 수 있다. 일반 속도 공급자와는 다른 속도 공급자를 선택하면 사용 중인 게임 시스템의 규칙에 더 잘 통합될 수 있다.아래 옵션은 여기에서 선택한 속도 공급자에 따라 다르다.",
"choices": {
"module": "모듈 {name}",
"native": "포괄적",
"system": "시스템 {name}"
}
}
},
"swapSpacebarRightClick": {
"name": "스페이스바와 우클릭 스왑",
"hint": "드래그 도중 스페이스바의 기능을 우클릭 기능과 바꾼다. 활성화된 경우 드래그시 우클릭을 사용하면 경유지가 배치되고, 스페이스바가 해당 경유지를 삭제한다."
}
}
}
}
+13 -3
View File
@@ -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.7.3",
"version": "1.7.7-prerelease1",
"minimumCoreVersion" : "0.8.5",
"compatibleCoreVersion" : "0.8.5",
"compatibleCoreVersion" : "0.8.8",
"authors": [
{
"name": "Manuel Vögele",
@@ -35,10 +35,20 @@
"name": "日本語",
"path": "lang/ja.json"
},
{
"lang": "ko",
"name": "한국어",
"path": "lang/ko.json"
},
{
"lang": "zh-tw",
"name": "正體中文",
"path": "lang/zh-tw.json"
},
{
"lang": "es",
"name": "Español",
"path": "lang/es.json"
}
],
"dependencies": [
@@ -49,7 +59,7 @@
],
"socket": true,
"url": "https://github.com/manuelVo/foundryvtt-drag-ruler",
"download": "https://github.com/manuelVo/foundryvtt-drag-ruler/archive/v1.7.3.zip",
"download": "https://codeload.github.com/manuelVo/foundryvtt-drag-ruler/zip/refs/heads/prerelease",
"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",
+18
View File
@@ -16,3 +16,21 @@ export function getGridPositionFromPixels(xPixel, yPixel) {
return [y, x]
return [x, y]
}
export function getGridPositionFromPixelsObj(o) {
const r = {};
[r.x, r.y] = getGridPositionFromPixels(o.x, o.y);
return r;
}
export function getPixelsFromGridPositionObj(o) {
const r = {};
[r.x, r.y] = getPixelsFromGridPosition(o.x, o.y);
return r;
}
export function getCenterFromGridPositionObj(o) {
const r = getPixelsFromGridPositionObj(o);
[r.x, r.y] = canvas.grid.getCenter(r.x, r.y);
return r;
}
+34 -3
View File
@@ -1,8 +1,10 @@
import {highlightMeasurementTerrainRuler, measureDistances} from "./compatibility.js";
import {getGridPositionFromPixels} from "./foundry_fixes.js";
import {getCenterFromGridPositionObj, getGridPositionFromPixels, getGridPositionFromPixelsObj} from "./foundry_fixes.js";
import {Line} from "./geometry.js";
import {getColorForDistance} from "./main.js"
import {trackRays} from "./movement_tracking.js"
import {find_path} from "./pathfinding.js";
import {settingsKey} from "./settings.js";
import {recalculate} from "./socket.js";
import {applyTokenSizeOffset, getSnapPointForEntity, getSnapPointForToken, getTokenShape, highlightTokenShape, zip} from "./util.js";
@@ -72,7 +74,12 @@ async function animateEntities(entities, draggedEntity, draggedRays, wasPaused)
const isToken = draggedEntity instanceof Token;
const animate = isToken && !game.keyboard.isDown("Alt");
const startWaypoint = animate ? 0 : entityAnimationData[0].rays.length - 1;
// This is a flag of the "Monk's Active Tile Triggers" module that signals that the movement should be cancelled early
this.cancelMovement = false;
for (let i = startWaypoint;i < entityAnimationData[0].rays.length; i++) {
if (!wasPaused && game.paused) break;
const entityPaths = entityAnimationData.map(({entity, rays, dx, dy}) => {
const ray = rays[i];
@@ -86,11 +93,18 @@ async function animateEntities(entities, draggedEntity, draggedRays, wasPaused)
await draggedEntity.scene.updateEmbeddedDocuments(draggedEntity.constructor.embeddedName, updates, {animate});
if (animate)
await Promise.all(entityPaths.map(({entity, path}) => entity.animateMovement(path)));
// This is a flag of the "Monk's Active Tile Triggers" module that signals that the movement should be cancelled early
if (this.cancelMovement) {
entityAnimationData.forEach(ead => ead.rays = ead.rays.slice(0, i + 1));
break;
}
}
if (isToken)
trackRays(entities, entityAnimationData.map(({rays}) => rays)).then(() => recalculate(entities));
}
function calculateEntityOffset(entityA, entityB) {
return {x: entityA.data.x - entityB.data.x, y: entityA.data.y - entityB.data.y};
}
@@ -106,6 +120,7 @@ export function onMouseMove(event) {
if (this._state === Ruler.STATES.MOVING) return;
// Extract event data
const destination = {x: event.data.destination.x + this.rulerOffset.x, y: event.data.destination.y + this.rulerOffset.y}
// Hide any existing Token HUD
@@ -121,7 +136,7 @@ function scheduleMeasurement(destination, event) {
const mt = event._measureTime || 0;
const originalEvent = event.data.originalEvent;
if (Date.now() - mt > measurementInterval) {
this.measure(destination, {snap: !originalEvent.shiftKey});
this.measure(destination, {snap: !originalEvent.shiftKey, pathfinding: game.settings.get(settingsKey, "autoPathfinding") != game.keyboard.isDown("y")});
event._measureTime = Date.now();
this._state = Ruler.STATES.MEASURING;
window.clearTimeout(this.deferredMeasurementTimeout);
@@ -138,7 +153,7 @@ function scheduleMeasurement(destination, event) {
}
// This is a modified version of Ruler.measure form foundry 0.7.9
export function measure(destination, {gridSpaces=true, snap=false} = {}) {
export function measure(destination, {gridSpaces=true, snap=false, pathfinding=false} = {}) {
const isToken = this.draggedEntity instanceof Token;
if (isToken && !this.draggedEntity.isVisible)
return []
@@ -147,6 +162,22 @@ export function measure(destination, {gridSpaces=true, snap=false} = {}) {
destination = getSnapPointForEntity(destination.x, destination.y, this.draggedEntity);
}
// Remove waypoints generated by pathfinding
this.waypoints = this.waypoints.filter(waypoint => !waypoint.isPathfinding);
if (isToken && pathfinding) {
let path = find_path(getGridPositionFromPixelsObj(this.waypoints[this.waypoints.length - 1]), getGridPositionFromPixelsObj(destination));
if (path) {
path = path.map(point => getCenterFromGridPositionObj(point));
path.forEach(point => point.isPathfinding = true);
this.waypoints = this.waypoints.concat(path);
}
else {
// Don't show a path if the pathfinding yields no result to show the user that the destination is unreachable
destination = this.waypoints[this.waypoints.length - 1];
}
}
const terrainRulerAvailable = isToken && game.modules.get("terrain-ruler")?.active && (!game.modules.get("TerrainLayer")?.active || canvas.grid.type !== CONST.GRID_TYPES.GRIDLESS);
const waypoints = this.waypoints.concat([destination]);
+2
View File
@@ -9,6 +9,7 @@ import {getMovementHistory, resetMovementHistory} from "./movement_tracking.js";
import {registerSettings, settingsKey} from "./settings.js"
import {recalculate} from "./socket.js";
import {SpeedProvider} from "./speed_provider.js"
import { wipe_cache } from "./pathfinding.js";
Hooks.once("init", () => {
registerSettings()
@@ -137,6 +138,7 @@ function onEntityLeftDragStart(event) {
else
entityCenter = this.center;
ruler.clear();
wipe_cache();
ruler._state = Ruler.STATES.STARTING;
ruler.rulerOffset = {x: entityCenter.x - event.data.origin.x, y: entityCenter.y - event.data.origin.y};
if (isToken && game.settings.get(settingsKey, "enableMovementHistory"))
+98
View File
@@ -0,0 +1,98 @@
import {getCenterFromGridPositionObj} from "./foundry_fixes.js";
// TODO Wipe cache if walls layer is being modified
let cached_nodes = undefined;
function get_node(pos, initialize=true) {
if (!cached_nodes)
// TODO Check if ceil is the right thing to do here
cached_nodes = new Array(Math.ceil(canvas.dimensions.sceneHeight / canvas.dimensions.size));
if (!cached_nodes[pos.y])
cached_nodes[pos.y] = new Array(Math.ceil(canvas.dimensions.sceneWidth / canvas.dimensions.size));
if (!cached_nodes[pos.y][pos.x]) {
cached_nodes[pos.y][pos.x] = {x: pos.x, y: pos.y};
}
const node = cached_nodes[pos.y][pos.x];
if (initialize && !node.edges) {
node.edges = [];
for (const neighborPos of neighbors(pos)) {
// TODO Work with pixels instead of grid locations
if (!canvas.walls.checkCollision(new Ray(getCenterFromGridPositionObj(pos), getCenterFromGridPositionObj(neighborPos)))) {
const neighbor = get_node(neighborPos, false);
node.edges.push({target: neighbor, cost: 1});
}
}
}
return node;
}
function* neighbors(pos) {
for (let y = -1;y < 2;y++) {
for (let x = -1;x < 2;x++) {
if (x != 0 || y != 0)
yield {x: pos.x + x, y: pos.y + y};
}
}
}
function calculate_path(from, to) {
const nextNodes = [{node: get_node(to), cost: 0, estimated: estimate_cost(to, from), previous: null}];
const previousNodes = new Set();
while (nextNodes.length > 0) {
// Sort by estimated cost, high to low
// TODO Re-sorting every iteration is expensive. Think of something better
nextNodes.sort((a, b) => b.estimated - a.estimated);
// Get node with cheapest estimate
const currentNode = nextNodes.pop();
if (currentNode.node.x === from.x && currentNode.node.y === from.y)
return currentNode;
previousNodes.add(currentNode.node);
for (const edge of currentNode.node.edges) {
const neighborNode = get_node(edge.target);
if (previousNodes.has(neighborNode))
continue;
// TODO We currently assume a cost of one for all transitions. Change this for 5/10/5 or difficult terrain support
// We charge an extra 0.0001 for diagonals
const isDiagonal = currentNode.node.x !== neighborNode.x && currentNode.node.y !== neighborNode.y;
const edgeCost = isDiagonal ? 1.0001 : 1;
const neighbor = {node: neighborNode, cost: currentNode.cost + edgeCost, estimated: currentNode.cost + edgeCost + estimate_cost(neighborNode, from), previous: currentNode};
const neighborIndex = nextNodes.findIndex(node => node.node === neighbor.node);
if (neighborIndex >= 0) {
// If the neighbor is cheaper to reach via the current route than through previously discovered routes, replace it
if (nextNodes[neighborIndex].cost > neighbor.cost) {
nextNodes[neighborIndex] = neighbor;
}
}
else {
nextNodes.push(neighbor);
}
}
}
}
function estimate_cost(pos, target) {
return Math.max(Math.abs(pos.x - target.x), Math.abs(pos.y - target.y));
}
export function find_path(from, to) {
const lastNode = calculate_path(from, to);
if (!lastNode)
return null;
const path = [];
let currentNode = lastNode;
while (currentNode) {
// TODO Check if the distance doesn't change
if (path.length >= 2 && !canvas.walls.checkCollision(new Ray(getCenterFromGridPositionObj(currentNode.node), getCenterFromGridPositionObj(path[path.length - 2]))))
// Replace last waypoint if the current waypoint leads to a valid path
path[path.length - 1] = {x: currentNode.node.x, y: currentNode.node.y};
else
path.push({x: currentNode.node.x, y: currentNode.node.y});
currentNode = currentNode.previous;
}
return path;
}
export function wipe_cache() {
cached_nodes = undefined;
}
+14 -3
View File
@@ -33,8 +33,16 @@ export class DragRulerRuler extends Ruler {
toJSON() {
const json = super.toJSON();
if (this.draggedEntity)
json["draggedEntity"] = this.draggedEntity.id;
if (this.draggedEntity) {
const isToken = this.draggedEntity instanceof Token;
json.draggedEntityIsToken = isToken;
json.draggedEntity = this.draggedEntity.id;
json.waypoints = json.waypoints.map(old => {
let w = duplicate(old);
w.isPathfinding = undefined;
return w;
});
}
return json;
}
@@ -44,7 +52,10 @@ export class DragRulerRuler extends Ruler {
return;
if (data.draggedEntity) {
this.draggedEntity = canvas.tokens.get(data.draggedEntity);
if (data.draggedEntityIsToken)
this.draggedEntity = canvas.tokens.get(data.draggedEntity);
else
this.draggedEntity = canvas.templates.get(data.draggedEntity);
}
super.update(data);
}
+9
View File
@@ -47,6 +47,15 @@ export function registerSettings() {
default: true,
});
game.settings.register(settingsKey, "autoPathfinding", {
name: "drag-ruler.settings.autoPathfinding.name",
hint: "drag-ruler.settings.autoPathfinding.hint",
scpoe: "client",
config: true,
type: Boolean,
defualt: true,
});
game.settings.register(settingsKey, "lastTerrainRulerHintTime", {
config: false,
type: Number,
+1 -1
View File
@@ -132,7 +132,7 @@ export class GenericSpeedProvider extends SpeedProvider {
const speedAttribute = this.getSetting("speedAttribute")
if (!speedAttribute)
return []
const tokenSpeed = parseInt(getProperty(token, speedAttribute));
const tokenSpeed = parseFloat(getProperty(token, speedAttribute));
if (tokenSpeed === undefined) {
console.warn(`Drag Ruler (Generic Speed Provider) | The configured token speed attribute "${speedAttribute}" didn't return a speed value. To use colors based on drag distance set the setting to the correct value (or clear the box to disable this feature).`)
return []
+8 -2
View File
@@ -1,6 +1,8 @@
export function getDefaultSpeedAttribute() {
switch (game.system.id) {
case "CoC7":
return "actor.data.data.attribs.mov.value";
case "dcc":
return "actor.data.data.attributes.speed.value";
case "dnd5e":
@@ -8,13 +10,14 @@ export function getDefaultSpeedAttribute() {
case "lancer":
return "actor.data.data.mech.speed"
case "pf1":
return "actor.data.data.attributes.speed.land.total"
case "D35E":
return "actor.data.data.attributes.speed.land.total"
case "sfrpg":
return "actor.data.data.attributes.speed.value";
case "shadowrun5e":
return "actor.data.data.movement.walk.value";
case "swade":
return "actor.data.data.stats.speed.value"
return "actor.data.data.stats.speed.adjusted";
}
return ""
}
@@ -27,9 +30,12 @@ export function getDefaultDashMultiplier() {
case "dnd5e":
case "lancer":
case "pf1":
case "D35E":
case "sfrpg":
case "shadowrun5e":
return 2
case "CoC7":
return 5;
}
return 0
}