'use strict'; /* global on log playerIsGM findObjs getObj getAttrByName sendChat globalconfig */ // eslint-disable-line no-unused-vars /* GMSheet 0.2.0 A quick GM Cheatsheet for the D&D 5e OGL sheets on roll20.net. Please use `!gmsheet` for inline help and examples. arthurbauer@me.com */ on('ready', function () { var v = '0.2.0'; // version number var scname = 'GMSheet'; // script name log(scname + ' v' + v + ' online. Select one or more party members, then use `!gmsheet -h`'); var output = ''; var collectedAttributes = ''; var wantedAttributes = void 0; var columnjumper = 0; var myoutput = ''; var resourceName = ''; var otherresourceName = ''; var resolveAttr = function resolveAttr(cid, attname) { var attobj = findObjs({ type: 'attribute', characterid: cid, name: attname }, { caseInsensitive: true })[0]; if (!attobj) { return { name: '', current: '', max: '' }; } var att2 = { name: attobj.get('name'), current: attobj.get('current'), max: attobj.get('max') }; return att2; }; var getCharMainAtt = function getCharMainAtt(cid2) { //! Main attributes output = ''; var cid = cid2.id; wantedAttributes = ['strength', 'dexterity', 'constitution', 'intelligence', 'wisdom', 'charisma']; wantedAttributes.forEach(function (myAtt) { collectedAttributes = resolveAttr(cid, myAtt); output += ''; if (columnjumper === 1) { output += ''; columnjumper = 0; } else { columnjumper = 1; } }); output += '
' + collectedAttributes.name.slice(0, 3).toUpperCase() + ': ' + (resolveAttr(cid, myAtt + '_mod').current > 0 ? '+' + resolveAttr(cid, myAtt + '_mod').current : resolveAttr(cid, myAtt + '_mod').current) + ' (' + collectedAttributes.current + ')  
'; return output; }; var getCharOtherAtt = function getCharOtherAtt(cid2) { //! Other Attributes output = ''; var cid = cid2.id; var hp = parseInt(resolveAttr(cid, 'hp').current, 10); var maxhp = parseInt(resolveAttr(cid, 'hp').max, 10); var hpdown = maxhp - hp; var hppercentage = Math.floor(100 * hp / maxhp / 5) * 5; output = '
' + resolveAttr(cid, 'race').current + ' Lvl ' + resolveAttr(cid, 'level').current + ' ' + resolveAttr(cid, 'class').current + ''; output += resolveAttr(cid, 'inspiration').current === 'on' ? " 🌟" : ''; output += '

HP: ' + hp + '/' + maxhp + ' '; output += hp < maxhp ? ' 🤕 ' + hppercentage + '% (-' + hpdown + ' HP) ' : ''; output += parseInt(resolveAttr(cid, 'hp_temp').current, 10) > 0 ? ' + ' + resolveAttr(cid, 'hp_temp').current + ' TMP' : ''; output += '
AC: ' + resolveAttr(cid, 'ac').current; output += '

Speed: ' + resolveAttr(cid, 'speed').current + ' ft, Passive Perception: ' + resolveAttr(cid, 'passive_wisdom').current + '
Initiative bonus: ' + (resolveAttr(cid, 'initiative_bonus').current > 0 ? '+' + resolveAttr(cid, 'initiative_bonus').current : resolveAttr(cid, 'initiative_bonus').current) + ', Proficiency ' + (resolveAttr(cid, 'pb').current > 0 ? '+' + resolveAttr(cid, 'pb').current : resolveAttr(cid, 'pb').current); output += '

'; return output; }; var getSpellSlots = function getSpellSlots(cid2) { //! Spell slots output = ''; var cid = cid2.id; output = '
Spell slots
'; var i = 1; var spellLevelTotal = 0; var spellLevelEx = 0; var spellcount = 0; while (i < 10) { spellLevelTotal = resolveAttr(cid, 'lvl' + parseInt(i, 10) + '_slots_total').current; if (spellLevelTotal === 0 || spellLevelTotal === '') break; spellLevelEx = resolveAttr(cid, 'lvl' + parseInt(i, 10) + '_slots_expended').current; if (spellLevelTotal > 0) { spellcount += 1; if (spellLevelEx / spellLevelTotal <= 0.25) spellLevelEx = '' + spellLevelEx + '';else if (spellLevelEx / spellLevelTotal <= 0.5) spellLevelEx = '' + spellLevelEx + '';else if (spellLevelEx / spellLevelTotal <= 0.75) spellLevelEx = '' + spellLevelEx + '';else spellLevelEx = '' + spellLevelEx + ''; output += 'Level ' + i + ': ' + spellLevelEx + ' / ' + spellLevelTotal + '
'; } i += 1; } if (spellcount < 1) output = ''; //! class resources resourceName = resolveAttr(cid, 'class_resource_name').current; otherresourceName = resolveAttr(cid, 'other_resource_name').current; var classResourceTotal = resolveAttr(cid, 'class_resource').max; var classResourceCurrent = resolveAttr(cid, 'class_resource').current; var otherResourceTotal = resolveAttr(cid, 'other_resource').max; var otherResourceCurrent = resolveAttr(cid, 'other_resource').current; if (resourceName && classResourceTotal > 0) output += '
' + resourceName + ': ' + classResourceCurrent + '/' + classResourceTotal; if (otherresourceName && otherResourceTotal > 0) output += '
' + otherresourceName + ': ' + otherResourceCurrent + '/' + otherResourceTotal; resourceName = ''; return output; }; on('chat:message', function (msg) { if (msg.type !== 'api' && !playerIsGM(msg.playerid)) return; if (msg.content.startsWith('!gmsheet') !== true) return; if (msg.content.includes('-help') || msg.content.includes('-h')) { //! Help sendChat(scname, '/w gm

Roll20-GMSheet

Version 0.2.0

A quick GM Cheatsheet for the D&D 5e OGL sheets on Roll20.Please use !gmsheet -h for inline help and examples.

Displayed information

The script currently shows

Usage

  1. Select one or several tokens
  2. Type !gmsheet in chat
'); // eslint-disable-line quotes } else if (msg.selected == null) { sendChat(scname, '/w gm **ERROR:** You need to select at least one character.'); /* will add a routine to save/load characters later */ } else { msg.selected.forEach(function (obj) { //! Output var token = getObj('graphic', obj._id); // eslint-disable-line no-underscore-dangle var character = void 0; if (token) { character = getObj('character', token.get('represents')); } if (character) { /* get the attributes and assemble the output */ var charname = character.get('name'); var charicon = character.get('avatar'); if (myoutput.length > 0) myoutput += '
'; myoutput += '
' + charname + '
' + getCharOtherAtt(character) + getCharMainAtt(character) + getSpellSlots(character); } }); sendChat(scname, '/w gm
' + myoutput + '
'); // eslint-disable-line quotes myoutput = ''; } }); });