export class TileHandler{ static isTileVisible(tile){ const currentToken = CONFIG.Levels.currentToken; CONFIG.Levels.FoWHandler.lazyCreateTileFogMask(tile); if(!currentToken) return true; const tokenElevation = currentToken.document.elevation; const tokenLOS = currentToken.losHeight; const bgElevation = canvas?.scene?.flags?.levels?.backgroundElevation ?? 0; //Handle background tiles if(!tile.document.overhead){ return tokenLOS >= bgElevation } if(!tile.document.flags.levels) return true; const {rangeTop, rangeBottom, showIfAbove, showAboveRange, isBasement, noFogHide} = getFlags(tile.document) //Not a levels tile, hide if token is under background if(rangeTop === Infinity && rangeBottom === -Infinity || !tile.document.overhead) return tokenLOS >= bgElevation; const inRange = tokenLOS < rangeTop && tokenLOS >= rangeBottom; //If tile is basement and token is out of it's range, it's not visible if(!inRange && isBasement) return false; //Non roof tiles under the token that don't have the show if above will be hidden if( tokenLOS < rangeBottom && !showIfAbove && rangeTop !== Infinity) return false; //Tiles set as show above will be hidden if the token exceeds the range if( tokenLOS < rangeBottom && showIfAbove && Math.abs(tokenElevation - rangeBottom) > showAboveRange) return false; //If it's a roof or show if above is enabled and the bottom of the tile is higher than the bg, and the token is under the bg, hide the tile if((showIfAbove || rangeTop === Infinity) && rangeBottom > bgElevation && tokenLOS < bgElevation) return false; return true; } static _identifyOccludedTiles(tokens) { const occluded = new Set(); const controlled = tokens.filter(t => t.controlled); for ( const token of (controlled.length ? controlled : tokens) ) { const tiles = canvas.tiles.quadtree.getObjects(token.bounds); for ( const tile of tiles ) { if ( occluded.has(tile) ) continue; // Don't bother re-testing a tile if ( tile.testOcclusion(token, {corners: tile.isRoof}) ) occluded.add(tile); } } return occluded; } } function getFlags(document){ const flags = {} for( const [k,v] of Object.entries(document.flags.levels)){ flags[k] = v ?? defaultValues[k]; } return flags; } const defaultValues = { rangeTop: Infinity, rangeBottom: -Infinity, showIfAbove: false, showAboveRange: Infinity, isBasement: false, noFogHide: false, excludeFromChecker: false }