-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #13543 from morgdalaine/wilderfeast
[New Sheet] Wilderfeast 🍽️
- Loading branch information
Showing
21 changed files
with
3,813 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"plugins": ["@prettier/plugin-pug"], | ||
"pugAttributeSeparator": "as-needed", | ||
"pugSortAttributes": "as-is", | ||
"pugBracketSpacing": false, | ||
"pugPrintWidth": 100 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Welcome to Wilderfeast | ||
|
||
![Version](https://img.shields.io/badge/version-1.0.0-blue.svg?cacheSeconds=2592000) | ||
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/license/MIT) | ||
|
||
|
||
An unofficial Roll20 sheet for [Wilderfeast](https://horribleguild.com/us/product-category/roleplaying-games/wilderfeast) Tabletop RPG! | ||
|
||
## Install | ||
|
||
```sh | ||
# Install all of the npm packages | ||
$ npm install | ||
``` | ||
|
||
## Usage | ||
|
||
> [!WARNING] | ||
> This sheet uses `pug` and SCSS to build the HTML and CSS files respectively. Please do not directly edit the HTML or CSS directly: it will be **wiped away** when the `npm` scripts are ran. | ||
```sh | ||
# Run the development environment | ||
$ npm run dev | ||
|
||
# Run final build and linting | ||
$ npm run build | ||
``` | ||
|
||
<a href='https://ko-fi.com/R5R54NXP1' target='_blank'><img height='20' style='border:0px;height:20px;' src='https://storage.ko-fi.com/cdn/brandasset/v2/kofi_symbol.png' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a> | ||
[![GitHub](https://img.shields.io/badge/@morgdalaine-whitesmoke?style=social&logo=github)](https://github.com/morgdalaine) | ||
[![GitHub](https://img.shields.io/badge/@morgdalaine-whitesmoke?style=social&logo=discord)](https://discordapp.com/users/186973853011017729) | ||
|
||
[^0]: This README was generated with ♥︎ by [readme-md-generator](https://github.com/kefranabg/readme-md-generator) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
{ | ||
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", | ||
"vcs": { | ||
"enabled": false, | ||
"clientKind": "git", | ||
"useIgnoreFile": false | ||
}, | ||
"files": { | ||
"ignoreUnknown": false, | ||
"ignore": [] | ||
}, | ||
"formatter": { | ||
"enabled": true, | ||
"useEditorconfig": true, | ||
"formatWithErrors": false, | ||
"indentStyle": "space", | ||
"indentWidth": 2, | ||
"lineEnding": "lf", | ||
"lineWidth": 100, | ||
"attributePosition": "auto", | ||
"bracketSpacing": false | ||
}, | ||
"organizeImports": { | ||
"enabled": true | ||
}, | ||
"linter": { | ||
"enabled": true, | ||
"rules": { | ||
"recommended": true | ||
} | ||
}, | ||
"javascript": { | ||
"formatter": { | ||
"arrowParentheses": "always", | ||
"attributePosition": "auto", | ||
"bracketSameLine": false, | ||
"bracketSpacing": true, | ||
"jsxQuoteStyle": "double", | ||
"quoteProperties": "asNeeded", | ||
"quoteStyle": "double", | ||
"semicolons": "always", | ||
"trailingCommas": "es5" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
{ | ||
"name": "wilderfeast", | ||
"version": "1.0.0", | ||
"author": "morgdalaine", | ||
"scripts": { | ||
"dev": "run-p dev:*", | ||
"build": "run-s lint:pug compile:* i18n lint:biome", | ||
|
||
"dev:sass": "npx sass ./src/scss/wilderfeast.scss:wilderfeast.css --watch --no-source-map --no-charset", | ||
"dev:pug": "npx pug3 ./src/pug/wilderfeast.pug -w --out ./ --pretty", | ||
|
||
"compile:sass": "npx sass ./src/scss/wilderfeast.scss:wilderfeast.css --no-source-map --no-charset", | ||
"compile:pug": "npx pug3 ./src/pug/wilderfeast.pug --out ./ --pretty", | ||
"compile:css": "npx postcss wilderfeast.css --output wilderfeast.css --use autoprefixer --verbose --no-map", | ||
|
||
"i18n": "i18ntool -i wilderfeast.html -a > /dev/null", | ||
|
||
"lint:biome": "npx @biomejs/biome check --write ./src", | ||
"lint:pug": "npx prettier --write '**/*.pug' --plugin '@prettier/plugin-pug'" | ||
}, | ||
"keywords": ["roll20"], | ||
"license": "MIT", | ||
"devDependencies": { | ||
"@anduh/pug-cli": "^1.0.0-alpha8", | ||
"@biomejs/biome": "1.9.4", | ||
"@prettier/plugin-pug": "^3.2.0", | ||
"autoprefixer": "^10.4.20", | ||
"npm-run-all": "^4.1.5", | ||
"postcss": "^8.4.49", | ||
"postcss-cli": "^11.0.0", | ||
"prettier": "^3.3.3", | ||
"pug": "^3.0.3", | ||
"sass": "^1.81.0", | ||
"typescript": "^5.6.3" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"html": "wilderfeast.html", | ||
"css": "wilderfeast.css", | ||
"authors": "morgdalaine", | ||
"roll20userid": "61327", | ||
"preview": "wilderfeast.png", | ||
"instructions": "The Unofficial Roll20 Wilderfeast TTRPG character sheet", | ||
"useroptions": [] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
const STYLES = ["mighty", "precise", "swift", "tricky"]; | ||
const SKILLS = [ | ||
"assurance", | ||
"display", | ||
"shot", | ||
"call", | ||
"grab", | ||
"strike", | ||
"craft", | ||
"hoard", | ||
"study", | ||
"cure", | ||
"search", | ||
"traversal", | ||
]; | ||
|
||
const CONDITIONS = [ | ||
{ label: "Burned", name: "burned" }, | ||
{ label: "Caught", name: "caught" }, | ||
{ label: "Confused", name: "confused", min: 1 }, | ||
{ label: "Discordant", name: "discordant" }, | ||
{ label: "Expanded", name: "expanded" }, | ||
{ label: "Exposed", name: "exposed" }, | ||
{ label: "Fatigued", name: "fatigued", min: 1 }, | ||
{ label: "Frightened", name: "frightened", min: 1 }, | ||
{ label: "Invigorated", name: "invigorated", min: 1 }, | ||
{ label: "Hidden", name: "hidden" }, | ||
{ label: "Poisoned", name: "poisoned", min: 1 }, | ||
{ label: "Rehabilitating", name: "rehabilitating", min: 1, max: 6 }, | ||
{ label: "Rested", name: "rested", min: 1 }, | ||
{ label: "Stunned", name: "stunned", min: 1 }, | ||
{ label: "Wounded", name: "wounded", min: 1, max: 3 }, | ||
]; | ||
const CONDITIONS_REQUEST = CONDITIONS.flatMap((c) => [c.name, `${c.name}_level`]); | ||
|
||
const MAX_FIELDS = ["hp", "tool_durability", "harmony"]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
on("clicked:focus_up", async (eventInfo) => { | ||
rollAction(); | ||
}); | ||
on("clicked:go_wild", async (eventInfo) => { | ||
rollAction(true); | ||
}); | ||
|
||
/** | ||
* | ||
* @param {string} template name of rolltemplate to use | ||
* @param {object} properties key value pairs | ||
* @param {function} callback startRoll callback function; should include `finishRoll()` | ||
*/ | ||
const makeRoll = async (template, properties, callback) => { | ||
const rollstring = createRollString(template, properties); | ||
await startRoll(rollstring, callback); | ||
}; | ||
|
||
/** | ||
* Create roll string including whisper, template, and roll properties | ||
* @param {string} template name of rolltemplate to use | ||
* @param {object} properties key value pairs | ||
* @returns finished roll string | ||
*/ | ||
const createRollString = (template, properties) => { | ||
const props = Object.entries(properties) | ||
.map(([key, val]) => `{{${key}=${val}}}`) | ||
.join(""); | ||
|
||
// return `@{wtype}&{template:${template}}${props}`; | ||
return `&{template:${template}}${props}`; | ||
}; | ||
|
||
const rollAction = async (wild = false) => { | ||
getAttrs( | ||
["style", "skill", "advantage", ...STYLES, ...SKILLS, ...CONDITIONS_REQUEST], | ||
(attributes) => { | ||
const styleName = attributes.style; | ||
const skillName = attributes.skill; | ||
const style = Number(attributes[styleName]) ?? 0; | ||
const skill = Number(attributes[skillName]) ?? 0; | ||
|
||
console.debug(attributes); | ||
const properties = {}; | ||
|
||
const dic = {}; | ||
dic.action = getTranslationByKey("action") || "Action"; | ||
dic.frightened = getTranslationByKey("frightened") || "Frightened"; | ||
|
||
properties.character_name = "@{character_name}"; | ||
properties.style = `^{${styleName}}`; | ||
properties.skill = `^{${skillName}} (+${skill})`; | ||
|
||
const action_is = wild ? "wild" : "focus"; | ||
properties[action_is] = action_is; | ||
properties.action_is = action_is; | ||
|
||
properties.question = "[[?{Circumstances|Normal,0|Advantage,1|Disadvantage,-1}]]"; | ||
|
||
const dice = style - (wild ? 1 : 0); | ||
for (const key of Array.from(Array(dice).keys(), (k) => k + 1)) { | ||
properties[`roll_style${key}`] = "[[1d6]]"; | ||
} | ||
|
||
const frightenedLevel = | ||
attributes.frightened === "on" ? Number(attributes.frightened_level) : 0; | ||
const frightenedMod = | ||
frightenedLevel > 0 ? `+ ${-1 * frightenedLevel}[${dic.frightened}]` : ""; | ||
properties.roll_action = `[[1d${wild ? 20 : 8}[${dic.action}] ${frightenedMod}]]`; | ||
|
||
makeRoll("action", properties, ({ rollId, results }) => { | ||
finishRoll(rollId, results); | ||
|
||
// const answer = Number(results.question.result); | ||
// const circumstance = answer > 0 ? "advantage" : answer < 0 ? "disadvantage" : ""; | ||
// finishRoll(rollId, { | ||
// [circumstance]: true, | ||
// }); | ||
}); | ||
} | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// Handle conditions that affect other rolls | ||
for (const condition of CONDITIONS) { | ||
on(`change:${condition.name} change:${condition.name}_level`, (eventInfo) => { | ||
getAttrs(CONDITIONS_REQUEST, (attributes) => { | ||
const state = attributes[condition.name]; | ||
const level = state === "on" ? Number(attributes[`${condition.name}_level`]) : 0; | ||
|
||
switch (condition.name) { | ||
case "fatigued": | ||
setAttrs({ hp_mod: -1 * level }, { silent: true }); | ||
break; | ||
|
||
default: | ||
break; | ||
} | ||
}); | ||
}); | ||
} | ||
|
||
// Handle attributes with an underscore_max attribute | ||
for (const field of MAX_FIELDS) { | ||
on(`change:${field}`, (eventInfo) => { | ||
if (eventInfo.sourceType !== "player") return; | ||
|
||
getAttrs([field, `${field}_max`, `${field}_mod`], (attributes) => { | ||
const current = Number(attributes[field]); | ||
const max = Number(attributes[`${field}_max`]); | ||
const mod = Number(attributes[`${field}_mod`]) || 0; | ||
|
||
if (current > max + mod) { | ||
setAttrs({ [field]: max + mod }, { silent: true }); | ||
} | ||
}); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
- const DICE = Array.from(Array(10).keys(), (key) => `roll_style${key + 1}`); | ||
|
||
mixin tags(array) | ||
each tag in array | ||
if (tag[0] === "^") | ||
| {{#{tag}}} | ||
else | ||
| {{##{tag}}} | ||
if block | ||
block | ||
each tag in array.reverse() | ||
if (tag[0] === "^") | ||
- tag = tag.slice(1); | ||
| {{/#{tag}}} | ||
else | ||
| {{/#{tag}}} | ||
|
||
mixin rollFunctions(array) | ||
each tag in array | ||
| {{##{tag}}} | ||
if block | ||
block | ||
each tag in array.reverse() | ||
| {{/#{tag}}} | ||
|
||
mixin displayDie(die) | ||
+rollFunctions([`rollBetween() ${die} 1 1`]) | ||
span.sheet-wf-style__face-1= `{{${die}}}` | ||
+rollFunctions([`rollBetween() ${die} 2 2`]) | ||
span.sheet-wf-style__face-2= `{{${die}}}` | ||
+rollFunctions([`rollBetween() ${die} 3 3`]) | ||
span.sheet-wf-style__face-3= `{{${die}}}` | ||
+rollFunctions([`rollBetween() ${die} 4 4`]) | ||
span.sheet-wf-style__face-4= `{{${die}}}` | ||
+rollFunctions([`rollBetween() ${die} 5 5`]) | ||
span.sheet-wf-style__face-5= `{{${die}}}` | ||
+rollFunctions([`rollBetween() ${die} 6 20`]) | ||
span.sheet-wf-style__face-6= `{{${die}}}` | ||
|
||
rolltemplate.sheet-rolltemplate-action | ||
.sheet-wf-wrapper | ||
.sheet-wf-header | ||
+tags(["character_name"]) | ||
.sheet-wf-character-name | ||
span {{character_name}} | ||
+tags(["wild"]) | ||
.sheet-wf-go-wild | ||
span(data-i18n="goes_wild") Goes Wild | ||
+tags(["focus"]) | ||
.sheet-wf-focus-up | ||
span(data-i18n="focuses_up") Focuses Up | ||
.sheet-wf-circumstance | ||
+rollFunctions(["rollBetween() question 1 1"]) | ||
span(data-i18n="advantage") Advantage! | ||
+rollFunctions(["rollBetween() question -1 -1"]) | ||
span(data-i18n="disadvantage") Disadvantage! | ||
|
||
.sheet-wf-style-and-skill | ||
span.sheet-wf-header--style {{style}} | ||
| | ||
span.sheet-wf-header--skill {{skill}} | ||
|
||
.sheet-wf-dice-tray | ||
.sheet-wf-style | ||
+rollFunctions(["rollBetween() question 1 1"]) | ||
.sheet-wf-style__roll--advantage | ||
each die in DICE | ||
+tags([die]) | ||
+displayDie(die) | ||
+rollFunctions(["rollBetween() question 0 0"]) | ||
.sheet-wf-style__roll | ||
each die in DICE | ||
+tags([die]) | ||
+displayDie(die) | ||
+rollFunctions(["rollBetween() question -1 -1"]) | ||
.sheet-wf-style__roll--disadvantage | ||
each die in DICE | ||
+tags([die]) | ||
+displayDie(die) | ||
|
||
.sheet-wf-action(class="sheet-wf-action--{{action_is}}") | ||
+rollFunctions(["rollBetween() roll_action 1 4"]) | ||
span.sheet-wf-action__roll--partial {{roll_action}} | ||
span.sheet-wf-action__result(data-i18n="success_partial") Partial Success | ||
+rollFunctions(["rollBetween() roll_action 5 7"]) | ||
span.sheet-wf-action__roll {{roll_action}} | ||
span.sheet-wf-action__result(data-i18n="success_standard") Standard Success | ||
+rollFunctions(["rollBetween() roll_action 8 20"]) | ||
span.sheet-wf-action__roll--critical {{roll_action}} | ||
span.sheet-wf-action__result(data-i18n="success_critical") Critical Success |
Oops, something went wrong.