How Hollow Wake works
Skills, monsters, items, and passive bonuses are defined as data that a shared game engine reads. This makes it easier to combine familiar mechanics in new ways and keep their rules consistent.
Curious about how damage bonuses stack, how minions use skills, or where to find a mechanic in the source? This page covers the basics. For a look at what you can play, start with the game overview.
How your stat bonuses stack
The modifier system combines bonuses in a set order. Flat values add to the base. Increased percentages add together. Each more modifier multiplies the result. An override, when present, replaces that result. These rules apply to bonuses from equipment, passives, and enemy traits.
flat
Adds to the base value. +35 Maximum Life
increased
Adds together with other increased bonuses. +47% increased melee damage
more
Multiplies separately from other more bonuses. 25% more damage
override
Sets a fixed result instead of the calculated value.
Tags determine which bonuses apply. For example, 10% increased damage [melee] improves a melee attack but does not improve a spell unless it also qualifies as melee.
Players and enemies share combat rules
Players, enemies, and minions use the same skill system: World.useSkill(). Their stats and skill choices differ, but attacks use common rules for targeting, damage, and effects. This also lets summoned creatures use skills from the monster roster.
Build with the gems you find
Find active skills and support gems as loot, spend essence to improve them, and fuse duplicates into higher-rarity skill gems at the Font. Branching skill trees and compatible supports let you specialize a skill, while character levels grant points for the shared passive tree.
Reuse mechanics to add content
Most content starts with an entry under src/data/. A new skill can combine existing attack types and effects. A new monster can reuse those skills with a different set of behaviors. New mechanics still need engine support.
Where it all lives
One engine, content as data, a Canvas 2D renderer, and an Electron shell around it.
- world.ts
- stats.ts
- damage.ts
- actor.ts
- ai · brain
- levelgen
- skills.ts
- monsters.ts
- passives.ts
- uniques.ts
- tilesets.ts
- vis/materials
- doodad painters
- light layer
- Event definitions and progression
- arena · builds
- metric taps
- ui panels
- meta / saves
- launcher
Entry point: index.html → src/main.ts. The working conventions and a deeper subsystem tour live in CLAUDE.md and the docs.
Testing a new build
Type checks and regression probes catch many errors before a change lands. Other checks run combat scenarios, generate maps, and measure frame times in the desktop game. Playtesting is still essential for finding awkward controls, unreadable fights, and balance problems.
npm run simCompares skills and builds at matched investment, checks support interactions, and measures rewards and item drops.
npm run perfRuns the desktop game and measures frame times across different environments, using town as a baseline.
npm run genqaGenerates maps across the biome and layout roster, checking that routes, doors, and required destinations remain valid.
npm run eventqaChecks world event definitions, saved state, and ownership rules against the event tools used during development.
Read it, run it, extend it
Read the code, try a local change, or investigate the monster that ended your last run. The repository is available under the PolyForm Noncommercial license; see the repository license for its terms.