fixed it after some experimentation - using OnyxRing's code for setting attribs and saving roll info in attribs to use for the next roll/reroll <!-- The visible and draggable button for the macro bar --> <button type="roll" name="roll_test" value="@{test_action}">test</button> <!-- The invisible button allowing the use of custom roll parsing --> <button type="action" name="act_test-action" class="hidden"></button> <button type="action" name="act_test-reroll" class="hidden"></button> <!-- The invisible field for the attribute which contains the ability call --> <input type="hidden" name="attr_test_action" value=""> <input type="hidden" name="attr_test_successes" value=""> <input type="hidden" name="attr_test_dicerolled" value=""> <input type="hidden" name="attr_test_ones" value=""> <rolltemplate class="sheet-rolltemplate-test"> <div class="sheet-template-container"> <h1>{{name}}</h1> <div class="sheet-results"> <h4>Successes = {{computed::roll1}}</h4> <h4>[Push]({{reroll}})</h4> </div> </div> </rolltemplate> <rolltemplate class="sheet-rolltemplate-testreroll"> <div class="sheet-template-container"> <h1>{{name}}</h1> <div class="sheet-results"> <h4>Successes = {{computed::roll1}} Prior={{prior}} Ones={{ones}}</h4> </div> </div> </rolltemplate> <script type="text/worker"> on("sheet:opened change:character_name", function(eventInfo) { getAttrs(["character_name", "test_action","test_reroll"], function(v) { var attrsToChange = {}; attrsToChange["test_action"] = "%{" + v["character_name"] + "|test-action}"; setAttrs(attrsToChange); }); }); on('clicked:test-action', async (info) => { const values = await getAttrsAsync(['strength','endure','character_name']); const stat = +parseInt(values.strength) || 0; const skill = +parseInt(values.endure) || 0; const charname = values.character_name || ""; const statskill = stat+skill; const results = await startRoll("&{template:test} {{name=Test}} {{roll1=[[[["+statskill+"+?{Bonus}]]d6>6]]}} {{reroll=~"+charname+"|test-reroll}}"); const successes = results.results.roll1.result; const dicerolled= results.results.roll1.dice.length; const thedice= results.results.roll1.dice; const ones= thedice.filter(element => element < 2); const totalofones = ones.length; const computed = successes; var attrsToChange = {}; attrsToChange["test_successes"] = successes; attrsToChange["test_dicerolled"] = dicerolled; attrsToChange["test_ones"] = totalofones; setAttrs(attrsToChange); finishRoll( results.rollId, { roll1: computed, } ); }); on('clicked:test-reroll', async (info) => { const values = await getAttrsAsync(['test_dicerolled','test_successes','test_ones']); const priorsuccesses = +parseInt(values.test_successes) || 0; const dicerolled = +parseInt(values.test_dicerolled) || 0; const ones = +parseInt(values.test_ones) || 0; const results = await startRoll("&{template:testreroll} {{name=Test}} {{roll1=[["+(dicerolled-priorsuccesses-ones)+"d6>6]]}}{{prior="+priorsuccesses+"}}{{ones="+ones+"}}"); const successes = results.results.roll1.result; const computed = successes+priorsuccesses; finishRoll( results.rollId, { roll1: computed, } ); });