From 308ab638f5aa2c204d4d66532c841ad51e493a12 Mon Sep 17 00:00:00 2001 From: kckaiwei Date: Tue, 12 Jan 2021 16:23:16 -0500 Subject: [PATCH 1/2] [DOC] Updating changelogs to prepare for new release --- CHANGELOG.md | 4 ++++ dist/module.json | 2 +- dist/scripts/turnmarker.js | 2 +- dist/scripts/turnmarker.js.map | 2 +- dist/templates/updateWindow.html | 12 +++++++++--- src/module.json | 2 +- src/templates/updateWindow.html | 12 +++++++++--- 7 files changed, 26 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22c1286..eaee604 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# 2.7.1 +- Fixed issue with start markers being left over +- Fixed issue with turn marker showing when combat has not started + # 2.7.0 - - Added Turn announcement filtering - Turns announced for everyone diff --git a/dist/module.json b/dist/module.json index 7146b4b..cd97c5d 100644 --- a/dist/module.json +++ b/dist/module.json @@ -3,7 +3,7 @@ "title": "Turn Marker", "description": "Displays a (optionally animated) marker on the token who's active turn it is. Originally by Brunhine", "author": "kckaiwei", - "version": "2.7.0", + "version": "2.7.1", "minimumCoreVersion": "0.7.5", "compatibleCoreVersion": "0.7.9", "esmodules": [ diff --git a/dist/scripts/turnmarker.js b/dist/scripts/turnmarker.js index 5c4e33b..abe6fca 100644 --- a/dist/scripts/turnmarker.js +++ b/dist/scripts/turnmarker.js @@ -1,3 +1,3 @@ /*! For license information please see turnmarker.js.LICENSE.txt */ -(()=>{"use strict";var e={"./src/scripts/chatter.js":(e,t,a)=>{a.r(t),a.d(t,{Chatter:()=>n});var s=a("./src/scripts/settings.js");class n{static sendTurnMessage(e,t=!1){let a=[];e.players.forEach((e=>{a.push(e.name)})),0==a.length&&a.push("GM");let n=e.actor.name,r=n;s.Settings.getAnnounceTokenName()&&(n=e.token.name,r=e.name),t&&!e.actor.hasPlayerOwner&&(n="???"),ChatMessage.create({speaker:{actor:e.actor,alias:r},content:`
${this.placeImage(e)}\n
\n

${n}'s Turn

\n

${a.join(" - ")}

\n
\n
Turn Marker`})}static placeImage(e){if(s.Settings.getIncludeAnnounceImage()){let t=e.img;return e.flags.core&&e.flags.core.thumb&&(t=e.flags.core.thumb),`
`}return""}}},"./src/scripts/marker.js":(e,t,a)=>{a.r(t),a.d(t,{Marker:()=>i});var s=a("./src/scripts/markeranimation.js"),n=a("./src/scripts/settings.js"),r=a("./src/scripts/utils.js");class i{static async placeTurnMarker(e,t){if(t)return this.moveMarkerToToken(e,t),t;if(this.clearAllMarkers(),n.Settings.getTurnMarkerEnabled()){let t=(0,r.findTokenById)(e),a=(n.Settings.getRatio(),this.getImageDimensions(t)),s=this.getImageLocation(t),i=new Tile({img:n.Settings.getImagePath(),width:a.w,height:a.h,x:s.x,y:s.y,z:900,rotation:0,hidden:t.data.hidden,locked:!1,flags:{turnMarker:!0}});return(await canvas.scene.createEmbeddedEntity("Tile",i.data))._id}return null}static async deleteStartMarker(){const e=canvas.scene.getEmbeddedCollection("Tile").filter((e=>e.flags.startMarker)).map((e=>e._id));await canvas.scene.deleteEmbeddedEntity("Tile",e)}static async placeStartMarker(e,t,a){if(n.Settings.getStartMarkerEnabled()){let s=(0,r.findTokenById)(e),i=this.getImageDimensions(s),o=this.getImageLocation(s,!1,t,a),m=new Tile({img:n.Settings.getStartMarker(),width:i.w,height:i.h,x:o.x,y:o.y,z:900,rotation:0,hidden:s.data.hidden,locked:!1,flags:{startMarker:!0}});game.user.isGM&&(canvas.scene.createEmbeddedEntity("Tile",m.data),canvas.scene.setFlag(r.FlagScope,r.Flags.startMarkerPlaced,!0))}}static async moveMarkerToToken(e,t){let a=(0,r.findTokenById)(e),s=(n.Settings.getRatio(),this.getImageDimensions(a)),i=this.getImageLocation(a);await canvas.scene.updateEmbeddedEntity("Tile",{_id:t,width:s.w,height:s.h,x:i.x,y:i.y,hidden:a.data.hidden})}static async clearAllMarkers(){let e=canvas.scene.getEmbeddedCollection("Tile");for(let t of e)(t.flags.turnMarker||t.flags.startMarker)&&await canvas.scene.deleteEmbeddedEntity("Tile",t._id)}static updateImagePath(){if(game.user.isGM){let e=canvas.tiles.placeables.find((e=>1==e.data.flags.turnMarker));e&&canvas.scene.updateEmbeddedEntity("Tile",{_id:e.id,img:n.Settings.getImagePath()})}}static reset(e){s.MarkerAnimation.stopAnimation(e),this.clearAllMarkers()}static getImageDimensions(e,t=!1){let a=t?1:n.Settings.getRatio(),s=0,r=0;switch(canvas.grid.type){case 2:case 3:s=r=e.h*a;break;case 4:case 5:s=r=e.w*a;break;default:s=e.w*a,r=e.h*a}return{w:s,h:r}}static getImageLocation(e,t=!1,a=null,s=null){let r=t?1:n.Settings.getRatio(),i=0,o=0,m=e.center.x,g=e.center.y;switch(a&&s&&(m=Math.abs(e.center.x-e.x)+a,g=Math.abs(e.center.y-e.y)+s),canvas.grid.type){case 2:case 3:i=m-e.h*r/2,o=g-e.h*r/2;break;case 4:case 5:i=m-e.w*r/2,o=g-e.w*r/2;break;default:i=m-e.w*r/2,o=g-e.h*r/2}return{x:i,y:o}}}},"./src/scripts/markeranimation.js":(e,t,a)=>{a.r(t),a.d(t,{MarkerAnimation:()=>n});var s=a("./src/scripts/settings.js");class n{static startAnimation(e,t){let a=canvas.scene.getEmbeddedEntity("Tile",t);return e=this.animateRotation.bind(a),canvas.app.ticker.add(e),e}static stopAnimation(e){canvas.app.ticker.remove(e)}static animateRotation(e){let t=canvas.tiles.placeables.find((e=>1==e.data.flags.turnMarker));if(t&&t.data.img){let a=s.Settings.getInterval()/1e4;try{t.tile.img.rotation+=a*e}catch(e){}}}}},"./src/scripts/settings.js":(e,t,a)=>{a.r(t),a.d(t,{imageTitles:()=>M,announcedActorOptions:()=>y,Settings:()=>v});var s=a("./src/scripts/marker.js"),n=a("./src/scripts/settingsForm.js"),r=a("./src/scripts/utils.js");const i="tm-version",o="ratio",m="animation",g="interval",c="announce-turn",d="announce-Actors",l="announce-image",u="announce-token",p="image",h="customimage",k="turnmarker-enabled",f="startMarker-enabled",b="startMarker-custom",M=["Runes of Incendium by Rin","Runes of the Cultist by Rin","Runes of Regeneration by Rin","Runes of the Cosmos by Rin","Runes of Earthly Dust by Rin","Runes of Reality by Rin","Runes of the Believer by Rin","Runes of the Mad Mage by Rin","Runes of the Blue Sky by Rin","Runes of the Universe by Rin","Runes of Prosperity by Rin"],y=["Announce for all","Announce for players","Announce for GM-controlled","Announce all but hide GM-controlled names"];class v{static getVersion(){return game.settings.get(r.modName,i)}static setVersion(e){game.settings.set(r.modName,i,e)}static getRatio(){return game.settings.get(r.modName,o)}static setRatio(e){game.settings.set(r.modName,o,e)}static getShouldAnimate(){return game.settings.get(r.modName,m)}static getInterval(){return game.settings.get(r.modName,g)}static shouldAnnounceTurns(){return game.settings.get(r.modName,c)}static setShouldAnnounceTurns(e){game.settings.set(r.modName,c,e)}static getAnnounceActors(){return game.settings.get(r.modName,d)}static setAnnounceActors(e){return game.settings.set(r.modName,d,e)}static getAnnounceTokenName(){return game.settings.get(r.modName,u)}static setAnnounceTokenName(e){return game.settings.set(r.modName,u,e)}static getIncludeAnnounceImage(){return game.settings.get(r.modName,l)}static setIncludeAnnounceImage(e){game.settings.set(r.modName,l,e)}static getImageIndex(){return game.settings.get(r.modName,p)}static getStartMarker(){return""==game.settings.get(r.modName,b).trim()?"modules/turnmarker/assets/start.png":game.settings.get(r.modName,b)}static getTurnMarkerEnabled(){return game.settings.get(r.modName,k)}static setTurnMarkerEnabled(e){game.settings.set(r.modName,k,e)}static getStartMarkerEnabled(){return game.settings.get(r.modName,f)}static setStartMarkerEnabled(e){game.settings.set(r.modName,f,e)}static getStartMarkerPath(){return game.settings.get(r.modName,b)}static setStartMarkerPath(e){game.settings.set(r.modName,b,e)}static getImagePath(){return""==game.settings.get(r.modName,h).trim()?this.getImageByIndex(game.settings.get(r.modName,p)):game.settings.get(r.modName,h)}static getImageByIndex(e){switch(e){case 0:return"modules/turnmarker/assets/incendium.png";case 1:return"modules/turnmarker/assets/cultist.png";case 2:return"modules/turnmarker/assets/regeneration.png";case 3:return"modules/turnmarker/assets/cosmos.png";case 4:return"modules/turnmarker/assets/earthlydust.png";case 5:return"modules/turnmarker/assets/reality.png";case 6:return"modules/turnmarker/assets/believer.png";case 7:return"modules/turnmarker/assets/madmage.png";case 8:return"modules/turnmarker/assets/bluesky.png";case 9:return"modules/turnmarker/assets/universe.png";case 10:return"modules/turnmarker/assets/prosperity.png"}}static setImage(e){game.settings.set(r.modName,p,e)}static getCustomImagePath(){return game.settings.get(r.modName,h)}static setCustomImagePath(e){game.settings.set(r.modName,h,e)}static registerSettings(){game.settings.registerMenu(r.modName,"tm.settingsMenu",{name:"tm.settings.button.name",label:"tm.settings.button.label",icon:"fas fa-sync-alt",type:n.SettingsForm,restricted:!0}),game.settings.register(r.modName,i,{name:`${r.modName} version`,default:"0.0.0",type:String,scope:"world"}),game.settings.register(r.modName,o,{name:"tm.settings.ratio.name",hint:"tm.settings.ratio.hint",scope:"world",config:!1,type:Number,default:1.5,restricted:!0}),game.settings.register(r.modName,m,{name:"tm.settings.animate.name",hint:"tm.settings.animate.hint",scope:"user",config:!0,type:Boolean,default:!0}),game.settings.register(r.modName,g,{name:"tm.settings.interval.name",hint:"tm.settings.interval.hint",scope:"user",config:!0,type:Number,default:100}),game.settings.register(r.modName,p,{name:"tm.settings.image.name",scope:"world",config:!1,type:Number,default:0,choices:M,restricted:!0,onChange:e=>s.Marker.updateImagePath(e)}),game.settings.register(r.modName,d,{name:"tm.settings.announcedActors.name",hint:"tm.settings.announcedActors.hint",scope:"world",config:!1,type:Number,default:0,restricted:!0,choices:y}),game.settings.register(r.modName,u,{name:"tm.settings.announceTokenName.name",hint:"tm.settings.announceTokenName.hint",scope:"world",config:!1,type:Boolean,default:!1,restricted:!0}),game.settings.register(r.modName,h,{name:"tm.settings.customImage.name",hint:"tm.settings.customImage.hint",scope:"world",config:!1,type:String,default:"",restricted:!0,onChange:e=>s.Marker.updateImagePath(e)}),game.settings.register(r.modName,c,{name:"tm.settings.announce.name",hint:"tm.settings.announce.hint",scope:"world",config:!1,type:Boolean,default:!0}),game.settings.register(r.modName,l,{name:"tm.settings.announceImage.name",hint:"tm.settings.announceImage.hint",scope:"world",config:!1,type:Boolean,default:!0}),game.settings.register(r.modName,"announce-asActor",{name:"tm.settings.announceAs.name",hint:"tm.settings.announceAs.hint",scope:"world",config:!1,type:Boolean,default:!0}),game.settings.register(r.modName,k,{name:"tm.settings.turnMarkerEnabled.name",hint:"tm.settings.turnMarkerEnabled.hint",scope:"world",config:!1,type:Boolean,default:!0,restricted:!0}),game.settings.register(r.modName,f,{name:"tm.settings.startEnabled.name",hint:"tm.settings.startEnabled.hint",scope:"world",config:!1,type:Boolean,default:!1,restricted:!0}),game.settings.register(r.modName,b,{name:"tm.settings.startImage.name",hint:"tm.settings.startImage.hint",scope:"world",config:!1,type:String,default:"",restricted:!0})}}},"./src/scripts/settingsForm.js":(e,t,a)=>{a.r(t),a.d(t,{SettingsForm:()=>r});var s=a("./src/scripts/settings.js");const n=["mp4","webm","ogg"];class r extends FormApplication{constructor(e,t={}){super(e,t)}static get defaultOptions(){return mergeObject(super.defaultOptions,{id:"turnmarker-settings-form",title:"Turn Marker - Global Settings",template:"./modules/turnmarker/templates/settings.html",classes:["sheet","tm-settings"],width:500,closeOnSubmit:!0})}getData(){return{turnMarkerEnabled:s.Settings.getTurnMarkerEnabled(),ratio:s.Settings.getRatio(),image:this.getSelectList(s.imageTitles,s.Settings.getImageIndex()),announceActors:this.getSelectList(s.announcedActorOptions,s.Settings.getAnnounceActors()),customImage:s.Settings.getCustomImagePath(),announce:s.Settings.shouldAnnounceTurns(),announceImage:s.Settings.getIncludeAnnounceImage(),announceTokenName:s.Settings.getAnnounceTokenName(),startMarkerEnabled:s.Settings.getStartMarkerEnabled(),startMarkerPath:s.Settings.getStartMarkerPath(),previewPath:s.Settings.getImagePath()}}async _updateObject(e,t){console.log("Turn Marker | Saving Settings"),s.Settings.setRatio(t.ratio),t.image&&s.Settings.setImage(t.image),s.Settings.setCustomImagePath(t.customImage),s.Settings.setShouldAnnounceTurns(t.announce),s.Settings.setAnnounceActors(t.announceActors),s.Settings.setIncludeAnnounceImage(t.announceImage),s.Settings.setAnnounceTokenName(t.announceTokenName),s.Settings.setTurnMarkerEnabled(t.turnMarkerEnabled),s.Settings.setStartMarkerEnabled(t.startMarkerEnabled),s.Settings.setStartMarkerPath(t.startMarkerPath)}activateListeners(e){super.activateListeners(e);const t=e.find("#image"),a=e.find("#customImage"),n=e.find("#markerImgPreview");this.updatePreview(e),t.length>0&&t.on("change",(e=>{""==a[0].value.trim()&&n.attr("src",s.Settings.getImageByIndex(Number(e.target.value)))})),a.length>0&&a.on("change",(t=>{this.updatePreview(e)}))}updatePreview(e){const t=e.find("#image"),a=e.find("#customImage"),r=e.find("#markerImgPreview"),i=e.find("#markerVideoPreview");if(""==a[0].value.trim())t[0].disabled=!1,r.attr("src",s.Settings.getImageByIndex(Number(t[0].value))),r.removeClass("hidden"),i.addClass("hidden");else{t[0].disabled=!0;const e=this.getExtension(a[0].value);console.warn(e),n.includes(e.toLowerCase())?(i.attr("src",a[0].value),r.addClass("hidden"),i.removeClass("hidden")):(r.attr("src",a[0].value),r.removeClass("hidden"),i.addClass("hidden"))}}getExtension(e){return e.slice(2+(e.lastIndexOf(".")-1>>>0))}getSelectList(e,t){let a=[];return e.forEach(((e,s)=>{a.push({value:e,selected:s==t})})),a}}},"./src/scripts/turnmarker.js":(e,t,a)=>{a.r(t);var s=a("./src/scripts/chatter.js"),n=a("./src/scripts/marker.js"),r=a("./src/scripts/markeranimation.js"),i=a("./src/scripts/settings.js"),o=a("./src/scripts/updateWindow.js"),m=a("./src/scripts/utils.js");let g,c,d="";Hooks.on("ready",(async()=>{console.log("redyings"),i.Settings.registerSettings();let e=canvas.tiles.placeables.find((e=>1==e.data.flags.turnMarker));if(console.log(e),e&&e.id){c=e.id;let t=canvas.tiles.placeables.find((e=>1==e.data.flags.turnMarker));t.zIndex=Math.max(...canvas.tiles.placeables.map((e=>e.zIndex)))+1,t.parent.sortChildren(),!game.paused&&i.Settings.getShouldAnimate()&&(g=r.MarkerAnimation.startAnimation(g,c))}game.user.isGM&&isNewerVersion(game.modules.get("turnmarker").data.version,i.Settings.getVersion())&&(0,o.renderUpdateWindow)()})),Hooks.on("createTile",((e,t)=>{1==t.flags.turnMarker&&(c=t._id,(t=canvas.tiles.placeables.find((e=>1==e.data.flags.turnMarker))).zIndex=Math.max(...canvas.tiles.placeables.map((e=>e.zIndex)))+1,t.parent.sortChildren(),i.Settings.getShouldAnimate()&&(g=r.MarkerAnimation.startAnimation(g,c)))})),Hooks.on("updateCombat",(async(e,t)=>{if(e.started||await n.Marker.deleteStartMarker(),e.combatant&&t&&d!=e.combatant._id&&game.user.isGM&&game.userId==(0,m.firstGM)()&&(d=e.combatant._id,e&&e.combatant&&e.started)){await n.Marker.placeStartMarker(game.combat.combatant.token._id);let t=canvas.tiles.placeables.find((e=>1==e.data.flags.turnMarker)),a=await n.Marker.placeTurnMarker(e.combatant.token._id,t&&t.id||void 0);if(a&&(c=a.markerId,g=a.animator),i.Settings.getTurnMarkerEnabled()&&(await n.Marker.deleteStartMarker(),canvas.scene.unsetFlag(m.FlagScope,m.Flags.startMarkerPlaced)),i.Settings.shouldAnnounceTurns()&&!e.combatant.hidden)switch(i.Settings.getAnnounceActors()){case 0:s.Chatter.sendTurnMessage(e.combatant);break;case 1:e.combatant.actor.hasPlayerOwner&&s.Chatter.sendTurnMessage(e.combatant);break;case 2:e.combatant.actor.hasPlayerOwner||s.Chatter.sendTurnMessage(e.combatant);break;case 3:s.Chatter.sendTurnMessage(e.combatant,!0)}}})),Hooks.on("deleteCombat",(async()=>{game.user.isGM&&await n.Marker.clearAllMarkers(),r.MarkerAnimation.stopAnimation(g)})),Hooks.on("updateToken",(async(e,t,a)=>{let s=canvas.tiles.placeables.find((e=>1==e.data.flags.turnMarker));s&&(a.x||a.y||a.width||a.height||a.hidden)&&game&&game.combat&&game.combat.combatant&&game.combat.combatant.tokenId==t._id&&game.user.isGM&&game.combat&&(await n.Marker.moveMarkerToToken(t._id,s.id),s.zIndex=Math.max(...canvas.tiles.placeables.map((e=>e.zIndex)))+1,s.parent.sortChildren())})),Hooks.on("updateTile",(async()=>{if(canvas.scene.data.tokenVision){let e=canvas.tiles.placeables.find((e=>1==e.data.flags.turnMarker));if(e){let t=canvas.tokens.placeables.find((e=>e.id==game.combat.combatant.tokenId));t&&!t.data.hidden&&(e.visible=canvas.sight.testVisibility(t.center,{tolerance:canvas.dimensions.size/4}))}}})),Hooks.on("pauseGame",(async e=>{c&&i.Settings.getShouldAnimate()&&(e?r.MarkerAnimation.stopAnimation(g):g=r.MarkerAnimation.startAnimation(g,c))}))},"./src/scripts/updateWindow.js":(e,t,a)=>{a.r(t),a.d(t,{renderUpdateWindow:()=>n});var s=a("./src/scripts/settings.js");function n(){const e=game.modules.get("turnmarker");if(isNewerVersion(e.data.version,s.Settings.getVersion())){class t extends Application{static get defaultOptions(){return mergeObject(super.defaultOptions,{template:`modules/${e.id}/templates/updateWindow.html`,resizable:!1,width:500,height:600,classes:["updateWindow"],title:`${e.data.title} - Updated`})}getData(){return{version:e.data.version}}activateListeners(t){super.activateListeners(t),t.find(".show-again").on("change",(t=>{s.Settings.setVersion(t.currentTarget.checked?e.data.version:oldVersion)}))}}(new t).render(!0)}}},"./src/scripts/utils.js":(e,t,a)=>{a.r(t),a.d(t,{modName:()=>s,FlagScope:()=>n,Flags:()=>r,socketName:()=>i,socketAction:()=>o,findTokenById:()=>m,firstGM:()=>g});const s="turnmarker",n="turnmarker",r={startMarkerPlaced:"startMarkerPlaced"},i="module.turnmarker",o={placeStartMarker:0};function m(e){return canvas.tokens.ownedTokens.find((t=>t.id==e))}function g(){for(let e of game.users.entities)if(e.data.role>=4&&e.active)return e.data._id}}},t={};function a(s){if(t[s])return t[s].exports;var n=t[s]={exports:{}};return e[s](n,n.exports,a),n.exports}a.d=(e,t)=>{for(var s in t)a.o(t,s)&&!a.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:t[s]})},a.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),a.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a("./src/scripts/turnmarker.js")})(); +(()=>{"use strict";var e={"./src/scripts/chatter.js":(e,t,a)=>{a.r(t),a.d(t,{Chatter:()=>n});var s=a("./src/scripts/settings.js");class n{static sendTurnMessage(e,t=!1){let a=[];e.players.forEach((e=>{a.push(e.name)})),0==a.length&&a.push("GM");let n=e.actor.name,r=n;s.Settings.getAnnounceTokenName()&&(n=e.token.name,r=e.name),t&&!e.actor.hasPlayerOwner&&(n="???"),ChatMessage.create({speaker:{actor:e.actor,alias:r},content:`
${this.placeImage(e)}\n
\n

${n}'s Turn

\n

${a.join(" - ")}

\n
\n
Turn Marker`})}static placeImage(e){if(s.Settings.getIncludeAnnounceImage()){let t=e.img;return e.flags.core&&e.flags.core.thumb&&(t=e.flags.core.thumb),`
`}return""}}},"./src/scripts/marker.js":(e,t,a)=>{a.r(t),a.d(t,{Marker:()=>i});var s=a("./src/scripts/markeranimation.js"),n=a("./src/scripts/settings.js"),r=a("./src/scripts/utils.js");class i{static async placeTurnMarker(e,t){if(t)return this.moveMarkerToToken(e,t),t;if(this.clearAllMarkers(),n.Settings.getTurnMarkerEnabled()){let t=(0,r.findTokenById)(e),a=(n.Settings.getRatio(),this.getImageDimensions(t)),s=this.getImageLocation(t),i=new Tile({img:n.Settings.getImagePath(),width:a.w,height:a.h,x:s.x,y:s.y,z:900,rotation:0,hidden:t.data.hidden,locked:!1,flags:{turnMarker:!0}});return(await canvas.scene.createEmbeddedEntity("Tile",i.data))._id}return null}static async deleteStartMarker(){const e=canvas.scene.getEmbeddedCollection("Tile").filter((e=>e.flags.startMarker)).map((e=>e._id));await canvas.scene.deleteEmbeddedEntity("Tile",e)}static async placeStartMarker(e){if(n.Settings.getStartMarkerEnabled()){let t=(0,r.findTokenById)(e),a=this.getImageDimensions(t),s=this.getImageLocation(t),i=new Tile({img:n.Settings.getStartMarker(),width:a.w,height:a.h,x:s.x,y:s.y,z:900,rotation:0,hidden:t.data.hidden,locked:!1,flags:{startMarker:!0}});game.user.isGM&&(canvas.scene.createEmbeddedEntity("Tile",i.data),canvas.scene.setFlag(r.FlagScope,r.Flags.startMarkerPlaced,!0))}}static async moveMarkerToToken(e,t){let a=(0,r.findTokenById)(e),s=(n.Settings.getRatio(),this.getImageDimensions(a)),i=this.getImageLocation(a);await canvas.scene.updateEmbeddedEntity("Tile",{_id:t,width:s.w,height:s.h,x:i.x,y:i.y,hidden:a.data.hidden})}static async clearAllMarkers(){let e=canvas.scene.getEmbeddedCollection("Tile");for(let t of e)(t.flags.turnMarker||t.flags.startMarker)&&await canvas.scene.deleteEmbeddedEntity("Tile",t._id)}static updateImagePath(){if(game.user.isGM){let e=canvas.tiles.placeables.find((e=>1==e.data.flags.turnMarker));e&&canvas.scene.updateEmbeddedEntity("Tile",{_id:e.id,img:n.Settings.getImagePath()})}}static reset(e){s.MarkerAnimation.stopAnimation(e),this.clearAllMarkers()}static getImageDimensions(e,t=!1){let a=t?1:n.Settings.getRatio(),s=0,r=0;switch(canvas.grid.type){case 2:case 3:s=r=e.h*a;break;case 4:case 5:s=r=e.w*a;break;default:s=e.w*a,r=e.h*a}return{w:s,h:r}}static getImageLocation(e,t=!1){let a=t?1:n.Settings.getRatio(),s=0,r=0;switch(canvas.grid.type){case 2:case 3:s=e.center.x-e.h*a/2,r=e.center.y-e.h*a/2;break;case 4:case 5:s=e.center.x-e.w*a/2,r=e.center.y-e.w*a/2;break;default:s=e.center.x-e.w*a/2,r=e.center.y-e.h*a/2}return{x:s,y:r}}}},"./src/scripts/markeranimation.js":(e,t,a)=>{a.r(t),a.d(t,{MarkerAnimation:()=>n});var s=a("./src/scripts/settings.js");class n{static startAnimation(e,t){let a=canvas.scene.getEmbeddedEntity("Tile",t);return e=this.animateRotation.bind(a),canvas.app.ticker.add(e),e}static stopAnimation(e){canvas.app.ticker.remove(e)}static animateRotation(e){let t=canvas.tiles.placeables.find((e=>1==e.data.flags.turnMarker));if(t&&t.data.img){let a=s.Settings.getInterval()/1e4;try{t.tile.img.rotation+=a*e}catch(e){}}}}},"./src/scripts/settings.js":(e,t,a)=>{a.r(t),a.d(t,{imageTitles:()=>M,announcedActorOptions:()=>v,Settings:()=>y});var s=a("./src/scripts/marker.js"),n=a("./src/scripts/settingsForm.js"),r=a("./src/scripts/utils.js");const i="tm-version",o="ratio",m="animation",g="interval",c="announce-turn",d="announce-Actors",l="announce-image",u="announce-token",p="image",h="customimage",k="turnmarker-enabled",f="startMarker-enabled",b="startMarker-custom",M=["Runes of Incendium by Rin","Runes of the Cultist by Rin","Runes of Regeneration by Rin","Runes of the Cosmos by Rin","Runes of Earthly Dust by Rin","Runes of Reality by Rin","Runes of the Believer by Rin","Runes of the Mad Mage by Rin","Runes of the Blue Sky by Rin","Runes of the Universe by Rin","Runes of Prosperity by Rin"],v=["Announce for all","Announce for players","Announce for GM-controlled","Announce all but hide GM-controlled names"];class y{static getVersion(){return game.settings.get(r.modName,i)}static setVersion(e){game.settings.set(r.modName,i,e)}static getRatio(){return game.settings.get(r.modName,o)}static setRatio(e){game.settings.set(r.modName,o,e)}static getShouldAnimate(){return game.settings.get(r.modName,m)}static getInterval(){return game.settings.get(r.modName,g)}static shouldAnnounceTurns(){return game.settings.get(r.modName,c)}static setShouldAnnounceTurns(e){game.settings.set(r.modName,c,e)}static getAnnounceActors(){return game.settings.get(r.modName,d)}static setAnnounceActors(e){return game.settings.set(r.modName,d,e)}static getAnnounceTokenName(){return game.settings.get(r.modName,u)}static setAnnounceTokenName(e){return game.settings.set(r.modName,u,e)}static getIncludeAnnounceImage(){return game.settings.get(r.modName,l)}static setIncludeAnnounceImage(e){game.settings.set(r.modName,l,e)}static getImageIndex(){return game.settings.get(r.modName,p)}static getStartMarker(){return""==game.settings.get(r.modName,b).trim()?"modules/turnmarker/assets/start.png":game.settings.get(r.modName,b)}static getTurnMarkerEnabled(){return game.settings.get(r.modName,k)}static setTurnMarkerEnabled(e){game.settings.set(r.modName,k,e)}static getStartMarkerEnabled(){return game.settings.get(r.modName,f)}static setStartMarkerEnabled(e){game.settings.set(r.modName,f,e)}static getStartMarkerPath(){return game.settings.get(r.modName,b)}static setStartMarkerPath(e){game.settings.set(r.modName,b,e)}static getImagePath(){return""==game.settings.get(r.modName,h).trim()?this.getImageByIndex(game.settings.get(r.modName,p)):game.settings.get(r.modName,h)}static getImageByIndex(e){switch(e){case 0:return"modules/turnmarker/assets/incendium.png";case 1:return"modules/turnmarker/assets/cultist.png";case 2:return"modules/turnmarker/assets/regeneration.png";case 3:return"modules/turnmarker/assets/cosmos.png";case 4:return"modules/turnmarker/assets/earthlydust.png";case 5:return"modules/turnmarker/assets/reality.png";case 6:return"modules/turnmarker/assets/believer.png";case 7:return"modules/turnmarker/assets/madmage.png";case 8:return"modules/turnmarker/assets/bluesky.png";case 9:return"modules/turnmarker/assets/universe.png";case 10:return"modules/turnmarker/assets/prosperity.png"}}static setImage(e){game.settings.set(r.modName,p,e)}static getCustomImagePath(){return game.settings.get(r.modName,h)}static setCustomImagePath(e){game.settings.set(r.modName,h,e)}static registerSettings(){game.settings.registerMenu(r.modName,"tm.settingsMenu",{name:"tm.settings.button.name",label:"tm.settings.button.label",icon:"fas fa-sync-alt",type:n.SettingsForm,restricted:!0}),game.settings.register(r.modName,i,{name:`${r.modName} version`,default:"0.0.0",type:String,scope:"world"}),game.settings.register(r.modName,o,{name:"tm.settings.ratio.name",hint:"tm.settings.ratio.hint",scope:"world",config:!1,type:Number,default:1.5,restricted:!0}),game.settings.register(r.modName,m,{name:"tm.settings.animate.name",hint:"tm.settings.animate.hint",scope:"user",config:!0,type:Boolean,default:!0}),game.settings.register(r.modName,g,{name:"tm.settings.interval.name",hint:"tm.settings.interval.hint",scope:"user",config:!0,type:Number,default:100}),game.settings.register(r.modName,p,{name:"tm.settings.image.name",scope:"world",config:!1,type:Number,default:0,choices:M,restricted:!0,onChange:e=>s.Marker.updateImagePath(e)}),game.settings.register(r.modName,d,{name:"tm.settings.announcedActors.name",hint:"tm.settings.announcedActors.hint",scope:"world",config:!1,type:Number,default:0,restricted:!0,choices:v}),game.settings.register(r.modName,u,{name:"tm.settings.announceTokenName.name",hint:"tm.settings.announceTokenName.hint",scope:"world",config:!1,type:Boolean,default:!1,restricted:!0}),game.settings.register(r.modName,h,{name:"tm.settings.customImage.name",hint:"tm.settings.customImage.hint",scope:"world",config:!1,type:String,default:"",restricted:!0,onChange:e=>s.Marker.updateImagePath(e)}),game.settings.register(r.modName,c,{name:"tm.settings.announce.name",hint:"tm.settings.announce.hint",scope:"world",config:!1,type:Boolean,default:!0}),game.settings.register(r.modName,l,{name:"tm.settings.announceImage.name",hint:"tm.settings.announceImage.hint",scope:"world",config:!1,type:Boolean,default:!0}),game.settings.register(r.modName,"announce-asActor",{name:"tm.settings.announceAs.name",hint:"tm.settings.announceAs.hint",scope:"world",config:!1,type:Boolean,default:!0}),game.settings.register(r.modName,k,{name:"tm.settings.turnMarkerEnabled.name",hint:"tm.settings.turnMarkerEnabled.hint",scope:"world",config:!1,type:Boolean,default:!0,restricted:!0}),game.settings.register(r.modName,f,{name:"tm.settings.startEnabled.name",hint:"tm.settings.startEnabled.hint",scope:"world",config:!1,type:Boolean,default:!1,restricted:!0}),game.settings.register(r.modName,b,{name:"tm.settings.startImage.name",hint:"tm.settings.startImage.hint",scope:"world",config:!1,type:String,default:"",restricted:!0})}}},"./src/scripts/settingsForm.js":(e,t,a)=>{a.r(t),a.d(t,{SettingsForm:()=>r});var s=a("./src/scripts/settings.js");const n=["mp4","webm","ogg"];class r extends FormApplication{constructor(e,t={}){super(e,t)}static get defaultOptions(){return mergeObject(super.defaultOptions,{id:"turnmarker-settings-form",title:"Turn Marker - Global Settings",template:"./modules/turnmarker/templates/settings.html",classes:["sheet","tm-settings"],width:500,closeOnSubmit:!0})}getData(){return{turnMarkerEnabled:s.Settings.getTurnMarkerEnabled(),ratio:s.Settings.getRatio(),image:this.getSelectList(s.imageTitles,s.Settings.getImageIndex()),announceActors:this.getSelectList(s.announcedActorOptions,s.Settings.getAnnounceActors()),customImage:s.Settings.getCustomImagePath(),announce:s.Settings.shouldAnnounceTurns(),announceImage:s.Settings.getIncludeAnnounceImage(),announceTokenName:s.Settings.getAnnounceTokenName(),startMarkerEnabled:s.Settings.getStartMarkerEnabled(),startMarkerPath:s.Settings.getStartMarkerPath(),previewPath:s.Settings.getImagePath()}}async _updateObject(e,t){console.log("Turn Marker | Saving Settings"),s.Settings.setRatio(t.ratio),t.image&&s.Settings.setImage(t.image),s.Settings.setCustomImagePath(t.customImage),s.Settings.setShouldAnnounceTurns(t.announce),s.Settings.setAnnounceActors(t.announceActors),s.Settings.setIncludeAnnounceImage(t.announceImage),s.Settings.setAnnounceTokenName(t.announceTokenName),s.Settings.setTurnMarkerEnabled(t.turnMarkerEnabled),s.Settings.setStartMarkerEnabled(t.startMarkerEnabled),s.Settings.setStartMarkerPath(t.startMarkerPath)}activateListeners(e){super.activateListeners(e);const t=e.find("#image"),a=e.find("#customImage"),n=e.find("#markerImgPreview");this.updatePreview(e),t.length>0&&t.on("change",(e=>{""==a[0].value.trim()&&n.attr("src",s.Settings.getImageByIndex(Number(e.target.value)))})),a.length>0&&a.on("change",(t=>{this.updatePreview(e)}))}updatePreview(e){const t=e.find("#image"),a=e.find("#customImage"),r=e.find("#markerImgPreview"),i=e.find("#markerVideoPreview");if(""==a[0].value.trim())t[0].disabled=!1,r.attr("src",s.Settings.getImageByIndex(Number(t[0].value))),r.removeClass("hidden"),i.addClass("hidden");else{t[0].disabled=!0;const e=this.getExtension(a[0].value);console.warn(e),n.includes(e.toLowerCase())?(i.attr("src",a[0].value),r.addClass("hidden"),i.removeClass("hidden")):(r.attr("src",a[0].value),r.removeClass("hidden"),i.addClass("hidden"))}}getExtension(e){return e.slice(2+(e.lastIndexOf(".")-1>>>0))}getSelectList(e,t){let a=[];return e.forEach(((e,s)=>{a.push({value:e,selected:s==t})})),a}}},"./src/scripts/turnmarker.js":(e,t,a)=>{a.r(t);var s=a("./src/scripts/chatter.js"),n=a("./src/scripts/marker.js"),r=a("./src/scripts/markeranimation.js"),i=a("./src/scripts/settings.js"),o=a("./src/scripts/updateWindow.js"),m=a("./src/scripts/utils.js");let g,c,d="";Hooks.on("ready",(async()=>{i.Settings.registerSettings();let e=canvas.tiles.placeables.find((e=>1==e.data.flags.turnMarker));if(e&&e.id){c=e.id;let t=canvas.tiles.placeables.find((e=>1==e.data.flags.turnMarker));t.zIndex=Math.max(...canvas.tiles.placeables.map((e=>e.zIndex)))+1,t.parent.sortChildren(),!game.paused&&i.Settings.getShouldAnimate()&&(g=r.MarkerAnimation.startAnimation(g,c))}game.user.isGM&&isNewerVersion(game.modules.get("turnmarker").data.version,i.Settings.getVersion())&&(0,o.renderUpdateWindow)()})),Hooks.on("createTile",((e,t)=>{1==t.flags.turnMarker&&(c=t._id,(t=canvas.tiles.placeables.find((e=>1==e.data.flags.turnMarker))).zIndex=Math.max(...canvas.tiles.placeables.map((e=>e.zIndex)))+1,t.parent.sortChildren(),i.Settings.getShouldAnimate()&&(g=r.MarkerAnimation.startAnimation(g,c)))})),Hooks.on("updateCombat",(async(e,t)=>{if(e.started||await n.Marker.deleteStartMarker(),e.combatant&&t&&d!=e.combatant._id&&game.user.isGM&&game.userId==(0,m.firstGM)()&&(d=e.combatant._id,e&&e.combatant&&e.started)){await n.Marker.placeStartMarker(game.combat.combatant.token._id);let t=canvas.tiles.placeables.find((e=>1==e.data.flags.turnMarker)),a=await n.Marker.placeTurnMarker(e.combatant.token._id,t&&t.id||void 0);if(a&&(c=a.markerId,g=a.animator),i.Settings.getTurnMarkerEnabled()&&(await n.Marker.deleteStartMarker(),canvas.scene.unsetFlag(m.FlagScope,m.Flags.startMarkerPlaced)),i.Settings.shouldAnnounceTurns()&&!e.combatant.hidden)switch(i.Settings.getAnnounceActors()){case 0:s.Chatter.sendTurnMessage(e.combatant);break;case 1:e.combatant.actor.hasPlayerOwner&&s.Chatter.sendTurnMessage(e.combatant);break;case 2:e.combatant.actor.hasPlayerOwner||s.Chatter.sendTurnMessage(e.combatant);break;case 3:s.Chatter.sendTurnMessage(e.combatant,!0)}}})),Hooks.on("deleteCombat",(async()=>{game.user.isGM&&await n.Marker.clearAllMarkers(),r.MarkerAnimation.stopAnimation(g)})),Hooks.on("updateToken",(async(e,t,a)=>{let s=canvas.tiles.placeables.find((e=>1==e.data.flags.turnMarker));s&&(a.x||a.y||a.width||a.height||a.hidden)&&game&&game.combat&&game.combat.combatant&&game.combat.combatant.tokenId==t._id&&game.user.isGM&&game.combat&&(await n.Marker.moveMarkerToToken(t._id,s.id),s.zIndex=Math.max(...canvas.tiles.placeables.map((e=>e.zIndex)))+1,s.parent.sortChildren())})),Hooks.on("updateTile",(async()=>{if(canvas.scene.data.tokenVision){let e=canvas.tiles.placeables.find((e=>1==e.data.flags.turnMarker));if(e){let t=canvas.tokens.placeables.find((e=>e.id==game.combat.combatant.tokenId));t&&!t.data.hidden&&(e.visible=canvas.sight.testVisibility(t.center,{tolerance:canvas.dimensions.size/4}))}}})),Hooks.on("pauseGame",(async e=>{c&&i.Settings.getShouldAnimate()&&(e?r.MarkerAnimation.stopAnimation(g):g=r.MarkerAnimation.startAnimation(g,c))}))},"./src/scripts/updateWindow.js":(e,t,a)=>{a.r(t),a.d(t,{renderUpdateWindow:()=>n});var s=a("./src/scripts/settings.js");function n(){const e=game.modules.get("turnmarker");if(isNewerVersion(e.data.version,s.Settings.getVersion())){class t extends Application{static get defaultOptions(){return mergeObject(super.defaultOptions,{template:`modules/${e.id}/templates/updateWindow.html`,resizable:!1,width:500,height:600,classes:["updateWindow"],title:`${e.data.title} - Updated`})}getData(){return{version:e.data.version}}activateListeners(t){super.activateListeners(t),t.find(".show-again").on("change",(t=>{s.Settings.setVersion(t.currentTarget.checked?e.data.version:oldVersion)}))}}(new t).render(!0)}}},"./src/scripts/utils.js":(e,t,a)=>{a.r(t),a.d(t,{modName:()=>s,FlagScope:()=>n,Flags:()=>r,socketName:()=>i,socketAction:()=>o,findTokenById:()=>m,firstGM:()=>g});const s="turnmarker",n="turnmarker",r={startMarkerPlaced:"startMarkerPlaced"},i="module.turnmarker",o={placeStartMarker:0};function m(e){return canvas.tokens.ownedTokens.find((t=>t.id==e))}function g(){for(let e of game.users.entities)if(e.data.role>=4&&e.active)return e.data._id}}},t={};function a(s){if(t[s])return t[s].exports;var n=t[s]={exports:{}};return e[s](n,n.exports,a),n.exports}a.d=(e,t)=>{for(var s in t)a.o(t,s)&&!a.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:t[s]})},a.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),a.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a("./src/scripts/turnmarker.js")})(); //# sourceMappingURL=turnmarker.js.map \ No newline at end of file diff --git a/dist/scripts/turnmarker.js.map b/dist/scripts/turnmarker.js.map index 0ab3467..a81b546 100644 --- a/dist/scripts/turnmarker.js.map +++ b/dist/scripts/turnmarker.js.map @@ -1 +1 @@ -{"version":3,"sources":["webpack://turnmarker-alt/./src/scripts/chatter.js","webpack://turnmarker-alt/./src/scripts/marker.js","webpack://turnmarker-alt/./src/scripts/markeranimation.js","webpack://turnmarker-alt/./src/scripts/settings.js","webpack://turnmarker-alt/./src/scripts/settingsForm.js","webpack://turnmarker-alt/./src/scripts/turnmarker.js","webpack://turnmarker-alt/./src/scripts/updateWindow.js","webpack://turnmarker-alt/./src/scripts/utils.js","webpack://turnmarker-alt/webpack/bootstrap","webpack://turnmarker-alt/webpack/runtime/define property getters","webpack://turnmarker-alt/webpack/runtime/hasOwnProperty shorthand","webpack://turnmarker-alt/webpack/runtime/make namespace object","webpack://turnmarker-alt/webpack/startup"],"names":["Chatter","combatant","hideNPC_name","players","forEach","player","push","name","length","combatantName","actor","aliasName","Settings","token","hasPlayerOwner","ChatMessage","create","speaker","alias","content","this","placeImage","join","img","flags","core","thumb","Marker","tokenId","markerId","moveMarkerToToken","clearAllMarkers","findTokenById","dims","getImageDimensions","center","getImageLocation","newTile","Tile","width","w","height","h","x","y","z","rotation","hidden","data","locked","turnMarker","canvas","scene","createEmbeddedEntity","_id","to_delete","getEmbeddedCollection","filter","tile","startMarker","map","deleteEmbeddedEntity","xCoord","yCoord","game","user","isGM","setFlag","FlagScope","Flags","updateEmbeddedEntity","tiles","placeables","find","t","id","animator","MarkerAnimation","ignoreRatio","ratio","newWidth","newHeight","grid","type","overrideX","overrideY","newX","newY","centerX","centerY","Math","abs","tileId","getEmbeddedEntity","animateRotation","bind","app","ticker","add","remove","dt","delta","err","version","animation","interval","announce","announceActors","announceImage","announceTokenName","image","customimage","turnMarkerEnabled","startMarkerEnabled","startMarkerImage","imageTitles","announcedActorOptions","settings","get","modName","val","set","trim","getImageByIndex","index","registerMenu","label","icon","SettingsForm","restricted","register","default","String","scope","hint","config","Number","Boolean","choices","onChange","value","videos","FormApplication","object","options","super","mergeObject","defaultOptions","title","template","classes","closeOnSubmit","getSelectList","customImage","startMarkerPath","previewPath","e","d","console","log","html","activateListeners","markerSelect","markerImgPreview","updatePreview","on","event","attr","target","markerVideoPreview","disabled","removeClass","addClass","ext","getExtension","warn","includes","toLowerCase","filePath","slice","lastIndexOf","array","selected","i","lastTurn","Hooks","async","marker","zIndex","max","o","parent","sortChildren","paused","isNewerVersion","modules","renderUpdateWindow","combat","update","started","userId","firstGM","result","undefined","unsetFlag","updateToken","updateData","tokenVision","tokens","visible","sight","testVisibility","tolerance","dimensions","size","isPaused","module","UpdateWindow","Application","resizable","ev","currentTarget","checked","oldVersion","render","startMarkerPlaced","socketName","socketAction","placeStartMarker","ownedTokens","users","entities","role","active","__webpack_module_cache__","__webpack_require__","moduleId","exports","__webpack_modules__","definition","key","Object","defineProperty","enumerable","obj","prop","prototype","hasOwnProperty","call","r","Symbol","toStringTag"],"mappings":"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","file":"turnmarker.js","sourcesContent":["import { Settings } from \"./settings.js\";\r\n\r\nexport class Chatter {\r\n\r\n static sendTurnMessage(combatant, hideNPC_name=false) {\r\n let players = [];\r\n combatant.players.forEach(player => {\r\n players.push(player.name);\r\n });\r\n if (players.length == 0) players.push(\"GM\");\r\n let combatantName = combatant.actor.name;\r\n let aliasName = combatantName;\r\n if (Settings.getAnnounceTokenName()) {\r\n combatantName = combatant.token.name;\r\n aliasName = combatant.name;\r\n }\r\n if (hideNPC_name && !combatant.actor.hasPlayerOwner) {\r\n combatantName = \"???\";\r\n }\r\n\r\n ChatMessage.create({\r\n speaker: { actor: combatant.actor, alias: aliasName },\r\n //speaker: { actor: {}, alias: 'Turn Marker' },\r\n content:\r\n `
${this.placeImage(combatant)}\r\n
\r\n

${combatantName}'s Turn

\r\n

${players.join(' - ')}

\r\n
\r\n
Turn Marker`\r\n });\r\n }\r\n\r\n static placeImage(combatant) {\r\n if (Settings.getIncludeAnnounceImage()) {\r\n let img = combatant.img;\r\n if (combatant.flags.core && combatant.flags.core.thumb) {\r\n img = combatant.flags.core.thumb;\r\n }\r\n return `
`;\r\n // return `
`;\r\n } else return '';\r\n }\r\n}","import { MarkerAnimation } from './markeranimation.js';\r\nimport { Settings } from './settings.js';\r\nimport { findTokenById, Flags, FlagScope, socketAction, socketName } from './utils.js';\r\n\r\n/**\r\n * Provides functionality for creating, moving, and animating the turn marker\r\n */\r\nexport class Marker {\r\n\r\n /**\r\n * Places a new turn marker under the token specified, and if required, starts the animation\r\n * @param {String} tokenId - The ID of the token where the marker should be placed\r\n * @param {Object} animator - The animator object\r\n * @param {String} markerId - The ID of the tile being used as the turn marker\r\n */\r\n static async placeTurnMarker(tokenId, markerId) {\r\n if (!markerId) {\r\n this.clearAllMarkers();\r\n\r\n if (Settings.getTurnMarkerEnabled()) {\r\n let token = findTokenById(tokenId);\r\n let ratio = Settings.getRatio();\r\n let dims = this.getImageDimensions(token);\r\n let center = this.getImageLocation(token);\r\n\r\n let newTile = new Tile({\r\n img: Settings.getImagePath(),\r\n width: dims.w,\r\n height: dims.h,\r\n x: center.x,\r\n y: center.y,\r\n z: 900,\r\n rotation: 0,\r\n hidden: token.data.hidden,\r\n locked: false,\r\n flags: { turnMarker: true }\r\n });\r\n\r\n let tile = await canvas.scene.createEmbeddedEntity('Tile', newTile.data);\r\n\r\n return tile._id;\r\n } else {\r\n return null;\r\n }\r\n } else {\r\n this.moveMarkerToToken(tokenId, markerId);\r\n return markerId;\r\n }\r\n }\r\n\r\n /**\r\n * Deletes any tiles flagged as a 'Start Marker' from the canvas\r\n */\r\n static async deleteStartMarker() {\r\n const to_delete = canvas.scene.getEmbeddedCollection('Tile')\r\n .filter(tile => tile.flags.startMarker)\r\n .map(tile => tile._id);\r\n await canvas.scene.deleteEmbeddedEntity('Tile', to_delete);\r\n }\r\n\r\n /**\r\n * If enabled in settings, place a \"start\" marker under the token where their turn started.\r\n * @param {String} tokenId - The ID of the token to place the start marker under\r\n * @param {int} xCoord - The X coordinate of where the token was last update to make adjustments\r\n * @param {int} yCoord - The Y coordinate of where the token was last update to make adjustments\r\n */\r\n static async placeStartMarker(tokenId, xCoord, yCoord) {\r\n if (Settings.getStartMarkerEnabled()) {\r\n let token = findTokenById(tokenId);\r\n let dims = this.getImageDimensions(token);\r\n let center = this.getImageLocation(token, false, xCoord, yCoord);\r\n let newTile = new Tile({\r\n img: Settings.getStartMarker(),\r\n width: dims.w,\r\n height: dims.h,\r\n x: center.x,\r\n y: center.y,\r\n z: 900,\r\n rotation: 0,\r\n hidden: token.data.hidden,\r\n locked: false,\r\n flags: { startMarker: true }\r\n });\r\n\r\n if (game.user.isGM) {\r\n canvas.scene.createEmbeddedEntity('Tile', newTile.data);\r\n canvas.scene.setFlag(FlagScope, Flags.startMarkerPlaced, true);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Moves the turn marker tile under the specified token\r\n * @param {String} tokenId - The ID of the token that the marker should be placed under\r\n * @param {String} markerId - The ID of the tile currently serving as the turn marker\r\n */\r\n static async moveMarkerToToken(tokenId, markerId) {\r\n let token = findTokenById(tokenId);\r\n let ratio = Settings.getRatio();\r\n let dims = this.getImageDimensions(token);\r\n let center = this.getImageLocation(token);\r\n\r\n await canvas.scene.updateEmbeddedEntity('Tile', {\r\n _id: markerId,\r\n width: dims.w,\r\n height: dims.h,\r\n x: center.x,\r\n y: center.y,\r\n hidden: token.data.hidden\r\n });\r\n }\r\n\r\n /**\r\n * Removes any existing turn marker and start marker tiles from the canvas\r\n */\r\n static async clearAllMarkers() {\r\n let tiles = canvas.scene.getEmbeddedCollection('Tile');\r\n\r\n for (let tile of tiles) {\r\n if (tile.flags.turnMarker || tile.flags.startMarker) {\r\n await canvas.scene.deleteEmbeddedEntity('Tile', tile._id);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Updates the tile image when the image path has changed\r\n */\r\n static updateImagePath() {\r\n if (game.user.isGM) {\r\n let tile = canvas.tiles.placeables.find(t => t.data.flags.turnMarker == true);\r\n if (tile) {\r\n canvas.scene.updateEmbeddedEntity('Tile', {\r\n _id: tile.id,\r\n img: Settings.getImagePath()\r\n });\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Completely resets the turn marker - deletes all tiles and stops any animation\r\n * @param {Object} animator - The animator object\r\n */\r\n static reset(animator) {\r\n MarkerAnimation.stopAnimation(animator);\r\n this.clearAllMarkers();\r\n }\r\n\r\n /**\r\n * Gets the proper dimensions of the marker tile taking into account the current grid layout\r\n * @param {object} token - The token that the tile should be placed under\r\n */\r\n static getImageDimensions(token, ignoreRatio = false) {\r\n let ratio = ignoreRatio ? 1 : Settings.getRatio();\r\n let newWidth = 0;\r\n let newHeight = 0;\r\n\r\n switch (canvas.grid.type) {\r\n case 2: case 3: // Hex Rows\r\n newWidth = newHeight = token.h * ratio;\r\n break;\r\n case 4: case 5: // Hex Columns\r\n newWidth = newHeight = token.w * ratio;\r\n break;\r\n default: // Gridless and Square\r\n newWidth = token.w * ratio;\r\n newHeight = token.h * ratio;\r\n break;\r\n }\r\n\r\n return { w: newWidth, h: newHeight };\r\n }\r\n\r\n /**\r\n * Gets the proper location of the marker tile taking into account the current grid layout\r\n * @param {object} token - The token that the tile should be placed under\r\n * @param {int} overrideX - The X coordinate of where the token was last update to make adjustments\r\n * @param {int} overrideY - The Y coordinate of where the token was last update to make adjustments\r\n */\r\n static getImageLocation(token, ignoreRatio = false, overrideX= null, overrideY= null) {\r\n let ratio = ignoreRatio ? 1 : Settings.getRatio();\r\n let newX = 0;\r\n let newY = 0;\r\n let centerX = token.center.x;\r\n let centerY = token.center.y;\r\n if (overrideX && overrideY) {\r\n centerX = Math.abs(token.center.x - token.x) + overrideX;\r\n centerY = Math.abs(token.center.y - token.y) + overrideY;\r\n }\r\n\r\n switch (canvas.grid.type) {\r\n case 2: case 3: // Hex Rows\r\n newX = centerX - ((token.h * ratio) / 2);\r\n newY = centerY - ((token.h * ratio) / 2);\r\n break;\r\n case 4: case 5: // Hex Columns\r\n newX = centerX - ((token.w * ratio) / 2);\r\n newY = centerY - ((token.w * ratio) / 2);\r\n break;\r\n default: // Gridless and Square\r\n newX = centerX - ((token.w * ratio) / 2);\r\n newY = centerY - ((token.h * ratio) / 2);\r\n }\r\n\r\n return { x: newX, y: newY };\r\n }\r\n}","import { Settings } from './settings.js';\r\n\r\nexport class MarkerAnimation {\r\n /**\r\n * Starts the animation loop for the specified tile\r\n * @param {object} animator - The animator object\r\n * @param {String} tileId - The ID of the tile currently serving as the turn marker \r\n */\r\n static startAnimation(animator, tileId) {\r\n let tile = canvas.scene.getEmbeddedEntity('Tile', tileId);\r\n animator = this.animateRotation.bind(tile);\r\n canvas.app.ticker.add(animator);\r\n return animator;\r\n }\r\n\r\n /**\r\n * Stops the animation loop for the specified tile\r\n * @param {object} animator - The animator object\r\n */\r\n static stopAnimation(animator) {\r\n canvas.app.ticker.remove(animator);\r\n }\r\n\r\n /**\r\n * Called on every tick of the animation loop to rotate the image based on the current frame\r\n * @param {number} dt - The delta time\r\n */\r\n static animateRotation(dt) {\r\n let tile = canvas.tiles.placeables.find(t => t.data.flags.turnMarker == true);\r\n if (tile && tile.data.img) {\r\n let delta = Settings.getInterval() / 10000;\r\n try {\r\n tile.tile.img.rotation += (delta * dt);\r\n } catch (err) {\r\n // skip lost frames if the tile is being updated by the server\r\n }\r\n }\r\n }\r\n}","import { Marker } from './marker.js';\r\nimport { SettingsForm } from './settingsForm.js';\r\nimport { modName } from './utils.js';\r\n\r\nconst version = 'tm-version';\r\nconst ratio = 'ratio';\r\nconst animation = 'animation';\r\nconst interval = 'interval';\r\nconst announce = 'announce-turn';\r\nconst announceActors = 'announce-Actors';\r\nconst announceAsActor = 'announce-asActor';\r\nconst announceImage = 'announce-image';\r\nconst announceTokenName = 'announce-token';\r\nconst image = 'image';\r\nconst customimage = 'customimage';\r\nconst turnMarkerEnabled = 'turnmarker-enabled';\r\nconst startMarkerEnabled = 'startMarker-enabled';\r\nconst startMarkerImage = 'startMarker-custom';\r\nexport const imageTitles = [\r\n 'Runes of Incendium by Rin',\r\n 'Runes of the Cultist by Rin',\r\n 'Runes of Regeneration by Rin',\r\n 'Runes of the Cosmos by Rin',\r\n 'Runes of Earthly Dust by Rin',\r\n 'Runes of Reality by Rin',\r\n 'Runes of the Believer by Rin',\r\n 'Runes of the Mad Mage by Rin',\r\n 'Runes of the Blue Sky by Rin',\r\n 'Runes of the Universe by Rin',\r\n 'Runes of Prosperity by Rin'\r\n];\r\n\r\nexport const announcedActorOptions = [\r\n 'Announce for all',\r\n 'Announce for players',\r\n 'Announce for GM-controlled',\r\n 'Announce all but hide GM-controlled names'\r\n];\r\n\r\n/**\r\n * Provides functionality for reading and writing module settings\r\n */\r\nexport class Settings {\r\n\r\n static getVersion() {\r\n return game.settings.get(modName, version);\r\n }\r\n\r\n static setVersion(val) {\r\n game.settings.set(modName, version, val);\r\n }\r\n\r\n /**\r\n * Gets the image ratio\r\n */\r\n static getRatio() {\r\n return game.settings.get(modName, ratio);\r\n }\r\n\r\n /**\r\n * Sets the image ratio\r\n * @param {Number} val - The image ratio\r\n */\r\n static setRatio(val) {\r\n game.settings.set(modName, ratio, val);\r\n }\r\n\r\n /**\r\n * Returns true if the marker should be animated\r\n */\r\n static getShouldAnimate() {\r\n return game.settings.get(modName, animation);\r\n }\r\n\r\n /**\r\n * Gets the animation interval in ms.\r\n */\r\n static getInterval() {\r\n return game.settings.get(modName, interval);\r\n }\r\n\r\n /**\r\n * Returns true if turn changes should be announced in chat\r\n */\r\n static shouldAnnounceTurns() {\r\n return game.settings.get(modName, announce);\r\n }\r\n\r\n /**\r\n * Sets whether or not to announce turn changes\r\n * @param {Boolean} val - Whether or not to announce turn changes\r\n */\r\n static setShouldAnnounceTurns(val) {\r\n game.settings.set(modName, announce, val);\r\n }\r\n\r\n\r\n /**\r\n * Gets index of setting\r\n * @returns {Number} - Index number of announced\r\n */\r\n static getAnnounceActors() {\r\n return game.settings.get(modName, announceActors);\r\n }\r\n\r\n /**\r\n * Sets who sees announced turn changes\r\n * @param announceActors - which owners get units announcedActorOptions, which is selected.\r\n */\r\n static setAnnounceActors(val) {\r\n return game.settings.set(modName, announceActors, val);\r\n }\r\n\r\n static getAnnounceTokenName() {\r\n return game.settings.get(modName, announceTokenName);\r\n }\r\n\r\n static setAnnounceTokenName(val) {\r\n return game.settings.set(modName, announceTokenName, val);\r\n }\r\n\r\n static getIncludeAnnounceImage() {\r\n return game.settings.get(modName, announceImage);\r\n }\r\n\r\n static setIncludeAnnounceImage(val) {\r\n game.settings.set(modName, announceImage, val);\r\n }\r\n\r\n /**\r\n * Gets the index of the currently selected marker image\r\n */\r\n static getImageIndex() {\r\n return game.settings.get(modName, image);\r\n }\r\n\r\n static getStartMarker() {\r\n if (game.settings.get(modName, startMarkerImage).trim() == '') {\r\n return 'modules/turnmarker/assets/start.png';\r\n } else {\r\n return game.settings.get(modName, startMarkerImage);\r\n }\r\n }\r\n\r\n static getTurnMarkerEnabled() {\r\n return game.settings.get(modName, turnMarkerEnabled);\r\n }\r\n\r\n\r\n static setTurnMarkerEnabled(val) {\r\n game.settings.set(modName, turnMarkerEnabled, val);\r\n }\r\n\r\n static getStartMarkerEnabled() {\r\n return game.settings.get(modName, startMarkerEnabled);\r\n }\r\n\r\n static setStartMarkerEnabled(val) {\r\n game.settings.set(modName, startMarkerEnabled, val);\r\n }\r\n\r\n static getStartMarkerPath() {\r\n return game.settings.get(modName, startMarkerImage);\r\n }\r\n\r\n static setStartMarkerPath(val) {\r\n game.settings.set(modName, startMarkerImage, val);\r\n }\r\n\r\n /**\r\n * Gets a path to the currently selected image to be used as the marker\r\n */\r\n static getImagePath() {\r\n if (game.settings.get(modName, customimage).trim() == '') {\r\n return this.getImageByIndex(game.settings.get(modName, image));\r\n } else {\r\n return game.settings.get(modName, customimage);\r\n }\r\n }\r\n\r\n static getImageByIndex(index) {\r\n switch (index) {\r\n case 0: return 'modules/turnmarker/assets/incendium.png';\r\n case 1: return 'modules/turnmarker/assets/cultist.png';\r\n case 2: return 'modules/turnmarker/assets/regeneration.png';\r\n case 3: return 'modules/turnmarker/assets/cosmos.png';\r\n case 4: return 'modules/turnmarker/assets/earthlydust.png';\r\n case 5: return 'modules/turnmarker/assets/reality.png';\r\n case 6: return 'modules/turnmarker/assets/believer.png';\r\n case 7: return 'modules/turnmarker/assets/madmage.png';\r\n case 8: return 'modules/turnmarker/assets/bluesky.png';\r\n case 9: return 'modules/turnmarker/assets/universe.png';\r\n case 10: return 'modules/turnmarker/assets/prosperity.png';\r\n }\r\n }\r\n\r\n static setImage(val) {\r\n game.settings.set(modName, image, val);\r\n }\r\n\r\n static getCustomImagePath() {\r\n return game.settings.get(modName, customimage);\r\n }\r\n\r\n static setCustomImagePath(val) {\r\n game.settings.set(modName, customimage, val);\r\n }\r\n\r\n /**\r\n * Registers all game settings\r\n */\r\n static registerSettings() {\r\n\r\n game.settings.registerMenu(modName, 'tm.settingsMenu', {\r\n name: 'tm.settings.button.name',\r\n label: 'tm.settings.button.label',\r\n icon: 'fas fa-sync-alt',\r\n type: SettingsForm,\r\n restricted: true,\r\n });\r\n\r\n game.settings.register(modName, version, {\r\n name: `${modName} version`,\r\n default: '0.0.0',\r\n type: String,\r\n scope: 'world',\r\n });\r\n\r\n game.settings.register(modName, ratio, {\r\n name: 'tm.settings.ratio.name',\r\n hint: 'tm.settings.ratio.hint',\r\n scope: 'world',\r\n config: false,\r\n type: Number,\r\n default: 1.5,\r\n restricted: true\r\n });\r\n\r\n game.settings.register(modName, animation, {\r\n name: 'tm.settings.animate.name',\r\n hint: 'tm.settings.animate.hint',\r\n scope: 'user',\r\n config: true,\r\n type: Boolean,\r\n default: true,\r\n });\r\n\r\n game.settings.register(modName, interval, {\r\n name: 'tm.settings.interval.name',\r\n hint: 'tm.settings.interval.hint',\r\n scope: 'user',\r\n config: true,\r\n type: Number,\r\n default: 100\r\n });\r\n\r\n game.settings.register(modName, image, {\r\n name: 'tm.settings.image.name',\r\n scope: 'world',\r\n config: false,\r\n type: Number,\r\n default: 0,\r\n choices: imageTitles,\r\n restricted: true,\r\n onChange: value => Marker.updateImagePath(value)\r\n });\r\n\r\n game.settings.register(modName, announceActors, {\r\n name: 'tm.settings.announcedActors.name',\r\n hint: 'tm.settings.announcedActors.hint',\r\n scope: 'world',\r\n config: false,\r\n type: Number,\r\n default: 0,\r\n restricted: true,\r\n choices: announcedActorOptions,\r\n });\r\n\r\n game.settings.register(modName, announceTokenName, {\r\n name: 'tm.settings.announceTokenName.name',\r\n hint: 'tm.settings.announceTokenName.hint',\r\n scope: 'world',\r\n config: false,\r\n type: Boolean,\r\n default: false,\r\n restricted: true,\r\n });\r\n\r\n game.settings.register(modName, customimage, {\r\n name: 'tm.settings.customImage.name',\r\n hint: 'tm.settings.customImage.hint',\r\n scope: 'world',\r\n config: false,\r\n type: String,\r\n default: '',\r\n restricted: true,\r\n onChange: value => Marker.updateImagePath(value)\r\n });\r\n\r\n game.settings.register(modName, announce, {\r\n name: 'tm.settings.announce.name',\r\n hint: 'tm.settings.announce.hint',\r\n scope: 'world',\r\n config: false,\r\n type: Boolean,\r\n default: true\r\n });\r\n\r\n game.settings.register(modName, announceImage, {\r\n name: 'tm.settings.announceImage.name',\r\n hint: 'tm.settings.announceImage.hint',\r\n scope: 'world',\r\n config: false,\r\n type: Boolean,\r\n default: true\r\n });\r\n\r\n game.settings.register(modName, announceAsActor, {\r\n name: 'tm.settings.announceAs.name',\r\n hint: 'tm.settings.announceAs.hint',\r\n scope: 'world',\r\n config: false,\r\n type: Boolean,\r\n default: true\r\n });\r\n\r\n game.settings.register(modName, turnMarkerEnabled, {\r\n name: 'tm.settings.turnMarkerEnabled.name',\r\n hint: 'tm.settings.turnMarkerEnabled.hint',\r\n scope: 'world',\r\n config: false,\r\n type: Boolean,\r\n default: true,\r\n restricted: true\r\n });\r\n\r\n game.settings.register(modName, startMarkerEnabled, {\r\n name: 'tm.settings.startEnabled.name',\r\n hint: 'tm.settings.startEnabled.hint',\r\n scope: 'world',\r\n config: false,\r\n type: Boolean,\r\n default: false,\r\n restricted: true\r\n });\r\n\r\n game.settings.register(modName, startMarkerImage, {\r\n name: 'tm.settings.startImage.name',\r\n hint: 'tm.settings.startImage.hint',\r\n scope: 'world',\r\n config: false,\r\n type: String,\r\n default: '',\r\n restricted: true\r\n });\r\n }\r\n}","import { imageTitles, announcedActorOptions, Settings } from './settings.js';\r\n\r\nconst videos = ['mp4', 'webm', 'ogg'];\r\n\r\nexport class SettingsForm extends FormApplication {\r\n\r\n constructor(object, options = {}) {\r\n super(object, options);\r\n }\r\n\r\n /**\r\n * Default Options for this FormApplication\r\n */\r\n static get defaultOptions() {\r\n return mergeObject(super.defaultOptions, {\r\n id: 'turnmarker-settings-form',\r\n title: 'Turn Marker - Global Settings',\r\n template: './modules/turnmarker/templates/settings.html',\r\n classes: ['sheet', 'tm-settings'],\r\n width: 500,\r\n closeOnSubmit: true\r\n });\r\n }\r\n\r\n getData() {\r\n return {\r\n turnMarkerEnabled: Settings.getTurnMarkerEnabled(),\r\n ratio: Settings.getRatio(),\r\n image: this.getSelectList(imageTitles, Settings.getImageIndex()),\r\n announceActors: this.getSelectList(announcedActorOptions, Settings.getAnnounceActors()),\r\n customImage: Settings.getCustomImagePath(),\r\n announce: Settings.shouldAnnounceTurns(),\r\n announceImage: Settings.getIncludeAnnounceImage(),\r\n announceTokenName :Settings.getAnnounceTokenName(),\r\n startMarkerEnabled: Settings.getStartMarkerEnabled(),\r\n startMarkerPath: Settings.getStartMarkerPath(),\r\n previewPath: Settings.getImagePath()\r\n };\r\n }\r\n\r\n /** \r\n * Executes on form submission.\r\n * @param {Object} e - the form submission event\r\n * @param {Object} d - the form data\r\n */\r\n async _updateObject(e, d) {\r\n console.log('Turn Marker | Saving Settings');\r\n Settings.setRatio(d.ratio);\r\n if (d.image) Settings.setImage(d.image);\r\n Settings.setCustomImagePath(d.customImage);\r\n Settings.setShouldAnnounceTurns(d.announce);\r\n Settings.setAnnounceActors(d.announceActors);\r\n Settings.setIncludeAnnounceImage(d.announceImage);\r\n Settings.setAnnounceTokenName(d.announceTokenName);\r\n Settings.setTurnMarkerEnabled(d.turnMarkerEnabled);\r\n Settings.setStartMarkerEnabled(d.startMarkerEnabled);\r\n Settings.setStartMarkerPath(d.startMarkerPath);\r\n }\r\n\r\n activateListeners(html) {\r\n super.activateListeners(html);\r\n const markerSelect = html.find('#image');\r\n const customImage = html.find('#customImage');\r\n const markerImgPreview = html.find('#markerImgPreview');\r\n\r\n this.updatePreview(html);\r\n\r\n if (markerSelect.length > 0) {\r\n markerSelect.on('change', event => {\r\n if (customImage[0].value.trim() == '') {\r\n markerImgPreview.attr('src', Settings.getImageByIndex(Number(event.target.value)));\r\n }\r\n });\r\n }\r\n\r\n if (customImage.length > 0) {\r\n customImage.on('change', event => {\r\n this.updatePreview(html);\r\n });\r\n }\r\n }\r\n\r\n updatePreview(html) {\r\n const markerSelect = html.find('#image');\r\n const customImage = html.find('#customImage');\r\n const markerImgPreview = html.find('#markerImgPreview');\r\n const markerVideoPreview = html.find('#markerVideoPreview');\r\n\r\n if (customImage[0].value.trim() == '') {\r\n markerSelect[0].disabled = false;\r\n markerImgPreview.attr('src', Settings.getImageByIndex(Number(markerSelect[0].value)));\r\n markerImgPreview.removeClass('hidden');\r\n markerVideoPreview.addClass('hidden');\r\n } else {\r\n markerSelect[0].disabled = true;\r\n const ext = this.getExtension(customImage[0].value);\r\n console.warn(ext);\r\n if (videos.includes(ext.toLowerCase())) {\r\n markerVideoPreview.attr('src', customImage[0].value);\r\n markerImgPreview.addClass('hidden');\r\n markerVideoPreview.removeClass('hidden');\r\n } else {\r\n markerImgPreview.attr('src', customImage[0].value);\r\n markerImgPreview.removeClass('hidden');\r\n markerVideoPreview.addClass('hidden');\r\n }\r\n }\r\n }\r\n\r\n getExtension(filePath) {\r\n return filePath.slice((filePath.lastIndexOf(\".\") - 1 >>> 0) + 2);\r\n }\r\n\r\n getSelectList(array, selected) {\r\n let options = [];\r\n array.forEach((x, i) => {\r\n options.push({ value: x, selected: i == selected });\r\n });\r\n return options;\r\n }\r\n}","import { Chatter } from './chatter.js';\r\nimport { Marker } from './marker.js';\r\nimport { MarkerAnimation } from './markeranimation.js';\r\nimport { Settings } from './settings.js';\r\nimport { renderUpdateWindow } from './updateWindow.js';\r\nimport { firstGM, Flags, FlagScope, socketAction, socketName } from './utils.js';\r\n\r\nlet animator;\r\nlet markerId;\r\nlet lastTurn = '';\r\n\r\n\r\nHooks.on('ready', async () => {\r\n console.log(\"redyings\")\r\n Settings.registerSettings();\r\n let marker = canvas.tiles.placeables.find(t => t.data.flags.turnMarker == true);\r\n console.log(marker)\r\n if (marker && marker.id) {\r\n markerId = marker.id;\r\n let tile = canvas.tiles.placeables.find(t => t.data.flags.turnMarker == true);\r\n tile.zIndex = Math.max(...canvas.tiles.placeables.map(o => o.zIndex)) + 1;\r\n tile.parent.sortChildren();\r\n if (!game.paused && Settings.getShouldAnimate()) {\r\n animator = MarkerAnimation.startAnimation(animator, markerId);\r\n }\r\n }\r\n\r\n if (game.user.isGM) {\r\n if (isNewerVersion(game.modules.get(\"turnmarker\").data.version, Settings.getVersion())) {\r\n renderUpdateWindow();\r\n }\r\n }\r\n});\r\n\r\nHooks.on('createTile', (scene, tile) => {\r\n if (tile.flags.turnMarker == true) {\r\n markerId = tile._id;\r\n tile = canvas.tiles.placeables.find(t => t.data.flags.turnMarker == true);\r\n tile.zIndex = Math.max(...canvas.tiles.placeables.map(o => o.zIndex)) + 1;\r\n tile.parent.sortChildren();\r\n if (Settings.getShouldAnimate()) {\r\n animator = MarkerAnimation.startAnimation(animator, markerId);\r\n }\r\n }\r\n});\r\n\r\n\r\nHooks.on('updateCombat', async (combat, update) => {\r\n // Clear out any leftovers, there seems to be a buggy instance where updateCombat is fired, when combat isn't\r\n // started nor, is a turn changed\r\n if (!combat.started) {\r\n await Marker.deleteStartMarker();\r\n }\r\n if (combat.combatant) {\r\n if (update && lastTurn != combat.combatant._id && game.user.isGM && game.userId == firstGM()) {\r\n lastTurn = combat.combatant._id;\r\n if (combat && combat.combatant && combat.started) {\r\n await Marker.placeStartMarker(game.combat.combatant.token._id)\r\n let tile = canvas.tiles.placeables.find(t => t.data.flags.turnMarker == true);\r\n let result = await Marker.placeTurnMarker(combat.combatant.token._id, (tile && tile.id) || undefined);\r\n if (result) {\r\n markerId = result.markerId;\r\n animator = result.animator;\r\n }\r\n if (Settings.getTurnMarkerEnabled()) {\r\n await Marker.deleteStartMarker();\r\n canvas.scene.unsetFlag(FlagScope, Flags.startMarkerPlaced);\r\n }\r\n if (Settings.shouldAnnounceTurns() && !combat.combatant.hidden) {\r\n switch (Settings.getAnnounceActors()) {\r\n case 0:\r\n Chatter.sendTurnMessage(combat.combatant);\r\n break;\r\n case 1:\r\n if (combat.combatant.actor.hasPlayerOwner) {\r\n Chatter.sendTurnMessage(combat.combatant);\r\n }\r\n break;\r\n case 2:\r\n if (!combat.combatant.actor.hasPlayerOwner) {\r\n Chatter.sendTurnMessage(combat.combatant);\r\n }\r\n break;\r\n case 3:\r\n Chatter.sendTurnMessage(combat.combatant, true);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n});\r\n\r\nHooks.on('deleteCombat', async () => {\r\n if (game.user.isGM) {\r\n await Marker.clearAllMarkers();\r\n }\r\n MarkerAnimation.stopAnimation(animator);\r\n});\r\n\r\nHooks.on('updateToken', async (scene, updateToken, updateData) => {\r\n /*\r\n Moving preUpdateToken logic here, since pre hooks induce race conditions\r\n */\r\n let tile = canvas.tiles.placeables.find(t => t.data.flags.turnMarker == true);\r\n if (tile) {\r\n if ((updateData.x || updateData.y || updateData.width || updateData.height || updateData.hidden) &&\r\n (game && game.combat && game.combat.combatant && game.combat.combatant.tokenId == updateToken._id) &&\r\n game.user.isGM && game.combat) {\r\n await Marker.moveMarkerToToken(updateToken._id, tile.id);\r\n tile.zIndex = Math.max(...canvas.tiles.placeables.map(o => o.zIndex)) + 1;\r\n tile.parent.sortChildren();\r\n }\r\n }\r\n});\r\n\r\nHooks.on('updateTile', async () => {\r\n if (canvas.scene.data.tokenVision) {\r\n let tile = canvas.tiles.placeables.find(t => t.data.flags.turnMarker == true);\r\n if (tile) {\r\n let combatant = canvas.tokens.placeables.find(x => x.id == game.combat.combatant.tokenId);\r\n if (combatant && !combatant.data.hidden) {\r\n tile.visible = canvas.sight.testVisibility(combatant.center, { tolerance: canvas.dimensions.size / 4 });\r\n }\r\n }\r\n }\r\n});\r\n\r\nHooks.on('pauseGame', async (isPaused) => {\r\n if (markerId && Settings.getShouldAnimate()) {\r\n if (isPaused) {\r\n MarkerAnimation.stopAnimation(animator);\r\n } else {\r\n animator = MarkerAnimation.startAnimation(animator, markerId);\r\n }\r\n }\r\n});\r\n","import { Settings } from './settings.js';\r\n\r\nexport function renderUpdateWindow() {\r\n const module = game.modules.get(\"turnmarker\");\r\n\r\n if (!isNewerVersion(module.data.version, Settings.getVersion()))\r\n return;\r\n\r\n class UpdateWindow extends Application {\r\n static get defaultOptions() {\r\n return mergeObject(super.defaultOptions, {\r\n template: `modules/${module.id}/templates/updateWindow.html`,\r\n resizable: false,\r\n width: 500,\r\n height: 600,\r\n classes: [\"updateWindow\"],\r\n title: `${module.data.title} - Updated`\r\n });\r\n }\r\n\r\n getData() {\r\n return {\r\n version: module.data.version\r\n };\r\n }\r\n\r\n activateListeners(html) {\r\n super.activateListeners(html);\r\n\r\n html.find('.show-again').on('change', ev => {\r\n Settings.setVersion(ev.currentTarget.checked ? module.data.version : oldVersion);\r\n });\r\n }\r\n }\r\n\r\n new UpdateWindow().render(true);\r\n}","\r\n/**\r\n * The name of the module\r\n */\r\nexport const modName = 'turnmarker';\r\n\r\n/*** Flag Info */\r\nexport const FlagScope = 'turnmarker';\r\nexport const Flags = {\r\n startMarkerPlaced: 'startMarkerPlaced'\r\n};\r\n\r\n/** Socket Info */\r\nexport const socketName = 'module.turnmarker';\r\nexport const socketAction = {\r\n placeStartMarker: 0\r\n};\r\n\r\n/**\r\n * Returns a token object from the canvas based on the ID value\r\n * @param {String} tokenId - The ID of the token to look for\r\n */\r\nexport function findTokenById(tokenId) {\r\n return canvas.tokens.ownedTokens.find(t => t.id == tokenId);\r\n}\r\n\r\n/**\r\n * Returns the ID of the first user logged in as GM.\r\n * Use for actions that need to be done by a GM but by only 1 GM\r\n */\r\nexport function firstGM() {\r\n for (let user of game.users.entities) {\r\n if (user.data.role >= 4 && user.active) {\r\n return user.data._id;\r\n }\r\n }\r\n return undefined;\r\n}","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tif(__webpack_module_cache__[moduleId]) {\n\t\treturn __webpack_module_cache__[moduleId].exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop)","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","// startup\n// Load entry module\n__webpack_require__(\"./src/scripts/turnmarker.js\");\n// This entry module used 'exports' so it can't be inlined\n"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack://turnmarker-alt/./src/scripts/chatter.js","webpack://turnmarker-alt/./src/scripts/marker.js","webpack://turnmarker-alt/./src/scripts/markeranimation.js","webpack://turnmarker-alt/./src/scripts/settings.js","webpack://turnmarker-alt/./src/scripts/settingsForm.js","webpack://turnmarker-alt/./src/scripts/turnmarker.js","webpack://turnmarker-alt/./src/scripts/updateWindow.js","webpack://turnmarker-alt/./src/scripts/utils.js","webpack://turnmarker-alt/webpack/bootstrap","webpack://turnmarker-alt/webpack/runtime/define property getters","webpack://turnmarker-alt/webpack/runtime/hasOwnProperty shorthand","webpack://turnmarker-alt/webpack/runtime/make namespace object","webpack://turnmarker-alt/webpack/startup"],"names":["Chatter","combatant","hideNPC_name","players","forEach","player","push","name","length","combatantName","actor","aliasName","Settings","token","hasPlayerOwner","ChatMessage","create","speaker","alias","content","this","placeImage","join","img","flags","core","thumb","Marker","tokenId","markerId","moveMarkerToToken","clearAllMarkers","findTokenById","dims","getImageDimensions","center","getImageLocation","newTile","Tile","width","w","height","h","x","y","z","rotation","hidden","data","locked","turnMarker","canvas","scene","createEmbeddedEntity","_id","to_delete","getEmbeddedCollection","filter","tile","startMarker","map","deleteEmbeddedEntity","game","user","isGM","setFlag","FlagScope","Flags","updateEmbeddedEntity","tiles","placeables","find","t","id","animator","MarkerAnimation","ignoreRatio","ratio","newWidth","newHeight","grid","type","newX","newY","tileId","getEmbeddedEntity","animateRotation","bind","app","ticker","add","remove","dt","delta","err","version","animation","interval","announce","announceActors","announceImage","announceTokenName","image","customimage","turnMarkerEnabled","startMarkerEnabled","startMarkerImage","imageTitles","announcedActorOptions","settings","get","modName","val","set","trim","getImageByIndex","index","registerMenu","label","icon","SettingsForm","restricted","register","default","String","scope","hint","config","Number","Boolean","choices","onChange","value","videos","FormApplication","object","options","super","mergeObject","defaultOptions","title","template","classes","closeOnSubmit","getSelectList","customImage","startMarkerPath","previewPath","e","d","console","log","html","activateListeners","markerSelect","markerImgPreview","updatePreview","on","event","attr","target","markerVideoPreview","disabled","removeClass","addClass","ext","getExtension","warn","includes","toLowerCase","filePath","slice","lastIndexOf","array","selected","i","lastTurn","Hooks","async","marker","zIndex","Math","max","o","parent","sortChildren","paused","isNewerVersion","modules","renderUpdateWindow","combat","update","started","userId","firstGM","result","undefined","unsetFlag","updateToken","updateData","tokenVision","tokens","visible","sight","testVisibility","tolerance","dimensions","size","isPaused","module","UpdateWindow","Application","resizable","ev","currentTarget","checked","oldVersion","render","startMarkerPlaced","socketName","socketAction","placeStartMarker","ownedTokens","users","entities","role","active","__webpack_module_cache__","__webpack_require__","moduleId","exports","__webpack_modules__","definition","key","Object","defineProperty","enumerable","obj","prop","prototype","hasOwnProperty","call","r","Symbol","toStringTag"],"mappings":"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","file":"turnmarker.js","sourcesContent":["import { Settings } from \"./settings.js\";\r\n\r\nexport class Chatter {\r\n\r\n static sendTurnMessage(combatant, hideNPC_name=false) {\r\n let players = [];\r\n combatant.players.forEach(player => {\r\n players.push(player.name);\r\n });\r\n if (players.length == 0) players.push(\"GM\");\r\n let combatantName = combatant.actor.name;\r\n let aliasName = combatantName;\r\n if (Settings.getAnnounceTokenName()) {\r\n combatantName = combatant.token.name;\r\n aliasName = combatant.name;\r\n }\r\n if (hideNPC_name && !combatant.actor.hasPlayerOwner) {\r\n combatantName = \"???\";\r\n }\r\n\r\n ChatMessage.create({\r\n speaker: { actor: combatant.actor, alias: aliasName },\r\n //speaker: { actor: {}, alias: 'Turn Marker' },\r\n content:\r\n `
${this.placeImage(combatant)}\r\n
\r\n

${combatantName}'s Turn

\r\n

${players.join(' - ')}

\r\n
\r\n
Turn Marker`\r\n });\r\n }\r\n\r\n static placeImage(combatant) {\r\n if (Settings.getIncludeAnnounceImage()) {\r\n let img = combatant.img;\r\n if (combatant.flags.core && combatant.flags.core.thumb) {\r\n img = combatant.flags.core.thumb;\r\n }\r\n return `
`;\r\n // return `
`;\r\n } else return '';\r\n }\r\n}","import { MarkerAnimation } from './markeranimation.js';\r\nimport { Settings } from './settings.js';\r\nimport { findTokenById, Flags, FlagScope, socketAction, socketName } from './utils.js';\r\n\r\n/**\r\n * Provides functionality for creating, moving, and animating the turn marker\r\n */\r\nexport class Marker {\r\n\r\n /**\r\n * Places a new turn marker under the token specified, and if required, starts the animation\r\n * @param {String} tokenId - The ID of the token where the marker should be placed\r\n * @param {Object} animator - The animator object\r\n * @param {String} markerId - The ID of the tile being used as the turn marker\r\n */\r\n static async placeTurnMarker(tokenId, markerId) {\r\n if (!markerId) {\r\n this.clearAllMarkers();\r\n\r\n if (Settings.getTurnMarkerEnabled()) {\r\n let token = findTokenById(tokenId);\r\n let ratio = Settings.getRatio();\r\n let dims = this.getImageDimensions(token);\r\n let center = this.getImageLocation(token);\r\n\r\n let newTile = new Tile({\r\n img: Settings.getImagePath(),\r\n width: dims.w,\r\n height: dims.h,\r\n x: center.x,\r\n y: center.y,\r\n z: 900,\r\n rotation: 0,\r\n hidden: token.data.hidden,\r\n locked: false,\r\n flags: { turnMarker: true }\r\n });\r\n\r\n let tile = await canvas.scene.createEmbeddedEntity('Tile', newTile.data);\r\n\r\n return tile._id;\r\n } else {\r\n return null;\r\n }\r\n } else {\r\n this.moveMarkerToToken(tokenId, markerId);\r\n return markerId;\r\n }\r\n }\r\n\r\n /**\r\n * Deletes any tiles flagged as a 'Start Marker' from the canvas\r\n */\r\n static async deleteStartMarker() {\r\n const to_delete = canvas.scene.getEmbeddedCollection('Tile')\r\n .filter(tile => tile.flags.startMarker)\r\n .map(tile => tile._id);\r\n await canvas.scene.deleteEmbeddedEntity('Tile', to_delete);\r\n }\r\n\r\n /**\r\n * If enabled in settings, place a \"start\" marker under the token where their turn started.\r\n * @param {String} tokenId - The ID of the token to place the start marker under\r\n */\r\n static async placeStartMarker(tokenId) {\r\n if (Settings.getStartMarkerEnabled()) {\r\n let token = findTokenById(tokenId);\r\n let dims = this.getImageDimensions(token);\r\n let center = this.getImageLocation(token);\r\n let newTile = new Tile({\r\n img: Settings.getStartMarker(),\r\n width: dims.w,\r\n height: dims.h,\r\n x: center.x,\r\n y: center.y,\r\n z: 900,\r\n rotation: 0,\r\n hidden: token.data.hidden,\r\n locked: false,\r\n flags: { startMarker: true }\r\n });\r\n\r\n if (game.user.isGM) {\r\n canvas.scene.createEmbeddedEntity('Tile', newTile.data);\r\n canvas.scene.setFlag(FlagScope, Flags.startMarkerPlaced, true);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Moves the turn marker tile under the specified token\r\n * @param {String} tokenId - The ID of the token that the marker should be placed under\r\n * @param {String} markerId - The ID of the tile currently serving as the turn marker\r\n */\r\n static async moveMarkerToToken(tokenId, markerId) {\r\n let token = findTokenById(tokenId);\r\n let ratio = Settings.getRatio();\r\n let dims = this.getImageDimensions(token);\r\n let center = this.getImageLocation(token);\r\n\r\n await canvas.scene.updateEmbeddedEntity('Tile', {\r\n _id: markerId,\r\n width: dims.w,\r\n height: dims.h,\r\n x: center.x,\r\n y: center.y,\r\n hidden: token.data.hidden\r\n });\r\n }\r\n\r\n /**\r\n * Removes any existing turn marker and start marker tiles from the canvas\r\n */\r\n static async clearAllMarkers() {\r\n let tiles = canvas.scene.getEmbeddedCollection('Tile');\r\n\r\n for (let tile of tiles) {\r\n if (tile.flags.turnMarker || tile.flags.startMarker) {\r\n await canvas.scene.deleteEmbeddedEntity('Tile', tile._id);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Updates the tile image when the image path has changed\r\n */\r\n static updateImagePath() {\r\n if (game.user.isGM) {\r\n let tile = canvas.tiles.placeables.find(t => t.data.flags.turnMarker == true);\r\n if (tile) {\r\n canvas.scene.updateEmbeddedEntity('Tile', {\r\n _id: tile.id,\r\n img: Settings.getImagePath()\r\n });\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Completely resets the turn marker - deletes all tiles and stops any animation\r\n * @param {Object} animator - The animator object\r\n */\r\n static reset(animator) {\r\n MarkerAnimation.stopAnimation(animator);\r\n this.clearAllMarkers();\r\n }\r\n\r\n /**\r\n * Gets the proper dimensions of the marker tile taking into account the current grid layout\r\n * @param {object} token - The token that the tile should be placed under\r\n */\r\n static getImageDimensions(token, ignoreRatio = false) {\r\n let ratio = ignoreRatio ? 1 : Settings.getRatio();\r\n let newWidth = 0;\r\n let newHeight = 0;\r\n\r\n switch (canvas.grid.type) {\r\n case 2: case 3: // Hex Rows\r\n newWidth = newHeight = token.h * ratio;\r\n break;\r\n case 4: case 5: // Hex Columns\r\n newWidth = newHeight = token.w * ratio;\r\n break;\r\n default: // Gridless and Square\r\n newWidth = token.w * ratio;\r\n newHeight = token.h * ratio;\r\n break;\r\n }\r\n\r\n return { w: newWidth, h: newHeight };\r\n }\r\n\r\n /**\r\n * Gets the proper location of the marker tile taking into account the current grid layout\r\n * @param {object} token - The token that the tile should be placed under\r\n */\r\n static getImageLocation(token, ignoreRatio = false) {\r\n let ratio = ignoreRatio ? 1 : Settings.getRatio();\r\n let newX = 0;\r\n let newY = 0;\r\n\r\n switch (canvas.grid.type) {\r\n case 2: case 3: // Hex Rows\r\n newX = token.center.x - ((token.h * ratio) / 2);\r\n newY = token.center.y - ((token.h * ratio) / 2);\r\n break;\r\n case 4: case 5: // Hex Columns\r\n newX = token.center.x - ((token.w * ratio) / 2);\r\n newY = token.center.y - ((token.w * ratio) / 2);\r\n break;\r\n default: // Gridless and Square\r\n newX = token.center.x - ((token.w * ratio) / 2);\r\n newY = token.center.y - ((token.h * ratio) / 2);\r\n }\r\n\r\n return { x: newX, y: newY };\r\n }\r\n}","import { Settings } from './settings.js';\r\n\r\nexport class MarkerAnimation {\r\n /**\r\n * Starts the animation loop for the specified tile\r\n * @param {object} animator - The animator object\r\n * @param {String} tileId - The ID of the tile currently serving as the turn marker \r\n */\r\n static startAnimation(animator, tileId) {\r\n let tile = canvas.scene.getEmbeddedEntity('Tile', tileId);\r\n animator = this.animateRotation.bind(tile);\r\n canvas.app.ticker.add(animator);\r\n return animator;\r\n }\r\n\r\n /**\r\n * Stops the animation loop for the specified tile\r\n * @param {object} animator - The animator object\r\n */\r\n static stopAnimation(animator) {\r\n canvas.app.ticker.remove(animator);\r\n }\r\n\r\n /**\r\n * Called on every tick of the animation loop to rotate the image based on the current frame\r\n * @param {number} dt - The delta time\r\n */\r\n static animateRotation(dt) {\r\n let tile = canvas.tiles.placeables.find(t => t.data.flags.turnMarker == true);\r\n if (tile && tile.data.img) {\r\n let delta = Settings.getInterval() / 10000;\r\n try {\r\n tile.tile.img.rotation += (delta * dt);\r\n } catch (err) {\r\n // skip lost frames if the tile is being updated by the server\r\n }\r\n }\r\n }\r\n}","import { Marker } from './marker.js';\r\nimport { SettingsForm } from './settingsForm.js';\r\nimport { modName } from './utils.js';\r\n\r\nconst version = 'tm-version';\r\nconst ratio = 'ratio';\r\nconst animation = 'animation';\r\nconst interval = 'interval';\r\nconst announce = 'announce-turn';\r\nconst announceActors = 'announce-Actors';\r\nconst announceAsActor = 'announce-asActor';\r\nconst announceImage = 'announce-image';\r\nconst announceTokenName = 'announce-token';\r\nconst image = 'image';\r\nconst customimage = 'customimage';\r\nconst turnMarkerEnabled = 'turnmarker-enabled';\r\nconst startMarkerEnabled = 'startMarker-enabled';\r\nconst startMarkerImage = 'startMarker-custom';\r\nexport const imageTitles = [\r\n 'Runes of Incendium by Rin',\r\n 'Runes of the Cultist by Rin',\r\n 'Runes of Regeneration by Rin',\r\n 'Runes of the Cosmos by Rin',\r\n 'Runes of Earthly Dust by Rin',\r\n 'Runes of Reality by Rin',\r\n 'Runes of the Believer by Rin',\r\n 'Runes of the Mad Mage by Rin',\r\n 'Runes of the Blue Sky by Rin',\r\n 'Runes of the Universe by Rin',\r\n 'Runes of Prosperity by Rin'\r\n];\r\n\r\nexport const announcedActorOptions = [\r\n 'Announce for all',\r\n 'Announce for players',\r\n 'Announce for GM-controlled',\r\n 'Announce all but hide GM-controlled names'\r\n];\r\n\r\n/**\r\n * Provides functionality for reading and writing module settings\r\n */\r\nexport class Settings {\r\n\r\n static getVersion() {\r\n return game.settings.get(modName, version);\r\n }\r\n\r\n static setVersion(val) {\r\n game.settings.set(modName, version, val);\r\n }\r\n\r\n /**\r\n * Gets the image ratio\r\n */\r\n static getRatio() {\r\n return game.settings.get(modName, ratio);\r\n }\r\n\r\n /**\r\n * Sets the image ratio\r\n * @param {Number} val - The image ratio\r\n */\r\n static setRatio(val) {\r\n game.settings.set(modName, ratio, val);\r\n }\r\n\r\n /**\r\n * Returns true if the marker should be animated\r\n */\r\n static getShouldAnimate() {\r\n return game.settings.get(modName, animation);\r\n }\r\n\r\n /**\r\n * Gets the animation interval in ms.\r\n */\r\n static getInterval() {\r\n return game.settings.get(modName, interval);\r\n }\r\n\r\n /**\r\n * Returns true if turn changes should be announced in chat\r\n */\r\n static shouldAnnounceTurns() {\r\n return game.settings.get(modName, announce);\r\n }\r\n\r\n /**\r\n * Sets whether or not to announce turn changes\r\n * @param {Boolean} val - Whether or not to announce turn changes\r\n */\r\n static setShouldAnnounceTurns(val) {\r\n game.settings.set(modName, announce, val);\r\n }\r\n\r\n\r\n /**\r\n * Gets index of setting\r\n * @returns {Number} - Index number of announced\r\n */\r\n static getAnnounceActors() {\r\n return game.settings.get(modName, announceActors);\r\n }\r\n\r\n /**\r\n * Sets who sees announced turn changes\r\n * @param announceActors - which owners get units announcedActorOptions, which is selected.\r\n */\r\n static setAnnounceActors(val) {\r\n return game.settings.set(modName, announceActors, val);\r\n }\r\n\r\n static getAnnounceTokenName() {\r\n return game.settings.get(modName, announceTokenName);\r\n }\r\n\r\n static setAnnounceTokenName(val) {\r\n return game.settings.set(modName, announceTokenName, val);\r\n }\r\n\r\n static getIncludeAnnounceImage() {\r\n return game.settings.get(modName, announceImage);\r\n }\r\n\r\n static setIncludeAnnounceImage(val) {\r\n game.settings.set(modName, announceImage, val);\r\n }\r\n\r\n /**\r\n * Gets the index of the currently selected marker image\r\n */\r\n static getImageIndex() {\r\n return game.settings.get(modName, image);\r\n }\r\n\r\n static getStartMarker() {\r\n if (game.settings.get(modName, startMarkerImage).trim() == '') {\r\n return 'modules/turnmarker/assets/start.png';\r\n } else {\r\n return game.settings.get(modName, startMarkerImage);\r\n }\r\n }\r\n\r\n static getTurnMarkerEnabled() {\r\n return game.settings.get(modName, turnMarkerEnabled);\r\n }\r\n\r\n\r\n static setTurnMarkerEnabled(val) {\r\n game.settings.set(modName, turnMarkerEnabled, val);\r\n }\r\n\r\n static getStartMarkerEnabled() {\r\n return game.settings.get(modName, startMarkerEnabled);\r\n }\r\n\r\n static setStartMarkerEnabled(val) {\r\n game.settings.set(modName, startMarkerEnabled, val);\r\n }\r\n\r\n static getStartMarkerPath() {\r\n return game.settings.get(modName, startMarkerImage);\r\n }\r\n\r\n static setStartMarkerPath(val) {\r\n game.settings.set(modName, startMarkerImage, val);\r\n }\r\n\r\n /**\r\n * Gets a path to the currently selected image to be used as the marker\r\n */\r\n static getImagePath() {\r\n if (game.settings.get(modName, customimage).trim() == '') {\r\n return this.getImageByIndex(game.settings.get(modName, image));\r\n } else {\r\n return game.settings.get(modName, customimage);\r\n }\r\n }\r\n\r\n static getImageByIndex(index) {\r\n switch (index) {\r\n case 0: return 'modules/turnmarker/assets/incendium.png';\r\n case 1: return 'modules/turnmarker/assets/cultist.png';\r\n case 2: return 'modules/turnmarker/assets/regeneration.png';\r\n case 3: return 'modules/turnmarker/assets/cosmos.png';\r\n case 4: return 'modules/turnmarker/assets/earthlydust.png';\r\n case 5: return 'modules/turnmarker/assets/reality.png';\r\n case 6: return 'modules/turnmarker/assets/believer.png';\r\n case 7: return 'modules/turnmarker/assets/madmage.png';\r\n case 8: return 'modules/turnmarker/assets/bluesky.png';\r\n case 9: return 'modules/turnmarker/assets/universe.png';\r\n case 10: return 'modules/turnmarker/assets/prosperity.png';\r\n }\r\n }\r\n\r\n static setImage(val) {\r\n game.settings.set(modName, image, val);\r\n }\r\n\r\n static getCustomImagePath() {\r\n return game.settings.get(modName, customimage);\r\n }\r\n\r\n static setCustomImagePath(val) {\r\n game.settings.set(modName, customimage, val);\r\n }\r\n\r\n /**\r\n * Registers all game settings\r\n */\r\n static registerSettings() {\r\n\r\n game.settings.registerMenu(modName, 'tm.settingsMenu', {\r\n name: 'tm.settings.button.name',\r\n label: 'tm.settings.button.label',\r\n icon: 'fas fa-sync-alt',\r\n type: SettingsForm,\r\n restricted: true,\r\n });\r\n\r\n game.settings.register(modName, version, {\r\n name: `${modName} version`,\r\n default: '0.0.0',\r\n type: String,\r\n scope: 'world',\r\n });\r\n\r\n game.settings.register(modName, ratio, {\r\n name: 'tm.settings.ratio.name',\r\n hint: 'tm.settings.ratio.hint',\r\n scope: 'world',\r\n config: false,\r\n type: Number,\r\n default: 1.5,\r\n restricted: true\r\n });\r\n\r\n game.settings.register(modName, animation, {\r\n name: 'tm.settings.animate.name',\r\n hint: 'tm.settings.animate.hint',\r\n scope: 'user',\r\n config: true,\r\n type: Boolean,\r\n default: true,\r\n });\r\n\r\n game.settings.register(modName, interval, {\r\n name: 'tm.settings.interval.name',\r\n hint: 'tm.settings.interval.hint',\r\n scope: 'user',\r\n config: true,\r\n type: Number,\r\n default: 100\r\n });\r\n\r\n game.settings.register(modName, image, {\r\n name: 'tm.settings.image.name',\r\n scope: 'world',\r\n config: false,\r\n type: Number,\r\n default: 0,\r\n choices: imageTitles,\r\n restricted: true,\r\n onChange: value => Marker.updateImagePath(value)\r\n });\r\n\r\n game.settings.register(modName, announceActors, {\r\n name: 'tm.settings.announcedActors.name',\r\n hint: 'tm.settings.announcedActors.hint',\r\n scope: 'world',\r\n config: false,\r\n type: Number,\r\n default: 0,\r\n restricted: true,\r\n choices: announcedActorOptions,\r\n });\r\n\r\n game.settings.register(modName, announceTokenName, {\r\n name: 'tm.settings.announceTokenName.name',\r\n hint: 'tm.settings.announceTokenName.hint',\r\n scope: 'world',\r\n config: false,\r\n type: Boolean,\r\n default: false,\r\n restricted: true,\r\n });\r\n\r\n game.settings.register(modName, customimage, {\r\n name: 'tm.settings.customImage.name',\r\n hint: 'tm.settings.customImage.hint',\r\n scope: 'world',\r\n config: false,\r\n type: String,\r\n default: '',\r\n restricted: true,\r\n onChange: value => Marker.updateImagePath(value)\r\n });\r\n\r\n game.settings.register(modName, announce, {\r\n name: 'tm.settings.announce.name',\r\n hint: 'tm.settings.announce.hint',\r\n scope: 'world',\r\n config: false,\r\n type: Boolean,\r\n default: true\r\n });\r\n\r\n game.settings.register(modName, announceImage, {\r\n name: 'tm.settings.announceImage.name',\r\n hint: 'tm.settings.announceImage.hint',\r\n scope: 'world',\r\n config: false,\r\n type: Boolean,\r\n default: true\r\n });\r\n\r\n game.settings.register(modName, announceAsActor, {\r\n name: 'tm.settings.announceAs.name',\r\n hint: 'tm.settings.announceAs.hint',\r\n scope: 'world',\r\n config: false,\r\n type: Boolean,\r\n default: true\r\n });\r\n\r\n game.settings.register(modName, turnMarkerEnabled, {\r\n name: 'tm.settings.turnMarkerEnabled.name',\r\n hint: 'tm.settings.turnMarkerEnabled.hint',\r\n scope: 'world',\r\n config: false,\r\n type: Boolean,\r\n default: true,\r\n restricted: true\r\n });\r\n\r\n game.settings.register(modName, startMarkerEnabled, {\r\n name: 'tm.settings.startEnabled.name',\r\n hint: 'tm.settings.startEnabled.hint',\r\n scope: 'world',\r\n config: false,\r\n type: Boolean,\r\n default: false,\r\n restricted: true\r\n });\r\n\r\n game.settings.register(modName, startMarkerImage, {\r\n name: 'tm.settings.startImage.name',\r\n hint: 'tm.settings.startImage.hint',\r\n scope: 'world',\r\n config: false,\r\n type: String,\r\n default: '',\r\n restricted: true\r\n });\r\n }\r\n}","import { imageTitles, announcedActorOptions, Settings } from './settings.js';\r\n\r\nconst videos = ['mp4', 'webm', 'ogg'];\r\n\r\nexport class SettingsForm extends FormApplication {\r\n\r\n constructor(object, options = {}) {\r\n super(object, options);\r\n }\r\n\r\n /**\r\n * Default Options for this FormApplication\r\n */\r\n static get defaultOptions() {\r\n return mergeObject(super.defaultOptions, {\r\n id: 'turnmarker-settings-form',\r\n title: 'Turn Marker - Global Settings',\r\n template: './modules/turnmarker/templates/settings.html',\r\n classes: ['sheet', 'tm-settings'],\r\n width: 500,\r\n closeOnSubmit: true\r\n });\r\n }\r\n\r\n getData() {\r\n return {\r\n turnMarkerEnabled: Settings.getTurnMarkerEnabled(),\r\n ratio: Settings.getRatio(),\r\n image: this.getSelectList(imageTitles, Settings.getImageIndex()),\r\n announceActors: this.getSelectList(announcedActorOptions, Settings.getAnnounceActors()),\r\n customImage: Settings.getCustomImagePath(),\r\n announce: Settings.shouldAnnounceTurns(),\r\n announceImage: Settings.getIncludeAnnounceImage(),\r\n announceTokenName :Settings.getAnnounceTokenName(),\r\n startMarkerEnabled: Settings.getStartMarkerEnabled(),\r\n startMarkerPath: Settings.getStartMarkerPath(),\r\n previewPath: Settings.getImagePath()\r\n };\r\n }\r\n\r\n /** \r\n * Executes on form submission.\r\n * @param {Object} e - the form submission event\r\n * @param {Object} d - the form data\r\n */\r\n async _updateObject(e, d) {\r\n console.log('Turn Marker | Saving Settings');\r\n Settings.setRatio(d.ratio);\r\n if (d.image) Settings.setImage(d.image);\r\n Settings.setCustomImagePath(d.customImage);\r\n Settings.setShouldAnnounceTurns(d.announce);\r\n Settings.setAnnounceActors(d.announceActors);\r\n Settings.setIncludeAnnounceImage(d.announceImage);\r\n Settings.setAnnounceTokenName(d.announceTokenName);\r\n Settings.setTurnMarkerEnabled(d.turnMarkerEnabled);\r\n Settings.setStartMarkerEnabled(d.startMarkerEnabled);\r\n Settings.setStartMarkerPath(d.startMarkerPath);\r\n }\r\n\r\n activateListeners(html) {\r\n super.activateListeners(html);\r\n const markerSelect = html.find('#image');\r\n const customImage = html.find('#customImage');\r\n const markerImgPreview = html.find('#markerImgPreview');\r\n\r\n this.updatePreview(html);\r\n\r\n if (markerSelect.length > 0) {\r\n markerSelect.on('change', event => {\r\n if (customImage[0].value.trim() == '') {\r\n markerImgPreview.attr('src', Settings.getImageByIndex(Number(event.target.value)));\r\n }\r\n });\r\n }\r\n\r\n if (customImage.length > 0) {\r\n customImage.on('change', event => {\r\n this.updatePreview(html);\r\n });\r\n }\r\n }\r\n\r\n updatePreview(html) {\r\n const markerSelect = html.find('#image');\r\n const customImage = html.find('#customImage');\r\n const markerImgPreview = html.find('#markerImgPreview');\r\n const markerVideoPreview = html.find('#markerVideoPreview');\r\n\r\n if (customImage[0].value.trim() == '') {\r\n markerSelect[0].disabled = false;\r\n markerImgPreview.attr('src', Settings.getImageByIndex(Number(markerSelect[0].value)));\r\n markerImgPreview.removeClass('hidden');\r\n markerVideoPreview.addClass('hidden');\r\n } else {\r\n markerSelect[0].disabled = true;\r\n const ext = this.getExtension(customImage[0].value);\r\n console.warn(ext);\r\n if (videos.includes(ext.toLowerCase())) {\r\n markerVideoPreview.attr('src', customImage[0].value);\r\n markerImgPreview.addClass('hidden');\r\n markerVideoPreview.removeClass('hidden');\r\n } else {\r\n markerImgPreview.attr('src', customImage[0].value);\r\n markerImgPreview.removeClass('hidden');\r\n markerVideoPreview.addClass('hidden');\r\n }\r\n }\r\n }\r\n\r\n getExtension(filePath) {\r\n return filePath.slice((filePath.lastIndexOf(\".\") - 1 >>> 0) + 2);\r\n }\r\n\r\n getSelectList(array, selected) {\r\n let options = [];\r\n array.forEach((x, i) => {\r\n options.push({ value: x, selected: i == selected });\r\n });\r\n return options;\r\n }\r\n}","import { Chatter } from './chatter.js';\r\nimport { Marker } from './marker.js';\r\nimport { MarkerAnimation } from './markeranimation.js';\r\nimport { Settings } from './settings.js';\r\nimport { renderUpdateWindow } from './updateWindow.js';\r\nimport { firstGM, Flags, FlagScope, socketAction, socketName } from './utils.js';\r\n\r\nlet animator;\r\nlet markerId;\r\nlet lastTurn = '';\r\n\r\n\r\nHooks.on('ready', async () => {\r\n Settings.registerSettings();\r\n let marker = canvas.tiles.placeables.find(t => t.data.flags.turnMarker == true);\r\n if (marker && marker.id) {\r\n markerId = marker.id;\r\n let tile = canvas.tiles.placeables.find(t => t.data.flags.turnMarker == true);\r\n tile.zIndex = Math.max(...canvas.tiles.placeables.map(o => o.zIndex)) + 1;\r\n tile.parent.sortChildren();\r\n if (!game.paused && Settings.getShouldAnimate()) {\r\n animator = MarkerAnimation.startAnimation(animator, markerId);\r\n }\r\n }\r\n\r\n if (game.user.isGM) {\r\n if (isNewerVersion(game.modules.get(\"turnmarker\").data.version, Settings.getVersion())) {\r\n renderUpdateWindow();\r\n }\r\n }\r\n});\r\n\r\nHooks.on('createTile', (scene, tile) => {\r\n if (tile.flags.turnMarker == true) {\r\n markerId = tile._id;\r\n tile = canvas.tiles.placeables.find(t => t.data.flags.turnMarker == true);\r\n tile.zIndex = Math.max(...canvas.tiles.placeables.map(o => o.zIndex)) + 1;\r\n tile.parent.sortChildren();\r\n if (Settings.getShouldAnimate()) {\r\n animator = MarkerAnimation.startAnimation(animator, markerId);\r\n }\r\n }\r\n});\r\n\r\n\r\nHooks.on('updateCombat', async (combat, update) => {\r\n // Clear out any leftovers, there seems to be a buggy instance where updateCombat is fired, when combat isn't\r\n // started nor, is a turn changed\r\n if (!combat.started) {\r\n await Marker.deleteStartMarker();\r\n }\r\n if (combat.combatant) {\r\n if (update && lastTurn != combat.combatant._id && game.user.isGM && game.userId == firstGM()) {\r\n lastTurn = combat.combatant._id;\r\n if (combat && combat.combatant && combat.started) {\r\n await Marker.placeStartMarker(game.combat.combatant.token._id)\r\n let tile = canvas.tiles.placeables.find(t => t.data.flags.turnMarker == true);\r\n let result = await Marker.placeTurnMarker(combat.combatant.token._id, (tile && tile.id) || undefined);\r\n if (result) {\r\n markerId = result.markerId;\r\n animator = result.animator;\r\n }\r\n if (Settings.getTurnMarkerEnabled()) {\r\n await Marker.deleteStartMarker();\r\n canvas.scene.unsetFlag(FlagScope, Flags.startMarkerPlaced);\r\n }\r\n if (Settings.shouldAnnounceTurns() && !combat.combatant.hidden) {\r\n switch (Settings.getAnnounceActors()) {\r\n case 0:\r\n Chatter.sendTurnMessage(combat.combatant);\r\n break;\r\n case 1:\r\n if (combat.combatant.actor.hasPlayerOwner) {\r\n Chatter.sendTurnMessage(combat.combatant);\r\n }\r\n break;\r\n case 2:\r\n if (!combat.combatant.actor.hasPlayerOwner) {\r\n Chatter.sendTurnMessage(combat.combatant);\r\n }\r\n break;\r\n case 3:\r\n Chatter.sendTurnMessage(combat.combatant, true);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n});\r\n\r\nHooks.on('deleteCombat', async () => {\r\n if (game.user.isGM) {\r\n await Marker.clearAllMarkers();\r\n }\r\n MarkerAnimation.stopAnimation(animator);\r\n});\r\n\r\nHooks.on('updateToken', async (scene, updateToken, updateData) => {\r\n /*\r\n Moving preUpdateToken logic here, since pre hooks induce race conditions\r\n */\r\n let tile = canvas.tiles.placeables.find(t => t.data.flags.turnMarker == true);\r\n if (tile) {\r\n if ((updateData.x || updateData.y || updateData.width || updateData.height || updateData.hidden) &&\r\n (game && game.combat && game.combat.combatant && game.combat.combatant.tokenId == updateToken._id) &&\r\n game.user.isGM && game.combat) {\r\n await Marker.moveMarkerToToken(updateToken._id, tile.id);\r\n tile.zIndex = Math.max(...canvas.tiles.placeables.map(o => o.zIndex)) + 1;\r\n tile.parent.sortChildren();\r\n }\r\n }\r\n});\r\n\r\nHooks.on('updateTile', async () => {\r\n if (canvas.scene.data.tokenVision) {\r\n let tile = canvas.tiles.placeables.find(t => t.data.flags.turnMarker == true);\r\n if (tile) {\r\n let combatant = canvas.tokens.placeables.find(x => x.id == game.combat.combatant.tokenId);\r\n if (combatant && !combatant.data.hidden) {\r\n tile.visible = canvas.sight.testVisibility(combatant.center, { tolerance: canvas.dimensions.size / 4 });\r\n }\r\n }\r\n }\r\n});\r\n\r\nHooks.on('pauseGame', async (isPaused) => {\r\n if (markerId && Settings.getShouldAnimate()) {\r\n if (isPaused) {\r\n MarkerAnimation.stopAnimation(animator);\r\n } else {\r\n animator = MarkerAnimation.startAnimation(animator, markerId);\r\n }\r\n }\r\n});\r\n","import { Settings } from './settings.js';\r\n\r\nexport function renderUpdateWindow() {\r\n const module = game.modules.get(\"turnmarker\");\r\n\r\n if (!isNewerVersion(module.data.version, Settings.getVersion()))\r\n return;\r\n\r\n class UpdateWindow extends Application {\r\n static get defaultOptions() {\r\n return mergeObject(super.defaultOptions, {\r\n template: `modules/${module.id}/templates/updateWindow.html`,\r\n resizable: false,\r\n width: 500,\r\n height: 600,\r\n classes: [\"updateWindow\"],\r\n title: `${module.data.title} - Updated`\r\n });\r\n }\r\n\r\n getData() {\r\n return {\r\n version: module.data.version\r\n };\r\n }\r\n\r\n activateListeners(html) {\r\n super.activateListeners(html);\r\n\r\n html.find('.show-again').on('change', ev => {\r\n Settings.setVersion(ev.currentTarget.checked ? module.data.version : oldVersion);\r\n });\r\n }\r\n }\r\n\r\n new UpdateWindow().render(true);\r\n}","\r\n/**\r\n * The name of the module\r\n */\r\nexport const modName = 'turnmarker';\r\n\r\n/*** Flag Info */\r\nexport const FlagScope = 'turnmarker';\r\nexport const Flags = {\r\n startMarkerPlaced: 'startMarkerPlaced'\r\n};\r\n\r\n/** Socket Info */\r\nexport const socketName = 'module.turnmarker';\r\nexport const socketAction = {\r\n placeStartMarker: 0\r\n};\r\n\r\n/**\r\n * Returns a token object from the canvas based on the ID value\r\n * @param {String} tokenId - The ID of the token to look for\r\n */\r\nexport function findTokenById(tokenId) {\r\n return canvas.tokens.ownedTokens.find(t => t.id == tokenId);\r\n}\r\n\r\n/**\r\n * Returns the ID of the first user logged in as GM.\r\n * Use for actions that need to be done by a GM but by only 1 GM\r\n */\r\nexport function firstGM() {\r\n for (let user of game.users.entities) {\r\n if (user.data.role >= 4 && user.active) {\r\n return user.data._id;\r\n }\r\n }\r\n return undefined;\r\n}","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tif(__webpack_module_cache__[moduleId]) {\n\t\treturn __webpack_module_cache__[moduleId].exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop)","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","// startup\n// Load entry module\n__webpack_require__(\"./src/scripts/turnmarker.js\");\n// This entry module used 'exports' so it can't be inlined\n"],"sourceRoot":""} \ No newline at end of file diff --git a/dist/templates/updateWindow.html b/dist/templates/updateWindow.html index 6fa64fb..8e84f93 100644 --- a/dist/templates/updateWindow.html +++ b/dist/templates/updateWindow.html @@ -23,6 +23,15 @@

Want to support development?

Important Changes

Below are just some of the changes to the module that should be called out. The full changelog is also available here.

+

v2.7.1

+ +

+

v2.7.0

-

v2.6.9