Moves all resources to Nauvis. Removes other planets.
Mods introducing new content into the game.
Version: 0.1.17 Date: 2026-09-XX Changes:
Version: 0.1.16
Date: 2026-10-13
Changes:
- eon-nauvis2-clone: the dummy primary surface (nauvis) is now shrunk to
a 32x32-tile single-chunk stub at runtime, the same trick biter-battles applies to its
default surface (map_gen_settings width/height = 32 + delete every
chunk), so the swap-staging surface costs nothing to exist, generate or
reset. The data stage cannot do this -- the engine clamps a planet's
map_gen_settings size up to the 2,000,000 maximum (probe-verified), so
the shrink lives in control.lua (on_init, on_configuration_changed for
old saves, on_surface_cleared for in-place resets) and is saved with
the game. Only when eon-nauvis2-clone is on; without it nauvis IS the
map.
- eon-nauvis2-clone: a player who died on a space platform respawned on
the dummy primary surface (the engine respawns platform deaths on the
force's default spawn surface, which with the clone live is the 32x32
staging stub) instead of the round. on_player_changed_surface now
catches the ghost before it respawns and teleports it to the clone's
round surface at the force spawn there -- the same event/condition pair
any-planet-start applies to its multi-planet starts. Only when
eon-nauvis2-clone is on; without it the primary IS the map.
- New pistol-start enemy tier: tiny pentapods (tiny-wriggler 15 HP / 1.5+1.5
dmg, tiny-strafer 75 HP / 25.2 explosion, tiny-stomper 150 HP / 7 stomp,
2.7-tile radius), built from space-age's make_wriggler/make_strafer/
make_stomper factories reusing small-pentapod graphics and icons. They
own the 0.0-0.4 evolution band on both gleba-spawner and
gleba-spawner-small (small pushed to 0.2, medium to 0.3 so tier onset stays
in-order tiny→small→medium→big; tiny appended after big so the
big tier keeps indices [7,8,9] and coexists with behemoth-enemies
regardless of load order), with gleba-spawner-small capped at 3 owned
units so near-spawn wriggler nests can swarm at pistol start. Spores
-> pollution absorptions auto-apply via pollution.lua. Gated by the
`eon-tiny-pentapods` startup setting (default on); disabling removes the tiny
tier and reverts the small/medium spawn windows to vanilla. Adds locale keys for
all tiny pentapod entities (wriggler/strafer/stomper, premature, corpses, shell)
so they display proper names in Factoriopedia instead of raw prototype ids. Band
names use the canonical wriggler-pentapod spelling (matching space-age's
make_wriggler prefix) so set_spawn_band lookups resolve correctly.
Version: 0.1.15
Date: 2026-10-07
Changes:
- eon-nauvis2-clone: the rocket silo refused to launch on the clone
("nauvis2 is not unlocked") -- the engine only starts the vanilla
"nauvis" unlocked per force, and there is no planet prototype flag for
it -- every space-platform stop read "inaccessible from current
position" because the space-connections still started at the dummy
nauvis while platforms orbit the clone, and the dummy nauvis itself
showed up as a droppable planet while the restored space-locations
stayed locked forever (their discovery technologies are hidden). The
solar system unlock state is now fixed for every force at game start /
save upgrade / force creation, and again after any force.reset() (which
wipes script-set unlock state, probe-verified; handled via
on_force_reset so scenario resets need no cooperation): nauvis2 and the
restored vulcanus/gleba/fulgora/aquilo + solar-system-edge are
unlocked, the dummy nauvis is locked (control.lua), and every
space-connection that touched nauvis is rewired onto nauvis2 (data
stage, both eon-restore-space-locations modes).
Version: 0.1.14
Date: 2026-09-XX
Changes:
- eon-nauvis2-clone (off): the dummy original nauvis planet is now stripped
to a vanilla default map (its map_gen_settings are nilled AFTER the clone
deepcopy takes the merged map). The primary surface only exists as a swap
staging area, so generating the full merged program there is wasted cost;
world creation safely falls back to the engine default map when the
settings are absent (probe-verified 2.0.77: --create succeeds, surface 1
tile = grass-1, planet still associated). The live cloned surface is
unaffected -- the deepcopy already carried the merged settings.
- New startup setting eon-restore-space-locations (on by default): instead of
deleting Vulcanus, Fulgora, Gleba and Aquilo, they come back as unlandable
SPACE LOCATIONS -- the same prototype as the solar system edge and the
shattered planet. The vanilla trip graph is restored (nauvis ->
vulcanus/gleba/fulgora -> aquilo -> solar-system-edge, with every planet's
asteroid field), so the first voyage is the normal easy kind instead of the
old straight nauvis->edge slog (edge-grade asteroids from day one), while no
surface exists anywhere but Nauvis so landing is impossible everywhere else
and play stays on Nauvis. The planet prototypes are deleted in the on state
(less data loaded; nothing but the discovery/removal machinery referenced
them); the off state keeps the old behavior (only Nauvis, solo trip to the
edge, aquilo-solar-system-edge.from = nauvis). Interacts with
eon-nauvis2-clone: the clone's edge rewire is skipped while the setting is
on, so the restored progression wins.
- Territory state is stored PER SURFACE (storage keyed by surface.name), not in one
shared marker table: a reset that replaces the map (clear in place, or a fresh
surface run alongside the old one) now gets clean state per surface, and an old
surface that survives a round keeps its own. A surface is "the map" when ITS OWN
map_gen_settings carry the merged map (the vulcanus_volcanism autoplace control),
planet or no planet -- so a second surface created to pre-generate the next map
in the background is claimed during pre-generation, and a pre-generated chunk
never re-fires on_chunk_generated, so that is the only timing that works. Note:
the PRIMARY surface (index 1, nauvis) is never deletable (LuaSurface.deletable is
false, hardcoded in the engine, probe-verified), so the planet can never lose its
surface and associate_surface can never move it to a runtime surface; the
deleted-surface path exists for created surfaces only. State
is cleared per surface on on_surface_cleared and on_pre_surface_deleted (the old
global wipe is gone). Old saves' single marker table is hoisted under the
surface name on first use, so claims survive an upgrade.
- New startup setting eon-nauvis2-clone (off by default): adds a second planet,
nauvis2, an exact deep-copied clone of the merged Nauvis, for scenario
map-swaps. The primary surface can never be deleted (see above), so the only
legal swap is to run the game on the clone: LuaPlanet::create_surface
materialises its surface (which IS deletable), the mod claims it through the
same settings-based identity (is_merged_map), and the scenario can delete and
re-create it freely. The clone is deep-copied in data-final-fixes AFTER the
whole map merge, so it carries identical map_gen_settings; the
aquilo-solar-system-edge space connection is rewired to point at it, the
original nauvis planet is hidden (it is the dummy), and every
default_import_location is swept onto the clone (remove-planets.lua had
pointed them at nauvis). Off by default: vanilla freeplay games keep a single
Nauvis.
- Fix: quantum-processor could not be crafted on Nauvis. Its surface condition is
a max only (pressure <= 600, Aquilo's value; Nauvis is 1000), and the rewrite
only relaxed conditions that carry a positive minimum, so the ceiling survived
and Nauvis failed it. Max-only conditions are now dropped too; the
min = 0 / max = 0 platform-exclusive shape (crusher, thruster, space-science-pack,
...) is untouched, so space platform restrictions stay exactly as they were.
- A BIG VOLCANO CARRIES TWO GUARDS. The claim is cut in two with one straight cut
through the cone's own centre -- a wedge of some fraction of the disc and the
rest of it -- and each piece becomes its own territory with its own patrol loop
and its own demolisher, so a big volcano is walked by a big guard and a medium
one at the same time. Why a cut through the centre: each piece then contains the
apex, so both guards stand on the middle of the volcano rather than one of them
patrolling a rim fragment. Why ONE cut and not two: three pieces of a circle are
~120 degree sectors, whose largest inscribed circle is 0.16 of the disc against
0.41 for a quadrant -- the angles get too sharp to carry a guard's body.
- The cut is clamped to a 90-180 degree wedge (a quarter to a half of the disc);
the other side is the remainder, since two pieces of a disc cut through its centre
cannot both be halves without a third piece between them. What the clamp costs is
the size mix: medium+big becomes a narrow band of the largest cones rather than
the common case, and sliver slices (which used to carry a guard that walked a pin)
are gone.
- The two guards are ONE SIZE STEP apart (small+medium, medium+big, and
big+behemoth with a modded fourth rung), never small+big. The sizes are not
chosen here: a slice with a fraction f of the area has a size fraction of
sqrt(f) times the cone's, and the cut is the one that lands the two sides on
adjacent rungs of the existing ladder (volcano-demolisher.lua), taken from the
middle of the range of cuts that qualify rather than off one edge of it. A cone
that no cut can do is left WHOLE, and says so in the log with the reason --
usually that it already carries the smallest guard, or that it is too small to
cut. On the vanilla ladder that leaves mostly small+medium and medium+big only
on the very largest cones: a cone sitting just above a tier boundary is already
one rung from the one below, so halving it drops it two.
- The two guards of one volcano no longer meet in the middle of it. Wedges closed at
the apex put both patrol loops through the same point, so the two guards converged
on the centre and walked each other's ground (measured: 0 tiles between the two
loops). Each loop now closes on an INNER ARC -- the volcano's own ground curve
scaled in, so it runs around the lava roughly where the lava is -- and the two of
them are two rings around the same middle. The claim is not cut back: a caldera of
unclaimed ground there was tried and dropped, because it is a hole in a volcano
and it made the claim something other than the mirror's chunk list.
- The inner arc does not hug the claim's edge, and it does not jitter. It used to
follow the claim's own inner edge, which is chunk-quantised, so it stepped 32 tiles
between neighbouring directions and the guard turned through a corner at every step;
the playtest saw both ("hugging it too closely", "jitter in the inner path"). It is
now a smooth curve at a fixed fraction of the volcano's ground radius, and its span
is narrower than the outer arc's so it keeps clear of the cut lines, because
membership is decided by the chunk centre. The sharpest corner anywhere over three
seeds and three frequencies, and not one point of either loop stands on the other
slice's ground.
- The two joins where a loop's legs meet its arcs are RIGHT ANGLES again, and
nothing is corner-cut. Both arcs share one span, so a leg is radial and a circle's
tangent is perpendicular to its radius; the guard rounds it itself, because its
patrolling turning radius is a whole radian per tile and the arcs stop well short
of the cuts, leaving it open ground to do that in. Giving the inner arc its own
narrower span -- which is what this did first -- made the leg run back across the
arc, and the join came out at 134-177 degrees: a hairpin no body can follow.
Corner cutting is worse than the corner it smooths, since a fillet is a list of
short edges each demanding a turn the body cannot make.
- The inner arc now follows the LAVA, which took finding where the lava is: the
expressions resolve to a lava pool at 0.060 of a cone's width with a lava-hot ring
out to 0.083 and nothing beyond 0.106, so the whole lava complex is inside a tenth
of the width -- and the arc was walking at 0.158, outside all of it. It is now at
0.115, just past the lava, and because the lava comes from the same spot field the
outer arc does, it follows the pool's rough outline for free. The wedge shrank with
it (a chunk's clearance from the cut is a fixed number of tiles, and the rim is now
near the middle), and every point of a loop must have a quarter-chunk of claim under
it in all four directions or the cut is refused: a point inside the claim is not
enough when the guard is a tile wide and the line between two of its points is not
the claim.
- The two guards of one volcano are kept a CHUNK apart, and it is measured rather
than hoped for: the arcs end a chunk clear of the cut lines, and the plan re-checks
the closest approach between the two finished loops and refuses the cut if it is
under a chunk. The one way it failed was a patrol point the walk moved, which is
how 19-tile passes were found. A cone whose rim cannot spare a chunk is left
whole: there is no room for two loops on it.
- FIX: both of a slice's legs joined the SAME end of its outer arc, so the guard
U-turned there and backtracked over ground it had already walked. One stray line
was appending the outer arc's radius to the inner arc's point list as well, which
made the outline the outer arc out, the inner arc in, and the outer arc again.
Every other measurement was happy with it -- every point on claimed ground, the
loop long enough for the guard, the sharpest corner 9.9 degrees -- so the check is
a new one: the bearing from the volcano's centre around the loop turns one way all
the way round except once at each of the two legs, and a backtrack shows up as
four. It had been costing cuts as well: a doubled outer arc has chords that span
twice as much ground, so they crossed a neighbour's dent and came back off the
claim (measured: 11-27 volcanoes cut per map before, 22-33 after, and the two
loops went from touching to 12-64 tiles apart).
- A slice is only claimed when BOTH guards fit, and each patrol path is a
PIE-SLICE OUTLINE of its piece: the arc the whole volcano would have walked
(the same radius curve, restricted to the wedge's directions), two legs running in
along the cuts, and their tip. A half-disc slice is a half circle with a diameter.
The corners where a leg meets the arc are right angles -- which a demolisher's body
cannot walk -- so they are rounded; the sharpest corner anywhere is 10 degrees. A
side that cannot carry even the smallest demolisher, or that comes back from the
ladder stepped down from what its own area asked for, means no cut at all. A cut volcano is also decided slice by
slice, each by a chunk of its OWN, because every list handed to
create_territory needs a generated chunk and the chunk that woke the mod
satisfies one of them at most; the other waits for the next chunk event that
carries one of its own. The cut is a pure function of the map (the bearing is a
hash of the cone's own id), so both pieces are identical on every load in either
generation order, and the pieces are DISJOINT because the cut test is TOTAL --
every chunk takes a side, with no third outcome. That is proved, not assumed:
create_territory settles an overlap silently by taking the chunk from whoever
held it, so an overlap would make the two pieces depend on which was built first
with nothing in the log. The apex chunk, the one the two cut lines meet in, goes
to one side like any other (both loops stay 23+ tiles from it); excluding it
instead would put an unclaimed hole in the middle of every cut volcano.
Version: 0.1.13
Date: 2026-09-XX
Changes:
- Volcano (demolisher) territories are built at RUNTIME from a spot mirror, not
from a noise-expression index -- and the index is gone, so there is no setting
to choose. Why: spot_noise returns a cone HEIGHT and never says which of its
selected spots produced it (features/upstream-spot-noise-owner-id.feature), so an
expression could only claim chunks by cell id plus a field threshold and could
not name a volcano. The mirror recovers the identity: a cone's centre is the
first dart-throw-accepted candidate of its region's taus88 stream -- integer
RNG, exact -- and its width is the engine's own effective radius. noise-mirror/
never touches Factorio and is tested without it.
- A chunk's owner is the NEAREST CENTRE among the cones whose ground covers it,
measured at the displaced point because that is where the engine reads the
field. It is recomputed every time from two or three cones; nothing is
materialised to answer it and nothing is kept. Overlapping cones therefore yield
DISJOINT chunk sets, decided up front, so whichever territory is created second
cannot take ground from the first and generation order cannot change the answer.
The engine's own MAX-of-cones field rule is not used for a claim: it lets a small
cone beside a big one win a bite out of the middle of the big one's disc
(measured on a 3-series: the big cone came out a 31%-wide crescent and the
middle cone got no territory at all).
- CONEXISTENCE is computed, not asked of the tiles. The engine's own spot density
(volcano_area / volcanism^2 * spawn gate) is ported into noise-mirror/density.lua,
so a cone exists or does not as a pure function of position. Chunks are
generated one at a time, so no per-chunk or per-tile test can see a whole
volcano: every tile-based gate was a function of what the player had revealed,
which is what made claims appear late, vanish when more ground arrived, and
need an audit to take them back. Verified against the shipped expression at the
candidate centres the gate asks at (100% sign agreement, 3.8e-4 worst relative)
and against the engine's own spot selection through the Rust oracle (240/240
region decisions agree).
- A cone is decided when a chunk of ITS OWN is generated. The chunk that woke the
mod is generated by definition, so create_territory's "at least one generated
chunk" precondition is met by construction, and the shipped path asks the
engine about the map NOWHERE -- no is_chunk_generated, no get_tile. That
replaced a walk of every waiting cone's whole share calling the engine: 0.48 us
a call, 241,840 calls over a 1681-chunk reveal at 100% volcanism and 611,762 at
600%. The old rule could also decide a cone on a chunk belonging to a neighbour;
that cannot happen now.
- Each volcano is ONE create_territory call carrying the cone's whole share,
including chunks that do not exist yet (create_territory holds them and they
join on arrival). Membership is geometric -- the cone's core disc, 0.42 of its
width, tested at each chunk's CENTRE -- so a claim never depends on what the
player has walked past. Sampling the engine's top-left corner instead leaves the
claimed area about half a chunk down-right of the volcano; the 16px-shifted
"_at16" expressions existed only to cancel that bias and are gone with it.
- The PATROL PATH is ours, from the cone's geometry: 0.78 of the core radius,
DENTED where a neighbouring cone takes the ground away, so an untouched volcano
gets a plain circle and a squashed one gives ground up only where it must. Its
points are sized to the ground available -- about one every 6 tiles, 8 to 32 --
and every point must land in the cone's own chunks or there is no claim at all,
because a territory with no units does not appear on the player's map. The
radius on each direction is the first-order inverse of the engine's
displacement rather than a search for it: one noise evaluation per direction,
where the previous root find marched 76 samples per direction for the last
crossing (2,432 noise evaluations and 16 ms per volcano).
- Demolishers are placed explicitly, in the same pass that creates the
territory: one per volcano, sized by the cone's rendered width, and created
WHOLE with body_nodes laid along its own patrol path at one-tile spacing, up to
the prototype's segment_engine.max_body_nodes (106 big / 81 medium / 55 small --
the API docs say 63 for all three and are stale). Previously the engine spawned
the head only and grew the body as it crawled.
- body_nodes are laid one node per TILE crossed, bounded at the prototype's node
budget -- a node past the budget is dropped by the engine, which is the cropped
tail seen from the other end. Spacing by path SEGMENT instead of by tile puts a
demolisher's body in a spiral around its own route rather than along it, so the
walk counts distance crossed, not nodes emitted. Measured live: 106/106 nodes at
1.00-tile spacing on a 475-wide volcano, 42/42 segments placed at spawn, and
unchanged after the unit walks 60 tiles.
- FIX: two volcanoes could be placed on top of each other, structurally rather
than by a mistuned number. The spots were TWO spot_noise calls merged with
max() -- a dense small-seed one and a sparse big-seed one -- to "merge into
varied sizes". Each call has its own candidate placement and its own
suggested_minimum_candidate_point_spacing, and nothing coordinates them, so a
big and a small cone can land on the same spot, with no way to say "not where
the other one is" across two calls. Measured on a real map (seed 1096463296,
600% volcanism, 113 cones): the closest pair sat 64 tiles apart with radii of
192 and 134, and 11 of 6328 pairs were closer than half their combined reach.
It is now ONE call, with the size varying per candidate through
eon_volcano_size_dist, which already varied and the two classes were masking.
Two calls also cost map generation: the field ran two full candidate systems
at every point.
- Sizes were uniform after that, and the cause was measurable: the ramp x noise
x gate product in eon_volcano_size_dist was capped at 1.0 and 55% of candidate
centres landed EXACTLY on that cap. Raising the cap would not have helped --
the engine clamps to maximum_spot_basement_radius, so overshooting cones would
all clamp to the same size -- so the product now varies below 1 (0% at the cap,
7 distinct buckets) with size_mult 1.3, a continuous spread bracketing the old
two classes: 0.35 / 0.55 / 0.74 / 0.87 / 1.11. 1.3 is a measured ceiling, not
a preference: 1.4 makes cones big enough that the patrol circle stops fitting
inside a claim a neighbour has trimmed.
- Map reset (surface.clear() plus a new map seed -- the Legendary Deathworld
scenario's /reset) drops the territory state instead of inheriting it. A cone
id is "seed<stream>@<region>:<region>" and does NOT contain the map seed, so
the new map's cones come back under the SAME ids pointing somewhere else
entirely, and every one of them would have been skipped as already decided.
- The load path is empty: on_chunk_generated is the only thing that feeds the
builder, and on_load does one thing, which is drop the cached builder -- which
is also how a new map seed is picked up. The load-time scan of already-generated
chunks it replaces only ever migrated saves from builds predating this path.
- There is no audit, no priority pass, no lens refill, no once-a-minute
re-assertion and no remotes. Each existed because the split was once computed
against cones that had not resolved yet; existence is computed, the split is
settled up front from geometry, and a placed cone is recognised by its marker.
Every volcano logs one line, which is the only channel a test has and what a
playtest is read from: "[eon] volcano <id>: centre ... width ... -> territory
of N chunks, patrol 32 points, demolishers 1 [...]".
- Per-chunk cost of the whole feature at 600% volcanism: 0.13 ms, from two hash
lookups and a handful of distance tests.
- Dead noise expressions are deleted (tests/dead_expressions.py: 910 defined, 0
unreachable) and the noise-dedup work that found them is gone with it. The
data stage keeps no expression the mirror makes unnecessary.
- The gate is hermetic and separate from the live rcon loop: run_spot_mirror_tests.py
runs the mirror's own self test against game-captured vectors, the claim path
against a fake surface (no Factorio), a patrol-turn-radius test, the
duplicate-function and dead-expression checks, density and field parity against
the shipped expressions, four spot-selection parity configurations, and two
headless end-to-end runs (100% and 600% volcanism). tools/noise-sandbox/ holds
the analysis side: a Python evaluator for the shipped noise expressions, the
Rust noise oracle, a complexity reporter, and the calibration scripts that set
the constants above.
- The requirements live in features/lua-territory.feature (AC-1..AC-15, each with
the probe that proves it) and the working agreements in AGENTS.md: no fallbacks
that change behaviour, no swallowed errors, nothing raised on a per-chunk path,
one Lua dialect (5.2), and measure rather than assume.
Version: 0.1.12
Date: 2026-09-25
Changes:
- Demolisher territories SPLIT: medium+ volcanoes get two territories
(west half + east half) instead of one, small volcanoes stay whole, and
overlapping/merged volcanoes no longer collapse into a single territory.
The cut is anchored by the volcano FIELD GRADIENT, not any world lattice:
the territory index compares the volcano spot field at x+32 vs x-32, whose
sign flips exactly at the deployed peak column (probe-verified: lossless
partition of the mask, cut within ~1 column of the lava centroid, immune
to the spot-deployment jitter that broke lattice-anchored cuts). Small
cones (size_dist < 0.55) are exempt so tiny halves never drop under the
territory floor (unguarded seams). Residual: the corner of a big cone
that pokes into a neighbouring voronoi cell keeps its own small territory
(~1-2 per map, guarded) -- the alternative is an unguarded gap.
- Demolisher SIZE now scales with volcano size, not distance: tier by
eon_volcano_size_dist (small < 0.55, medium 0.55-0.8, big >= 0.8), plus a
per-territory nudge (0/1) so the two halves of a split cone are adjacent
size classes (small+medium / medium+big, never small+big). Small-only
cones cap at medium.
- Probe tooling: territory grouping is now verifiable headless via
LuaTerritory.get_chunks()/get_segmented_units() (tests/eon-probe-grouping,
tests/probe_split_grouping.py - the dedicated territory E2E; unguarded-lava
quota + leak guard).
- Volcanoes are real cones now: the surface elevation property carries the
FFF-390 cone profile (min(x, P - x)) -- tiles rise from the folds foot to
a crest at the lava edge and drop back toward the center, so the lava
sits in a visible caldera bowl below the rim instead of a flat disc
wearing cliff rings. Cliff rings staircase only the climb side and
plateau from the crest inward, so the top ring is outward-facing and no
rings descend into the lava (probe: zero cliffs on lava tiles). Ring
spacing stays uniform across volcano sizes: the 300-unit relief amplitude
scales with the distance-driven size growth and big-spot-system dominance
(bigger cone, higher peak, same slope).
- Volcano size vs distance: ramps from 0.30 near spawn to full by 4000
tiles, so the nearest cones are small and can never swallow spawn (old
0.8-bottom ramp + ~424px base radius let big-system cones reach it).
Per-volcano random size was attempted but rejected: spot_noise parameters
must be compile-time constants, and a random term in the spot radius
broke map-gen compilation (surfaced as "Expected a constant: spotNoise[3]"
on unrelated early-compiled expressions like barnacles-decal).
- Volcano frequency is a pure density control again: vanilla couples it
into eon_volcanism as a divider (cranking frequency shrank every volcano
-- at 600% ~129px radius vs 300), decoupled, and the density curve rescaled
so the highest slider setting yields ~2x the volcanoes (11 vs 5 per 3.2km
square at 100%, ~linear in frequency past the GUI max). Volcano spawn
protection halved (candidates may form from ~425 tiles out) so volcanoes
can sit close to spawn -- no harm in nearby volcanoes.
- Sulfuric acid geysers: gated to the inner volcano core (eon_vulcano_coverage,
the per-tile form of the demolisher-territory signals), with a per-volcano
presence lottery driven by the geyser frequency slider (roughly 20% of
volcanoes at the bottom, ~half at default, all of them by 350%). Cluster
geometry reuses the same helper/grid as calcite (offset 0 on the shared
span-3 sub-grid, so calcite and acid never stack -- measured zero calcite
within 30px of a geyser); tile density is vanilla's 0.025 with a capped
per-geyser richness (no size-slider inverse, so shrinking size no longer
makes each remaining geyser 16x richer). Baseline acid total sits ~1.5-2x
crude-oil at default settings.
- Sulfur puddles and stains follow the geysers (same core + hash gate)
instead of a feathered volcano band; the old mask_volcano_fade rendered
them on plain ground outside the rim.
- Scrap is fixed in the holmium-off config: vanilla scrap's probability is
0 (it only spawned via Fulgora's per-planet overrides) and the old branch
wrapped that dead 0, so scrap never rendered. It is now rebuilt as a real
nauvis ore (same params holmium-ore uses) with its own resource-autoplace
patch-set index, masked like every other ore -- off volcano ground, off
aquilo/ammonia/gleba -- so it can't stack on calcite (volcano-anchored) or
the base ores (measured zero scrap within 25px of iron).
- Calcite ore grows at volcanoes (vanilla Vulcanus behavior) instead of as
plain Nauvis scatter: spots anchor on a smoothed volcano spot field via
vanilla's vulcanus_place_non_metal_spots, so each volcano carries roughly
1-2 compact patches (the candidate lottery leaves some volcanoes bare and
some with a couple more, which map-gen noise and water rims naturally
shuffle). Patches may spill a few tiles past the volcano rim onto plain
ground and outside demolisher territory (a breadcrumb pointing at the
volcano), but never drift far from one; richness is flat in distance like
vanilla and capped at tungsten's per-tile scale (2500), so calcite is
never richer than tungsten. This replaces the dead
vulcanus_calcite_probability override (nothing referenced it) and the
nauvis-scatter richness that silently vetoed volcano patches.
- Sulfuric acid puddles and geysers are gated tight to volcano terrain (no
feather band): their vanilla region is positive over the broad pre-biome
around a volcano, so the old mask_volcano_fade band rendered them on
plain ground just outside the rim.
- Volcano/gleba/aquilo boundary masks renamed *_early -> *_fade (the
consistent suffix for the eon_fade boundary family); no behavior change.
- Ashland and flaming ashland trees grow on volcano terrain.
- Gleba starts with a translated starting area instead of a lone frontier: vanilla's own yumako+jellynut patch pair (same starting_spot_at_angle formula, radii and wobbles) moved to just below the transition, with vanilla's starting_aux/starting_radius gradient translated to the same spot so gleba_biome_mask_green/red split the start into a yumako side and a jellynut side instead of reading the province lottery (previously one fruit dominated and the other needed deep exploration). Both fruits ~400 tiles apart at gleba landfall; deep south stays regular vanilla Gleba with shared fruit/ore provinces.
- Gleba's desert-province flora restored: vanilla Gleba grows ~15 shared base-prototype decoratives (desert bushes, pitas, croton, mud/lichen/shroom decals, green carpet/hairy grass) via its own property_expression_names. The merged map now evaluates those same vanilla gleba formulas in gleba territory (nauvis-side behavior untouched); the red/purple/cream nerve-roots-veins decoratives (referenced by wrong unprefixed names in the original mod so they never placed) are registered and masked like the other gleba natives. Measured vs a vanilla-gleba baseline in the same box: all species within ~1-10% in the deep south, cliffs 1.0x vanilla.
- One transition field only, no wide variant: moisture/aux/elevation/cliffiness all morph on a clean few-hundred-tile ramp around eon_gleba_south_offset (0 north of line-100, 1 by line+400; the territory LINE keeps its wobble character). A wide/slow moisture morph and a wobble-laden blend input both silently shifted the deep-south decoration provinces (measured 3-4x swings on aux-selective species); the aux gardening at the translated start is gated by a tight anisotropic box (full only across the patch pair, zero by |x|=330 / y=1450) so it cannot tilt the deep south.
- Gleba cliffs are vanilla-faithful again: the merged surface has to use the nauvis cliff ladder (interval 40, first band ~10), so the south arm of eon_cliff_elevation now rescales gleba elevation (2/3, offset -50/3) to emulate vanilla's ladder (interval 60, first band 40) - no more cliffs in wetland/lowland ground and the same contour spacing on dry land (measured: 2.9x vanilla cliff count down to ~1.0x with the single blend).
- Transition flora leads the tile line: water-cane feathers across the handoff, red-pita/honeycomb/cups/coral start ahead of Gleba tiles; elevation and shoreline signals morph fast for crisp bands while moisture keeps the wide mix.
- Nauvis-Gleba transition is a mixing band instead of a hard line: highland/midland reach north, dry Nauvis tiles die out early, forest and grass end at the shore fringe, water hands over water-to-water, fields morph across the full width.
- Fewer chimneys and volcanic rocks spawn on volcano terrain.
- Gleba natives react to pollution (yoinked from EverythingOnNauvis-Patches, always on since spores are dead without other planets): pentapod units/spawners join attacks on pollution instead of spores, harvest and agricultural towers emit pollution.
- Atomic bomb ground effects for deleted planets are deleted outright (nuke-effects-aquilo/vulcanus plus their atomic-rocket triggers) instead of being gated behind explosion surface conditions, so the bomb always leaves nuclear ground.
- Tungsten ore now grows on volcano flanks, guarded by demolishers (vanilla Vulcanus behavior): smaller, more numerous patches favored by mineable volcano ground. No fallback: volcanism cannot be disabled, so every map has volcanoes and therefore tungsten.
- Lava and crater cliffs are masked to volcano terrain like every other volcano feature: vanilla's lava formula keys off a biome value that is meaningless on Nauvis and used to strand lava-hot lakes on dirt and Aquilo ice with no volcano around them.
- Volcano decoratives feather past the terrain edge in two bands (outer debris wider than mid details), mirroring the staggered Gleba transition; chimneys, big rocks and lava fire stay tight.
- Calcite stains now pair with calcite ore wherever it grows, inside or outside volcanoes, instead of only staining volcano terrain.
- Volcanoes vary in size (small/dense and big/sparse spot systems) and grow bigger further from spawn.
- Volcano spawn protection moved from field subtraction into candidate density: volcanoes near spawn are fewer, never cropped (no more missing lava or clipped demolisher territory).
- Demolisher sizes fit their volcanoes: slowed progression normalized by volcano packing density (yoinked from EverythingOnNauvis-Patches, dense maps progress earlier, sparse maps later), mixed sizes across a volcano's territories, small-only volcanoes capped to medium.
- Volcano rims feather each side's own decoratives, band-gated with depth falloff: aquilo ice, bergs and drifts on the aquilo flank; Nauvis and Gleba flora (rock entities stay home) and trees on the others; Nauvis trees also cross onto the icy shore fringe; crater-cliffs stay off Aquilo.
- Territory masks rule the boundaries: aquilo tiles, snow variants and fish stay off the whole volcano mask (coverage + folds + soft-edged rim) and off non-Nauvis liquids — no fish in lava, ammonia ocean, or Gleba wetlands/lakes (fish yoinked from EverythingOnNauvis-Patches).
- Aquilo keeps only crude oil, lithium brine and fluorine vents: all other ores stay off aquilo land and ammonia ocean.
- Tungsten is leaner (richness base halved-ish) with frequency-normalized distance gradients; flaming ashland trees stay deep inside volcanoes; lava fills big-volcano centers (vanilla upper bound).
Bugfixes:
- Nauvis/Gleba decorative fades were leaking everywhere: the probability snapshots are
signed, so any fade that MULTIPLIED the expression by -inf turned negative snapshots
into +inf (spawn at max density in the very region being excluded). Every -inf
exclusion now REPLACES via if(); only 0..1 fades multiply. Grass tufts stay on nauvis
(feathered ~10 tiles before the gleba line, zero on volcano ground, zero on aquilo);
gleba transition flora mirror that; all other decoratives hard-masked upstream-style.
- Demolisher territory is bound to the volcano CORE (folds + lava rings, outer
folds-flat skirt excluded): the mask is the same signals that place the core tiles,
built on the 16px-shifted spot field so the engine's top-left-corner chunk sampling
stays centered (measured +15/+16px SE bias un-shifted, ~0 after), plus a thin inner
edge of the flat skirt (spots > 0.6, tile-truth). The skirt becomes a buffer ring:
rim/water fringe chunks no longer grab territory, and demolisher patrol anchors stay
inside volcano ground (measured: every lava-bearing chunk is covered; the canyon of
screening off-territory chunks is zero). The index expression is sampled at one fixed
world-aligned corner per 32x32 chunk (claimed iff >= 0), and minimum_territory_size
= 3 drops the last 1x1/2x1 voronoi cells that stranded a medium demolisher on a single
patrol point (tail-chasing); territory voronoi cells (radius 512) are larger than the
typical volcano, so interior chunks share one cell and one patrolable territory.
- Tungsten hugs the lava heart of the volcano: the favor band is the flank ring at
spots > 0.65 (outside the lava core, which blocks placement itself), candidate
frequency boosted x3 to repay the inward clip, and the render gate is the territory
core mask so virtually no ore renders outside demolisher territory (0.3% measured,
all in northwest-rim chunks one sample off a chunk corner; nil at any reported gps).
Roughly one in five small volcanoes has no ore (accepted: presence on the rest
beats rim drift).
- Nauvis ores (iron, copper, stone, coal, uranium, crude oil, holmium/scrap) no longer spawn inside volcano areas.
- Dead grey trunks no longer spawn outside Nauvis territory (no more dead trees on volcanoes).
- Volcanoes get elevation-driven cliff terraces up their flanks; rings generate as nauvis cliffs and control.lua re-skins volcano-terrain ones as cliff-vulcanus, keeping orientation. Only newly generated chunks convert.
- Gleba lakes restored: wetland-blue-slime and gleba-deep-lake are registered on Nauvis again (unlisted tiles never place), with water handing over water-to-water at the border.
- Gleba no longer takes priority over volcano terrain: the full volcano (including the outer folds-flat ring, i.e. demolisher territory) now beats Gleba everywhere, per aquilo > vulcanus > gleba > nauvis.
- Gleba territory now grows cliff-gleba cliffs: cliff elevation/density blend toward Gleba fields in the south and control.lua re-skins new-chunk cliffs on Gleba tiles (same pattern as cliff-vulcanus).
- Scrap (when eon-holmium-ore is off): restored the VANILLA FULGORA
placement and shapes instead of the round nauvis-style blob patches -
structure-cell blocks (frequency = % of cells covered, capped at 600%, so
the slider behaves like vanilla), per-cell sub-noise, road carves, dense
vault spots, no scrap in the starting area, vanilla richness. Transplanted
onto the merged map with two substitutions: the fulgora elevation/coast
land gate became a nauvis land gate (eon_scrap_land on the raw
elevation_nauvis field, water level 0 + shore margin), and the tile mask
is gated by eon_scrap_ore_exclusion (0 wherever iron/copper/coal/stone/
uranium/crude-oil probability > 0) so scrap never shares a tile with
another ore (sign-safe if() form; the resource-autoplace patch-set skip
only de-overlaps spot grids, not ~22-tile cell blocks).
- Live-server gotcha for continuing saves: a surface's baked
autoplace_settings.entity.settings never re-syncs from the planet
prototype - a save created while eon-holmium-ore was on has 'holmium-ore'
registered but NO 'scrap', so scrap never autoplaces on it (verified live:
entity_scrap=false, 0 scrap on the whole map while iron works). Scenario
resets only rewrite mgs.seed, so this never self-heals. Fix the surface
registry (and regenerate chunks) to heal such saves - see
map-gen-settings-eon-defaults.json.
Version: 0.1.9
Date: 2025-05-XX
Changes:
- New startup setting "Replace scrap with holmium ore" (default on): when enabled, scrap is replaced with holmium ore on Nauvis.
- New startup setting "Remove space platform surface restrictions" (default on): when enabled, all surface conditions are removed so space-platform machines (crushers, ...) can be built on the surface and planet machines (chests, burner furnaces, ...) work on space platforms.
- New startup setting "Asteroid chunk stack size 50" (default on): asteroid chunks stack up to 50 instead of the vanilla stack size.
- Gleba placement is now tuned per map via Nauvis map-gen settings property expression names "eon_gleba_south_offset" (default 1000, how far south Gleba terrain starts) and "eon_gleba_deep_south_cap" (default 1, caps how strongly distant southern terrain turns into Gleba; lower it for more biter-friendly Nauvis gaps deep south). No restart needed, applies to newly generated chunks.
- Far-south terrain no longer becomes pure Gleba: the south bias is capped, so deep south stays mostly Gleba with regular Nauvis gaps where biter nests can spawn again.
Bugfixes:
- Atomic bombs no longer create ammoniacal-ocean and lava tiles on Nauvis. Surface conditions are now kept for explosion prototypes so only the vanilla nuclear-ground effect applies (matches vanilla Nauvis behaviour).
Version: 0.1.8
Date: 2025-05-05
Changes:
- Borders of gleba terrain are less smooth now
Bugfixes:
- Fixed compatibility for honeycomb fungus when playing with Spaghetorio mod
- Fixed some locale typo
- Fixed compatibility with factorio 2.0.47 with new gleba decoratives
Version: 0.1.7
Date: 2025-04-18
Changes:
- Gleba tiles are much more prevalent in the south
- New algorithm for spawning yumako and jellynut
- Vulcane have a slightly different lava spot size
Bugfixes:
- Yumako and jellynut plants now will spawn with water disabled
Version: 0.1.6
Date: 2025-03-21
Changes:
- Ores related to Nauvis will not spawn on ice
- Lightning collectors are now hidden from player
Version: 0.1.5
Date: 2025-03-14
Changes:
- Gleba tiles absorb pollution
Version: 0.1.4
Date: 2025-02-19
Modding:
- Added space travel flag
Version: 0.1.3
Date: 2025-02-02
Bugfixes:
- Now the menu simulations are fixed for good
Version: 0.1.2
Date: 2025-01-30
Bugfixes:
- Removed some menu simulations which could crash the game
Version: 0.1.1
Date: 2025-01-19
Bugfixes:
- Calcite and Tungsten ore wont spawn on ammonia oceans
Modding:
- Resource changes to tungsten ore and calcite are now done in data instead of data-final-fixes
Version: 0.1.0
Date: 2025-01-19
Features:
- This version was played from finish through end
- Added descriptions to resources
- Tungsten ore and calcite now spawn like normal nauvis ores
Bugfixes:
- Removed startup settings which did not do anything.
- Removed small lava patches around the map (or at least the ones that i carefully checked out :))
Version: 0.0.9
Date: 2025-01-18
Bugfixes:
- Heating tower unlocked after concrete
- lithium processing is now unlockable
Version: 0.0.8
Date: 2025-01-15
Bugfixes:
- Updated holmium graphics with higher contrast.
Version: 0.0.7
Date: 2025-01-14
Features:
- Asteroid chunks now have stack size of 50
- new technology for traveling to solar system edge
- removed rail support foundations technology since fulgora does not exist any more
Version: 0.0.6
Date: 2025-01-10
Bugfixes:
- Vulcanic rocks also provide calcite. This is needed for big mining drill
Version: 0.0.5
Date: 2025-01-09
Bugfixes:
- Removed some research triggers that were needed to continue with fulgora items
- Updated mod compatibility list
Version: 0.0.4
Date: 2025-01-09
Features:
- Agriculture technology, calcite processing and tungsten carbide technologies are unlocked earier
- Heating tower is unlocked after nuclear power
Version: 0.0.3
Date: 2025-01-07
Bugfixes:
- Removed vulcanus_enemy_base autoplace control
Version: 0.0.2
Date: 2025-01-07
Bugfixes:
- Removed some gleba water tiles, since there is no smooth transition towards nauvis water
Version: 0.0.1
Date: 2025-01-06
Features:
- Initial release