16 Commits

Author SHA1 Message Date
Jakub
7f2a32fbbd Translated using Weblate (Polish)
Currently translated at 100.0% (17 of 17 strings)

Translation: Smart Doors/main
Translate-URL: https://weblate.foundryvtt-hub.com/projects/smart-doors/main/pl/
2023-05-06 20:42:46 +00:00
Jakub
24f8fc12b2 Added translation using Weblate (Polish) 2023-05-05 19:46:11 +00:00
5cec10941a Release v1.4.1 2022-10-24 09:36:02 +02:00
Foundry Hub
77f1048518 Translations update from Foundry Hub - Weblate (#30) 2022-10-24 09:31:27 +02:00
02ea8aeb93 Release v1.4.0 2022-10-15 22:35:42 +02:00
59e2d0884f Fix a typo in the manifest 2022-10-15 22:32:29 +02:00
vincent
62c76e3d23 Translated using Weblate (French)
Currently translated at 100.0% (17 of 17 strings)

Translation: Smart Doors/main
Translate-URL: https://weblate.foundryvtt-hub.com/projects/smart-doors/main/fr/
2022-10-15 22:32:01 +02:00
0fd9a7b71f Translated using Weblate (German)
Currently translated at 100.0% (17 of 17 strings)

Translation: Smart Doors/main
Translate-URL: https://weblate.foundryvtt-hub.com/projects/smart-doors/main/de/
2022-10-15 22:32:01 +02:00
bc46a05f3c Translated using Weblate (English)
Currently translated at 100.0% (17 of 17 strings)

Translation: Smart Doors/main
Translate-URL: https://weblate.foundryvtt-hub.com/projects/smart-doors/main/en/
2022-10-15 22:32:01 +02:00
e53a1b6a21 Update for Foundry v10 2022-10-15 22:29:25 +02:00
2ea4eb04cb Reformat with prettier 2022-10-15 21:48:14 +02:00
Alexander Minges
04d85d818b Fix typos in German translation (#24) 2022-05-09 11:04:19 +02:00
a0cdaff5db Release v1.3.3 2022-02-14 15:35:29 +01:00
30272cfbf4 Remove extra curly brace in french translation (fixes #21) 2022-02-14 15:08:18 +01:00
46581362fb Implement delayed reload to esnure all settings are applied 2022-02-12 18:35:23 +01:00
993cc2b658 Fix typo in readme 2022-02-12 18:34:55 +01:00
18 changed files with 482 additions and 289 deletions

4
.prettierrc Normal file
View File

@@ -0,0 +1,4 @@
printWidth: 100
trailingComma: "all"
bracketSpacing: false
arrowParens: "avoid"

View File

@@ -1,3 +1,24 @@
## 1.4.1
### Translation
- Added portugese (Brazil) translation (thanks eunaumtenhoid!)
## 1.4.0
### Compatibility
- Smart Doors is now compatible with Foundry v10
### Translation
- Updated the english text for several UI items
- Updated the german translation (thanks Athemis!)
- Updated the french translation (thanks rectulo!)
## 1.3.3
### Bugfixes
- Fixed a bug that could cause some settings to not apply if multiple settings were changed at once
- Fixed a bug that caused the french translation to not work
## 1.3.2 ## 1.3.2
### Bugfixes ### Bugfixes
- The message sent to chat when triggering a locke door alert can now be translated - The message sent to chat when triggering a locke door alert can now be translated

View File

@@ -24,7 +24,7 @@ Keep everyone informed who tried to open which door. Whenever a player tries to
If the GM tries to open a locked door the sound will only played for him and no chat message will be sent. If the GM tries to open a locked door the sound will only played for him and no chat message will be sent.
### Tint Secret Doors ### Tint Secret Doors
This tints secret doors in a gay shade to make them easier to discern from regular doors when being zoomed further out. This tints secret doors in a gray shade to make them easier to discern from regular doors when being zoomed further out.
### Synchronized Doors ### Synchronized Doors

View File

@@ -1,41 +1,41 @@
{ {
"smart-doors": { "smart-doors": {
"keybindings": { "keybindings": {
"toggleSecretDoor": { "toggleSecretDoor": {
"name": "Geheimtüren umschalten", "name": "Geheimtüren umschalten",
"hint": "Solange diese Taste gedrückt ist, werden Türen beim Klicken zwischen normaler Tür und Geheimtür umgeschalten." "hint": "Solange diese Taste gedrückt ist, werden Türen beim Klicken zwischen normaler Tür und Geheimtür umgeschaltet."
} }
}, },
"settings": { "settings": {
"doorControlSizeFactor": { "doorControlSizeFactor": {
"name": "Sklaierungsfaktor des Türsymbols", "name": "Skalierungsfaktor des Türsymbols",
"hint": "Legt fest um welchen faktor die Größe der Türsymbole hochskaliert werden sollen" "hint": "Legt fest um welchen Faktor die Größe der Türsymbole hochskaliert werden sollen."
}, },
"highlightSecretDoors": { "highlightSecretDoors": {
"name": "Geheimtüren einfärben", "name": "Geheimtüren einfärben",
"hint": "Geheimtüren werden beim Spielleiter in einer anderen Farbe dargestellt, um sie einfacher von anderen Türen unterscheiden zu können." "hint": "Geheimtüren werden beim Spielleiter in einer anderen Farbe dargestellt, um sie einfacher von anderen Türen unterscheiden zu können."
}, },
"lockedDoorAlert": { "lockedDoorAlert": {
"name": "Alarm bei verschlossenen Türen", "name": "Alarm bei verschlossenen Türen",
"hint": "Wenn ein Spieler versucht eine verschlossene Tür zu öffnen wird eine Nachricht im Chat angezeigt" "hint": "Wenn ein Spieler versucht eine verschlossene Tür zu öffnen, wird eine Nachricht im Chat angezeigt."
}, },
"synchronizedDoors": { "synchronizedDoors": {
"name": "Synchronisierte Türen", "name": "Synchronisierte Türen",
"hint": "Erlaubt es den Zustand mehrerer Türen zu synchronisieren" "hint": "Erlaubt es den Zustand mehrerer Türen zu synchronisieren."
} }
}, },
"ui": { "ui": {
"lockedDoorAlert": "Hat versucht eine verschlossene Tür zu öffnen", "lockedDoorAlert": "Hat versucht eine verschlossene Tür zu öffnen",
"messages": { "messages": {
"migrating": "Update Smart Doors zur Version {version}. Bitte schließe die Anwendung nicht.", "migrating": "Aktualisiere Smart Doors zur Version {version}. Bitte schließe die Anwendung nicht.",
"migrationDone": "Smart Doors wurde erfolgreich auf die Version {version} geupdated.", "migrationDone": "Smart Doors wurde erfolgreich auf die Version {version} aktualisiert.",
"unknownVersion": "Das Update von Smart doors ist mit folgendem Fehler fehlgeschlagen: Unbekannte Version {version}. Bite melde diesen Fehler im Bugtracker von Smart Doors. Um Datenverlust zu vermeiden, dekativiere dieses Modul bis dieser Fehler behoben ist." "unknownVersion": "Die Aktualisierung von Smart Doors ist mit folgendem Fehler fehlgeschlagen: unbekannte Version {version}. Bitte melde diesen Fehler im Bugtracker von Smart Doors. Um Datenverlust zu vermeiden, deaktiviere dieses Modul, bis dieser Fehler behoben ist."
}, },
"synchronizedDoors": { "synchronizedDoors": {
"description": "Zustandsänderungen von Türen in der gleichen Synchronisationsgruppe werden Szenenübergreifend synchronisiert. Lasse dieses Feld leer, wenn du diese Tür nicht Synchornisieren möchtest.", "description": "Zustandsänderungen von Türen in der gleichen Synchronisationsgruppe werden szenenübergreifend synchronisiert. Lasse dieses Feld leer, wenn du diese Tür nicht synchronisieren möchtest.",
"groupName": "Synchronisationsgruppe", "groupName": "Synchronisationsgruppe",
"synchronizeSecretStatus": "Geheimtürstatus synchronisieren" "synchronizeSecretStatus": "Geheimtürstatus synchronisieren"
} }
} }
} }
} }

View File

@@ -1,27 +1,27 @@
{ {
"smart-doors": { "smart-doors": {
"keybindings": { "keybindings": {
"toggleSecretDoor": { "toggleSecretDoor": {
"name": "Toggle Secret Door", "name": "Toggle Secret Door",
"hint": "While this key is being pressed, clicking on doors will cause the to toggle between normal and secret door" "hint": "While this key is being pressed, clicking on doors will cause the to toggle between normal and secret door."
} }
}, },
"settings": { "settings": {
"doorControlSizeFactor": { "doorControlSizeFactor": {
"name": "Door Control Size Factor", "name": "Door Control Size Factor",
"hint": "Defines by which factor the size of the door control icons should be scaled up" "hint": "Defines by which factor the size of the door control icons should be scaled up."
}, },
"highlightSecretDoors": { "highlightSecretDoors": {
"name": "Tint Secret Doors", "name": "Tint Secret Doors",
"hint": "Shade secret doors in a different color on the gm screen to differentiate them from normal doors" "hint": "Shade secret doors in a different color on the GM screen to differentiate them from normal doors."
}, },
"lockedDoorAlert": { "lockedDoorAlert": {
"name": "Locked Door Alert", "name": "Locked Door Alert",
"hint": "Send a message in chat when a player tried to open a locked door" "hint": "Send a message in chat when a player tried to open a locked door."
}, },
"synchronizedDoors": { "synchronizedDoors": {
"name": "Synchronized Doors", "name": "Synchronized Doors",
"hint": "Synchronize the state of configured doors" "hint": "Synchronize the state of multiple doors."
} }
}, },
"ui": { "ui": {
@@ -29,7 +29,7 @@
"messages": { "messages": {
"migrating": "Migrating Smart Doors to version {version}. Please don't close the application.", "migrating": "Migrating Smart Doors to version {version}. Please don't close the application.",
"migrationDone": "Smart Doors successfully migrated to version {version}.", "migrationDone": "Smart Doors successfully migrated to version {version}.",
"unknownVersion": "Smart Doors migration failed with the error: Unkown Version {version}. Please report this to the Smart Doors issue tracker. To prevent possible data loss don't use this plugin until this error is fixed." "unknownVersion": "Smart Doors migration failed with the error: Unknown Version {version}. Please report this to the Smart Doors issue tracker. To prevent possible data loss don't use this plugin until this error is fixed."
}, },
"synchronizedDoors": { "synchronizedDoors": {
"description": "State changes of doors in the same synchronization group will be synchronized across scenes. Leave blank to disable synchronization for this door.", "description": "State changes of doors in the same synchronization group will be synchronized across scenes. Leave blank to disable synchronization for this door.",

View File

@@ -3,19 +3,39 @@
"settings": { "settings": {
"doorControlSizeFactor": { "doorControlSizeFactor": {
"name": "Facteur de taille de commande de porte", "name": "Facteur de taille de commande de porte",
"hint": "Définit par quel facteur la taille des icônes de contrôle de porte doit être agrandie" "hint": "Définit par quel facteur la taille des icônes de contrôle de porte doit être mise à l'échelle."
}, },
"highlightSecretDoors": { "highlightSecretDoors": {
"name": "Teinte des portes secrètes", "name": "Teinte des portes secrètes",
"indice": "Ombragez les portes secrètes d'une couleur différente sur l'écran gm pour les différencier des portes normales" "indice": "Ombragez les portes secrètes d'une couleur différente sur l'écran gm pour les différencier des portes normales",
"hint": "Ombre les portes secrètes en une couleur différent sur l'écran du MJ pour les différencier des portes normales."
}, },
"lockedDoorAlert": { "lockedDoorAlert": {
"name": "Alerte de porte verrouillée", "name": "Alerte de porte verrouillée",
"hint": "Envoyer un message dans le chat lorsqu'un joueur essaie d'ouvrir une porte verrouillée" "hint": "Envoyer un message dans la conversation lorsqu'un joueur essaie d'ouvrir une porte verrouillée."
}, },
"synchronizedDoors": { "synchronizedDoors": {
"name": "Portes synchronisées", "name": "Portes synchronisées",
"hint": "Synchroniser l'état des portes configurées" "hint": "Synchroniser l'état de plusieurs portes."
}
},
"keybindings": {
"toggleSecretDoor": {
"name": "Activer porte secrète",
"hint": "Lorsque cette clé est maintenue, cliquer sur les portes permettra de passer d'une porte normale à une porte secrète."
}
},
"ui": {
"synchronizedDoors": {
"description": "Les changements d'état des portes dans le même groupe de synchronisation seront synchronisés à travers les scènes. Laisser vierge pour désactiver la synchronisation pour cette porte.",
"groupName": "Groupe de synchronisation",
"synchronizeSecretStatus": "Synchroniser le statut 'secret'"
},
"lockedDoorAlert": "vient d'essayer d'ouvrir une porte verrouillée",
"messages": {
"migrating": "Migre Smart doors à la version {version}. Ne pas fermer l'application.",
"migrationDone": "Smart doors a migré avec succès à la version {version}.",
"unknownVersion": "La migration de Smart doors est un échec avec l'erreur : version inconnue {version}. SVP, signalez cela dans le traqueur de problème de Smart doors. Pour prévenir de potentielles pertes de donnés, n'utilisez plus le plugin jusqu'à ce que cette erreur soit réparée."
} }
} }
}, },
@@ -32,4 +52,3 @@
} }
} }
} }
}

41
lang/pl.json Normal file
View File

@@ -0,0 +1,41 @@
{
"smart-doors": {
"keybindings": {
"toggleSecretDoor": {
"name": "Przełącznik sekretnych drzwi",
"hint": "Przytrzymując klawisz i klikając na drzwiach przełączasz typ między normalnymi i sekretnymi drzwiami."
}
},
"settings": {
"doorControlSizeFactor": {
"name": "Współczynnik wielkości drzwi",
"hint": "Określa, o jaki współczynnik powinien być skalowany rozmiar ikon sterowania drzwiami."
},
"highlightSecretDoors": {
"name": "Barwienie sekretnych drzwi",
"hint": "Pomaluj sekretne drzwi na inny kolor na ekranie GM, aby odróżnić je od zwykłych drzwi."
},
"lockedDoorAlert": {
"name": "Alarm o zablokowanych drzwiach",
"hint": "Wysyła wiadomość na czacie, gdy gracz próbował otworzyć zablokowane drzwi."
},
"synchronizedDoors": {
"name": "Drzwi zsynchronizowane",
"hint": "Synchronizacja stanu wielu drzwi."
}
},
"ui": {
"lockedDoorAlert": "Próbowałem otworzyć zamknięte drzwi",
"messages": {
"migrationDone": "Smart Doors pomyślnie zmigrował do wersji {version}.",
"migrating": "Migracja Smart Doors do wersji {wersja}. Proszę nie zamykać aplikacji.",
"unknownVersion": "Migracja Smart Doors nie powiodła się z błędem: Unknown Version {version}. Proszę zgłosić to do trackera problemów Smart Doors. Aby zapobiec możliwej utracie danych, nie używaj tej wtyczki, dopóki ten błąd nie zostanie naprawiony."
},
"synchronizedDoors": {
"description": "Zmiany stanu drzwi w tej samej grupie synchronizacyjnej będą synchronizowane na wszystkich scenach. Pozostawić puste, aby wyłączyć synchronizację dla tych drzwi.",
"groupName": "Grupa synchronizacji",
"synchronizeSecretStatus": "Synchronizacja sekretnego statusu"
}
}
}
}

41
lang/pt-BR.json Normal file
View File

@@ -0,0 +1,41 @@
{
"smart-doors": {
"keybindings": {
"toggleSecretDoor": {
"name": "Alternar porta secreta",
"hint": "Enquanto esta tecla estiver sendo pressionada, clicar nas portas fará com que ela alterne entre a porta normal e a secreta."
}
},
"settings": {
"doorControlSizeFactor": {
"name": "Fator de tamanho de controle de porta",
"hint": "Define por qual fator o tamanho dos ícones de controle de porta deve ser ampliado."
},
"highlightSecretDoors": {
"name": "Tinta portas secretas",
"hint": "Sombreie as portas secretas com uma cor diferente na tela do GM para diferenciá-las das portas normais."
},
"lockedDoorAlert": {
"name": "Alerta de porta trancada",
"hint": "Envie uma mensagem no chat quando um jogador tentar abrir uma porta trancada."
},
"synchronizedDoors": {
"name": "Portas sincronizadas",
"hint": "Sincronize o estado de várias portas."
}
},
"ui": {
"lockedDoorAlert": "Apenas tentei abrir uma porta trancada",
"messages": {
"migrating": "Migrando Smart Doors para a versão {version}. Por favor, não feche o aplicativo.",
"migrationDone": "O Smart Doors migrou com sucesso para a versão {version}.",
"unknownVersion": "A migração do Smart Doors falhou com o erro: Unknown Version {version}. Informe isso ao rastreador de problemas do Smart Doors. Para evitar uma possível perda de dados, não use este plugin até que este erro seja corrigido."
},
"synchronizedDoors": {
"description": "As mudanças de estado das portas no mesmo grupo de sincronização serão sincronizadas nas cenas. Deixe em branco para desabilitar a sincronização para esta porta.",
"groupName": "Grupo de Sincronização",
"synchronizeSecretStatus": "Sincronizar status secreto"
}
}
}
}

View File

@@ -1,10 +1,12 @@
{ {
"name": "smart-doors", "id": "smart-doors",
"title": "Smart Doors", "title": "Smart Doors",
"description": "Makes doors smarter. Allows doors to synchronize across multiple scenes and sends chat messages when players try to open locked doors.", "description": "Makes doors smarter. Allows doors to synchronize across multiple scenes and sends chat messages when players try to open locked doors.",
"version": "1.3.2", "version": "1.4.1",
"minimumCoreVersion" : "9.238", "compatibility": {
"compatibleCoreVersion" : "9", "minimum": 10,
"verified": 10
},
"authors": [ "authors": [
{ {
"name": "Manuel Vögele", "name": "Manuel Vögele",
@@ -36,13 +38,23 @@
"lang": "ja", "lang": "ja",
"name": "日本語", "name": "日本語",
"path": "lang/ja.json" "path": "lang/ja.json"
},
{
"lang": "pt-BR",
"name": "Português (Brasil)",
"path": "lang/pt-BR.json"
},
{
"lang": "pl",
"name": "polski",
"path": "lang/pl.json"
} }
], ],
"url": "https://github.com/manuelVo/foundryvtt-smart-doors", "url": "https://github.com/manuelVo/foundryvtt-smart-doors",
"manifest": "https://raw.githubusercontent.com/manuelVo/foundryvtt-smart-doors/master/module.json", "manifest": "https://raw.githubusercontent.com/manuelVo/foundryvtt-smart-doors/master/module.json",
"download": "https://github.com/manuelVo/foundryvtt-smart-doors/archive/v1.3.2.zip", "download": "https://github.com/manuelVo/foundryvtt-smart-doors/archive/v1.4.1.zip",
"readme": "https://github.com/manuelVo/foundryvtt-smart-doors/blob/master/README.md", "readme": "https://github.com/manuelVo/foundryvtt-smart-doors/blob/master/README.md",
"changelog": "https://github.com/manuelVo/foundryvtt-smart-doors/blob/master/CHANGELOG.md", "changelog": "https://github.com/manuelVo/foundryvtt-smart-doors/blob/master/CHANGELOG.md",
"bugs": "https://github.com/manuelVo/foundryvtt-smart-doors/issues", "bugs": "https://github.com/manuelVo/foundryvtt-smart-doors/issues",
"allowBugReporter": true "allowBugReporter": true
} }

View File

@@ -1,37 +1,66 @@
import { libWrapper } from "../../lib/libwrapper_shim.js" import {libWrapper} from "../../lib/libwrapper_shim.js";
import {settingsKey} from "../settings.js" import {settingsKey} from "../settings.js";
// Adjust the repositioning formula for the door controls // Adjust the repositioning formula for the door controls
export function hookDoorControlReposition() { export function hookDoorControlReposition() {
libWrapper.register("smart-doors", "DoorControl.prototype.reposition", function () { libWrapper.register(
let gridSize = this.wall.scene.data.grid "smart-doors",
gridSize *= game.settings.get(settingsKey, "doorControlSizeFactor") "DoorControl.prototype.reposition",
const pos = this.wall.midpoint.map(p => p - gridSize * 0.2) function () {
this.position.set(...pos) let gridSize = this.wall.scene.grid.size;
}, "OVERRIDE"); gridSize *= game.settings.get(settingsKey, "doorControlSizeFactor");
const pos = this.wall.midpoint.map(p => p - gridSize * 0.2);
this.position.set(...pos);
},
"OVERRIDE",
);
} }
// Set the size of all door controls in relation to the grid size so it'll have a constant percieved size // Set the size of all door controls in relation to the grid size so it'll have a constant percieved size
export function onCanvasReady(currentCanvas) { export function onCanvasReady(currentCanvas) {
const doors = currentCanvas.controls.doors.children const doors = currentCanvas.controls.doors.children;
doors.forEach(control => fixDoorControlSize(control)) doors.forEach(control => fixDoorControlSize(control));
} }
// Set the size of the door control in relation to the grid size so it'll have a constant percieved size // Set the size of the door control in relation to the grid size so it'll have a constant percieved size
export function onDoorControlPostDraw() { export function onDoorControlPostDraw() {
// If the canvas isn't ready we'll do this after the "canvasReady" event is fired instead // If the canvas isn't ready we'll do this after the "canvasReady" event is fired instead
if (!canvas.ready) if (!canvas.ready) return;
return
fixDoorControlSize(this) fixDoorControlSize(this);
} }
// Resizes the door control according to the grid size // Resizes the door control according to the grid size
function fixDoorControlSize(control) { function fixDoorControlSize(control) {
let gridSize = control.wall.scene.data.grid let gridSize = control.wall.scene.grid.size;
gridSize *= game.settings.get(settingsKey, "doorControlSizeFactor") gridSize *= game.settings.get(settingsKey, "doorControlSizeFactor");
control.icon.width = control.icon.height = gridSize * 0.4 control.icon.width = control.icon.height = gridSize * 0.4;
control.hitArea = new PIXI.Rectangle(gridSize * -0.02, gridSize * -0.02, gridSize * 0.44, gridSize * 0.44); control.hitArea = new PIXI.Rectangle(
control.border.clear().lineStyle(1, 0xFF5500, 0.8).drawRoundedRect(gridSize * -0.02, gridSize * -0.02, gridSize * 0.44, gridSize * 0.44, gridSize * 0.05).endFill(); gridSize * -0.02,
control.bg.clear().beginFill(0x000000, 1.0).drawRoundedRect(gridSize * -0.02, gridSize * -0.02, gridSize * 0.44, gridSize * 0.44, gridSize * 0.05).endFill(); gridSize * -0.02,
gridSize * 0.44,
gridSize * 0.44,
);
control.border
.clear()
.lineStyle(1, 0xff5500, 0.8)
.drawRoundedRect(
gridSize * -0.02,
gridSize * -0.02,
gridSize * 0.44,
gridSize * 0.44,
gridSize * 0.05,
)
.endFill();
control.bg
.clear()
.beginFill(0x000000, 1.0)
.drawRoundedRect(
gridSize * -0.02,
gridSize * -0.02,
gridSize * 0.44,
gridSize * 0.44,
gridSize * 0.05,
)
.endFill();
} }

View File

@@ -1,34 +1,35 @@
import {settingsKey} from "../settings.js" import {settingsKey} from "../settings.js";
const SECRET_DOOR_TINT = 0x888888 const SECRET_DOOR_TINT = 0x888888;
// Tint all secret doors dark grey // Tint all secret doors dark grey
export function onCanvasReady(currentCanvas) { export function onCanvasReady(currentCanvas) {
if (game.settings.get(settingsKey, "highlightSecretDoors")) { if (game.settings.get(settingsKey, "highlightSecretDoors")) {
const types = CONST.WALL_DOOR_TYPES const types = CONST.WALL_DOOR_TYPES;
const secretDoors = canvas.controls.doors.children.filter(control => control.wall.data.door == types.SECRET) const secretDoors = canvas.controls.doors.children.filter(
secretDoors.forEach(control => control.icon.tint = SECRET_DOOR_TINT) control => control.wall.door == types.SECRET,
);
secretDoors.forEach(control => (control.icon.tint = SECRET_DOOR_TINT));
} }
} }
// If door type has been changed, tint the door accordingly // If door type has been changed, tint the door accordingly
export function onUpdateWall(scene, wall, update) { export function onUpdateWall(wall, update, options) {
if (!game.settings.get(settingsKey, "highlightSecretDoors")) if (!game.settings.get(settingsKey, "highlightSecretDoors")) return;
return const types = CONST.WALL_DOOR_TYPES;
const types = CONST.WALL_DOOR_TYPES if (wall.door === types.NONE) return;
if (wall.door === types.NONE)
return
// Find the door control corresponding to the changed door // Find the door control corresponding to the changed door
const changedDoor = canvas.controls.doors.children.find(control => control.wall.data._id === wall._id); const changedDoor = canvas.controls.doors.children.find(control => control.wall.id === wall.id);
// If the changed door doesn't have a control it's not on this scene - ignore it // If the changed door doesn't have a control it's not on this scene - ignore it
if (!changedDoor) if (!changedDoor) return;
return
// The wall object we got passed might be from another scene so we replace it with the door from the current scene // The wall object we got passed might be from another scene so we replace it with the door from the current scene
wall = changedDoor.wall.data wall = changedDoor.wall;
if (wall.door === types.DOOR) if (wall.document.door === types.DOOR) changedDoor.icon.tint = 0xffffff;
changedDoor.icon.tint = 0xFFFFFF else if (wall.document.door === types.SECRET) changedDoor.icon.tint = SECRET_DOOR_TINT;
else if (wall.door === types.SECRET)
changedDoor.icon.tint = SECRET_DOOR_TINT
else else
console.warn("Smart Doors | Encountered unknown door type " + wall.door + " while highlighting secret doors.") console.warn(
"Smart Doors | Encountered unknown door type " +
wall.door +
" while highlighting secret doors.",
);
} }

View File

@@ -1,26 +1,27 @@
import {settingsKey} from "../settings.js" import {settingsKey} from "../settings.js";
// Tint the source door red when a locked alert is hovered // Tint the source door red when a locked alert is hovered
export function onRenderChatMessage(message, html, data) { export function onRenderChatMessage(message, html, data) {
// Tint the door that generated this message // Tint the door that generated this message
const source = message.data.flags.smartdoors?.source const source = message.flags.smartdoors?.source;
if (!source) if (!source) return;
return
// Tint on mouse enter // Tint on mouse enter
const mouseEnter = function () { const mouseEnter = function () {
const sourceDoor = canvas.controls.doors.children.find(door => door.wall.id === source.wall && door.wall.scene.id === source.scene); const sourceDoor = canvas.controls.doors.children.find(
if (sourceDoor) door => door.wall.id === source.wall && door.wall.scene.id === source.scene,
sourceDoor.icon.tint = 0xff0000; );
} if (sourceDoor) sourceDoor.icon.tint = 0xff0000;
};
html.on("mouseenter", mouseEnter); html.on("mouseenter", mouseEnter);
// Remove tint on mouse leave // Remove tint on mouse leave
const mouseLeave = function () { const mouseLeave = function () {
const sourceDoor = canvas.controls.doors.children.find(door => door.wall.id === source.wall && door.wall.scene.id === source.scene); const sourceDoor = canvas.controls.doors.children.find(
if (sourceDoor) door => door.wall.id === source.wall && door.wall.scene.id === source.scene,
sourceDoor.icon.tint = 0xffffff; );
} if (sourceDoor) sourceDoor.icon.tint = 0xffffff;
};
html.on("mouseleave", mouseLeave); html.on("mouseleave", mouseLeave);
// Localize the message // Localize the message
@@ -30,28 +31,24 @@ export function onRenderChatMessage(message, html, data) {
// Creates a chat message stating that a player tried to open a locked door // Creates a chat message stating that a player tried to open a locked door
export function onDoorLeftClick() { export function onDoorLeftClick() {
// Check if this feature is enabled // Check if this feature is enabled
if (!game.settings.get(settingsKey, "lockedDoorAlert")) if (!game.settings.get(settingsKey, "lockedDoorAlert")) return false;
return false
const state = this.wall.data.ds const state = this.wall.document.ds;
const states = CONST.WALL_DOOR_STATES const states = CONST.WALL_DOOR_STATES;
// Only create messages when the door is locked. // Only create messages when the door is locked.
if (state !== states.LOCKED) if (state !== states.LOCKED) return false;
return false
// Generate no message if the gm attempts to open the door // Generate no message if the gm attempts to open the door
if (game.user.isGM) if (game.user.isGM) return false;
return false
// Create and send the chat message // Create and send the chat message
const message = {} const message = {};
message.user = game.user.id; message.user = game.user.id;
if (game.user.character) if (game.user.character) message.speaker = {actor: game.user.character};
message.speaker = {actor: game.user.character}
message.content = game.i18n.localize("smart-doors.ui.lockedDoorAlert"); message.content = game.i18n.localize("smart-doors.ui.lockedDoorAlert");
message.sound = CONFIG.sounds.lock message.sound = CONFIG.sounds.lock;
message.flags = {smartdoors: {source: {wall: this.wall.data._id, scene: this.wall.scene.id}}} message.flags = {smartdoors: {source: {wall: this.wall.id, scene: this.wall.scene.id}}};
ChatMessage.create(message) ChatMessage.create(message);
return true return true;
} }

View File

@@ -1,31 +1,35 @@
import {settingsKey} from "../settings.js" import {settingsKey} from "../settings.js";
import * as Util from "../util.js" import * as Util from "../util.js";
// Inject settings for synchronized doors // Inject settings for synchronized doors
export function onRederWallConfig(wallConfig, html, data) { export function onRederWallConfig(wallConfig, html, data) {
if (game.settings.get(settingsKey, "synchronizedDoors") && data.isDoor) { if (game.settings.get(settingsKey, "synchronizedDoors") && data.data.door) {
// Inject settings // Inject settings
const synchronizedSettings = ` const synchronizedSettings = `
<p class="notes">${game.i18n.localize("smart-doors.ui.synchronizedDoors.description")}</p> <p class="notes">${game.i18n.localize("smart-doors.ui.synchronizedDoors.description")}</p>
<div class="form-group"> <div class="form-group">
<label for="synchronizationGroup">${game.i18n.localize("smart-doors.ui.synchronizedDoors.groupName")}</label> <label for="synchronizationGroup">${game.i18n.localize(
"smart-doors.ui.synchronizedDoors.groupName",
)}</label>
<input type="text" name="synchronizationGroup"/> <input type="text" name="synchronizationGroup"/>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="synchronizeSecretStatus">${game.i18n.localize("smart-doors.ui.synchronizedDoors.synchronizeSecretStatus")}</label> <label for="synchronizeSecretStatus">${game.i18n.localize(
"smart-doors.ui.synchronizedDoors.synchronizeSecretStatus",
)}</label>
<input type="checkbox" name="synchronizeSecretStatus" value="true"/> <input type="checkbox" name="synchronizeSecretStatus" value="true"/>
</div> </div>
` `;
html.find(".form-group").last().after(synchronizedSettings) html.find(".form-group").last().after(synchronizedSettings);
const smartdoorsData = data.object.flags.smartdoors const smartdoorsData = data.object.flags.smartdoors;
// Fill the injected input fields with values // Fill the injected input fields with values
const input = (name) => html.find(`input[name="${name}"]`); // input is a helper function to search for a input field by it's name const input = name => html.find(`input[name="${name}"]`); // input is a helper function to search for a input field by it's name
input("synchronizationGroup").prop("value", smartdoorsData?.synchronizationGroup) input("synchronizationGroup").prop("value", smartdoorsData?.synchronizationGroup);
input("synchronizeSecretStatus").prop("checked", smartdoorsData?.synchronizeSecretStatus); input("synchronizeSecretStatus").prop("checked", smartdoorsData?.synchronizeSecretStatus);
// Recalculate config window height // Recalculate config window height
wallConfig.setPosition({height: "auto"}) wallConfig.setPosition({height: "auto"});
} }
} }
@@ -46,29 +50,29 @@ export async function onWallConfigUpdate(event, formData) {
// Search for other doors in the synchronization group that aren't in the list of edited doors // Search for other doors in the synchronization group that aren't in the list of edited doors
const doorInGroup = Util.findInAllWalls(wall => { const doorInGroup = Util.findInAllWalls(wall => {
// We only search for doors // We only search for doors
if (!wall.data.door) if (!wall.door) return false;
return false
// We only want doors in the same synchronization group // We only want doors in the same synchronization group
if (wall.data.flags.smartdoors?.synchronizationGroup !== formData.synchronizationGroup) if (wall.flags.smartdoors?.synchronizationGroup !== formData.synchronizationGroup)
return false return false;
// Doors on this scene that have their id included in `ids` are currently being changed. Ignore them. // Doors on this scene that have their id included in `ids` are currently being changed. Ignore them.
if (wall.parent.id === canvas.scene.id && ids.includes(wall.id)) if (wall.parent.id === canvas.scene.id && ids.includes(wall.id)) return false;
return false return true;
return true });
})
if (doorInGroup) { if (doorInGroup) {
// ds is the door sate in foundry // ds is the door sate in foundry
updateData.ds = doorInGroup.data.ds; updateData.ds = doorInGroup.ds;
if (synchronizeSecretStatus) { if (synchronizeSecretStatus) {
// door is the door type in foundry // door is the door type in foundry
updateData.door = doorInGroup.data.door; updateData.door = doorInGroup.door;
} }
} }
} }
// Update all the edited walls // Update all the edited walls
const updateDataset = ids.map(id => {return {_id: id, ...updateData}}); const updateDataset = ids.map(id => {
return {_id: id, ...updateData};
});
const updateResult = await canvas.scene.updateEmbeddedDocuments("Wall", updateDataset); const updateResult = await canvas.scene.updateEmbeddedDocuments("Wall", updateDataset);
// If door is synchronized, synchronize secret status among synchronized doors // If door is synchronized, synchronize secret status among synchronized doors
@@ -80,70 +84,74 @@ export async function onWallConfigUpdate(event, formData) {
// Update the state of all synchronized doors // Update the state of all synchronized doors
export function onDoorLeftClick() { export function onDoorLeftClick() {
const state = this.wall.data.ds const state = this.wall.document.ds;
const states = CONST.WALL_DOOR_STATES const states = CONST.WALL_DOOR_STATES;
// Check if this feature is enabled // Check if this feature is enabled
if (!game.settings.get(settingsKey, "synchronizedDoors")) if (!game.settings.get(settingsKey, "synchronizedDoors")) return false;
return false
const synchronizationGroup = this.wall.data.flags.smartdoors?.synchronizationGroup const synchronizationGroup = this.wall.document.flags.smartdoors?.synchronizationGroup;
// Does this door have a synchronization group? If not there is nothing to do // Does this door have a synchronization group? If not there is nothing to do
if (!synchronizationGroup) if (!synchronizationGroup) return false;
return false
// If the door is locked there is nothing to synchronize // If the door is locked there is nothing to synchronize
if (state === states.LOCKED) if (state === states.LOCKED) return false;
return false
// Calculate new door state // Calculate new door state
const newstate = state === states.CLOSED ? states.OPEN : states.CLOSED const newstate = state === states.CLOSED ? states.OPEN : states.CLOSED;
// Update all doors belonging to the synchronization group // Update all doors belonging to the synchronization group
const updateData = {ds: newstate} const updateData = {ds: newstate};
updateSynchronizedDoors(updateData, synchronizationGroup) updateSynchronizedDoors(updateData, synchronizationGroup);
return true return true;
} }
export function onDoorRightClick() { export function onDoorRightClick() {
const state = this.wall.data.ds const state = this.wall.document.ds;
const states = CONST.WALL_DOOR_STATES const states = CONST.WALL_DOOR_STATES;
// Check if this feature is enabled // Check if this feature is enabled
if (!game.settings.get(settingsKey, "synchronizedDoors")) if (!game.settings.get(settingsKey, "synchronizedDoors")) return false;
return false
const synchronizationGroup = this.wall.data.flags.smartdoors?.synchronizationGroup const synchronizationGroup = this.wall.document.flags.smartdoors?.synchronizationGroup;
// Does this door have a synchronization group? If not there is nothing to do // Does this door have a synchronization group? If not there is nothing to do
if (!synchronizationGroup) if (!synchronizationGroup) return false;
return false
// Only the gm is allowed to lock/unlock doors // Only the gm is allowed to lock/unlock doors
if ( !game.user.isGM ) if (!game.user.isGM) return false;
return false;
// If the door is currently opened we cannot lock the door // If the door is currently opened we cannot lock the door
if ( state === states.OPEN ) if (state === states.OPEN) return false;
return false;
// Calculate new door state // Calculate new door state
const newstate = state === states.LOCKED ? states.CLOSED : states.LOCKED; const newstate = state === states.LOCKED ? states.CLOSED : states.LOCKED;
// Update all doors belonging to the synchronization group // Update all doors belonging to the synchronization group
const updateData = {ds: newstate} const updateData = {ds: newstate};
updateSynchronizedDoors(updateData, synchronizationGroup) updateSynchronizedDoors(updateData, synchronizationGroup);
return true return true;
} }
// Updates all doors in the specified synchronization group with the provided data // Updates all doors in the specified synchronization group with the provided data
export function updateSynchronizedDoors(updateData, synchronizationGroup) { export function updateSynchronizedDoors(updateData, synchronizationGroup) {
// Search for doors belonging to the synchronization group in all scenes // Search for doors belonging to the synchronization group in all scenes
let scenes = Util.filterAllWalls(wall => wall.data.door && wall.data.flags.smartdoors?.synchronizationGroup === synchronizationGroup); let scenes = Util.filterAllWalls(
wall => wall.door && wall.flags.smartdoors?.synchronizationGroup === synchronizationGroup,
);
// Update all doors in the synchronization group // Update all doors in the synchronization group
return Promise.all(scenes.map(scene => scene.scene.updateEmbeddedDocuments("Wall", scene.walls.map((wall) => {return {_id: wall.id, ...updateData}})))); return Promise.all(
scenes.map(scene =>
scene.scene.updateEmbeddedDocuments(
"Wall",
scene.walls.map(wall => {
return {_id: wall.id, ...updateData};
}),
),
),
);
} }

View File

@@ -1,21 +1,24 @@
import {toggleSecretDoor} from "../keybindings.js"; import {toggleSecretDoor} from "../keybindings.js";
import {settingsKey} from "../settings.js" import {settingsKey} from "../settings.js";
import {updateSynchronizedDoors} from "./synchronized_doors.js"; import {updateSynchronizedDoors} from "./synchronized_doors.js";
// Toggles between normal and secret doors // Toggles between normal and secret doors
export function onDoorLeftClick() { export function onDoorLeftClick() {
// We don't trust the event to be filled with the expected data for compatibilty with arms reach (which passes a broken event) // We don't trust the event to be filled with the expected data for compatibilty with arms reach (which passes a broken event)
if (toggleSecretDoor && game.user.isGM) { if (toggleSecretDoor && game.user.isGM) {
const types = CONST.WALL_DOOR_TYPES const types = CONST.WALL_DOOR_TYPES;
const newtype = this.wall.data.door === types.DOOR ? types.SECRET : types.DOOR const newtype = this.wall.document.door === types.DOOR ? types.SECRET : types.DOOR;
const updateData = {door: newtype} const updateData = {door: newtype};
const synchronizationGroup = this.wall.data.flags.smartdoors?.synchronizationGroup const synchronizationGroup = this.wall.document.flags.smartdoors?.synchronizationGroup;
if (game.settings.get(settingsKey, "synchronizedDoors") && synchronizationGroup && this.wall.data.flags.smartdoors?.synchronizeSecretStatus) if (
updateSynchronizedDoors(updateData, synchronizationGroup) game.settings.get(settingsKey, "synchronizedDoors") &&
else synchronizationGroup &&
this.wall.document.update(updateData) this.wall.document.flags.smartdoors?.synchronizeSecretStatus
)
updateSynchronizedDoors(updateData, synchronizationGroup);
else this.wall.document.update(updateData);
return true return true;
} }
return false return false;
} }

View File

@@ -1,105 +1,116 @@
"use strict"; "use strict";
import {libWrapper} from "../lib/libwrapper_shim.js"; import {libWrapper} from "../lib/libwrapper_shim.js";
import * as DoorControlIconScale from "./features/door_control_icon_scale.js" import * as DoorControlIconScale from "./features/door_control_icon_scale.js";
import * as HighlightSecretDoors from "./features/highlight_secret_doors.js" import * as HighlightSecretDoors from "./features/highlight_secret_doors.js";
import * as LockedDoorAlert from "./features/locked_door_alert.js" import * as LockedDoorAlert from "./features/locked_door_alert.js";
import * as SynchronizedDoors from "./features/synchronized_doors.js" import * as SynchronizedDoors from "./features/synchronized_doors.js";
import * as ToggleSecretDoor from "./features/toggle_secret_door.js" import * as ToggleSecretDoor from "./features/toggle_secret_door.js";
import {performMigrations} from "./migration.js" import {performMigrations} from "./migration.js";
import {registerKeybindings} from "./keybindings.js" import {registerKeybindings} from "./keybindings.js";
import {registerSettings, settingsKey} from "./settings.js" import {registerSettings, settingsKey} from "./settings.js";
Hooks.once("init", () => { Hooks.once("init", () => {
registerSettings() registerSettings();
registerKeybindings() registerKeybindings();
hookDoorEvents() hookDoorEvents();
hookWallConfigUpdate() hookWallConfigUpdate();
hookDoorControlDraw() hookDoorControlDraw();
DoorControlIconScale.hookDoorControlReposition() DoorControlIconScale.hookDoorControlReposition();
}) });
Hooks.once("ready", () => { Hooks.once("ready", () => {
performMigrations() performMigrations();
}) });
Hooks.on("renderChatMessage", LockedDoorAlert.onRenderChatMessage) Hooks.on("renderChatMessage", LockedDoorAlert.onRenderChatMessage);
Hooks.on("canvasReady", DoorControlIconScale.onCanvasReady) Hooks.on("canvasReady", DoorControlIconScale.onCanvasReady);
Hooks.on("canvasReady", HighlightSecretDoors.onCanvasReady) Hooks.on("canvasReady", HighlightSecretDoors.onCanvasReady);
Hooks.on("updateWall", HighlightSecretDoors.onUpdateWall) Hooks.on("updateWall", HighlightSecretDoors.onUpdateWall);
// Inject our custom settings into the WallConfig dialog // Inject our custom settings into the WallConfig dialog
Hooks.on("renderWallConfig", SynchronizedDoors.onRederWallConfig) Hooks.on("renderWallConfig", SynchronizedDoors.onRederWallConfig);
// Hook the update function of the WallConfig dialog so we can store our custom data // Hook the update function of the WallConfig dialog so we can store our custom data
function hookWallConfigUpdate() { function hookWallConfigUpdate() {
// Replace the original function with our custom one // Replace the original function with our custom one
libWrapper.register("smart-doors", "WallConfig.prototype._updateObject", async function (wrapped, event, formData) { libWrapper.register(
await wrapped(event, formData); "smart-doors",
return SynchronizedDoors.onWallConfigUpdate.call(this, event, formData) "WallConfig.prototype._updateObject",
}, "WRAPPER"); async function (wrapped, event, formData) {
await wrapped(event, formData);
return SynchronizedDoors.onWallConfigUpdate.call(this, event, formData);
},
"WRAPPER",
);
} }
function hookDoorControlDraw() { function hookDoorControlDraw() {
libWrapper.register("smart-doors", "DoorControl.prototype.draw", async function (wrapped) { libWrapper.register(
const result = await wrapped(); "smart-doors",
DoorControlIconScale.onDoorControlPostDraw.call(this) "DoorControl.prototype.draw",
return result; async function (wrapped) {
}, "WRAPPER"); const result = await wrapped();
DoorControlIconScale.onDoorControlPostDraw.call(this);
return result;
},
"WRAPPER",
);
} }
// Hook mouse events on DoorControls to perform our logic. // Hook mouse events on DoorControls to perform our logic.
// If we successfully handled the event block the original handler. Forward the event otherwise. // If we successfully handled the event block the original handler. Forward the event otherwise.
function hookDoorEvents() { function hookDoorEvents() {
// Replace the original mousedown handler with our custom one // Replace the original mousedown handler with our custom one
libWrapper.register("smart-doors", "DoorControl.prototype._onMouseDown", function (wrapped, event) { libWrapper.register(
// Call our handler first. Only allow the original handler to run if our handler returns true "smart-doors",
const eventHandled = onDoorMouseDown.call(this, event) "DoorControl.prototype._onMouseDown",
if (eventHandled) function (wrapped, event) {
return // Call our handler first. Only allow the original handler to run if our handler returns true
return wrapped(event); const eventHandled = onDoorMouseDown.call(this, event);
}, "MIXED"); if (eventHandled) return;
return wrapped(event);
},
"MIXED",
);
// Replace the original rightdown handler with our custom one // Replace the original rightdown handler with our custom one
libWrapper.register("smart-doors", "DoorControl.prototype._onRightDown", function (wrapped, event) { libWrapper.register(
// Call our handler first. Only allow the original handler to run if our handler returns true "smart-doors",
const eventHandled = onDoorRightDown.call(this, event) "DoorControl.prototype._onRightDown",
if (eventHandled) function (wrapped, event) {
return // Call our handler first. Only allow the original handler to run if our handler returns true
return wrapped(event); const eventHandled = onDoorRightDown.call(this, event);
}, "MIXED"); if (eventHandled) return;
return wrapped(event);
},
"MIXED",
);
} }
// Our custom handler for mousedown events on doors // Our custom handler for mousedown events on doors
function onDoorMouseDown(event) { function onDoorMouseDown(event) {
// If the user doesn't have the "door" permission we don't do anything. // If the user doesn't have the "door" permission we don't do anything.
if (!game.user.can("WALL_DOORS")) if (!game.user.can("WALL_DOORS")) return false;
return false
// If the game is paused don't do anything if the current player isn't the gm // If the game is paused don't do anything if the current player isn't the gm
if ( game.paused && !game.user.isGM ) if (game.paused && !game.user.isGM) return false;
return false
if (ToggleSecretDoor.onDoorLeftClick.call(this, event)) if (ToggleSecretDoor.onDoorLeftClick.call(this, event)) return true;
return true
if (LockedDoorAlert.onDoorLeftClick.call(this)) if (LockedDoorAlert.onDoorLeftClick.call(this)) return true;
return true
if (SynchronizedDoors.onDoorLeftClick.call(this)) if (SynchronizedDoors.onDoorLeftClick.call(this)) return true;
return true
return false return false;
} }
// Our custom handler for rightdown events on doors // Our custom handler for rightdown events on doors
function onDoorRightDown(event) { function onDoorRightDown(event) {
if (SynchronizedDoors.onDoorRightClick.call(this)) return true;
if (SynchronizedDoors.onDoorRightClick.call(this)) return false;
return true
return false
} }

View File

@@ -1,57 +1,58 @@
import {settingsKey} from "./settings.js" import {settingsKey} from "./settings.js";
const currentDataVersion = "1.1.0" const currentDataVersion = "1.1.0";
export function performMigrations() { export function performMigrations() {
if (!game.user.isGM) if (!game.user.isGM) return;
return
let dataVersion = game.settings.get(settingsKey, "dataVersion") let dataVersion = game.settings.get(settingsKey, "dataVersion");
if (dataVersion === "fresh install") if (dataVersion === "fresh install") {
{
game.settings.set(settingsKey, "dataVersion", currentDataVersion); game.settings.set(settingsKey, "dataVersion", currentDataVersion);
return; return;
} }
if (dataVersion === "1.0.0") { if (dataVersion === "1.0.0") {
dataVersion = "1.1.0" dataVersion = "1.1.0";
ui.notifications.info(game.i18n.format("smart-doors.ui.messages.migrating", {version: dataVersion})) ui.notifications.info(
game.i18n.format("smart-doors.ui.messages.migrating", {version: dataVersion}),
);
// Make a dictionary that maps all door ids to their scenes // Make a dictionary that maps all door ids to their scenes
const walls = game.scenes.reduce((dict, scene) => { const walls = game.scenes.reduce((dict, scene) => {
scene.data.walls.forEach(wall => { scene.walls.forEach(wall => {
if (!wall.data.door) if (!wall.door) return;
return
dict[wall.id] = scene.id; dict[wall.id] = scene.id;
}) });
return dict return dict;
}, {}) }, {});
// Migrate all messages that have a (wall) source id // Migrate all messages that have a (wall) source id
game.messages.forEach(async message => { game.messages.forEach(async message => {
const wallId = message.data.flags.smartdoors?.sourceId const wallId = message.flags.smartdoors?.sourceId;
if (!wallId) if (!wallId) return;
return const flags = message.flags;
const flags = message.data.flags delete flags.smartdoors.sourceId;
delete flags.smartdoors.sourceId const scene = walls[wallId];
const scene = walls[wallId]
// If there is no wall with this id anymore we can drop the value. It has no purpose anymore // If there is no wall with this id anymore we can drop the value. It has no purpose anymore
if (!scene) { if (!scene) {
if (!message.data.flags.smartdoors) if (!message.flags.smartdoors) delete flags.smartdoors;
delete flags.smartdoors } else {
}
else {
// Assign the id and the scene id to the new data structure // Assign the id and the scene id to the new data structure
flags.smartdoors.source = {wall: wallId, scene: scene} flags.smartdoors.source = {wall: wallId, scene: scene};
} }
// We have to disable recursive here so deleting keys will actually work // We have to disable recursive here so deleting keys will actually work
message.update({flags: flags}, {diff: false, recursive: false}) message.update({flags: flags}, {diff: false, recursive: false});
}) });
game.settings.set(settingsKey, "dataVersion", dataVersion) game.settings.set(settingsKey, "dataVersion", dataVersion);
ui.notifications.info(game.i18n.format("smart-doors.ui.messages.migrationDone", {version: dataVersion})) ui.notifications.info(
game.i18n.format("smart-doors.ui.messages.migrationDone", {version: dataVersion}),
);
} }
if (dataVersion != currentDataVersion) if (dataVersion != currentDataVersion)
ui.notifications.error(game.i18n.format("smart-doors.ui.messages.unknownVersion", {version: dataVersion}), {permanent: true}) ui.notifications.error(
game.i18n.format("smart-doors.ui.messages.unknownVersion", {version: dataVersion}),
{permanent: true},
);
} }

View File

@@ -1,8 +1,11 @@
export const settingsKey = "smart-doors"; export const settingsKey = "smart-doors";
function reloadGM() { function reloadGM() {
if (game.user.isGM) if (game.user.isGM) delayedReload();
location.reload() }
function delayedReload() {
window.setTimeout(() => location.reload(), 500);
} }
export function registerSettings() { export function registerSettings() {
@@ -10,8 +13,8 @@ export function registerSettings() {
scope: "world", scope: "world",
config: false, config: false,
type: String, type: String,
default: "fresh install" default: "fresh install",
}) });
game.settings.register(settingsKey, "doorControlSizeFactor", { game.settings.register(settingsKey, "doorControlSizeFactor", {
name: "smart-doors.settings.doorControlSizeFactor.name", name: "smart-doors.settings.doorControlSizeFactor.name",
hint: "smart-doors.settings.doorControlSizeFactor.hint", hint: "smart-doors.settings.doorControlSizeFactor.hint",
@@ -19,8 +22,8 @@ export function registerSettings() {
config: true, config: true,
type: Number, type: Number,
default: 1.5, default: 1.5,
onChange: () => location.reload() onChange: delayedReload,
}) });
game.settings.register(settingsKey, "highlightSecretDoors", { game.settings.register(settingsKey, "highlightSecretDoors", {
name: "smart-doors.settings.highlightSecretDoors.name", name: "smart-doors.settings.highlightSecretDoors.name",
hint: "smart-doors.settings.highlightSecretDoors.hint", hint: "smart-doors.settings.highlightSecretDoors.hint",
@@ -29,7 +32,7 @@ export function registerSettings() {
type: Boolean, type: Boolean,
default: false, default: false,
onChange: reloadGM, onChange: reloadGM,
}) });
game.settings.register(settingsKey, "lockedDoorAlert", { game.settings.register(settingsKey, "lockedDoorAlert", {
name: "smart-doors.settings.lockedDoorAlert.name", name: "smart-doors.settings.lockedDoorAlert.name",
hint: "smart-doors.settings.lockedDoorAlert.hint", hint: "smart-doors.settings.lockedDoorAlert.hint",
@@ -37,7 +40,7 @@ export function registerSettings() {
config: true, config: true,
type: Boolean, type: Boolean,
default: true, default: true,
}) });
game.settings.register(settingsKey, "synchronizedDoors", { game.settings.register(settingsKey, "synchronizedDoors", {
name: "smart-doors.settings.synchronizedDoors.name", name: "smart-doors.settings.synchronizedDoors.name",
hint: "smart-doors.settings.synchronizedDoors.hint", hint: "smart-doors.settings.synchronizedDoors.hint",
@@ -45,5 +48,5 @@ export function registerSettings() {
config: true, config: true,
type: Boolean, type: Boolean,
default: true, default: true,
}) });
} }

View File

@@ -1,15 +1,17 @@
// Searches through all scenes for walls and returns those that match the given filter criteria. // Searches through all scenes for walls and returns those that match the given filter criteria.
export function filterAllWalls(filterFn) { export function filterAllWalls(filterFn) {
// Find all walls that match the filter criteria // Find all walls that match the filter criteria
const scenes = game.scenes.map((scene) => {return {scene: scene, walls: scene.data.walls.filter(filterFn)}}) const scenes = game.scenes.map(scene => {
return {scene: scene, walls: scene.walls.filter(filterFn)};
});
// Drop all scenes that don't contain any results // Drop all scenes that don't contain any results
return scenes.filter(scene => scene.walls.length > 0) return scenes.filter(scene => scene.walls.length > 0);
} }
// Searches through all scenes for a wall that matches the given filter criteria // Searches through all scenes for a wall that matches the given filter criteria
export function findInAllWalls(filterFn) { export function findInAllWalls(filterFn) {
// TODO The performance of this could be increased by stopping the search on the first hit // TODO The performance of this could be increased by stopping the search on the first hit
const scenes = filterAllWalls(filterFn) const scenes = filterAllWalls(filterFn);
// If results were found take the first wall from the first scene. // If results were found take the first wall from the first scene.
return scenes[0]?.walls[0] return scenes[0]?.walls[0];
} }