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

Getting the repeating session number in the roll template

1615519888

Edited 1615531825
Marco M.
KS Backer
Sheet Author
API Scripter
Compendium Curator
I have a script that is supposed to get the information from a roll, and modify the character sheet accordingly For normal sections it's pretty easy. I have structured the rolltemplate such that one of the input is the character_id and the other is the name of the attribute to change. However I am not sure how to do it for a repeating sections. The code works really well when a normal session is used, but for repeating sections, I need a way to pass either the number of the repeating section (so I can use $N) or the unique ID. To give you an idea. This is how the call to the rolltemplate in the sheet button looks like value="@{gm_toggle} &{template:rolls} {{characterid=@{character_id}}} {{attribute=nameattribute}}" And this is what the code is supposed to do  on('chat:message',(msg)=>{ let msgCopy = _.clone(msg), rollResult,rollRating,attributeToSet,characterID; const rolltype=/rolls/; // name of the template I'm interested in const rollskill=/{{characterid=/; // only the rolls I'm interested in have the characther_id information const patternMatch = /{{characterid=(.+?)}} {{attribute=(.+?)}}/ // this is the regExp to extract the information I need if(rolltype.test(msg.rolltemplate) && rollskill.test(msg.content)){ rollRating=msg.inlinerolls[1].results.total; // the second roll is the total rating rollResult=msg.inlinerolls[2].results.total; // the third roll is the result if (rollResult>rollRating){ // I'm only interested in log('checkmark'); msg.content.replace(patternMatch,(match,cID,attributeToChange)=>{ characterID=cID; attributeToSet=attributeToChange; log(characterID); log(attributeToSet);                  // find the object I need...                  let obj=findObjs({characerid:characterID,name:attributeToSet},{caseInsensitive:true});                  obj.setWithWorker({current:1}); // set the value to 1 on a failure (it's zero if you never failed) }); } } }); EDIT:   I'm thinking more about the problem, one option would probably be to add an hidden value called "fullname" that is populated on ready or on the creation of a new repeating section with the text "repeating_skill_ID_valueIwant". I would prefer to pass something like unique name of the button itself, but if there is no simpler way, I think that could be a workaround
1615557751
timmaugh
Pro
API Scripter
Repeating items can be difficult, especially within the constraint of having to deliver a piece of info to a predetermined structure like a roll template. If you want to do it in your code, I talked about retrieving repeating items in a couple of posts that might be of help: <a href="https://app.roll20.net/forum/post/9575741/getting-and-changing-repeating-attributes-in-a-fieldset/?pageforid=9576123#post-9576123" rel="nofollow">https://app.roll20.net/forum/post/9575741/getting-and-changing-repeating-attributes-in-a-fieldset/?pageforid=9576123#post-9576123</a> <a href="https://app.roll20.net/forum/permalink/9069028/" rel="nofollow">https://app.roll20.net/forum/permalink/9069028/</a> That said, APILogic has an update pending that should bring an immediate handle to get the information you're after. The idea is that just as you would use @{character|attribute_name} to get an attribute, you could use a structure like @|character|attribute_name, which would get the attribute if it's there and provide a "soft" value if not (maybe an empty string, maybe a 0, etc.). The repeating element retrieval would let you do pattern matching for pieces of information out of the set: *|Character|listname|[name_attr = "Splash of Mojo" prepared]|retreive_attr ...and would allow you to retrieve the value of that "retrieve_attr", the name of that "retrieve_attr" (i.e., "repeating_skill_-M1234567890abcdef_retrieve_attr"), the short name, (ie, "repeating_skill_$0_retrieve_attr"), or just the row id (ie, "$0"). With APILogic installed, that would be like another native structure to the Roll20 chat, and an easy way to locate a piece of sheet data you needed. The update is very nearly ready. I just have to run some testing either later today or this weekend. But, like I said, if you want to do it yourself in your code, we can help with that to. Check out the links above and post back with any questions!
1615558556
timmaugh
Pro
API Scripter
One other thing, if you are going to code the retrieval yourself (and not wait for APILogic), and what you need is specifically the rowID (the $0, $1, etc.), you can translate that from the set of full names using this function: &nbsp; &nbsp; const repeatingOrdinal = (character_id, section = '', attr_name = '') =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; if (!section &amp;&amp; !attr_name) return; &nbsp; &nbsp; &nbsp; &nbsp; let ordrx, match; &nbsp; &nbsp; &nbsp; &nbsp; if (attr_name) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ordrx = /^repeating_([^_]+)_([^_]+)_.*$/; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!ordrx.test(attr_name)) return; // the supplied attribute name isn't a repeating attribute at all &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; match = ordrx.exec(attr_name); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; section = match[1]; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; let sectionrx = new RegExp(`repeating_${section}_([^_]+)_.*$`); &nbsp; &nbsp; &nbsp; &nbsp; let createOrderKeys = [...new Set(findObjs({ type: 'attribute', characterid: character_id }) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .filter(a =&gt; sectionrx.test(a.get('name'))) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .map(a =&gt; sectionrx.exec(a.get('name'))[1]))]; &nbsp; &nbsp; &nbsp; &nbsp; let sortOrderKeys = (findObjs({ type: 'attribute', characterid: character_id, name: `_reporder_repeating_${section}` })[0] || { get: () =&gt; { return ''; } }) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .get('current') &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .split(/\s*,\s*/) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .filter(a =&gt; createOrderKeys.includes(a)); &nbsp; &nbsp; &nbsp; &nbsp; sortOrderKeys.push(...createOrderKeys.filter(a =&gt; !sortOrderKeys.includes(a))); &nbsp; &nbsp; &nbsp; &nbsp; return attr_name ? sortOrderKeys.indexOf(match[2]) : sortOrderKeys; &nbsp; &nbsp; }; That was originally some of Aaron's code which I modified to use modern/native js (he'd written it before some of the ES7 structures were available), and to account for a weird issue in character sheets were you get corrupted (or "ghost") rows... where your "Magic Missile" entry might exist 3 times in the list even though only 1 shows on the character sheet. (If you've never seen that, you can install my InsertArg script and use XRay. I haven't updated that script to use the fixed version of the function, above, so it will show you all of the ghost rows on a sheet that has this sort of issue/corruption.) Anyway, using the above function should give you the rowiD if you pass in a single attribute, or if you don't supply a single attribute it should give you the elements in the repeating section properly ordered to how they appear on the character sheet (accounting for user relocation, etc.).
1615572959
Marco M.
KS Backer
Sheet Author
API Scripter
Compendium Curator
Oooh wow, that's an elegant way... I went the poor man route for the moment (I want the parameter to be there in the sheet, and to be retrieved in the API). So basically on ready and on the creation of a new repeating section I have update["repeating_skills_"+id+"_fullname"]=String(id); So it's always there hidden and waiting in the roll template in an unused parameter that's passed in the msg. Thanks so much from the advise. I'm going to include the repeatingOrdinal cause it's easier and I'm sure less prone to bugs :)