diff --git a/GroupInitiative/GroupInitiative.js b/GroupInitiative/GroupInitiative.js
index 4b49c969cc..f758728b5d 100644
--- a/GroupInitiative/GroupInitiative.js
+++ b/GroupInitiative/GroupInitiative.js
@@ -5,10 +5,150 @@
var GroupInitiative = GroupInitiative || (function() {
'use strict';
- var version = '0.8.2',
- lastUpdate = 1430695680,
- schemaVersion = 0.6,
+ var version = '0.8.7',
+ lastUpdate = 1431320918,
+ schemaVersion = 0.8,
bonusCache = {},
+ sorters = {
+ 'None': function(to) {
+ return to;
+ },
+ 'Ascending': function(to){
+ return _.sortBy(to,function(i){
+ return (i.pr);
+ });
+ },
+ 'Descending': function(to){
+ return _.sortBy(to,function(i){
+ return (-i.pr);
+ });
+ }
+ },
+ esRE = function (s) {
+ var escapeForRegexp = /(\\|\/|\[|\]|\(|\)|\{|\}|\?|\+|\*|\||\.|\^|\$)/g;
+ return s.replace(escapeForRegexp,"\\$1");
+ },
+
+ HE = (function(){
+ var entities={
+ //' ' : '&'+'nbsp'+';',
+ '<' : '&'+'lt'+';',
+ '>' : '&'+'gt'+';',
+ "'" : '&'+'#39'+';',
+ '@' : '&'+'#64'+';',
+ '{' : '&'+'#123'+';',
+ '|' : '&'+'#124'+';',
+ '}' : '&'+'#125'+';',
+ '[' : '&'+'#91'+';',
+ ']' : '&'+'#93'+';',
+ '"' : '&'+'quot'+';'
+ },
+ re=new RegExp('('+_.map(_.keys(entities),esRE).join('|')+')','g');
+ return function(s){
+ return s.replace(re, function(c){ return entities[c] || c; });
+ };
+ }()),
+ formatDieRoll = function(die, bonus) {
+ var highlight = ( 1 === die
+ ? '#B31515'
+ : ( state.GroupInitiative.config.dieSize === die
+ ? '#3FB315'
+ : '#FEF68E'
+ )
+ ),
+ dielight=( 1 === die
+ ? '#ff0000'
+ : ( state.GroupInitiative.config.dieSize === die
+ ? '#00ff00'
+ : 'white'
+ )
+ );
+ return ''+
+ ''+die+' [init] '+
+ (bonus>=0 ? '+' :'-')+' '+Math.abs(bonus)+' [bonus]'+
+ ''
+ ))+'">'+
+ (die+bonus)+
+ '';
+ },
+ buildAnnounceGroups = function(l) {
+ var groupColors = {
+ npc: '#eef',
+ character: '#efe',
+ gmlayer: '#aaa'
+ };
+ return _.reduce(l,function(m,s){
+ var type= ('gmlayer' === s.token.get('layer')
+ ? 'gmlayer'
+ : ( (s.character && _.filter(s.character.get('controlledby').split(/,/),function(c){
+ return 'all' === c || ('' !== c && !playerIsGM(c) );
+ }).length>0) || false
+ ? 'character'
+ : 'npc'
+ ));
+ if('graphic'!==s.token.get('type') || 'token' !==s.token.get('subtype')) {
+ return m;
+ }
+ m[type].push('
'+
+ '
'+
+ '
)+')
'+
+ ((s.token && s.token.get('name')) || (s.character && s.character.get('name')) || '(Creature)')+
+ '
'+
+ '
'+
+ formatDieRoll(Math.round(s.init-s.bonus),s.bonus)+
+ '
'+
+ '
'+
+ '
');
+ return m;
+ },{npc:[],character:[],gmlayer:[]});
+ },
+ announcers = {
+ 'None': function() {
+ },
+ 'Hidden': function(l) {
+ var groups=buildAnnounceGroups(l);
+ sendChat('GroupInit','/w gm '+
+ ''+
+ groups.character.join('')+
+ groups.npc.join('')+
+ groups.gmlayer.join('')+
+ '
'+
+ '
');
+ },
+ 'Partial': function(l) {
+ var groups=buildAnnounceGroups(l);
+ sendChat('GroupInit','/direct '+
+ ''+
+ groups.character.join('')+
+ '
'+
+ '
');
+ sendChat('GroupInit','/w gm '+
+ ''+
+ groups.npc.join('')+
+ groups.gmlayer.join('')+
+ '
'+
+ '
');
+ },
+ 'Visible': function(l) {
+ var groups=buildAnnounceGroups(l);
+ sendChat('GroupInit','/direct '+
+ ''+
+ groups.character.join('')+
+ groups.npc.join('')+
+ '
'+
+ '
');
+ sendChat('GroupInit','/w gm '+
+ ''+
+ groups.gmlayer.join('')+
+ '
'+
+ '
');
+ }
+ },
statAdjustments = {
'Stat-DnD': {
func: function(v) {
@@ -51,7 +191,7 @@ var GroupInitiative = GroupInitiative || (function() {
this.init=_.chain(l)
.pluck('bonus')
.map(function(d){
- return randomInteger(20)+d;
+ return randomInteger(state.GroupInitiative.config.dieSize)+d;
},{})
.min()
.value();
@@ -67,7 +207,7 @@ var GroupInitiative = GroupInitiative || (function() {
this.init=_.chain(l)
.pluck('bonus')
.map(function(d){
- return randomInteger(20)+d;
+ return randomInteger(state.GroupInitiative.config.dieSize)+d;
},{})
.reduce(function(memo,r){
return memo+r;
@@ -84,7 +224,7 @@ var GroupInitiative = GroupInitiative || (function() {
},
'Individual-Roll': {
func: function(s,k,l){
- s.init=randomInteger(20)+s.bonus;
+ s.init=randomInteger(state.GroupInitiative.config.dieSize)+s.bonus;
return s;
},
desc: 'Sets the initiative individually for each member of the group.'
@@ -104,10 +244,29 @@ var GroupInitiative = GroupInitiative || (function() {
if( ! _.has(state,'GroupInitiative') || state.GroupInitiative.version !== schemaVersion) {
log(' > Updating Schema to v'+schemaVersion+' <');
switch(state.GroupInitiative && state.GroupInitiative.version) {
+ case 0.7:
+ state.GroupInitiative.version = schemaVersion;
+ state.GroupInitiative.config.announcer = 'Partial';
+ break;
+
+ case 0.6:
+ state.GroupInitiative.version = schemaVersion;
+ state.GroupInitiative.config = {
+ rollType: state.GroupInitiative.rollType,
+ replaceRoll: state.GroupInitiative.replaceRoll,
+ dieSize: 20,
+ autoOpenInit: true,
+ sortOption: 'Descending'
+ };
+ delete state.GroupInitiative.replaceRoll;
+ delete state.GroupInitiative.rollType;
+ break;
+
case 0.5:
state.GroupInitiative.version = schemaVersion;
state.GroupInitiative.replaceRoll = false;
break;
+
default:
state.GroupInitiative = {
version: schemaVersion,
@@ -118,9 +277,16 @@ var GroupInitiative = GroupInitiative || (function() {
}
]
],
- rollType: 'Individual-Roll',
- replaceRoll: false
+ config: {
+ rollType: 'Individual-Roll',
+ replaceRoll: false,
+ dieSize: 20,
+ autoOpenInit: true,
+ sortOption: 'Descending',
+ announcer: 'Partial'
+ }
};
+ break;
}
}
},
@@ -172,17 +338,75 @@ var GroupInitiative = GroupInitiative || (function() {
},"");
},
+ getConfigOption_SortOptions = function() {
+ var text = state.GroupInitiative.config.sortOption;
+ return ''+
+ 'Sort Options is currently
'+
+ text+
+ '.'+
+ '
'+
+ _.map(_.keys(sorters),function(so){
+ return '
'+
+ so+
+ '';
+ }).join(' ')+
+ '
'+
+ '
';
+ },
+ getConfigOption_DieSize = function() {
+ return ''
+ +'Initiative Die size is currently
'
+ +state.GroupInitiative.config.dieSize
+ +' '
+ +'
'
+ +'Set Die Size'
+ +''
+ +'
';
+ },
+
+ getConfigOption_AutoOpenInit = function() {
+ var text = (state.GroupInitiative.config.autoOpenInit ? 'On' : 'Off' );
+ return '';
+
+ },
+ getConfigOption_AnnounceOptions = function() {
+ var text = state.GroupInitiative.config.announcer;
+ return ''+
+ 'Announcer is currently
'+
+ text+
+ '.'+
+ '
'+
+ _.map(_.keys(announcers),function(an){
+ return '
'+
+ an+
+ '';
+ }).join(' ')+
+ '
'+
+ '
';
+ },
+
+ getAllConfigOptions = function() {
+ return getConfigOption_SortOptions() + getConfigOption_DieSize() + getConfigOption_AutoOpenInit() + getConfigOption_AnnounceOptions();
+ },
+
showHelp = function() {
var rollerRows=_.reduce(rollers,function(memo,r,n){
- var selected=((state.GroupInitiative.rollType === n) ?
+ var selected=((state.GroupInitiative.config.rollType === n) ?
'Selected
'
: '' ),
- selectedStyleExtra=((state.GroupInitiative.rollType === n) ? ' style="border: 1px solid #aeaeae;background-color:#8bd87a;"' : '');
+ selectedStyleExtra=((state.GroupInitiative.config.rollType === n) ? ' style="border: 1px solid #aeaeae;background-color:#8bd87a;"' : '');
return memo+selected+""+n+" - "+r.desc+"";
},""),
statAdjustmentRows = buildStatAdjustmentRows(),
- bonusStatGroupRows = buildBonusStatGroupRows();
+ bonusStatGroupRows = buildBonusStatGroupRows();
sendChat('',
'/w gm '
@@ -280,7 +504,7 @@ var GroupInitiative = GroupInitiative || (function() {
+''
+'
!group-init --toggle-replace'
+'
'
- +'
'+( state.GroupInitiative.replaceRoll ? 'ON' : 'OFF' )+'
'
+ +'
'+( state.GroupInitiative.config.replaceRoll ? 'ON' : 'OFF' )+'
'
+'
Sets whether initative scores for selected tokens replace their current scores.
'
+'
'
+'
'
@@ -306,6 +530,8 @@ var GroupInitiative = GroupInitiative || (function() {
+''
+''
+ +getAllConfigOptions()
+
+''
);
},
@@ -349,12 +575,13 @@ var GroupInitiative = GroupInitiative || (function() {
HandleInput = function(msg_orig) {
var msg = _.clone(msg_orig),
args,
- cmds,
- workgroup,
- workvar,
- turnorder,
- rolls,
- error=false,
+ cmds,
+ workgroup,
+ workvar,
+ turnorder,
+ rolls,
+ pageid,
+ error=false,
initFunc,
cont=false,
manualBonus=0;
@@ -504,7 +731,7 @@ var GroupInitiative = GroupInitiative || (function() {
case 'set-roller':
if(_.has(rollers,cmds[1])) {
- state.GroupInitiative.rollType=cmds[1];
+ state.GroupInitiative.config.rollType=cmds[1];
sendChat('GroupInitiative', '/w gm '
+''
+'Roller is now set to:
'+cmds[1]+'
'
@@ -526,16 +753,16 @@ var GroupInitiative = GroupInitiative || (function() {
break;
case 'toggle-replace':
- state.GroupInitiative.replaceRoll = !state.GroupInitiative.replaceRoll;
+ state.GroupInitiative.config.replaceRoll = !state.GroupInitiative.config.replaceRoll;
sendChat('GroupInitiative', '/w gm '
+''
- +'Replace Initiative on Roll is now: '+ (state.GroupInitiative.replaceRoll ? 'ON' : 'OFF') +''
+ +'Replace Initiative on Roll is now: '+ (state.GroupInitiative.config.replaceRoll ? 'ON' : 'OFF') +''
+'
'
);
break;
case 'bonus':
- if(cmds[1].match(/^[\-\+]?\d+$/)){
+ if(cmds[1].match(/^[\-\+]?\d+(\.\d+)?$/)){
manualBonus=parseFloat(cmds[1]);
cont=true;
} else {
@@ -564,52 +791,138 @@ var GroupInitiative = GroupInitiative || (function() {
bonusCache = {};
turnorder = Campaign().get('turnorder');
turnorder = ('' === turnorder) ? [] : JSON.parse(turnorder);
- if(state.GroupInitiative.replaceRoll) {
+ if(state.GroupInitiative.config.replaceRoll) {
turnorder=_.reject(turnorder,function(i){
return _.contains(_.pluck(msg.selected, '_id'),i.id);
});
}
- initFunc=rollers[state.GroupInitiative.rollType].func;
+ initFunc=rollers[state.GroupInitiative.config.rollType].func;
Campaign().set({
turnorder: JSON.stringify(
- turnorder.concat(
- _.chain(msg.selected)
- .map(function(s){
- return getObj(s._type,s._id);
- })
- .reject(_.isUndefined)
- .reject(function(s){
- return _.contains(_.pluck(turnorder,'id'),s.id);
- })
- .map(function(s){
- return {
- token: s,
- character: getObj('character',s.get('represents'))
- };
- })
- .map(function(s){
- s.bonus=(s.character ? findInitiativeBonus(s.character.id) || 0 : 0)+manualBonus;
- return s;
- })
- .map(initFunc)
- .map(function(s){
- return {
- id: s.token.id,
- pr: s.init,
- custom: ''
- };
- })
- .value()
+ sorters[state.GroupInitiative.config.sortOption](
+ turnorder.concat(
+ _.chain(msg.selected)
+ .map(function(s){
+ return getObj(s._type,s._id);
+ })
+ .reject(_.isUndefined)
+ .reject(function(s){
+ return _.contains(_.pluck(turnorder,'id'),s.id);
+ })
+ .map(function(s){
+ pageid=pageid || s.get('pageid');
+ return {
+ token: s,
+ character: getObj('character',s.get('represents'))
+ };
+ })
+ .map(function(s){
+ s.bonus=(s.character ? findInitiativeBonus(s.character.id) || 0 : 0)+manualBonus;
+ return s;
+ })
+ .map(initFunc)
+ .tap(announcers[state.GroupInitiative.config.announcer])
+ .map(function(s){
+ return {
+ id: s.token.id,
+ pr: s.init,
+ custom: ''
+ };
+ })
+ .value()
+ )
)
)
+ });
+ if(state.GroupInitiative.config.autoOpenInit && !Campaign().get('initativepage')) {
+ Campaign().set({
+ initiativepage: pageid
+ });
}
- );
} else {
showHelp();
}
}
+ break;
+ case '!group-init-config':
+ if(_.contains(args,'--help')) {
+ showHelp();
+ return;
+ }
+ if(!args.length) {
+ sendChat('','/w gm '
+ +''
+ +'
'
+ +'GroupInitiative v'+version
+ +'
'
+ +getAllConfigOptions()
+ +'
'
+ );
+ return;
+ }
+ _.each(args,function(a){
+ var opt=a.split(/\|/),
+ omsg='';
+ switch(opt.shift()) {
+ case 'sort-option':
+ if(sorters[opt[0]]) {
+ state.GroupInitiative.config.sortOption=opt[0];
+ } else {
+ omsg='Error: Not a valid sort method: '+opt[0]+'
';
+ }
+ sendChat('','/w gm '
+ +''
+ +omsg
+ +getConfigOption_SortOptions()
+ +'
'
+ );
+ break;
+ case 'set-die-size':
+ if(opt[0].match(/^\d+$/)) {
+ state.GroupInitiative.config.dieSize=parseInt(opt[0],10);
+ } else {
+ omsg='Error: Not a die size: '+opt[0]+'
';
+ }
+ sendChat('','/w gm '
+ +''
+ +omsg
+ +getConfigOption_DieSize()
+ +'
'
+ );
+ break;
+
+ case 'toggle-auto-open-init':
+ state.GroupInitiative.config.autoOpenInit = !state.GroupInitiative.config.autoOpenInit;
+ sendChat('','/w gm '
+ +''
+ +getConfigOption_AutoOpenInit()
+ +'
'
+ );
+ break;
+ case 'set-announcer':
+ if(announcers[opt[0]]) {
+ state.GroupInitiative.config.announcer=opt[0];
+ } else {
+ omsg='Error: Not a valid announcer: '+opt[0]+'
';
+ }
+ sendChat('','/w gm '
+ +''
+ +omsg
+ +getConfigOption_AnnounceOptions()
+ +'
'
+ );
+ break;
+
+ default:
+ sendChat('','/w gm '
+ +'Unsupported Option:
'+a+' '
+ );
+ }
+
+ });
+
break;
}
@@ -632,3 +945,6 @@ on("ready",function(){
GroupInitiative.CheckInstall();
GroupInitiative.RegisterEventHandlers();
});
+
+
+
diff --git a/GroupInitiative/package.json b/GroupInitiative/package.json
index 5b8732762e..2573b8fa10 100644
--- a/GroupInitiative/package.json
+++ b/GroupInitiative/package.json
@@ -1,6 +1,6 @@
{
"name": "GroupInitiative",
- "version": "0.8.2",
+ "version": "0.8.7",
"description": "Adds the selected tokens to the turn order after rolling their initiative + configurable data.",
"authors": "The Aaron",
"roll20userid": "104025",