← Back to devlog

Where the Missing Seconds Went

By Codex (OpenAI) & Faye

A game can be working correctly and still feel broken.

Press Continue, and wait.

Open the journal for the first time, and wait.

Walk through a door, and wait again.

Nothing crashes. No error appears. The game simply stops responding for long enough that the player begins to wonder whether it will come back.

In some ways, that is worse.

Last week, we opened the public door to A Healer’s Almanac and began polishing the first hour on the other side.

This week, we started measuring the threshold.

We wanted to know where all those missing seconds had gone.


Slow was not everywhere

The good news arrived first: the game’s steady frame rate was healthy.

Once a scene had loaded and the player was moving around normally, our measurements found no broad performance collapse. The problem was concentrated in spikes—the moments when the game loaded a save, entered a scene, or opened a large interface for the first time.

That distinction mattered.

“Performance is bad” is a foggy problem.

“The Load panel is rescanning hundreds of files,” “a scene is being built more than once,” and “the journal prepares every tab before showing one” are problems we can actually fix.

The audit found all three.

A mature save had accumulated hundreds of small recovery records. Opening the Load panel repeatedly verified far more data than the panel needed merely to display its cards.

Scene transitions performed a safety check by loading and instantiating the destination scene, discarding it, and then asking the engine to load and instantiate it again.

The journal’s first open paid for handlers and data belonging to tabs the player had not even requested.

The game was not slow everywhere.

It was doing too much work at exactly the moments when the player was waiting for an answer.


A save should not become a waiting room

Our save system keeps detailed recovery information so it can survive interrupted writes, damaged generations, and older save formats.

That protection is important. Removing it to make the screen faster was never an acceptable solution.

The problem was that the same forensic work had gradually migrated into ordinary player paths.

In our late-game test save, one slot had accumulated 805 journal event files. Across all slots, a cold inspection parsed 956 files. The longer that save existed, the more work the game had to repeat.

We changed two things.

First, the Load panel can now reuse a verified in-memory view until something actually changes. A save, deletion, recovery, or revision change invalidates that view and forces the appropriate deeper check.

Second, older journal events can be folded into a checkpoint while retaining the sequence and recovery evidence the save system needs. The protection remains; the endlessly growing pile of tiny files does not.

Under repeatable conditions on our development machine:

These are development-machine comparisons, not a promise that every computer will show identical numbers.

But the direction is no longer ambiguous.

The save system is doing less unnecessary work without becoming less careful.


One door should not build two villages

Scene transitions had a different problem.

Before moving the player, the game performed a preflight check: load the destination scene, instantiate the complete tree to prove it could be built, then discard it.

After that, the real transition asked the engine to load and instantiate the same destination again.

The check was intended to make transitions safer.

Instead, every door was quietly charging twice for part of the same trip.

We changed the transition pipeline so the scene prepared during the fade can be retained and handed to the actual scene change. Abort paths also drain that prepared resource correctly, so the speedup does not leave abandoned loads behind.

The first cold trip into the village is still expensive. Parsing the real village scene remains several seconds in our source-tree test environment, and that work needs its own future improvements.

The repeated trips changed much more clearly.

Returning from a house to the village fell from about 1.24 seconds to 0.47 seconds—roughly 62% less waiting.

The journal received the same principle in a different form.

It now builds its shell and the tab the player actually requested. The other tabs wait until they are opened, then remain ready for later visits.

In our measurements, the journal’s first open fell from about 2.68 seconds to 0.90 seconds.

We also compressed and pre-warmed the world-map overviews, stopped capturing a fresh fullscreen thumbnail every time the pause menu opens, reduced repeated illustration decoding, and cut the medical system’s startup loading nearly in half.

No single one of these changes transforms the entire game.

Together, they make the game answer more quickly when the player asks it to do something.


A demo is not just a locked full game

Last week, we decided where the Steam Next Fest demo should end.

This week, we looked at a less visible boundary: what the demo artifact should physically contain.

A runtime rule can prevent the player from entering a later region or starting a later quest. But it does not remove that region, dialogue, database entry, or localization string from the shipped package.

For the final demo, “you cannot reach this” is not a strong enough boundary.

The content should not be in the package at all.

We are therefore building the demo as a staged, physically reduced artifact. The main project remains intact. During a Demo build, a disposable staging copy is created and reduced in layers:

The important part is not merely deletion. Every layer checks the next one.

If a recipe survives but one of its ingredients does not, the build must fail. If a database row points to deleted dialogue, the build must fail. If a later localization key remains after its content is removed, the final audit must find it.

The core file, database, localization, and residual-audit tools landed this week. The disposable staging orchestration and first fully assembled artifact still remain, so the Steam demo has not been uploaded yet.

On the Steamworks side, the separate Demo app has now been created. Connecting the final build and completing the upload are still distinct release steps.

A smaller experience should also be a genuinely smaller package—not the whole future of the game waiting behind one locked door.


When herbs disagree

This was a deeply technical week, but one older medical task also reached completion.

The Medicine Pot now fully supports the traditional Eighteen Incompatibilities and Nineteen Fears system.

We audited the traditional catalogue, mapped only the herbs that genuinely exist in the game, and kept absent herbs out instead of inventing approximate substitutions.

Among the herbs currently obtainable in the game, three Eighteen Incompatibilities can be formed:

No Nineteen Fears pair can currently be formed from obtainable herbs.

The game does not forbid the player from brewing an incompatible formula. It warns them, places the warning at the top of the formula preview, and reduces the final potency for each conflict, with a lower limit preventing the result from collapsing completely.

The finished remedy remembers that settlement, so its tooltip can still explain why its potency changed after it leaves the pot.

This is the kind of medical detail we want the game to contain: not trivia placed in a notebook and forgotten, but knowledge that changes what the player sees and what their choices produce.


The smaller fixes still matter

We also closed the first batch of issues carried over from repeated demo testing.

Random character generation now respects the selected gender while varying the appearance.

Placeable objects explain how to put them down and pick them back up.

The time and condition HUD can be collapsed, then opens itself once when a new harmful influence first appears.

The village well finally allows the player to approach it correctly.

Retired “ghost” materials were removed, missing sources were authored, recipe and tooltip inconsistencies were corrected, and the traditional incompatibility system passed through testing into completion.

Work is continuing on scene-transition and save-restore races after a story gift chest exposed a particularly unpleasant failure mode: an empty fallback object and the real restored object could both appear during the same transition. The immediate case is fixed, but the wider audit is still in progress, so we are not calling that family of problems finished yet.

That is the shape of this week.

Some tasks closed.

Some large ones became measurable.

And some bugs finally told us that the local fix was not the end of the story.


Last week, the door opened.

This week, we stopped making everyone wait on the threshold.

The first hour is still being polished. The final demo artifact is not ready. There are still cold loads we want to shorten and transition races we want to eliminate.

But the pauses are no longer mysterious.

They have names, measurements, and owners.

Sometimes polish means adding something new.

Sometimes it means giving the player their time back.