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

A Sheet Author's Journey - Do the PUG!

1644388717

Edited 1648660175
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Welcome to the second week of A Sheet Author's Journey! Last week we sketched out a rough idea of what our sheet was going to look like and assembled our tools. Today, we're going to actually start making the sheet. We're going to start our coding with the top two rows of that sketch, although we're going to hold off on the image section because we want to make sure we're going to have room for it. The code from today's post can be found in folder  2 First Code  of the Tutorial Sheet . Series Posts The Beginning Do the Pug Repeating Sections and sheetworkers Style and Layout Finding our Flair! Roll on! Organizing our code Where do we start though? Well, first we need to define what the various components of our sheet are going to be. Last week we sketched out a prototype layout for the PC sheet, but we'll need an NPC sheet as well so that GM's can take advantage of the sheet as well. In addition, we'll need a settings page where users can modify how the sheet functions. At the very least, this is going to be how the sheet is switched from PC to NPC mode. Let's split our code up so that each section of each page is it's own file. This allows us to work with smaller blocks of code at a time, while not making our code so divided that it's difficult to navigate. As an added bonus, this gives us defined milestones so that we can get a sense of accomplishment while writing the sheet. So, Here's what our file structure is going to look like: First lines of code That seems like a lot of files, but splitting them up this way is going to save us lots of time scrolling looking for that one line of code that we need to change. Also, note that the files for each section start their names with an underscore. This tells prePros to not generate an HTML file for those files. Instead it only generates the html for system.pug which will include those files. Here's what the code for system.pug looks like: include scaffold/_kpug.pug include mixins/_sheetmixins.pug - let templateName = 'thj2e'; +hidden({name:'template start',value:`@{whisper}&{template:${templateName}} {{character_name=@{character_name}}} {{character_id=@{character_id}}}`}) +hidden({name:'sheet state',value:'settings'}) +hidden({name:'collapsed',value:''}) main#main nav#main-nav.sheet-nav each val in ['character','npc'] +action({name:`nav ${val}`,class:`sheet-nav__tab ${val}`,'data-i18n':`${val} sheet`,'data-i18n-title':`${val} sheet button title`,role:'heading','aria-level':5,trigger:{listenerFunc:'navigateSheet'}}) +action({name:'nav settings',class:'pictos active sheet-nav__tab settings','data-i18n-title':'open the settings page',role:'heading','aria-level':5,trigger:{listenerFunc:'navigateSheet'}}) |y include articles/settings/_settings.pug include articles/character/_character.pug include articles/npc/_npc.pug include rolltemplates/_thj2etemplate.pug +kscript //- All additional javascript files should start here A fully commented version can be found on the github repository, but lets take a look at what's going on in this file. It sure doesn't look like the code for an entire character sheet after all. include scaffold/_kpug.pug include mixins/_sheetmixins.pug The first line here simply installs the K-scaffold so that we can use its library of PUG mixins and functions and connect our PUG and Javascript code. The second line includes a file that I've set up to hold the system specific mixins we will almost certainly be writing as we go along. Speaking of mixins, we use some in the next couple lines: +hidden({name:'template start',value:`@{whisper}&{template:${templateName}} {{character_name=@{character_name}}} {{character_id=@{character_id}}}`}) +hidden({name:'sheet state',value:'settings'}) +hidden({name:'collapsed',value:''}) Here, we're defining three hidden inputs that will be used by various pieces of the sheet. The first line just gives us an attribute we can call to include the standard roll template fields so that we don't have to type those in constantly. The other two attributes will be used by our Javascript powered navigation system that we will eventually write. Then we come to the container for our actual sheet: main#main nav#main-nav.sheet-nav each val in ['character','npc'] +action({name:`nav ${val}`,class:`sheet-nav__tab ${val}`,'data-i18n':`${val} sheet`,'data-i18n-title':`${val} sheet button title`,role:'heading','aria-level':5,trigger:{listenerFunc:'navigateSheet'}}) +action({name:'nav settings',class:'pictos active sheet-nav__tab settings','data-i18n-title':'open the settings page',role:'heading','aria-level':5,trigger:{listenerFunc:'navigateSheet'}}) |y We're putting this in a main  element so that our HTML will be semantic. While writing semantic HTML is not essential, it will make understanding your code easier and will help make your sheet more accessible to users that rely on screen readers. Also in this section, we define our navigation bar, which will have a button to access the character sheet, the settings sheet, and the NPC sheet. We can add additional buttons to this set as needed. Note the trigger object at the end of each of the action button declarations. This will be an object format that we'll use frequently throughout the sheet as it is how the K-scaffold writes our Javascript listeners for us. These trigger objects are defining a custom function to respond to these buttons being clicked. And finally, we've got references to each of our separate pages: include articles/settings/_settings.pug include articles/character/_character.pug include articles/npc/_npc.pug These are including the code for each of our pages so that the html that is generated will include all of this code. Each page is going to be an article  which will include the code for each section: article#character.character include sections/_header.pug include sections/_attributes.pug include sections/_defenses.pug include sections/_weapons.pug include sections/_armor.pug include sections/_lineage.pug include sections/_archetype.pug include sections/_equipment.pug include sections/_spells.pug Creating our first section That's pretty simple! So, let's jump into what one of these sections looks like. We'll take a look _attributes.pug here, but those first three files are written and available to view in the repository. Here's what the attributes section looks like on the paper sheet: So, we've got 6 attributes that need to be tracked, and each one has a raw score and a modifier that is derived from that score. We could write out our inputs for each of these attributes by hand, but PUG allows us to do this by iteration so that all we need to write is: - const attributes = [ 'might', 'finesse', 'resolve', 'insight', 'bearing', 'weal' ]; - varObjects.attributeNames = attributes; section#attributes.attributes.paper-background h5(data-i18n='score').score-head h5(data-i18n='modifier').modifier-head each name in attributes +roller({name,role:'heading','aria-level':4,'data-i18n':name,trigger:{listenerFunc:'initiateRoll'}}) +number({name,class:'underlined',trigger:{affects:[`${name}_mod`]}}) +number({name:`${name} mod`,readonly:'',class:'underlined',trigger:{calculation:'calcAttribute'}}) So, we've defined an array that stores the names of all the attributes. Additionally, we're storing that array in the K-scaffold provided varObjects so that it will be available in our javascript as well (once we get to writing it). Then, we iterate through that array to create our elements. This means we only have to write the elements once, and PUG will generate each of them for us. Each attribute is going to have a clickable button that will roll a basic attribute check for the character, a number input to store the raw score, and a number input to store the modifier in. Note the trigger objects for those two number inputs. We're setting our raw score input for each attribute to affect the mod for each attribute and defining a function that we'll need to write to calculate the modifier score. That's pretty much it for this section. We've also added some classes and roles to various elements that we'll hook into when we write our SCSS and our Javascript navigation functions. Is that all!? It may not seem like we've done a lot yet, but we've got pretty much all of our basic attributes for a PC done. Next week we'll look at creating repeating sections to handle all the rest and start laying the sheet out into its basic grid. Hope you all find this helpful and hit me up with questions, suggestions, or critiques in the comments. If you're enjoying this series of posts, d rop by the   Kurohyou Studios Patreon ! See the previous post  | Check out the Repository  | See the next post
1645045189
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Post three is up. We're talking about repeating sections and sheetworkers. Come on by to see what's going on !
1645490881
Hi Scott, I've used your Pathfinder Companion script for several years and really enjoyed it. Thank you! A few months ago something changed -- I'm not sure what -- and I can no longer do imports of stat bloks (i.e., pfc --parse). I've tried setting up test games using the Pathfinder Community Sheet and even older editions of it from github but I haven't figured out the right mojo. Can you walk me through what I need to do to start using it again? One thing I have noticed is that if I download a sheet package from github it includes the following files: pathfinder-neceros.css pathfinder-neceros.html sheet.json translation.json However, if I choose a Custom sheet in the game settings I see only 3 tabs: HTML, CSS, and Translation. So I don't know what to do with "sheet.json". Any suggestions are appreciated. Regards, Jason Freeman
1645493305
vÍnce
Pro
Sheet Author
Hi Jason, probably best to create a new post for this since your question is about the PFC script.  ;-)  I'll post a quick response, but I will delete/move my post soon to keep this on-topic. PFC and PF Community sheet; You probably don't need to worry about the sheet.json unless you are developing a sheet.  You can ignore the sheet.json for a custom game.  It will work in a sandbox game if needed.  The PF Community sheet hasn't had any fundamental changes in a long while. I believe that some issues that might be arising with the PFC script has more to do with roll20 changes. You should be able to ignore the warning message if prompted and I would not recommend changing to an older version of the sheet.  The majority of updates that have been done to the sheet over the last few years were for bug fixes and adjustments for roll20's features. PFC parse; YMMV, but I have been able to use a simple macro to parse statblocks.  PFC was designed to parse Paizo's SRD, results may vary grabbing a statblock from other sources. !pfc --parse|{{ PASTE STATBLOCK HERE }} I have noticed recently that you will probably need to also use the "parse" button from the NPC statblock box on the NPC tab of the sheet to finish an import.  Again, there may be some things that do not completely parse over.  I'm sure Scott would agree that the sheet and script can use an overhaul, but that's kind of where we are at the moment. If you post in another thread, maybe you can elaborate on specific issues. Cheers