2026-09-25 · REIGN OF VALTHERIN

The Input System was discarding the keys

Automated walks that failed after a camera change turned out to have nothing to do with the camera. The Input System was throwing away the test's key events. Also today: real sun shadows for every character, four kinds of arrow with tracers, and measuring a face before calling it straight.

A day with one long debugging story, then a run of things you can see.

It was not the camera

After the camera was framed closer, the automated walks that cross each area in turn started stalling in most outdoor areas. A baseline run with the new camera files set aside walked clean, so the camera was blamed. It was not the cause.

The hero was running on stale keys. The walker's key releases were being thrown away part-way through every test, at the same point each time.

The Input System records the editor's real clock when it leaves edit mode and again when play mode is up, and in play mode it discards any key event stamped between the two. The test fixture runs its own input clock from zero, a sixtieth of a second a frame, and stamps its keys with that. Once a test had run for as many fake seconds as the editor had been open at the moment play mode started, every press and release was dropped until the fake clock passed the play-mode moment too.

That is about 16 to 21 seconds in a batch run, and hours in an open editor, which is why the walks were green in the editor and red in batch. It is also why the baseline run that looked innocent was only innocent by luck: it had happened to compile for longer before play mode came up.

The fixture now zeroes those two timestamps for each test and restores them afterwards. Six areas that stalled walk clean, and the camera tests went from 22 of 40 passing to 33 of 40 with no stalls.

Two further fixes came out of the same hunt:

  • A batch run renders into a squarer hidden window than any player has, so the camera fitted a narrower frame. One area scrolled eleven tiles where it should have scrolled four. The fixture now holds the camera at 16:9.
  • A stall now logs what the body touches, its state and speed, every input device and key, and the keyboard's last update against the input clock. That log is what found the clock.

Sun shadows from the real light

Characters now cast a shadow from the game's actual sun, so the angle moves with the time of day. Each character's current frame is laid flat on the ground, away from the sun. That covers the hero, villagers, enemies, bosses, the two companions, and worn armour and weapons.

  • It shears the frame rather than rotating it, so each pixel row stays a crisp row.
  • It uses the same 3.75 degree angle steps and length as the tree and prop shadows, and fades with cloud, night and indoors.
  • A stencil stops body, armour and weapon from darkening the same ground twice.
  • It is darker than the trees. The first captures looked too faint, so opacity is 0.85 against the trees' 0.70.

A debug menu jumps to dawn, noon, dusk or night and moves the hero beside the villagers or an enemy, so shadows can be captured at each. Ten tests cover it.

Arrows, and what they leave behind

Before today a bow in the hand swung like a sword and hit nothing at range.

Bows shoot now. The attack buttons loose one arrow from the active slot on the bow's strike frame. R1 is the quick shot and R2 the heavy. Holding R2 with the charge bar full looses a charged shot: faster, harder, piercing one more body, paid for from the charge bar and not from stamina. An empty slot clicks and says "Out of arrows."

arrowstatusprice, per 10
woodennone30
fireburn120
frostfrostbite120
lightningshock150

Each elemental arrow adds its element as a share of the shot's damage. Two arrow slots sit on the Equipment screen, and one button swaps between them.

Every arrow now has a tracer, including the Watchtower archers' arrows, which had no sprite at all before. The streak is one art pixel wide, drawn as pixel quads on the tile grid, and fades from white-hot to the arrow's own colour over 0.24 seconds. Wood is a warm white, fire orange-gold, frost icy blue, and lightning yellow with a one-pixel crackle.

One way to make every enemy sheet

Six enemies went in with redesigned art: the boar, the field wolf, the weald spider, the foot soldier, the Watchtower archer and the wolfrat. Each has its own clip for every attack, plus hurt, stagger and death, in eight facings.

The method matters more than the six. An enemy's hand-drawn sheet is the design, not the asset. The character is modelled and animated in three.js and baked to pixel art, and the drawn frames are never cut up or shrunk into sprites. Both approaches were put side by side, and the baked renders won. The cut-out scripts were dropped.

Straight heads, measured

The redrawn villagers went into the game, 19 in the morning and all 22 by evening, each rebuilt cell for cell against its old sheet at the new hero's pixel density. A note said some heads were crooked and some necks too thin from behind, so the head-to-body offset was measured on every front and back idle and walk frame instead of judged by eye.

Every offset is at most about one art pixel. The largest, 1.8 on one character, is her hat's flop. One character's "weird" look was his eyes set 7 pixels apart against a cast norm of 3 to 5, and they were moved in.

The new sheets only replace the old when every page of a character has a redrawn twin, so no character ever mixes old and new art. A test checks that all 19 keep every move, facing, pivot and on-screen size.

The edge treatment was borrowed from a commercial pixel-art pack that does not outline everything in black. Its sheets were measured and the targets copied: ink on the bottom edge of a figure 83 to 91% of the time, but only 22 to 50% on top, 32 to 54% on the left and 38 to 72% on the right. Lit edges soften to the material's own darkest tone and no new colours are added.

EditMode passes 582 of 582 at the start of the day and 608 of 608 by the end of it.

Smaller things

  • The length of a game day was tried at 24 minutes, 12, 20 and then 12 again, within a few commits. It is one constant, and every villager's walking pace and schedule reads it, so they all speed up and slow down together. It settled at 12.
  • A sword or spear hit on an enemy now plays a body punch under the slice, at 0.8 of the steel's volume. A heavy blow already layers a big finisher thud, so it does not get a second one.