Design documents · Area redesign

The rules every area follows

The period rule (5th century BC, nothing later), how the builders and tests work, and what to watch for.

The period rule (owner, 2026-10-28)

The game is set in the 5th century BCE, between 447 BC and 406 BC (Periclean Athens and Eleusis). All art, buildings, ships, props, clothes, weapons, plants and names must fit.

  • Already caught and removed: half-timbered houses, clinker longships, iron-hooped barrels, rectangular hay bales, glass lanterns, Philon's porch (c. 310 BC), a Roman propylon, the sarissa.
  • Still to catch: see each area's list. When in doubt, check Mylonas 1961 (Eleusis), Thucydides, Plutarch, Pausanias, Camp (Athens and Attica), Morrison and Coates (triremes).
  • Alphabet: Athenian inscriptions use the old Attic alphabet until 403/2 BC.
  • Recorded in: docs/GREEK-AUTHENTICITY.md (repo), the NAS notes, the area PDFs, Claude memory (embers-period-447-406bc.md).

Standing rules (from earlier in the project)

  • NAS paths only for project docs; Unity project is at D:\Dev\embers-of-olympus-unity (git, no remote). Never push.
  • Log every change in CHANGELOG.md with an "Unreal:" line; log work in Video Notes\notes-from-claude.md.
  • Stage only Assets\_Project, README.md, CHANGELOG.md, docs. Commit trailer: Co-Authored-By: Claude Sonnet 5.5 <(email removed)>.
  • Free-for-commercial assets are fine and must be logged in art-work\embers-of-olympus\free-assets-credits.md.
  • Greek names must be historically correct; display text only (ids and saves never change).
  • Blender 5.2 may be used freely (background scripts). Local AI: ComfyUI (port 8188 now; was 8189) on the RX 7900 XT.

How the town is built (so the next session does not have to re-learn it)

  • The scene is rebuilt from code: HubBuilder.Create() (in Assets/_Project/Code/Editor). Source of truth is the builders, never the saved scene.
  • Rebuild without the editor open: a temporary editor class TmpRebuild.Run() calling HubBuilder.Create(), run with -batchmode -quit -executeMethod EmbersOfOlympus.EditorTools.TmpRebuild.Run, then delete it.
  • Tests: -runTests -testPlatform PlayMode|EditMode -testResults x.xml -logFile x.log. Counts on 2026-10-30: 29 PlayMode, 278 EditMode, all green. The first PlayMode run after a code change can come back short (27) because the new test assembly was not built yet: run it again before believing a count.
  • Build: EmbersOfOlympus.EditorTools.BuildTools.BuildWindowsRelease writes to D:\Dev\Builds\EmbersOfOlympus\<date_time>\.
  • Screenshots without a player: the temporary PlayMode probe tools/ZoneProbe.cs (env vars PROBE_SCENE, PROBE_DIR, PROBE_VIEWS as name:px,py,pz:lx,ly,lz;...). Copy it into Tests/PlayMode/World/, run with -testFilter ZoneProbe, delete it after. Camera framing is unreliable for low or close views; the overview -60,40,-40:10,2,20 always works.
  • Post-build moves (order in HubBuilder.Create): CompactEast() slides everything east of x 28.5 by -9 m; CompactSouth() slides the south by +8 m; MarketWest() slides the stalls near the acropolis stair 10 m west; Crowd.Build() scatters piles and stalls last in final coordinates.
  • Key constants: HubBuilder.EastWallX = 33, SouthSlide = 8, TemplePosition = (20.5, 22.5), Acropolis.Shift = (-17.5, -76), the acropolis stair at z -11.5 to 10.5 on the east wall.

Gotchas learned the hard way

  • Normals: a mesh whose two faces share vertices gets zero normals (NaN, a black triangle that blooms to a white blob). Use separate vertices and set normals by hand. (This caused the "white blob" bug in the house gables.)
  • Bloom: bloom.clamp = 8 in DarkMood stops any single bright pixel becoming a screen-filling blob. Keep it.
  • Particles: every particle renderer in the town is capped (maxParticleSize 0.12; the test Smoke_CannotFillTheScreen checks all of them). Particle velocity curves must all use the same mode or Unity logs an error and tests fail.
  • Solid-props test: every visible prop must have a collider unless it is under an exempt name (Surroundings*, Awning, Rocking, Trireme, GateLintel, ...). Flat decals live in Surroundings_* groups.
  • Walk tests hold the layout in place: the yard lap, the gate walk, the pier walks, the quay and wall tests, the acropolis stair test, the three Telesterion tests. Crowd.Routes and Crowd.Keep list the same routes so the scatter keeps them clear. When you move a building, re-run them.
  • Shell quoting: long Python or C# edits via heredoc inside bash -c can break on quotes; write the script with the file tool and run it.
  • The AI image tools cannot draw a Greek trireme (always a Viking ship) and add gibberish lettering to temples. Use in-engine renders or hand-built shapes.
  • TRELLIS.2 / Hunyuan3D: Hunyuan3D is not usable here (its licence excludes the EU, UK and South Korea; the owner is in Greece). TRELLIS.2 (MIT) makes torn, hollow hulls from boat pictures; Qwen-Image-Edit-2511 (Apache) is excellent for cleaning reference pictures.

Open decisions for the owner (carried from the PDFs)

  1. Historically strict or historically grounded but dramatic? (the plan assumes the second)
  2. The tholos: remove or keep as a clearly invented shrine?
  3. First Furrow: restyle, or replace with Bouzyges, the first ploughman?
  4. Threshold Warden: Hekate Kleidouchos / doorway guardian, or a Cerberus-like statue?
  5. Boss body: a bronze krater (a mechanism, as the canon wants) or a more figurative presence?
  6. Zone A mood: keep the grey rationed look, or golden barley under a grey sky?
  7. The older open items: generated sounds never auditioned; Valor/Favor and attribute names; Long Doru vs Sarissa; visuals not audited for historical shape (helmet crests, shield devices, bows).

Gotchas added 2026-10-29/30

  • Do not lerp a negative into Mathf.Pow: Pow(sin(pi t), 0.9) at t=1 is NaN, the mesh bounds were zero and the whole cypress was invisible. When a built mesh does not show, log its renderer bounds.
  • Primitive colliders: a cylinder primitive squashed flat keeps a capsule collider (an invisible 4 m sphere); remove it and use a MeshCollider or a box.
  • Ground rays and the boss's own box: skip colliders under the boss (IsChildOf(transform)) and creatures when finding floor, or telegraph rings float.
  • Hit flash needs a renderer: a component that throws inside Health.ApplyDamage stops Died being raised.
  • Holders and _local: in the builders, children of a rotated holder must be placed by local position; a plain group at the origin takes world positions.
  • Test counts and waypoint names: WaypointOrderTests expects the display names (now Anthrakeion, Katabasis, Gates of Plouton).
  • -startscene <scene> launches New Game in any scene in the build (RunState.StartSceneOverride). Every build folder has Play_*_Monitor3.bat launchers (the top screens 1 and 2 are rotated 180 degrees and reverse the mouse; use 3 or 4).
  • Waypoint doors are built by WaypointPadArt (the marble doorway), not by the scene builders; the town portal you cast keeps its vortex-in-a-rune-ring look.
  • Local AI: ComfyUI started by hand needs --extra-model-paths-config "%APPDATA%\Comfy Desktop\instance-model-paths\inst-1792911866490.yaml" and the venv python at ComfyUI\ComfyUI\.venv\Scripts\python.exe, --cuda-device 1, port 8188; Flux Schnell makes good concept mockups (about 40 s each). OpenArt had 8 credits left on 2026-10-29 (every image model costs 10 or more). The Ollama coder model at the local network invents Unity API methods: use it only for boilerplate.
  • Probe screenshots: ZoneProbe's camera inside a prop shows a flat colour; step back and up. Copy the probe test in, run it, delete it (and any Tmp* editor helpers and TMP_* scenes).

All design documents