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

[Warhammer 4e] Character Sheet (Official and Unofficial)

1579874751

Edited 1579874868
GiGs
Pro
Sheet Author
API Scripter
Axel said: Thank you, that's a helpful explanation, but sadly not enough for me to actually write the code myself. Is something like this what I'm looking for? <a href="https://app.roll20.net/forum/post/5798542/help-explain-this-working-sheet-worker-to-me/?pageforid=5798542#post-5798542" rel="nofollow">https://app.roll20.net/forum/post/5798542/help-explain-this-working-sheet-worker-to-me/?pageforid=5798542#post-5798542</a> That thread does illustrate some concepts, but I dont think its helpful enough for people who havent created a version script before - there's a bit too much complexity there. It doesnt have to be that complex. Here's a simple example, that is imperfect (it only handles one version change, and ideally you want future proofing for multiple updates). First, you need a standalone function that does the actual work. You said some data might be lost - to avoid that, you'd create a function to list the attributes that are being lost, and grab those values and transfer to the equivalent attributes used by your sheet. Here's the basic framework for that: function transferAttributes() { &nbsp; &nbsp; getAttrs(['name list of old attributes'], function(values) { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; // some code to swap the old values to the new attributes, including any processing of data necessary &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; setAttrs({ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newattributes:newvalues // this could be a very long list of attributes and new values &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;})}; &nbsp;&nbsp;&nbsp;&nbsp;}) }; Then your versioning macro would look something like (this is for illustrating the process, I'll post a better version below): on('sheet:opened', function() { &nbsp; &nbsp; getAttrs(['version'], function (values) { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; let version = +values.version || 0; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; if(version &lt; 1.0) { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; // version is less than current version, this sheet hasnt been updated, so update now &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; transferAttributes(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setAttrs({version: 1.0}); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp; &nbsp; }); }): So this function checks the version value, and if it is below the current value, it runs the macro that changes values, then sets the version to 1.0, so that the next time the sheet is run, it doesnt trigger again. The version above is easy to read and understand, and is what most of the versions on the github do, but it has a serious flaw, so I don't recommend using it exactly. Here's a simple upgrade: function transferAttributes(newversion) { // now has a parameter for the new version number &nbsp; &nbsp; getAttrs(['name list of old attributes'], function(values) { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; // some code to swap the old values to the new attributes, including any processing of data necessary &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; setAttrs({ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newattributes:newvalues , &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;version: newversion&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// and now sets the new version number at the same time as updating the other stats. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;})}; // you might or might not want {silent:true} here, depending on how your sheet works. &nbsp;&nbsp;&nbsp;&nbsp;}) }; on('sheet:opened', function() { &nbsp; &nbsp; getAttrs(['version'], function (values) { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; let version = +values.version || 0; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; if(version &lt; 1.0) { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; transferAttributes(1.0); // here we send the new version number to the function &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp; &nbsp; }); }): Again its not perfect, since it handles only one version change and ideally you need to handle multiple version upgrades over the course of sheet's life. I've been meaning to post a generic solution for that, hopefully I'll find time for it soon. But in the meantime, the problem this fixes: in the first version above, if something breaks in your upgrading function, all the attributes won't update, but the version number will still be changed, so the function wont run again and some data will be lost. In this version, the version number doesnt change until the data is updated, so you can be sure that if the version number has updated, the update function has worked. Hope this helps!
1579876150

Edited 1579876169
Victor B.
Pro
Sheet Author
API Scripter
There are sample sheet workers in my sheet.&nbsp; They were added to support modifying token HP and that that carry over to the char sheet.&nbsp; You'll get an idea how to access char sheet attributes.&nbsp; Gig wrote them for me.&nbsp;&nbsp;
1579907669
Axel
Pro
Sheet Author
GiGs said: Hope this helps! It certainly does! I still have questions though. I assume that "version" needs to be an attribute, and since a "version" attribute doesn't exist in the old sheet, do I create that attribute within the html? Then, whenever I update the sheet, it seems clear that I need to change the version in the script only. Is this part necessary? &lt;input type="hidden" name="attr_version" value="0"/&gt; When you say "newattributes:newvalues" in the script, does the "newvalue" refer to the name of the old attribute? That would seem to be the thing that actually transfers the old attributes values. If those attributes don't exist, which they won't for new characters, then nothing will be transferred by the version will still update. Example with old attributes to new attributes: function transferAttributes(newversion) { // now has a parameter for the new version number &nbsp;&nbsp;&nbsp; getAttrs(["WS_CareerAdvance", "BS_CareerAdvance", "S_CareerAdvance"], function(values) { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setAttrs({ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; weaponskill_advances:WS_CareerAdvance, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ballisticskill_advances:BS_CareerAdvance, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strength_advances:S_CareerAdvance, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; version: 1.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // and now sets the new version number at the same time as updating the other stats. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; })};&nbsp; // you might or might not want {silent:true} here, depending on how your sheet works. &nbsp;&nbsp;&nbsp; }) }; When the sheet then receives a new version, all instances of "1.0" in the script need to be changed to match? How would this work for attributes in repeating sections? I'm sure that a generic script for this that any sheet author could employ for their work would be extremely helpful for the community, but I for one won't make any demands for it. I just appreciate any help I can get, and this is certainly a good start.
1579907674
Axel
Pro
Sheet Author
Victor B. said: There are sample sheet workers in my sheet.&nbsp; They were added to support modifying token HP and that that carry over to the char sheet.&nbsp; You'll get an idea how to access char sheet attributes.&nbsp; Gig wrote them for me.&nbsp;&nbsp; Thanks, I have some of the basics down already, but I have to confess that I still don't understand why the "wounds" attribute can't be autocalc. I know that best practices says to use sheet workers instead of autocalc, but I don't get what it is about about autocalc makes the attribute impractical to link on a token. I don't seem to have any problems at all with using "attr_wounds" as an editable attribute, and then "attr_wounds_max" as a disabled autocalc attribute. The "wounds" attribute links perfectly to token in my testing, and behaves just like any other hitpoint-equivalent attribute.
1579911887
GiGs
Pro
Sheet Author
API Scripter
Axel said: Victor B. said: There are sample sheet workers in my sheet.&nbsp; They were added to support modifying token HP and that that carry over to the char sheet.&nbsp; You'll get an idea how to access char sheet attributes.&nbsp; Gig wrote them for me.&nbsp;&nbsp; Thanks, I have some of the basics down already, but I have to confess that I still don't understand why the "wounds" attribute can't be autocalc. I know that best practices says to use sheet workers instead of autocalc, but I don't get what it is about about autocalc makes the attribute impractical to link on a token. I don't seem to have any problems at all with using "attr_wounds" as an editable attribute, and then "attr_wounds_max" as a disabled autocalc attribute. The "wounds" attribute links perfectly to token in my testing, and behaves just like any other hitpoint-equivalent attribute. You could do it that way and it would be fine. The advice on not using autocalcs is because people often have the current value set as an autocalc. If you want current value to be set automatically, when a character is created, you need to either use a sheet worker or autocalc.&nbsp;
1579912712
GiGs
Pro
Sheet Author
API Scripter
Axel said: GiGs said: Hope this helps! It certainly does! I still have questions though. I assume that "version" needs to be an attribute, and since a "version" attribute doesn't exist in the old sheet, do I create that attribute within the html? Then, whenever I update the sheet, it seems clear that I need to change the version in the script only. Is this part necessary? &lt;input type="hidden" name="attr_version" value="0"/&gt; Yes, that part is vital. You need an attribute defined in the sheet, with a default value that is lower than whatever you are setting in your version script, to ensure it runs the first time it is needed. When you say "newattributes:newvalues" in the script, does the "newvalue" refer to the name of the old attribute? That would seem to be the thing that actually transfers the old attributes values. If those attributes don't exist, which they won't for new characters, then nothing will be transferred by the version will still update. Example with old attributes to new attributes: function transferAttributes(newversion) { // now has a parameter for the new version number &nbsp;&nbsp;&nbsp; getAttrs(["WS_CareerAdvance", "BS_CareerAdvance", "S_CareerAdvance"], function(values) { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setAttrs({ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; weaponskill_advances:WS_CareerAdvance, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ballisticskill_advances:BS_CareerAdvance, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strength_advances:S_CareerAdvance, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; version: 1.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // and now sets the new version number at the same time as updating the other stats. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; })};&nbsp; // you might or might not want {silent:true} here, depending on how your sheet works. &nbsp;&nbsp;&nbsp; }) }; This depends. yes, you can do it that way, if the old attributes are simply swapped over to new names. But sometimes you are combining multiple abilities into single, or breaking one ability into several, or converting some abilities into a repeating section. In those situations you need to do some processing on the values first.&nbsp; In my example function function transferAttributes(newversion) { // now has a parameter for the new version number &nbsp; &nbsp; getAttrs(['name list of old attributes'], function(values) { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; // some code to swap the old values to the new attributes, including any processing of data necessary &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; setAttrs({ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newattributes:newvalues , &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;version: newversion&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// and now sets the new version number at the same time as updating the other stats. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;})}; // you might or might not want {silent:true} here, depending on how your sheet works. &nbsp;&nbsp;&nbsp;&nbsp;}) }; the commented line starting // some code to swap &nbsp;was shorthand, to indicate there might be some processing there before you do the setAttrs. But if its just a straight swap from attributes with one name to attributes with a different name, the code sample you posted would be perfect. When the sheet then receives a new version, all instances of "1.0" in the script need to be changed to match? How would this work for attributes in repeating sections? Repeating sections are trickier. You need to use the getSectionIDs function (see the wiki) to walk through the old repeating section and grab its attributes, then create new repeating section attributes with those new values. If you do a sheet update to version 1.0, then later create a new version, you use a new version number, like 1.1, or 2.0, Then your version check can check if the sheet is below version 1, run that update, then check if it is below version 1.1, and run that update, then check if its eblow 2.0, then run that update, and so on. In this way you can keep a any sheet fully updated to the latest version, without needing to know what version a sheet currently is. The progressive updates handle it nicely. One Piece of Advice All this said, the three of you making WFRP sheets would be best off using one set of attribute names, and not changing them unless you have a very good reason to. Then players can switch between sheets with minimal issues. You'd only need small version sheet workers, to handle only the actual differences between the sheets, and not just different attribute names.
1580559395
Axel
Pro
Sheet Author
Progress Update: I feel done with the layout and I'm working on the roll template now. Then I can get to making sure translation is working. Finally, I can get to attributes. I'm still debating the merits of changing attributes or making scripts to transfer them. If i can't get a script that fetches attributes from repeating fields, I don't think there's any point, but I'll see what it looks like once I'm done with template and translation.
1580568759
Victor B.
Pro
Sheet Author
API Scripter
There's two approaches here Axel.&nbsp; 1) You have a new sheet, 2) Your's will improve the original sheet.&nbsp; Up to you which approach you want to take.&nbsp; If you choose option 2, then I'd change the attributes to match as close as possible to the original.&nbsp; If there's substantial changes in way you're storing things, then possibly a couple of sheet workers will be required.&nbsp; Yes you can access attributes in repeating sections.&nbsp;&nbsp;
1580597713
Axel
Pro
Sheet Author
I'm sure it's possible to access attributes in repeating sections with a script, but I can't do that myself.
1580601075
GiGs
Pro
Sheet Author
API Scripter
Have a look here&nbsp; <a href="https://wiki.roll20.net/Sheet_Worker_Scripts#getSectionIDs.28section_name.2Ccallback.29_.5BAsynchronous.5D" rel="nofollow">https://wiki.roll20.net/Sheet_Worker_Scripts#getSectionIDs.28section_name.2Ccallback.29_.5BAsynchronous.5D</a>
Seems like something broke with the new sheet, since the background image for the sheet is gone. That or you're looking for new images to use.
1580764290
GiGs
Pro
Sheet Author
API Scripter
Axel said: I'm sure it's possible to access attributes in repeating sections with a script, but I can't do that myself. To add to my previous post, if you tell me the name of a repeating section you want to get attribute values from, the attribute names you want from within it, and how you want to use them, I can post an example sheet worker to give you pointers.
1580764886
Victor B.
Pro
Sheet Author
API Scripter
@sollow, which sheet
1580772301

Edited 1580772324
GiGs
Pro
Sheet Author
API Scripter
Looks like its the WFRP4CharSheet sheet on github. keith posted the error in another thread: keithcurtis &nbsp;said: It looks like something happened to the background image. <a href="http://imgsrv.roll20.net/?src=raw.githubusercontent.com/Roll20/roll20-character-sheets/master/WFRP4CharSheet/assets/parchment.jpg" rel="nofollow">http://imgsrv.roll20.net/?src=raw.githubusercontent.com/Roll20/roll20-character-sheets/master/WFRP4CharSheet/assets/parchment.jpg</a> &nbsp;comes up broken. The notes say: "It is being continually developed by&nbsp; Arioch1973 &nbsp;and any questions regarding it can be directed to him through the roll20 forums or messages." The parchment.jpg file is missing from the assets subfolder on github.
1580774264
GiGs
Pro
Sheet Author
API Scripter
Cassie just posted in that thread that it should be fixed now <a href="https://app.roll20.net/forum/post/8101348/character-sheet-image-error" rel="nofollow">https://app.roll20.net/forum/post/8101348/character-sheet-image-error</a>