As Oosh said, the Roll20Async side does unfortunately break the API sandbox which makes it unusable in my opinion (I really wish it was usable). However, there are two alternatives. If you just need the stat to be used in a roll, you could do what I did for the Starfinder by Roll20 character sheet. The starfinder ship sheet allows users to enter their character names in the various crew slots and then the sheet's sheetworkers construct the macros for a given roll so that it calls the correct attribute from that character's sheet. This could of course be swapped if you need characters to call attributes from the ship sheet. Additionally, with custom roll parsing this would actually become easier to setup as the macro could be assembled in real time. The second option is something that only became possible with the advent of Custom Roll Parsing (CRP). It is however a very hacky method that I'm not sure I'd ever use on a sheet that is going to be used for the public. This method would let you actually use another sheet's attribute values in calculations. What you'd need for the hacky CRP method: A button to trigger a recalculation of values dependent on the other sheet. This will trigger a CRP function A place to input the name of the sheet(s) to pull data from Your CRP function, which will send a roll to chat that will call the values needed from the other sheet. This roll would start with an exclamation ( ! ) to stop it from showing up in chat. In general, option 2 would look something like this (untested code for demo purposes only): <button type="action" name="act_pull-data">Update data from other sheet</button>
<input type="text" name="attr_connected_character" value="">
<input type="number" name="attr_attribute_to_get" value="10">
<input type="number" name="attr_attribute_to_set" value="">
<script type="text/worker">
const getOtherAttribute = async function(charName,attrName){
debug('entering extractQueryResult');
let queryRoll = await startRoll(`!{{query=[[0[response=@{${charName}|${attrName}}]]]}}`);
finishRoll(queryRoll.rollId);
return queryRoll.results.query.expression.replace(/^.+?response=|\]$/g,'');
};
on("click:pull-data",()=>{
getAttrs(['connected_character'],async (attributes)=>{
if(!attributes.connected_character){
return;
}
const setObj = {};
setObj.attribute_to_set = await getOtherAttribute(attributes.connected_character,'attribute_to_get');//Returns a string version of the attribute. Convert to number as needed.
setAttrs(setObj);
});
})
</script> I use something similar to this in several sheets to query the user for options they want to use for a given roll. The reason I wouldn't recommend doing this in a sheet meant for the repo is that this method will screw with users' ability to up arrow to see their last roll. The last roll may be one of these messages to get another character's data instead of the roll they actually sent to chat. This is also why, regardless of whether the sheet is meant for production or not, I'd recommend locking this update behind a button; otherwise you could wind up with literally hundreds of these hidden messages polluting the chat archive as they'd be sent every time an attribute related to the connected value was updated. And, finally, you could reverse the function as well and have the update button work so that it calls an action button on another sheet to inject data into that other sheet. You'd want to use some of the discoveries from Oosh's Adventures with startRoll for that .