Here's a script that might fit your needs. It'll print out a roll using your rolltemplate, and include the mp cost, as well as update it on the character sheet. You lose the crit and fumble color coding on the d100 inline roll, but since you have a row that reports whether its a critical or fumble, that shouldn't matter. First, add this to your rolltemplate (maybe make it the last row of the table): {{#mp_spent}} <tr> <td colspan="2" class="template_label">&nbsp;MP Spent:</td> <td class="template_value">{{mp_spent}}</td> </tr> {{/mp_spent}} Change your button code from <button type="roll" name="roll_SPELL" value="&{template:spell} {{name=@{Name} casts @{SPELL-NAME}}} {{skill_lvl=[[@{SPELL-SKILL}]]}}{{totalmod=[[floor((round(@{SPELL-SKILL}*?{Multiplier|1})+?{Modifier|0}))-@{SPELL-SKILL}]]}}{{success=[[floor((round(@{SPELL-SKILL}*?{Multiplier|1})+?{Modifier|0}))]]}}{{half=[[((round((@{SPELL-SKILL}*?{Multiplier|1})+?{Modifier|0})/2))]]}} {{quarter=[[round(((@{SPELL-SKILL}*?{Multiplier|1})+?{Modifier|0})/4)]]}}{{thirty=[[floor((round(@{SPELL-SKILL}*?{Multiplier|1})+?{Modifier|0}))-30]]}}{{sixty=[[floor((round(@{SPELL-SKILL}*?{Multiplier|1})+?{Modifier|0}))-60]]}}{{crit=[[floor((round((@{SPELL-SKILL}*?{Multiplier|1})+?{Modifier|0}))/10)]]}}{{fumble=[[90 +floor((round((@{SPELL-SKILL}*?{Multiplier|1})+?{Modifier|0}))/10)]]}}{{Rolled=[[d100cs<[[floor((round((@{SPELL-SKILL}*?{Multiplier|1})+?{Modifier|0}))/10)]]cf>[[90 +floor((round((@{SPELL-SKILL}*?{Multiplier|1})+?{Modifier|0}))/10)]]]]}}"></button> to <button type="roll" name="roll_SPELL" value="!pjspellroll --id:@{character_id} --name:@{name} --spell:@{SPELL-NAME} --level:@{SPELL-SKILL} --cost:@{SPELL-MP} --multiplier:?{Multiplier|1} --modifier:?{modifier|0} --roll:[[1d100]]"></button> And in your API scripts, add this on("ready", () => { const numberParams = ['level','multiplier','modifier','roll','cost'], textParams = ['id','name','spell'], mpname = 'Magic-Points', mpspent = 'mp_spent', 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; } }, getParameters = function(args) { const params = args .map(x => x.split(':').map(y => y.trim())) .reduce((a, x) => { a[x[0]] = x[1]; return a; }, {}); return params; }, getSuccess = params => Math.floor(Math.round(params.level * params.multiplier) + params.modifier*1), getFumble = params => { const success = getSuccess(params); return success > 98 ? 100 : 90 + Math.floor(success/10); }, buildOutput = function(params) { let output = `&{template:spell} {{name=${params.name} casts ${params.spell}}} {{skill_lvl=[[${params.level}]]}} `; //&{template:spell} const success = getSuccess(params); const fumble = getFumble(params); const crit = Math.round(success/10); output += `{{totalmod=[[${success}-${params.level}]]}} `; output += `{{success=[[${success}]]}} `; output += `{{half=[[${Math.round(success/2)}]]}} `; output += `{{quarter=[[${Math.round(success/4)}]]}} `; output += `{{thirty=[[${success -30}]]}} `; output += `{{sixty=[[${success -60}]]}} `; output += `{{crit=[[${crit}]]}} `; output += `{{fumble=[[${fumble}]]}} `; output += `{{Rolled=[[${params.roll}]]}}`; output += `{{${mpspent}=[[${getSpent(params)}]]}}`; return output; }, getSpent = function(params) { const success = getSuccess(params); const fumble = getFumble(params); let cost = params.cost; if(params.roll > success && params.roll < fumble) cost = Math.ceil(cost/2); return cost; }, updateCost = function(params) { const cost = getSpent(params); const mp = findObjs({ _characterid: params.id, name: mpname, })[0]; if(mp) { let current = mp.get('current'); current -= cost; mp.set('current',current); }; }; on("chat:message", msg => { if(msg.type == "api" && msg.content.match(`!pjspellroll --`)){ const msg_new = processInlinerolls(msg); const args = msg_new.split('--'); args.shift(); const params = getParameters(args); const output = buildOutput(params); sendChat('character|' + params.id,output); updateCost(params); } }); }); CAVEATS: I dont have error checking, so if there are typos in the button code or missing attributes or attributes with invalid values, it can crash the script sandbox, and scripts will stop working till you manually restart that. But since you are calling this from a character sheet, that shouldn't happen very often. I'll add it later if you like this script, but it's bedtime for now.