Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog,
[0.0.21] - 2026-09-05
Added
- The potion hit-flash now also plays for a thrown rock, in a plain grey rather than either potion color (a blunt hit isn't a magic effect, so it shouldn't borrow a potion identity's color). The flash trigger in
throwItemAt()is now generic - any item can opt in with animpactColorin itsItemDefsentry, no new visual code needed.
Fixed
- Throwing a potion at a nearby creature showed a black rectangle around it instead of a clean glow. The hit-flash's billboard defaulted to casting a shadow (correct for sprite-textured billboards, whose
alphaTestshapes the shadow to the sprite), but the flash uses a custom shader that three.js's shadow pass can't read alpha from, so it was casting a full opaque square shadow from the torch light. The flash no longer casts a shadow at all, since it's a transient glow, not a solid object. - A level's item spawn (
Dungeon.generateItems()) could place two different item types (e.g. a rock and a potion) on the same tile, since each type rolled its spawn tiles from the full eligible pool independently instead of avoiding tiles an earlier type had already claimed. The map only stores one tile-type string per tile, so the second item to land there silently overwrote the first's map entry while both stayed in the item list - and rendering that tile could then resolve the wrong (mismatched-type) item, crashing withmaterial.transparent = trueon an undefined material (a colorless item's data read as if it were a colored potion, which has no plain fallback material). Item types now claim tiles from a shared pool so no two can ever collide.
[0.0.20] - 2026-09-03
Added
- A glowing ring flash when a thrown potion lands a hit, colored by whichever effect it turned out to be (warm gold for heal, sickly green for poison). Built as a small reusable shader rather than sprite art, since this project has no dedicated impact-effect artwork - any future effect (wand, scroll, ...) can trigger the same flash later with just its own color. Early pass, potions only for now - expect this to keep evolving as ranged weapons and equipment get built out.
[0.0.19] - 2026-09-03
Fixed
- Level 3 (the minotaur's maze) was spawning rats and spiders alongside the minotaur instead of being minotaur-only, and the minotaur was always placed at the stairs down to level 4 regardless of which staircase the player actually entered from. Arriving from level 4 (going back up) placed the player on the same tile as the minotaur - it can't attack while sharing a tile, so nothing seemed to happen, but stepping off that tile put the player adjacent to it for an unexpected hit. The minotaur is now the only creature on level 3, and always spawns at whichever staircase is opposite the one the player is currently entering from.
- Swapped the blue potion sprite for a lighter, higher-contrast one - the original was too dark to spot against a dim torch-lit floor.
[0.0.18] - 2026-09-03
Fixed
- The page could scroll on mobile Safari, breaking the "everything fits on one screen" layout. The root cause: the game canvas sized itself purely from its own width (a fixed 1:1 aspect ratio), with nothing accounting for how much vertical space the message log and control pad also needed - on any screen where those didn't leave enough room, the page overflowed. The canvas now sizes itself from whatever vertical space is actually left after the message log and controls claim theirs, shrinking to fit instead of overflowing, verified down to a viewport shorter than any real phone.
[0.0.17] - 2026-09-03
Added
- A test suite (
npm test), covering the plain-logic modules (creatureAI.js,utils.js,items.js,effects.js) - including regression tests for the flee-movement and treasure-chest-patrol bugs fixed earlier this cycle. Uses Node's built-in test runner rather than adding a test framework dependency.
Changed
- A few modules (
game.js,messages.js,ui.js) grabbed specific DOM elements eagerly at module-load time instead of on first use; converted those to getters so importing them (directly or transitively) no longer requires a browser/DOM environment - this is what made the test suite above possible without a jsdom-style dependency.
[0.0.16] - 2026-09-03
Added
- Blue potion, and a random potion-identity system: each color (red, blue) is secretly assigned a random effect (heal or poison) at the start of every game, so the same color can mean something different from one run to the next. Drinking or throwing a potion reveals what it does.
Changed
- Rewrote the item system to be data-driven (
src/items.js) instead of hand-wiring a new file's worth of code per item. Adding an item is now a single-file edit: a sprite rect, how many spawn per dungeon level (and whether that count rises or falls with depth), and what its inventory actions do - rock and torch have been ported onto this system alongside the new potions, with identical spawn odds and behavior to before. - Item spawn counts now scale with dungeon depth per item (independently increasing or decreasing), rather than each item type having its own hardcoded formula.
Fixed
- A thrown rock that missed and landed nearby was added directly to the scene instead of the items group, bypassing the group-based cleanup every other item mesh goes through.
- A creature that survived an attack and dropped to low health would flee into a permanent stand-still instead of actually moving away, due to a pre-existing bug in the flee-movement logic that had never been reachable in real gameplay until a fix earlier this same release cycle made it so.
[0.0.15] - 2026-09-03
Changed
- Updated dependencies:
vite6.3.1 -> 6.4.3,terser-> 5.51.2,marked-> 18.0.11,@tweenjs/tween.js20.0.3 -> 23.1.3,three0.176.0 -> 0.185.1. Resolved 5 known high-severity advisories (nanoid, picomatch, postcss, rollup, vite) that came in transitively through vite;npm auditnow reports 0 vulnerabilities.
Fixed
- Restarting the game threw a WebGL
INVALID_OPERATION: texImage3D: FLIP_Y or PREMULTIPLY_ALPHA isn't allowed for uploading 3D textureserror (surfaced by the three.js update) because a brand newWebGLRenderer/WebGL context was being created on the same canvas on every restart, inheriting leftover pixel-store state from the previous session's texture uploads. The renderer is now created once and reused for the app's lifetime instead of being disposed and recreated. - Replaced the now-deprecated
THREE.PCFSoftShadowMapwithTHREE.PCFShadowMap. - The idle weapon-bob animation could visibly glitch/flash between its two extremes when it ran at the same time as the walk or attack weapon animations, since all three independently tweened the same
weaponOverlay.positionwith nothing coordinating between them. Replaced the infinite bob Tween with a stateless per-frame sine offset (the same pattern already used for creature idle bounce) that's simply gated off while a walk/attack animation is in flight, rather than trying to pause/resume a competing Tween.
[0.0.14] - 2026-09-03
Fixed
- Killing a creature could dispose its type's shared texture (
isSharedwas lost when the material was cloned), corrupting the appearance of every other creature of that type for the rest of the run. gameOver()only cleared top-level scene children, missing meshes nested in the dungeon/creature/item/effect groups, and skipped roughly every other item due to mutating the children array while iterating it.- The
resizelistener was re-added on every restart with nothing to remove the old one, stacking duplicate listeners over a play session. - Spiders and ghasts never used their "smartAggressive" chase/flee behavior - the switch in
Creature.act()was missing that case entirely. - Tapping a water tile did nothing; the tap hit-test map had no entry for it.
- A leftover copy-paste reference (
environmentinstead ofdungeon) in the tap hit-test's fallback path. - Sounds meant to play at the player's position never actually got positioned there.
- The lich's "patrol around the chest" behavior was unreachable dead code, and its fallback move call used absolute coordinates instead of the relative offset
tryMove()expects. - Tap/click handlers could be registered more than once if the game was restarted before a full tap had completed.
- Previously-seen water tiles rendered the wrong color on the minimap due to an invalid CSS color string.
- CSS assets under
public/were referenced with an incorrect/public/prefix, which doesn't match how Vite serves them.
[0.0.13] - 2025-06-10
Added
- You can throw any inventory item if it has the proper internal flags. Potions for example.
- Added modal system to handle what you throw.
Changed
- Update health and light portions of UI.
[0.0.12] - 2025-06-05
Added
- Added a transition overlay when you change levels with messaging
- Added grouping of items in UI, now you see item and stack size
Changed
- Updated how to play section on About page
- Updated manifest.json a little, I really need to make icons...
- Moved weapon overlay a little, looks better?
- Updated Use message on torch and potion
Removed
- General cleanup, removed some refactored code, removed nes.min.css which I stopped using a while ago
[0.0.11] - 2025-05-24
Added
- Idle bounce on creatures
[0.0.10] - 2025-05-22
Added
- Death animation for creatures.
Changed
- moved inventory back to B button, added B button back. Its just too easy to hit vs making the user reach for the top of the screen.
[0.0.9] - 2025-05-22
Added
- Better? player UI for health, and for certain light since we didnt display that info in any way, and a new way to open the inventory with a clearly labeled button. This new player ui sits opposite of the minimap.
Changed
- Slight tweaking of the control pad since we dropped a button.
- Fixed issue with restarting and weapon overlay not getting cleaned up causing duplicate
Removed
- Removed the B button from control pad, as its only function was to open the inventory and has been replaced.
[0.0.8] - 2025-05-21
Changed
- Tweaked holding weapon visuals and animations, added an idle bounce
- Refactored parts of the main Game for better name spacing
- Changed from rot simple scheduler to speed based
- Manual chunking vendor packages into seperate name space
Added
- Creatures now drop down into water like the player, poor rats look like they are drowning...
- Added rot speed scheduler, moving in water is half the speed of land for player and current creatures.
[0.0.7] - 2025-05-21
Added
- added first person holding weapon overlay and animate it on attack
[0.0.6] - 2025-05-17
Changed
- Fixed issue with materials past level 1, already live, criticial bug
- Reverted creatures back to no diagonal movement, everyone moves the same for now
- Moved this file to public, linked from homepage and about
[0.0.5] - 2025-05-16
Changed
- Moved cave floorWater to instancedmeshes
- Hopefully fixed issue with lingering meshes after pickUp
- Other cleanup regarding mesh disposal in disposeMesh
Removed
- Removed unused code in MeshUtils from refactor
[0.0.4] - 2025-05-15
Added
- Stepping into water lowers the camera, stepping out moves it back up, moving in water causes splashing footsteps
Changed
- Lowered water height
- Really fixed the lich this time...
[0.0.3] - 2025-05-14
Added
- Basic prefab functionality. First prefab is in caves.
[0.0.2] - 2025-05-14
Changed
- Changed game name to proper name. Dunil's Hold is born.
- Changed Message log css to teal for latest message, gray for past messages.
[0.0.1] - 2025-05-13
Added
- Added Changelog