All user data for FoundryVTT. Includes worlds, systems, modules, and any asset in the "foundryuserdata" directory. Does NOT include the FoundryVTT installation itself.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

277 lines
9.8 KiB

export function registerWrappers() {
const LevelsConfig = CONFIG.Levels
const computeUI = LevelsConfig.handlers.UIHandler.UIVisible
Hooks.on("refreshTile", (placeable) => {
const visible = LevelsConfig.handlers.TileHandler.isTileVisible(placeable);
if (CONFIG.Levels.currentToken || canvas.tokens.controlled.length) {
if ((CONFIG.Levels.currentToken ?? canvas.tokens.controlled[0]).losHeight < placeable.document.elevation) {
if (!visible) {
if (placeable.mesh) {
placeable.mesh.occluded = true;
placeable.mesh.shader.enabled = false;
placeable.mesh.alpha = 0;
}
placeable.visible = placeable.visible && visible;
}
} else {
placeable.visible = placeable.visible && visible;
}
} else {
placeable.visible = placeable.visible && visible;
}
computeUI(placeable);
})
Hooks.on("refreshDrawing", (placeable) => {
const visible = LevelsConfig.handlers.DrawingHandler.isDrawingVisible(placeable);
placeable.visible = placeable.visible && visible;
computeUI(placeable);
})
Hooks.on("refreshToken", (placeable, renderFlags) => {
LevelsConfig.handlers.TokenHandler.refreshTooltip(placeable);
CONFIG.Levels.FoWHandler.lazyCreateBubble(placeable);
LevelsConfig.handlers.TokenHandler.setScale(placeable, renderFlags);
computeUI(placeable);
})
Hooks.on("updateToken", (token, updates) => {
if ("elevation" in updates && CONFIG.Levels.settings.get("tokenElevScale")) {
LevelsConfig.handlers.RefreshHandler.refresh(canvas.tokens)
}
})
Hooks.on("controlToken", (token, control) => {
CONFIG.Levels.settings.get("tokenElevScale") && LevelsConfig.handlers.RefreshHandler.refresh(canvas.tokens)
})
Hooks.on("refreshAmbientLight", (placeable) => {
computeUI(placeable);
})
Hooks.on("refreshNote", (placeable) => {
computeUI(placeable);
})
Hooks.on("refreshWall", (placeable) => {
computeUI(placeable);
})
Hooks.on("refreshAmbientSound", (placeable) => {
computeUI(placeable);
})
Hooks.on("activateTilesLayer ", () => {
if(CONFIG.Levels.UI?.rangeEnabled){
ui.controls.control.foreground = true;
canvas.tiles._activateSubLayer(true);
}
})
libWrapper.register(
LevelsConfig.MODULE_ID,
"TokenLayer.prototype._getOccludableTokens",
function (wrapped, ...args) {
if (game.user.isGM) return wrapped(...args);
else {
return CONFIG.Levels.currentToken ? [CONFIG.Levels.currentToken] : wrapped(...args);
}
},
"MIXED",
);
libWrapper.register(
LevelsConfig.MODULE_ID,
"CONFIG.Tile.objectClass.prototype.isRoof", function isRoof(wrapped, ...args){
if(this.document.flags?.levels?.noCollision || this.document.flags["tile-scroll"]?.enableRotate || this.document.flags["tile-scroll"]?.enableScroll) return wrapped(...args);
return wrapped(...args) || (this.document.overhead && Number.isFinite(this.document.flags?.levels?.rangeBottom));
},
"WRAPPER",
{ perf_mode: "FAST" }
);
libWrapper.register(
LevelsConfig.MODULE_ID,
"CONFIG.Wall.objectClass.prototype.identifyInteriorState", function disableInteriorState(wrapped,...args){
this.roof = null;
for (const tile of canvas.tiles.roofs) {
const allWallBlockSight = tile.document?.flags?.levels?.allWallBlockSight ?? true;
if (tile.document.hidden || !allWallBlockSight) continue;
const isBottomFinite = Number.isFinite(tile.document.flags?.levels?.rangeBottom);
if (isBottomFinite && Number.isFinite(tile.document?.flags?.levels?.rangeTop)) continue;
if(isBottomFinite){
const bottom = tile.document.flags?.levels?.rangeBottom;
const wallBottom = this.document.flags["wall-height"]?.bottom ?? -Infinity;
if(wallBottom >= bottom) continue;
}
const [x1, y1, x2, y2] = this.document.c;
const isInterior = tile.mesh?.containsPixel(x1, y1) && tile.mesh?.containsPixel(x2, y2);
if (isInterior) {
this.roof = tile;
break;
}
}
},
"OVERRIDE",
{ perf_mode: "FAST" }
);
libWrapper.register(
LevelsConfig.MODULE_ID,
"TilesLayer.prototype.displayRoofs", function displayRoofs(wrapped, ...args){
const res = wrapped(...args);
return res || (CONFIG.Levels.UI?.rangeEnabled && !canvas.tokens.controlled.length);
},
"WRAPPER"
);
const visibilityTestObjectStack = [];
libWrapper.register(
LevelsConfig.MODULE_ID,
"CanvasVisibility.prototype.testVisibility",
function visibilityWrapper(wrapped, ...args) {
const options = args[1] ??= {};
if (options.object instanceof Token) options.tolerance = 0;
visibilityTestObjectStack.push(LevelsConfig.visibilityTestObject);
LevelsConfig.visibilityTestObject = args[1].object;
const res = wrapped(...args);
LevelsConfig.visibilityTestObject = visibilityTestObjectStack.pop();
return !!res;
},
"WRAPPER"
);
function elevatePoints(config, visionSource) {
const object = config.object;
const unitsToPixel = canvas.dimensions.size / canvas.dimensions.distance;
if (object instanceof Token) {
if (config.tests._levels !== object) {
config.tests.length = 0;
for (const p of LevelsConfig.handlers.SightHandler.getTestPoints(object)) {
config.tests.push({ point: { x: p.x, y: p.y, z: p.z * unitsToPixel }, los: new Map() });
}
config.tests._levels = object;
}
} else {
let z;
if (object instanceof PlaceableObject) {
z = object.document.elevation ?? object.document.flags.levels?.rangeBottom;
} else if (object instanceof DoorControl) {
z = visionSource?.elevation;
}
z ??= canvas.primary.background.elevation;
z *= unitsToPixel;
for (const test of config.tests) {
test.point.z = z;
}
}
return config;
}
libWrapper.register(
LevelsConfig.MODULE_ID,
"DetectionMode.prototype.testVisibility",
function (wrapped, visionSource, mode, config) {
return wrapped(visionSource, mode, elevatePoints(config, visionSource));
},
"WRAPPER",
{ perf_mode: "FAST" }
);
libWrapper.register(
LevelsConfig.MODULE_ID,
"LightSource.prototype.testVisibility",
function (wrapped, config) {
return wrapped(elevatePoints(config, CONFIG.Levels.currentToken?.vision));
},
"WRAPPER",
{ perf_mode: "FAST" }
);
libWrapper.register(
LevelsConfig.MODULE_ID,
"DetectionMode.prototype._testRange",
LevelsConfig.handlers.SightHandler._testRange,
"OVERRIDE",
{ perf_mode: "FAST" }
);
libWrapper.register(
LevelsConfig.MODULE_ID,
"ClockwiseSweepPolygon.prototype.contains",
LevelsConfig.handlers.SightHandler.containsWrapper,
"MIXED"
);
libWrapper.register(
LevelsConfig.MODULE_ID,
"ClockwiseSweepPolygon.prototype._testCollision",
LevelsConfig.handlers.SightHandler._testCollision,
"MIXED"
);
libWrapper.register(
LevelsConfig.MODULE_ID,
"CONFIG.AmbientLight.objectClass.prototype.emitsLight",
LevelsConfig.handlers.LightHandler.isLightVisibleWrapper,
"WRAPPER"
);
libWrapper.register(
LevelsConfig.MODULE_ID,
"CONFIG.Token.objectClass.prototype.emitsLight",
LevelsConfig.handlers.LightHandler.isLightVisibleWrapper,
"WRAPPER"
);
libWrapper.register(
LevelsConfig.MODULE_ID,
"CONFIG.AmbientSound.objectClass.prototype.isAudible",
LevelsConfig.handlers.SoundHandler.isAudible,
"WRAPPER"
);
libWrapper.register(
LevelsConfig.MODULE_ID,
"CONFIG.Note.objectClass.prototype.isVisible",
LevelsConfig.handlers.NoteHandler.isVisible,
"WRAPPER"
);
libWrapper.register(
LevelsConfig.MODULE_ID,
"CONFIG.MeasuredTemplate.objectClass.prototype.draw",
LevelsConfig.handlers.TemplateHandler.drawTooltip,
"WRAPPER"
);
libWrapper.register(
LevelsConfig.MODULE_ID,
"CONFIG.MeasuredTemplate.objectClass.prototype._refreshRulerText",
LevelsConfig.handlers.TemplateHandler._refreshRulerText,
"OVERRIDE"
);
libWrapper.register(
LevelsConfig.MODULE_ID,
"CONFIG.MeasuredTemplate.objectClass.prototype.isVisible",
LevelsConfig.handlers.TemplateHandler.isVisible,
"WRAPPER"
);
libWrapper.register(
LevelsConfig.MODULE_ID,
"CanvasOcclusionMask.prototype._identifyOccludedTiles",
LevelsConfig.handlers.TileHandler._identifyOccludedTiles,
"OVERRIDE"
);
libWrapper.register(LevelsConfig.MODULE_ID, "CONFIG.Token.objectClass.prototype.isVisible", LevelsConfig.handlers.UIHandler.tokenUIWrapperIsVisible, "WRAPPER");
}