Skip to content

Instantly share code, notes, and snippets.

@shdwjk
Last active August 29, 2015 14:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shdwjk/79a60b8d2ee58e87604d to your computer and use it in GitHub Desktop.
Save shdwjk/79a60b8d2ee58e87604d to your computer and use it in GitHub Desktop.
Roll20 API: Ammo - provides inventory management for ammunition stored in an attribute of a character.
// GIST: https://gist.github.com/shdwjk/79a60b8d2ee58e87604d
var Ammo = Ammo || (function() {
'use strict';
var version = 0.11,
adjustAmmo = function (playerid,attr,amount) {
var val = parseInt(attr.get('current'),10)||0,
max = parseInt(attr.get('max'),10)||10000,
adj = (val+amount),
chr = getObj('character',attr.get('characterid')),
valid = true;
if(adj < 0 ) {
sendChat('Ammo', (isGM(playerid) ? '/w gm ' : '')
+'<div style="padding:1px 3px;border: 1px solid #8B4513;background: #eeffee; color: #8B4513; font-size: 80%;">'
+'<b>'+chr.get('name') + '</b> does not have enough ammo. Needs '+Math.abs(amount)+', but only has '
+'<span style="color: #ff0000;">'+val+'</span>.'
+'<span style="font-weight:normal;color:#708090;>&#91;Attribute: '+attr.get('name')+'&#93;</span>'
+'</div>'
);
valid = false;
} else if( adj > max) {
sendChat('Ammo', (isGM(playerid) ? '/w gm ' : '')
+'<div style="padding:1px 3px;border: 1px solid #8B4513;background: #eeffee; color: #8B4513; font-size: 80%;">'
+'<b>'+chr.get('name') + '</b> does not have enough storage space for ammo. Needs '+adj+', but only has '
+'<span style="color: #ff0000;">'+max+'</span>.'
+'<span style="font-weight:normal;color:#708090;>&#91;Attribute: '+attr.get('name')+'&#93;</span>'
+'</div>'
);
valid = false;
}
if( isGM(playerid) || valid ) {
attr.set({current: adj});
sendChat('Ammo', (isGM(playerid) ? '/w gm ' : '')
+'<div style="padding:1px 3px;border: 1px solid #8B4513;background: #eeffee; color: #8B4513; font-size: 80%;">'
+'<b>'+chr.get('name') + '</b> '+( (adj<val) ? 'uses' : 'gains' )+' '+Math.abs(amount)+' ammo and has '+adj+' remaining.'
+'</div>'
);
if(!valid) {
sendChat('Ammo', '/w gm '
+'<div style="padding:1px 3px;border: 1px solid #8B4513;background: #eeffee; color: #8B4513; font-size: 80%;">'
+'Ignoring warnings and applying adjustment anyway. Was: '+val+'/'+max+' Now: '+adj+'/'+max
+'</div>'
);
}
}
},
showHelp = function(playerid) {
var who=getObj('player',playerid).get('_displayname').split(' ')[0];
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%;">'
+'Ammo v'+version
+'</div>'
+'<div style="padding-left:10px;margin-bottom:3px;">'
+'<p>Ammo provides inventory management for ammunition stored in a character'
+'attribute. If the adjustment would change the attribute to be below 0 or above'
+'it\'s maximum value, a warning will be issued and the attribute will not be'
+'changed.</p>'
+( (isGM(playerid)) ? '<p><b>Note:</b> As the GM, bounds will not be '
+'enforced for you. You will be whispered the warnings, but the operation '
+'will succeed. You will also be told the previous and current state in case '
+'you want to revert the change.' : '')
+'</div>'
+'<b>Commands</b>'
+'<div style="padding-left:10px;">'
+'<b><span style="font-family: serif;">!ammo &lt;id&gt; &lt;attribute&gt; &lt;amount&gt; </span></b>'
+'<div style="padding-left: 10px;padding-right:20px">'
+'This command requires 3 parameters:'
+'<ul>'
+'<li style="border-top: 1px solid #ccc;border-bottom: 1px solid #ccc;">'
+'<b><span style="font-family: serif;">id</span></b> -- The id of the character which has the attribute. You can pass this as &#64;&#123;selected|token_id&#125; and the character id will be pulled from represents field of the token.'
+'</li> '
+'<li style="border-top: 1px solid #ccc;border-bottom: 1px solid #ccc;">'
+'<b><span style="font-family: serif;">attribute</span></b> -- The name of the attribute representing ammunition.'
+'</li> '
+'<li style="border-top: 1px solid #ccc;border-bottom: 1px solid #ccc;">'
+'<b><span style="font-family: serif;">amount</span></b> -- The change to apply to the current quantity of ammo. Use negative numbers to decrease the amount, and possitive numbers to increase it.'
+'</li> '
+'</ul>'
+'</div>'
+'</div>'
+'<div style="padding-left:10px;">'
+'<b><span style="font-family: serif;">!get-represents [token_id]</span></b>'
+'<div style="padding-left: 10px;padding-right:20px">'
+'This command will show the character id for the supplied token id, or will list the character ids for all the selected tokens.'
+'<ul>'
+'<li style="border-top: 1px solid #ccc;border-bottom: 1px solid #ccc;">'
+'<b><span style="font-family: serif;">token_id</span></b> -- The id of the token to lookup, usually supplied with: &#64;&#123;selected|token_id&#125;'
+'</li> '
+'</ul>'
+'</div>'
+'</div>'
+'</div>'
);
},
HandleInput = function(msg_orig) {
var msg = _.clone(msg_orig),
args,attr,amount,chr,token,text='';
if (msg.type !== "api") {
return;
}
if(_.has(msg,'inlinerolls')){
msg.content = _.chain(msg.inlinerolls)
.reduce(function(m,v,k){
m['$[['+k+']]']=v.results.total || 0;
return m;
},{})
.reduce(function(m,v,k){
return m.replace(k,v);
},msg.content)
.value();
}
args = msg.content.split(" ");
switch(args[0]) {
case '!ammo':
if(args.length > 1) {
chr = getObj('character', args[1]);
if( ! chr ) {
token = getObj('graphic', args[1]);
if(token) {
chr = getObj('character', token.get('represents'));
}
}
if(chr) {
if(! isGM(msg.playerid)
&& ! _.contains(chr.get('controlledby').split(','),msg.playerid)
&& ! _.contains(chr.get('controlledby').split(','),'all')
)
{
sendChat('Ammo', '<div style="padding:1px 3px;border: 1px solid #8B4513;background: #eeffee; color: #8B4513; font-size: 80%;">'
+'You do not control the specified character: '+chr.id
+'</div>'
);
sendChat('Ammo', '/w gm <div style="padding:1px 3px;border: 1px solid #8B4513;background: #eeffee; color: #8B4513; font-size: 80%;">'
+'<b>'+getObj('player',msg.playerid).get('_displayname')+'</b> attempted to adjust attribute <b>'+args[2]+'</b> on character <b>'+chr.get('name')+'</b>.'
+'</div>'
);
return;
}
attr = findObjs({_type: 'attribute', _characterid: chr.id, name: args[2]})[0];
}
amount=parseInt(args[3],10);
if(attr && amount) {
adjustAmmo(msg.playerid,attr,amount);
} else {
if(attr) {
sendChat('Ammo', (isGM(msg.playerid) ? '/w gm ' : '')
+'<div style="padding:1px 3px;border: 1px solid #8B4513;background: #eeffee; color: #8B4513; font-size: 80%;">'
+'Amount ['+args[3]+'] is not correct. Please specify a positive or negative integer value like -1 or 4.'
+'</div>'
);
} else {
if(chr) {
sendChat('Ammo', (isGM(msg.playerid) ? '/w gm ' : '')
+'<div style="padding:1px 3px;border: 1px solid #8B4513;background: #eeffee; color: #8B4513; font-size: 80%;">'
+' Attribute ['+args[2]+'] was not found. Please verify that you have the right name.'
+'</div>'
);
} else {
sendChat('Ammo', (isGM(msg.playerid) ? '/w gm ' : '')
+'<div style="padding:1px 3px;border: 1px solid #8B4513;background: #eeffee; color: #8B4513; font-size: 80%;">'
+( (undefined !== token) ? ('Token id ['+args[1]+'] does not represent a character. ') : ('Character/Token id ['+args[1]+'] is not valid. ') )
+'Please be sure you are specifying it correctly, either with &#64;&#123;selected|token_id&#125; or copying the character id from: !get-represents &#64;&#123;selected|token_id&#125; '
+'</div>'
);
}
}
}
} else {
showHelp(msg.playerid);
}
break;
case '!get-represents':
if(args.length > 1) {
chr = getObj('character', args[1]);
if( ! chr ) {
token = getObj('graphic', args[1]);
if(token) {
sendChat('Ammo', (isGM(msg.playerid) ? '/w gm ' : '')
+'<div style="padding:1px 3px;border: 1px solid #8B4513;background: #eeffee; color: #8B4513; font-size: 80%;">'
+'The specified token represents the following character:'
+'<ul><li>'+ ( ('' !== token.get('name')) ? token.get('name') : 'BLANK' )+' -> '+ ( ('' !== token.get('represents')) ? token.get('represents') : 'NOTHING' ) + '</li></ul>'
+'</div>'
);
} else {
sendChat('Ammo', (isGM(msg.playerid) ? '/w gm ' : '')
+'<div style="padding:1px 3px;border: 1px solid #8B4513;background: #eeffee; color: #8B4513; font-size: 80%;">'
+' Token id ['+args[1]+'] is not valid.'
+'</div>'
);
}
}
} else if (msg.selected && msg.selected.length) {
_.each(msg.selected, function(s) {
token = getObj('graphic', s._id);
if(token) {
text += '<li>'+ ( ('' !== token.get('name')) ? token.get('name') : 'BLANK' )+' -> '+ ( ('' !== token.get('represents')) ? token.get('represents') : 'NOTHING' ) + '</li>';
}
});
sendChat('Ammo', (isGM(msg.playerid) ? '/w gm ' : '')
+'<div style="padding:1px 3px;border: 1px solid #8B4513;background: #eeffee; color: #8B4513; font-size: 80%;">'
+'The selected tokens represent the following characters:'
+'<ul>' + text + '</ul>'
+'</div>'
);
} else {
showHelp(msg.playerid);
}
break;
}
},
RegisterEventHandlers = function() {
on('chat:message', HandleInput);
};
return {
RegisterEventHandlers: RegisterEventHandlers
};
}());
on("ready",function(){
'use strict';
var Has_IsGM=false;
try {
_.isFunction(isGM);
Has_IsGM=true;
}
catch (err)
{
log('--------------------------------------------------------------');
log('Ammo requires the isGM module to work.');
log('isGM GIST: https://gist.github.com/shdwjk/8d5bb062abab18463625');
log('--------------------------------------------------------------');
}
if( Has_IsGM )
{
Ammo.RegisterEventHandlers();
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment