Ok. First, you'd need to know when to make/set that attribute, which means an event. It's best to wrap your scripts in the "ready" event anyway, just to create a separate namespace, but in this case it's vitally important so that your events don't run for every single character on startup as the add events are issued for all those attributes: // ready event happens after the API has loaded all the objects
on('ready',()=>{
// function to call on changed/added attributes
const checkAttribute = (obj,prev) => {
};
// register the above function to be called when an attribute is added or changed.
on('add:attribute', checkAttribute);
on('change:attribute', checkAttribute);
}); That's the bare bones of where to start, now for the actual details of the function: on('ready',()=>{
const checkAttribute = (obj,prev) => {
// obj will be the created or modified attribute object. (a Roll20 Object)
// prev will be the properties the object had before being changed. (a simple JS object)
// Roll20 objects have their properties accessed with the .get() function,
// which takes the property name as an argument
// /^size$/i is a regular expression that matches (case insensitive)
// the word "size" with no leading or trailing whitespace.
if(/^size$/i.test(obj.get('name'))){
// In here, we know we have the right object
// next we need to get or create the attribute for MIT.
// findObjs() will return an array of matching Roll20 Objects or the empty array [].
// The one we want will be the first one (index 0). If it wasn't found, this index will
// contain undefined, which is "falsy".
// || is the Javascript boolean OR, which "short circuits", meaning the second half won't
// execute if the first half was "truthy", which the Roll20 object would be.
// createObj() will then get executed if we didn't find the object, creating an attribute
// named "MIT" and returning it.
// The practical upshot being that this will find or create the MIT attribute for the character.
let mit = findObjs({type:'attribute',name:'MIT',characterid: obj.get('characterid')})[0] ||
createObj('attribute',{name:'MIT', characterid: obj.get('characterid')});
// switch() is a nice way to do things for certain values. The case that matches will then
// get executed.
// obj.get('current') will return the value in the attribute, .toLowerCase() will guarantee it
// matches if it somehow ends up capitalized differently.
switch(obj.get('current').toLowerCase()){
// if the current is "tiny", it will set mit's current to 'd4', then break out of the switch.
// Roll20 objects' properties are set with the .set() function, which comes in two forms:
// .set(property, value) -- first argument is what to change, second is what to set it to.
// .set({property: value}) -- only argument is a key/value mapping from properties to values,
// which is useful if you're changing several properties at once.
case 'tiny': mit.set('current','d4'); break;
case 'small': mit.set('current','d6'); break;
case 'medium': mit.set('current','d8'); break;
case 'large': mit.set('current','d10'); break;
case 'huge': mit.set('current','d12'); break;
case 'gargantuan': mit.set('current','d20'); break;
}
}
};
on('add:attribute', checkAttribute);
on('change:attribute', checkAttribute);
}); That should be basically it. Cleared of comments: on('ready',()=>{
const checkAttribute = (obj,prev) => {
if(/^size$/i.test(obj.get('name'))){
let mit = findObjs({type:'attribute',name:'MIT',characterid: obj.get('characterid')})[0] ||
createObj('attribute',{name:'MIT', characterid: obj.get('characterid')});
switch(obj.get('current').toLowerCase()){
case 'tiny': mit.set('current','d4'); break;
case 'small': mit.set('current','d6'); break;
case 'medium': mit.set('current','d8'); break;
case 'large': mit.set('current','d10'); break;
case 'huge': mit.set('current','d12'); break;
case 'gargantuan': mit.set('current','d20'); break;
}
}
};
on('add:attribute', checkAttribute);
on('change:attribute', checkAttribute);
}); Hope that helps! I didn't test this or anything, but it should be right?