|
|
- import { registerWrappers } from "./patches.js";
- import { getWallBounds,getSceneSettings,migrateData,getTokenLOSheight } from "./utils.js";
- import { WallHeightToolTip } from './tooltip.js';
- import { MODULE_SCOPE, TOP_KEY, BOTTOM_KEY, ENABLE_ADVANCED_VISION_KEY, ENABLE_ADVANCED_MOVEMENT_KEY } from "./const.js";
-
- const MODULE_ID = 'wall-height';
-
- Object.defineProperty(Token.prototype, "losHeight", {
- get: function myProperty() {
- return getTokenLOSheight(this);
- },
- });
-
- Hooks.once("init",()=>{
- registerWrappers();
- registerSettings();
- if(game.settings.get(MODULE_ID,'enableTooltip')){
- Hooks.on("renderHeadsUpDisplay", (app, html, data) => {
- canvas.hud.wallHeight?.close();
- html.find("#wall-height-tooltip").remove();
- html.append('<template id="wall-height-tooltip"></template>');
- canvas.hud.wallHeight = new WallHeightToolTip();
- });
- }
- WallHeight.cacheSettings();
- });
-
- Hooks.once("ready", ()=>{
- if(!game.user.isGM) return;
- if(game.settings.get(MODULE_ID, 'migrateOnStartup')) WallHeight.migrateAll();
- if(game.settings.get(MODULE_ID, 'migrateTokenHeight')) {
- WallHeight.migrateTokenHeight();
- game.settings.set(MODULE_ID, 'migrateTokenHeight',false)
- }
- })
-
- Hooks.on("hoverWall",(wall, hovered)=>{
- if (!canvas.hud?.wallHeight || canvas.walls._chain) return;
- const {advancedVision} = getSceneSettings(canvas.scene);
- if(advancedVision!=null && !advancedVision)
- return;
- if (hovered) {
- canvas.hud.wallHeight.bind(wall);
- } else {
- canvas.hud.wallHeight.clear();
- }
- });
-
- Hooks.on("renderSceneControls", () => {
- if (canvas.hud?.wallHeight) canvas.hud.wallHeight.clear();
- });
-
- Hooks.on("deleteWall", () => {
- if (canvas.hud?.wallHeight) canvas.hud.wallHeight.clear();
- });
-
- Hooks.on("createWall", () => {
- if (canvas.hud?.wallHeight) canvas.hud.wallHeight.clear();
- });
-
- Hooks.on("updateWall", () => {
- if (canvas.hud?.wallHeight) canvas.hud.wallHeight.clear();
- });
-
- function registerSettings() {
- game.settings.register(MODULE_ID, 'enableTooltip', {
- name: game.i18n.localize(`${MODULE_SCOPE}.settings.enableTooltip.name`),
- hint: game.i18n.localize(`${MODULE_SCOPE}.settings.enableTooltip.hint`),
- scope: 'world',
- config: true,
- type: Boolean,
- default: false
- });
-
- game.settings.register(MODULE_ID, 'enableWallText', {
- name: game.i18n.localize(`${MODULE_SCOPE}.settings.enableWallText.name`),
- hint: game.i18n.localize(`${MODULE_SCOPE}.settings.enableWallText.hint`),
- scope: 'world',
- config: true,
- type: Boolean,
- default: true,
- onChange: () => {
- WallHeight.cacheSettings();
- },
- });
-
- game.settings.register(MODULE_ID, "blockSightMovement", {
- name: game.i18n.localize(`${MODULE_SCOPE}.settings.blockSightMovement.name`),
- hint: game.i18n.localize(`${MODULE_SCOPE}.settings.blockSightMovement.hint`),
- scope: "world",
- config: true,
- type: Boolean,
- default: true,
- onChange: () => {
- WallHeight.cacheSettings();
- },
- });
-
- game.settings.register(MODULE_ID, "autoLOSHeight", {
- name: game.i18n.localize(`${MODULE_SCOPE}.settings.autoLOSHeight.name`),
- hint: game.i18n.localize(`${MODULE_SCOPE}.settings.autoLOSHeight.hint`),
- scope: "world",
- config: true,
- type: Boolean,
- default: true,
- onChange: () => {
- WallHeight.cacheSettings();
- },
- });
-
-
- game.settings.register(MODULE_ID, "defaultLosHeight", {
- name: game.i18n.localize(`${MODULE_SCOPE}.settings.defaultLosHeight.name`),
- hint: game.i18n.localize(`${MODULE_SCOPE}.settings.defaultLosHeight.hint`),
- scope: "world",
- config: true,
- type: Number,
- default: 6,
- onChange: () => {
- WallHeight.cacheSettings();
- },
- });
-
- game.settings.register(MODULE_ID, "losHeightMulti", {
- name: game.i18n.localize(`${MODULE_SCOPE}.settings.losHeightMulti.name`),
- hint: game.i18n.localize(`${MODULE_SCOPE}.settings.losHeightMulti.hint`),
- scope: "world",
- config: true,
- type: Number,
- default: 0.89,
- range: {
- min: 0.1,
- max: 2,
- step: 0.01,
- },
- onChange: () => {
- WallHeight.cacheSettings();
- },
- });
-
- game.settings.register(MODULE_ID, 'globalAdvancedLighting', {
- name: game.i18n.localize(`${MODULE_SCOPE}.settings.globalAdvancedLighting.name`),
- hint: game.i18n.localize(`${MODULE_SCOPE}.settings.globalAdvancedLighting.hint`),
- scope: 'world',
- config: true,
- type: Boolean,
- default: true,
- });
-
- game.settings.register(MODULE_ID, 'migrateOnStartup', {
- name: game.i18n.localize(`${MODULE_SCOPE}.settings.migrateOnStartup.name`),
- hint: game.i18n.localize(`${MODULE_SCOPE}.settings.migrateOnStartup.hint`),
- scope: 'world',
- config: true,
- type: Boolean,
- default: false
- });
-
- game.settings.register(MODULE_ID, 'migrateTokenHeight', {
- scope: 'world',
- config: false,
- type: Boolean,
- default: false
- });
- }
-
- Hooks.on("renderWallConfig", (app, html, data) => {
- const {advancedVision} = getSceneSettings(canvas.scene);
- if(!advancedVision) return;
- let { top, bottom } = getWallBounds(app.object);
- top = parseFloat(top);
- bottom = parseFloat(bottom);
- const topLabel = game.i18n.localize(`${MODULE_SCOPE}.WallHeightTopLabel`);
- const bottomLabel = game.i18n.localize(`${MODULE_SCOPE}.WallHeightBottomLabel`);
- const moduleLabel = game.i18n.localize(`${MODULE_SCOPE}.ModuleLabel`);
- html.find(`.door-options`).after(`
- <fieldset>
- <legend>${moduleLabel}</legend>
- <div class="form-group">
- <label>${topLabel}</label>
- <input name="flags.${MODULE_SCOPE}.${TOP_KEY}" type="number" step="any" value="${Number.isFinite(top) ? top : ""}" placeholder="Infinity">
- </div>
- <div class="form-group">
- <label>${bottomLabel}</label>
- <input name="flags.${MODULE_SCOPE}.${BOTTOM_KEY}" type="number" step="any" value="${Number.isFinite(bottom) ? bottom : ""}" placeholder="-Infinity">
- </div>
- </legend>
- </fieldset>
- `);
- app.setPosition({ height: "auto" });
- });
-
- Hooks.on("renderAmbientLightConfig", (app, html, data) => {
- const {advancedVision} = getSceneSettings(canvas.scene);
- if(!advancedVision) return;
- const label = game.i18n.localize(`${MODULE_SCOPE}.advancedLightingLabel`);
- const notes = game.i18n.localize(`${MODULE_SCOPE}.advancedLightingNotes`);
- const rangeTop = game.i18n.localize(`${MODULE_SCOPE}.levelsRangeTop`);
- const rangeBottom = game.i18n.localize(`${MODULE_SCOPE}.levelsRangeBottom`);
- const distance = (app.object.parent?.grid.units ?? game.system.grid.units) || game.i18n.localize(`${MODULE_SCOPE}.distance`);
- const checked = app.object.getFlag(MODULE_SCOPE, "advancedLighting") ? "checked" : "";
- const globalAdvancedLighting = game.settings.get(MODULE_ID, 'globalAdvancedLighting');
- const warnEnabledGlobally = `<p class="hint" style="color: red;">${game.i18n.localize(`${MODULE_SCOPE}.ALGlobal`)}</p>`;
- const hint = globalAdvancedLighting ? warnEnabledGlobally : ""
- const _injectHTML = `<div class="form-group">
- <label>${label}</label>
- <input type="checkbox" name="flags.${MODULE_SCOPE}.advancedLighting" ${checked} ${globalAdvancedLighting ? "disabled" : ""}>
- ${hint}
- <p class="hint">${notes}</p>
- </div>`
- html.find(`input[name="walls"]`).closest(".form-group").after(_injectHTML);
- app.setPosition({ height: "auto" });
-
- if(WallHeight.isLevels) return
- const bottom = app.object.flags?.levels?.rangeBottom;
- const top = app.object.flags?.levels?.rangeTop;
- const elevationHtml = `
- <div class="form-group">
- <label>${rangeTop} <span class="units">(${distance})</span></label>
- <div class="form-fields">
- <input name="flags.levels.rangeTop" type="number" step="any" value="${Number.isFinite(top) ? top : ""}" placeholder="Infinity">
- </div>
- </div>
- <div class="form-group">
- <label>${rangeBottom} <span class="units">(${distance})</span></label>
- <div class="form-fields">
- <input name="flags.levels.rangeBottom" type="number" step="any" value="${Number.isFinite(bottom) ? bottom : ""}" placeholder="-Infinity">
- </div>
- </div>
- `
- html.find(`input[name="config.dim"]`).closest(".form-group").after(elevationHtml);
- app.setPosition({ height: "auto" });
-
- })
-
- Hooks.on("renderAmbientSoundConfig", (app, html, data) => {
- const {advancedVision} = getSceneSettings(canvas.scene);
- if(!advancedVision) return;
- const label = game.i18n.localize(`${MODULE_SCOPE}.advancedLightingLabel`);
- const notes = game.i18n.localize(`${MODULE_SCOPE}.advancedLightingNotes`);
- const checked = app.object.getFlag(MODULE_SCOPE, "advancedLighting") ? "checked" : "";
- const rangeTop = game.i18n.localize(`${MODULE_SCOPE}.levelsRangeTop`);
- const rangeBottom = game.i18n.localize(`${MODULE_SCOPE}.levelsRangeBottom`);
- const distance = (canvas.scene.grid.units ?? game.system?.grid?.units) || game.i18n.localize(`${MODULE_SCOPE}.distance`);
- const globalAdvancedLighting = game.settings.get(MODULE_ID, 'globalAdvancedLighting');
- const warnEnabledGlobally = `<p class="hint" style="color: red;">${game.i18n.localize(`${MODULE_SCOPE}.ALGlobal`)}</p>`;
- const hint = globalAdvancedLighting ? warnEnabledGlobally : ""
- const _injectHTML = `<div class="form-group">
- <label>${label}</label>
- <input type="checkbox" name="flags.${MODULE_SCOPE}.advancedLighting" ${checked} ${globalAdvancedLighting ? "disabled" : ""}>
- ${hint}
- <p class="hint">${notes}</p>
- </div>`
- html.find(`input[name="walls"]`).closest(".form-group").after(_injectHTML);
- app.setPosition({ height: "auto" });
- if(WallHeight.isLevels) return
- const bottom = app.object.flags?.levels?.rangeBottom;
- const top = app.object.flags?.levels?.rangeTop;
- const elevationHtml = `
- <div class="form-group">
- <label>${rangeTop} <span class="units">(${distance})</span></label>
- <div class="form-fields">
- <input name="flags.levels.rangeTop" type="number" step="any" value="${Number.isFinite(top) ? top : ""}" placeholder="Infinity">
- </div>
- </div>
- <div class="form-group">
- <label>${rangeBottom} <span class="units">(${distance})</span></label>
- <div class="form-fields">
- <input name="flags.levels.rangeBottom" type="number" step="any" value="${Number.isFinite(bottom) ? bottom : ""}" placeholder="-Infinity">
- </div>
- </div>
- `
- html.find(`input[name="radius"]`).closest(".form-group").after(elevationHtml);
- app.setPosition({ height: "auto" });
- })
-
- Hooks.on("renderTokenConfig", (app, html, data) => {
- const tokenHeight = app.token.getFlag(MODULE_SCOPE, "tokenHeight") || 0;
- const label = game.i18n.localize(`${MODULE_SCOPE}.tokenHeightLabel`);
- const losHeight = app.object?.object?.losHeight ?? 0;
- const height = losHeight - app.token.elevation;
- const hint = game.i18n.localize(`${MODULE_SCOPE}.tokenHeightHint`).replace("{{height}}", height).replace("{{losHeight}}", losHeight);
- const distance = (canvas.scene.grid.units ?? game.system?.grid?.units) || game.i18n.localize(`${MODULE_SCOPE}.distance`);
- let newHtml = `
- <div class="form-group slim">
- <label>${label} <span class="units">(${distance})</span></label>
- <div class="form-fields">
- <input type="number" step="any" name="flags.${MODULE_SCOPE}.tokenHeight" placeholder="units" value="${tokenHeight}">
- </div>
- ${app.object?.object?.losHeight ? `<p class="hint">${hint}</p>` : ""}
- </div>
- `;
- html.find('input[name="lockRotation"]').closest(".form-group").before(newHtml);
- app.setPosition({ height: "auto" });
- });
-
- Hooks.on("renderSceneConfig", (app, html, data) => {
- const {advancedVision} = getSceneSettings(app.object);
- const enableVisionKeyLabel = game.i18n.localize(`${MODULE_SCOPE}.AdvancedVisionLabel`);
- const moduleLabel = game.i18n.localize(`${MODULE_SCOPE}.ModuleLabel`);
- html.find(`input[name="globalLightThreshold"]`).closest(".form-group").after(`
- <fieldset>
- <legend>${moduleLabel}</legend>
- <div class="form-group">
- <li class="flexrow">
- <label>${enableVisionKeyLabel}</label>
- <input name="flags.${MODULE_SCOPE}.${ENABLE_ADVANCED_VISION_KEY}" type="checkbox" data-dtype="Boolean" `+ ((advancedVision || advancedVision==null)?`checked`:``)+`>
- </li>
- </div>
- </fieldset>`
- );
- app.setPosition({ height: "auto" });
- });
-
- Handlebars.registerHelper('if_null', function(a, opts) {
- if (a == null) {
- return opts.fn(this);
- } else {
- return opts.inverse(this);
- }
- });
-
- // First time message
-
- Hooks.once("ready", () => {
- if(game.modules.get("levels-3d-preview")?.active) return;
- // Module title
- const MODULE_TITLE = game.modules.get(MODULE_ID).title;
-
- const FALLBACK_MESSAGE_TITLE = "Welcome to Wall Height";
- const FALLBACK_MESSAGE = `<large>
- <p><strong>I (theripper93) am now taking over the development of Wall Height, be sure to stop by my <a href="https://theripper93.com/">Discord</a> for help and support from the wonderful community as well as many resources</strong></p>
-
- <p>Thanks to all the patreons supporting the development of my modules making continued updates possible!</p>
- <p>If you want to support the development of the module you can do so here : <a href="https://www.patreon.com/theripper93">Patreon</a> </p></large>
- <p><strong>Patreons</strong> get also access to <strong>15+ premium modules</strong></p>
- <p>Want even more verticality? Go Full 3D</p>
- <h1>3D Canvas</h1>
- <iframe width="385" height="225" src="https://www.youtube.com/embed/rziXLJEfxqI" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
- <p>Check 3D Canvas and all my other <strong>15+ premium modules <a href="https://theripper93.com/">Here</a></strong></p>`;
-
- // Settings key used for the "Don't remind me again" setting
- const DONT_REMIND_AGAIN_KEY = "popup-dont-remind-again";
-
- // Dialog code
- game.settings.register(MODULE_ID, DONT_REMIND_AGAIN_KEY, {
- name: "",
- default: false,
- type: Boolean,
- scope: "world",
- config: false,
- });
- if (game.user.isGM && !game.settings.get(MODULE_ID, DONT_REMIND_AGAIN_KEY)) {
- new Dialog({
- title: FALLBACK_MESSAGE_TITLE,
- content: FALLBACK_MESSAGE,
- buttons: {
- dont_remind: {
- icon: '<i class="fas fa-times"></i>',
- label: "Don't remind me again",
- callback: () => game.settings.set(MODULE_ID, DONT_REMIND_AGAIN_KEY, true),
- },
- },
- default: "dont_remind",
- }).render(true);
- }
- });
-
|