Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
287 changes: 275 additions & 12 deletions TokenNameNumber/TokenNameNumber.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,259 @@
var TokenNameNumber = TokenNameNumber || (function() {
'use strict';

var version = 0.4,
schemaVersion = 0.2,
var version = '0.5.1',
lastUpdate = 1429599526,
schemaVersion = 0.3,
maxWaitTime = 1000,
randomSpace = 0,
escapeForRegexp = /(\\|\/|\[|\]|\(|\)|\{|\}|\?|\+|\*|\||\.|\^|\$)/g,
statuses = [
'red', 'blue', 'green', 'brown', 'purple', 'pink', 'yellow', // 0-6
'skull', 'sleepy', 'half-heart', 'half-haze', 'interdiction',
'snail', 'lightning-helix', 'spanner', 'chained-heart',
'chemical-bolt', 'death-zone', 'drink-me', 'edge-crack',
'ninja-mask', 'stopwatch', 'fishing-net', 'overdrive', 'strong',
'fist', 'padlock', 'three-leaves', 'fluffy-wing', 'pummeled',
'tread', 'arrowed', 'aura', 'back-pain', 'black-flag',
'bleeding-eye', 'bolt-shield', 'broken-heart', 'cobweb',
'broken-shield', 'flying-flag', 'radioactive', 'trophy',
'broken-skull', 'frozen-orb', 'rolling-bomb', 'white-tower',
'grab', 'screaming', 'grenade', 'sentry-gun', 'all-for-one',
'angel-outfit', 'archery-target'
],
statusColormap = ['#C91010', '#1076c9', '#2fc910', '#c97310', '#9510c9', '#eb75e1', '#e5eb75'],
regex = {
escape: /(\\|\/|\[|\]|\(|\)|\{|\}|\?|\+|\*|\||\.|\^|\$)/g
},

checkInstall = function() {
log('-=> TokenNameNumber v'+version+' <=- ['+(new Date(lastUpdate*1000))+']');

if( ! _.has(state,'TokenNameNumber') || state.TokenNameNumber.version !== schemaVersion) {
state.TokenNameNumber = {
version: schemaVersion,
registry: {
}
};
log(' > Updating Schema to v'+schemaVersion+' <');
switch(state.TokenNameNumber && state.TokenNameNumber.version) {
case 0.2:
state.TokenNameNumber = _.defaults({
version: schemaVersion,
config: {
randomSpace: 0,
useDots: false,
dots: ['red','brown','yellow','green','blue','pink','purple']
}
}, state.TokenNameNumber);
break;
default:
state.TokenNameNumber = {
version: schemaVersion,
config: {
useDots: false,
dots: ['red','brown','yellow','green','blue','purple']
},
registry: {
}
};
break;
}
}
},
esRE = function (s) {
return s.replace(escapeForRegexp,"\\$1");
return s.replace(regex.escape,"\\$1");
},

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 '';
},

getConfigOption_RandomSpace = function() {
var text = ( state.TokenNameNumber.config.randomSpace > 0
? '<span style="color: green; font-weight:bold;">'+ state.TokenNameNumber.config.randomSpace+ '</span>'
: '<span style="color: red; font-weight:bold;">Off</span>' );
return '<div>'+
'Random Space of numbers between each consecutively generated token number:'+
text+'. '+
'<a href="!tnn-config --random-space|?{size of the random gap between token numbers (0 for off, any number for a range from 1 to that number)?|'+state.TokenNameNumber.config.randomSpace+'}">'+
'Set Random Space'+
'</a>'+
'</div>';
},

getConfigOption_UseDots = function() {
var text = (state.TokenNameNumber.config.useDots
? '<span style="color: green; font-weight:bold;">On</span>'
: '<span style="color: red; font-weight:bold;">Off</span>');

return '<div>'+
'Use Dots is currently <b>'+
text+
'</b>.'+
'<a href="!tnn-config --toggle-use-dots">Toggle</a>'+
'</div>';
},

getStatusButton = function(status) {
var i=_.indexOf(statuses,status);
if(i<7) {
return '<a style="background-color: transparent; padding: 0;" href="!tnn-config --toggle-dot|'+status+'"><div style="width: 22px; height: 22px; border-radius:20px; display:inline-block; margin: 0; border:0; cursor: pointer;background-color: '+statusColormap[i]+'"></div></a>';
}
return '<a style="background-color: transparent; padding: 0;" href="!tnn-config --toggle-dot|'+status+'"><div style="width: 24px; height: 24px; display:inline-block; margin: 0; border:0; cursor: pointer;padding:0;background-image: url(\'https://app.roll20.net/images/statussheet.png\');background-repeat:no-repeat;background-position: '+((-34)*(i-7))+'px 0px;"></div></a>';
},

// https://app.roll20.net/images/statussheet.png
getConfigOption_Dots = function() {
return '<div>'+
'<div>'+
'<div style="font-weight: bold;">Dots (Click to move between pools).</div>'+
'<div style="border: 1px solid #999999;border-radius: 10px; background-color: #eeffee;">'+
_.map(state.TokenNameNumber.config.dots,function(s){
return getStatusButton(s);
}).join('')+
'</div>'+
'</div>'+
'<div>'+
'<div style="font-weight: bold;">Available Statuses</div>'+
'<div style="border: 1px solid #999999;border-radius: 10px; background-color: #ffeeee;">'+
_.map(_.difference(statuses,state.TokenNameNumber.config.dots),function(s){
return getStatusButton(s);
}).join('')+
'</div>'+
'</div>'+
'</div>';
},

getAllConfigOptions = function() {
return '<ul>'+_.map([
getConfigOption_RandomSpace(),
getConfigOption_UseDots(),
getConfigOption_Dots()
], function(c){
return '<li style="border-top: 1px solid #ccc;border-bottom: 1px solid #ccc;">'+c+'</li>';
}).join('')+'</ul>';
},

showHelp = function(who) {
sendChat('','/w '+who+' '+
'<div style="border: 1px solid black; background-color: white; padding: 3px 3px;">'+
'<div style="font-weight: bold; border-bottom: 1px solid black;font-size: 130%;">'+
'TokenNameNumber v'+version+
'</div>'+
'<div style="padding-left:10px;margin-bottom:3px;">'+
'<p>Provides automatic numbering of tokens dragged into onto the tabletop. Token names need to have the special word <b>%%NUMBERED%%</b> somewhere in them.</p>'+
'</div>'+
'<b>Commands</b>'+
'<div style="padding-left:10px;">'+
'<b><span style="font-family: serif;">!tnn [--help]</span></b>'+
'<div style="padding-left: 10px;padding-right:20px">'+
'<p>Currently, this just displayed the help, which is used for configuring.</p>'+
'<ul>'+
'<li style="border-top: 1px solid #ccc;border-bottom: 1px solid #ccc;">'+
'<b><span style="font-family: serif;">--help</span></b> '+ch('-')+' Displays the help and configuration options.'+
'</li> '+
'</ul>'+
'</div>'+
'</div>'+
'<b>Config</b>'+
'<div>'+
getAllConfigOptions()+
'</div>'+
'</div>'
);
},

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 '!tnn':
showHelp(who);
break;

case '!tnn-config':
if(_.contains(args,'help')) {
showHelp(who);
return;
}
if(!args.length) {
sendChat('','/w '+who+' '
+'<div style="border: 1px solid black; background-color: white; padding: 3px 3px;">'
+'<div style="font-weight: bold; border-bottom: 1px solid black;font-size: 130%;">'
+'TokenNameNumber v'+version
+'</div>'
+getAllConfigOptions()
+'</div>'
);
return;
}
_.each(args,function(a){
var opt=a.split(/\|/);
switch(opt.shift()) {
case 'toggle-use-dots':
state.TokenNameNumber.config.useDots=!state.TokenNameNumber.config.useDots;
sendChat('','/w '+who+' '
+'<div style="border: 1px solid black; background-color: white; padding: 3px 3px;">'
+getConfigOption_UseDots()
+'</div>'
);
break;

case 'toggle-dot':
if(_.contains(state.TokenNameNumber.config.dots, opt[0])){
state.TokenNameNumber.config.dots = _.without(state.TokenNameNumber.config.dots, opt[0]);
} else {
state.TokenNameNumber.config.dots.push(opt[0]);
}
sendChat('','/w '+who+' '
+'<div style="border: 1px solid black; background-color: white; padding: 3px 3px;">'
+getConfigOption_Dots()
+'</div>'
);
break;


case 'random-space':
state.TokenNameNumber.config.randomSpace=parseInt(opt[0],10);
sendChat('','/w '+who+' '
+'<div style="border: 1px solid black; background-color: white; padding: 3px 3px;">'
+getConfigOption_RandomSpace()
+'</div>'
);
break;

default:
sendChat('','/w '+who+' '
+'<div><b>Unsupported Option:</div> '+a+'</div>'
);
}

});

break;
}
},



getMatchers = function(pageid,represents) {
var matchers = [];
if(_.has(state.TokenNameNumber.registry, pageid)
Expand All @@ -45,14 +279,31 @@ var TokenNameNumber = TokenNameNumber || (function() {
}
},

getDotNumber = function(num) {
var base = (function (b){
var radix = b;
return (b && function base_dot(number,digits){
digits = digits || [];
digits.push(number % radix);
if(number < radix) {
return digits;
}
return base_dot(Math.floor(number/radix),digits);
}) || function(){return [];};
}(state.TokenNameNumber.config.dots.length));

return base(num);
},

setNumberFunction = function(id,lastTimeout) {
var obj = getObj('graphic',id),
matchers = (obj && getMatchers(obj.get('pageid'), obj.get('represents'))) || [],
tokenName = (obj && obj.get('name')),
matcher,
renamer,
parts,
num;
num,
statuspart='';


if(obj && (tokenName.match( /%%NUMBERED%%/ ) || _.some(matchers,function(m) { return m.test(tokenName);}) ) ) {
Expand Down Expand Up @@ -87,7 +338,18 @@ var TokenNameNumber = TokenNameNumber || (function() {
},0)
.value() );

num += ( randomSpace ? (randomInteger(randomSpace)-1) : 0);
num += ( state.TokenNameNumber.config.randomSpace ? (randomInteger(state.TokenNameNumber.config.randomSpace)-1) : 0);

if(state.TokenNameNumber.config.useDots) {
statuspart = _.map(getDotNumber(num), function(n){
return state.TokenNameNumber.config.dots[n];
}).join(',');
if(statuspart) {
obj.set({
statusmarkers: statuspart
});
}
}

parts=renamer.exec(tokenName);
obj.set({
Expand All @@ -107,6 +369,7 @@ var TokenNameNumber = TokenNameNumber || (function() {
},

registerEventHandlers = function() {
on('chat:message', handleInput);
on('add:graphic', setNumberOnToken);
};

Expand Down
33 changes: 16 additions & 17 deletions TokenNameNumber/package.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
{
"name": "TokenNameNumber",
"version": "0.4",
"description": "Automatic Numbering of tokens with special placeholder.",
"authors": "The Aaron",
"roll20userid": "104025",
"dependencies": {
},
"modifies": {
"state.TokenNameNumber": "read,write",
"graphic.name": "read,write",
"graphic.pageid": "read",
"graphic.represents": "read",
"graphic.subtype": "read",
"graphic.type": "read"
},
"conflicts": [
]
"name": "TokenNameNumber",
"version": "0.5.1",
"description": "Automatic Numbering of tokens with special placeholder.",
"authors": "The Aaron",
"roll20userid": "104025",
"dependencies": [],
"modifies": {
"state.TokenNameNumber": "read,write",
"graphic.name": "read,write",
"graphic.statusmarkers": "write",
"graphic.pageid": "read",
"graphic.represents": "read",
"graphic.subtype": "read",
"graphic.type": "read"
},
"conflicts": []
}