/* theripper93 * Copyright (C) 2021 dnd-randomizer * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * Original License: * https://github.com/theripper93/dnd-randomizer/blob/master/LICENSE */ /* WARPGATE CHANGES * exporting propagator class * removed test function from original code */ export class Propagator{ // Find a non-occupied cell in the grid that matches the size of the token given an origin static getFreePosition(tokenData,origin, collision = true){ const center = canvas.grid.getCenter(origin.x,origin.y) origin = {x:center[0],y:center[1]}; const positions = Propagator.generatePositions(origin); for(let position of positions){ if(Propagator.canFit(tokenData, position, positions[0], collision)){ return position; } } } //generate positions radiantially from the origin static generatePositions(origin){ let positions = [canvas.grid.getSnappedPosition(origin.x-1,origin.y-1)]; for(let r = canvas.scene.dimensions.size; r < canvas.scene.dimensions.size*10; r+=canvas.scene.dimensions.size){ for(let theta = 0; theta < 2*Math.PI; theta+=Math.PI/(4*r/canvas.scene.dimensions.size)){ const newPos = canvas.grid.getTopLeft(origin.x + r*Math.cos(theta),origin.y + r*Math.sin(theta)) positions.push({x:newPos[0],y:newPos[1]}); } } return positions; } //check if a position is free static isFree(position){ for(let token of canvas.tokens.placeables){ const hitBox = new PIXI.Rectangle(token.x,token.y,token.w,token.h); if(hitBox.contains(position.x,position.y)){ return false; } } return true; } //check if a token can fit in a position static canFit(tokenData, position, origin, collision){ for(let i = 0; i < tokenData.width; i++){ for(let j = 0; j < tokenData.height; j++){ const x = position.x + j*canvas.scene.dimensions.size; const y = position.y + i*canvas.scene.dimensions.size; if(!Propagator.isFree({x,y})){ return false; } } } const wallCollisions = canvas.walls.checkCollision( new Ray(origin, { x:position.x+tokenData.width*canvas.scene.dimensions.size/2, y:position.y+tokenData.height*canvas.scene.dimensions.size/2 }),{ type: "move" } )?.length ?? 0; return !collision || !wallCollisions } }