The trophy does look like a good choice. Here you go! I also made some tweaks to the messages that pop up when you try to loot an invalid token, to make it clearer which token is invalid. /* !Loot @{target|token_id} or !Loot @{selected|token_id} You must have an Ability on the character sheet named Loot. This will be printed out, will roll any inline rolls, and preserve paragraphs. */ var loot = loot || (function () { 'use strict'; const version = '0.3', COMMAND = 'Loot', // this is the name you must use for the Ability, make sure capitalisation matches. HPBAR = 1, // this is the bar used for tracking HP MARKER = 'trophy', // set the status marker used to show if treasure has been rolled for this token. scriptName = 'Loot', lastUpdate = 1545273360606, divider = ' -|- ', // do not use same as newline newline = '--', random = '|', checkInstall = function () { log('--| ' + scriptName + ' v' + version + ' |-- [' + (new Date(lastUpdate)) + ']'); }, processInlinerolls = function (msg) { if (_.has(msg, 'inlinerolls')) { return _.chain(msg.inlinerolls) .reduce(function(previous, current, index) { previous['$[[' + index + ']]'] = current.results.total || 0; return previous; },{}) .reduce(function(previous, current, index) { return previous.replace(index, current); }, msg.content) .value(); } else { return msg.content; } }, getSpeaker = function(msg) { let characters = findObjs({_type: 'character'}); let speaking; characters.forEach(function(chr) { if(chr.get('name') == msg.who) speaking = chr; }); let speaker = speaking ? 'character|'+speaking.id : 'player|'+msg.playerid; return speaker; }, handleInput = function (msg) { if ('api' === msg.type && msg.content.match(`!format${COMMAND} `)) { let args = processInlinerolls(msg).split(divider); //); let lootBase = args[2].split(newline); let loot = [], i = 0; lootBase.forEach(row => { let item = row.split(random); loot[i] = item.length === 1 ? item : item[randomInteger(item.length -1)]; i ++; }); let output = `&{template:traits} {{name=${args[1].trim()}'s Treasure}} {{description=${loot.join('\n')}}}`; let speaker = args[3]; sendChat(speaker,output); } else if ('api' === msg.type && msg.content.match(`!${COMMAND} `)) { let id = msg.content.replace(`!${COMMAND}`,'').trim(); let token = findObjs({_type: 'graphic', id: id})[0]; let tname = token.get('name'); if(!token) { sendChat(COMMAND,'/w GM Token Not Found'); return; } if(token.get('status_' + MARKER)) { sendChat(COMMAND,`${tname} has already been looted.`); return; } let character = getObj('character', token.get('represents')); if(!character) { sendChat(COMMAND,`/w GM Character Not Found for token ${tname}.`); return; } let greenVal = token.get(`bar${HPBAR}_value`); if (isNaN(greenVal)) { sendChat(COMMAND,`/w GM ${tname}'s Bar is not a number`); } else if (greenVal > 0) { sendChat(COMMAND,`${tname} is not yet defeated.`); } else { //let loot = getAttrByName(character.id, COMMAND, 'current'); let loot = findObjs({_type: 'ability', characterid: character.id, name: COMMAND})[0]; if(!loot) { sendChat(COMMAND,`/w GM Loot Not Found for ${tname}'s token.`); } else { let speaker = getSpeaker(msg); let action = loot.get('action').toString(); let output = action.split('\n').join(newline); token.set('status_' + MARKER,true); sendChat(COMMAND, `!format${COMMAND} ${divider} ${tname} ${divider} ${output} ${divider} ${speaker}`); // } } } }, registerEventHandlers = function () { on('chat:message', handleInput); }; return { CheckInstall: checkInstall, RegisterEventHandlers: registerEventHandlers }; }()); on('ready', function () { 'use strict'; loot.CheckInstall(); loot.RegisterEventHandlers(); });