'use strict'; /* global on log playerIsGM findObjs getObj getAttrByName sendChat globalconfig */ // eslint-disable-line no-unused-vars /* GMSheet 0.1.3 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.1.3'; // 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 resolveAttr = function resolveAttr(cid, name) { return { name: name, current: getAttrByName(cid, name), max: getAttrByName(cid, name, 'max') }; }; 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; 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 = ''; // start with sorcerer points here... // check which attribute to get. if (resolveAttr(cid, 'class').current === 'Sorcerer') { resourceName = 'Sorcerer points'; } else if (resolveAttr(cid, 'class').current === 'Barbarian') { resourceName = 'Rage'; } else if (resolveAttr(cid, 'class').current === 'Bard') { resourceName = 'Bardic Inspiration'; } else if (resolveAttr(cid, 'class').current === 'Cleric' || resolveAttr(cid, 'class').current === 'Paladin') { resourceName = 'Channel Divinity'; } else if (resolveAttr(cid, 'class').current === 'Druid') { resourceName = 'Wild Shape'; } else if (resolveAttr(cid, 'class').current === 'Fighter') { resourceName = 'Second Wind'; } else if (resolveAttr(cid, 'class').current === 'Monk') { resourceName = 'KI'; } else if (resolveAttr(cid, 'class').current === 'Warlock') { resourceName = 'Spell Slots'; } var classResourceTotal = resolveAttr(cid, 'class_resource').max; var classResourceCurrent = resolveAttr(cid, 'class_resource').current; if (resourceName) output += '
' + resourceName + ': ' + classResourceCurrent + '/' + classResourceTotal; 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.1.3

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 = ''; } }); });