diff --git a/lang/en.json b/lang/en.json
index 66c6f9c..a06e484 100644
--- a/lang/en.json
+++ b/lang/en.json
@@ -245,6 +245,7 @@
"clearLevels": "Clear Levels",
"debugScene": "Debug Scene (Red means issues detected)",
"minElevDiff": "Minimum Level Size",
+ "tokenAttacher": "Place Token Attacher prefabs relative to the current level",
"warning": "WARNING! 'Don't disable lights' is enabled in the Scene Settings - Multiple levels will not work correctly. Click to resolve this issue."
},
"yesnodialog": {
diff --git a/packs/levels-samples/002055.log b/packs/levels-samples/002095.log
similarity index 100%
rename from packs/levels-samples/002055.log
rename to packs/levels-samples/002095.log
diff --git a/packs/levels-samples/CURRENT b/packs/levels-samples/CURRENT
index 4c0052f..9ba62b9 100644
--- a/packs/levels-samples/CURRENT
+++ b/packs/levels-samples/CURRENT
@@ -1 +1 @@
-MANIFEST-002054
+MANIFEST-002094
diff --git a/packs/levels-samples/LOG b/packs/levels-samples/LOG
index 65ab5c8..6872016 100644
--- a/packs/levels-samples/LOG
+++ b/packs/levels-samples/LOG
@@ -1,3 +1,3 @@
-2024/03/17-14:22:08.913 9100 Recovering log #2052
-2024/03/17-14:22:08.917 9100 Delete type=0 #2052
-2024/03/17-14:22:08.917 9100 Delete type=3 #2050
+2024/03/23-17:18:29.289 7450 Recovering log #2093
+2024/03/23-17:18:29.293 7450 Delete type=0 #2093
+2024/03/23-17:18:29.293 7450 Delete type=3 #2092
diff --git a/packs/levels-samples/LOG.old b/packs/levels-samples/LOG.old
index 1d538dd..8db7b61 100644
--- a/packs/levels-samples/LOG.old
+++ b/packs/levels-samples/LOG.old
@@ -1,8 +1,3 @@
-2024/03/16-23:28:33.229 156c Recovering log #2048
-2024/03/16-23:28:33.237 156c Delete type=0 #2048
-2024/03/16-23:28:33.237 156c Delete type=3 #2046
-2024/03/16-23:33:04.688 8f84 Level-0 table #2053: started
-2024/03/16-23:33:04.688 8f84 Level-0 table #2053: 0 bytes OK
-2024/03/16-23:33:04.689 8f84 Delete type=0 #2051
-2024/03/16-23:33:04.689 8f84 Manual compaction at level-0 from '!scenes!fT64AORvwMUdHzwr' @ 72057594037927935 : 1 .. '!scenes.walls!w5eztsez7EhiFrmE.zlashxFbpTyjyOHo' @ 0 : 0; will stop at (end)
-2024/03/16-23:33:04.689 8f84 Manual compaction at level-1 from '!scenes!fT64AORvwMUdHzwr' @ 72057594037927935 : 1 .. '!scenes.walls!w5eztsez7EhiFrmE.zlashxFbpTyjyOHo' @ 0 : 0; will stop at (end)
+2024/03/22-16:56:02.550 195c Recovering log #2091
+2024/03/22-16:56:02.553 195c Delete type=0 #2091
+2024/03/22-16:56:02.553 195c Delete type=3 #2090
diff --git a/packs/levels-samples/MANIFEST-002054 b/packs/levels-samples/MANIFEST-002094
similarity index 86%
rename from packs/levels-samples/MANIFEST-002054
rename to packs/levels-samples/MANIFEST-002094
index 2e2489a..fe70246 100644
Binary files a/packs/levels-samples/MANIFEST-002054 and b/packs/levels-samples/MANIFEST-002094 differ
diff --git a/packs/macros/002055.log b/packs/macros/002095.log
similarity index 100%
rename from packs/macros/002055.log
rename to packs/macros/002095.log
diff --git a/packs/macros/CURRENT b/packs/macros/CURRENT
index 4c0052f..9ba62b9 100644
--- a/packs/macros/CURRENT
+++ b/packs/macros/CURRENT
@@ -1 +1 @@
-MANIFEST-002054
+MANIFEST-002094
diff --git a/packs/macros/LOG b/packs/macros/LOG
index 30d3a15..222e718 100644
--- a/packs/macros/LOG
+++ b/packs/macros/LOG
@@ -1,3 +1,3 @@
-2024/03/17-14:22:08.900 3084 Recovering log #2052
-2024/03/17-14:22:08.904 3084 Delete type=0 #2052
-2024/03/17-14:22:08.905 3084 Delete type=3 #2050
+2024/03/23-17:18:29.275 12c0 Recovering log #2093
+2024/03/23-17:18:29.280 12c0 Delete type=0 #2093
+2024/03/23-17:18:29.280 12c0 Delete type=3 #2092
diff --git a/packs/macros/LOG.old b/packs/macros/LOG.old
index 9ea36fb..e7e4a0e 100644
--- a/packs/macros/LOG.old
+++ b/packs/macros/LOG.old
@@ -1,8 +1,3 @@
-2024/03/16-23:28:33.209 913c Recovering log #2048
-2024/03/16-23:28:33.218 913c Delete type=0 #2048
-2024/03/16-23:28:33.218 913c Delete type=3 #2046
-2024/03/16-23:33:04.683 8f84 Level-0 table #2053: started
-2024/03/16-23:33:04.683 8f84 Level-0 table #2053: 0 bytes OK
-2024/03/16-23:33:04.685 8f84 Delete type=0 #2051
-2024/03/16-23:33:04.685 8f84 Manual compaction at level-0 from '!macros!2LfY4Ky5rRDkK7h8' @ 72057594037927935 : 1 .. '!macros!yx7Eb76rfzjh0LEO' @ 0 : 0; will stop at (end)
-2024/03/16-23:33:04.685 8f84 Manual compaction at level-1 from '!macros!2LfY4Ky5rRDkK7h8' @ 72057594037927935 : 1 .. '!macros!yx7Eb76rfzjh0LEO' @ 0 : 0; will stop at (end)
+2024/03/22-16:56:02.537 6e8c Recovering log #2091
+2024/03/22-16:56:02.541 6e8c Delete type=0 #2091
+2024/03/22-16:56:02.541 6e8c Delete type=3 #2090
diff --git a/packs/macros/MANIFEST-002054 b/packs/macros/MANIFEST-002094
similarity index 52%
rename from packs/macros/MANIFEST-002054
rename to packs/macros/MANIFEST-002094
index 1d7aa87..5f18bdb 100644
Binary files a/packs/macros/MANIFEST-002054 and b/packs/macros/MANIFEST-002094 differ
diff --git a/scripts/ui.js b/scripts/ui.js
index 997537e..9529d1b 100644
--- a/scripts/ui.js
+++ b/scripts/ui.js
@@ -1,804 +1,694 @@
class LevelsUI extends FormApplication {
- constructor() {
- super();
- this.range = [];
- this.rangeEnabled = false;
- this.isEdit = false;
- this.definedLevels = [];
- this.roofEnabled = false;
- this.placeOverhead = false;
- this.stairEnabled = true;
- }
-
- static get defaultOptions() {
- return {
- ...super.defaultOptions,
- title: game.i18n.localize("levels.ui.title"),
- id: "levelsUI",
- template: `modules/levels/templates/layerTool.hbs`,
- resizable: true,
- dragDrop: [{ dragSelector: null, dropSelector: null }],
- };
- }
-
- get currentRange() {
- const bgElev = canvas.primary.background.elevation;
- if(!this.rangeEnabled) return { bottom: bgElev, top: bgElev };
- if(!this.range?.length) return { bottom: bgElev, top: bgElev };
- return {
- bottom: parseFloat(this.range[0]),
- top: parseFloat(this.range[1]),
+ constructor() {
+ super();
+ this.range = [];
+ this.rangeEnabled = false;
+ this.isEdit = false;
+ this.definedLevels = [];
+ this.roofEnabled = false;
+ this.placeOverhead = false;
+ this.stairEnabled = true;
+ this.tokenOnly = false;
}
- }
- getRange() {
- return {
- bottom: parseFloat(this.range[0] ?? -Infinity),
- top: parseFloat(this.range[1] ?? Infinity),
+ static get defaultOptions() {
+ return {
+ ...super.defaultOptions,
+ title: game.i18n.localize("levels.ui.title"),
+ id: "levelsUI",
+ template: `modules/levels/templates/layerTool.hbs`,
+ resizable: true,
+ dragDrop: [{ dragSelector: null, dropSelector: null }],
+ };
}
- }
- getData() {
- return {
- lightMasking: canvas.scene.getFlag(CONFIG.Levels.MODULE_ID, "lightMasking") ?? true,
- };
- }
-
- async activateListeners(html) {
- ui.controls.control.foreground = true;
- canvas.tiles._activateSubLayer(true);
- this.rangeEnabled = true;
- this.loadLevels();
- html.on("click", ".level-item", this._onChangeLevel.bind(this));
- html.on("click", ".level-item .fa-trash", this._onRemoveLevel.bind(this));
- html.on(
- "click",
- "#levels-ui-controls .fa-trash",
- this._onClearLevels.bind(this)
- );
- html.on(
- "click",
- "#levels-ui-controls .fa-plus",
- this._onAddLevel.bind(this)
- );
- html.on(
- "click",
- "#levels-ui-controls .fa-edit",
- this._onToggleEdit.bind(this)
- );
- html.on(
- "click",
- "#levels-ui-controls .fa-map",
- this._onGetFromScene.bind(this)
- );
- html.on(
- "click",
- "#levels-ui-controls .fa-users",
- this._onShowPlayerList.bind(this)
- );
- html.on(
- "click",
- "#levels-ui-controls .fa-archway",
- () => {
- this.roofEnabled = !this.roofEnabled;
- this.setButtonStyles();
- this.computeLevelsVisibility();
- }
- );
- html.on(
- "click",
- "#levels-ui-controls .fa-tree",
- () => {
- this.placeOverhead = !this.placeOverhead;
+ get currentRange() {
+ const bgElev = canvas.primary.background.elevation;
+ if (!this.rangeEnabled) return { bottom: bgElev, top: bgElev };
+ if (!this.range?.length) return { bottom: bgElev, top: bgElev };
+ return {
+ bottom: parseFloat(this.range[0]),
+ top: parseFloat(this.range[1]),
+ };
+ }
+
+ getRange() {
+ return {
+ bottom: parseFloat(this.range[0] ?? -Infinity),
+ top: parseFloat(this.range[1] ?? Infinity),
+ };
+ }
+
+ getData() {
+ return {
+ lightMasking: canvas.scene.getFlag(CONFIG.Levels.MODULE_ID, "lightMasking") ?? true,
+ };
+ }
+
+ async activateListeners(html) {
+ ui.controls.control.foreground = true;
+ canvas.tiles._activateSubLayer(true);
+ this.rangeEnabled = true;
+ this.loadLevels();
+ html.on("click", ".level-item", this._onChangeLevel.bind(this));
+ html.on("click", ".level-item .fa-trash", this._onRemoveLevel.bind(this));
+ html.on("click", "#levels-ui-controls .fa-trash", this._onClearLevels.bind(this));
+ html.on("click", "#levels-ui-controls .fa-plus", this._onAddLevel.bind(this));
+ html.on("click", "#levels-ui-controls .fa-edit", this._onToggleEdit.bind(this));
+ html.on("click", "#levels-ui-controls .fa-map", this._onGetFromScene.bind(this));
+ html.on("click", "#levels-ui-controls .fa-users", this._onShowPlayerList.bind(this));
+ html.on("click", "#levels-ui-controls .fa-archway", () => {
+ this.roofEnabled = !this.roofEnabled;
+ this.setButtonStyles();
+ this.computeLevelsVisibility();
+ });
+ html.on("click", "#levels-ui-controls .fa-tree", () => {
+ this.placeOverhead = !this.placeOverhead;
+ this.setButtonStyles();
+ });
+ html.on("click", "#levels-ui-controls .fa-sort-amount-up-alt", () => {
+ this.stairEnabled = !this.stairEnabled;
+ this.setButtonStyles();
+ });
+ html.on("click", "#levels-ui-controls .fa-circle-exclamation", async () => {
+ await canvas.scene.setFlag(CONFIG.Levels.MODULE_ID, "lightMasking", false);
+ this.render(true);
+ });
+
+ html.on("click", "#levels-ui-controls .fa-link", async () => {
+ this.tokenOnly = !this.tokenOnly;
this.setButtonStyles();
- }
- );
- html.on(
- "click",
- "#levels-ui-controls .fa-sort-amount-up-alt",
- () => {
- this.stairEnabled = !this.stairEnabled;
+ });
+
+ html.on("drop", (event) => {
+ let data;
+ try {
+ data = JSON.parse(event.originalEvent.dataTransfer.getData("text/plain"));
+ } catch (err) {
+ return false;
+ }
+ if (data.type === "Scene") this._onDropScene(data.uuid);
+ });
+
+ html.on("click", ".player-portrait", this._onControlToken.bind(this));
+ html.on("change", ".level-inputs input", this.saveData.bind(this));
+ //make list sortable
+ html.find("#levels-list").sortable({
+ axis: "y",
+ handle: ".fa-arrows-alt",
+ update: this.saveData.bind(this),
+ });
+ const index = this.definedLevels ? this.definedLevels.indexOf(this.definedLevels.find((l) => l[0] == this.range[0] && l[1] == this.range[1] && l[2] == this.range[2])) : undefined;
+ if (index === undefined || index === -1) {
+ html.find("#levels-list li:last-child").click();
+ } else html.find("#levels-list li")[index].click();
+ this.updatePlayerList();
this.setButtonStyles();
- }
- );
- html.on(
- "click",
- "#levels-ui-controls .fa-circle-exclamation",
- async () => {
- await canvas.scene.setFlag(CONFIG.Levels.MODULE_ID, "lightMasking", false);
- this.render(true);
- }
- )
-
- html.on("drop", (event) => {
- let data;
- try {
- data = JSON.parse(event.originalEvent.dataTransfer.getData("text/plain"));
- } catch (err) {
- return false;
- }
- if(data.type === "Scene") this._onDropScene(data.uuid)
- });
-
- html.on("click", ".player-portrait", this._onControlToken.bind(this));
- html.on("change", ".level-inputs input", this.saveData.bind(this));
- //make list sortable
- html.find("#levels-list").sortable({
- axis: "y",
- handle: ".fa-arrows-alt",
- update: this.saveData.bind(this),
- });
- const index = this.definedLevels
- ? this.definedLevels.indexOf(
- this.definedLevels.find(
- (l) =>
- l[0] == this.range[0] &&
- l[1] == this.range[1] &&
- l[2] == this.range[2]
- )
- )
- : undefined;
- if (index === undefined || index === -1) {
- html.find("#levels-list li:last-child").click();
- } else html.find("#levels-list li")[index].click();
- this.updatePlayerList();
- this.setButtonStyles();
- }
-
- setButtonStyles() {
- this.element.find(".fa-archway").toggleClass("active", this.roofEnabled);
- this.element.find(".fa-tree").toggleClass("active", this.placeOverhead);
- this.element.find(".fa-sort-amount-up-alt").toggleClass("active", this.stairEnabled);
- this.element.find(".fa-users").toggleClass("active", this.element.find(".players-on-level").hasClass("active"));
- }
-
- _onAddLevel(event) {
- let $li = this.generateLi([0, 0, ""]);
- $("#levels-list").append($li);
- }
- //toggle readonly property of inputs and toggle visibility of trash icon
- _onToggleEdit(event) {
- this.isEdit = !this.isEdit;
- let $inputs = $(".level-inputs input");
- $inputs.prop("readonly", !$inputs.prop("readonly"));
- $(".level-item .fa-trash").toggleClass("hidden");
- $(".level-item .fa-arrows-alt").toggleClass("hidden");
- this.saveData();
- }
-
- activateForeground(){
- try{
- ui.controls.control.foreground = true;
- ui.controls.control.foreground = true;
- canvas.tiles._activateSubLayer(true);
- canvas.perception.update({refreshLighting: true, refreshTiles: true}, true);
- const fgControl = document.querySelector(`[data-tool="foreground"]`)
- if(fgControl) fgControl.classList.add("active")
- }catch(e){}
- }
-
- _onChangeLevel(event) {
- this.activateForeground()
- if (!$(event.target).hasClass("player-portrait"))
- canvas.tokens.releaseAll();
- let $target = $(event.currentTarget);
- let $parent = $target.parent();
- $parent.find(".fa-caret-right").removeClass("active");
- $parent.find("li").removeClass("active");
- $target.find(".fa-caret-right").addClass("active");
- $target.addClass("active");
- const top = $target.find(".level-top").val();
- const bottom = $target.find(".level-bottom").val();
- const name = $target.find(".level-name").val();
- this.definedLevels = canvas.scene.getFlag(
- CONFIG.Levels.MODULE_ID,
- "sceneLevels"
- );
- this.range = this.definedLevels?.find((l) => l[0] == bottom && l[1] == top) ?? [parseFloat(bottom), parseFloat(top)];
- if ($(event.target).hasClass("player-portrait")) return;
- WallHeight.currentTokenElevation = parseFloat(bottom);
- this.computeLevelsVisibility(this.range);
- Hooks.callAll("levelsUiChangeLevel");
- }
-
- _onRemoveLevel(event) {
- Dialog.confirm({
- title: game.i18n.localize("levels.dialog.removeLevel.title"),
- content: game.i18n.localize("levels.dialog.removeLevel.content"),
- yes: () => {
- let $target = $(event.currentTarget);
- $target.remove();
+ }
+
+ setButtonStyles() {
+ this.element.find(".fa-archway").toggleClass("active", this.roofEnabled);
+ this.element.find(".fa-tree").toggleClass("active", this.placeOverhead);
+ this.element.find(".fa-sort-amount-up-alt").toggleClass("active", this.stairEnabled);
+ this.element.find(".fa-users").toggleClass("active", this.element.find(".players-on-level").hasClass("active"));
+ this.element.find(".fa-link").toggleClass("active", this.tokenOnly);
+ }
+
+ _onAddLevel(event) {
+ let $li = this.generateLi([0, 0, ""]);
+ $("#levels-list").append($li);
+ }
+ //toggle readonly property of inputs and toggle visibility of trash icon
+ _onToggleEdit(event) {
+ this.isEdit = !this.isEdit;
+ let $inputs = $(".level-inputs input");
+ $inputs.prop("readonly", !$inputs.prop("readonly"));
+ $(".level-item .fa-trash").toggleClass("hidden");
+ $(".level-item .fa-arrows-alt").toggleClass("hidden");
this.saveData();
- },
- no: () => {},
- defaultYes: false,
- });
- }
-
- _onGetFromScene(event) {
- Dialog.confirm({
- title: game.i18n.localize("levels.dialog.getFromScene.title"),
- content: game.i18n.localize("levels.dialog.getFromScene.content"),
- yes: (html) => {
- const maxRange = parseFloat(html.find("#maxelevationdifference").val());
- this.getFromScene(maxRange);
- },
- no: () => {},
- render: (html) => {
- const maxRange = `
+ }
+
+ activateForeground() {
+ try {
+ ui.controls.control.foreground = true;
+ ui.controls.control.foreground = true;
+ canvas.tiles._activateSubLayer(true);
+ canvas.perception.update({ refreshLighting: true, refreshTiles: true }, true);
+ const fgControl = document.querySelector(`[data-tool="foreground"]`);
+ if (fgControl) fgControl.classList.add("active");
+ } catch (e) {}
+ }
+
+ _onChangeLevel(event) {
+ this.activateForeground();
+ if (!$(event.target).hasClass("player-portrait")) canvas.tokens.releaseAll();
+ let $target = $(event.currentTarget);
+ let $parent = $target.parent();
+ $parent.find(".fa-caret-right").removeClass("active");
+ $parent.find("li").removeClass("active");
+ $target.find(".fa-caret-right").addClass("active");
+ $target.addClass("active");
+ const top = $target.find(".level-top").val();
+ const bottom = $target.find(".level-bottom").val();
+ const name = $target.find(".level-name").val();
+ this.definedLevels = canvas.scene.getFlag(CONFIG.Levels.MODULE_ID, "sceneLevels");
+ this.range = this.definedLevels?.find((l) => l[0] == bottom && l[1] == top) ?? [parseFloat(bottom), parseFloat(top)];
+ if ($(event.target).hasClass("player-portrait")) return;
+ WallHeight.currentTokenElevation = parseFloat(bottom);
+ this.computeLevelsVisibility(this.range);
+ Hooks.callAll("levelsUiChangeLevel");
+ }
+
+ _onRemoveLevel(event) {
+ Dialog.confirm({
+ title: game.i18n.localize("levels.dialog.removeLevel.title"),
+ content: game.i18n.localize("levels.dialog.removeLevel.content"),
+ yes: () => {
+ let $target = $(event.currentTarget);
+ $target.remove();
+ this.saveData();
+ },
+ no: () => {},
+ defaultYes: false,
+ });
+ }
+
+ _onGetFromScene(event) {
+ Dialog.confirm({
+ title: game.i18n.localize("levels.dialog.getFromScene.title"),
+ content: game.i18n.localize("levels.dialog.getFromScene.content"),
+ yes: (html) => {
+ const maxRange = parseFloat(html.find("#maxelevationdifference").val());
+ this.getFromScene(maxRange);
+ },
+ no: () => {},
+ render: (html) => {
+ const maxRange = `
- `
- $(html[0]).append(maxRange);
- },
- defaultYes: false,
- });
- }
-
- _onShowPlayerList(event) {
- this.element.find(".players-on-level").toggleClass("active");
- this.setButtonStyles();
- }
-
- _onControlToken(event) {
- canvas.tokens.releaseAll();
- const tokenId = event.currentTarget.dataset.tokenid;
- const token = canvas.tokens.get(tokenId);
- token.control();
- }
-
- async _onDropScene(uuid) {
- const scene = await fromUuid(uuid);
- if (!scene) return;
- const dialogResult = await Dialog.confirm({
- title: game.i18n.localize("levels.dialog.sceneDrop.title"),
- content: game.i18n.localize("levels.dialog.sceneDrop.content"),
- })
- if (!dialogResult) return;
- const collections = Object.keys(scene.collections);
- for (const collection of collections) {
- const documents = Array.from(scene[collection]);
- if(!documents.length) continue;
- await canvas.scene.createEmbeddedDocuments(documents[0].documentName, documents);
+ `;
+ $(html[0]).append(maxRange);
+ },
+ defaultYes: false,
+ });
}
- const sceneBg = scene.background.src;
- if(!sceneBg) return;
- const {sceneWidth, sceneHeight, sceneX, sceneY} = scene.dimensions;
- await canvas.scene.createEmbeddedDocuments("Tile", [{
- "texture.src": sceneBg,
- "width": sceneWidth,
- "height": sceneHeight,
- "x": sceneX,
- "y": sceneY,
- }]);
- }
-
- saveData() {
- let data = [];
- $(this.element)
- .find("li")
- .each((index, element) => {
- let $element = $(element);
- let name = $element.find(".level-name").val();
- let top = $element.find(".level-top").val();
- let bottom = $element.find(".level-bottom").val();
- data.push([bottom, top, name]);
- });
- canvas.scene.setFlag(CONFIG.Levels.MODULE_ID, "sceneLevels", data);
- }
-
- async loadLevels() {
- $("#levels-list").empty();
- let levelsFlag =
- canvas.scene.getFlag(CONFIG.Levels.MODULE_ID, "sceneLevels") || [];
- this.definedLevels = levelsFlag;
- this.range = this.range ?? this.definedLevels[levelsFlag.length - 1];
- if (levelsFlag) {
- for (let level of levelsFlag) {
- this.element.find("#levels-list").append(this.generateLi(level));
- }
+
+ _onShowPlayerList(event) {
+ this.element.find(".players-on-level").toggleClass("active");
+ this.setButtonStyles();
+ }
+
+ _onControlToken(event) {
+ canvas.tokens.releaseAll();
+ const tokenId = event.currentTarget.dataset.tokenid;
+ const token = canvas.tokens.get(tokenId);
+ token.control();
}
- }
- generateLi(data) {
- //data 0 - top 1- bottom 2- name
- let $li = $(`
+ async _onDropScene(uuid) {
+ const scene = await fromUuid(uuid);
+ if (!scene) return;
+ const dialogResult = await Dialog.confirm({
+ title: game.i18n.localize("levels.dialog.sceneDrop.title"),
+ content: game.i18n.localize("levels.dialog.sceneDrop.content"),
+ });
+ if (!dialogResult) return;
+ const collections = Object.keys(scene.collections);
+ for (const collection of collections) {
+ const documents = Array.from(scene[collection]);
+ if (!documents.length) continue;
+ await canvas.scene.createEmbeddedDocuments(documents[0].documentName, documents);
+ }
+ const sceneBg = scene.background.src;
+ if (!sceneBg) return;
+ const { sceneWidth, sceneHeight, sceneX, sceneY } = scene.dimensions;
+ await canvas.scene.createEmbeddedDocuments("Tile", [
+ {
+ "texture.src": sceneBg,
+ width: sceneWidth,
+ height: sceneHeight,
+ x: sceneX,
+ y: sceneY,
+ },
+ ]);
+ }
+
+ saveData() {
+ let data = [];
+ $(this.element)
+ .find("li")
+ .each((index, element) => {
+ let $element = $(element);
+ let name = $element.find(".level-name").val();
+ let top = $element.find(".level-top").val();
+ let bottom = $element.find(".level-bottom").val();
+ data.push([bottom, top, name]);
+ });
+ canvas.scene.setFlag(CONFIG.Levels.MODULE_ID, "sceneLevels", data);
+ }
+
+ async loadLevels() {
+ $("#levels-list").empty();
+ let levelsFlag = canvas.scene.getFlag(CONFIG.Levels.MODULE_ID, "sceneLevels") || [];
+ this.definedLevels = levelsFlag;
+ this.range = this.range ?? this.definedLevels[levelsFlag.length - 1];
+ if (levelsFlag) {
+ for (let level of levelsFlag) {
+ this.element.find("#levels-list").append(this.generateLi(level));
+ }
+ }
+ }
+
+ generateLi(data) {
+ //data 0 - top 1- bottom 2- name
+ let $li = $(`
-
+
-
+
`);
- $li.find("input").prop("readonly", !this.isEdit);
- $li.find(".fa-trash").toggleClass("hidden", this.isEdit);
- $li.find(".fa-arrows-alt").toggleClass("hidden", this.isEdit);
- return $li;
- }
-
- async _onClearLevels() {
- Dialog.confirm({
- title: game.i18n.localize("levels.dialog.levelsclear.title"),
- content: game.i18n.localize("levels.dialog.levelsclear.content"),
- yes: async () => {
- await canvas.scene.setFlag(CONFIG.Levels.MODULE_ID, "sceneLevels", []);
- this.loadLevels();
- },
- no: () => {},
- defaultYes: false,
- });
- }
-
- updatePlayerList() {
- const playerActors = Array.from(game.users).map(
- (user) => user.character?.id
- );
- const players = canvas.tokens.placeables.filter((token) =>
- playerActors.includes(token.actor?.id)
- );
- $(this.element)
- .find("li")
- .each((index, element) => {
- let $element = $(element);
- const top = $element.find(".level-top").val();
- const bottom = $element.find(".level-bottom").val();
- const $playerList = $element.find(".players-on-level");
- $playerList.empty();
- players.forEach((player) => {
- if (
- player.losHeight >= bottom &&
- player.losHeight < top &&
- player.id
- ) {
- const color = Array.from(game.users).find(
- (user) => user.character?.id == player?.actor?.id
- )?.border;
- $playerList.append(
- ``
- );
- }
+ $li.find("input").prop("readonly", !this.isEdit);
+ $li.find(".fa-trash").toggleClass("hidden", this.isEdit);
+ $li.find(".fa-arrows-alt").toggleClass("hidden", this.isEdit);
+ return $li;
+ }
+
+ async _onClearLevels() {
+ Dialog.confirm({
+ title: game.i18n.localize("levels.dialog.levelsclear.title"),
+ content: game.i18n.localize("levels.dialog.levelsclear.content"),
+ yes: async () => {
+ await canvas.scene.setFlag(CONFIG.Levels.MODULE_ID, "sceneLevels", []);
+ this.loadLevels();
+ },
+ no: () => {},
+ defaultYes: false,
});
- });
- this.element.css("height", "auto");
- }
-
- close(force = false) {
- if (!force) this.saveData();
- this.rangeEnabled = false;
- if (!force) this.computeLevelsVisibility();
- CONFIG.Levels.handlers.RefreshHandler.restoreVisAll();
- CONFIG.Levels.handlers.RefreshHandler.refreshAll();
- WallHeight.schedulePerceptionUpdate()
- super.close();
- }
-
- async getFromScene(maxRange = 9) {
- let autoLevels = {};
- for (let wall of canvas.walls.placeables) {
- const { top, bottom } = WallHeight.getWallBounds(wall);
- let entityRange = [bottom, top];
- if (
- entityRange[0] != -Infinity &&
- entityRange[1] != Infinity &&
- (entityRange[0] || entityRange[0] == 0) &&
- (entityRange[1] || entityRange[1] == 0)
- ) {
- autoLevels[`${entityRange[0]}${entityRange[1]}`] = entityRange;
- }
}
- for (let tile of canvas.tiles.placeables.filter(
- (t) => t.document.overhead
- )) {
- let { rangeBottom, rangeTop } =
- CONFIG.Levels.helpers.getRangeForDocument(tile);
- if (
- (rangeBottom || rangeBottom == 0) &&
- (rangeTop || rangeTop == 0) &&
- rangeTop != Infinity &&
- rangeBottom != -Infinity
- ) {
- autoLevels[`${rangeBottom}${rangeTop}`] = [rangeBottom, rangeTop];
- }
+ updatePlayerList() {
+ const playerActors = Array.from(game.users).map((user) => user.character?.id);
+ const players = canvas.tokens.placeables.filter((token) => playerActors.includes(token.actor?.id));
+ $(this.element)
+ .find("li")
+ .each((index, element) => {
+ let $element = $(element);
+ const top = $element.find(".level-top").val();
+ const bottom = $element.find(".level-bottom").val();
+ const $playerList = $element.find(".players-on-level");
+ $playerList.empty();
+ players.forEach((player) => {
+ if (player.losHeight >= bottom && player.losHeight < top && player.id) {
+ const color = Array.from(game.users).find((user) => user.character?.id == player?.actor?.id)?.border;
+ $playerList.append(``);
+ }
+ });
+ });
+ this.element.css("height", "auto");
}
- for (let light of canvas.lighting.placeables) {
- let { rangeBottom, rangeTop } =
- CONFIG.Levels.helpers.getRangeForDocument(light);
- if (
- (rangeBottom || rangeBottom == 0) &&
- (rangeTop || rangeTop == 0) &&
- rangeTop != Infinity &&
- rangeBottom != -Infinity
- ) {
- autoLevels[`${rangeBottom}${rangeTop}`] = [rangeBottom, rangeTop];
- }
+ close(force = false) {
+ if (!force) this.saveData();
+ this.rangeEnabled = false;
+ if (!force) this.computeLevelsVisibility();
+ CONFIG.Levels.handlers.RefreshHandler.restoreVisAll();
+ CONFIG.Levels.handlers.RefreshHandler.refreshAll();
+ WallHeight.schedulePerceptionUpdate();
+ super.close();
}
- for (let drawing of canvas.drawings.placeables) {
- let { rangeBottom, rangeTop } =
- CONFIG.Levels.helpers.getRangeForDocument(drawing);
- if (
- (rangeBottom || rangeBottom == 0) &&
- (rangeTop || rangeTop == 0) &&
- rangeTop != Infinity &&
- rangeBottom != -Infinity
- ) {
- autoLevels[`${rangeBottom}${rangeTop}`] = [rangeBottom, rangeTop];
- }
+ async getFromScene(maxRange = 9) {
+ let autoLevels = {};
+ for (let wall of canvas.walls.placeables) {
+ const { top, bottom } = WallHeight.getWallBounds(wall);
+ let entityRange = [bottom, top];
+ if (entityRange[0] != -Infinity && entityRange[1] != Infinity && (entityRange[0] || entityRange[0] == 0) && (entityRange[1] || entityRange[1] == 0)) {
+ autoLevels[`${entityRange[0]}${entityRange[1]}`] = entityRange;
+ }
+ }
+
+ for (let tile of canvas.tiles.placeables.filter((t) => t.document.overhead)) {
+ let { rangeBottom, rangeTop } = CONFIG.Levels.helpers.getRangeForDocument(tile);
+ if ((rangeBottom || rangeBottom == 0) && (rangeTop || rangeTop == 0) && rangeTop != Infinity && rangeBottom != -Infinity) {
+ autoLevels[`${rangeBottom}${rangeTop}`] = [rangeBottom, rangeTop];
+ }
+ }
+
+ for (let light of canvas.lighting.placeables) {
+ let { rangeBottom, rangeTop } = CONFIG.Levels.helpers.getRangeForDocument(light);
+ if ((rangeBottom || rangeBottom == 0) && (rangeTop || rangeTop == 0) && rangeTop != Infinity && rangeBottom != -Infinity) {
+ autoLevels[`${rangeBottom}${rangeTop}`] = [rangeBottom, rangeTop];
+ }
+ }
+
+ for (let drawing of canvas.drawings.placeables) {
+ let { rangeBottom, rangeTop } = CONFIG.Levels.helpers.getRangeForDocument(drawing);
+ if ((rangeBottom || rangeBottom == 0) && (rangeTop || rangeTop == 0) && rangeTop != Infinity && rangeBottom != -Infinity) {
+ autoLevels[`${rangeBottom}${rangeTop}`] = [rangeBottom, rangeTop];
+ }
+ }
+ let autoRange = Object.entries(autoLevels)
+ .map((x) => x[1])
+ .filter((x) => Math.abs(x[1] - x[0]) >= maxRange)
+ .sort()
+ .reverse();
+ if (autoRange.length) {
+ await canvas.scene.setFlag(CONFIG.Levels.MODULE_ID, "sceneLevels", autoRange);
+ this.loadLevels();
+ }
}
- let autoRange = Object.entries(autoLevels)
- .map((x) => x[1])
- .filter( x => Math.abs(x[1] - x[0]) >= maxRange)
- .sort()
- .reverse();
- if (autoRange.length) {
- await canvas.scene.setFlag(
- CONFIG.Levels.MODULE_ID,
- "sceneLevels",
- autoRange
- );
- this.loadLevels();
+
+ computeLevelsVisibility() {
+ WallHeight.currentTokenElevation = parseFloat(this.range[0] ?? 0);
+ CONFIG.Levels.handlers.RefreshHandler.refreshAll();
+ WallHeight.schedulePerceptionUpdate();
}
- }
-
- computeLevelsVisibility() {
- WallHeight.currentTokenElevation = parseFloat(this.range[0] ?? 0);
- CONFIG.Levels.handlers.RefreshHandler.refreshAll();
- WallHeight.schedulePerceptionUpdate();
- }
-
- computeRangeForDocument(document, range, isTile = false) {
- let { rangeBottom, rangeTop } =
- CONFIG.Levels.helpers.getRangeForDocument(document);
- rangeBottom = rangeBottom ?? -Infinity;
- rangeTop = rangeTop ?? Infinity;
- range[0] = parseFloat(range[0]) ?? -Infinity;
- range[1] = parseFloat(range[1]) ?? Infinity;
- let entityRange = [rangeBottom, rangeTop];
- if (!isTile) {
- if (
- (entityRange[0] >= range[0] && entityRange[0] <= range[1]) ||
- (entityRange[1] >= range[0] && entityRange[1] <= range[1])
- ) {
- return true;
- } else {
- return false;
- }
- } else {
- if (entityRange[0] == range[1] + 1 && entityRange[1] == Infinity) {
- return true;
- } else {
- if (entityRange[0] >= range[0] && entityRange[1] <= range[1]) {
- return true;
+
+ computeRangeForDocument(document, range, isTile = false) {
+ let { rangeBottom, rangeTop } = CONFIG.Levels.helpers.getRangeForDocument(document);
+ rangeBottom = rangeBottom ?? -Infinity;
+ rangeTop = rangeTop ?? Infinity;
+ range[0] = parseFloat(range[0]) ?? -Infinity;
+ range[1] = parseFloat(range[1]) ?? Infinity;
+ let entityRange = [rangeBottom, rangeTop];
+ if (!isTile) {
+ if ((entityRange[0] >= range[0] && entityRange[0] <= range[1]) || (entityRange[1] >= range[0] && entityRange[1] <= range[1])) {
+ return true;
+ } else {
+ return false;
+ }
} else {
- return false;
+ if (entityRange[0] == range[1] + 1 && entityRange[1] == Infinity) {
+ return true;
+ } else {
+ if (entityRange[0] >= range[0] && entityRange[1] <= range[1]) {
+ return true;
+ } else {
+ return false;
+ }
+ }
}
- }
}
- }
-
- getObjUpdateData(range) {
- return {
- flags: {
- [`${CONFIG.Levels.MODULE_ID}`]: {
- rangeBottom: parseFloat(range[0]),
- rangeTop: parseFloat(range[1]),
- },
- },
- };
- }
- async elevationDialog(tool) {
- let content = `
+ getObjUpdateData(range) {
+ return {
+ flags: {
+ [`${CONFIG.Levels.MODULE_ID}`]: {
+ rangeBottom: parseFloat(range[0]),
+ rangeTop: parseFloat(range[1]),
+ },
+ },
+ };
+ }
+
+ async elevationDialog(tool) {
+ let content = `
`;
- let ignoreClose = false;
- let toolhtml = $("body").find(`li[data-tool="setTemplateElevation"]`);
- let dialog = new Dialog({
- title: game.i18n.localize("levels.dialog.elevation.title"),
- content: content,
- buttons: {
- confirm: {
- label: game.i18n.localize("levels.yesnodialog.yes"),
- callback: (html) => {
- CONFIG.Levels.UI.nextTemplateHeight = html.find(
- `input[name="templateElevation"]`
- )[0].valueAsNumber;
- CONFIG.Levels.UI.nextTemplateSpecial = html.find(
- `input[name="special"]`
- )[0].valueAsNumber;
- CONFIG.Levels.UI.templateElevation = true;
- ignoreClose = true;
- tool.active = true;
- if (toolhtml[0])
- $("body")
- .find(`li[data-tool="setTemplateElevation"]`)
- .addClass("active");
- },
- },
- close: {
- label: game.i18n.localize("levels.yesnodialog.no"),
- callback: () => {
- CONFIG.Levels.UI.nextTemplateHeight = undefined;
- CONFIG.Levels.UI.nextTemplateSpecial = undefined;
- CONFIG.Levels.UI.templateElevation = false;
- tool.active = false;
- if (toolhtml[0])
- $("body")
- .find(`li[data-tool="setTemplateElevation"]`)
- .removeClass("active");
- },
- },
- },
- default: "confirm",
- close: () => {
- if (ignoreClose == true) {
- ignoreClose = false;
- return;
- }
- CONFIG.Levels.nextTemplateHeight = undefined;
- CONFIG.Levels.nextTemplateSpecial = undefined;
- CONFIG.Levels.templateElevation = false;
- tool.active = false;
- if (toolhtml[0])
- $("body")
- .find(`li[data-tool="setTemplateElevation"]`)
- .removeClass("active");
- },
- });
- await dialog._render(true);
- }
+ let ignoreClose = false;
+ let toolhtml = $("body").find(`li[data-tool="setTemplateElevation"]`);
+ let dialog = new Dialog({
+ title: game.i18n.localize("levels.dialog.elevation.title"),
+ content: content,
+ buttons: {
+ confirm: {
+ label: game.i18n.localize("levels.yesnodialog.yes"),
+ callback: (html) => {
+ CONFIG.Levels.UI.nextTemplateHeight = html.find(`input[name="templateElevation"]`)[0].valueAsNumber;
+ CONFIG.Levels.UI.nextTemplateSpecial = html.find(`input[name="special"]`)[0].valueAsNumber;
+ CONFIG.Levels.UI.templateElevation = true;
+ ignoreClose = true;
+ tool.active = true;
+ if (toolhtml[0]) $("body").find(`li[data-tool="setTemplateElevation"]`).addClass("active");
+ },
+ },
+ close: {
+ label: game.i18n.localize("levels.yesnodialog.no"),
+ callback: () => {
+ CONFIG.Levels.UI.nextTemplateHeight = undefined;
+ CONFIG.Levels.UI.nextTemplateSpecial = undefined;
+ CONFIG.Levels.UI.templateElevation = false;
+ tool.active = false;
+ if (toolhtml[0]) $("body").find(`li[data-tool="setTemplateElevation"]`).removeClass("active");
+ },
+ },
+ },
+ default: "confirm",
+ close: () => {
+ if (ignoreClose == true) {
+ ignoreClose = false;
+ return;
+ }
+ CONFIG.Levels.nextTemplateHeight = undefined;
+ CONFIG.Levels.nextTemplateSpecial = undefined;
+ CONFIG.Levels.templateElevation = false;
+ tool.active = false;
+ if (toolhtml[0]) $("body").find(`li[data-tool="setTemplateElevation"]`).removeClass("active");
+ },
+ });
+ await dialog._render(true);
+ }
}
$(document).on("click", `li[data-control="levels"]`, (e) => {
- CONFIG.Levels.UI.render(true);
-})
+ CONFIG.Levels.UI.render(true);
+});
Hooks.on("renderSceneControls", (controls, b, c) => {
- if(game.user.isGM){
- $(".main-controls").append(`
+ if (game.user.isGM) {
+ $(".main-controls").append(`
- `)
- }
+ `);
+ }
});
Hooks.on("ready", () => {
- if (game.user.isGM) {
-
- Hooks.on("activateTilesLayer", ()=>{
- if(CONFIG.Levels.UI.rangeEnabled){
- Hooks.once("renderSceneControls", ()=>{
- CONFIG.Levels.UI.activateForeground();
- })
- }
- })
-
- Hooks.on("canvasInit", () => {
- CONFIG.Levels.UI.close(true);
- })
-
- Hooks.on("updateToken", (token,updates)=>{
- if("elevation" in updates)CONFIG.Levels.UI.updatePlayerList();
- })
-
- Hooks.on("createToken", (token,updates)=>{
- CONFIG.Levels.UI.updatePlayerList();
- })
-
- Hooks.on("deleteToken", (token,updates)=>{
- CONFIG.Levels.UI.updatePlayerList();
- })
-
- Hooks.on("controlToken", (token,controlled)=>{
- if(CONFIG.Levels.UI.rangeEnabled && !canvas.tokens.controlled.length){
- CONFIG.Levels.UI.computeLevelsVisibility();
- }else if(CONFIG.Levels.UI.rangeEnabled){
- CONFIG.Levels.handlers.RefreshHandler.refresh(canvas.tokens);
- }
- })
-
- Hooks.on("renderLevelsUI", (app, html) => {
-
- if(!app.positionSet){
- console.log((window.innerWidth - $("#sidebar").width() - $("#levelsUI").width()))
- app.setPosition({
- top: 2,
- left: (window.innerWidth - $("#sidebar").width() - $("#levelsUI").width()) - 10,
- width: $("#levelsUI").width(),
- height: Math.max(150, $("#levelsUI").height()) + 10,
+ if (game.user.isGM) {
+ Hooks.on("activateTilesLayer", () => {
+ if (CONFIG.Levels.UI.rangeEnabled) {
+ Hooks.once("renderSceneControls", () => {
+ CONFIG.Levels.UI.activateForeground();
+ });
+ }
});
- app.positionSet = true
- }
- })
-
- Hooks.on("preCreateTile", (tile, updates) => {
- if (CONFIG.Levels.UI.rangeEnabled == true) {
- tile.updateSource({
- overhead: true,
+
+ Hooks.on("canvasInit", () => {
+ CONFIG.Levels.UI.close(true);
});
- if(!game.Levels3DPreview?._active){
- tile.updateSource({
- flags: {
- "betterroofs": {
- brMode: CONFIG.Levels.UI.roofEnabled,
- },
- [`${CONFIG.Levels.MODULE_ID}`]: {
- rangeBottom: CONFIG.Levels.UI.roofEnabled
- ? parseFloat(CONFIG.Levels.UI.range[1])
- : parseFloat(CONFIG.Levels.UI.range[0]),
- rangeTop: CONFIG.Levels.UI.roofEnabled ? Infinity : parseFloat(CONFIG.Levels.UI.range[1]),
- allWallBlockSight: CONFIG.Levels.UI.roofEnabled
- }
- },
- roof: CONFIG.Levels.UI.roofEnabled,
- });
- }else{
- tile.updateSource({
- flags: {
- [`${CONFIG.Levels.MODULE_ID}`]: {
- rangeTop: CONFIG.Levels.UI.roofEnabled ? Infinity : CONFIG.Levels.UI.range[1],
- }
+
+ Hooks.on("updateToken", (token, updates) => {
+ if ("elevation" in updates) CONFIG.Levels.UI.updatePlayerList();
+ });
+
+ Hooks.on("createToken", (token, updates) => {
+ CONFIG.Levels.UI.updatePlayerList();
+ });
+
+ Hooks.on("deleteToken", (token, updates) => {
+ CONFIG.Levels.UI.updatePlayerList();
+ });
+
+ Hooks.on("controlToken", (token, controlled) => {
+ if (CONFIG.Levels.UI.rangeEnabled && !canvas.tokens.controlled.length) {
+ CONFIG.Levels.UI.computeLevelsVisibility();
+ } else if (CONFIG.Levels.UI.rangeEnabled) {
+ CONFIG.Levels.handlers.RefreshHandler.refresh(canvas.tokens);
}
- });
- }
- if(CONFIG.Levels.UI.placeOverhead){
+ });
- tile.updateSource({
- roof: false,
- flags: {
- [`${CONFIG.Levels.MODULE_ID}`]: {
- showIfAbove: true,
- noCollision: true,
- showAboveRange: parseFloat(CONFIG.Levels.UI.range[1]) - parseFloat(CONFIG.Levels.UI.range[0]),
- rangeBottom: parseFloat(CONFIG.Levels.UI.range[1]),
- rangeTop: parseFloat(CONFIG.Levels.UI.range[1]),
- }
+ Hooks.on("renderLevelsUI", (app, html) => {
+ if (!app.positionSet) {
+ console.log(window.innerWidth - $("#sidebar").width() - $("#levelsUI").width());
+ app.setPosition({
+ top: 2,
+ left: window.innerWidth - $("#sidebar").width() - $("#levelsUI").width() - 10,
+ width: $("#levelsUI").width(),
+ height: Math.max(150, $("#levelsUI").height()) + 10,
+ });
+ app.positionSet = true;
}
- });
- }
- }
- });
-
- Hooks.on("preCreateAmbientLight", (light, updates) => {
- if (CONFIG.Levels.UI.rangeEnabled == true && !game.Levels3DPreview?._active) {
- light.updateSource(CONFIG.Levels.UI.getObjUpdateData(CONFIG.Levels.UI.range));
- }
- });
-
- Hooks.on("preCreateAmbientSound", (sound, updates) => {
- if (CONFIG.Levels.UI.rangeEnabled == true) {
- sound.updateSource(CONFIG.Levels.UI.getObjUpdateData(CONFIG.Levels.UI.range));
- }
- });
-
- Hooks.on("preCreateNote", (note, updates) => {
- if (CONFIG.Levels.UI.rangeEnabled == true) {
- note.updateSource(CONFIG.Levels.UI.getObjUpdateData(CONFIG.Levels.UI.range));
- }
- });
-
- Hooks.on("preCreateDrawing", (drawing, updates) => {
- let sortedLevels = [...CONFIG.Levels.UI.definedLevels].sort((a, b) => {
- return parseFloat(b[0]) - parseFloat(a[0])
- })
- let aboverange = sortedLevels.find(l => CONFIG.Levels.UI.range[0] === l[0] && CONFIG.Levels.UI.range[1] === l[1])
- aboverange = sortedLevels.indexOf(aboverange) === 0 ? undefined : sortedLevels[sortedLevels.indexOf(aboverange) - 1]
-
- if (aboverange) {
- let newTop = aboverange[1];
- let newBot = aboverange[0];
- if (CONFIG.Levels.UI.rangeEnabled == true) {
- drawing.updateSource({
- hidden: CONFIG.Levels.UI.stairEnabled,
- text: CONFIG.Levels.UI.stairEnabled ? `Levels Stair ${CONFIG.Levels.UI.range[0]}-${newBot}` : "",
- flags: {
- levels: {
- drawingMode: CONFIG.Levels.UI.stairEnabled ? 2 : 0,
- rangeBottom: parseFloat(CONFIG.Levels.UI.range[0]),
- rangeTop: newBot - 1,
- },
- },
- });
- }
- } else {
- if (CONFIG.Levels.UI.rangeEnabled == true) {
- drawing.updateSource({
- hidden: CONFIG.Levels.UI.stairEnabled,
- text: CONFIG.Levels.UI.stairEnabled ? `Levels Stair ${CONFIG.Levels.UI.range[0]}-${CONFIG.Levels.UI.range[1] + 1}` : "",
- flags: {
- levels: {
- drawingMode: CONFIG.Levels.UI.stairEnabled ? 2 : 0,
- rangeBottom: parseFloat(CONFIG.Levels.UI.range[0]),
- rangeTop: parseFloat(CONFIG.Levels.UI.range[1]),
- },
- },
- });
- }
- }
- });
-
- Hooks.on("preCreateWall", (wall, updates) => {
- if (CONFIG.Levels.UI.rangeEnabled == true) {
- wall.updateSource({
- flags: {
- "wall-height": {
- bottom: parseFloat(CONFIG.Levels.UI.range[0]),
- top: parseFloat(CONFIG.Levels.UI.range[1]),
- },
- },
});
- }
- });
-
- Hooks.on("preCreateToken", (token, updates) => {
- if (CONFIG.Levels.UI.rangeEnabled == true) {
- if(updates) updates.elevation = parseFloat(CONFIG.Levels.UI.range[0]);
- token.updateSource({
- elevation: updates?.elevation ?? parseFloat(CONFIG.Levels.UI.range[0]),
+
+ Hooks.on("preCreateTile", (tile, updates) => {
+ if (CONFIG.Levels.UI.tokensOnly) return;
+ if (CONFIG.Levels.UI.rangeEnabled == true) {
+ tile.updateSource({
+ overhead: true,
+ });
+ if (!game.Levels3DPreview?._active) {
+ tile.updateSource({
+ flags: {
+ betterroofs: {
+ brMode: CONFIG.Levels.UI.roofEnabled,
+ },
+ [`${CONFIG.Levels.MODULE_ID}`]: {
+ rangeBottom: CONFIG.Levels.UI.roofEnabled ? parseFloat(CONFIG.Levels.UI.range[1]) : parseFloat(CONFIG.Levels.UI.range[0]),
+ rangeTop: CONFIG.Levels.UI.roofEnabled ? Infinity : parseFloat(CONFIG.Levels.UI.range[1]),
+ allWallBlockSight: CONFIG.Levels.UI.roofEnabled,
+ },
+ },
+ roof: CONFIG.Levels.UI.roofEnabled,
+ });
+ } else {
+ tile.updateSource({
+ flags: {
+ [`${CONFIG.Levels.MODULE_ID}`]: {
+ rangeTop: CONFIG.Levels.UI.roofEnabled ? Infinity : CONFIG.Levels.UI.range[1],
+ },
+ },
+ });
+ }
+ if (CONFIG.Levels.UI.placeOverhead) {
+ tile.updateSource({
+ roof: false,
+ flags: {
+ [`${CONFIG.Levels.MODULE_ID}`]: {
+ showIfAbove: true,
+ noCollision: true,
+ showAboveRange: parseFloat(CONFIG.Levels.UI.range[1]) - parseFloat(CONFIG.Levels.UI.range[0]),
+ rangeBottom: parseFloat(CONFIG.Levels.UI.range[1]),
+ rangeTop: parseFloat(CONFIG.Levels.UI.range[1]),
+ },
+ },
+ });
+ }
+ }
});
- }
- });
- }
+
+ Hooks.on("preCreateAmbientLight", (light, updates) => {
+ if (CONFIG.Levels.UI.tokensOnly) return;
+ if (CONFIG.Levels.UI.rangeEnabled == true && !game.Levels3DPreview?._active) {
+ light.updateSource(CONFIG.Levels.UI.getObjUpdateData(CONFIG.Levels.UI.range));
+ }
+ });
+
+ Hooks.on("preCreateAmbientSound", (sound, updates) => {
+ if (CONFIG.Levels.UI.tokensOnly) return;
+
+ if (CONFIG.Levels.UI.rangeEnabled == true) {
+ sound.updateSource(CONFIG.Levels.UI.getObjUpdateData(CONFIG.Levels.UI.range));
+ }
+ });
+
+ Hooks.on("preCreateNote", (note, updates) => {
+ if (CONFIG.Levels.UI.tokensOnly) return;
+ if (CONFIG.Levels.UI.rangeEnabled == true) {
+ note.updateSource(CONFIG.Levels.UI.getObjUpdateData(CONFIG.Levels.UI.range));
+ }
+ });
+
+ Hooks.on("preCreateDrawing", (drawing, updates) => {
+ if (CONFIG.Levels.UI.tokensOnly) return;
+ let sortedLevels = [...CONFIG.Levels.UI.definedLevels].sort((a, b) => {
+ return parseFloat(b[0]) - parseFloat(a[0]);
+ });
+ let aboverange = sortedLevels.find((l) => CONFIG.Levels.UI.range[0] === l[0] && CONFIG.Levels.UI.range[1] === l[1]);
+ aboverange = sortedLevels.indexOf(aboverange) === 0 ? undefined : sortedLevels[sortedLevels.indexOf(aboverange) - 1];
+
+ if (aboverange) {
+ let newTop = aboverange[1];
+ let newBot = aboverange[0];
+ if (CONFIG.Levels.UI.rangeEnabled == true) {
+ drawing.updateSource({
+ hidden: CONFIG.Levels.UI.stairEnabled,
+ text: CONFIG.Levels.UI.stairEnabled ? `Levels Stair ${CONFIG.Levels.UI.range[0]}-${newBot}` : "",
+ flags: {
+ levels: {
+ drawingMode: CONFIG.Levels.UI.stairEnabled ? 2 : 0,
+ rangeBottom: parseFloat(CONFIG.Levels.UI.range[0]),
+ rangeTop: newBot - 1,
+ },
+ },
+ });
+ }
+ } else {
+ if (CONFIG.Levels.UI.rangeEnabled == true) {
+ drawing.updateSource({
+ hidden: CONFIG.Levels.UI.stairEnabled,
+ text: CONFIG.Levels.UI.stairEnabled ? `Levels Stair ${CONFIG.Levels.UI.range[0]}-${CONFIG.Levels.UI.range[1] + 1}` : "",
+ flags: {
+ levels: {
+ drawingMode: CONFIG.Levels.UI.stairEnabled ? 2 : 0,
+ rangeBottom: parseFloat(CONFIG.Levels.UI.range[0]),
+ rangeTop: parseFloat(CONFIG.Levels.UI.range[1]),
+ },
+ },
+ });
+ }
+ }
+ });
+
+ Hooks.on("preCreateWall", (wall, updates) => {
+ if (CONFIG.Levels.UI.tokensOnly) return;
+
+ if (CONFIG.Levels.UI.rangeEnabled == true) {
+ wall.updateSource({
+ flags: {
+ "wall-height": {
+ bottom: parseFloat(CONFIG.Levels.UI.range[0]),
+ top: parseFloat(CONFIG.Levels.UI.range[1]),
+ },
+ },
+ });
+ }
+ });
+
+ Hooks.on("preCreateToken", (token, updates) => {
+ if (CONFIG.Levels.UI.rangeEnabled == true) {
+ if (updates) updates.elevation = parseFloat(CONFIG.Levels.UI.range[0]);
+ token.updateSource({
+ elevation: updates?.elevation ?? parseFloat(CONFIG.Levels.UI.range[0]),
+ });
+ }
+ });
+ }
});
Hooks.on("getSceneControlButtons", (controls, b, c) => {
- let templateTool = {
- name: "setTemplateElevation",
- title: game.i18n.localize("levels.controls.setTemplateElevation.name"),
- icon: "fas fa-sort",
- toggle: true,
- active: CONFIG.Levels?.UI.templateElevation || false,
- onClick: (toggle) => {
- CONFIG.Levels.UI.templateElevation = toggle;
- if (toggle) CONFIG.Levels.UI.elevationDialog(templateTool);
- else CONFIG.Levels.UI.nextTemplateHeight = undefined;
- },
- };
- CONFIG.Levels.UI._levelsTemplateTool = templateTool;
- controls.find((c) => c.name == "token").tools.push(templateTool);
+ let templateTool = {
+ name: "setTemplateElevation",
+ title: game.i18n.localize("levels.controls.setTemplateElevation.name"),
+ icon: "fas fa-sort",
+ toggle: true,
+ active: CONFIG.Levels?.UI.templateElevation || false,
+ onClick: (toggle) => {
+ CONFIG.Levels.UI.templateElevation = toggle;
+ if (toggle) CONFIG.Levels.UI.elevationDialog(templateTool);
+ else CONFIG.Levels.UI.nextTemplateHeight = undefined;
+ },
+ };
+ CONFIG.Levels.UI._levelsTemplateTool = templateTool;
+ controls.find((c) => c.name == "token").tools.push(templateTool);
});
Hooks.once("canvasReady", () => {
- console.log(
- `%cLEVELS\n%cWelcome to the 3rd Dimension`,
- "font-weight: bold;text-shadow: 10px 10px 0px rgba(0,0,0,0.8), 20px 20px 0px rgba(0,0,0,0.6), 30px 30px 0px rgba(0,0,0,0.4);font-size:100px;background: #444; color: #d43f3f; padding: 2px 28px 0 2px; display: inline-block;",
- "font-weight: bold;text-shadow: 2px 2px 0px rgba(0,0,0,0.8), 4px 4px 0px rgba(0,0,0,0.6), 6px 6px 0px rgba(0,0,0,0.4);font-size:20px;background: #444; color: #d43f3f; padding: 10px 27px; display: inline-block; margin-left: -30px"
- );
-});
\ No newline at end of file
+ console.log(`%cLEVELS\n%cWelcome to the 3rd Dimension`, "font-weight: bold;text-shadow: 10px 10px 0px rgba(0,0,0,0.8), 20px 20px 0px rgba(0,0,0,0.6), 30px 30px 0px rgba(0,0,0,0.4);font-size:100px;background: #444; color: #d43f3f; padding: 2px 28px 0 2px; display: inline-block;", "font-weight: bold;text-shadow: 2px 2px 0px rgba(0,0,0,0.8), 4px 4px 0px rgba(0,0,0,0.6), 6px 6px 0px rgba(0,0,0,0.4);font-size:20px;background: #444; color: #d43f3f; padding: 10px 27px; display: inline-block; margin-left: -30px");
+});
diff --git a/templates/layerTool.hbs b/templates/layerTool.hbs
index e0a4571..cb0c67d 100644
--- a/templates/layerTool.hbs
+++ b/templates/layerTool.hbs
@@ -7,6 +7,7 @@
+