Files
foundryvtt-drag-ruler/src/foundry_imports.js
T
Manuel Vögele 633563b672 Add custom implementation of Ruler.moveToken
This allows us to move multiple tokens at a time
and allows the gm to move tokens through walls again
2021-02-02 10:52:15 +01:00

70 lines
2.7 KiB
JavaScript

// This is a modified version of Ruler.moveToken from foundry 0.7.9
export async function moveTokens(selectedTokens) {
let wasPaused = game.paused;
if (wasPaused && !game.user.isGM) {
ui.notifications.warn(game.i18n.localize("GAME.PausedWarning"));
return false;
}
if (!this.visible || !this.destination) return false;
const draggedToken = this._getMovementToken();
if (!draggedToken) return;
// Get the movement rays and check collision along each Ray
// These rays are center-to-center for the purposes of collision checking
const rays = this._getRaysFromWaypoints(this.waypoints, this.destination);
if (!game.user.isGM) {
const hasCollision = selectedTokens.some(token => {
const offset = calculateTokenOffset(token, draggedToken)
const offsetRays = rays.map(ray => applyOffsetToRay(ray, offset))
return offsetRays.some(r => canvas.walls.checkCollision(r));
})
if (hasCollision) {
ui.notifications.error(game.i18n.localize("ERROR.TokenCollide"));
this._endMeasurement();
return true;
}
}
// 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)
}))
// Once all animations are complete we can clear the ruler
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.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 origin = canvas.grid.getTopLeft(this.waypoints[0].x + tokenOffset.x, this.waypoints[0].y + tokenOffset.y);
const s2 = canvas.dimensions.size / 2;
const dx = Math.round((token.data.x - origin[0]) / s2) * s2;
const dy = Math.round((token.data.y - origin[1]) / s2) * s2;
token._noAnimate = true;
for (let r of offsetRays) {
if (!wasPaused && game.paused) break;
const dest = canvas.grid.getTopLeft(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);
}
token._noAnimate = false;
}
function calculateTokenOffset(tokenA, tokenB) {
return {x: tokenA.data.x - tokenB.data.x, y: tokenA.data.y - tokenB.data.y}
}
function applyOffsetToRay(ray, offset) {
return new Ray({x: ray.A.x + offset.x, y: ray.A.y + offset.y}, {x: ray.B.x + offset.x, y: ray.B.y + offset.y})
}