Now that I'm back home and not rushing, here's a more in depth explanation: <div class="caracs">
<span><label>Caractéristique</label></span>
<span><label>Valeur</label></span>
<span><label>Explosif</label></span>
<span><label>Non explosif</label></span>
<span><label>Force</label></span>
<!-- Unrelated, but I'd really recommend using full names and snake_case for attribute names. It makes it easier for a user to decipher what is going on. So, I'd recommend `force`, `force_die_explode`, and `force_die` for these attributes. I've changed these to this naming scheme for this more complete demo.-->
<span><input type="number" name="attr_force" value=""/></span>
<input type="hidden" name="attr_force_die_explode"><!-- The actual attributes to hold the die numbers are hidden. You may actually want to make these visible, and just leave them as readonly so that only your script can edit them. -->
<span name="attr_force_die_explode_display" style="font-family:dicefontd6;color:red;"></span><!-- This will hold the display version of the dice number. It's an attribute backed span, so only the script can edit it. -->
<input type="hidden" name="attr_force_die">
<span name="attr_force_die_display" style="font-family:dicefontd6;color:blue;"></span>
<!--Same thing repeated for every abilty-->
</div>
<script type="text/worker">
// This tag holds our sheetworkers; the Roll20 specific javascript that allows us to do powerful things with our sheets.
//In the previous version of this, I had missed that you weren't already using a sheetworker to calculate the dice types, so I'll adjust the below to handle that as well.
const characteristics = ['force','agilite','focus','intuition','logique','presence','endurance','constitution'];//The names of all the characteristics
characteristics.forEach((characteristic)=>{//iterate through each characteristic
on(`change:${characteristic}`,(event)=>{//Create a listener for when our base attributes change.
getAttrs([event.sourceAttribute],(attributes)=>{//Get the value of the attributes. I avoid using the `newValue` property of the event object because it is fragile and not dependable.
const setObj = {};//Create an object that will accumlate our changes
const characteristicValue = +attributes[characteristic] || 0;//Convert the attribute value to a number. We need to do this because the values stored in the Roll20 database are usually stored as strings regardless of the type of input.
//Next we'll calculate the values of each die type.
setObj[`${characteristic}_die`] = Math.floor(characteristicValue/2);
setObj[`${characteristic}_die_explode`] = Math.ceil(characteristicValue/2);
//Then we'll create the dice display
['die','die_explode']//The two types of dice
.forEach((suffix)=>{//Iterate through each die type
setObj[`${characteristic}_${suffix}_display`] = _.range(setObj[`${characteristic}_${suffix}`])//Create an array with a length equal to the dieValue, the values of each item in the array will be the index of that item.
.map(()=>'F')//For each item in the array, return the capital letter F.
.join('')//Join the letters into a cohesive string
.replace(/^$/,' ');//If the created string would be an empty string, set it to a string with a single space.
});
//We've now got several items stored in our setObj. Given a new force value of 11, our setObj will look something like:
/*
{
force_die:5,
force_die_explode:6,
force_die_display:"FFFFF",
force_die_explode_display:"FFFFFF"
}
*/
//Each of these attributes will be set on the sheet.
setAttrs(setObj,{silent:true});//Set the attribute value
});
});
});
</script> That gives us the following: Hope that helps, Scott