Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d1367aa82e | |||
| 9f70e5bc27 | |||
| 334ccbc0f1 | |||
| 1242035744 | |||
| 49542a68e5 | |||
| 27a6235cc1 | |||
| c26b39c984 | |||
| e8ab77a62e | |||
| 7bed5abd0a | |||
| 4a96348659 | |||
| bed16de575 | |||
| 891bb1b4d8 | |||
| 43f26088b5 | |||
| 39a0787c79 | |||
| 3be898e49c | |||
| 817662bf30 | |||
| 56527ccf75 | |||
| 6bf8083f7a | |||
| b5ea1f2284 | |||
| 6d9870bedb | |||
| afbe5f9473 | |||
| bae0e43b7b | |||
| 1acc012d65 | |||
| 4671e6de51 | |||
| f0ef109658 | |||
| f0d1ef9d48 | |||
| d04ea9b0b7 | |||
| ba8ab9d473 | |||
| 2691720090 | |||
| 70b166d844 | |||
| 908600bfa3 | |||
| 6472c1d5bd | |||
| 9151b45874 | |||
| d732f7ca17 | |||
| 4be6730fd5 | |||
| 1faeda6f47 | |||
| 667259d5d6 |
@@ -1,3 +1,62 @@
|
||||
## 1.6.5
|
||||
### Bugfixes
|
||||
- Drag Ruler no longer get's stuck if the user presses ESC during drag ([#70](https://github.com/manuelVo/foundryvtt-drag-ruler/issues/70))
|
||||
|
||||
|
||||
## 1.6.4
|
||||
### Bugfixes
|
||||
- Fixed a bug where a bug in a Speed Provider could lead to the ruler getting stuck, leaving the token immovable
|
||||
|
||||
|
||||
## 1.6.3
|
||||
### Bugfixes
|
||||
- If the movement history for a token is being updated (for example by a history reset by the gm) while a player is currently measuring a distance for that token the history change is now being reflected in the active measurement.
|
||||
|
||||
### Compatibility
|
||||
- Drag Ruler's Generic SpeedProvider is now aware of good default values for the Savage Worlds Adventure Edition game system
|
||||
|
||||
|
||||
## 1.6.2
|
||||
### Bugfixes
|
||||
- The reset movement history button now resets the movement history for all players, not just for the GM
|
||||
|
||||
|
||||
## 1.6.1
|
||||
### API
|
||||
- Added `onMovementHistoryUpdate` callback to Speed Providers, that allows them to perform game systems specific improvements to the movement history
|
||||
- Added `dragRuler.resetMovementHistory` that clears the stored movement history for a token.
|
||||
|
||||
|
||||
## 1.6.0
|
||||
### Performance
|
||||
- Greatly increased the performance when playing on huge maps and when moving many tokens at once.
|
||||
- Huge performance improvements for speed providers. (Technical details: `getRanges` is now being called way less frequently)
|
||||
|
||||
### New features
|
||||
- GMs now have an option to reset the movement history for individual tokens in the right click menu of the combat tracker
|
||||
- When releasing a dragged token while pressing Alt the token will be moved to the target location without an animation ([#3](https://github.com/manuelVo/foundryvtt-drag-ruler/issues/3))
|
||||
|
||||
### Bugfixes
|
||||
- When starting to drag a new token while the previous one is still moving the ruler won't dissappear anymore when the previous token arrives at it's destination.
|
||||
|
||||
|
||||
## 1.5.4
|
||||
### Bugfixes
|
||||
- Fixed a bug that prevented tokens from being moved when their movement history collides with a wall. ([#61](https://github.com/manuelVo/foundryvtt-drag-ruler/issues/61))
|
||||
|
||||
|
||||
## 1.5.3
|
||||
### Compatiblilty
|
||||
- Drag Ruler's Generic Speed Provider is now able to work with game systems that put non-number characters behind the tokens movement speed (like `30ft.`). One example for such a game system is Dungeon Crawl Classics. ([#60](https://github.com/manuelVo/foundryvtt-drag-ruler/issues/60))
|
||||
- The Generic Speed Provider now has good default settings for the Dungeon Crawl Classics (dcc) game system.
|
||||
|
||||
|
||||
## 1.5.2
|
||||
### Bugfixes
|
||||
- Drag Ruler no longer prevents tokens that don't have an actor from being moved. ([#58](https://github.com/manuelVo/foundryvtt-drag-ruler/issues/58))
|
||||
- Grid highlighting now also works for tokens that don't have an actor.
|
||||
|
||||
|
||||
## 1.5.1
|
||||
### Bugfixes
|
||||
- The hint that tells users how to enable difficult terrain measurement in Drag Ruler is no longer shown if no terrain layer module is installed.
|
||||
|
||||
@@ -36,7 +36,10 @@ The game systems that offer Drag Ruler integration are:
|
||||
- Cypher System (starting with version 1.13.0)
|
||||
- Pathfinder 1 (starting with version 0.77.3)
|
||||
- Pathfinder 2e (via the module [PF2E Drag Ruler Integration](https://foundryvtt.com/packages/pf2e-dragruler/))
|
||||
- Tagmar RPG (starting with version 1.1.4)
|
||||
- Tormenta20 (starting with version 1.1.37)
|
||||
- Shadow of the Demon Lord (starting with version 1.7.15)
|
||||
- WWII:OWB (starting with version 1.0.4)
|
||||
|
||||
|
||||
## Translations
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"text": "Drag Ruler benötigt das socketlib-Modul, um korrekt zu funktionieren. Bitte aktiviere das socketlib-Modul in dieser Welt."
|
||||
}
|
||||
},
|
||||
"resetMovementHistory": "Bewegungsverlauf zurücksetzen",
|
||||
"genericSpeedProvider": {
|
||||
"settings": {
|
||||
"dashMultiplier": {
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"text": "Drag Ruler requires the socketlib module to work properly. Please activate the socketlib module in this world."
|
||||
}
|
||||
},
|
||||
"resetMovementHistory": "Reset Movement History",
|
||||
"genericSpeedProvider": {
|
||||
"settings": {
|
||||
"dashMultiplier": {
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@
|
||||
"name": "drag-ruler",
|
||||
"title": "Drag Ruler",
|
||||
"description": "When dragging a token displays a ruler showing how far you've moved that token.",
|
||||
"version": "1.5.1",
|
||||
"version": "1.6.5",
|
||||
"minimumCoreVersion" : "0.7.9",
|
||||
"compatibleCoreVersion" : "0.7.9",
|
||||
"authors": [
|
||||
@@ -49,7 +49,7 @@
|
||||
],
|
||||
"socket": true,
|
||||
"url": "https://github.com/manuelVo/foundryvtt-drag-ruler",
|
||||
"download": "https://github.com/manuelVo/foundryvtt-drag-ruler/archive/v1.5.1.zip",
|
||||
"download": "https://github.com/manuelVo/foundryvtt-drag-ruler/archive/v1.6.5.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",
|
||||
|
||||
@@ -101,11 +101,17 @@ export function getUnreachableColorFromSpeedProvider() {
|
||||
}
|
||||
|
||||
export function getCostFromSpeedProvider(token, area) {
|
||||
try {
|
||||
if (currentSpeedProvider instanceof Function) {
|
||||
return SpeedProvider.prototype.getCostForStep.call(undefined, token, area);
|
||||
}
|
||||
return currentSpeedProvider.getCostForStep(token, area);
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
export function getMovedDistanceFromToken(token) {
|
||||
const history = getMovementHistory(token);
|
||||
|
||||
@@ -2,13 +2,10 @@
|
||||
|
||||
// https://gitlab.com/foundrynet/foundryvtt/-/issues/4705
|
||||
export function getPixelsFromGridPosition(xGrid, yGrid) {
|
||||
if (canvas.grid.isHex) {
|
||||
if (canvas.grid.type !== CONST.GRID_TYPES.GRIDLESS) {
|
||||
return canvas.grid.grid.getPixelsFromGridPosition(yGrid, xGrid)
|
||||
}
|
||||
const [x, y] = canvas.grid.grid.getPixelsFromGridPosition(xGrid, yGrid)
|
||||
if (canvas.grid.type === CONST.GRID_TYPES.SQUARE)
|
||||
return [y, x]
|
||||
return [x, y]
|
||||
return canvas.grid.grid.getPixelsFromGridPosition(xGrid, yGrid)
|
||||
}
|
||||
|
||||
// Wrapper to fix a FoundryVTT bug that causes the return values of canvas.grid.grid.getPixelsFromGridPosition to be ordered inconsistently
|
||||
|
||||
+38
-20
@@ -2,6 +2,7 @@ import {highlightMeasurementTerrainRuler, measureDistances} from "./compatibilit
|
||||
import {getGridPositionFromPixels} from "./foundry_fixes.js";
|
||||
import {getColorForDistance} from "./main.js"
|
||||
import {trackRays} from "./movement_tracking.js"
|
||||
import {recalculate} from "./socket.js";
|
||||
import {applyTokenSizeOffset, getSnapPointForToken, getTokenShape, highlightTokenShape, zip} from "./util.js";
|
||||
|
||||
// This is a modified version of Ruler.moveToken from foundry 0.7.9
|
||||
@@ -20,7 +21,7 @@ export async function moveTokens(draggedToken, selectedTokens) {
|
||||
if (!game.user.isGM) {
|
||||
const hasCollision = selectedTokens.some(token => {
|
||||
const offset = calculateTokenOffset(token, draggedToken)
|
||||
const offsetRays = rays.map(ray => applyOffsetToRay(ray, offset))
|
||||
const offsetRays = rays.filter(ray => !ray.isPrevious).map(ray => applyOffsetToRay(ray, offset))
|
||||
return offsetRays.some(r => canvas.walls.checkCollision(r));
|
||||
})
|
||||
if (hasCollision) {
|
||||
@@ -33,45 +34,62 @@ export async function moveTokens(draggedToken, selectedTokens) {
|
||||
// Execute the movement path.
|
||||
// Transform each center-to-center ray into a top-left to top-left ray using the prior token offsets.
|
||||
this._state = Ruler.STATES.MOVING;
|
||||
await Promise.all(selectedTokens.map(token => {
|
||||
// Return the promise so we can wait for it outside the loop
|
||||
const offset = calculateTokenOffset(token, draggedToken)
|
||||
return animateToken.call(this, token, rays, offset, wasPaused)
|
||||
}))
|
||||
await animateTokens.call(this, selectedTokens, draggedToken, rays, wasPaused);
|
||||
|
||||
// Once all animations are complete we can clear the ruler
|
||||
if (this.draggedToken?.id === draggedToken.id)
|
||||
this._endMeasurement();
|
||||
}
|
||||
|
||||
// This is a modified version code extracted from Ruler.moveToken from foundry 0.7.9
|
||||
async function animateToken(token, rays, tokenOffset, wasPaused) {
|
||||
const offsetRays = rays.filter(r => !r.isPrevious).map(ray => applyOffsetToRay(ray, tokenOffset));
|
||||
trackRays(token, offsetRays);
|
||||
async function animateTokens(tokens, draggedToken, draggedRays, wasPaused) {
|
||||
const newRays = draggedRays.filter(r => !r.isPrevious);
|
||||
const tokenAnimationData = tokens.map(token => {
|
||||
const tokenOffset = calculateTokenOffset(token, draggedToken);
|
||||
const offsetRays = newRays.map(ray => applyOffsetToRay(ray, tokenOffset));
|
||||
|
||||
// Determine offset relative to the Token top-left.
|
||||
// This is important so we can position the token relative to the ruler origin for non-1x1 tokens.
|
||||
const firstWaypoint = this.waypoints.find(w => !w.isPrevious);
|
||||
const origin = [firstWaypoint.x + tokenOffset.x, firstWaypoint.y + tokenOffset.y];
|
||||
let dx, dy
|
||||
let dx, dy;
|
||||
if (canvas.grid.type === CONST.GRID_TYPES.GRIDLESS) {
|
||||
dx = token.data.x - origin[0]
|
||||
dy = token.data.y - origin[1]
|
||||
dx = token.data.x - origin[0];
|
||||
dy = token.data.y - origin[1];
|
||||
}
|
||||
else {
|
||||
dx = token.data.x - origin[0]
|
||||
dy = token.data.y - origin[1]
|
||||
dx = token.data.x - origin[0];
|
||||
dy = token.data.y - origin[1];
|
||||
}
|
||||
|
||||
return {token, rays: offsetRays, dx, dy};
|
||||
});
|
||||
|
||||
for (const {token, rays} of tokenAnimationData) {
|
||||
token._noAnimate = true;
|
||||
for (let r of offsetRays) {
|
||||
if (!wasPaused && game.paused) break;
|
||||
const dest = [r.B.x, r.B.y];
|
||||
const path = new Ray({ x: token.x, y: token.y }, { x: dest[0] + dx, y: dest[1] + dy });
|
||||
await token.update(path.B);
|
||||
await token.animateMovement(path);
|
||||
}
|
||||
const animate = !game.keyboard.isDown("Alt");
|
||||
const startWaypoint = animate ? 0 : tokenAnimationData[0].rays.length - 1;
|
||||
for (let i = startWaypoint;i < tokenAnimationData[0].rays.length; i++) {
|
||||
if (!wasPaused && game.paused) break;
|
||||
const tokenPaths = tokenAnimationData.map(({token, rays, dx, dy}) => {
|
||||
const ray = rays[i];
|
||||
const dest = [ray.B.x, ray.B.y];
|
||||
const path = new Ray({x: token.x, y: token.y}, {x: dest[0] + dx, y: dest[1] + dy});
|
||||
return {token, path};
|
||||
});
|
||||
const updates = tokenPaths.map(({token, path}) => {
|
||||
return {x: path.B.x, y: path.B.y, _id: token.id};
|
||||
});
|
||||
await draggedToken.scene.updateEmbeddedEntity(draggedToken.constructor.embeddedName, updates, {animate});
|
||||
if (animate)
|
||||
await Promise.all(tokenPaths.map(({token, path}) => token.animateMovement(path)));
|
||||
}
|
||||
for (const {token} of tokenAnimationData) {
|
||||
token._noAnimate = false;
|
||||
}
|
||||
trackRays(tokens, tokenAnimationData.map(({rays}) => rays)).then(() => recalculate(tokens));
|
||||
}
|
||||
|
||||
function calculateTokenOffset(tokenA, tokenB) {
|
||||
return {x: tokenA.data.x - tokenB.data.x, y: tokenA.data.y - tokenB.data.y}
|
||||
|
||||
+22
-2
@@ -5,8 +5,9 @@ import {checkDependencies, getHexSizeSupportTokenGridCenter} from "./compatibili
|
||||
import {moveTokens, onMouseMove} from "./foundry_imports.js"
|
||||
import {performMigrations} from "./migration.js"
|
||||
import {DragRulerRuler} from "./ruler.js";
|
||||
import {getMovementHistory} from "./movement_tracking.js";
|
||||
import {getMovementHistory, resetMovementHistory} from "./movement_tracking.js";
|
||||
import {registerSettings, settingsKey} from "./settings.js"
|
||||
import {recalculate} from "./socket.js";
|
||||
import {SpeedProvider} from "./speed_provider.js"
|
||||
|
||||
Hooks.once("init", () => {
|
||||
@@ -22,6 +23,8 @@ Hooks.once("init", () => {
|
||||
getMovedDistanceFromToken,
|
||||
registerModule,
|
||||
registerSystem,
|
||||
recalculate,
|
||||
resetMovementHistory,
|
||||
}
|
||||
})
|
||||
|
||||
@@ -42,6 +45,15 @@ Hooks.on("canvasReady", () => {
|
||||
})
|
||||
})
|
||||
|
||||
Hooks.on("getCombatTrackerEntryContext", function (html, menu) {
|
||||
const entry = {
|
||||
name: "drag-ruler.resetMovementHistory",
|
||||
icon: '<i class="fas fa-undo-alt"></i>',
|
||||
callback: li => resetMovementHistory(ui.combat.combat, li.data('combatant-id')),
|
||||
};
|
||||
menu.splice(1, 0, entry);
|
||||
});
|
||||
|
||||
function hookTokenDragHandlers() {
|
||||
const originalDragLeftStartHandler = Token.prototype._onDragLeftStart
|
||||
Token.prototype._onDragLeftStart = function(event) {
|
||||
@@ -140,6 +152,9 @@ function onTokenDragLeftDrop(event) {
|
||||
return false
|
||||
onMouseMove.call(ruler, event);
|
||||
const selectedTokens = canvas.tokens.controlled
|
||||
// This can happen if the user presses ESC during drag (maybe there are other ways too)
|
||||
if (selectedTokens.length === 0)
|
||||
selectedTokens.push(ruler.draggedToken);
|
||||
ruler._state = Ruler.STATES.MOVING
|
||||
moveTokens.call(ruler, ruler.draggedToken, selectedTokens)
|
||||
return true
|
||||
@@ -166,6 +181,9 @@ function onTokenDragLeftCancel(event) {
|
||||
export function getColorForDistance(startDistance, subDistance=0) {
|
||||
if (!this.isDragRuler)
|
||||
return this.color
|
||||
if (!this.draggedToken.actor) {
|
||||
return this.color;
|
||||
}
|
||||
// Don't apply colors if the current user doesn't have at least observer permissions
|
||||
if (this.draggedToken.actor.permission < 2) {
|
||||
// If this is a pc and alwaysShowSpeedForPCs is enabled we show the color anyway
|
||||
@@ -173,7 +191,9 @@ export function getColorForDistance(startDistance, subDistance=0) {
|
||||
return this.color
|
||||
}
|
||||
const distance = startDistance + subDistance
|
||||
const ranges = getRangesFromSpeedProvider(this.draggedToken)
|
||||
if (!this.dragRulerRanges)
|
||||
this.dragRulerRanges = getRangesFromSpeedProvider(this.draggedToken)
|
||||
const ranges = this.dragRulerRanges;
|
||||
if (ranges.length === 0)
|
||||
return this.color
|
||||
const currentRange = ranges.reduce((minRange, currentRange) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {measureDistances} from "./compatibility.js";
|
||||
import {updateCombatantDragRulerFlags} from "./socket.js";
|
||||
import {getTokenShape} from "./util.js";
|
||||
import {recalculate, updateCombatantDragRulerFlags} from "./socket.js";
|
||||
import {getTokenShape, zip} from "./util.js";
|
||||
|
||||
function initTrackingFlag(combatant) {
|
||||
const initialFlag = {passedWaypoints: [], trackedRound: 0};
|
||||
@@ -23,13 +23,21 @@ function getInitializedCombatant(token, combat) {
|
||||
return combatant;
|
||||
}
|
||||
|
||||
export async function trackRays(token, rays) {
|
||||
// Only track movement if the current token is participating in the active combat
|
||||
export async function trackRays(tokens, tokenRays) {
|
||||
const combat = game.combat;
|
||||
if (!combat)
|
||||
return;
|
||||
if (!combat.started)
|
||||
return;
|
||||
if (!(tokens instanceof Array)) {
|
||||
tokens = [tokens];
|
||||
tokenRays = [tokenRays];
|
||||
}
|
||||
const updates = Array.from(zip(tokens, tokenRays)).map(([token, rays]) => calculateUpdate(combat, token, rays)).filter(Boolean);
|
||||
await updateCombatantDragRulerFlags(combat, updates);
|
||||
}
|
||||
|
||||
function calculateUpdate(combat, token, rays) {
|
||||
const combatant = getInitializedCombatant(token, combat);
|
||||
if (!combatant)
|
||||
return;
|
||||
@@ -55,7 +63,7 @@ export async function trackRays(token, rays) {
|
||||
waypoints.push(ray.A);
|
||||
}
|
||||
}
|
||||
await updateCombatantDragRulerFlags(combat, combatant, dragRulerFlags);
|
||||
return {_id: combatant._id, dragRulerFlags};
|
||||
}
|
||||
|
||||
export function getMovementHistory(token) {
|
||||
@@ -72,3 +80,15 @@ export function getMovementHistory(token) {
|
||||
return [];
|
||||
return dragRulerFlags.passedWaypoints ?? [];
|
||||
}
|
||||
|
||||
export async function resetMovementHistory(combat, combatantId) {
|
||||
const combatant = combat.getCombatant(combatantId);
|
||||
const dragRulerFlags = combatant.flags.dragRuler;
|
||||
if (!dragRulerFlags)
|
||||
return;
|
||||
dragRulerFlags.passedWaypoints = null;
|
||||
dragRulerFlags.trackedRound = null;
|
||||
dragRulerFlags.rulerState = null;
|
||||
await updateCombatantDragRulerFlags(combat, [{_id: combatantId, dragRulerFlags}]);
|
||||
recalculate();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {measure} from "./foundry_imports.js"
|
||||
import {getMovementHistory} from "./movement_tracking.js";
|
||||
import {settingsKey} from "./settings.js";
|
||||
import {getSnapPointForToken} from "./util.js";
|
||||
|
||||
@@ -14,6 +15,7 @@ export class DragRulerRuler extends Ruler {
|
||||
super.clear();
|
||||
this.previousWaypoints = [];
|
||||
this.previousLabels.removeChildren().forEach(c => c.destroy());
|
||||
this.dragRulerRanges = undefined;
|
||||
}
|
||||
|
||||
async moveToken(event) {
|
||||
@@ -77,6 +79,11 @@ export class DragRulerRuler extends Ruler {
|
||||
}
|
||||
}
|
||||
|
||||
dragRulerClearWaypoints() {
|
||||
this.waypoints = [];
|
||||
this.labels.removeChildren().forEach(c => c.destroy());
|
||||
}
|
||||
|
||||
dragRulerDeleteWaypoint(event={preventDefault: () => {return}}) {
|
||||
if (this.waypoints.filter(w => !w.isPrevious).length > 1) {
|
||||
event.preventDefault();
|
||||
@@ -99,6 +106,22 @@ export class DragRulerRuler extends Ruler {
|
||||
}
|
||||
}
|
||||
|
||||
async dragRulerRecalculate(tokenIds) {
|
||||
if (this._state !== Ruler.STATES.MEASURING)
|
||||
return;
|
||||
if (tokenIds && !tokenIds.includes(this.draggedToken.id))
|
||||
return;
|
||||
const waypoints = this.waypoints.filter(waypoint => !waypoint.isPrevious);
|
||||
this.dragRulerClearWaypoints();
|
||||
if (game.settings.get(settingsKey, "enableMovementHistory"))
|
||||
this.dragRulerAddWaypointHistory(getMovementHistory(this.draggedToken));
|
||||
for (const waypoint of waypoints) {
|
||||
this.dragRulerAddWaypoint(waypoint, false);
|
||||
}
|
||||
this.measure(this.destination);
|
||||
game.user.broadcastActivity({ruler: this});
|
||||
}
|
||||
|
||||
static dragRulerGetRaysFromWaypoints(waypoints, destination) {
|
||||
if ( destination )
|
||||
waypoints = waypoints.concat([destination]);
|
||||
|
||||
+31
-5
@@ -1,17 +1,43 @@
|
||||
import {currentSpeedProvider} from "./api.js";
|
||||
|
||||
let socket;
|
||||
|
||||
Hooks.once("socketlib.ready", () => {
|
||||
socket = socketlib.registerModule("drag-ruler");
|
||||
socket.register("updateCombatantDragRulerFlags", _socketUpdateCombatantDragRulerFlags);
|
||||
socket.register("recalculate", _socketRecalculate);
|
||||
});
|
||||
|
||||
export async function updateCombatantDragRulerFlags(combat, combatant, flags) {
|
||||
export function updateCombatantDragRulerFlags(combat, updates) {
|
||||
const combatId = combat.id;
|
||||
const combatantId = combatant._id;
|
||||
return socket.executeAsGM(_socketUpdateCombatantDragRulerFlags, combatId, combatantId, flags);
|
||||
// TODO Check if canvas.tokens.get is still neccessary in future foundry versions
|
||||
return socket.executeAsGM(_socketUpdateCombatantDragRulerFlags, combatId, updates)
|
||||
.then(() => currentSpeedProvider.onMovementHistoryUpdate(updates.map(update => canvas.tokens.get(combat.getCombatant(update._id).token._id))));
|
||||
}
|
||||
|
||||
async function _socketUpdateCombatantDragRulerFlags(combatId, combatantId, flags) {
|
||||
async function _socketUpdateCombatantDragRulerFlags(combatId, updates) {
|
||||
const user = game.users.get(this.socketdata.userId);
|
||||
const combat = game.combats.get(combatId);
|
||||
await combat.updateEmbeddedEntity("Combatant", {_id: combatantId, flags: {dragRuler: flags}}, {diff: false});
|
||||
const requestedUpdates = updates.length;
|
||||
updates = updates.filter(update => {
|
||||
const actor = combat.getCombatant(update._id).actor;
|
||||
if (!actor)
|
||||
return false;
|
||||
return actor.hasPerm(user, "OWNER");
|
||||
});
|
||||
if (updates.length !== requestedUpdates) {
|
||||
console.warn(`Some of the movement history updates requested by user '${game.users.get(this.socketdata.userId).name}' were not performed because the user lacks owner permissions for those tokens`);
|
||||
}
|
||||
updates = updates.map(update => {
|
||||
return {_id: update._id, flags: {dragRuler: update.dragRulerFlags}};
|
||||
});
|
||||
await combat.updateEmbeddedEntity("Combatant", updates, {diff: false});
|
||||
}
|
||||
|
||||
export function recalculate(tokens) {
|
||||
socket.executeForEveryone(_socketRecalculate, tokens ? tokens.map(token => token.id) : undefined);
|
||||
}
|
||||
|
||||
function _socketRecalculate(tokenIds) {
|
||||
return canvas.controls.ruler.dragRulerRecalculate(tokenIds);
|
||||
}
|
||||
|
||||
@@ -84,6 +84,14 @@ export class SpeedProvider {
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* This hook is being called after Drag Ruler has updated the movement history for one or more tokens.
|
||||
* It'll receive an array of tokens that have been updated.
|
||||
* If your speed provider is storing any additional values that are relevant for the movement history, this function should
|
||||
* await until those updates have completed inside foundry.
|
||||
*/
|
||||
async onMovementHistoryUpdate(tokens) {}
|
||||
|
||||
/**
|
||||
* Returns the value that is currently set for the setting registered with the provided settingId.
|
||||
*
|
||||
@@ -124,7 +132,7 @@ export class GenericSpeedProvider extends SpeedProvider {
|
||||
const speedAttribute = this.getSetting("speedAttribute")
|
||||
if (!speedAttribute)
|
||||
return []
|
||||
const tokenSpeed = getProperty(token, speedAttribute)
|
||||
const tokenSpeed = parseInt(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 []
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
|
||||
export function getDefaultSpeedAttribute() {
|
||||
switch (game.system.id) {
|
||||
case "dcc":
|
||||
return "actor.data.data.attributes.speed.value";
|
||||
case "dnd5e":
|
||||
return "actor.data.data.attributes.movement.walk"
|
||||
case "lancer":
|
||||
return "actor.data.data.mech.speed"
|
||||
case "pf1":
|
||||
return "actor.data.data.attributes.speed.land.total"
|
||||
case "shadowrun5e":
|
||||
return "actor.data.data.movement.walk.value";
|
||||
case "swade":
|
||||
return "actor.data.data.stats.speed.value"
|
||||
}
|
||||
@@ -17,9 +21,11 @@ export function getDefaultDashMultiplier() {
|
||||
switch (game.system.id) {
|
||||
case "swade":
|
||||
return 0
|
||||
case "dcc":
|
||||
case "dnd5e":
|
||||
case "lancer":
|
||||
case "pf1":
|
||||
case "shadowrun5e":
|
||||
return 2
|
||||
}
|
||||
return 0
|
||||
|
||||
Reference in New Issue
Block a user