Skip to content

Commit

Permalink
feat: Add new Pathfinder 2e Creature layout (#436) (#438)
Browse files Browse the repository at this point in the history
* feat: Add new Pathfinder 2e Creature layout (#436)

pf2e.css generated from the Fantasy-Statblocks-CSS-Development repo

* chore: Remove unused StatblockPF2e

As far as I can tell this is never used anywhere and doesn't appear to
have contents relevant to PF2e.

* feat: Pass the plugin object to IfThen layout blocks

This allows conditional blocks to do things like check plugin settings
and whether other plugins are enabled. In particular, this allows
layouts to only show encounter buttons when the Initiative Tracker
plugin is enabled.

* feat: Allow Saves layout blocks to be CSS styled

Separates out the name and value into their own HTML elements rather
than just rendered text so that we can style individual portions with
CSS. This change has no visible effects - existing statblocks should
look exactly the same.

* feat: Use CSS to add modifier parens for the Table block

This is instead of adding them to the text content itself. This allows layout authors to customize the appearance with CSS.

* feat: Add property-dependant CSS class for Table layout blocks

* fix: Refine the PF2e creature layout

Thank you to MostTornBrain for valuable feedback! Most of this comes
from there :)

- Fix traits only showing when the trait property was present (even if
  alignment, size, or rarity was present)
- Add sign (+/-) to perception modifier
- Move Weaknesses before Resistances to match book layout
- Don't show Initiative Tracker encounter buttons if Initiative Tracker
  isn't enabled
- Show the initiative tracker view when the encounter buttons are
  pressed, to match the functionality of encounter buttons in the actual
  encounter blocks
- Bold save names
- Add sign (+/-) to ability modifiers

* docs: Improve settings doc for Trait block callbacks

* feat: Add callbacks for Saves layout blocks

* feat: Add more CSS classes for Saves blocks

* feat: Add more structured data entry for skills and saves

* doc: Update documentation with new creature layout

* fix: Pf2e Creature layout attack bonus giving NaN if undefined

* fix: Change UI-facing text for CSS property setting toggle to be a positive rather than a negative

* feat: Change attributes to a saves block so the data entry is clearer
  • Loading branch information
miscoined authored Feb 10, 2025
1 parent 9c37306 commit 9cfca6c
Show file tree
Hide file tree
Showing 12 changed files with 3,152 additions and 744 deletions.
3 changes: 2 additions & 1 deletion src/layouts/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Layout5e } from "./basic 5e/basic5e";
import { LayoutFateCore } from "./fate core/fateCore";
import { LayoutPF2e } from "./pathfinder 2e/pf2e";
import { LayoutPF2e, LayoutPF2eCreature } from "./pathfinder 2e/pf2e";
import { Layout13thAgeMonster} from "./13th age/monster/13th-age-monster";
import { LayoutBnBBestiary } from "./BnB/bestiary/bnb-bestiary";
import { LayoutBnBFamiliar } from "./BnB/familiar/bnb-familiar";
Expand All @@ -16,6 +16,7 @@ export const DefaultLayouts = [
Layout5e,
LayoutFateCore,
LayoutPF2e,
LayoutPF2eCreature,
Layout13thAgeMonster,
LayoutBnBBestiary,
LayoutBnBFamiliar
Expand Down
1 change: 1 addition & 0 deletions src/layouts/layout.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ type PropertyProps = {
};
type SavesProps = {
type: "saves";
callback?: string;
display?: string;
};
type SpellsProps = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"blocks":[{"type":"inline","id":"e9b8483aeafa","properties":[],"nested":[{"type":"property","id":"2b596a6919fb","properties":["name"],"fallback":"-","markdown":true,"dice":false,"conditioned":true,"display":" "},{"type":"ifelse","id":"badbdb298988","conditions":[{"nested":[{"type":"group","id":"990a4a988ae8","properties":[],"nested":[{"type":"inline","id":"499aea6a9aca","properties":[],"nested":[{"type":"action","id":"8a6a7a499b78","icon":"sword","callback":"(async() => {\n if (!InitiativeTracker.plugin.view) {\n await InitiativeTracker.plugin.addTrackerView();\n }\n InitiativeTracker.newEncounter({\n roll: true,\n creatures: [monster]\n });\n if (InitiativeTracker.plugin.view) {\n InitiativeTracker.plugin\n .app\n .workspace\n .revealLeaf(InitiativeTracker.plugin.view.leaf);\n }\n})();"},{"type":"action","id":"fbea380b09b9","icon":"plus-with-circle","callback":"(async() => {\n if (!InitiativeTracker.plugin.view) {\n await InitiativeTracker.plugin.addTrackerView();\n }\n InitiativeTracker.addCreatures([monster]);\n if (InitiativeTracker.plugin.view) {\n InitiativeTracker.plugin\n .app\n .workspace\n .revealLeaf(InitiativeTracker.plugin.view.leaf);\n }\n})();"}]}]}],"condition":"return plugin.app.plugins.enabledPlugins.has(\"initiative-tracker\");\n"}]},{"type":"property","id":"98389a48f808","properties":["level"],"fallback":"-","display":" ","conditioned":true,"markdown":true,"dice":false}],"hasRule":true},{"type":"group","id":"4b3a6809a938","properties":[],"nested":[{"type":"property","id":"0979a989583a","properties":[],"fallback":"-","callback":"const traits = []\nif (monster.rarity && monster.rarity.toLowerCase() !== \"common\") {\n traits.push(`<span class=\"rarity ${monster.rarity.toLowerCase()}\">${monster.rarity}</span>`);\n}\n\nif (monster.alignment) {\n traits.push(`<span class=alignment>${monster.alignment}</span>`);\n}\nif (monster.size) {\n traits.push(`<span class=size>${monster.size}</span>`);\n}\n\nif (monster.traits) {\n traits.push(...monster.traits);\n}\n\nreturn traits ? (\"- \" + traits.join(\"\\n- \")) : \"\";","conditioned":true,"display":""}],"hasRule":true,"cls":"pf2e-traits"},{"type":"group","id":"5999ea79ca3b","properties":[],"nested":[{"type":"inline","id":"881859197838","properties":[],"nested":[{"type":"property","id":"4ad9f92ab8f8","properties":["modifier"],"fallback":"-","display":"Perception","conditioned":false,"dice":false,"diceCallback":"const num = (property < 0 ? \"-\" : \"+\") + Math.abs(property);\nreturn [num, \" (\", { text: \"1d20\"+num }, \")\"];","callback":"return (monster.modifier < 0 ? \"-\" : \"+\") + Math.abs(monster.modifier);"},{"type":"property","id":"8bd82998dadb","properties":["senses"],"fallback":"-","conditioned":true,"display":""}],"cls":"oneline","conditioned":true},{"type":"property","id":"ba28f9384918","properties":["languages"],"fallback":"-","display":"Language","conditioned":true,"markdown":true},{"type":"saves","id":"6a2b78099b0b","properties":["skills"],"fallback":"-","display":"Skills","conditioned":true,"dice":true,"callback":"const keys = [...Object.keys(property)];\nconst name = keys.shift();\n\nif (name === \"note\") {\n return {note: property.note};\n}\n\nvar note;\nvar stats = [];\nfor (const key of keys) {\n if (key === \"note\") {\n note = property[key];\n } else {\n const sign = property[key] < 0 ? \"-\" : \"+\";\n const num = Math.abs(property[key]);\n stats.push(`(${sign}${num} ${key})`);\n }\n}\n\nif (stats.length == 0 && !note) {\n return property;\n}\n\nstats.unshift(\n (property[name] < 0 ? \"-\" : \"+\") +\n Math.abs(property[name]));\nconst parts = [stats.join(\" \")];\nif (note) {\n parts.push(note);\n}\nreturn {[name]: parts.join(\", \")};"},{"type":"saves","id":"b82b0a1a9969","properties":["attributes"],"fallback":"-","conditioned":true,"display":""},{"type":"property","id":"1b6a98ba4888","properties":["items"],"fallback":"-","display":"Items","conditioned":true},{"type":"traits","id":"e96ba9d8a80a","properties":["abilities_top"],"fallback":"-","conditioned":true,"dice":true,"markdown":true,"heading":" ","hasRule":false}],"hasRule":true},{"type":"group","id":"faaa08993a98","properties":[],"nested":[{"type":"inline","id":"3a5ab84a2b89","properties":[],"nested":[{"type":"inline","id":"cb6a7809aa2b","properties":[],"nested":[{"type":"property","id":"6b0b0bda0a7a","properties":["ac"],"fallback":"-","display":"AC"},{"type":"property","id":"0908aaab3b1b","properties":["acNote"],"fallback":"-","conditioned":true,"display":""}],"cls":"withnote","conditioned":true},{"type":"saves","id":"9999386a58ea","properties":["saves"],"fallback":"-","dice":true,"display":"","conditioned":true,"callback":"const keys = [...Object.keys(property)];\nconst name = keys.shift();\n\nif (name === \"note\") {\n return {note: property.note};\n}\n\nvar note;\nvar stats = [];\nfor (const key of keys) {\n if (key === \"note\") {\n note = property[key];\n } else {\n const sign = property[key] < 0 ? \"-\" : \"+\";\n const num = Math.abs(property[key]);\n stats.push(`(${sign}${num} ${key})`);\n }\n}\n\nif (stats.length == 0 && !note) {\n return property;\n}\n\nstats.unshift(\n (property[name] < 0 ? \"-\" : \"+\") +\n Math.abs(property[name]));\nconst parts = [stats.join(\" \")];\nif (note) {\n parts.push(note);\n}\nreturn {[name]: parts.join(\", \")};"}],"cls":"oneline","conditioned":true},{"type":"inline","id":"ea29d9ea5aa8","properties":[],"nested":[{"type":"inline","id":"39584be95ae9","properties":[],"nested":[{"type":"property","id":"bb6989092939","properties":["hp"],"fallback":"-","display":"HP"},{"type":"property","id":"b9fa1a89c8d9","properties":["hpNote"],"fallback":"-","doNotAddClass":false,"conditioned":true,"display":""}],"cls":"withnote","conditioned":true},{"type":"property","id":"4bbaa9380a9b","properties":["hardness"],"fallback":"-","display":"Hardness","conditioned":true},{"type":"property","id":"0a8ac8d96bba","properties":["immunities"],"fallback":"-","conditioned":true,"display":"Immunities"},{"type":"property","id":"78689b6b6b79","properties":["weaknesses"],"fallback":"-","conditioned":true,"display":"Weaknesses"},{"type":"property","id":"8b7a3b89fa59","properties":["resistances"],"fallback":"-","conditioned":true,"display":"Resistances"}],"cls":"oneline","conditioned":true},{"type":"traits","id":"ca2bf968987b","properties":["abilities_mid"],"fallback":"-","heading":"","conditioned":true,"dice":true,"markdown":true,"hasRule":false}],"hasRule":true},{"type":"group","id":"cbeabaf93b58","properties":[],"nested":[{"type":"property","id":"0b4809ba0b29","properties":["speed"],"fallback":"-","display":"Speed","conditioned":true,"markdown":true,"dice":false},{"type":"traits","id":"882bc9aa0898","properties":["attacks"],"fallback":"-","conditioned":true,"dice":true,"markdown":true,"headingProp":false,"heading":"","callback":"var s = \"\";\nif (property.bonus) {\n s += (property.bonus < 0 ? \"-\" : \"+\") + Math.abs(property.bonus);\n}\nif (property.desc) {\n s += \" \" + property.desc\n}\nif (property.damage) {\n s += \", __Damage__ \" + property.damage\n}\nreturn s"},{"type":"traits","id":"faeafb7b6b1b","properties":["spellcasting"],"fallback":"-","conditioned":true,"dice":true},{"type":"traits","id":"aacb399a3b58","properties":["abilities_bot"],"fallback":"-","conditioned":true,"dice":true,"markdown":true,"hasRule":false}],"hasRule":true},{"type":"text","id":"1b195a894b58","properties":["token"],"text":null,"fallback":"","heading":"Show to Players","conditioned":true,"markdown":true},{"type":"image","id":"1bba89582b29","properties":["token"],"fallback":"","conditioned":true,"hasRule":true},{"type":"property","id":"88e97a485b79","properties":["sourcebook"],"fallback":"-","conditioned":true,"markdown":true,"dice":false,"display":" Source:"}],"name":"Pathfinder 2e Creature Layout","id":"b8ab3ae89a0a","diceParsing":[{"regex":"(\\s|^)(\\d+d\\d+(?:\\s*[+-]\\s*\\d+)?)(\\W|$)","parser":"const [, before, text, after] = matches;\nreturn [before + text, \" (\", { text }, \")\", after];","id":"4a79397b896a","desc":"1d6+10"},{"regex":"(^|\\s)([+-]\\d+)(\\W|$)(?!status|bonus)","parser":"let [, before, bonus, after] = matches;\nreturn [\n before + bonus,\n \" (\", { text: \"1d20\" + bonus }, \")\",\n after\n];","id":"8bb8fbbb0869","desc":"+15"}],"edited":true}
Loading

0 comments on commit 9cfca6c

Please sign in to comment.