Mechanics wiki / Survive the Storm / Map conditions

Map conditions

Every new colony gets a set of conditions, in the spirit of Against the Storm's map modifiers: fixed for the colony's whole life, announced by a "Map Conditions" notification the player clicks once to read (reading clears it for good), and listed permanently on the Mission Goals page below the commander profile. Five are rolled per colony; one (Topography) is not rolled at all but read from the map the run landed on. Every run lands on exactly two medium and four extreme across the six. This page is the mod's design; the shipped build rolls and shows these conditions and applies each one's gameplay effect - all six built and tested (see Status). It gets its own page because the system is large: six conditions, each with its own game-code translation.

This replaces and expands the old three-slot "Map modifiers" feature listed under Randomization on the feature index. The roll, persistence and notification are inherited from Code/StS_MapModifiers.lua; the new conditions add their own couplings into the disaster, funding, exploration and landscaping systems.

The six conditions

Two kinds. Rolled conditions (five) are drawn per colony and independent of the map. The one derived condition (Topography) is a deterministic function of the map's rating - it looks random only because the landing site is random. Every condition has one medium value (the default, no special change) and two extremes. The roll constrains the colony to exactly two medium and four extreme across all six (see the roll).

#ConditionExtremeMediumExtremeKind
1Rocketfast: 1 rocket, 1-day travelpods: 1 rocket, 2-day travel, +5 Podsbig: 2 rockets, 3-day travelrolled
2Dust Storm vs Cold WaveDust Storms +33% / Cold Waves -33%even: roughly 1:1Cold Waves +33% / Dust Storms -33%rolled
3FundingRare Metals +20% / Tourists -20%even: both unchangedTourists +20% / Rare Metals -20%rolled
4Sensor Towers+33% range / -33% boosteven: as defined-33% range / +33% boostrolled
5Vistas+33% more Vistaseven: default split+33% more Research Sitesrolled
6TopographyFlat: Metal & Rare Metal -20%Rough: 0%Steep/Mountainous: +20%derived from map

The roll: exactly two medium, four extreme

Across all six conditions, every run lands on exactly two medium and four extreme. So a colony is never fully neutral and never extreme on every axis - it always shows four extremes and two defaults. Topography is not rolled (the map fixes it: rough is its medium, flat and steep its extremes), but it counts toward the target, so the five rolled conditions fill the rest: if Topography lands rough (medium), the roll produces one medium and four extreme among the five; if it lands flat or steep (extreme), the roll produces two medium and three extreme. Either way the colony ends on two medium, four extreme.

Because Topography is only known reliably in-game (not necessarily at the roll, which fires at OnMsg.NewGame), the roll does not resolve concrete values up front. It persists a plan: a shuffled priority order of the five rolled conditions plus a chosen extreme direction for each. Each condition's value is resolved on demand by StS_GetMapCondition against the live Topography - the first N in the priority order are medium (N = 1 if Topography is rough, else 2), the rest take their chosen extreme. Every reader goes through StS_GetMapCondition and only reads in-game (on CityStart/LoadGame and later), when Topography is available, so the two-medium-four-extreme guarantee always holds.

The plan lives in one GlobalVar, which the engine serializes into the save automatically (Docs/LuaSavegame.md.html:11,19), rolled once in OnMsg.NewGame (fires on a new colony, not on load) guarded by an "already set" check - the same pattern the base game uses for its own session randomness (g_SessionSeed = g_SessionSeed or AsyncRand(), Lua/Colony.lua:89-94). The const-modifier effects are re-applied on every CityStart and LoadGame, keyed by our ids so re-applying never compounds. A "Map Conditions" notification (AddCustomOnScreenNotification, Lua/UI/OnScreenNotification.lua:708) announces them; clicking opens a CreateMessageBox with the full readout, then the notification clears itself (close_on_read plus a persisted StS_MapConditionsRead flag) so it never re-shows. The same readout is built once (StS_MapConditionsLines) and also appended to the Mission Goals page below the commander profile (Code/StS_GoalsPage.lua), so the two never drift.

Length budget and voice. Each readout is one plain sentence that names the cause and lets its effect follow (no Label: value colon), with a verb that carries the direction (mountains offer more ore, flat land thins it, a region leans to one disaster). It must fit on one line on the Mission Goals page, so no condition line runs past 60 characters (the on-screen width is that plus the "- " bullet). The current longest are 57: the funding "tourist economy" line and the vistas "strange geology" line. Any readout that would read longer must be shortened.

1. Rocket

The colony's starting fleet and rocket travel time, as one of three trade-off packages. Its medium is the middle package (pods: 1 rocket, 2-day travel, +5 free Supply Pods); the extremes are fast and big.

PackageStarting rocketsTravel time per legExtra
A11 day (base, 25 h)-
B (middle)12 days (+100%, 50 h)+5 free Supply Pods
C23 days (+200%, 75 h)-

The abstraction "N-day travel" is N times the base leg. The base Earth-Mars leg is 25 h (TravelTimeEarthMars = 750000 at scale HourDuration = 30000, Lua/_const.lua:793-807), about one sol (a sol is 24 h). So the three tiers are the base leg, the leg doubled, and the leg tripled.

2. Dust Storm vs Cold Wave (prevalence)

Mid-capable. Which of the two weather disasters is more prevalent, as a ratio of how often each is on the map. This replaces the old weather slot, which biased storm duration (the +20% STS_WEATHER_LENGTH_BONUS_PCT stretch); the new condition is about frequency.

OptionDust StormCold Wave
extreme+33%-33%
mediumas definedas defined
extreme-33%+33%

The Harsher disasters escalation splits its occupancy target 50/50 between Dust Storm and Cold Wave - each carries half the curve (StS_DisasterParams, StS_HarsherDisasters.lua). This condition re-weights that split by ±33%, scaling each disaster's length up and its gap down by its share, inside the same OverrideDisasterDescriptor wrap that already writes each storm's min_duration / max_duration and spawntime. The combined weather load stays on the escalation curve; only the mix of the two shifts.

3. Funding

The colony rolls one of three outcomes: a coupled +/-20% trade-off between the two funding streams, or an even split. It never raises both.

RollEffectLevers
metalsRare Metals price +20%, Tourist funding -20%ExportPricePreciousMetals +20%, TouristFundingMultiplier -20%
tourismTourist funding +20%, Rare Metals price -20%TouristFundingMultiplier +20%, ExportPricePreciousMetals -20%
evenboth unchanged (neutral)both modifiers 0

4. Sensor Towers

Trades how far a sensor tower's scan boost reaches against how strong that boost is. The boost speeds up map-sector scanning (shown in the overview as "Sensor towers boost X%"), not disaster warning (that is the separate sensor-tower prediction time, left untouched).

OptionRangeBoost
extreme+33%-33%
mediumas definedas defined
extreme-33%+33%

Range is const.SensorTowerScanBoostMaxRange, the zero-boost outer radius; the boost amount is const.SensorTowerScanBoostMax (390, Lua/_GameConst.lua:109-111). A sector's boost from the nearest working tower is MulDivRound(SensorTowerScanBoostMax, min(maxR-minR, maxR-dist), maxR-minR) (Lua/Exploration.lua:284-306). The options set range ×1.33 / ×1 / ×0.67 and boost ×0.67 / ×1 / ×1.33, applied from a stashed base on CityStart and LoadGame so a mod reload never compounds. (Not ClassesBuilt: the roll is set in OnMsg.NewGame, which fires after ClassesBuilt, so at that point the roll does not exist yet.) Because both are plain consts recomputed from the stashed base, each factor is inherently multiplicative after every other modifier. The full-boost radius (SensorTowerScanBoostMinRange) is left untouched, so only the falloff length and the peak boost move. Tested v2.13 as StS_RandomTowerRange.lua, which supersedes the flat-50% range-cut proof of concept that file previously held.

5. Vistas

Shifts the map's mix of two scenic surface deposits: Vistas (comfort) and Research Sites (research).

OptionEffect
extreme+33% more Vistas (some Research Sites flip to Vistas)
mediumdefault split (unchanged)
extreme+33% more Research Sites (some Vistas flip to Research Sites)

"Vista" is BeautyEffectDeposit (Lua/Buildings/EffectDeposit.lua:108, display_name "Vista", +10 dome comfort); "Research Site" is ResearchEffectDeposit (:154, display_name "Research Site", +10/15/20% research). They are sibling EffectDeposit classes. The map places them as markers at generation; a marker becomes a real deposit only when its sector is scanned, through RevealDeposits (Lua/Exploration.lua:417), which calls the marker's EffectDepositMarker:SpawnDeposit (EffectDeposit.lua:10) to build PlaceObjectIn(self.deposit_type, ...). There is no ratio field, so the swap hooks that reveal path: RevealDeposits is wrapped to raise a flag around itself, and SpawnDeposit is overridden to re-point deposit_type from the source class to the target class on an AsyncRand(100) < 33 chance while the flag is up. So the swap lands as each source-type deposit is uncovered and flips about a third of them, which yields roughly +33% more of the target deposit type (and about a third fewer of the source) when the two are similarly common on the map. Story-event deposits (the SpawnEffectDeposit effect) call PlaceDeposit directly, outside RevealDeposits (Lua/ClassDefs/ClassDef-Effects.generated.lua:2189,2412), so they never see the flag and are never swapped. Both hooks install once at ClassesBuilt, guarded so a mod reload cannot double the coin flip. In StS as Code/StS_ConditionVistas.lua.

6. Topography (derived from the map)

Not rolled. Read from the map the run landed on, so it looks random only because the landing site is random. The hillier the map, the more Metal and Rare Metal it carries: Topography shifts every Metals and Rare Metals total on the map by a flat percent.

TopographyMap ratingMetal & Rare Metal shift
Relatively Flatchallenge_rating ≤ 59-20%
Rough≤ 990% (baseline)
Steep or Mountainous≥ 100+20%

The label is the game's own Topography readout, MapChallengeRatingToDifficulty(rating) (Lua/UI/PlanetUI.lua:93-103), keyed off the map's challenge_rating (ActiveMapData.challenge_rating). The percent is a single source of truth in Code/StS_ConditionTopography.lua (StS_TopographyMetalPercent); Resource Parity reads it and scales the Metals and Rare Metals targets in every tier (loose surface piles, shallow deposits, deep deposits) by (100 + pct)/100 as it normalizes the map on MapSectorsReady. Water and Concrete are not shifted. Applied totals, on top of the rough baseline (loose 1200, shallow 6400, deep 13000; Rare 3000 / 5000):

TopographyLooseShallowDeepMetal totalRare total
Relatively Flat (-20%)96051201040016,4806,400
Rough (0%)120064001300020,6008,000
Steep or Mountainous (+20%)144076801560024,7209,600

Landscaping time is no longer topography-driven. It is now fixed at +100% (2x drone work time) on every map, set in the same file via g_Consts:SetModifier("DroneTimeToWorkOnLandscapeMultiplier", ..., 100) (base 100, Lua/_const.lua:557-563; the multiplier drone landscaping reads at LandscapeConstructionSiteBase.lua:140), applied on CityStart and LoadGame. It is the same const the Green Planet landscaping techs modify, and const modifiers aggregate additively, so those techs keep their full effect measured from a raised baseline. This map-wide rule is listed in the General Rules readout, not here. Design and prior verification: docs/landscaping-concrete-cost.md.

Status

The foundation (StS_MapModifiers.lua) rolls this page's six-condition plan (the two-medium-four-extreme rule above), stores it in one GlobalVar, resolves each value through StS_GetMapCondition, shows the read-once "Map Conditions" notification, and lists the same readout on the Mission Goals page below the commander profile. All six condition effects are built and tested individually; each lives in its own file and registers its own readout. The unified two-medium-four-extreme roll and the removal of the former Meteors vs Dust Devils condition are Tested v2.222. Sensor Towers and Vistas moved to +/-33% and Funding and Topography to +/-20%, and the base Rare Metals price is 25 M, all Tested v2.222. The foundation writeup is the Map conditions foundation section on the feature page. Per condition:

ConditionStatus
1 RocketTested v2.9 (Code/StS_ConditionRocket.lua): fixed starting fleet (1 / 1 / 2 rockets), +0/+100/+200% travel on the two travel consts (regular rockets) plus the same ×1/×2/×3 on the custom-travel rockets (Dragon / Zeus / Expedition, template + live fleet), and +5 free Supply Pods on pods. Supply Pods keep a fixed travel speed. Rolled by the foundation (fast / pods / big).
2 Dust Storm vs Cold WaveTested v2.143 (in Code/StS_HarsherDisasters.lua): re-weights the Dust:Cold prevalence by +/-33% by scaling each disaster's target duty by its share inside the disaster-descriptor wrap, the combined load staying on the escalation curve. Rolled by the foundation.
3 FundingTested v2.222, edge +/-20% (Code/StS_ConditionFunding.lua): a coupled +/-20% trade-off per colony - metals raises the Rare Metals export price and lowers the tourist payout, tourism the reverse, even leaves both unchanged. Applied as two g_Consts modifiers on CityStart/LoadGame. The earlier +50% single-edge design (and its research tech-scaling edge) is removed. Rolled by the foundation.
4 Sensor TowersTested v2.222, edge +/-33% (Code/StS_RandomTowerRange.lua): rolled range / even / boost scales the scan-boost reach (x1.33 / x1 / x0.67) against the boost amount (x0.67 / x1 / x1.33) from a stashed base on CityStart/LoadGame. Supersedes the flat-50% range-cut proof of concept.
5 VistasTested v2.222, swap chance 33% (Code/StS_ConditionVistas.lua): on an extreme roll each map-placed Research Site (or Vista) has a 33% chance to flip to the other as it is uncovered (roughly +33% more of the target type); the medium roll leaves the split unchanged. Story-event deposits are left untouched.
6 TopographyTested v2.222, shift +/-20%. Derived live (flat / rough / steep) and shifts every Metals and Rare Metals total -20% / 0% / +20% (applied by Code/StS_ResourceParity.lua, percent from Code/StS_ConditionTopography.lua). Landscaping time is now a fixed +100% on every map, no longer topography-driven.

Sources

Base game, paths relative to external/SurvivingMars; Green Planet in armstrong (decompiled under external/dlc_unpacked/armstrong). Rockets and travel Lua/City.lua, Lua/Buildings/RocketBase.lua, Lua/_const.lua; supply pods Lua/Buildings/SupplyPod.lua, Lua/ClassDefs/ClassDef-Effects.generated.lua; funding Lua/Funding.lua, Lua/HolidayRating.lua, Lua/Modifiers.lua; disasters Lua/MapSettings.lua and the per-disaster presets; sensor towers Lua/Exploration.lua, Lua/_GameConst.lua; vistas and research sites Lua/Buildings/EffectDeposit.lua, Lua/Exploration.lua; topography Lua/UI/PlanetUI.lua, Lua/_const.lua. Mod files: map roll Code/StS_MapModifiers.lua, disasters Code/StS_HarsherDisasters.lua, sensor Code/StS_RandomTowerRange.lua, funding Code/StS_ConditionFunding.lua, vistas Code/StS_ConditionVistas.lua, landscaping Code/StS_ConditionTopography.lua. Design notes: docs/landscaping-concrete-cost.md.