// Github: https://github.com/shdwjk/Roll20API/blob/master/TokenLock/TokenLock.js // By: The Aaron, Arcane Scriptomancer // Contact: https://app.roll20.net/users/104025/the-aaron var TokenLock = TokenLock || (function() { 'use strict'; var version = '0.2.3', lastUpdate = 1428859122, schemaVersion = 0.2, ch = function (c) { var entities = { '<' : 'lt', '>' : 'gt', "'" : '#39', '@' : '#64', '{' : '#123', '|' : '#124', '}' : '#125', '[' : '#91', ']' : '#93', '"' : 'quot', '-' : 'mdash', ' ' : 'nbsp' }; if(_.has(entities,c) ){ return ('&'+entities[c]+';'); } return ''; }, getCommandOption_ToggleLock = function() { var text = (state.TokenLock.locked ? 'Locked' : 'Unlocked' ); return '
' +'Tokens are now ' +text +'. ' +'' +'Toggle' +'' +'
'; }, getConfigOption_AllowMoveOnTurn = function() { var text = (state.TokenLock.config.allowMoveOnTurn ? 'On' : 'Off' ); return '
' +'Allow Move on Turn is currently ' +text +' ' +'' +'Toggle' +'' +'
'; }, showHelp = function(who) { var stateColor = (state.TokenLock.locked) ? ('#990000') : ('#009900'), stateName = (state.TokenLock.locked) ? ('Locked') : ('Unlocked'); sendChat('', '/w '+who+' ' +'
' +'
' +'
'+stateName+'
' +'TokenLock v'+version +'
' +'
' +'
' +'

TokenLock allows the GM to selectively prevent players from moving their tokens. ' +'Since change:graphic events to not specify who changed the ' +'graphic, determination of player tokens is based on whether that token ' +'has an entry in the controlled by field of either the token or ' +'the character it represents. If controlled by is empty, the ' +'GM can freely move the token at any point. If there is any entry in ' +'controlled by, the token can only be moved when TokenLock is ' +'unlocked.

' + '

Moving of player controlled cards is still permissible.

' +'
' +'Commands' +'
!tl' +'
' +'Executing the command with no arguments prints this help. The following arguments may be supplied in order to change the configuration. All changes are persisted between script restarts.' +'
    ' +'
  • ' +'lock -- Locks the player tokens to prevent moving them.' +'
  • ' +'
  • ' +'unlock -- Unlocks the player tokens allowing them to be moved.' +'
  • ' +'
' +'
' +'
' +getCommandOption_ToggleLock() +'
' +'!tl-config ['+ch('<')+'Options'+ch('>')+'|--help]' +'
' +'

Swaps the selected Tokens for their counterparts on the other layer.

' +'
    ' +'
  • ' +'--help '+ch('-')+' Shows the Help screen' +'
  • ' +'
  • ' +'--toggle-allowmoveonturn '+ch('-')+' Sets whether tokens can be moved if they are at the top of the turn order.' +'
  • ' +'
' +'
' +'
' +getConfigOption_AllowMoveOnTurn() +'
' ); }, handleInput = function(msg) { var args,who; if (msg.type !== "api" || !playerIsGM(msg.playerid) ) { return; } who=getObj('player',msg.playerid).get('_displayname').split(' ')[0]; args = msg.content.split(/\s+/); switch(args.shift()) { case '!tl': if(_.contains(args,'--help')) { showHelp(who); return; } switch(args.shift()) { case 'lock': state.TokenLock.locked=true; sendChat('TokenLock','/w gm ' +getCommandOption_ToggleLock() ); break; case 'unlock': state.TokenLock.locked=false; sendChat('TokenLock','/w gm ' +getCommandOption_ToggleLock() ); break; case '--toggle-lock': state.TokenLock.locked= !state.TokenLock.locked; sendChat('TokenLock','/w gm ' +getCommandOption_ToggleLock() ); break; default: showHelp(who); break; } break; case '!tl-config': if(_.contains(args,'--help')) { showHelp(who); return; } if(!args.length) { sendChat('','/w '+who+' ' +'
' +'
' +'TokenLock v'+version +'
' +getConfigOption_AllowMoveOnTurn() +'
' ); return; } _.each(args,function(a){ var opt=a.split(/\|/); switch(opt.shift()) { case '--toggle-allowmoveonturn': state.TokenLock.config.allowMoveOnTurn = !state.TokenLock.config.allowMoveOnTurn; sendChat('','/w '+who+' ' +'
' +getConfigOption_AllowMoveOnTurn() +'
' ); break; default: sendChat('','/w '+who+' ' +'
Unsupported Option:
'+a+'' ); } }); break; } }, handleMove = function(obj,prev) { if(state.TokenLock.locked && 'token' === obj.get('subtype') && ( !state.TokenLock.config.allowMoveOnTurn || (( (JSON.parse(Campaign().get('turnorder'))||[{id:false}])[0].id) !== obj.id) ) && ( obj.get('left') !== prev.left || obj.get('top') !== prev.top || obj.get('rotation') !== prev.rotation ) ) { if('' !== obj.get('controlledby')) { obj.set({left: prev.left, top: prev.top, rotation: prev.rotation}); } else if('' !== obj.get('represents') ) { var character = getObj('character',obj.get('represents')); if( character && character.get('controlledby') ) { obj.set({left: prev.left, top: prev.top, rotation: prev.rotation}); } } } }, checkInstall = function() { log('-=> TokenLock v'+version+' <=- ['+(new Date(lastUpdate*1000))+']'); if( ! _.has(state,'TokenLock') || state.TokenLock.version !== schemaVersion) { log(' > Updating Schema to v'+schemaVersion+' <'); switch(state.TokenLock && state.TokenLock.version) { case 0.1: state.TokenLock.config={ allowMoveOnTurn: false }; state.TokenLock.version=schemaVersion; break; default: state.TokenLock = { version: schemaVersion, config: { allowMoveOnTurn: false }, locked: false }; } } }, registerEventHandlers = function() { on('chat:message', handleInput); on('change:graphic', handleMove); }; return { RegisterEventHandlers: registerEventHandlers, CheckInstall: checkInstall }; }()); on("ready",function(){ 'use strict'; TokenLock.CheckInstall(); TokenLock.RegisterEventHandlers(); });