From 1ad565d70648ce284085ca99c5f74f036bce0dda Mon Sep 17 00:00:00 2001 From: ironmonk88 <75920956+ironmonk88@users.noreply.github.com> Date: Sun, 4 Aug 2024 21:56:09 -0700 Subject: [PATCH] 12.02 changes --- CHANGELOG.md | 42 +++ actions.js | 377 +++++++++++++++------------ css/monks-active-tiles.css | 2 +- lang/en.json | 13 +- lang/pt-BR.json | 499 ++++++++++++++++++++++++++++++++++++ module.json | 16 +- monks-active-tiles.js | 178 ++++++++++--- packs/active-tile-macros.db | 2 +- 8 files changed, 911 insertions(+), 218 deletions(-) create mode 100644 lang/pt-BR.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 0861437..6abf07b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,45 @@ +## Version 12.02 + +Allowing rotation action to pick Ambient lights + +Fixing issues Foundry introduced with changing colour from a string to an Object. + +Fixing issues with referencing Permission constants instead of Ownership constants. + +Allowing Roll Table quantity to use Handlebar notation. + +Allow open journal to set the ownership of the journal + +Fixed setting permissions for a user to include players that aren't logged in. + +Fixed setting a scene's background action to actually set the background image. + +Fixed set tile image to allow using `1-4` notation + +Fixed Dialog so that it can use html files again. + +Fixed scene preload action + +Added trigger caching, so instead of having to search through all tiles every time a trigger is requested, the tiles are already cached and the trigger knows exactly which tiles would apply. + +Added a new trigger, when lighting change animates + +Fixed issue with rotating an ambient Light + +Fixed issue with temporary Images + +Updated the Region Trigger to allow triggering the tile with appropriate data filled in. + +Fixed issue with adding an item to a character that D&D 5e introduced. + +Fixed issue with tile history not being recorded properly. + +Fixed issues with Burning Wheel system + +Fixed issue with Tile image when dropping an item on the canvas. + +Fixed issue with door trigger when turning into a secret door + ## Version 12.01 v12 compatibility diff --git a/actions.js b/actions.js index bc7c604..9267938 100644 --- a/actions.js +++ b/actions.js @@ -1016,7 +1016,8 @@ export class ActionManager { return ( entity instanceof Token || entity instanceof Tile || - entity instanceof Drawing + entity instanceof Drawing || + entity instanceof AmbientLight ); } }, @@ -1825,7 +1826,7 @@ export class ActionManager { let prop = foundry.utils.getProperty(base, attr); - if (prop && typeof prop == 'object' && !(prop instanceof Array)) { + if (prop && typeof prop == 'object' && !(prop instanceof Array) && !(prop instanceof Color)) { if (prop.value == undefined) { debug("Attribute returned an object and the object doesn't have a value property", entity, attr, prop); continue; @@ -1835,7 +1836,13 @@ export class ActionManager { prop = prop.value; } - update[attr] = await getValue(val, args, entity, { prop }); + let updateValue = await getValue(val, args, entity, { prop }); + console.log("UpdateValue: ", updateValue, args.darkness); + if (prop instanceof Color) { + update[attr] = Color.fromString(updateValue); + } else { + update[attr] = updateValue; + } MonksActiveTiles.batch.add('update', base, update); MonksActiveTiles.addToResult(entity, result); @@ -2570,7 +2577,7 @@ export class ActionManager { for (let token of tokens) { if (token.actor) { for (let [user, perm] of Object.entries(token.actor.ownership)) { - if (perm >= CONST.DOCUMENT_PERMISSION_LEVELS.OWNER && !owners.includes(user)) + if (perm >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER && !owners.includes(user)) owners.push(user); } } @@ -3258,10 +3265,8 @@ export class ActionManager { { id: "quantity", name: "MonksActiveTiles.ctrl.quantity", - type: "number", - defvalue: 1, - min: 1, - step: 1, + type: "text", + defvalue: "1", help: "Set this to blank to use the roll table quantity" }, { @@ -3353,7 +3358,16 @@ export class ActionManager { if (!available.length && action?.data?.reset) await rolltable.resetResults(); - let numRolls = action.data?.quantity || 1; + let numRolls = await MonksActiveTiles.getValue(action.data?.quantity || 1, args, rolltable); + if (isNaN(numRolls)) { + try { + numRolls = parseInt(numRolls); + } catch { + numRolls = 1; + } + } + if (numRolls < 1) numRolls = 1; + let tblResults = await rolltable.drawMany(numRolls, { rollMode: action.data.rollmode, displayChat: false }); //Check to see what the privacy rules are @@ -3923,7 +3937,9 @@ export class ActionManager { { id: "permission", name: "MonksActiveTiles.ctrl.usepermission", - type: "checkbox" + list: "permission", + type: "list", + defvalue: "false" }, { id: "enhanced", @@ -3941,6 +3957,13 @@ export class ActionManager { "token": "MonksActiveTiles.for.token", "owner": "MonksActiveTiles.for.owner", "previous": "MonksActiveTiles.for.current" + }, + 'permission': { + "true": "MonksActiveTiles.permission.check", + "false": "MonksActiveTiles.permission.ignore", + "LIMITED": "MonksActiveTiles.permission.limited", + "OBSERVER": "MonksActiveTiles.permission.observer", + "OWNER": "MonksActiveTiles.permission.owner", } }, fn: async (args = {}) => { @@ -3965,6 +3988,8 @@ export class ActionManager { let showto = action.data.showto || "everyone"; + const levels = CONST.DOCUMENT_OWNERSHIP_LEVELS; + for (let entity of entities) { //open journal if (!entity || !(entity instanceof JournalEntry || entity instanceof JournalEntryPage)) @@ -3972,6 +3997,22 @@ export class ActionManager { let showUsers = MonksActiveTiles.getForPlayers(showto, args); + if (action.data.permission != "true" && action.data.permission != "false") { + const ownership = entity.ownership; + if (showto == "everyone") { + //If everyone, then set the ownership to the default + ownership.default = levels[action.data.permission]; + } + showUsers.forEach(id => { + //If any users are less than the default, boost them up, and if greater and force is true, then bring them down. + let user = game.users.get(id); + if (!user?.isGM) { + ownership[id] = levels[action.data.permission]; + } + }); + await entity.update({ ownership }); + } + if (showUsers.includes(game.user.id)) { if (game.modules.get("monks-enhanced-journal")?.active && entity instanceof JournalEntry && entity.pages.size == 1 && !!foundry.utils.getProperty(entity.pages.contents[0], "flags.monks-enhanced-journal.type")) { let type = foundry.utils.getProperty(entity.pages.contents[0], "flags.monks-enhanced-journal.type"); @@ -4474,7 +4515,7 @@ export class ActionManager { lvl = CONST.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER; const perms = entity.ownership || entity.actor?.ownership; - let showUsers = MonksActiveTiles.getForPlayers(showto, args); + let showUsers = MonksActiveTiles.getForPlayers(showto, args, {notactive: true}); if (showto == 'everyone') { if (action.data.permission == 'default') { @@ -4967,7 +5008,7 @@ export class ActionManager { let entities = await MonksActiveTiles.getEntities(args, 'scenes', action.data.sceneid); for (let scene of entities) { let img = await getValue(action.data?.img, args, scene); - await scene.update({ img }); + await scene.update({ "background.src": img }); } }, content: async (trigger, action) => { @@ -5369,10 +5410,10 @@ export class ActionManager { let parts = pos.split('-'); let lower = parseInt(parts[0]); let upper = parseInt(parts[1]); - pos = Math.floor((Math.random() * (upper - lower)) + lower); + position = Math.floor((Math.random() * (upper - lower)) + lower); } else { let roll = await rollDice(pos); - pos = parseInt(roll.value); + position = parseInt(roll.value); } } else position = parseInt(position); @@ -5987,12 +6028,12 @@ export class ActionManager { method: method, change: change }; - if (!_templateCache.hasOwnProperty(action.data.file) && action.data.file.startsWith("http")) { + if (!Handlebars.partials.hasOwnProperty(action.data.file) && action.data.file.startsWith("http")) { let html = await fetch(action.data.file); let text = await html.text(); const compiled = Handlebars.compile(text); Handlebars.registerPartial(action.data.file, compiled); - _templateCache[action.data.file] = compiled; + Handlebars.partials[action.data.file] = compiled; content = compiled(context, { allowProtoMethodsByDefault: true, allowProtoPropertiesByDefault: true @@ -6240,7 +6281,7 @@ export class ActionManager { name: "MonksActiveTiles.action.preload", ctrls: [ { - id: "sceneid", + id: "entity", name: "MonksActiveTiles.ctrl.scene", type: "select", subtype: "entity", @@ -6277,7 +6318,7 @@ export class ActionManager { let showfor = action.data.for || "trigger"; let showUsers = MonksActiveTiles.getForPlayers(showfor, args); - let entities = await MonksActiveTiles.getEntities(args, 'scene'); + let entities = await MonksActiveTiles.getEntities(args, 'scene', action.data?.sceneid); for (let entity of entities) { if (showUsers.includes(game.user.id)) { await game.scenes.preload(entity.id); @@ -6819,156 +6860,156 @@ export class ActionManager { } }, - 'distance': { - name: "MonksActiveTiles.filter.distance", - ctrls: [ - { - id: "entity", - name: "MonksActiveTiles.ctrl.select-entity", - type: "select", - subtype: "entity", - options: { show: ['token', 'within', 'players', 'previous', 'tagger'] }, - restrict: (entity) => { return (entity instanceof Token); } - }, - { - id: "measure", - name: "Measure", - list: "measure", - type: "list", - onChange: (app) => { - app.checkConditional(); - }, - defvalue: 'lte' - }, - { - id: "distance", - name: "MonksActiveTiles.ctrl.distance", - type: "number", - required: true, - variation: 'unit', - conditional: (app) => { - return $('select[name="data.measure"]', app.element).val() != 'lt'; - }, - defvalue: 1 - }, - { - id: "from", - name: "Measure From", - list: "from", - type: "list", - defvalue: 'edge' - }, - { - id: "continue", - name: "Continue if", - list: "continue", - type: "list", - defvalue: 'within' - } - ], - values: { - 'measure': { - 'lt': "inside tile", - 'lte': "less than", - 'eq': "within", - 'gt': "greater than" - }, - 'continue': { - "always": "Always", - "within": "Any Within Distance", - "all": "All Within Distance" - }, - 'unit': { - 'sq': "grid sq.", - 'px': "pixel" - }, - 'from': { - 'edge': "Edge", - 'center': "Center" - } - }, - group: "filters", - fn: async (args = {}) => { - const { tile, value, action } = args; - - let midTile = { x: tile.x + (Math.abs(tile.width) / 2), y: tile.y + (Math.abs(tile.height) / 2) }; - - let entities = await MonksActiveTiles.getEntities(args); - - let tokens = entities.filter(t => { - if (!(t instanceof TokenDocument)) - return false; - - const hW = ((Math.abs(t.width) * t.parent.dimensions.size) / 2); - const hH = ((Math.abs(t.height) * t.parent.dimensions.size) / 2); - const midToken = { x: t.x + hW, y: t.y + hH }; - - if (action.data.measure == 'lt') { - return tile.pointWithin(midToken); - } else { - let distance = parseInt(action.data?.distance.value || action.data?.distance || 0); - if (action.data.distance.var == 'sq') - distance = (t.parent.grid.size * distance); - - let dest = { x: midTile.x - hW, y: midTile.y - hH }; - - if (action.data.from == "center") { - const dist = Math.hypot(midTile.x - midToken.x, midTile.y - midToken.y) - ((Math.abs(t.width) * t.parent.dimensions.size) / 2); - debug('token within', dist); - - return (action.data.measure == 'gt' ? dist > distance : dist < distance && dist > -(Math.abs(t.width) * t.parent.dimensions.size)); - } else { - let collisions = tile.getIntersections(t, dest); - - if (collisions.length == 0) { - //it's within the tile - return action.data.measure == 'lte'; - } else { - let sorted = (collisions.length > 1 ? collisions.sort((c1, c2) => (c1.t0 > c2.t0) ? 1 : -1) : collisions); - - //clear out any duplicate corners - collisions = sorted.filter((value, index, self) => { - return self.findIndex(v => v.x === value.x && v.y === value.y) === index; - }); - - /* - let gr = new PIXI.Graphics(); - if (MonksActiveTiles.debugGr) - canvas.tokens.removeChild(MonksActiveTiles.debugGr); - MonksActiveTiles.debugGr = gr; - canvas.tokens.addChild(gr); - - gr.beginFill(0x800080) - .lineStyle(2, 0x800080) - .moveTo(midToken.x, midToken.y) - .lineTo(collisions[0].x, collisions[0].y) - .drawCircle(midTile.x, midTile.y, 4) - .drawCircle(midToken.x, midToken.y, 4) - .drawCircle(collisions[0].x, collisions[0].y, 4) - .endFill(); - */ - - const dist = Math.hypot(collisions[0].x - midToken.x, collisions[0].y - midToken.y) - ((Math.abs(t.width) * t.parent.dimensions.size) / 2); - debug('token within', dist); - - return (action.data.measure == 'gt' ? dist > distance : dist < distance && dist > -(Math.abs(t.width) * t.parent.dimensions.size)); - } - } - } - }); - - let cont = (action.data?.continue == 'always' - || (action.data?.continue == 'within' && tokens.length > 0) - || (action.data?.continue == 'all' && tokens.length == value["tokens"].length && tokens.length > 0)); - - return { continue: cont, tokens: tokens }; - }, - content: async (trigger, action) => { - let unit = (action.data.distance.var == 'sq' ? 'grid square' : 'pixels'); - let ctrl = trigger.ctrls.find(c => c.id == "entity"); - let entityName = await MonksActiveTiles.entityName(action.data?.entity || ctrl?.defvalue || "previous"); - return `Filter ${entityName} ${action.data.measure != 'lte' ? 'by a distance' : 'that are'} ${trigger.values.measure[action.data.measure || 'eq']}${(action.data.measure != 'lt' ? ` "${action.data?.distance.value || action.data?.distance || 0}" ${unit} of this Tile` : '')} ${(action.data?.continue != 'always' ? ', Continue if ' + (action.data?.continue == 'within' ? 'Any Within Distance' : 'All Within Distance') : '')}`; - } + 'distance': { + name: "MonksActiveTiles.filter.distance", + ctrls: [ + { + id: "entity", + name: "MonksActiveTiles.ctrl.select-entity", + type: "select", + subtype: "entity", + options: { show: ['token', 'within', 'players', 'previous', 'tagger'] }, + restrict: (entity) => { return (entity instanceof Token); } + }, + { + id: "measure", + name: "Measure", + list: "measure", + type: "list", + onChange: (app) => { + app.checkConditional(); + }, + defvalue: 'lte' + }, + { + id: "distance", + name: "MonksActiveTiles.ctrl.distance", + type: "number", + required: true, + variation: 'unit', + conditional: (app) => { + return $('select[name="data.measure"]', app.element).val() != 'lt'; + }, + defvalue: 1 + }, + { + id: "from", + name: "Measure From", + list: "from", + type: "list", + defvalue: 'edge' + }, + { + id: "continue", + name: "Continue if", + list: "continue", + type: "list", + defvalue: 'within' + } + ], + values: { + 'measure': { + 'lt': "inside tile", + 'lte': "less than", + 'eq': "within", + 'gt': "greater than" + }, + 'continue': { + "always": "Always", + "within": "Any Within Distance", + "all": "All Within Distance" + }, + 'unit': { + 'sq': "grid sq.", + 'px': "pixel" + }, + 'from': { + 'edge': "Edge", + 'center': "Center" + } + }, + group: "filters", + fn: async (args = {}) => { + const { tile, value, action } = args; + + let midTile = { x: tile.x + (Math.abs(tile.width) / 2), y: tile.y + (Math.abs(tile.height) / 2) }; + + let entities = await MonksActiveTiles.getEntities(args); + + let tokens = entities.filter(t => { + if (!(t instanceof TokenDocument)) + return false; + + const hW = ((Math.abs(t.width) * t.parent.dimensions.size) / 2); + const hH = ((Math.abs(t.height) * t.parent.dimensions.size) / 2); + const midToken = { x: t.x + hW, y: t.y + hH }; + + if (action.data.measure == 'lt') { + return tile.pointWithin(midToken); + } else { + let distance = parseInt(action.data?.distance.value || action.data?.distance || 0); + if (action.data.distance.var == 'sq') + distance = (t.parent.grid.size * distance); + + let dest = { x: midTile.x - hW, y: midTile.y - hH }; + + if (action.data.from == "center") { + const dist = Math.hypot(midTile.x - midToken.x, midTile.y - midToken.y) - ((Math.abs(t.width) * t.parent.dimensions.size) / 2); + debug('token within', dist); + + return (action.data.measure == 'gt' ? dist > distance : dist < distance && dist > -(Math.abs(t.width) * t.parent.dimensions.size)); + } else { + let collisions = tile.getIntersections(t, dest); + + if (collisions.length == 0) { + //it's within the tile + return action.data.measure == 'lte'; + } else { + let sorted = (collisions.length > 1 ? collisions.sort((c1, c2) => (c1.t0 > c2.t0) ? 1 : -1) : collisions); + + //clear out any duplicate corners + collisions = sorted.filter((value, index, self) => { + return self.findIndex(v => v.x === value.x && v.y === value.y) === index; + }); + + /* + let gr = new PIXI.Graphics(); + if (MonksActiveTiles.debugGr) + canvas.tokens.removeChild(MonksActiveTiles.debugGr); + MonksActiveTiles.debugGr = gr; + canvas.tokens.addChild(gr); + + gr.beginFill(0x800080) + .lineStyle(2, 0x800080) + .moveTo(midToken.x, midToken.y) + .lineTo(collisions[0].x, collisions[0].y) + .drawCircle(midTile.x, midTile.y, 4) + .drawCircle(midToken.x, midToken.y, 4) + .drawCircle(collisions[0].x, collisions[0].y, 4) + .endFill(); + */ + + const dist = Math.hypot(collisions[0].x - midToken.x, collisions[0].y - midToken.y) - ((Math.abs(t.width) * t.parent.dimensions.size) / 2); + debug('token within', dist); + + return (action.data.measure == 'gt' ? dist > distance : dist < distance && dist > -(Math.abs(t.width) * t.parent.dimensions.size)); + } + } + } + }); + + let cont = (action.data?.continue == 'always' + || (action.data?.continue == 'within' && tokens.length > 0) + || (action.data?.continue == 'all' && tokens.length == value["tokens"].length && tokens.length > 0)); + + return { continue: cont, tokens: tokens }; + }, + content: async (trigger, action) => { + let unit = (action.data.distance.var == 'sq' ? 'grid square' : 'pixels'); + let ctrl = trigger.ctrls.find(c => c.id == "entity"); + let entityName = await MonksActiveTiles.entityName(action.data?.entity || ctrl?.defvalue || "previous"); + return `Filter ${entityName} ${action.data.measure != 'lte' ? 'by a distance' : 'that are'} ${trigger.values.measure[action.data.measure || 'eq']}${(action.data.measure != 'lt' ? ` "${action.data?.distance.value || action.data?.distance || 0}" ${unit} of this Tile` : '')} ${(action.data?.continue != 'always' ? ', Continue if ' + (action.data?.continue == 'within' ? 'Any Within Distance' : 'All Within Distance') : '')}`; + } }, 'visibility': { name: "MonksActiveTiles.filter.visibility", diff --git a/css/monks-active-tiles.css b/css/monks-active-tiles.css index 0992cb5..5067ab9 100644 --- a/css/monks-active-tiles.css +++ b/css/monks-active-tiles.css @@ -540,5 +540,5 @@ body.system-CoC7 .multiple-dropdown .multiple-dropdown-option { } #trigger-action .small-field { - flex: 0 0 75px; + flex: 0 0 150px; } \ No newline at end of file diff --git a/lang/en.json b/lang/en.json index b06d81c..ad6c7d2 100644 --- a/lang/en.json +++ b/lang/en.json @@ -197,7 +197,7 @@ "MonksActiveTiles.ctrl.loop": "Loop", "MonksActiveTiles.ctrl.audiotype": "Audio Type", "MonksActiveTiles.ctrl.activate": "Activate", - "MonksActiveTiles.ctrl.usepermission": "Check Permission", + "MonksActiveTiles.ctrl.usepermission": "Permissions", "MonksActiveTiles.ctrl.distance": "Distance", "MonksActiveTiles.ctrl.name": "Name", "MonksActiveTiles.ctrl.chatbubble": "Chat Bubble", @@ -322,6 +322,7 @@ "MonksActiveTiles.mode.create": "Token Create", "MonksActiveTiles.mode.door": "Door Trigger", "MonksActiveTiles.mode.darkness": "Lighting Change", + "MonksActiveTiles.mode.darknesschange": "Lighting Animation", "MonksActiveTiles.mode.time": "Time Change", "MonksActiveTiles.restrict.all": "Allow All Tokens", @@ -459,6 +460,12 @@ "MonksActiveTiles.resettype.everything": "Everything", "MonksActiveTiles.resettype.token": "Token", + "MonksActiveTiles.permission.check": "Check Permission", + "MonksActiveTiles.permission.ignore": "Ignore Permissions", + "MonksActiveTiles.permission.limited": "Assign Limited Permission", + "MonksActiveTiles.permission.observer": "Assign Observer Permission", + "MonksActiveTiles.permission.owner": "Assign Owner Permission", + "MonksActiveTiles.msg.prevent-teleport": "Teleporting off the map has been prevented", "MonksActiveTiles.msg.prevent-movement": "Moving off the map has been prevented", "MonksActiveTiles.msg.invalid-entity": "Invalid Entity Type", @@ -552,6 +559,10 @@ "uuid": { "label": "Tile", "hint": "Tile to trigger" + }, + "usetiletrigger": { + "label": "Trigger using event", + "hint": "Trigger the tile using the region event data" } } } diff --git a/lang/pt-BR.json b/lang/pt-BR.json new file mode 100644 index 0000000..d3da7e5 --- /dev/null +++ b/lang/pt-BR.json @@ -0,0 +1,499 @@ +{ + "MonksActiveTiles.Triggers": "Gatilhos", + "MonksActiveTiles.TriggersHint": "Configuração para quando um jogador interage com este bloco", + "MonksActiveTiles.TriggersImages": "Lista de imagens adicionais para este bloco", + "MonksActiveTiles.TriggerAction": "Acionar Ação", + "MonksActiveTiles.ThisTile": "Este Bloco", + "MonksActiveTiles.TriggeringToken": "Token Desencadeador", + "MonksActiveTiles.PlayerTokens": "Fichas do Jogador", + "MonksActiveTiles.CurrentLocation": "Local Atual", + "MonksActiveTiles.WithinTile": "{collection} dentro do Bloco", + "MonksActiveTiles.WithinWall": "Telhas sob a porta", + "MonksActiveTiles.CurrentCollection": "Atual {collection}", + "MonksActiveTiles.Origin": "Destino Original", + "MonksActiveTiles.Controlled": "Tokens Controlados", + "MonksActiveTiles.CurrentlyPlaying": "Atualmente em reprodução", + "MonksActiveTiles.TileVariables": "Variáveis de Bloco", + "MonksActiveTiles.ClearVariables": "Limpar Variáveis", + "MonksActiveTiles.TileHistory": "Histórico do Bloco", + "MonksActiveTiles.ResetHistory": "Redefinir Histórico", + "MonksActiveTiles.SelectTile": "Selecionar Bloco", + "MonksActiveTiles.Match": "Corresponder", + "MonksActiveTiles.Scene": "Cena", + "MonksActiveTiles.After": "Depois", + "MonksActiveTiles.Action": "Ação", + "MonksActiveTiles.Update": "Atualizar", + "MonksActiveTiles.Seconds": "segundos", + "MonksActiveTiles.CreateNewAction": "Criar Nova Ação", + "MonksActiveTiles.Active": "Ativo", + "MonksActiveTiles.RestrictedTo": "Tokens Restritos", + "MonksActiveTiles.ControlledBy": "Controlado Por", + "MonksActiveTiles.When": "Quando", + "MonksActiveTiles.ChanceTrigger": "% de chance de acionar", + "MonksActiveTiles.Add": "Adicionar", + "MonksActiveTiles.ToggleActive": "Alternar Estado Ativo", + "MonksActiveTiles.PerToken": "Uma vez por ficha", + "MonksActiveTiles.EditAction": "Editar Ação", + "MonksActiveTiles.DeleteAction": "Ação de Excluir", + "MonksActiveTiles.Actions": "Ações", + "MonksActiveTiles.ManualTrigger": "Acionar Manualmente Ações", + "MonksActiveTiles.MinRequired": "Mínimo necessário para acionar", + "MonksActiveTiles.TagName": "Digite o nome da tag", + "MonksActiveTiles.Save": "Salvar", + "MonksActiveTiles.SnapToGrid": "Ajustar à grade", + "MonksActiveTiles.History": "Histórico", + "MonksActiveTiles.HoverPointer": "Ponteiro de Hover", + "MonksActiveTiles.UseTransparency": "Acionar usando imagem em vez de borda", + "MonksActiveTiles.Sounds": "Reprodução de Sons", + "MonksActiveTiles.AllowWhenPaused": "Permitir quando Pausado", + "MonksActiveTiles.ShownImage": "Imagem Exibida", + "MonksActiveTiles.TileTemplates": "Modelos de Bloco", + "MonksActiveTiles.Players": "Jogadores", + "MonksActiveTiles.Cooldown": "Tempo de Recarga (segundos)", + "MonksActiveTiles.MultiplePlayers": "Jogadores Múltiplos ({players})", + "MonksActiveTiles.UnknownPlayer": "Jogador Desconhecido", + "MonksActiveTiles.MultipleLocations": "Múltiplas Localizações ({locations})", + "MonksActiveTiles.UnknownLocation": "Local desconhecido", + "MonksActiveTiles.MultipleEntities": "Múltiplas Entidades ({entities})", + "MonksActiveTiles.UnknownEntity": "Entidade Desconhecida", + "MonksActiveTiles.ActiveScene": "Cena Ativa", + "MonksActiveTiles.TriggeringTokenScene": "Ativando Cena do Token", + "MonksActiveTiles.TokenVision": "O token deve ter visão para ativar", + "MonksActiveTiles.actiontext.pause": "{pausar} jogo", + "MonksActiveTiles.actiontext.delay": "Esperar por \"{delay} segundos\"", + "MonksActiveTiles.actiontext.movement": "{action}{snap}", + "MonksActiveTiles.group.actions": "Ações", + "MonksActiveTiles.group.filters": "Filtros", + "MonksActiveTiles.group.logic": "Fluxo de Ação", + "MonksActiveTiles.action.pause": "Pausar Jogo", + "MonksActiveTiles.action.stopmovement": "Parar Movimento do Token", + "MonksActiveTiles.action.teleport": "Teleport", + "MonksActiveTiles.action.showhide": "Mostrar/Ocultar", + "MonksActiveTiles.action.activate": "Ativar/Desativar", + "MonksActiveTiles.action.alter": "Alterar", + "MonksActiveTiles.action.playsound": "Reproduzir arquivo de som", + "MonksActiveTiles.action.playlist": "Lista de reprodução", + "MonksActiveTiles.action.stopsound": "Parar Som", + "MonksActiveTiles.action.changedoor": "Alterar Parede/Porta", + "MonksActiveTiles.action.notification": "Enviar notificação", + "MonksActiveTiles.action.chatmessage": "Mensagem no Chat", + "MonksActiveTiles.action.runmacro": "Executar Macro", + "MonksActiveTiles.action.rolltable": "Rolar Tabela", + "MonksActiveTiles.action.pancanvas": "Mover Canvas", + "MonksActiveTiles.action.resetfog": "Redefinir Nevoeiro de Guerra", + "MonksActiveTiles.action.activeeffect": "Efeito Ativo", + "MonksActiveTiles.action.movement": "Mover", + "MonksActiveTiles.action.createtoken": "Criar Token", + "MonksActiveTiles.action.playanimation": "Animação de Bloco", + "MonksActiveTiles.action.openjournal": "Abrir um Diário", + "MonksActiveTiles.action.openactor": "Abrir uma ficha de ator", + "MonksActiveTiles.action.additem": "Adicionar Item", + "MonksActiveTiles.action.permission": "Alterar Permissões", + "MonksActiveTiles.action.attack": "Atacar", + "MonksActiveTiles.action.trigger": "Ativar Bloco", + "MonksActiveTiles.action.scene": "Alterar Cena", + "MonksActiveTiles.action.addtocombat": "Adicionar ao Combate", + "MonksActiveTiles.action.elevation": "Elevação", + "MonksActiveTiles.action.hurtheal": "Machucar/Curar", + "MonksActiveTiles.action.resethistory": "Redefinir Histórico de Acionamento de Bloco", + "MonksActiveTiles.action.delay": "Atraso de ações", + "MonksActiveTiles.action.imagecycle": "Alterar Imagens", + "MonksActiveTiles.action.imagecycleset": "Alterar Imagens, Definir Imagem", + "MonksActiveTiles.action.delete": "Excluir Entidades", + "MonksActiveTiles.action.createjournal": "Criar Anotação de Diário", + "MonksActiveTiles.action.scenelighting": "Iluminação da Cena", + "MonksActiveTiles.action.target": "Alvo", + "MonksActiveTiles.action.globalvolume": "Volume Global", + "MonksActiveTiles.action.dialog": "Mostrar Diálogo", + "MonksActiveTiles.action.scenebackground": "Plano de Fundo da Cena", + "MonksActiveTiles.action.scrollingtext": "Texto Rolante", + "MonksActiveTiles.action.preload": "Pré-carregar Cena", + "MonksActiveTiles.action.removeitem": "Remover Item", + "MonksActiveTiles.action.tileimage": "Alterar Imagem do Bloco", + "MonksActiveTiles.action.runbatch": "Executar Todas as Ações em Lote", + "MonksActiveTiles.action.rotation": "Rotação", + "MonksActiveTiles.action.showimage": "Mostrar Imagem", + "MonksActiveTiles.action.writetojournal": "Escrever no Diário", + "MonksActiveTiles.action.setvariable": "Definir Variável de Blocos Ativos", + "MonksActiveTiles.action.setcurrent": "Definir Coleção Atual de Blocos Ativos", + "MonksActiveTiles.action.closedialog": "Fechar Diálogo", + "MonksActiveTiles.action.url": "Abrir URL", + "MonksActiveTiles.action.tempimage": "Imagem Temporária do Bloco", + "MonksActiveTiles.action.ping": "Ping", + "MonksActiveTiles.action.gametime": "Tempo de Jogo", + "MonksActiveTiles.action.shuffle": "Embaralhar Coleção", + "MonksActiveTiles.action.preloadtileimage": "Pré-carregar imagens de Blocos", + "MonksActiveTiles.action.runcode": "Executar Código", + "MonksActiveTiles.filter.distance": "Filtrar tokens por distância", + "MonksActiveTiles.filter.exists": "Verificar contagem de entidades", + "MonksActiveTiles.filter.triggercount": "Verificar contagem de gatilho de bloco", + "MonksActiveTiles.filter.tokencount": "Filtrar por contagem de acionamento de token", + "MonksActiveTiles.filter.first": "Posição na lista", + "MonksActiveTiles.filter.attribute": "Filtrar por atributos", + "MonksActiveTiles.filter.inventory": "Filtrar por itens no inventário", + "MonksActiveTiles.filter.condition": "Filtrar por condição", + "MonksActiveTiles.filter.random": "Número Aleatório", + "MonksActiveTiles.filter.visibility": "Filtrar por visibilidade", + "MonksActiveTiles.filter.variable": "Verificar variável", + "MonksActiveTiles.filter.value": "Verificar valor", + "MonksActiveTiles.logic.anchor": "Página de Destino", + "MonksActiveTiles.logic.goto": "Ir para o Destino", + "MonksActiveTiles.logic.stop": "Parar ações restantes", + "MonksActiveTiles.logic.playertype": "Redirecionar com base no tipo de jogador", + "MonksActiveTiles.logic.loop": "Iterar através de Entidades", + "MonksActiveTiles.logic.method": "Redirecionar com base no Método", + "MonksActiveTiles.logic.checkdata": "Verificar dados", + "MonksActiveTiles.logic.stoptriggers": "Parar gatilhos de tiles adicionais", + "MonksActiveTiles.ctrl.snap": "Ajustar à grade", + "MonksActiveTiles.ctrl.select-coordinates": "Selecionar Coordenadas", + "MonksActiveTiles.ctrl.select-entity": "Selecionar Entidade", + "MonksActiveTiles.ctrl.select-actor": "Selecionar Ator", + "MonksActiveTiles.ctrl.select-tile": "Selecionar Bloco", + "MonksActiveTiles.ctrl.select-token": "Selecionar Token", + "MonksActiveTiles.ctrl.state": "Estado", + "MonksActiveTiles.ctrl.attribute": "Atributo", + "MonksActiveTiles.ctrl.value": "Valor", + "MonksActiveTiles.ctrl.audiofile": "Arquivo de Som", + "MonksActiveTiles.ctrl.playlist": "Lista de Reprodução de Som", + "MonksActiveTiles.ctrl.for": "Para", + "MonksActiveTiles.ctrl.selectdoor": "Selecionar Porta", + "MonksActiveTiles.ctrl.selectrolltable": "Selecionar Tabela de Rolagem", + "MonksActiveTiles.ctrl.type": "Tipo", + "MonksActiveTiles.ctrl.text": "Texto", + "MonksActiveTiles.ctrl.macro": "Macro", + "MonksActiveTiles.ctrl.args": "Argumentos", + "MonksActiveTiles.ctrl.animate": "Animar", + "MonksActiveTiles.ctrl.language": "Idioma", + "MonksActiveTiles.ctrl.effectlist": "Efeito", + "MonksActiveTiles.ctrl.waitforanimation": "Aguardar Animação", + "MonksActiveTiles.ctrl.animation": "Animação", + "MonksActiveTiles.ctrl.showto": "Mostrar para", + "MonksActiveTiles.ctrl.invisible": "Criar Invisível", + "MonksActiveTiles.ctrl.select-item": "Selecionar Item", + "MonksActiveTiles.ctrl.rollmode": "Modo de Rolagem", + "MonksActiveTiles.ctrl.chatmessage": "Adicionar mensagem de chat", + "MonksActiveTiles.ctrl.flavor": "Sabor", + "MonksActiveTiles.ctrl.changefor": "Troco", + "MonksActiveTiles.ctrl.permission": "Permissão", + "MonksActiveTiles.ctrl.attack": "Ataque", + "MonksActiveTiles.ctrl.scenerestrict": "Restringir à Cena", + "MonksActiveTiles.ctrl.scene": "Cena", + "MonksActiveTiles.ctrl.animatepan": "Animar Panorama do Canvas", + "MonksActiveTiles.ctrl.deletesource": "Excluir Token de Origem", + "MonksActiveTiles.ctrl.avoidtokens": "Evite outros tokens no Destino", + "MonksActiveTiles.ctrl.rollattack": "Tipo de ação", + "MonksActiveTiles.ctrl.rolldamage": "Rolar Dano", + "MonksActiveTiles.ctrl.volume": "Volume", + "MonksActiveTiles.ctrl.incharacter": "Em Caráter", + "MonksActiveTiles.ctrl.speaker": "Palestrante", + "MonksActiveTiles.ctrl.loop": "Repetir", + "MonksActiveTiles.ctrl.audiotype": "Tipo de Áudio", + "MonksActiveTiles.ctrl.activate": "Ativar", + "MonksActiveTiles.ctrl.usepermission": "Verificar Permissão", + "MonksActiveTiles.ctrl.distance": "Distância", + "MonksActiveTiles.ctrl.name": "Nome", + "MonksActiveTiles.ctrl.chatbubble": "Balão de bate-papo", + "MonksActiveTiles.ctrl.runasgm": "Executar como", + "MonksActiveTiles.ctrl.startcombat": "Iniciar Combate", + "MonksActiveTiles.ctrl.delay": "Atraso por (segundos)", + "MonksActiveTiles.ctrl.limit": "Limitar para (loops)", + "MonksActiveTiles.ctrl.resume": "Continuar após limite", + "MonksActiveTiles.ctrl.resumeloop": "Continuar após o looping", + "MonksActiveTiles.ctrl.preservesettings": "Preservar configurações se o token já existe", + "MonksActiveTiles.ctrl.images": "Imagens", + "MonksActiveTiles.ctrl.imgat": "Mostrando Imagem #", + "MonksActiveTiles.ctrl.enhanced": "Use Monk's Enhanced Journal", + "MonksActiveTiles.ctrl.stopwhenreached": "Parar quando alcançado no código", + "MonksActiveTiles.ctrl.triggertiles": "Ativar Blocos ao se mover", + "MonksActiveTiles.ctrl.icon": "Ícone de Entrada", + "MonksActiveTiles.ctrl.tag": "Nome da Tag", + "MonksActiveTiles.ctrl.random": "Aleatório", + "MonksActiveTiles.ctrl.count": "Contagem", + "MonksActiveTiles.ctrl.triggercount": "Contagem de Acionamentos", + "MonksActiveTiles.ctrl.tokencount": "Contagem de Acionamento de Token", + "MonksActiveTiles.ctrl.itemname": "Nome do Item", + "MonksActiveTiles.ctrl.itemcount": "Contagem de itens", + "MonksActiveTiles.ctrl.itemquantity": "Quantidade do Item", + "MonksActiveTiles.ctrl.darkness": "Nível de Escuridão", + "MonksActiveTiles.ctrl.speed": "Velocidade (segundos)", + "MonksActiveTiles.ctrl.play": "Reproduzir", + "MonksActiveTiles.ctrl.quantity": "Quantidade", + "MonksActiveTiles.ctrl.volumetype": "Tipo de Volume", + "MonksActiveTiles.ctrl.onyes": "Ir para o Sim", + "MonksActiveTiles.ctrl.onno": "Ao Não Ir Para", + "MonksActiveTiles.ctrl.title": "Título", + "MonksActiveTiles.ctrl.content": "Conteúdo", + "MonksActiveTiles.ctrl.options": "Opções", + "MonksActiveTiles.ctrl.dialogtype": "Tipo de Diálogo", + "MonksActiveTiles.ctrl.image": "Imagem", + "MonksActiveTiles.ctrl.easing": "Suavização de Volume", + "MonksActiveTiles.ctrl.radius": "Raio do Efeito (Unidades de Grade)", + "MonksActiveTiles.ctrl.reset": "Redefinir quando todos usados", + "MonksActiveTiles.ctrl.slotmachine": "Caça-níqueis", + "MonksActiveTiles.ctrl.spins": "Rodadas", + "MonksActiveTiles.ctrl.rate": "Taxa de Giro", + "MonksActiveTiles.ctrl.duration": "Duração (segundos)", + "MonksActiveTiles.ctrl.anchor": "Âncora", + "MonksActiveTiles.ctrl.direction": "Direção", + "MonksActiveTiles.ctrl.doesnthave": "Não Possui", + "MonksActiveTiles.ctrl.distribution": "Distribuição", + "MonksActiveTiles.ctrl.position": "Posição", + "MonksActiveTiles.ctrl.preventsound": "Impedir que o som comece se já estiver tocando", + "MonksActiveTiles.ctrl.gmredirect": "Redirecionamento GM", + "MonksActiveTiles.ctrl.playerredirect": "Redirecionar Jogador", + "MonksActiveTiles.ctrl.fade": "Desvanecer", + "MonksActiveTiles.ctrl.transition": "Transição", + "MonksActiveTiles.ctrl.returndata": "Usar dados retornados", + "MonksActiveTiles.ctrl.select": "Alterar para", + "MonksActiveTiles.ctrl.loops": "Laços", + "MonksActiveTiles.ctrl.rotation": "Rotação", + "MonksActiveTiles.ctrl.rolldice": "Rolar o dado, se necessário", + "MonksActiveTiles.ctrl.positioning": "Posicionamento", + "MonksActiveTiles.ctrl.waitresponse": "Aguardar resposta", + "MonksActiveTiles.ctrl.landing": "Página inicial", + "MonksActiveTiles.ctrl.washcolour": "Lavar cor", + "MonksActiveTiles.ctrl.imagefile": "Arquivo de Imagem", + "MonksActiveTiles.ctrl.caption": "Legenda", + "MonksActiveTiles.ctrl.activetoken": "Apenas use fichas de jogadores ativos", + "MonksActiveTiles.ctrl.randomnumber": "Porcentagem Aleatória", + "MonksActiveTiles.ctrl.fail": "Ir para a página inicial em caso de falha", + "MonksActiveTiles.ctrl.showdice": "Mostrar Dados", + "MonksActiveTiles.ctrl.allowdisabled": "Permitir desativados", + "MonksActiveTiles.ctrl.showplaylist": "Mostrar na playlist", + "MonksActiveTiles.ctrl.htmlfile": "Arquivo HTML", + "MonksActiveTiles.ctrl.buttons": "Botões", + "MonksActiveTiles.ctrl.select-target": "Selecionar Alvo", + "MonksActiveTiles.ctrl.close-means-no": "Fechar o diálogo não aciona o redirecionamento", + "MonksActiveTiles.ctrl.fastforward": "Avançar rápido", + "MonksActiveTiles.ctrl.width": "Largura", + "MonksActiveTiles.ctrl.height": "Altura", + "MonksActiveTiles.ctrl.chatcard": "Mostrar Cartão de Chat", + "MonksActiveTiles.ctrl.method": "Método", + "MonksActiveTiles.ctrl.redirect": "Redirecionar", + "MonksActiveTiles.ctrl.variablename": "Nome da Variável", + "MonksActiveTiles.ctrl.activeuser": "Usuário Ativo", + "MonksActiveTiles.ctrl.owners": "Proprietários", + "MonksActiveTiles.ctrl.id": "ID", + "MonksActiveTiles.ctrl.trigger": "Ativar", + "MonksActiveTiles.ctrl.valuename": "Nome do Valor", + "MonksActiveTiles.ctrl.action": "Ação", + "MonksActiveTiles.ctrl.allowplayer": "Usar Jogador", + "MonksActiveTiles.ctrl.resetcollection": "Redefinir Coleção", + "MonksActiveTiles.ctrl.asimage": "Como Imagem", + "MonksActiveTiles.ctrl.offset": "Deslocamento (ms)", + "MonksActiveTiles.ctrl.pingstyle": "Estilo de Ping", + "MonksActiveTiles.ctrl.delayactions": "Atrasar ações até terminar", + "MonksActiveTiles.ctrl.time": "Tempo (min)", + "MonksActiveTiles.ctrl.landingname": "Nome da Página de Destino", + "MonksActiveTiles.ctrl.resettype": "Tipo de redefinição", + "MonksActiveTiles.ctrl.triggerremote": "Acionar no Destino", + "MonksActiveTiles.ctrl.code": "Código", + "MonksActiveTiles.ctrl.hascondition": "Tem", + "MonksActiveTiles.mode.enter": "Entrar", + "MonksActiveTiles.mode.exit": "Sair", + "MonksActiveTiles.mode.both": "Na entrada/saída", + "MonksActiveTiles.mode.movement": "Movimento", + "MonksActiveTiles.mode.click": "Clique", + "MonksActiveTiles.mode.rightclick": "Clique com o botão direito", + "MonksActiveTiles.mode.dblclick": "Clique Duplo", + "MonksActiveTiles.mode.dblrightclick": "Clique Duplo com o Botão Direito", + "MonksActiveTiles.mode.hover": "Ao passar o mouse", + "MonksActiveTiles.mode.hoverin": "Passar o mouse", + "MonksActiveTiles.mode.hoverout": "Sair do Hover", + "MonksActiveTiles.mode.manual": "Ativar Manualmente", + "MonksActiveTiles.mode.stop": "Parar dentro do Bloco", + "MonksActiveTiles.mode.round": "Rodada de Combate", + "MonksActiveTiles.mode.turn": "Início do Turno de Combate", + "MonksActiveTiles.mode.turnend": "Fim do Turno de Combate", + "MonksActiveTiles.mode.combatstart": "Início do Combate", + "MonksActiveTiles.mode.combatend": "Fim do Combate", + "MonksActiveTiles.mode.canvasready": "Mudança de Cena", + "MonksActiveTiles.mode.elevation": "Elevação", + "MonksActiveTiles.mode.rotation": "Rotação", + "MonksActiveTiles.mode.create": "Criar Token", + "MonksActiveTiles.mode.door": "Acionador de Porta", + "MonksActiveTiles.mode.darkness": "Mudança de Iluminação", + "MonksActiveTiles.mode.time": "Alteração de Tempo", + "MonksActiveTiles.restrict.all": "Permitir Todos os Tokens", + "MonksActiveTiles.restrict.player": "Apenas Fichas de Jogador", + "MonksActiveTiles.restrict.gm": "Apenas Fichas do Mestre", + "MonksActiveTiles.control.all": "Qualquer pessoa", + "MonksActiveTiles.control.player": "Apenas Jogador", + "MonksActiveTiles.control.gm": "Apenas GM", + "MonksActiveTiles.hidden.show": "Mostrar", + "MonksActiveTiles.hidden.hide": "Ocultar", + "MonksActiveTiles.hidden.toggle": "Alternar", + "MonksActiveTiles.hidden.previous": "Da Ação Anterior", + "MonksActiveTiles.activate.activate": "Ativar", + "MonksActiveTiles.activate.deactivate": "Desativar", + "MonksActiveTiles.activate.toggle": "Alternar", + "MonksActiveTiles.activate.previous": "Da Ação Anterior", + "MonksActiveTiles.add.add": "Adicionar", + "MonksActiveTiles.add.remove": "Remover", + "MonksActiveTiles.add.toggle": "Alternar", + "MonksActiveTiles.add.clear": "Limpar", + "MonksActiveTiles.for.all": "Todos", + "MonksActiveTiles.for.gm": "Apenas GM", + "MonksActiveTiles.for.token": "Acionando Proprietário do Token", + "MonksActiveTiles.for.owner": "Proprietário Atual dos Tokens", + "MonksActiveTiles.for.triggering": "Jogador que Ativou", + "MonksActiveTiles.for.players": "Apenas Jogadores", + "MonksActiveTiles.for.current": "Usuários Ativos", + "MonksActiveTiles.audiotype.all": "Sons Ambientes", + "MonksActiveTiles.audiotype.tile": "Sons de Bloco", + "MonksActiveTiles.state.open": "Aberto", + "MonksActiveTiles.state.closed": "Fechado", + "MonksActiveTiles.state.locked": "Bloqueado", + "MonksActiveTiles.state.toggle": "Alternar", + "MonksActiveTiles.state.add": "Adicionar", + "MonksActiveTiles.state.remove": "Remover", + "MonksActiveTiles.doortype.door": "Porta", + "MonksActiveTiles.doortype.secret": "Secreto", + "MonksActiveTiles.doortype.toggle": "Alternar", + "MonksActiveTiles.animate.start": "Iniciar", + "MonksActiveTiles.animate.pause": "Pausar", + "MonksActiveTiles.animate.stop": "Parar", + "MonksActiveTiles.animate.toggle": "Alternar", + "MonksActiveTiles.animate.reset": "Redefinir", + "MonksActiveTiles.animate.resume": "Continuar", + "MonksActiveTiles.pause.pause": "Pausar", + "MonksActiveTiles.pause.unpause": "Despausar", + "MonksActiveTiles.pause.toggle": "Alternar Pausa", + "MonksActiveTiles.showto.everyone": "Todos", + "MonksActiveTiles.showto.gm": "Apenas Mestre", + "MonksActiveTiles.showto.players": "Apenas Jogadores", + "MonksActiveTiles.showto.trigger": "Jogador que está acionando", + "MonksActiveTiles.attack.attack": "Ataque", + "MonksActiveTiles.attack.spell": "Magia", + "MonksActiveTiles.attack.ranged": "À distância", + "MonksActiveTiles.attack.action": "Ação", + "MonksActiveTiles.attack.weapon": "Arma", + "MonksActiveTiles.attack.melee": "Corpo a corpo", + "MonksActiveTiles.attack.consumable": "Consumível", + "MonksActiveTiles.rollmode.public": "Rolagem Pública", + "MonksActiveTiles.rollmode.private": "Rolagem Privada do Mestre", + "MonksActiveTiles.rollmode.blind": "Rolar Teste do Mestre às Cegas", + "MonksActiveTiles.rollmode.self": "Rolar para si mesmo", + "MonksActiveTiles.notification.info": "Informações", + "MonksActiveTiles.notification.warning": "Aviso", + "MonksActiveTiles.notification.error": "Erro", + "MonksActiveTiles.runas.gm": "Mestre", + "MonksActiveTiles.runas.player": "Jogador que Acionou", + "MonksActiveTiles.volumetype.globalPlaylistVolume": "Listas de reprodução", + "MonksActiveTiles.volumetype.globalAmbientVolume": "Ambiente", + "MonksActiveTiles.volumetype.globalInterfaceVolume": "Interface", + "MonksActiveTiles.volumetype.globalSoundEffectVolume": "Efeito Sonoro", + "MonksActiveTiles.dialogtype.confirm": "Confirmar", + "MonksActiveTiles.dialogtype.alert": "Alert", + "MonksActiveTiles.dialogtype.custom": "Personalizado", + "MonksActiveTiles.target.appendtarget": "Adicionar Alvos Adicionais", + "MonksActiveTiles.target.overwritetarget": "Trocar Alvos", + "MonksActiveTiles.target.removetarget": "Remover Alvo", + "MonksActiveTiles.target.clear": "Limpar Todos os Alvos", + "MonksActiveTiles.position.random": "Aleatório Dentro", + "MonksActiveTiles.position.center": "Centro", + "MonksActiveTiles.position.relative": "Relativo à Entrada", + "MonksActiveTiles.msgtype.MessageAndBubble": "Mensagem de Bate-papo e Bolha de Token", + "MonksActiveTiles.msgtype.MessageOnly": "Apenas Mensagem de Bate-Papo", + "MonksActiveTiles.msgtype.ChatBubble": "Bolha de Token Apenas", + "MonksActiveTiles.attacktype.chatcard": "Cartão de Chat", + "MonksActiveTiles.attacktype.attack": "Ataque", + "MonksActiveTiles.attacktype.use": "Usar", + "MonksActiveTiles.transition.none": "Nenhum", + "MonksActiveTiles.transition.fade": "Desaparecer", + "MonksActiveTiles.transition.blur": "Desfoque", + "MonksActiveTiles.transition.slide-left": "Deslizar para a Esquerda", + "MonksActiveTiles.transition.slide-up": "Deslizar para cima", + "MonksActiveTiles.transition.slide-right": "Deslizar para a direita", + "MonksActiveTiles.transition.slide-down": "Deslizar para Baixo", + "MonksActiveTiles.transition.slide-random": "Slide Aleatório", + "MonksActiveTiles.transition.bump-left": "Empurrar para a Esquerda", + "MonksActiveTiles.transition.bump-up": "Bump Up", + "MonksActiveTiles.transition.bump-right": "Empurrar para a Direita", + "MonksActiveTiles.transition.bump-down": "Bump Down", + "MonksActiveTiles.transition.bump-random": "Bump Aleatório", + "MonksActiveTiles.transition.slotmachine": "Caça-níqueis", + "MonksActiveTiles.distribute.everyone": "Os personagens recebem uma cópia de todos os itens", + "MonksActiveTiles.distribute.single": "Os personagens recebem um único item", + "MonksActiveTiles.distribute.evenall": "Todos os itens distribuídos entre os personagens", + "MonksActiveTiles.distribute.even": "Distribuído uniformemente, os restantes são passados adiante", + "MonksActiveTiles.ping.pulse": "Pulso", + "MonksActiveTiles.ping.alert": "Alerta", + "MonksActiveTiles.ping.chevron": "Chevron", + "MonksActiveTiles.ping.arrow": "Seta", + "MonksActiveTiles.resettype.everything": "Tudo", + "MonksActiveTiles.resettype.token": "Token", + "MonksActiveTiles.msg.prevent-teleport": "Teleportar para fora do mapa foi impedido", + "MonksActiveTiles.msg.prevent-movement": "Movimentar-se para fora do mapa foi impedido", + "MonksActiveTiles.msg.invalid-entity": "Tipo de Entidade Inválido", + "MonksActiveTiles.msg.invalid-location": "Local inválido, por favor selecione na mesma Cena", + "MonksActiveTiles.msg.select-location": "Por favor, selecione uma localização nesta cena", + "MonksActiveTiles.msg.select-location-any": "Por favor, selecione uma localização nesta cena ou em uma cena diferente", + "MonksActiveTiles.msg.select-entity": "Por favor, selecione uma entidade", + "MonksActiveTiles.msg.select-user": "Por favor, selecione um usuário", + "MonksActiveTiles.msg.selectlocation": "Selecione uma localização", + "MonksActiveTiles.msg.selectentity": "Selecione uma entidade", + "MonksActiveTiles.msg.usetile": "Use este bloco", + "MonksActiveTiles.msg.usetoken": "Use o token de acionamento", + "MonksActiveTiles.msg.useplayers": "Usar tokens de jogador", + "MonksActiveTiles.msg.useplayersjournal": "Usar o diário do jogador", + "MonksActiveTiles.msg.usewithin": "Use entidades dentro do tile de acionamento", + "MonksActiveTiles.msg.usewithinwall": "Acione o Bloco sob esta porta", + "MonksActiveTiles.msg.useprevious": "Usar a coleção atual destas ações", + "MonksActiveTiles.msg.usepreviouslocation": "Usar a localização atual desta ação", + "MonksActiveTiles.msg.usecontrolled": "Use Tokens atualmente controlados", + "MonksActiveTiles.msg.useorigin": "Usar destino original", + "MonksActiveTiles.msg.noteleporttoken": "Sem ficha para teletransporte", + "MonksActiveTiles.msg.setposition": "Usar visualização atual", + "MonksActiveTiles.msg.usetagger": "Usar Tagger", + "MonksActiveTiles.msg.itempiles": "A funcionalidade de soltar itens das Telhas Ativas entra em conflito com os Montes de Itens, a configuração foi desativada.", + "MonksActiveTiles.msg.useplayerlocation": "Usar localização do token dos jogadores", + "MonksActiveTiles.msg.currentlyplaying": "Atualmente em reprodução", + "MonksActiveTiles.msg.useusers": "Usar jogadores", + "MonksActiveTiles.msg.usescene": "Usar cena ativa", + "MonksActiveTiles.allow-player.name": "Permitir jogadores", + "MonksActiveTiles.allow-player.hint": "Permite que os jogadores ativem Blocos se não houver um Mestre presente.", + "MonksActiveTiles.use-core-macro.name": "Usar Macro de Núcleo Executar", + "MonksActiveTiles.use-core-macro.hint": "A execução do macro principal não passa todas as informações disponíveis, então Active Blocos lida com a execução dos macros. Ative novamente se estiver causando problemas.'", + "MonksActiveTiles.drop-item.name": "Soltar item no Canvas", + "MonksActiveTiles.drop-item.hint": "Permite que os itens soltos no canvas sejam criados como Blocos Ativos", + "MonksActiveTiles.drop-scene.name": "Drop Scene on Canvas", + "MonksActiveTiles.drop-scene.hint": "Permitir que cenas arrastadas para o canvas sejam criadas como Blocos Ativos", + "MonksActiveTiles.allow-door.name": "Acionadores de Porta", + "MonksActiveTiles.allow-door.hint": "Permitir que portas acionem Blocos", + "MonksActiveTiles.teleport-wash.name": "Mostrar Teleport Wash", + "MonksActiveTiles.teleport-wash.hint": "Quando um token se teletransporta, adicione um efeito de lavagem na tela para evitar desorientação enquanto a Cena muda.", + "MonksActiveTiles.teleport-colour.name": "Teleportar Cor de Lavagem", + "MonksActiveTiles.teleport-colour.hint": "Cor a ser usada para o fundo ao fundo quando um token teleporta", + "MonksActiveTiles.default-trigger.name": "Gatilho Padrão", + "MonksActiveTiles.default-trigger.hint": "Gatilho padrão a ser usado ao criar um Bloco", + "MonksActiveTiles.default-restricted.name": "Restrito Padrão", + "MonksActiveTiles.default-restricted.hint": "Restrição padrão a ser usada ao criar um Bloco", + "MonksActiveTiles.default-controlled.name": "Controlado Padrão", + "MonksActiveTiles.default-controlled.hint": "Controlado por padrão para usar ao criar um Bloco", + "MonksActiveTiles.show-help.name": "Mostrar Dicas", + "MonksActiveTiles.show-help.hint": "Mostra dicas de ação úteis para campos que possuem valores complexos", + "MonksActiveTiles.prevent-when-paused.name": "Impedir quando pausado", + "MonksActiveTiles.prevent-when-paused.hint": "Impede que os jogadores ativem os Blocos quando o jogo está pausado.", + "MonksActiveTiles.allow-door-passthrough.name": "Permitir clique através da porta", + "MonksActiveTiles.allow-door-passthrough.hint": "Permitir que os Blocos sob uma porta ainda sejam acionados se a porta for clicada", + "MonksActiveTiles.drop-item-size.name": "Tamanho do Item Descartado", + "MonksActiveTiles.drop-item-size.hint": "Defina o tamanho do item solto", + "MonksActiveTiles.show-landing.name": "Mostrar Destaque de Destino", + "MonksActiveTiles.show-landing.hint": "Destaque as ações que acontecem dentro dos landings", + "MonksActiveTiles.drop-macro.name": "Macro de Despejo no Canvas", + "MonksActiveTiles.drop-macro.hint": "Permitir que macros soltas na tela sejam criadas como Blocos Ativos", + "MonksActiveTiles.tile-edit.name": "Permitir Edição de Modelo de Bloco", + "MonksActiveTiles.tile-edit.hint": "Permitir a edição de Modelos de Bloco, eu recomendaria fortemente não usar isso a menos que você tenha certeza do que está fazendo", + "MonksActiveTiles.tabs.Setup": "Configuração", + "MonksActiveTiles.tabs.Actions": "Ações", + "MonksActiveTiles.tabs.Images": "Imagens", + "MonksActiveTiles.history.ViewHistory": "Ver histórico", + "MonksActiveTiles.history.ViewVariables": "Visualizar Variáveis", + "MonksActiveTiles.history.Token": "Token", + "MonksActiveTiles.history.When": "Quando", + "MonksActiveTiles.history.How": "Como", + "MonksActiveTiles.history.Who": "Quem", + "MonksActiveTiles.history.Name": "Nome", + "MonksActiveTiles.history.Value": "Valor" +} \ No newline at end of file diff --git a/module.json b/module.json index 5c23992..121829a 100644 --- a/module.json +++ b/module.json @@ -1,7 +1,7 @@ { "title": "Monk's Active Tile Triggers", "description": "Want to teleport, or open doors, or hide characters, or display a message, or play a sound, or change a token's elevation when a token walks over a tile... now you can", - "version": "12.01", + "version": "12.02", "authors": [ { "name": "IronMonk", @@ -34,6 +34,11 @@ "lang": "pl", "name": "polski", "path": "lang/pl.json" + }, + { + "lang": "pt-BR", + "name": "Português", + "path": "lang/pt-BR.json" } ], "packs": [ @@ -56,21 +61,20 @@ "css/monks-active-tiles.css" ], "url": "https://github.com/ironmonk88/monks-active-tiles", - "download": "https://github.com/ironmonk88/monks-active-tiles/archive/12.01.zip", + "download": "https://github.com/ironmonk88/monks-active-tiles/archive/12.02.zip", "manifest": "https://github.com/ironmonk88/monks-active-tiles/releases/latest/download/module.json", "bugs": "https://github.com/ironmonk88/monks-active-tiles/issues", - "allowBugReporter": true, "id": "monks-active-tiles", "compatibility": { "minimum": "12", "verified": "12" }, - "name": "monks-active-tiles", - "minimumCoreVersion": "12", - "compatibleCoreVersion": "12", "documentTypes": { "RegionBehavior": { "triggerTile": {} } + }, + "flags": { + "allowBugReporter": true } } \ No newline at end of file diff --git a/monks-active-tiles.js b/monks-active-tiles.js index eb651f3..4e81ba5 100644 --- a/monks-active-tiles.js +++ b/monks-active-tiles.js @@ -114,6 +114,8 @@ export class MonksActiveTiles { static batch = new BatchManager(); + static tileTriggerCache = { ready: [], hover: [], time: [], darkness: [], lighting: [], click: [], combat: [] }; + static timeout(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } @@ -160,6 +162,7 @@ export class MonksActiveTiles { 'manual': i18n("MonksActiveTiles.mode.manual"), 'door': i18n("MonksActiveTiles.mode.door"), 'darkness': i18n("MonksActiveTiles.mode.darkness"), + 'lighting': i18n("MonksActiveTiles.mode.darknesschange"), 'time': i18n("MonksActiveTiles.mode.time") } }; @@ -190,6 +193,30 @@ export class MonksActiveTiles { } } + static findTileTriggers = async () => { + MonksActiveTiles.tileTriggerCache = { ready: [], hover: [], time: [], darkness: [], lighting: [], click: [], combat: [] }; + for (let tile of canvas.scene.tiles.contents) { + let triggerData = tile.flags["monks-active-tiles"]; + if (triggerData && triggerData.active) { + let triggers = MonksActiveTiles.getTrigger(triggerData?.trigger); + if (triggers.includes("ready")) + MonksActiveTiles.tileTriggerCache["ready"].push(tile); + if (triggers.includes("hoverin") || triggers.includes("hoverout")) + MonksActiveTiles.tileTriggerCache["hover"].push(tile); + if (triggers.includes("time")) + MonksActiveTiles.tileTriggerCache["time"].push(tile); + if (triggers.includes("darkness")) + MonksActiveTiles.tileTriggerCache["darkness"].push(tile); + if (triggers.includes("lighting")) + MonksActiveTiles.tileTriggerCache["lighting"].push(tile); + if (triggers.includes("click") || triggers.includes("dblclick") || triggers.includes("rightclick") || triggers.includes("dblrightclick")) + MonksActiveTiles.tileTriggerCache["click"].push(tile); + if (triggers.includes("combatstart") || triggers.includes("round") || triggers.includes("turn") || triggers.includes("turnend") || triggers.includes("combatend")) + MonksActiveTiles.tileTriggerCache["combat"].push(tile); + } + } + } + /* static drawingPoints(drawing) { let points = []; @@ -431,7 +458,7 @@ export class MonksActiveTiles { return triggers; } - static getForPlayers(forId, args) { + static getForPlayers(forId, args, options = {}) { switch (forId) { case "all": case "everyone": @@ -439,7 +466,7 @@ export class MonksActiveTiles { case "gm": return game.users.filter(u => u.isGM).map(u => u.id); case "players": - return game.users.filter(u => !u.isGM && u.active).map(u => u.id); + return game.users.filter(u => !u.isGM && (options.notactive || u.active)).map(u => u.id); case "previous": case "current": return args.value.users || []; @@ -1486,7 +1513,7 @@ export class MonksActiveTiles { } static async animateEntity(entity, from, animation) { - let object = entity.mesh || entity.shape || entity; + let object = entity.mesh || entity.shape || entity.field || entity; let to = { x: entity.document.x, y: entity.document.y, @@ -1560,7 +1587,8 @@ export class MonksActiveTiles { attribute.parent.object.visible = true; if (attribute.parent instanceof AmbientLight) { attribute.parent.document[attribute.attribute] = realval; - attribute.parent.updateSource(); + attribute.parent.initializeLightSource({ deleted: false }); + //attribute.parent.updateSource(); } } @@ -1905,9 +1933,9 @@ export class MonksActiveTiles { t.bg.clear(); } t.mesh.texture = tex; - t.mesh.scale.x = t.width / t.texture.width; - t.mesh.scale.y = t.height / t.texture.height; - t.mesh.refresh(); + //t.mesh.scale.x = t.width / t.texture.width; + //t.mesh.scale.y = t.height / t.texture.height; + t._refreshMesh(); } else if (t.mesh) { canvas.primary.removeTile(t); t.mesh = null; @@ -2014,13 +2042,14 @@ export class MonksActiveTiles { if (["/save", "/damage", "/skill", "/check", "/tool"].includes((command || "").trim())) return match; - let roll = await Roll.create(formula).roll({async: true}); + let roll = await Roll.create(formula)._evaluate({async: true}); if (chatMessage) { const cls = ChatMessage.implementation; const speaker = cls.getSpeaker({ token: token }); let mode = command?.replace(/[^A-Za-z]/g, ""); + if (mode == "br") mode = "blindroll"; if (!["publicroll", "gmroll", "blindroll", "selfroll"].includes(mode)) mode = rollMode; mode = mode || rollMode; @@ -2157,7 +2186,12 @@ export class MonksActiveTiles { single: false, label: "BEHAVIOR.TYPES.triggerTile.FIELDS.uuid.label", hint: "BEHAVIOR.TYPES.triggerTile.FIELDS.uuid.hint" - }) + }), + usetiletrigger: new foundry.data.fields.BooleanField({ + initial: true, + label: "BEHAVIOR.TYPES.triggerTile.FIELDS.usetiletrigger.label", + hint: "BEHAVIOR.TYPES.triggerTile.FIELDS.usetiletrigger.hint" + }), } } async _handleRegionEvent(event) { @@ -2184,7 +2218,33 @@ export class MonksActiveTiles { return; } - let result = await doc.trigger({ tokens: tokens, method: 'region', options: { value: { region: this.region } } }) || {}; + let method = 'region'; + if (this.usetiletrigger) { + if (event.name == "tokenMoveIn" || event.name == "tokenEnter") { + method = "enter"; + } else if (event.name == "tokenMoveOut" || event.name == "tokenExit") { + method = "exit"; + } else if (event.name == "tokenTurnStart") { + method = "turn"; + } else if (event.name == "tokenTurnEnd") { + method = "turnend"; + } else if (event.name == "tokenRoundStart") { + method = "round"; + } + } + + let pt = event.data.destination; + if (event.data.segments?.length > 0) { + pt = event.data.segments[0].to; + } + let result = await doc.trigger({ + tokens: tokens, method, pt, options: { + original: event.data.destination, + elevation: event.data.destination?.elevation, + src: event.data.origin, + value: { region: this.region, regionData: event.data } + } + }) || {}; //foundry.utils.mergeObject(results, result); //if (result?.stoptriggers) // break; @@ -2683,7 +2743,7 @@ export class MonksActiveTiles { entities = game.canvas.tokens.placeables.filter(t => t.document.actorId == game.user.character?.id); } - for (let tile of canvas.scene.tiles) { + for (let tile of MonksActiveTiles.tileTriggerCache.hover) { let triggerData = tile.flags["monks-active-tiles"]; let triggers = MonksActiveTiles.getTrigger(triggerData?.trigger); @@ -3489,7 +3549,7 @@ export class MonksActiveTiles { if (data.type == 'all') { game.audio.playing.forEach((s) => s.stop()); } else { - if (data.users.includes(game.user.id)) { + if (data.users?.includes(game.user.id)) { let tile = await fromUuid(data.tileid); if (tile) { if (tile.soundeffect != undefined) { @@ -3844,7 +3904,7 @@ export class MonksActiveTiles { if (actor) { let sheet = actor.sheet; if (sheet) { - sheet._onDropItem({ preventDefault: () => { } }, { type: "Item", uuid: data.uuid, data: data.item }); + sheet._onDropItem({ preventDefault: () => { }, target: { closest: () => { return false; } } }, { type: "Item", uuid: data.uuid, data: data.item }); } } } @@ -3900,7 +3960,7 @@ export class MonksActiveTiles { } static async checkClick(pt, clicktype = "click", event) { - let tiles = canvas.scene.tiles.map((tile) => { + let tiles = MonksActiveTiles.tileTriggerCache.click.map((tile) => { return tile.checkClick(pt, clicktype, event); }).filter(t => !!t) .sort((a, b) => { @@ -5138,8 +5198,10 @@ export class MonksActiveTiles { } TileDocument.prototype.addHistory = async function (tokenid, method, userId) { - let tileHistory = this.flags["monks-active-tiles"]?.history || {}; + let tileHistory = foundry.utils.duplicate(this.flags["monks-active-tiles"]?.history || {}); let data = { id: makeid(), who: userId, how: method, when: Date.now() }; + if (!tokenid) + tokenid = "_blank"; if (!tileHistory[tokenid]) tileHistory[tokenid] = { tokenid: tokenid, triggered: [data] }; else @@ -5148,13 +5210,14 @@ export class MonksActiveTiles { //this.flags = foundry.utils.mergeObject(this.flags, { "monks-active-tiles.history": tileHistory }); //Due to a race condition we need to set the actual value before trying to save it try { - await this.setFlag("monks-active-tiles", "history", foundry.utils.duplicate(this.flags["monks-active-tiles"]?.history || tileHistory)); + //await this.unsetFlag("monks-active-tiles", "history"); + await this.update({ "flags.monks-active-tiles.history": tileHistory }, { diff: false }); canvas.perception.update({ refreshLighting: true, refreshSounds: true, initializeVision: true, refreshVision: true, - refreshTiles: true + refreshOcclusion: true }, true); } catch {} } @@ -5214,7 +5277,7 @@ export class MonksActiveTiles { let user = game.users.find(p => p.id == data.who); stats.list.push(foundry.utils.mergeObject(data, { tokenid: k, - name: token?.name || (k == "" ? "" : 'Unknown'), + name: token?.name || (k == "_blank" ? "[No tokens selected]" : 'Unknown'), username: user?.name || 'Unknown', whenfrmt: time, howname: MonksActiveTiles.triggerModes[data.how] || data.how @@ -5294,7 +5357,12 @@ export class MonksActiveTiles { html += ``; } } else { - Object.entries(group.groups).forEach(e => option(...e)); + if (game.system.id == "burningwheel") { + const a = RegExp.escape(Handlebars.escapeExpression(choices)) + , s = new RegExp(` value=["']${a}["']`); + return options.fn(this).replace(s, "$& selected") + } else + Object.entries(choices).forEach(e => option(...e)); } return new Handlebars.SafeString(html); } @@ -5812,7 +5880,8 @@ Hooks.on("preUpdateCombat", async function (combat, delta) { Hooks.on("updateCombat", async function (combat, delta) { if (combat.started && game.user.isGM && combat.scene) { - let tiles = combat.scene.tiles.map(tile => { + let sceneTiles = combat.scene.id == canvas.scene.id ? MonksActiveTiles.tileTriggerCache.combat : combat.scene.tiles; + let tiles = sceneTiles.map(tile => { let triggerData = tile.flags["monks-active-tiles"]; let triggers = MonksActiveTiles.getTrigger(triggerData?.trigger); if (triggerData?.active && triggerData.actions?.length > 0) { @@ -5994,7 +6063,7 @@ Hooks.on("dropCanvasData", async (canvas, data, options, test) => { let dest = { x: data.x - (size / 2), y: data.y - (size / 2) }; let td = foundry.utils.mergeObject(dest, { - img: item.img, + texture: { src: item.img }, width: size, height: size, flags: { @@ -6033,7 +6102,7 @@ Hooks.on("dropCanvasData", async (canvas, data, options, test) => { let dest = { x: data.x - (size / 2), y: data.y - (size / 2) }; let td = foundry.utils.mergeObject(dest, { - img: scene.background?.src, + texture: { src: scene.background?.src }, width: size, height: size, flags: { @@ -6110,9 +6179,10 @@ Hooks.on("renderTileConfig", (app, html, data) => { }); Hooks.on("canvasReady", async () => { + MonksActiveTiles.findTileTriggers(); $('#board').css({ 'cursor': '' }); MonksActiveTiles.hoveredTiles = new Set(); - let tiles = canvas.scene.tiles.map(tile => { + let tiles = MonksActiveTiles.tileTriggerCache.ready.map(tile => { let triggerData = tile.flags["monks-active-tiles"]; let triggers = MonksActiveTiles.getTrigger(triggerData?.trigger); if (triggerData?.active && triggers.includes("ready")) { @@ -6141,6 +6211,7 @@ Hooks.on("openJournalEntry", (document, options, userId) => { }); Hooks.on('updateTile', async (document, update, options, userId) => { + MonksActiveTiles.findTileTriggers(); if (update?.texture?.src != undefined || foundry.utils.getProperty(update, "flags.monks-active-tiles.usealpha") != undefined) { let triggerData = document.flags["monks-active-tiles"]; if (triggerData?.usealpha) { @@ -6151,10 +6222,15 @@ Hooks.on('updateTile', async (document, update, options, userId) => { } }); -Hooks.on('preUpdateWall', async (document, update, options, userId) => { - if (update.door != undefined && (document.door == 2 || update.door == 2)) - document._wallchange = "secret"; +Hooks.on('createTile', async (document, options, userId) => { + MonksActiveTiles.findTileTriggers(); +}); +Hooks.on('deleteTile', async (document, options, userId) => { + MonksActiveTiles.findTileTriggers(); +}); + +Hooks.on('preUpdateWall', async (document, update, options, userId) => { if (update.ds != undefined) { if (document.ds == 2 || update.ds == 2) document._wallchange = "lock"; @@ -6164,6 +6240,9 @@ Hooks.on('preUpdateWall', async (document, update, options, userId) => { document._wallchange = "open"; } + if ((update.door != undefined || update.ds == 0) && (document.door == 2 || update.door == 2)) + document._wallchange = "secret"; + let entity = foundry.utils.getProperty(update, "flags.monks-active-tiles.entity"); if (!!entity && typeof entity == "string") { foundry.utils.setProperty(update, "flags.monks-active-tiles.entity", JSON.parse(entity)); @@ -6172,7 +6251,7 @@ Hooks.on('preUpdateWall', async (document, update, options, userId) => { Hooks.on("globalAmbientVolumeChanged", (volume) => { if (!game.modules.get("monks-sound-enhancements")?.active) { - for (let tile of canvas.scene.tiles) { + for (let tile of canvas.scene.tiles.contents) { for (let sound of Object.values(tile.soundeffect || {})) { if (sound.effectiveVolume != undefined) { sound.volume = volume * (sound.effectiveVolume ?? 1); @@ -6183,7 +6262,7 @@ Hooks.on("globalAmbientVolumeChanged", (volume) => { }); Hooks.on("globalSoundEffectVolumeChanged", (volume) => { - for (let tile of canvas.scene.tiles) { + for (let tile of canvas.scene.tiles.contents) { for (let sound of Object.values(tile.soundeffect || {})) { if (sound.effectiveVolume != undefined) { sound.volume = volume * (sound.effectiveVolume ?? 1); @@ -6230,7 +6309,8 @@ Hooks.on("refreshToken", (token) => { Hooks.on("updateScene", async (scene, data, options) => { if (data.environment?.darknessLevel != undefined) { - let tiles = (scene?.tiles || []).map(tile => { + let sceneTile = scene.id == canvas.scene.id ? MonksActiveTiles.tileTriggerCache.darkness : scene?.tiles; + let tiles = (sceneTile || []).map(tile => { let triggerData = tile.flags["monks-active-tiles"]; let triggers = MonksActiveTiles.getTrigger(triggerData?.trigger); if (triggerData?.active && triggers.includes('darkness')) { @@ -6243,7 +6323,7 @@ Hooks.on("updateScene", async (scene, data, options) => { tokens = tokens.filter(t => !this.object.document.hasTriggered(t.id)); //Trigger this Tile - return { tile, args: { tokens: tokens, method: 'darkness', options: { darkness: data.darkness } } }; + return { tile, args: { tokens: tokens, method: 'darkness', options: { darkness: data.environment?.darknessLevel } } }; } return null; }).filter(t => !!t).sort((a, b) => (b.tile.sort ?? b.tile.z) - (a.tile.sort ?? a.tile.z)); @@ -6255,22 +6335,38 @@ Hooks.on("updateScene", async (scene, data, options) => { } }); +Hooks.on("lightingRefresh", async (lightinEffect) => { + let tiles = MonksActiveTiles.tileTriggerCache.lighting.map(tile => { + let triggerData = tile.flags["monks-active-tiles"]; + + if (setting("prevent-when-paused") && game.paused && !game.user.isGM && triggerData.allowpaused !== true) + return; + + //Trigger this Tile + return { tile, args: { tokens: [], method: 'lighting', options: { darkness: canvas.scene.environment?.darknessLevel } } }; + }).filter(t => !!t).sort((a, b) => (b.tile.sort ?? b.tile.z) - (a.tile.sort ?? a.tile.z)); + for (let t of tiles) { + let triggerResult = await t.tile.trigger(t.args); + if (triggerResult?.stoptriggers) + break; + }; +}); + Hooks.on('updateWorldTime', async (worldTime) => { - let tiles = canvas.scene.tiles.map(tile => { + let tiles = MonksActiveTiles.tileTriggerCache.time.map(tile => { let triggerData = tile.flags["monks-active-tiles"]; - let triggers = MonksActiveTiles.getTrigger(triggerData?.trigger); - if (triggerData?.active && triggers.includes('time')) { - if (setting("prevent-when-paused") && game.paused && !game.user.isGM && triggerData.allowpaused !== true) - return; - let tokens = canvas.tokens.controlled.map(t => t.document); + if (setting("prevent-when-paused") && game.paused && !game.user.isGM && triggerData.allowpaused !== true) + return; + + let tokens = canvas.tokens.controlled.map(t => t.document); - if (triggerData.pertoken) - tokens = tokens.filter(t => !this.object.document.hasTriggered(t.id)); + if (triggerData.pertoken) + tokens = tokens.filter(t => !this.object.document.hasTriggered(t.id)); + + //Trigger this Tile + return { tile, args: { tokens: tokens, method: 'time', options: { time: MonksActiveTiles.getWorldTime(worldTime) } } }; - //Trigger this Tile - return { tile, args: { tokens: tokens, method: 'time', options: { time: MonksActiveTiles.getWorldTime(worldTime) } } }; - } return null; }).filter(t => !!t).sort((a, b) => (b.tile.sort ?? b.tile.z) - (a.tile.sort ?? a.tile.z)); for (let t of tiles) { diff --git a/packs/active-tile-macros.db b/packs/active-tile-macros.db index 7527ae7..f792993 100644 --- a/packs/active-tile-macros.db +++ b/packs/active-tile-macros.db @@ -37,7 +37,7 @@ "author": "NoP0yFyEU0MJHD4O", "img": "icons/svg/dice-target.svg", "scope": "global", - "command": "/*\nSo if you forget to set the Tile to active while you're creating them\nor if you want to reset the scene you can use this macro to re-activate\nall the Active Tiles.\n*/\nlet count = 0;\nfor (let tile of canvas.scene.tiles){\n if (!foundry.utils.getProperty(tile, \"flags.monks-active-tiles\")?.active){\n await tile.setFlag('monks-active-tiles', 'active', true);\n count++;\n }\n}\nui.notifications.info(`Activated ${count} tiles`);", + "command": "/*\nSo if you forget to set the Tile to active while you're creating them\nor if you want to reset the scene you can use this macro to re-activate\nall the Active Tiles.\n*/\nlet count = 0;\nfor (let tile of canvas.scene.tiles.contents){\n if (!foundry.utils.getProperty(tile, \"flags.monks-active-tiles\")?.active){\n await tile.setFlag('monks-active-tiles', 'active', true);\n count++;\n }\n}\nui.notifications.info(`Activated ${count} tiles`);", "flags": { "advanced-macros": { "runAsGM": false }, "core": { "sourceId": "Macro.sxbiqFyIjwSEgMmp" }