Skip to content

feat: implement mechanical effects for hit dice and max HP modifications#8

Open
sjlevin wants to merge 2 commits intobitnook-cc:mainfrom
sjlevin:main
Open

feat: implement mechanical effects for hit dice and max HP modifications#8
sjlevin wants to merge 2 commits intobitnook-cc:mainfrom
sjlevin:main

Conversation

@sjlevin
Copy link
Copy Markdown

@sjlevin sjlevin commented Mar 20, 2026

Bug

Hunter Keeper of the Wild Heart's "Impressive Form" feature says "+5 max HP. Upgrade your Hit Dice to d10s." but had no mechanical effect — the traits array was empty. Same issue with Oozeling/Construct's "Odd Constitution" (hit dice +1 step) and Shadowmancer's "Fiendish Boon" (-1 max hit dice).

Changes

  • Added maxHpBonus, hitDieSizeOverride, and hitDieSizeStep to the stat bonus system
  • Added getMaxHp() computed method following the existing pattern used by getMaxWounds(), getArmorValue(), etc.
  • Extended getHitDice() to apply feature-based die size overrides and step increments
  • Updated all UI displays and service methods (healing, resting, level-up, PDF export) to use computed values
  • Implemented mechanical traits for Impressive Form, Odd Constitution, and Fiendish Boon
  • Added sizeOverride field on hit dice for manual user overrides that take priority over all feature bonuses
  • Added NumericInput component to fix a UX issue where numeric config fields couldn't be cleared and retyped
  • Added signedFlexibleValueSchema for hitDiceBonus to support negative values (Fiendish Boon's -1)

How to test

  • Create a Hunter, select Keeper of the Wild Heart at level 3 → hit dice should show d10, max HP should increase by 5
  • Create an Oozeling Hunter → hit dice should show d10 (base d8 + 1 step)
  • Create an Oozeling Wild Heart Hunter → hit dice should show d12
  • Edit hit die size via "Edit Level & Hit Dice" → should set the final value as an override
  • Edit max HP in Character Configuration → should show effective value including bonuses
  • Catch Breath / Make Camp as an Oozeling Hunter → healing should use d10, not d8

Design notes

  • Hit die size modifications use the existing stat_bonus pattern with three new fields: hitDieSizeOverride (absolute, e.g. Wild Heart d10), hitDieSizeStep (relative, e.g. Oozeling +1 step), and maxHpBonus (e.g. Wild Heart +5)
  • Manual user edits to hit die size are stored as a sizeOverride on the character that takes highest priority, bypassing all feature bonuses
  • Manual user edits to max HP reverse-calculate the base value — this works cleanly because additive bonuses are always reversible
  • hitPoints.max can now be stored below 1 to support scenarios where a user manually sets effective max HP to 1 while feature bonuses exist (e.g. a curse). getMaxHp() enforces a floor of 1 on the effective value.

Tests

11 unit tests covering:

  • Feature combinations (Oozeling + Wild Heart = d12, each individually, etc.)
  • Max HP bonus (+5 from Impressive Form)
  • Hit dice quantity bonuses (Dwarf +2, Survivalist +1, Fiendish Boon -1)
  • Manual sizeOverride priority and restoration
  • Healing cap at computed max HP (applyHealing, performSafeRest)
  • Computed hit die size used in resting (performCatchBreath, performMakeCamp)
  • Effective max HP override to 1 with active bonuses (witch curse scenario)

sjlevin added 2 commits March 20, 2026 16:01
Previously, features like Keeper of the Wild Heart's Impressive Form (+5 max
HP, upgrade hit dice to d10) and Oozeling's Odd Constitution (increment hit
dice one step) had no mechanical effect — they were description-only with
empty traits arrays.

Schema changes:
- Add maxHpBonus, hitDieSizeOverride, hitDieSizeStep to stat bonus schema
- Add signedFlexibleValueSchema for hitDiceBonus to support negative values
- Add sizeOverride to hitDice schema for manual user overrides
- Allow hitPoints.max below 1 to support overrides with feature bonuses

Service layer:
- Extend getHitDice() with override priority, feature overrides, and step logic
- Add getMaxHp() computed method (min effective HP is always 1)
- Update applyHealing, performSafeRest, performCatchBreath, performMakeCamp
  to use computed hit die size and max HP

Data fixes:
- Hunter Keeper of the Wild Heart: +5 max HP, hit die override to d10
- Oozeling/Construct Odd Constitution: hit die +1 step
- Shadowmancer Fiendish Boon: -1 max hit dice

UI updates:
- All hit die size displays use computed value via getHitDice()
- All max HP displays and caps use computed value via getMaxHp()
- Hit dice edit form shows effective size with manual override support
- Character config shows effective max HP with transparent base conversion
- Add NumericInput component for commit-on-blur numeric field editing
- Feature traits display shows new bonus types

Includes 11 unit tests covering feature combinations, manual overrides,
healing caps, and rest mechanics.
@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

4 Skipped Deployments
Project Deployment Actions Updated (UTC)
nimble-discord Skipped Skipped Mar 20, 2026 11:28pm
nimble-portal Skipped Skipped Mar 20, 2026 11:28pm
nimble-sidekick-api Skipped Skipped Mar 20, 2026 11:28pm
nimble-vault Skipped Skipped Mar 20, 2026 11:28pm

Request Review

@vercel vercel Bot temporarily deployed to Preview – nimble-discord March 20, 2026 23:28 Inactive
@vercel vercel Bot temporarily deployed to Preview – nimble-sidekick-api March 20, 2026 23:28 Inactive
@vercel vercel Bot temporarily deployed to Preview – nimble-portal March 20, 2026 23:28 Inactive
@vercel vercel Bot temporarily deployed to Preview – nimble-vault March 20, 2026 23:28 Inactive
@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 20, 2026

@sjlevin is attempting to deploy a commit to the Martin's projects Team on Vercel.

A member of the Team first needs to authorize it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant