Character Sheet Development/Pattern Libraries
From Roll20 Wiki
Page Updated: 2022-02-23 |
Character Sheet Development
Getting Started
- Using Custom Sheets
- Building Sheets
(Main Page) - Glossary
- Code Restrictions
- Best Practice
- Common Mistakes
- Tutorials
- Examples, Templates
- Pattern Libraries
- HTML & storing data
- CSS & Styling
General
- Updates & Changelog
- Known Bugs
- Character Sheet Enhancement(CSE)
- Custom Roll Parsing
- Legacy Sheet(LCS)
- Beacon SDK
Reference
- Buttons
- Repeating Sections
- Sheetworkers
- Roll Templates
- sheet.json
- Translation
- Auto-Calc
- Advanced
- All SheetDev Pages
Tools & Tips
Other
This is related to Editing(coding) Character Sheets, which require Pro info to be able to use.Main Page: Building Character Sheets |
Main Page: Building Character Sheets
Pattern Libararies useful for creating your own character sheets.
Pattern Libraries
- K-Scaffold - by Scott C.
- Examples & Demo(Forum)
- Sheet Author's Journey - a sheet dev tutorial using K-Scaffold
- Roll20 Snippets - Char sheet & API code snippets - maintained by Scott C.
- Roll20Async - framework to support for asynchronous code in Roll20 Sheetworkers
- The Aaron Sheet - A facade for Sheet Worker Tasks and Utility Functions, including stylized console.log messaging.
- RepeatingSum - sheetworker snippets to make it simple to sum up info on repeating sections
- Cassie's pattern library - various HTML/CSS/JS snippets & design patterns. Feb 2020, LCS
- Roll20 Sheet Dev (VS Code Extension) - contains some code snippets for common roll20 sheet components - by Andreas J.
Contents |
Examples
Helpful Functions
//Convert Integers to be Negative const convertIntegerNegative = number => number > 0 ? -Math.abs(number) : number //Convert an object with negative numbers const convertIntegersNegatives = numbers => { numbers => { for (let [key, value] of Object.entries(numbers)) { numbers[key] = convertIntegerNegative(value); } return numbers } } //Pass in eventinfo.triggerName const findRepeatingField = trigger => trigger.split('_')[1] //Pass in eventinfo.triggerName const getReprowid = trigger => { const split = trigger.split('_'); return `${split[0]}_${split[1]}_${split[2]}` } //Pass in an object keep that has the repeating section //Example repeating_weapon_-m1czg68yzicwhfdpyys_name const getReprowAttribute = key => { const getReprowid = processingFunctions.getReprowid(key) return key.split(`${getReprowid}_`)[1] } //Provide the function with an array of keys to find translations for //Example ['strength', 'agility', 'willpower'] const getTranslations = translationKeys => { let translations = {} translationKeys.forEach(key => translations[`${key}`] = getTranslationByKey(key)) return translations } const parseInteger = string => parseInt(string) || 0 //Use for converting the result of getAttrs from strings into integers const parseIntegers = numbers => { for (let [key, value] of Object.entries(numbers)) { numbers[key] = parseInt(value) || 0 } return numbers } const setAttributes = (update, silent) => silent && typeof update === 'object' ? setAttrs(update, {silent:true}) : typeof update === 'object' ? setAttrs(update) : console.error(`${update} is not an object`) //returns strength from @{strength} const sliceAttr = attribute => attribute.slice(2, -1) const sumIntegers = numbers => numbers.reduce((a,b) => a + b, 0)
Sheet Versioning
It can be beneficial to use a visible sheet version on a sheet, so people know when the sheet have updated. Also using sheet version will make it easier for you and others to track the state of the sheet and possible changelog.
If you have complex stat & sheetworkers in you sheet and make changes to them, it can be beneficial to add sheet versioning sheetworker that updates things for character using older version of the sheet to a new one.
An example would be to update an attribute name with a typo, to one with the correct spelling. The sheet versioning would next time a sheet is opened notice it is a older version, and then perform the sheet update transferring the attribute values of the old attribute to the new one, while it would do nothing on sheet that are already the latest version.
- Forum post(Forum) by GiGs, explaining a sheet versioning script, found in this gist
- Primal Zed's example(Forum)
- The Aaron's take on a Versioning script, in the context of API scripts post(Forum)
- Sheet Versioning example - Exalted 3E sheet(Forum) (2017)
- includes attribute migration from static attributes to a repeating section. Utilizes TheAaronSheet
See also the MigrateAttributes sheetworker examples, both show a simple method for sheet versioning alongside migrating attributes to new names.
Improved Sheetworker diagnostics
TheAaronSheet contains a number of helpful sheetworker functions like simplifying repeating sections, but it also has a improved debugging settings that can help making various dev console messages more distinct.
Documentation
The "Instructions"-section of the sheet.json is a bit unwieldy to fill out and structure(mix of normal Markdown-syntax, and using /n
for line breaks), so it might be easier to place any larger documentation here on the Roll20 Community Wiki.
If the character sheet have several tabs or is long, the wiki could better fit more preview images of the sheet, rather than having something complicated on GitHub/the Sheet Template Preview.
- How to create a new wiki page
- ExampleRPG - example page for sheet documentation
- Category:Character Sheet Documentation - list of all Community Wiki pages for sheet instructions
Alternatively, add a Readme.md
-file in the same folder with the sheet code, and then write sheet instructions using Markdown on it.
Link to the sheet's wiki page/readme in the "Instructions" (e.g. For sheet instructions, go to [ExampleRPG](https://wiki.roll20.net/ExampleRPG).
.
-
sheet.json
example 1 -ink to wiki page -
sheet.json
Horizon TRPG/sheet.json example 2 link to github readme file
Using REGEX
One method of saving time with sheet dev is to use regex to find & replace more complex things in code.
Example:
- Using REGEX to add
title=
(i.e. hover descriptions) for all attributes and roll buttons - Many sheets do not tell users the different attribute names. The easiest method is to include a
title="@{attrname}"
in each input/select. Buttons could also benefit from adding atitle="%{buttonname}"
but isn't as big of a deal. - It's possible to create a regex or some other syntax/replace command that could be run on any sheet that already doesn't have them, and add these attribute name tooltips for all attributes.
- This same example could be used as a base for creating
i18n
attributes for sheet translations
- Using REGEX to add
- Basic syntax to add Attribute titles:
- find all: name="attr_REGEX"
- replace with: name="attr_REGEX" title="@{REGEX}"
- REGEX is replaced with regex commands or some other search syntax that search/accepts alphanumerals, -, _ (in essence, anything that's a valid attribute name)
- Basic syntax to add Roll buttons titles:
- find all: name="roll_REGEX"
- replace with: name="roll_REGEX" title="%{REGEX}"
- Attribute example:
find regex: name="attr_([A-Za-z0-9_-]{1,50})" replace regex: name="attr_$1" title="@{$1}"
- Buttons example:
find regex: name="roll_([A-Za-z0-9_-]{1,50})" replace regex: name="roll_$1" title="%{$1}"
- (Arbitrarily chose "50" as the max-length of possible
attr
names, use a larger number if you might have longer names.)
- (Arbitrarily chose "50" as the max-length of possible
See Also
- Character Sheet Development/Sheet Templates
- Character Sheet Development/Complete Examples - a curated list of sheets which make for a good study of how a complete sheet might be designed.
- Character Sheet Repository - code for all the existing character sheets