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 .
×

Sheetworker - another noob trying to fix his code...

1602309838

Edited 1602309882
Hi there, I'm trying to use sheetworkers, and failing to understand why it is not working. I'm an absolute noob in javascript, and my programming  skills are ... rusted. Please help ? I'm creating a mini D6 game, and want to have a specific character sheet for it. To manage stats, I'm using a single stat value, stored in a hidden input, that I convert on the sheet to a "xD + y" readout using readonly inputs. That does not work at the moment : const attribs = ['vig','agi','coord','esp','per','aura']; attribs.forEach(function (attrib)  {                                        // pour tous les attributs     on('change:' + attrib + ' sheet:opened', function () {                  // à l'ouverture et sur une modif de l'attribut, recalcule les dés et pips         getAttrs([attrib], function (values) {             var update {};             const attrib_score = parseInt(values[attrib], 10)||0;           // extrait la valeur de l'attribut, en décimal             update[attrib + 'dice'] = Math.floor(attrib_score/3);             update[attrib + 'pip'] = attrib_score % 3;             setAttrs(update);         });     }); });    I expect this to get attr_vig value, and set attr_vigdice and attr_vigpip correspondingly. And so on for all the attributes in attribs array. Note : I suspect there is something wrong with my use of the "update" var. the problem may also be on the html side, if there is nothing wrong with this code. I'm stuck.
1602310074
GiGs
Pro
Sheet Author
API Scripter
your var update line is missing the = sign: var update = {};
1602310337

Edited 1602313362
dammit... thanks GiG ! I'm now gone to hid in a damp place. :)
1602310614
GiGs
Pro
Sheet Author
API Scripter
hehe, those silly syntax errors catch us all at some point. 
1602352883

Edited 1602353763
Okay, I went headfirst into another hurdle : Here I am trying to update calculated values inside a repeating section. And I'm stuck. again. I will try to explain my problem as clearly as I can. Each PC has 6 characteristics, and Aura is an exemple of one, described in html part like this : <input type="hidden" name="attr_aura" value="3"/> <!-- hidden --> <button type="action" name="act_incaura" class="incdec">+</button> <button type="action" name="act_decaura" class="incdec">-</button> <input type="number" name="attr_auradice" class="nonumber" readonly="True"/>D+ <input type="number" name="attr_aurapip" class="nonumber" readonly="True"/> Aura governs 5 skills, described in html with the same logic, here Bluff which I coded as "blu" : <input type="hidden" name="attr_blu" value="0"/> <!-- hidden --> <button type="action" name="act_incblu" class="incdec">+</button> <button type="action" name="act_decblu" class="incdec">-</button> <input type="number" name="attr_bludice" class="nonumber shortnumber" readonly="true" />D+ <input type="number" name="attr_blupip" class="nonumber shortnumber" readonly="true" /> Each Aura skill may have a specialization, which are handled by a repeating section at the bottom of the characteristics box. I placed specialisations for all skills concerning a characteristic in the same repeating section in order to improve lisibility of the sheet. That makes my life miserable when trying now to code. Here the corresponding html part for aura : <Span> Spécialisations : </span> <fieldset class="repeating_auraspecs"> <!-- Skills Aura --> <!-- Rolls here --> <select class="skilltext" name="attr_auraspectype" style="width:80px;"> <option value="blu" selected="selected">Bluff</option> <option value="cmd">Commander</option> <option value="crg">Courage</option> <option value="degu">Déguisement</option> <option value="pss">Persuasion</option> <option value="sed">Séduction</option> </select> <input type="text" name="attr_auraspecname" class="skilltext"/> <div class="right"> <input type="hidden" name="attr_auraspec" value="0"/> <!-- hidden --> <button type="action" name="act_incauraspec" class="incdec">+</button> <button type="action" name="act_decauraspec" class="incdec">-</button> <input type="number" name="attr_auraspecdice" class="nonumber shortnumber" readonly="true" />D+ <input type="number" name="attr_auraspecpip" class="nonumber shortnumber" readonly="true" /> </div> </fieldset> As you can see, I added a <select> to hold the codename of the corresponding skill, with the intent to use it in my code. for script purposes, I created an array to upgrade the attribute with a unique loop : const auraskills = ['blu','cmd','crg','degu','pss','sed']; here is the loop : auraskills.forEach(function (auraskill)  {                                                    // For each skill based on Aura     on('change:aura change:' + auraskill + ' change:repeating_auraspecs remove:repeating_auraspecs sheet:opened', function () {             getSectionIDs('repeating_auraspecs', function (idarray) {             const specs = [];             const spectypes = [];             for (let i = 0; i < idarray.length; i++) {                 specs.push('repeating_auraspecs_' + idarray[i] + '_auraspec');             // met les valeurs des repeating specs existants dans le champ des stats à récupérer                 spectypes.push('repeating_auraspecs_' + idarray[i] + '_auraspectype');     // met les valeur du skill de base des repeating skills existants dans le champ des stats à récupérer             }             getAttrs(['aura', auraskill, specs, spectypes], function (values) {                 var update = {};                 const aura_score = parseInt(values.aura, 10)||0;                          // extrait la valeur de l'aura, en décimal                 const auraskill_score = parseInt(values[auraskill], 10)||0;                // extrait la valeur de l'auraskill, en décimal                 update[auraskill + 'dice'] = Math.floor((aura_score + auraskill_score)/3);                 update[auraskill + 'pip'] = (aura_score + auraskill_score) % 3;                 for (let i=0; i < idarray.length; i++) {                     const spec_score = parseInt(values[specs[i]], 10)||0;                  // extrait la valeur de la repspec, en décimal                     const spec_type = values[spectypes[i]]                                 // extrait le type de la repsk                     if (spec_type == auraskill) {                                          // si le type du repeating_auraspecs == auraskill il faut mettre à jour                         update[specs[i] + 'dice'] = Math.floor((aura_score + auraskill_score + respspec_score)/3);                         update[specs[i] + 'pip'] = (aura_score + auraskill_score + respspec_score) % 3;                     }                 }                 setAttrs(update);                                                          // affecte les nouvelles valeurs             }         });     }); });     ... and it doesnt work since I tried to handle the repeating sections. It was working before, for Aura and Auraskills updates. What did I have done wrong ? Thx for any help.
1602353567
GiGs
Pro
Sheet Author
API Scripter
I havent looked over the code to examine it, just plugged it into a syntax chacker, and the getAttrs block isnt closed properly. The end of your code is                 setAttrs(update);                                                          // affecte les nouvelles valeurs             }         });     }); });     and it should be                 setAttrs(update);                                                          // affecte les nouvelles valeurs              });         });     }); });    
1602353807

Edited 1602354205
GiGs
Pro
Sheet Author
API Scripter
Now that I'm actually looking at your code I see another issue:             getAttrs(['aura', auraskill, specs, spectypes], function (values) { In this line, specs and spectypes are each arrays. So this line wont work as expected. You would end up with something lke [ 'aura' ,  auraskill , [attr1, attr2], [attr3, attr4] ] Basically arrays nested inside an array, and getAttrs either breaks or ignores them. You can fix this with the spread operator (...). This expands the array into its parts, so try this:             getAttrs ([ 'aura' ,  auraskill , ... specs , ... spectypes ],  function  ( values ) { Anther issue - this line: const spec_score = parseInt(values[specs[i]], 10)||0;                  // extrait la valeur de la repspec, en décimal This defines a spec_score variable, but spec_score isnt used. There is a  respspec_score , that isnt defined. That will cause the sheet worker to crash.
Well, caught again. I'll test it immediately. I need to find a good syntax checker. Actually using notepad++ ...
1602354509
GiGs
Pro
Sheet Author
API Scripter
Note: i updated my previous post. I use visual studio code for syntax checking, by creating a file named working.js, saving it, and copying the sheet workers into it. Sublime Text 3 is probably better if you are just looking for a syntax checker.
1602354655

Edited 1602354936
Thanks Gig for the spread operator info. That did the trick. There was another mistake caused by a const name change that I forgot to check, but it works fine now. Big Thanks for your help, and for your input on these forums. I learned a lot from the examples given here and on the wiki. Edit : for those interested, here is the final script, corrected : auraskills.forEach(function (auraskill) { on('change:aura change:' + auraskill + ' change:repeating_auraskills remove:repeating_auraskills sheet:opened', function () { getSectionIDs('repeating_auraspecs', function (idarray) { const specs = []; const spectypes = []; for (let i = 0; i < idarray.length; i++) { specs.push('repeating_auraspecs_' + idarray[i] + '_auraspec'); // met les valeurs des repeating skills existants dans le champ des stats à récupérer spectypes.push('repeating_auraspecs_' + idarray[i] + '_auraspectype'); // met les valeur du skill de base des repeating skills existants dans le champ des stats à récupérer } getAttrs(['aura', auraskill, ...specs, ...spectypes], function (values) { var update = {}; const aura_score = parseInt(values.aura, 10)||0; // extrait la valeur de l'aura, en décimal const auraskill_score = parseInt(values[auraskill], 10)||0; // extrait la valeur de l'auraskill, en décimal update[auraskill + 'dice'] = Math.floor((aura_score + auraskill_score)/3); update[auraskill + 'pip'] = (aura_score + auraskill_score) % 3; for (let i=0; i < idarray.length; i++) { const spec_score = parseInt(values[specs[i]], 10)||0; // extrait la valeur de la repskill, en décimal const spec_type = values[spectypes[i]] // extrait le type de la repskill, en décimal // si le type du repeating_auraskills == auraskill il faut mettre à jour if (spec_type == auraskill) { update[specs[i] + 'dice'] = Math.floor((aura_score + auraskill_score + spec_score)/3); update[specs[i] + 'pip'] = (aura_score + auraskill_score + spec_score) % 3; } } setAttrs(update); // affecte les nouvelles valeurs }); }); }); });
1602356306

Edited 1602360073
GiGs
Pro
Sheet Author
API Scripter
You mentioned having 6 stats, each of which would need a worker like this. Here's a way to create all 6, without needing to write them all out. After the code, I'll explain how to adjust it for you need. const   stats  = {      aura :  [ 'blu' , 'cmd' , 'crg' , 'degu' , 'pss' , 'sed' ], }; Object . keys ( stats ). forEach ( stat   =>  {   // convert the stats into an array, and loop through them      const   skills  =  stats [ stat ];  // get the array of stats inside each master stat      skills . forEach ( skill   =>  {          on ( 'change:'  +  stat  +  ' change:'  +  skill  +  ' change:repeating_'  +  skill  +  '_specs   remove:repeating_'  +  skill  +  'specs sheet:opened' ,  function  () {                   getSectionIDs ( 'repeating_'  +  skill  +  'specs' ,  function  ( idarray ) {                  const   specs  = [];                  const   spectypes  = [];                  for  ( let   i  =  0 ;  i  <  idarray . length ;  i ++) {                      specs . push ( 'repeating_'  +  skill  +  'specs_'  +  idarray [ i ] +  '_'  +  skill  +  'spec' );              // met les valeurs des repeating specs existants dans le champ des stats à récupérer                      spectypes . push ( 'repeating_'  +  skill  +  'specs_'  +  idarray [ i ] +  '_'  +  skill  +  'spectype' );      // met les valeur du stat de base des repeating skills existants dans le champ des stats à récupérer                 }                  getAttrs ([ stat ,  skill , ... specs , ... spectypes ],  function  ( values ) {                      var   update  = {};                      const   skill_score  =  parseInt ( values [ stat ],  10 )|| 0 ;                            // extrait la valeur de l'aura, en décimal                      const   subskill_score  =  parseInt ( values [ skill ],  10 )|| 0 ;                 // extrait la valeur de l'skill, en décimal                      update [ skill  +  'dice' ] =  Math . floor (( skill_score  +  subskill_score )/ 3 );                      update [ skill  +  'pip' ] = ( skill_score  +  subskill_score ) %  3 ;                      for  ( let   i = 0 ;  i  <  idarray . length ;  i ++) {                          const   spec_score  =  parseInt ( values [ specs [ i ]],  10 )|| 0 ;                   // extrait la valeur de la repspec, en décimal                          const   spec_type  =  values [ spectypes [ i ]];                                  // extrait le type de la repsk                          if  ( spec_type  ==  skill ) {                                           // si le type du repeating_auraspecs == skill il faut mettre à jour                              update [ specs [ i ] +  'dice' ] =  Math . floor (( skill_score  +  subskill_score  +  spec_score )/ 3 );                              update [ specs [ i ] +  'pip' ] = ( skill_score  +  subskill_score  +  spec_score ) %  3 ;                         }                     }                      setAttrs ( update );                                                           // affecte les nouvelles valeurs                 });             });         });     }); }); To make it work for you, first try it out as is (after removing the original worker - very important !). It should work for your aura skills. Once youre sure its working okay (I havent tested it!), you just need to edit this bit: const stats = {     aura: ['blu','cmd','crg','degu','pss','sed'], }; Just add another line with a label for your stat name, and an array of the skills based on it, and a comma at the end. These (the stat name and skill names) must be exactly as used in your attribute names (and repeating section name for the stat). So if you have a stat named chill , its repeating section should be called repeating_chillspecs with attributes chillspec and chillspectype .  Everything must be named in the correct format, but if so, this should handle all 6 stats.
Wow ! that is the step i was currently trying to do... I do not know what to say, except thanks ! And uhhh, is the spread operator no longer necessary in the getAttrs line ?
1602360103
GiGs
Pro
Sheet Author
API Scripter
Kordolius said: And uhhh, is the spread operator no longer necessary in the getAttrs line ? Well spotted - it is still needed, I just forgot to update the code :)
Working on it, but I have to modifiy some part of code, I was already using a stats const. Keeping you informed in a few moments.
1602361073
GiGs
Pro
Sheet Author
API Scripter
just pick a different name and do a search/replace on stats in my code, before you paste it into your html.
1602361322

Edited 1602361475
Yeah ! it works ! All the calculated values are updated, for all stats. Really great ! I now have to rework my action button handling with your method to be operational ! I will try to do it on my own in order to learn what you just showed me. Thanks ! One thing i'm not familiar with (yet) is the => notation, but that is the opportunity to learn it. Thanks again GiGs ! :)
1602361612
GiGs
Pro
Sheet Author
API Scripter
oh yeah, I tried to limit myself to the same methods you were using, but that slipped in by habit. For googling purpose, thats called an "arrow function" or fat arrow syntax.
1602362103
GiGs
Pro
Sheet Author
API Scripter
One other feature I'd recommend investigation is template literals . Using them owuld change this line  specs.push('repeating_' + skill + 'specs_' + idarray[i] + '_' + skill + 'spec');      to  specs.push(`repeating_${skill}specs_${idarray[i]}_${skill}spec`);      Its a way to build strings. You put the template inside backticks ` ` (these are not single quotes or double quotes; on the UK keyboard they appear on the top row to the left of the 1).  Then instead of breaking up the string when you want to enter variables or code, you use ${code goes here}.  For building long strings like this, it's roughly equivalent to normal string construction, but it has a lot more power. You can put entire code blocks inside the ${ }, and even nest more ${ } inside them, so it's extremely powerful when you get ocmfortable with them. For lines like the on(change) line, it's also I think cleaner. This: on('change:' + stat + ' change:' + skill + ' change:repeating_' + skill + '_specs remove:repeating_' + skill + 'specs sheet:opened', function () {   becomes on(`change:${stat} change:${skill} change:repeating_${skill}_specs remove:repeating_${skill}specs sheet:opened`, () => {      (with a bonus arrow function at the end there). Once you get familiar with them, it's much easier to read.