// Github: https://github.com/shdwjk/Roll20API/blob/master/Ammo/Ammo.js // By: The Aaron, Arcane Scriptomancer // Contact: https://app.roll20.net/users/104025/the-aaron var Ammo = Ammo || (function() { 'use strict'; var version = '0.3.2', lastUpdate = 1457507907, schemaVersion = 0.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 ''; }, sendMessage = function(message, who) { sendChat('Ammo', (who ? ('/w '+who+' ') : '') + '
'+ message+ '
' ); }, 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 ) { sendMessage( ''+chr.get('name') + ' does not have enough ammo. Needs '+Math.abs(amount)+', but only has '+ ''+val+'.'+ ''+max+'.'+ ''+ '
'+ 'Ammo v'+version+ '
'+ '
'+ '

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.

'+ ( (playerIsGM(playerid)) ? '

Note: 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.' : '')+ '

'+ 'Commands'+ '
'+ '!ammo '+ch('<')+'id'+ch('>')+' '+ch('<')+'attribute'+ch('>')+' '+ch('<')+'amount'+ch('>')+' '+ '
'+ 'This command requires 3 parameters:'+ '
    '+ '
  • '+ 'id -- The id of the character which has the attribute. You can pass this as '+ch('@')+ch('{')+'selected|token_id'+ch('}')+' and the character id will be pulled from represents field of the token.'+ '
  • '+ '
  • '+ 'attribute -- The name of the attribute representing ammunition.'+ '
  • '+ '
  • '+ 'amount -- The change to apply to the current quantity of ammo. Use negative numbers to decrease the amount, and possitive numbers to increase it.'+ '
  • '+ '
'+ '
'+ '
'+ '' ); }, 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(/\s+/); switch(args[0]) { case '!ammo': if(args.length > 1) { switch(args[1]) { case 'recover': // // apply policy to put amounts back in case 'check': // // print the amount in the attribute nicely formatted case 'recovery-policy': // [character/token_id] [attribute_name] // create the right entry in the state case 'name': // [character/token_id] [attribute_name] // create the right entry in the state // configs case 'recovery-updates-maximum': // adjust the maximum to be whatever the current is case 'create-attributes-automatically': // create the requested attribute and start using it. } chr = getObj('character', args[1]); if( ! chr ) { token = getObj('graphic', args[1]); if(token) { chr = getObj('character', token.get('represents')); } } if(chr) { if(! playerIsGM(msg.playerid) && ! _.contains(chr.get('controlledby').split(','),msg.playerid) && ! _.contains(chr.get('controlledby').split(','),'all') ) { sendMessage( 'You do not control the specified character: '+chr.id ); sendMessage( ''+getObj('player',msg.playerid).get('_displayname')+' attempted to adjust attribute '+args[2]+' on character '+chr.get('name')+'.', 'gm' ); 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) { sendMessage( 'Amount ['+args[3]+'] is not correct. Please specify a positive or negative integer value like -1 or 4.', (playerIsGM(msg.playerid) ? 'gm' : false) ); } else { if(chr) { sendMessage( 'Attribute ['+args[2]+'] was not found. Please verify that you have the right name.', (playerIsGM(msg.playerid) ? 'gm' : false) ); } else { sendMessage( ( 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 '+ch('@')+ch('{')+'selected|token_id'+ch('}')+ ' or '+ch('@')+ch('{')+'selected|character_id'+ch('}')+'.', (playerIsGM(msg.playerid) ? 'gm' : false) ); } } } } else { showHelp(msg.playerid); } break; } }, checkInstall = function() { log('-=> Ammo v'+version+' <=- ['+(new Date(lastUpdate*1000))+']'); if( ! _.has(state,'Ammo') || state.Ammo.version !== schemaVersion) { log(' > Updating Schema to v'+schemaVersion+' <'); state.Ammo = { version: schemaVersion, config: { }, policies: { global: { recoveryUpdatesMaximum: false }, byAttribute: { }, byCharacter: { } } }; } }, RegisterEventHandlers = function() { on('chat:message', HandleInput); }; return { CheckInstall: checkInstall, RegisterEventHandlers: RegisterEventHandlers }; }()); on("ready",function(){ 'use strict'; Ammo.CheckInstall(); Ammo.RegisterEventHandlers(); });