Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

Creating actions and Traits

Hello there! I'm developing a script that inject some actions and traits into a NPC Sheet, and it works...sometimes I would like to know what I'm doing wrong. Sometimes it works perfectily and sometimes it doesn't The following functions are been called from a for loop, in case there is more than one action or trait that must be injected The add Trait and Action script, specifically: function add_action(action, character){     var new_action = createObj("attribute", {name: "repeating_npcaction", characterid: character.id});     AddPCAttribute(`repeating_npcaction_${new_action.id}_name`, `${action.action_name}`, character.id);     AddPCAttribute(`repeating_npcaction_${new_action.id}_description`, `${action.action_description}`, character.id);          // Checking if the actions is an attack     if(action.is_attack){         var attack_flag = AddPCAttribute(`repeating_npcaction_${new_action.id}_attack_flag`, "on", character.id);         var attack_tohit = AddPCAttribute(`repeating_npcaction_${new_action.id}_attack_tohit`,`${action.attack}`, character.id);         var attack_damage = AddPCAttribute(`repeating_npcaction_${new_action.id}_attack_damage`, `${action.hit_dice}`, character.id);         var rollbase = AddPCAttribute(`repeating_npcaction_${new_action.id}_rollbase`, "@{wtype}&{template:npcatk} {{attack=1}} @{damage_flag} @{npc_name_flag} {{rname=[@{name}](~repeating_npcaction_npc_dmg)}} {{rnamec=[@{name}](~repeating_npcaction_npc_crit)}} {{type=[^{attack-u}](~repeating_npcaction_npc_dmg)}} {{typec=[^{attack-u}](~repeating_npcaction_npc_crit)}} {{r1=[[@{d20}+(@{attack_tohit}+0)]]}} @{rtype}+(@{attack_tohit}+0)]]}} @{charname_output}", character.id);         var damage_flag = AddPCAttribute(`repeating_npcaction_${new_action.id}_damage_flag`, "{{damage=1}} {{dmg1flag=1}} ", character.id);         var attack_onhit = AddPCAttribute(`repeating_npcaction_${new_action.id}_attack_onhit`, `${action.hit_dice} damage`, character.id);         var attack_otohitrange = AddPCAttribute(`repeating_npcaction_${new_action.id}_attack_tohitrange`, `+${action.attack}`, character.id);     }     return new_action; } // Adds the traits to the sheet function add_trait(trait, characterid){     var new_trait = AddPCAttribute("repeating_npctrait", 0, characterid);     var trait_name = AddPCAttribute(`repeating_npctrait_${new_trait.id}_name`,`${trait.specialtrait_name}`, characterid);     var trait_description = AddPCAttribute(`repeating_npctrait_${new_trait.id}_description`, `${trait.specialtrait_description}`, characterid);     return new_trait; }
1663612327
The Aaron
Roll20 Production Team
API Scripter
Your attributes for the Repeating Sections are not named correctly.  You have to generate the ID and build it into the name.  You can use these functions: const generateUUID = (() => { let a = 0; let b = []; return () => { let c = (new Date()).getTime() + 0; let f = 7; let e = new Array(8); let d = c === a; a = c; for (; 0 <= f; f--) { e[f] = "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz".charAt(c % 64); c = Math.floor(c / 64); } c = e.join(""); if (d) { for (f = 11; 0 <= f && 63 === b[f]; f--) { b[f] = 0; } b[f]++; } else { for (f = 0; 12 > f; f++) { b[f] = Math.floor(64 * Math.random()); } } for (f = 0; 12 > f; f++){ c += "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz".charAt(b[f]); } return c; }; })(); const generateRowID = () => generateUUID().replace(/_/g, "Z"); For each repeating row, call generateRowID(), and use it to name the attributes: // Adds the traits to the sheet function add_trait(trait, characterid){     const newID = generateRowID();     let trait_name = AddPCAttribute(`repeating_npctrait_${newID}_name`,`${trait.specialtrait_name}`, characterid);     let trait_description = AddPCAttribute(`repeating_npctrait_${newID}_description`, `${trait.specialtrait_description}`, characterid);     return {name:trait_name, description: trait_description}; } The new_trait and new_action attributes you're creating aren't real and may cause issues when you create duplicates.  That's possibly a clever way to get an ID generated, but it can generate invalid IDs as rowIDs have a further constraint of not containing `_`, which normal IDs do not have.  A row doesn't really have a single attribute that contains all of it's fields, it is just the sum of all of its fields.  I adjusted the sample there to return the collection of created fields instead of the invalid attribute.  Hopefully that helps.  I don't work much with creating these sorts of attributes, so others may help a bit more.
I will teste that, but another question: in the foor loop does it matter to have a variable been initialized multiple times like this: if (monster_json.traits != null){                 for (const trait of monster_json.traits){                     var new_trait = add_trait(trait, Character.id);                 }             }
1663614894
The Aaron
Roll20 Production Team
API Scripter
Not explicitly.  In Javascript, the `var` declaration is hoisted and function scoped, so what you have is really: var new_trait; // possibly higher, depending on where the function starts and how deeply nested this code is. if (monster_json.traits != null){ for (const trait of monster_json.traits){ new_trait = add_trait(trait, Character.id); } } `let` and `const` are not hoisted and are block scoped, so using them to declare the variable would lead to new_trait only being defined within the scope of the for loop: if (monster_json.traits != null){ // new_trait is not defined here for (const trait of monster_json.traits){ let new_trait = add_trait(trait, Character.id); } // new_trait is not defined here. } So, it depends on what you are doing.  Using `let` or `const` are certainly considered best practice in modern Javascript.  The only place where I use `var` anymore is a single edgecase that has to do with redeclaring an existing symbol, I've otherwise completely replaced it.
Nice! I'm not new to programming, but new to JS. Still learning and now this is certainly more clear for me! Thank PS: It worked for the actions, but not for the traits. But now it is DEFINITELY more stable
1663626077
The Aaron
Roll20 Production Team
API Scripter
I'd look at what's different between the two, and verify you have all the names spelt correctly.  Worst case, you can write a little script to dump our attributes on add and change, then look at what gets added when you add a new row to traits, then use that to inform creating them yourself.