diff --git a/TurnMarker1/TurnMarker.js b/TurnMarker1/TurnMarker.js deleted file mode 100644 index f8bcfe804a..0000000000 --- a/TurnMarker1/TurnMarker.js +++ /dev/null @@ -1,738 +0,0 @@ -// Github: https://github.com/shdwjk/Roll20API/blob/master/TurnMarker1/TurnMarker.js -// By: The Aaron, Arcane Scriptomancer -// Contact: https://app.roll20.net/users/104025/the-aaron - -/* ############################################################### */ -/* TurnMarker */ -/* ############################################################### */ - -var TurnMarker = TurnMarker || { - version: 1.22, - schemaVersion: 1.16, - active: false, - threadSync: 1, - - CheckInstall: function() { - if( ! state.hasOwnProperty('TurnMarker') || state.TurnMarker.version != TurnMarker.schemaVersion) - { - /* Default Settings stored in the state. */ - state.TurnMarker = { - version: TurnMarker.version, - announceRounds: true, - announceTurnChange: true, - announcePlayerInTurnAnnounce: true, - announcePlayerInTurnAnnounceSize: '100%', - autoskipHidden: true, - tokenName: 'Round', - tokenURL: 'https://s3.amazonaws.com/files.d20.io/images/4095816/086YSl3v0Kz3SlDAu245Vg/thumb.png?1400535580', - playAnimations: false, - rotation: false, - animationSpeed: 5, - scale: 1.7, - aura1: { - pulse: false, - size: 5, - color: '#ff00ff' - }, - aura2: { - pulse: false, - size: 5, - color: '#00ff00' - } - } - } - if(Campaign().get('turnorder') =='') - { - Campaign().set('turnorder','[]'); - } - }, - - GetMarker: function(){ - var marker = findObjs({ - imgsrc: state.TurnMarker.tokenURL, - pageid: Campaign().get("playerpageid") - })[0]; - - if (marker === undefined) { - marker = createObj('graphic', { - name: state.TurnMarker.tokenName+' 0', - pageid: Campaign().get("playerpageid"), - layer: 'gmlayer', - imgsrc: state.TurnMarker.tokenURL, - left: 0, - top: 0, - height: 70, - width: 70, - bar2_value: 0, - showplayers_name: true, - showplayers_aura1: true, - showplayers_aura2: true - }); - marker=fixNewObject(marker); - } - if(!TurnOrder.HasTurn(marker.id)) - { - TurnOrder.AddTurn({ - id: marker.id, - pr: -1, - custom: "", - pageid: marker.get('pageid') - }); - } - return marker; - }, - - Step: function( sync ){ - if (!state.TurnMarker.playAnimations || sync != TurnMarker.threadSync) - { - return; - } - var marker=TurnMarker.GetMarker(); - if(TurnMarker.active === true) - { - var rotation=(marker.get('bar1_value')+state.TurnMarker.animationSpeed)%360; - marker.set('bar1_value', rotation ); - if(state.TurnMarker.rotation) - { - marker.set( 'rotation', rotation ); - } - if( state.TurnMarker.aura1.pulse ) - { - marker.set('aura1_radius', Math.abs(Math.sin(rotation * (Math.PI/180))) * state.TurnMarker.aura1.size ); - } - else - { - marker.set('aura1_radius',''); - } - if( state.TurnMarker.aura2.pulse ) - { - marker.set('aura2_radius', Math.abs(Math.cos(rotation * (Math.PI/180))) * state.TurnMarker.aura2.size ); - } - else - { - marker.set('aura2_radius',''); - } - setTimeout(_.bind(TurnMarker.Step,this,sync), 100); - } - }, - - Reset: function() { - TurnMarker.active=false; - TurnMarker.threadSync++; - - var marker = TurnMarker.GetMarker(); - - marker.set({ - layer: "gmlayer", - aura1_radius: '', - aura2_radius: '', - left: 35, - top: 35, - height: 70, - width: 70, - rotation: 0, - bar1_value: 0 - }); - }, - - Start: function() { - var marker = TurnMarker.GetMarker(); - - - if(state.TurnMarker.playAnimations && state.TurnMarker.aura1.pulse) - { - marker.set({ - aura1_radius: state.TurnMarker.aura1.size, - aura1_color: state.TurnMarker.aura1.color, - }); - } - if(state.TurnMarker.playAnimations && state.TurnMarker.aura2.pulse) - { - marker.set({ - aura2_radius: state.TurnMarker.aura2.size, - aura2_color: state.TurnMarker.aura2.color, - }); - } - TurnMarker.active=true; - TurnMarker.Step(TurnMarker.threadSync); - TurnMarker.TurnOrderChange(false); - }, - - HandleInput: function(tokens,who){ - switch (tokens[0]) - { - case 'reset': - var marker = TurnMarker.GetMarker(); - marker.set({ - name: state.TurnMarker.tokenName+' '+0, - bar2_value: 0 - }); - sendChat('','/w '+who+' Round count is reset to 0.'); - break; - - case 'toggle-announce': - state.TurnMarker.announceRounds=!state.TurnMarker.announceRounds; - sendChat('','/w '+who+' Announce Rounds is now '+(state.TurnMarker.announceRounds ? 'ON':'OFF' )+'.'); - break; - - case 'toggle-announce-turn': - state.TurnMarker.announceTurnChange=!state.TurnMarker.announceTurnChange; - sendChat('','/w '+who+' Announce Turn Changes is now '+(state.TurnMarker.announceTurnChange ? 'ON':'OFF' )+'.'); - break; - - case 'toggle-announce-player': - state.TurnMarker.announcePlayerInTurnAnnounce=!state.TurnMarker.announcePlayerInTurnAnnounce; - sendChat('','/w '+who+' Player Name in Announce is now '+(state.TurnMarker.announcePlayerInTurnAnnounce ? 'ON':'OFF' )+'.'); - break; - - case 'toggle-skip-hidden': - state.TurnMarker.autoskipHidden=!state.TurnMarker.autoskipHidden; - sendChat('','/w '+who+' Auto-skip Hidden is now '+(state.TurnMarker.autoskipHidden ? 'ON':'OFF' )+'.'); - break; - - case 'toggle-animations': - state.TurnMarker.playAnimations=!state.TurnMarker.playAnimations; - if(state.TurnMarker.playAnimations) - { - TurnMarker.Step(TurnMarker.threadSync); - } - else - { - var marker = TurnMarker.GetMarker(); - marker.set({ - aura1_radius: '', - aura2_radius: '', - }); - } - - sendChat('','/w '+who+' Animations are now '+(state.TurnMarker.playAnimations ? 'ON':'OFF' )+'.'); - break; - - case 'toggle-rotate': - state.TurnMarker.rotation=!state.TurnMarker.rotation; - sendChat('','/w '+who+' Rotation is now '+(state.TurnMarker.rotation ? 'ON':'OFF' )+'.'); - break; - - case 'toggle-aura-1': - state.TurnMarker.aura1.pulse=!state.TurnMarker.aura1.pulse; - sendChat('','/w '+who+' Aura 1 is now '+(state.TurnMarker.aura1.pulse ? 'ON':'OFF' )+'.'); - break; - - case 'toggle-aura-2': - state.TurnMarker.aura2.pulse=!state.TurnMarker.aura2.pulse; - sendChat('','/w '+who+' Aura 2 is now '+(state.TurnMarker.aura2.pulse ? 'ON':'OFF' )+'.'); - break; - - - default: - case 'help': - TurnMarker.Help(who); - break; - - } - }, - - Help: function(who){ - var marker = TurnMarker.GetMarker(); - var rounds =parseInt(marker.get('bar2_value')); - sendChat('', - '/w '+who+' ' -+'
' - +'
' - +'TurnMarker v'+TurnMarker.version - +'
' - +'Commands' - +'
!tm' - +'
' - +'The following arguments may be supplied in order to change the configuration. All changes are persisted between script restarts.' - +'
    ' - +'
    '+rounds+'
    ' - +'
  • reset -- Sets the round counter back to 0.
  • ' - +'
    '+( state.TurnMarker.announceRounds ? 'ON' : 'OFF' )+'
    ' - +'
  • toggle-announce -- When on, each round will be announced to chat.
  • ' - +'
    '+( state.TurnMarker.announceTurnChange ? 'ON' : 'OFF' )+'
    ' - +'
  • toggle-announce-turn -- When on, the transition between visible turns will be announced.
  • ' - +'
    '+( state.TurnMarker.announcePlayerInTurnAnnounce ? 'ON' : 'OFF' )+'
    ' - +'
  • toggle-announce-player -- When on, the player(s) controlling the current turn are included in the turn announcement.
  • ' - +'
    '+( state.TurnMarker.autoskipHidden ? 'ON' : 'OFF' )+'
    ' - +'
  • toggle-skip-hidden -- When on, turn order will automatically be advanced past any hidden turns.
  • ' - +'
    '+( state.TurnMarker.playAnimations ? 'ON' : 'OFF' )+'
    ' - +'
  • toggle-animations -- Turns on turn marker animations. [Experimental!]
  • ' - +'
    '+( state.TurnMarker.rotation ? 'ON' : 'OFF' )+'
    ' - +'
  • toggle-rotate -- When on, the turn marker will rotate slowly clockwise. [Animation]
  • ' - +'
    '+( state.TurnMarker.aura1.pulse ? 'ON' : 'OFF' )+'
    ' - +'
  • toggle-aura-1 -- When on, aura 2 will pulse in and out. [Animation]
  • ' - +'
    '+( state.TurnMarker.aura2.pulse ? 'ON' : 'OFF' )+'
    ' - +'
  • toggle-aura-2 -- When on, aura 2 will pulse in and out. [Animation]
  • ' - +'
' - +'
' - +'
' - +'
!eot' - +'
' - +'Players may execute this command to advance the initiative to the next turn. This only succeeds if the current token is one that the caller controls or if it is executed by a GM.' - +'
' - +'
' -+'
' - ); - }, - - CheckForTokenMove: function(obj){ - if(TurnMarker.active) - { - var turnOrder = TurnOrder.Get(); - var current = _.first(turnOrder); - if( obj && current && current.id == obj.id) - { - TurnMarker.threadSync++; - - var marker = TurnMarker.GetMarker(); - marker.set({ - "top": obj.get("top"), - "left": obj.get("left") - }); - - setTimeout(_.bind(TurnMarker.Step,this,TurnMarker.threadSync), 300); - } - } - }, - - RequestTurnAdvancement: function(playerid){ - if(TurnMarker.active) - { - var turnOrder = TurnOrder.Get(); - var current = getObj('graphic',_.first(turnOrder).id); - var character = getObj('character',current.get('represents')); - if(isGM(playerid) - || ( undefined != current && - ( _.contains(current.get('controlledby').split(','),playerid) - || _.contains(current.get('controlledby').split(','),'all') ) - ) - || ( undefined != character && - ( _.contains(character.get('controlledby').split(','),playerid) - || _.contains(character.get('controlledby').split(','),'all') ) - ) - ) - { - TurnOrder.Next(); - TurnMarker.TurnOrderChange(true); - } - } - }, - - _AnnounceRound: function(round){ - if(state.TurnMarker.announceRounds) - { - sendChat( - '', - "/direct " - +"
" - +"" - +"Round "+ round - +"" - +"
" - ); - } - }, - _HandleMarkerTurn: function(){ - var marker = TurnMarker.GetMarker(); - var turnOrder = TurnOrder.Get(); - - if(turnOrder[0].id == marker.id) - { - var round=parseInt(marker.get('bar2_value'))+1; - marker.set({ - name: state.TurnMarker.tokenName+' '+round, - bar2_value: round - }); - TurnMarker._AnnounceRound(round); - TurnOrder.Next(); - } - }, - _HandleAnnounceTurnChange: function(){ - - if(state.TurnMarker.announceTurnChange ) - { - var marker = TurnMarker.GetMarker(); - var turnOrder = TurnOrder.Get(); - var currentToken = getObj("graphic", turnOrder[0].id); - if('gmlayer' == currentToken.get('layer')) - { - return; - } - var previousTurn=_.last(_.filter(turnOrder,function(element){ - var token=getObj("graphic", element.id); - return ((undefined != token) - && (token.get('layer')!='gmlayer') - && (element.id != marker.id)); - })); - - /* find previous token. */ - var previousToken = getObj("graphic", previousTurn.id); - var pImage=previousToken.get('imgsrc'); - var cImage=currentToken.get('imgsrc'); - var pRatio=previousToken.get('width')/previousToken.get('height'); - var cRatio=currentToken.get('width')/currentToken.get('height'); - - var pNameString="The Previous turn is done."; - if(previousToken && previousToken.get('showplayers_name')) - { - pNameString='' - +previousToken.get('name') - +'\'s turn is done.'; - } - - var cNameString='The next turn has begun!'; - if(currentToken && currentToken.get('showplayers_name')) - { - cNameString='' - +currentToken.get('name') - +', it\'s now your turn!'; - } - - - var PlayerAnnounceExtra=''; - if(state.TurnMarker.announcePlayerInTurnAnnounce) - { - var Char=currentToken.get('represents'); - if('' != Char) - { - var Char=getObj('character',Char); - if(Char && _.isFunction(Char.get)) - { - var Controllers=Char.get('controlledby').split(','); - _.each(Controllers,function(c){ - switch(c) - { - case 'all': - PlayerAnnounceExtra+='
' - +'All' - +'
'; - break; - break; - default: - var player=getObj('player',c); - if(player) { - var PlayerColor=player.get('color'); - var PlayerName=player.get('displayname'); - PlayerAnnounceExtra+='
' - +PlayerName - +'
'; - } - break; - } - }); - } - } - } - - var tokenSize=70; - sendChat( - '', - "/direct " - +"
" - +'
' - +"" - + pNameString - +'
' - +'
' - +"" - + '' - +cNameString - + '' - +'
' - +'
' - +PlayerAnnounceExtra - +"
" - ); - } - }, - - TurnOrderChange: function(FirstTurnChanged){ - var marker = TurnMarker.GetMarker(); - - if(Campaign().get('initiativepage') === false) - { - return; - } - - var turnOrder = TurnOrder.Get(); - - if (!turnOrder.length) return; - - var current = _.first(turnOrder); - - if(state.TurnMarker.playAnimations) - { - TurnMarker.threadSync++; - setTimeout(_.bind(TurnMarker.Step,this,TurnMarker.threadSync), 300); - } - - if (current.id == "-1") return; - - TurnMarker._HandleMarkerTurn(); - - if(state.TurnMarker.autoskipHidden) - { - TurnOrder.NextVisible(); - TurnMarker._HandleMarkerTurn(); - } - - turnOrder=TurnOrder.Get(); - - if(turnOrder[0].id == marker.id) - { - return; - } - - current = _.first(TurnOrder.Get()); - - var currentToken = getObj("graphic", turnOrder[0].id); - if(undefined != currentToken) - { - - if(FirstTurnChanged) - { - TurnMarker._HandleAnnounceTurnChange(); - } - - var size = Math.max(currentToken.get("height"),currentToken.get("width")) * state.TurnMarker.scale; - - if (marker.get("layer") == "gmlayer" && currentToken.get("layer") != "gmlayer") { - marker.set({ - "top": currentToken.get("top"), - "left": currentToken.get("left"), - "height": size, - "width": size - }); - setTimeout(function() { - marker.set({ - "layer": currentToken.get("layer") - }); - }, 500); - } else { - marker.set({ - "layer": currentToken.get("layer"), - "top": currentToken.get("top"), - "left": currentToken.get("left"), - "height": size, - "width": size - }); - } - toFront(currentToken); - } - }, - - DispatchInitiativePage: function(){ - if(Campaign().get('initiativepage') === false) - { - this.Reset(); - } - else - { - this.Start(); - } - }, - - RegisterEventHandlers: function(){ - on("change:campaign:initiativepage", function(obj, prev) { - TurnMarker.DispatchInitiativePage(); - }); - - on("change:campaign:turnorder", function(obj, prev) { - var prevOrder=JSON.parse(prev.turnorder); - var objOrder=JSON.parse(obj.get('turnorder')); - - if( undefined !=prevOrder - && undefined !=objOrder - && _.isArray(prevOrder) - && _.isArray(objOrder) - && 0 != prevOrder.length - && 0 != objOrder.length - && objOrder[0].id != prevOrder[0].id - ) - { - TurnMarker.TurnOrderChange(true); - } - }); - - on("change:graphic", function(obj,prev) { - TurnMarker.CheckForTokenMove(obj); - }); - - on("chat:message", function (msg) { - /* Exit if not an api command */ - if (msg.type != "api") return; - - /* clean up message bits. */ - msg.who = msg.who.replace(" (GM)", ""); - msg.content = msg.content.replace("(GM) ", ""); - - // get minimal player name (hopefully unique!) - var who=getObj('player',msg.playerid).get('_displayname').split(' ')[0]; - - var tokenized = msg.content.split(" "); - var command = tokenized[0]; - - switch(command) - { - case "!tm": - case "!turnmarker": - { - TurnMarker.HandleInput(_.rest(tokenized),who); - } - break; - - case "!eot": - { - TurnMarker.RequestTurnAdvancement(msg.playerid); - } - break; - } - }); - } - -}; - - - - - - -on("ready",function(){ - 'use strict'; - - var Has_IsGM=false; - try { - _.isFunction(isGM); - Has_IsGM=true; - } - catch (err) - { - log('--------------------------------------------------------------'); - log('TurnMarker requires the isGM module to work.'); - log('isGM GIST: https://gist.github.com/shdwjk/8d5bb062abab18463625'); - log('--------------------------------------------------------------'); - } - - if( Has_IsGM ) - { - TurnMarker.CheckInstall(); - TurnMarker.RegisterEventHandlers(); - TurnMarker.DispatchInitiativePage(); - } -}); - -// Utility Function -var fixNewObject = fixNewObject || function(obj){ - var p = obj.changed._fbpath; - var new_p = p.replace(/([^\/]*\/){4}/, "/"); - obj.fbpath = new_p; - return obj; -} - - -var TurnOrder = TurnOrder || { - Get: function(){ - var to=Campaign().get("turnorder"); - to=(''===to ? '[]' : to); - return JSON.parse(to); - }, - Set: function(turnOrder){ - Campaign().set({turnorder: JSON.stringify(turnOrder)}); - }, - Next: function(){ - this.Set(TurnOrder.Get().rotate(1)); - if("undefined" !== typeof Mark && _.has(Mark,'Reset') && _.isFunction(Mark.Reset)) { - Mark.Reset(); - } - }, - NextVisible: function(){ - var turns=this.Get(); - var context={skip: 0}; - var found=_.find(turns,function(element){ - var token=getObj("graphic", element.id); - if( - (undefined !== token) - && (token.get('layer')!='gmlayer') - ) - { - return true; - } - else - { - this.skip++; - } - },context); - if(undefined !== found && context.skip>0) - { - this.Set(turns.rotate(context.skip)); - } - }, - HasTurn: function(id){ - return (_.filter(this.Get(),function(turn){ - return id == turn.id; - }).length != 0); - }, - AddTurn: function(entry){ - var turnorder = this.Get(); - turnorder.push(entry); - this.Set(turnorder); - } -} - -Object.defineProperty(Array.prototype, 'rotate', { - enumerable: false, - writable: true -}); - -Array.prototype.rotate = (function() { - var unshift = Array.prototype.unshift, - splice = Array.prototype.splice; - - return function(count) { - var len = this.length >>> 0, - count = count >> 0; - - unshift.apply(this, splice.call(this, count % len, len)); - return this; - }; -})(); diff --git a/TurnMarker1/TurnMarker1.js b/TurnMarker1/TurnMarker1.js new file mode 100644 index 0000000000..24ec3c899e --- /dev/null +++ b/TurnMarker1/TurnMarker1.js @@ -0,0 +1,727 @@ +// Github: https://github.com/shdwjk/Roll20API/blob/master/TurnMarker1/TurnMarker1.js +// By: The Aaron, Arcane Scriptomancer +// Contact: https://app.roll20.net/users/104025/the-aaron + +/* ############################################################### */ +/* TurnMarker */ +/* ############################################################### */ + +var TurnMarker = TurnMarker || (function(){ + "use strict"; + + var version = '1.3.0', + schemaVersion = 1.16, + active = false, + threadSync = 1; + + +return { + + CheckInstall: function() { + log('-=> TurnMarker v'+version+' <=-'); + + if( ! state.hasOwnProperty('TurnMarker') || state.TurnMarker.version !== TurnMarker.schemaVersion) + { + /* Default Settings stored in the state. */ + state.TurnMarker = { + version: TurnMarker.version, + announceRounds: true, + announceTurnChange: true, + announcePlayerInTurnAnnounce: true, + announcePlayerInTurnAnnounceSize: '100%', + autoskipHidden: true, + tokenName: 'Round', + tokenURL: 'https://s3.amazonaws.com/files.d20.io/images/4095816/086YSl3v0Kz3SlDAu245Vg/thumb.png?1400535580', + playAnimations: false, + rotation: false, + animationSpeed: 5, + scale: 1.7, + aura1: { + pulse: false, + size: 5, + color: '#ff00ff' + }, + aura2: { + pulse: false, + size: 5, + color: '#00ff00' + } + }; + } + if(Campaign().get('turnorder') ==='') + { + Campaign().set('turnorder','[]'); + } + }, + + GetMarker: function(){ + var marker = findObjs({ + imgsrc: state.TurnMarker.tokenURL, + pageid: Campaign().get("playerpageid") + })[0]; + + if (marker === undefined) { + marker = createObj('graphic', { + name: state.TurnMarker.tokenName+' 0', + pageid: Campaign().get("playerpageid"), + layer: 'gmlayer', + imgsrc: state.TurnMarker.tokenURL, + left: 0, + top: 0, + height: 70, + width: 70, + bar2_value: 0, + showplayers_name: true, + showplayers_aura1: true, + showplayers_aura2: true + }); + } + if(!TurnOrder.HasTurn(marker.id)) + { + TurnOrder.AddTurn({ + id: marker.id, + pr: -1, + custom: "", + pageid: marker.get('pageid') + }); + } + return marker; + }, + + Step: function( sync ){ + if (!state.TurnMarker.playAnimations || sync !== TurnMarker.threadSync) + { + return; + } + var marker=TurnMarker.GetMarker(); + if(TurnMarker.active === true) + { + var rotation=(marker.get('bar1_value')+state.TurnMarker.animationSpeed)%360; + marker.set('bar1_value', rotation ); + if(state.TurnMarker.rotation) + { + marker.set( 'rotation', rotation ); + } + if( state.TurnMarker.aura1.pulse ) + { + marker.set('aura1_radius', Math.abs(Math.sin(rotation * (Math.PI/180))) * state.TurnMarker.aura1.size ); + } + else + { + marker.set('aura1_radius',''); + } + if( state.TurnMarker.aura2.pulse ) + { + marker.set('aura2_radius', Math.abs(Math.cos(rotation * (Math.PI/180))) * state.TurnMarker.aura2.size ); + } + else + { + marker.set('aura2_radius',''); + } + setTimeout(_.bind(TurnMarker.Step,this,sync), 100); + } + }, + + Reset: function() { + TurnMarker.active=false; + TurnMarker.threadSync++; + + var marker = TurnMarker.GetMarker(); + + marker.set({ + layer: "gmlayer", + aura1_radius: '', + aura2_radius: '', + left: 35, + top: 35, + height: 70, + width: 70, + rotation: 0, + bar1_value: 0 + }); + }, + + Start: function() { + var marker = TurnMarker.GetMarker(); + + + if(state.TurnMarker.playAnimations && state.TurnMarker.aura1.pulse) + { + marker.set({ + aura1_radius: state.TurnMarker.aura1.size, + aura1_color: state.TurnMarker.aura1.color + }); + } + if(state.TurnMarker.playAnimations && state.TurnMarker.aura2.pulse) + { + marker.set({ + aura2_radius: state.TurnMarker.aura2.size, + aura2_color: state.TurnMarker.aura2.color + }); + } + TurnMarker.active=true; + TurnMarker.Step(TurnMarker.threadSync); + TurnMarker.TurnOrderChange(false); + }, + + HandleInput: function(tokens,who){ + switch (tokens[0]) + { + case 'reset': + var marker = TurnMarker.GetMarker(); + marker.set({ + name: state.TurnMarker.tokenName+' 0', + bar2_value: 0 + }); + sendChat('','/w '+who+' Round count is reset to 0.'); + break; + + case 'toggle-announce': + state.TurnMarker.announceRounds=!state.TurnMarker.announceRounds; + sendChat('','/w '+who+' Announce Rounds is now '+(state.TurnMarker.announceRounds ? 'ON':'OFF' )+'.'); + break; + + case 'toggle-announce-turn': + state.TurnMarker.announceTurnChange=!state.TurnMarker.announceTurnChange; + sendChat('','/w '+who+' Announce Turn Changes is now '+(state.TurnMarker.announceTurnChange ? 'ON':'OFF' )+'.'); + break; + + case 'toggle-announce-player': + state.TurnMarker.announcePlayerInTurnAnnounce=!state.TurnMarker.announcePlayerInTurnAnnounce; + sendChat('','/w '+who+' Player Name in Announce is now '+(state.TurnMarker.announcePlayerInTurnAnnounce ? 'ON':'OFF' )+'.'); + break; + + case 'toggle-skip-hidden': + state.TurnMarker.autoskipHidden=!state.TurnMarker.autoskipHidden; + sendChat('','/w '+who+' Auto-skip Hidden is now '+(state.TurnMarker.autoskipHidden ? 'ON':'OFF' )+'.'); + break; + + case 'toggle-animations': + state.TurnMarker.playAnimations=!state.TurnMarker.playAnimations; + if(state.TurnMarker.playAnimations) + { + TurnMarker.Step(TurnMarker.threadSync); + } + else + { + var marker = TurnMarker.GetMarker(); + marker.set({ + aura1_radius: '', + aura2_radius: '' + }); + } + + sendChat('','/w '+who+' Animations are now '+(state.TurnMarker.playAnimations ? 'ON':'OFF' )+'.'); + break; + + case 'toggle-rotate': + state.TurnMarker.rotation=!state.TurnMarker.rotation; + sendChat('','/w '+who+' Rotation is now '+(state.TurnMarker.rotation ? 'ON':'OFF' )+'.'); + break; + + case 'toggle-aura-1': + state.TurnMarker.aura1.pulse=!state.TurnMarker.aura1.pulse; + sendChat('','/w '+who+' Aura 1 is now '+(state.TurnMarker.aura1.pulse ? 'ON':'OFF' )+'.'); + break; + + case 'toggle-aura-2': + state.TurnMarker.aura2.pulse=!state.TurnMarker.aura2.pulse; + sendChat('','/w '+who+' Aura 2 is now '+(state.TurnMarker.aura2.pulse ? 'ON':'OFF' )+'.'); + break; + + + case 'help': + default: + TurnMarker.Help(who); + break; + + } + }, + + Help: function(who){ + var marker = TurnMarker.GetMarker(); + var rounds =parseInt(marker.get('bar2_value'),10); + sendChat('', + '/w '+who+' ' ++'
' + +'
' + +'TurnMarker v'+TurnMarker.version + +'
' + +'Commands' + +'
!tm' + +'
' + +'The following arguments may be supplied in order to change the configuration. All changes are persisted between script restarts.' + +'
    ' + +'
    '+rounds+'
    ' + +'
  • reset -- Sets the round counter back to 0.
  • ' + +'
    '+( state.TurnMarker.announceRounds ? 'ON' : 'OFF' )+'
    ' + +'
  • toggle-announce -- When on, each round will be announced to chat.
  • ' + +'
    '+( state.TurnMarker.announceTurnChange ? 'ON' : 'OFF' )+'
    ' + +'
  • toggle-announce-turn -- When on, the transition between visible turns will be announced.
  • ' + +'
    '+( state.TurnMarker.announcePlayerInTurnAnnounce ? 'ON' : 'OFF' )+'
    ' + +'
  • toggle-announce-player -- When on, the player(s) controlling the current turn are included in the turn announcement.
  • ' + +'
    '+( state.TurnMarker.autoskipHidden ? 'ON' : 'OFF' )+'
    ' + +'
  • toggle-skip-hidden -- When on, turn order will automatically be advanced past any hidden turns.
  • ' + +'
    '+( state.TurnMarker.playAnimations ? 'ON' : 'OFF' )+'
    ' + +'
  • toggle-animations -- Turns on turn marker animations. [Experimental!]
  • ' + +'
    '+( state.TurnMarker.rotation ? 'ON' : 'OFF' )+'
    ' + +'
  • toggle-rotate -- When on, the turn marker will rotate slowly clockwise. [Animation]
  • ' + +'
    '+( state.TurnMarker.aura1.pulse ? 'ON' : 'OFF' )+'
    ' + +'
  • toggle-aura-1 -- When on, aura 2 will pulse in and out. [Animation]
  • ' + +'
    '+( state.TurnMarker.aura2.pulse ? 'ON' : 'OFF' )+'
    ' + +'
  • toggle-aura-2 -- When on, aura 2 will pulse in and out. [Animation]
  • ' + +'
' + +'
' + +'
' + +'
!eot' + +'
' + +'Players may execute this command to advance the initiative to the next turn. This only succeeds if the current token is one that the caller controls or if it is executed by a GM.' + +'
' + +'
' ++'
' + ); + }, + + CheckForTokenMove: function(obj){ + if(TurnMarker.active) + { + var turnOrder = TurnOrder.Get(); + var current = _.first(turnOrder); + if( obj && current && current.id === obj.id) + { + TurnMarker.threadSync++; + + var marker = TurnMarker.GetMarker(); + marker.set({ + "top": obj.get("top"), + "left": obj.get("left") + }); + + setTimeout(_.bind(TurnMarker.Step,this,TurnMarker.threadSync), 300); + } + } + }, + + RequestTurnAdvancement: function(playerid){ + if(TurnMarker.active) + { + var turnOrder = TurnOrder.Get(), + current = getObj('graphic',_.first(turnOrder).id), + character = getObj('character',(current && current.get('represents'))); + if(playerIsGM(playerid) + || ( current && + ( _.contains(current.get('controlledby').split(','),playerid) + || _.contains(current.get('controlledby').split(','),'all') ) + ) + || ( character && + ( _.contains(character.get('controlledby').split(','),playerid) + || _.contains(character.get('controlledby').split(','),'all') ) + ) + ) + { + TurnOrder.Next(); + TurnMarker.TurnOrderChange(true); + } + } + }, + + _AnnounceRound: function(round){ + if(state.TurnMarker.announceRounds) + { + sendChat( + '', + "/direct " + +"
" + +"" + +"Round "+ round + +"" + +"
" + ); + } + }, + _HandleMarkerTurn: function(){ + var marker = TurnMarker.GetMarker(); + var turnOrder = TurnOrder.Get(); + + if(turnOrder[0].id === marker.id) + { + var round=parseInt(marker.get('bar2_value'))+1; + marker.set({ + name: state.TurnMarker.tokenName+' '+round, + bar2_value: round + }); + TurnMarker._AnnounceRound(round); + TurnOrder.Next(); + } + }, + _HandleAnnounceTurnChange: function(){ + + if(state.TurnMarker.announceTurnChange ) + { + var marker = TurnMarker.GetMarker(); + var turnOrder = TurnOrder.Get(); + var currentToken = getObj("graphic", turnOrder[0].id); + if('gmlayer' === currentToken.get('layer')) + { + return; + } + var previousTurn=_.last(_.filter(turnOrder,function(element){ + var token=getObj("graphic", element.id); + return ((undefined !== token) + && (token.get('layer')!=='gmlayer') + && (element.id !== marker.id)); + })); + + /* find previous token. */ + var previousToken = getObj("graphic", previousTurn.id); + var pImage=previousToken.get('imgsrc'); + var cImage=currentToken.get('imgsrc'); + var pRatio=previousToken.get('width')/previousToken.get('height'); + var cRatio=currentToken.get('width')/currentToken.get('height'); + + var pNameString="The Previous turn is done."; + if(previousToken && previousToken.get('showplayers_name')) + { + pNameString='' + +previousToken.get('name') + +'\'s turn is done.'; + } + + var cNameString='The next turn has begun!'; + if(currentToken && currentToken.get('showplayers_name')) + { + cNameString='' + +currentToken.get('name') + +', it\'s now your turn!'; + } + + + var PlayerAnnounceExtra=''; + if(state.TurnMarker.announcePlayerInTurnAnnounce) + { + var Char=currentToken.get('represents'); + if('' !== Char) + { + Char=getObj('character',Char); + if(Char && _.isFunction(Char.get)) + { + var Controllers=Char.get('controlledby').split(','); + _.each(Controllers,function(c){ + switch(c) + { + case 'all': + PlayerAnnounceExtra+='
' + +'All' + +'
'; + break; + + default: + var player=getObj('player',c); + if(player) { + var PlayerColor=player.get('color'); + var PlayerName=player.get('displayname'); + PlayerAnnounceExtra+='
' + +PlayerName + +'
'; + } + break; + } + }); + } + } + } + + var tokenSize=70; + sendChat( + '', + "/direct " + +"
" + +'
' + +"" + + pNameString + +'
' + +'
' + +"" + + '' + +cNameString + + '' + +'
' + +'
' + +PlayerAnnounceExtra + +"
" + ); + } + }, + + TurnOrderChange: function(FirstTurnChanged){ + var marker = TurnMarker.GetMarker(); + + if(Campaign().get('initiativepage') === false) + { + return; + } + + var turnOrder = TurnOrder.Get(); + + if (!turnOrder.length) { + return; + } + + var current = _.first(turnOrder); + + if(state.TurnMarker.playAnimations) + { + TurnMarker.threadSync++; + setTimeout(_.bind(TurnMarker.Step,this,TurnMarker.threadSync), 300); + } + + if (current.id === "-1") { + return; + } + + TurnMarker._HandleMarkerTurn(); + + if(state.TurnMarker.autoskipHidden) + { + TurnOrder.NextVisible(); + TurnMarker._HandleMarkerTurn(); + } + + turnOrder=TurnOrder.Get(); + + if(turnOrder[0].id === marker.id) + { + return; + } + + current = _.first(TurnOrder.Get()); + + var currentToken = getObj("graphic", turnOrder[0].id); + if(undefined !== currentToken) + { + + if(FirstTurnChanged) + { + TurnMarker._HandleAnnounceTurnChange(); + } + + var size = Math.max(currentToken.get("height"),currentToken.get("width")) * state.TurnMarker.scale; + + if (marker.get("layer") === "gmlayer" && currentToken.get("layer") !== "gmlayer") { + marker.set({ + "top": currentToken.get("top"), + "left": currentToken.get("left"), + "height": size, + "width": size + }); + setTimeout(function() { + marker.set({ + "layer": currentToken.get("layer") + }); + }, 500); + } else { + marker.set({ + "layer": currentToken.get("layer"), + "top": currentToken.get("top"), + "left": currentToken.get("left"), + "height": size, + "width": size + }); + } + toFront(currentToken); + } + }, + + DispatchInitiativePage: function(){ + if(Campaign().get('initiativepage') === false) + { + this.Reset(); + } + else + { + this.Start(); + } + }, + + RegisterEventHandlers: function(){ + on("change:campaign:initiativepage", function(obj, prev) { + TurnMarker.DispatchInitiativePage(); + }); + + on("change:campaign:turnorder", function(obj, prev) { + var prevOrder=JSON.parse(prev.turnorder); + var objOrder=JSON.parse(obj.get('turnorder')); + + if( undefined !==prevOrder + && undefined !==objOrder + && _.isArray(prevOrder) + && _.isArray(objOrder) + && 0 !== prevOrder.length + && 0 !== objOrder.length + && objOrder[0].id !== prevOrder[0].id + ) + { + TurnMarker.TurnOrderChange(true); + } + }); + + on("change:graphic", function(obj,prev) { + TurnMarker.CheckForTokenMove(obj); + }); + + on("chat:message", function (msg) { + /* Exit if not an api command */ + if (msg.type !== "api") { + return; + } + + /* clean up message bits. */ + msg.who = msg.who.replace(" (GM)", ""); + msg.content = msg.content.replace("(GM) ", ""); + + // get minimal player name (hopefully unique!) + var who=getObj('player',msg.playerid).get('_displayname').split(' ')[0]; + + var tokenized = msg.content.split(" "); + var command = tokenized[0]; + + switch(command) + { + case "!tm": + case "!turnmarker": + { + TurnMarker.HandleInput(_.rest(tokenized),who); + } + break; + + case "!eot": + { + TurnMarker.RequestTurnAdvancement(msg.playerid); + } + break; + } + }); + } + +}; +}()); + + + + + + +on("ready",function(){ + 'use strict'; + + TurnMarker.CheckInstall(); + TurnMarker.RegisterEventHandlers(); + TurnMarker.DispatchInitiativePage(); +}); + +var TurnOrder = TurnOrder || { + Get: function(){ + var to=Campaign().get("turnorder"); + to=(''===to ? '[]' : to); + return JSON.parse(to); + }, + Set: function(turnOrder){ + Campaign().set({turnorder: JSON.stringify(turnOrder)}); + }, + Next: function(){ + this.Set(TurnOrder.Get().rotate(1)); + if("undefined" !== typeof Mark && _.has(Mark,'Reset') && _.isFunction(Mark.Reset)) { + Mark.Reset(); + } + }, + NextVisible: function(){ + var turns=this.Get(); + var context={skip: 0}; + var found=_.find(turns,function(element){ + var token=getObj("graphic", element.id); + if( + (undefined !== token) + && (token.get('layer')!=='gmlayer') + ) + { + return true; + } + else + { + this.skip++; + } + },context); + if(undefined !== found && context.skip>0) + { + this.Set(turns.rotate(context.skip)); + } + }, + HasTurn: function(id){ + return (_.filter(this.Get(),function(turn){ + return id === turn.id; + }).length !== 0); + }, + AddTurn: function(entry){ + var turnorder = this.Get(); + turnorder.push(entry); + this.Set(turnorder); + } +} + +Object.defineProperty(Array.prototype, 'rotate', { + enumerable: false, + writable: true +}); + +Array.prototype.rotate = (function() { + var unshift = Array.prototype.unshift, + splice = Array.prototype.splice; + + return function(count) { + var len = this.length >>> 0, + count = count >> 0; + + unshift.apply(this, splice.call(this, count % len, len)); + return this; + }; +}()); + diff --git a/TurnMarker1/package.json b/TurnMarker1/package.json index 669873d3fc..08de9d389e 100644 --- a/TurnMarker1/package.json +++ b/TurnMarker1/package.json @@ -1,37 +1,34 @@ { - "name": "TurnMarker", - "version": "1.22", - "description": "Round counter and a moving marker that shows who's turn it is.", - "authors": "The Aaron", - "roll20userid": "104025", - "dependencies": { - "isGMModule": "0.x" - }, - "modifies": { - "state.TurnMarker": "read,write", - "campaign.initiativepage": "read", - "campaign.playerpageid": "read", - "campaign.turnorder": "read,write", - "character.controlledby": "read", - "graphic": "create", - "graphic.aura1_color": "read,write", - "graphic.aura1_radius": "read,write", - "graphic.aura2_color": "read,write", - "graphic.aura2_radius": "read,write", - "graphic.bar1_value": "read,write", - "graphic.bar2_value": "read,write", - "graphic.controlledby": "read", - "graphic.height": "read,write", - "graphic.layer": "read,write", - "graphic.left": "read,write", - "graphic.name": "read,write", - "graphic.pageid": "read", - "graphic.represents": "read", - "graphic.rotation": "read,write", - "graphic.showplayers_name": "read", - "graphic.top": "read,write", - "graphic.width": "read,write" - }, - "conflicts": [ - ] -} + "name": "TurnMarker1", + "version": "1.3.0", + "description": "Round counter and a moving marker that shows who's turn it is.", + "authors": "The Aaron", + "roll20userid": "104025", + "dependencies": [], + "modifies": { + "state.TurnMarker": "read,write", + "campaign.initiativepage": "read", + "campaign.playerpageid": "read", + "campaign.turnorder": "read,write", + "character.controlledby": "read", + "graphic": "create", + "graphic.aura1_color": "read,write", + "graphic.aura1_radius": "read,write", + "graphic.aura2_color": "read,write", + "graphic.aura2_radius": "read,write", + "graphic.bar1_value": "read,write", + "graphic.bar2_value": "read,write", + "graphic.controlledby": "read", + "graphic.height": "read,write", + "graphic.layer": "read,write", + "graphic.left": "read,write", + "graphic.name": "read,write", + "graphic.pageid": "read", + "graphic.represents": "read", + "graphic.rotation": "read,write", + "graphic.showplayers_name": "read", + "graphic.top": "read,write", + "graphic.width": "read,write" + }, + "conflicts": [] +} \ No newline at end of file