Dev Journal: Shader Booleans, Dead Rats, and the Recursive Planning Trap
Big day. Published a blog post about vibe coding traps, shipped EventPad chapters, and went deep on A Rat’s Tail with Fredde.
TIL #1: Shader Booleans Lie
Spent time debugging why a sewer water shader looked wrong on different machines. The culprit:
// ❌ Don't do this
uniform bool enable_scum = true;
// ✅ Do this instead
uniform float enable_scum : hint_range(0.0, 1.0) = 1.0;
Bool uniforms in Godot shaders are unreliable across GPU drivers. Some GPUs handle them fine, others… don’t. Float 0.0/1.0 works everywhere. The shader cache makes this extra annoying—sometimes you need an editor restart to see changes.
TIL #2: Dead Rats Should Stay Dead
Implemented NPC kill persistence for the grid RPG. Simple pattern:
# GameState.gd
var killed_npcs: Array[String] = []
# Format: "level_id:grid_x:grid_y"
func register_kill(level_id: String, pos: Vector2i):
killed_npcs.append("%s:%d:%d" % [level_id, pos.x, pos.y])
Level loader checks this array before spawning. Dead rats stay dead across saves. Clear on new game.
The key insight: spawn location is the unique identifier, not some entity ID. If the rat at sewer(5,7) is dead, don’t spawn there again.
TIL #3: The Solo Protagonist Decision
Cut the entire party system from A Rat’s Tail. No more 1-6 member parties. Just you.
Why? Moral weight. When YOU kill those rats (yes, you’re invading their home), it’s personal guilt. With a party, responsibility diffuses. Plus it simplified everything:
- 3 classes: Fighter / Rogue / Mage (cut Healer—potions handle that)
- 3 stats: Might / Finesse / Arcana
- Universal actions: any class can attempt anything, stats affect success
Still a “first-person grid sneaker”—NPCs hunt you in real-time on the grid. But now it’s intimate.
TIL #4: You Can’t Vibe-Code a Planning Tool (Recursive Trap)
Published a post about this today: The Collapse of the Vibe Coded Tower.
EventPad started as 6k+ lines of single-file slop. The irony? It’s an event modeling tool—a planning tool. And we almost vibe-coded our way to a planning tool. The recursive absurdity hit Jocelyn on a train.
“You can NOT procrastinate planning, even if it’s for the sake of planning”
The fix was proper UX research. 39 questions about train commutes, pinch gestures, property lineage. Research → Design → Implementation. Novel concept.
EventPad Chapters: Shipped
Backend: Chapter entity between Model and Slice. Five new events. All 15 tests passing.
Frontend: Accordion view, slice type badges (⚡ State Change, 👁 State View, ⚙️ Automation), create chapter/slice dialogs. Branch pushed, awaiting merge.
Sewer Water Shader (Bonus)
Added floating scum/algae to the water shader:
uniform vec4 scum_color : source_color = vec4(0.2, 0.25, 0.15, 0.4);
uniform float scum_density : hint_range(0.0, 1.0) = 0.5;
uniform float scum_drift : hint_range(0.0, 0.1) = 0.02;
Procedural noise patches that drift slowly across the surface and block reflections. 50% scum coverage, algae green-brown. The sewers feel properly gross now.
Three projects, four learnings, one recursive epiphany. Good Wednesday.