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

[LF Help] [SheetWorkers-> Repeating Sections] Converting Older Sheet to Sheetworkers

I am updating an older style character sheet for Dark Heresy 1e so that it uses more modern character building techniques, CSE, Sheetworkers etc.  This process is proving to be slow, as I need to do so while I run a game with the same sheet.  What complicates this is my limited experience with JS and sheet workers is limited in scope to basic logic, numeric arithmetic and overall have just enough knowledge to be dangerous. I have built a sheetworkers for a d20 system character sheet years ago, but a lot of the code has changed since then.  And when trying to current sheet over I've used my old sheet as an example, however, examanining the forums I've noticed none of them seem to have similar code.  The basic code is as shown below: /* Repeating Weapons Parsing -- Both Global and Local (Excluding ROW ID OUTPUT Display) */ const calcWeaponDamage = function (prefix) { const sourceAttrs = [prefix+"_atkName"]; getAttrs(sourceAttrs, function (v) { wNameLabelText = v[prefix+'_atkName'] console.log("Name of Weapon " +wNameLabelText+ "."); setAttrs({ // [prefix+"_wepEnh"]: wepEnh, }); }); }; on('change:repeating_weapon change:ws-base change:ws-unnatural change:bs-base change:bs-unnatural change:str-base change:str-unnatural change:tou-base change:tou-unnatural change:agi-base change:agi-unnatural', function () {  // Make sure all of the attributes are properly checked, the fewer the better for efficiency for weapon rolls. getSectionIDs('repeating_weapon', function (ids) { ids.forEach(id => calcWeaponDamage('repeating_weapon_'+id)); }); }); Is this code obsolete?  Is it not correct to use anymore and is there better code to use to mesh with the new features?  My desire for coding style is to have a balance between as succinct and combat as possible and also not having over complicated weird code that only those with 20+ years of coding can decipher.  So while I want compact code I will do everything I can to avoid overcomplications ... To complicate matters I am using ScriptCards NOT rolltemplates because the nature of Dark Heresy is that the combat rolls can be highly conditional in their nature and roll template does not allow for easy conditional outputs without code that is... extensive.  Up until now I've been using the ScriptCards for extensive checking what sort of conditions are active on weapons at any given time and altering the final numbers based on that.  My goal is to take alot of the logic out of the ScriptCards and and making it the final number is sent back to the character sheet so that the scriptCards only needs to use that number.  That way token drag and drop token action buttons can be used.  (For some reason token action butttons often break when I've used ScriptCards, and when I'ved asked why... I've not gotten a full explanation.  Beyond "ScriptCards cant use AutoCalc values that include math."  Which really doesnt help me build a solution to the problem) So below is the a picture of the repeating section for the weapons on my sheet. The 0-25 buttons at the top were designed so I could create "template character sheets" and under the attributes and abilities tab of each sheet you can have weapons #0 - #n and in those have @{selected|repeating_weapon_0_wRoll} and be able to check either show as macro bar or show as token action and it will function just as well as opening the character sheet and pressing the roll button within the repeating section which is a pain in the neck as a GM running larger encounters.  Unfortunately, it doesnt really work with ScriptCards EXCEPT on the Custom Sandbox, it works 99% of the time on the sandbox. Anyways, its my hope that doing the repeating sections with sheet workers will fix that problem. I want to thank you all in advance for the questions I'm going to ask here.  For those who might want a copy of this character sheet's code I'd be happy to share with other Dark Heresy players.  Especially, the person who maintains the Dark Heresy 1e character sheet, Accession sheet, Rogue Trader sheet and Deathwatch Sheet.  As this is being designed to be compatible with all such..
1683506653

Edited 1683518707
GiGs
Pro
Sheet Author
API Scripter
I'm not going to answer the script-related question, just the sheet worker. Your code can't be that old, because it uses const, which is a (relatively) new feature of JS. No, the code isn't obsolete. If you want the more modern syntax, you'd just change any use of function(something) as follows. From this: const calcWeaponDamage = function (prefix) { to this: const calcWeaponDamage = (prefix) => { Everything else is the same. This is called the Fat Arrow syntax. But the first version is likely to more familiar to most roll20 coders. It's fine. You might want to look into Custom Roll Parsing as an alternative to ScriptCards - it can likely do the stuff you use scriptcards for, but you will need to build a rolltemplate. Also, can you say what specifically isn't working - where are you having a problem?
1683514525
GiGs
Pro
Sheet Author
API Scripter
Personally, I'd redesign your sheet worker to avoid the function call and use getSectionIds and an internal loop. But looking at your code again I notice two serious syntax errors that would break the code. Assuming the uncommented code looks like this: setAttrs({ [prefix+"_wepEnh"]: wepEnh, }); The wepEnh variable isn't listed anywhere else in your code, so that will cause a crash. In addition, the line ends with a comma, and that will also cause a crash. You can only use a comma there if there are more than one items inside setAttrs - and the last one never has a comma.
1683515673

Edited 1683518870
GiGs
Pro
Sheet Author
API Scripter
I trimmed my first response. See my next post for comments on the way your function is built. This is how I'd build your function instead. There are a couple of things about it I'll describe after the code.     // function to construct the name of a repeating section attribute     const section_name = ( section , id , field ) => `repeating_ ${ section } _ ${ id } _ ${ field } ` ;     on ( 'change:repeating_weapon change:ws-base change:ws-unnatural change:bs-base change:bs-unnatural change:str-base change:str-unnatural change:tou-base change:tou-unnatural change:agi-base change:agi-unnatural' , () => {   // Make sure all of the attributes are properly checked, the fewer the better for efficiency for weapon rolls.         getSectionIDs ( 'repeating_weapon' , ( ids ) => {             // build an array of field names.             const fields = ids . reduce (( all , id ) => [ ... all , section_name ( 'weapon' , id , 'atkName' )], []);             getAttrs ( fields , v => {                 // create an object variable to hold multiple attribute names and their values                 const output = {};                 // loop through the fields array, which contains all te attribute names.                 fields . forEach ( field => {                     wNameLabelText = v [ field ];                     console . log ( `Name of Weapon ${ wNameLabelText } .` );                     // you might want to transfer something else to this attribute - this is just a proof of concept.                     output [ section_name ( 'weapon' , id , 'wepEnh' )] = wNameLabelText ;                 });                 setAttrs ( output );             });         });     }); The section_name function at the start is handy to have just once at the start of your scriptblock. You can use it any sheet worker to get a repeating section attribute name. Notice the way the string is constructioned, using ` ${} ` - this is called a template literal , and is a newish alternative to doing things like prefix+'_atkName' . When you have complex strings, it is a lot clearer IMO. Then, The line just before getAttrs contains a reduce function. These are complex, and you don't want complicated, so here's an alternative that does the same thing: const fields = []; ids . forEach ( id => fields . push ( section_name ( 'weapon' , id , 'atkName' ))); This first creates an empty array [], then loops through the repeating section array ids , and constructs an attribute name and pushes that to the fields array. Then getAttrs uses that array to grab attributes from the whole sheet. It grabs all the repeating section attributes at once. Then we loop through the fields array which contains all of the attributes, and save an attibte to output. That is used by setAttrs. Final comment: your event line is really long, making me think something else is going on in that worker, but I can't begin to guess what.
1683516530

Edited 1683518987
GiGs
Pro
Sheet Author
API Scripter
I should have stated this earlier. There was never a time when the code you are using was a good approach. The reason: You should never have a loop that includes getAttrs and setAttrs when there are alternative approaches. getAttrs and setAttrs are slow functions, each use of them requires a call across the internet to Roll20's servers, where you are put into a queue and your code has to wait till a response is recieved. Consider that there might be thousands or even hundreds of thousands of people playing games, whose character sheets might be querying roll20's servers. When you have a loop inside getSectionIDs, you are calling that function once for every row in the repeating section. But getAttrs and setAttrs can contain multiple attributes - so you can simplify that to just one call no matter how many rows the fieldset contains. A fieldset with 100 rows runs just as fast as a fieldset with 1 row. (It's a little bit slower, but much, much faster than 100 separate calls.) You have always been able to built workers like this. The many sheets on roll20 that have getAttrs and setAttrs inside loops, like your function call, are just written inefficiently.
I've spent about an hour trying to write a response to these, and I've determined I cant.  That code, as efficient as it might be, just makes no sense to me.  Lots of extra code that seems to go nowhere.  What I am going to do is have all the sourceAttributes assigned to a variable so I dont need to use the full.... /sourceAttr/ when manipulating things, or doing arithmetic or logic.  I am not a programmer.  I learn from example code that I can copy/paste stitch together.  And in order to do that I need to be able to understand what I'm looking at. Your reply to my post about 1 on 1 help, and your sheet workers guide was/is helpful as far as it goes.  Although, I really do struggle with the code at points. To also give you a better idea of where I'm at now with my character sheet my new code is : /* Repeating Weapons Parsing -- Both Global and Local (Excluding ROW ID OUTPUT Display) */ const calcWeaponDamage = function (prefix) { const sourceAttrs = [prefix+"_atkName", prefix+"_notes", prefix+"_relod", // strings prefix+"_wProficiency", prefix+"_wClass", prefix+"_wType", prefix+"_wCraftsmanship", prefix+"_wAvailability", // dropdowns prefix+"_q-accurate", prefix+"_q-balanced",   prefix+"_q-defensive",  prefix+"_q-flame",       prefix+"_q-flexible", // toggles prefix+"_q-hotshot", prefix+"_q-inaccurate", prefix+"_q-overheats",  prefix+"_q-power_field", prefix+"_q-primitive", // toggles prefix+"_q-recharge",    prefix+"_q-reliable",   prefix+"_q-sanctified", prefix+"_q-scatter",     prefix+"_q-shocking", // toggles prefix+"_q-smoke", prefix+"_q-snare",      prefix+"_q-storm", prefix+"_q-tearing",     prefix+"_q-toxic", // toggles prefix+"_q-unbalanced",  prefix+"_q-unreliable", prefix+"_q-unstable", prefix+"_q-unwieldy", // toggles prefix+"_damage",        prefix+"_damageMod",    prefix+"_penetration",  prefix+"_range-n", // numbers prefix+"_RoF1",          prefix+"_RoF2",         prefix+"_RoF3",      prefix+"_clip",          prefix+"_clip_max", // numbers prefix+"_weight", prefix+"_carried" // Checkbox ]; getAttrs(sourceAttrs, function (v) { var wNameLabelText = v[prefix+'_atkName']; var wClip = v[prefix+"_clip"], wClipMax = v[prefix+"_clip_max"]; console.log("Name of Weapon " +wNameLabelText+ "."); console.log("clip: " +wClip+ "/" +wClipMax+ "."); var isAccurate = v[prefix+'_q-accurate'] || 0, isBalanced   = v[prefix+'_q-balanced'] || 0, isBlast   = v[prefix+'_q-blast'] || 0, isDefensive  = v[prefix+'_q-defensive'] || 0, isFlame      = v[prefix+'_q-flame'] || 0, isFlexible = v[prefix+'_q-flexible'] || 0, isHotshot  = 0, isInaccurate = 0, isOverheats = 0, isPower      = 0, isPrimitive  = 0, isRecharge = 0, isReliable = 0, isSanctified = 0, isScatter   = 0, isShocking   = 0, isSmoke      = 0, isSnare    = 0, isStorm    = 0, isTearing    = 0, isToxic     = 0, isUnbalanced = 0, isUnreliable = 0, isUnstable = 0, isUnwieldy = 0; console.log("isAccurate: " +isAccurate+ " isBalanced: " +isBalanced+ " isBlast: " +isBlast+ " isDefensive: " +isDefensive+ " isFlame: " +isFlame+ " isFlexible: " +isFlexible+ "."); console.log("isHotshot: " +isHotshot+ " isInaccurate: " +isInaccurate+ "isOverheats: " +isOverheats+ " isPower: " +isPower+ " isPrimitive: " +isPrimitive+ " isRecharge: " +isRecharge+ "."); var wIsCarried = v[prefix + '_carried']; console.log("Is carried: " + wIsCarried); //if (v[prefix+"_fail-target"] >= 2) {showFail = 1;} else {showAtk = 0;} setAttrs({ // [prefix+"_wepEnh"]: wepEnh }); }); }; on('change:repeating_weapon change:ws-base change:ws-unnatural change:bs-base change:bs-unnatural change:str-base change:str-unnatural change:tou-base change:tou-unnatural change:agi-base change:agi-unnatural', function () {  // Make sure all of the attributes are properly checked, the fewer the better for efficiency for weapon rolls. getSectionIDs('repeating_weapon', function (ids) { ids.forEach(id => calcWeaponDamage('repeating_weapon_'+id)); }); }); Yes, it probably is overwrought, and inefficient.  But, once the framework is built (which is what I spent today doing).  I can create on/off checkbox button toggles for weapon special abilities, I can do the logic for switching between the different types of damage and how damage is calculated bases on those specials, I can have the arithmetic for weapon range, and calculate how much size a token takes up based on the creature size to subtract that from the range selected -> targeted tokens to add in bonuses to hit based on range. Now, some of the things that your code can probably do that mine can't... special console.log() grouping so that it only displays changes detected in a single row of a repeating section... I'd KILL to have that instead of all rows having their output sent.  Your code can probably create the crit tables using arrays based on how much damage is dealt below zero. And your code could probably create dynamic code to force those buttons at the top of the weapons section to function as intended.  Again I'd KILL to have that, it would literally save me HOURS of game prep. Anyways, I'd like to thank you once again for tolerating my amateurness.  And also understanding that while it may 'sound' like I'm abrupt or short in text.  Its more that I have a hard time explaining what it is I mean, and that I like to be brutally honest..
1683529923

Edited 1683531245
GiGs
Pro
Sheet Author
API Scripter
I don't care for brutal honesty (usually, the brutal part is unneccessary), but I totally relate to having issues explaining what I mean and sounding abrupt in text, so don't worry about that. I'm about to go to bed and I'll have another look tomorrow, but one thing I can say is if you are loading more attributes into the fields variable, my code won't work as is. It can be tweaked to make it work, but that will have to wait tomorrow. The problem is in this part: fields.forEach(field => { which would need to be altered to ids.forEach(id => { And the code inside the loop modified as needed. Basically you loop through the repeating section ids again, and rebuild whatever attributes you need. They are all in the getattrs v object, but you need to extract them individually. I'll have a look at your post tomorrow. I'll need to know what you code is meant to do though. At present your setAttrs is commented out, so I can't tell what the worker actually meant to do. Can you describe in normal english, without mentioning any sheet worker code? I don't play any of the systems you mentioned, but I'm familiar with WFRP1e if it helps.
1683563552
GiGs
Pro
Sheet Author
API Scripter
If the code doesnt make sense to you. ask about bits you don't understand, and we'll demistify it, one confusing bit after another. I can't read you mind (yet), so you'll have to explain what you don't understand. Also, I still need to know what your code is meant to do.
Alright so I'm just realising something the image I posted above is only showing the melee output.  A small thing, but perhaps important.  As for the WHFRP1e.  Funny you should mention that game.  This sheet is for WHDH1e Dark Heresy 1e.  Which is warhammer 40k, the core rules were pretty much cloned from the WHFRP 1e, at least thats what I've been told. I just woke up not so long ago and I'll need some time to write out what I'm looking for.  I'm sorry I couldnt have this ready previously.  My sleep is kinda all sorts of messed up working on something of a time crunch.  I should have what I'm wanting from the repeating section sheet workers to do by tomorrow evening. Again sorry for the delay, I just wanted to let you know so you werent waiting.
1683569922

Edited 1683586686
GiGs
Pro
Sheet Author
API Scripter
Take your time, I just wanted to be sure you were still there :) By the way, when I mentioned code could be inefficient, I wasnt saying, "it would be nice if this was neater," i was saying, "if this isn't set up correctly, the sheet will lag, and it will sometimes be so bad it will drive people away from using the sheet." At the moment you have a bunch of what look like global attributes on the event line (the changes line), but they aren't used in the worker itself. That is a source of potential lag that should be removed - if those attributes arent used in the finished worker. In that case, your first line would look more like this: on('change:repeating_weapon', function () {  It maybe be that those attributes are used, in which case you probably wouldn't want to make this change. But as the code stands now, it should be done. PS: about the worker I posted: when you grasp it, you will be shocked at how easy it is to adapt you worker to that method. It is really easy , once you make a small adjustment in the way you look at things.
1683584111

Edited 1683585243
GiGs
Pro
Sheet Author
API Scripter
Here's your last big function converted into a single worker, with commentary explaining it.     // we satart with an event line as before, but instead of running a separate function, everything will be in the body of this woeker. const section_name = ( section , id , field ) => `repeating_ ${ section } _ ${ id } _ ${ field } ` ; on ( 'change:repeating_weapon change:ws-base change:ws-unnatural change:bs-base change:bs-unnatural change:str-base change:str-unnatural change:tou-base change:tou-unnatural change:agi-base change:agi-unnatural' , function () {     // then we convert your sourceattributes to a format we can use     const sourceAttrs = [ "atkName" , "notes" , "relod" ,                                                   // strings     "wProficiency" , "wClass" , "wType" , "wCraftsmanship" , "wAvailability" ,               // dropdowns         "q-accurate" ,   "q-balanced" ,   "q-defensive" ,   "q-flame" ,       "q-flexible" ,       // toggles         "q-hotshot" ,     "q-inaccurate" , "q-overheats" ,   "q-power_field" , "q-primitive" , // toggles         "q-recharge" ,     "q-reliable" ,   "q-sanctified" , "q-scatter" ,     "q-shocking" ,     // toggles         "q-smoke" ,       "q-snare" ,       "q-storm" ,   "q-tearing" ,     "q-toxic" ,     // toggles         "q-unbalanced" ,   "q-unreliable" , "q-unstable" ,   "q-unwieldy" ,                               // toggles         "damage" ,         "damageMod" ,     "penetration" ,   "range-n" ,                                 // numbers         "RoF1" ,           "RoF2" ,         "RoF3" ,         "clip" ,           "clip_max" ,       // numbers         "weight" ,         "carried"       // Checkbox             ];         // Then we combine that with the getSectionIDs function to build a fields attribute for every row in the repeating section     getSectionIDs ( 'repeating_weapon' , ( ids ) => {         // build an array of field names.         const fields = [];         ids . forEach ( id => sourceAttrs . forEach ( attr => fields . push ( section_name ( 'weapon' , id , attr ))));         // notice there are two foreach loops here.         // first we do a loop for every row in the repeating section (ids).         // Then with each row, we do another loop for the sourceAttrs, to build a full repeating section name         // now we can use getAttrs - it grabs the values of all the attrributes in fields.         getAttrs ( fields , v => {             // create an object variable to hold multiple attribute names and their values             const output = {};                         // Now, you had the getAttrs running on every row of the repeating section, but they were called through the calcWeaponDamage function.             // we do the same thing, but using a forEach loop instead (running it for Each row of the repeating section).             ids . forEach ( id => {                 var wNameLabelText = v [ section_name ( "weapon" , id , 'atkName' )];                 var wClip   = v [ section_name ( "weapon" , id , "clip" )];                 var wClipMax = v [ section_name ( "weapon" , id , "clip_max" )];                 console . log ( "Name of Weapon " + wNameLabelText + "." );                 console . log ( "clip: " + wClip + "/" + wClipMax + "." );                 var isAccurate = + v [ section_name ( "weapon" , id , 'q-accurate' )] || 0 ;                 var isBalanced = + v [ section_name ( "weapon" , id , 'q-balanced' )] || 0                 var isBlast = + v [ section_name ( "weapon" , id , 'q-blast' )] || 0 ;                 var isDefensive   = + v [ section_name ( "weapon" , id , 'q-defensive' )] || 0 ;                 var isFlame       = v [ section_name ( "weapon" , id , 'q-flame' )] || 0 ;                 var isFlexible = + v [ section_name ( "weapon" , id , 'q-flexible' )] || 0 ;                 var isHotshot   = 0 , isInaccurate = 0 , isOverheats = 0 , isPower       = 0 , isPrimitive   = 0 , isRecharge = 0 ,                     isReliable = 0 , isSanctified = 0 , isScatter   = 0 , isShocking   = 0 , isSmoke       = 0 , isSnare     = 0 ,                     isStorm     = 0 , isTearing     = 0 , isToxic     = 0 , isUnbalanced = 0 , isUnreliable = 0 , isUnstable = 0 ,                     isUnwieldy = 0 ;                 console . log ( "isAccurate: " + isAccurate + " isBalanced: " + isBalanced + " isBlast: " + isBlast + " isDefensive: " + isDefensive + " isFlame: " + isFlame + " isFlexible: " + isFlexible + "." );                 console . log ( "isHotshot: " + isHotshot + " isInaccurate: " + isInaccurate + "isOverheats: " + isOverheats + " isPower: " + isPower + " isPrimitive: " + isPrimitive + " isRecharge: " + isRecharge + "." );                 var wIsCarried = v [ section_name ( "weapon" , id , 'carried' )];                 console . log ( "Is carried: " + wIsCarried );                 //if (v["fail-target"] >= 2) {showFail = 1;} else {showAtk = 0;}             });             // in your current loop you dont run setAttrs. But once you do, everything will be saved to output and so run here.             setAttrs ( output );         });     }); }); Compare what you do in the original function to this worker and you'll find things are very similar. If you have any questions, ask away. There are other ways to do what this worker does, but I made sure it was close to your original worker and function, so it was more easily understood.
1683584243
GiGs
Pro
Sheet Author
API Scripter
I do notice that not every attribute in your sourceAttributes is actually used in the body. That along with the fact that setAttrs isn't used strongly suggests this is an incomplete worker. It would be good to know exactly what it is supposed to do and how each attribute is actually used. A lot of them might be irrelevant.
1683585347
GiGs
Pro
Sheet Author
API Scripter
Also you have a prefix+"relod" which I suspect should be prefix+"reload"
1683671316

Edited 1683701479
GiGs
Pro
Sheet Author
API Scripter
I realised the biggest source of my confusion: what is this sheet worker for? Your setAttrs is commented out, so I just cant tell. Right now you have a lot of attributes being grabbed, but as far as I can tell, not a single one of them is actually used. The purpose of a sheet worker is to modify one or more attributes, and those attributes are then used in some way. What attribute(s) are you creating here, and why?
Please forgive the wall of text that is incoming... I have decided to build you a picture of what I’m looking for using word.  Last time I tried this my power died (Thanks Murphy).  And I had to start over.  Not an experience I want to repeat. So, first let me start with giving an overview of how the DH1e rules work.  I’ve taken a look at the Warhammer Fantasy 1e that you told me you were familiar with and I was correct.  At their core they are nearly identical.  WHF has more base attributes.  But many of the rolling mechanics are they same so that should help. Lets start off with the ability scores.  For weapons and attacks the only really relevant ones are STRENGTH (melee) and TOUGHNESS (opponent) which I don’t think SheetWorkers can deal with.  They also need to take in Unnatural Toughness.  Which is a calculated field based on TOUGHNESS.  The code for calculating the ability scores are also handled with sheet workers. So for global attributes we really only need to do an onChange for Strength, Unnatural Strength, Toughness and Unnatural Toughness. We need to get STR/TOU modifier and Unnatural STR and Unnatural TOU Modifiers. That’s it.  Nothing Else from Global. ================-========================================-========== Inside the repeating section the easiest way to do it would be onChange(repeating_weapons), but I could probably find which specific ones need to be checked as not all attributes are used. The way attack rolls work is you roll a d100 against a target number.  IF you roll less than the target number it is a hit.  For every 10 less you have an additional degree of success for every 10 above you have an additional degree of failure. Depending on the weapon type and various other situaltional circumstances the degrees of success may add to the damage.  Additionally, additional modifiers alter the target.  Much of that is handled with the ScriptCards.  Truthfully, I would have rather handle all of that using SheetWorkers.  But I don’t have the expertise to build an entire roll output with sheet workers.  Waaay beyond me and I’d probably need someone to build it from the ground up for me. So ScriptCards it is.  My goal however, is to transfer as much of the logic as I can to sheet workers.  Because of my desire to make it so I can build character sheets/tokens that can roll atk/damage from the token rather than having to open the sheet every time.  It limits what I can do with encounters in a severe and significant way. I know you wanted me to to say things in plain english and not to include mention of ScriptCards.  However, in this one instance I cant, since that’s the primary purpose of rebuilding these as SheetWorkers instead of autocalc. All of the q-ATTRIBUTE_NAME are toggles that have an ON or OFF state, entirely boolean.  They are styled checkboxes, although I wouldn’t be averse to changing them to the new style of <buttons> rather than styled checkboxes.  I’d just need guidance on the code. Each of the checkboxes’ on or off state will be used for if else or case statements.  Or will be used in the ScriptCards.  I want to use them to define an on/off state for use both in the weapon script and outside the weapon script. For example the common one <q-accurate>, accurate weapons gain a +10 bonus to the wielders balistics skill (BS) when used with the AIM action.  (The aim action is checked as part of a RollQuery). And the <q-inaccurate> negates any bonuses normally granted from any aim action. While I understant that SheetWorkers can’t handle RollQueries(RQ) and cannot handle targeting opponents token.  I want to make it easier for me to reference these buttons in either ScriptCards or rollTemplates. Next I move on to the DROPDOWNS. Weapon Proficiency <wProficiency>, Weapon Class <wClass>, Weapon Type <wType>, Weapon Crafsmanship <wCraftsmanship> and Availability <wAvailability>. Weapon Proficiency is a Yes/No dropdown that detects if the wielder is proficient in said weapon.  There is a penalty to attacks made with non-proficient weapons. Weapon Class is what class of weapon a specific weapon is, Basic, Heavy, Melee, Pistol, Thrown or (3pp)Utility.  Alone the weapon type doesn’t have any direct effect on the rolls or damage output.  They do however, modify how other aspects of the weeapon function. Weapon Type is the damage type the weapon produces, Energy, Impact, Rending, Explosive or Normal.  And a (3pp) option of NONE.  Which I use for weapons like net-throwers and bolas.  Damage type have different ways of calculating certain modifiers to either attack or damage. Craftsmanship, the better the craftsmanship the more bonuses the weapon has.  This can be in accuracy or by granting the automatic <q-reliable> and <q-accurate> qualities.  Although, I don’t need it to check those automatically.  I’m not even sure if that is possible. Availability, is purely a label, although, I do have dreams of creating a code that can build a “store” and in such a case availability would be essential.  It currently is only used as a label.  And can probably be dropped from consideration. Math / Arithmatic The range section has one (1) user input field and five (5) calculated fields.  The Normal range is input by the user which then calculates the Point Blank, Small, Medium, Large and Extreme Range.  This is fairly straightforward math with a formulat that’s established and not generally modified by other modifiers. The Rate of Fire Clip (ammo) and Reload generalyl cant be used in calculations with SheetWorkers. Two other fields that I’d like to have is the weight and the isCarried checkbox.  Basically if the isCarried checkbox is checked then the weight is passed on and the weight that weapon is added to a total weapon weight field which is outside of the repeating section. The second is an id field, where the weapon’s row id is posted for copy/paste use elsewhere.   I do have some other questions, like, is it possible to use sheetWorkers to target opponent tokens?  If so, is it hard? One of my primary goals is to be able to eventually be able to roll weapons from a token action.  Above all other things this is my HIGHEST PRIORITY.  Beyond any other considerations.  What are some of the issues I need to worry about to make this happen. If I wanted to switch from ScriptCards to doing 100% of the work with SheetWorkers.  (including rolls, roll formatting and output).  Is that possible?  This would also mean, token targeting would need to be possible. Keep in mind the character sheet is still a work in progress.  There are some elements I haven’t finished.  For example, the Flame, Blast and Smoke all /should/ have numbers associated with them.  Which indicate a radius.  The problem is I havent found a way to format the code properly on the character sheet.  Not to mention, my higher priority has been to get the weapon damage accurate.  Therefore at some point all of those will have a number associated with them as well as an additional damage calculation one for direct damage and the other for splash. P.S., This document doesn't include how everything works, just more of an overview of what its supposed to do.  I can provide a document of how each aspect of the weapon is supposed to interact with the attack rolls, damage rolls and other direct output.  But that'd take me a bit longer to put everything together.
1683701462

Edited 1683701628
GiGs
Pro
Sheet Author
API Scripter
That explains more of the system, but doesn't explain what you are trying to do with the sheet worker. I don't see how we can proceed without knowing what you are trying to do. I'm not trying to be rude here. I just have no idea what you need, so I can't help you. Please answer the question in my last comment.
I am sorry for not responding for the past two days, I've not be able to work on anything for that time.  I understand that you are not being rude, despite that it was necessary that some basics of the system were needed for this. As for what I need I have made something I hope better explains this. Okay.. you asked for all the calculations wWeapProf dropdown(Yes/No) if no wProfMod = -20 wClass dropdown(several opt.) if Basic OR Heavy OR Pistol OR Thrown wAttr = @{bs-mod}; IF Melee wAttr = @{ws-mod}, wMeleePen = -30 wRngSm = [[floor(@{range-n})/2]] wRngNormal = @{range-n} wRngMed = @{range-n}*2 wRngLong = @{range-n}*3 wRngExtreme = @{range-n}*4 The next one is dependent on if sheet workers can use detect the distance to a selected token from the EDGE of a token not the center. wRngToTarget = calculate distance from selected token to targeted token from the EDGE of the token. The next is a logical calculation checking the range to target and determining what range increment the weapon falls into. IF wRngToTarget === wRngSm THEN wAtkMod = 10 IF wRngToTarget === wRngNormal THEN wAtkMod = 0 IF wRngToTarget === wRngLong THEN wAtkMod = 0 IF wRngToTarget === wRngLong THEN wAtkMod = -10 IF wRngToTarget === wRngExtreme THEN wAtkMod = -30 -- -- If its not possible to target tokens to get their range with sheet workers then ignore previous. wCraftsmanshipMod dropdown (several options) I think I have a handle on how to do this.  I do not believe I need assistance. I also want to total the weight all the CARRIED weapons using the checkbox isCarried to mark if a weapon is currently being carried by the player.  Then total it outside of the weapons repeating section for use by encombrence rules. wWeight = @{weight} IF isCarried === checked THEN wWeight = @{weight} ELSE wWeight = 0 And finally, I have a display spot on each repeating section to show the rowID for use in macros and such.  I want to display that on the character sheet.
1683919282
GiGs
Pro
Sheet Author
API Scripter
Toby said: -- -- If its not possible to target tokens to get their range with sheet workers then ignore previous. wCraftsmanshipMod dropdown (several options) I think I have a handle on how to do this.&nbsp; I do not believe I need assistance. I also want to total the weight all the CARRIED weapons using the checkbox isCarried to mark if a weapon is currently being carried by the player.&nbsp; Then total it outside of the weapons repeating section for use by encombrence rules. wWeight = @{weight} IF isCarried === checked THEN wWeight = @{weight} ELSE wWeight = 0 And finally, I have a display spot on each repeating section to show the rowID for use in macros and such.&nbsp; I want to display that on the character sheet. Sheet workers are internal to a character sheet and don't know anything about tokens. You can get attributes from other characters in a roll just as you can with any macro, but not token properties. For that you need a script. If you want to total the weight of all carried stuff, that's easy enough - the sheet worker for that only needs to include attributes that are directly involved. if your isCarried checkbox is given a value of 1 (should always be done IMO), you can simply multiply by the checkbox (its value will always be 0 and 1) in the sheet worker, you don't need an if statement. One way to do this is to copy the repeatingSum function as described here; <a href="https://app.roll20.net/forum/post/11149070/a-question-about-the-repeatingsum-function" rel="nofollow">https://app.roll20.net/forum/post/11149070/a-question-about-the-repeatingsum-function</a> To show the rowid, thats pretty easy. Here's a sheet worker that will handle any number of repeating sections and update their row ids: const id_attributes = { &nbsp; &nbsp; &nbsp; &nbsp; WHATEVER: 'IDATTRIBUTE' &nbsp; &nbsp; }; &nbsp; &nbsp; Object . keys ( id_attributes ). forEach ( section =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; on ( `change:repeating_ ${ section } ` , () =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; getSectionIDs ( `repeating_ ${ section } ` , ids =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const output = {}; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ids . forEach ( id =&gt; output [ `repeating_ ${ section } - ${ id } _ ${ id_attributes [ section ] } ` ] = id ); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setAttrs ( output ); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; }); You should leave this exactly as listed, except to update this part: const id_attributes = { &nbsp; &nbsp; &nbsp; &nbsp; WHATEVER: 'IDATTRIBUTE' &nbsp; &nbsp; }; Change the WHATEVER to match your repeating section name (without repeating_), and change IDATTRIBUTE to the name of the attribute you want to include. You can add extra sections by adding a comma, like so: const id_attributes = { &nbsp; &nbsp; &nbsp; &nbsp; weapon: 'row_ids', &nbsp; &nbsp; &nbsp; &nbsp; gear: 'attribute_to_contain_row_id' &nbsp; &nbsp; };
Sheet workers are internal to a character sheet and don't know anything about tokens. You can get attributes from other characters in a roll just as you can with any macro, but not token properties. For that you need a script. --By script, I assume you mean an API? One way to do this is to copy the repeatingSum function as described here;&nbsp; <a href="https://app.roll20.net/forum/post/11149070/a-question-about-the-repeatingsum-function" rel="nofollow">https://app.roll20.net/forum/post/11149070/a-question-about-the-repeatingsum-function</a> --I have the repeatingSum API running, and it works for one section of my code, but it doesn't seem to work for my weapons, though It is probable I have fudged up.&nbsp; That and I'd rather rely on built in workers in both cases. And for your last section, the code snippet, that is not going to be part of the weapon code in general?&nbsp; This a separate code within the sheetworkers?
1683959413

Edited 1683959592
GiGs
Pro
Sheet Author
API Scripter
"--By script, I assume you mean an API?" That is correct. "And for your last section, the code snippet, that is not going to be part of the weapon code in general?&nbsp; This a separate code within the sheetworkers?" Yes. One thing I'm a bit wary about is that you might be trying to do too much in your single worker. You have sv=everal things that don't seem to be related. It can be better to break workers down into separate focussed bits of code. They are easier to understand and follow. While you can do everything in a single worker, in my view thats something you should only do if you understand how all the bits fit together. If you have several desires that can be solved by separate bits of code that don't always run together, you can break them up. Once you have the full working code, you can then think about combining them into a single worker if you still want to. "--I have the repeatingSum API running, and it works for one section of my code, but it doesn't seem to work for my weapons, though It is probable I have fudged up.&nbsp; That and I'd rather rely on built in workers in both cases." I don't use repeatingSum very often, and I wrote it! Like you, I generally prefer to have built-in sheet workers. But it is an easy way to do a lot of repetitive things with repeating sections. I'm curious about where it's not working. I think you are right about fudging up something - but this is easy to do with sheet workers. I do it myself quite often! I can't identify the problem without seeing the code though. Just in case: One common issue is sheet workers can't do anything with autocalc attributes. So if you have disabled=true attributes anywhere in the chain, you'll need to rewrite them as sheet workers if you want to use those attributes with other sheet workers.
I did fark up the repeatingSum code. I had two errors, I hade disabled in my html and I had the code written as&nbsp; on('change:repeating_weapon:carried &nbsp; change:repeating_weapon:qty &nbsp; change:repeating_weight &nbsp;remove:repeating_weapon', function() { repeatingSum("weap_total_weight","weapon", "carried", "qty", "weight"); }); instead of: on('change:repeating_weapon remove:repeating_weapon', function() { repeatingSum("weap_total_weight","weapon", ["carried", "qty", "weight"]); }); I removed the specific attribute change, because that simply didn't do anything.&nbsp; I was also missing the array format for carried, qty and weight].
1684006282
GiGs
Pro
Sheet Author
API Scripter
I plan to change the syntax when I net fiddle with the code, that might be a while though :)
1684006385
GiGs
Pro
Sheet Author
API Scripter
Your first repeatingsum worker seems to have different repeating sections in the event line - the worker only calculates based on one repeating section at time, so this part can likely be deleted: change:repeating_weight
The first one is the one that didnt work--it was how i had it before, the second one was.. AFTER I fixed it and got it to work.&nbsp; =^.^=
1684044251
GiGs
Pro
Sheet Author
API Scripter
Ah, I see you do mention that in the post and I overlooked it :)