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.