Skip to content

Ion storms

Scripted global condition that grounds aircraft and hovercraft, calls lightning down on the map, and swaps the scenario to its ion lighting values.

Features & systemsCombat & weaponsSuperweapons & special systems

Changed in 0.1.0

One storm exists at a time and it covers the whole map for every house. Nothing raises one on its own: no rules setting, timer, or weather model schedules a storm, so every storm in a scenario comes from scenario scripting.

This section introduces the entity the rest of the page turns on. Anyone who already knows what a locomotor is can skip to starting a storm.

A locomotor is a separate object that carries one aircraft, infantryman or vehicle about — the thing that settles whether that object drives, walks, hovers, flies, burrows or steps, and the thing an ion storm switches off underneath it. Each instance is given one as it is created, of the class its type’s Locomotor= names; ten classes are registered, and that page lists them.

Only two of the ten report themselves sensitive to an ion storm: the flying locomotor, which aircraft use, and the hover locomotor, which hovercraft use. Drive, walk, jumpjet, tunnel, teleport, mech, levitate and ballistic objects keep their power throughout, and the jumpjet is not so much exempt as handled separately and more harshly.

A storm therefore reaches an object through its locomotor rather than through what kind of object it is. That is why aircraft and hovercraft are named together below wherever a locomotor decides the outcome, and vehicles, infantry and aircraft are named together wherever something else does.

Ion Storm start… takes a number and starts a storm that lasts that many seconds. The action is refused outright while a storm is already running.

Ion storm start in… takes a number and starts a storm that lasts that many game frames. It is skipped while a storm is already running.

A duration of -1 is the one value that never expires; a storm started with it lasts until Ion Storm stop… or Ion storn end runs. Only the team mission can deliver that value unchanged.

UseIonStorms=yes in a map seed makes the generator load the hard-coded file ION.INI while it builds the map. The generator applies that file’s [General] section over the loaded rules, reads the six ion values from its [Lighting] section, and registers that file’s trigger types and tag types with the generated map — storms then come from whatever triggers the file carries, as the engine never schedules one itself. When the generator randomizes a seed itself, it turns the option on for about half of all seeds, and only while the Firestorm addon is enabled.

Both scripted entry points schedule the storm rather than breaking it at once: they arm a countdown of IonStormWarning seconds, which then runs down one frame at a time. Every fifteen seconds of that countdown, the EVA line for an approaching ion storm plays and an on-screen message holds for ten seconds. At the default of 31 seconds the warning is therefore announced twice, 30 and 15 seconds out. Setting IonStormWarning=0 breaks the storm on the frame the action or mission runs.

A second start request during the countdown keeps the shorter of the two countdowns, but replaces the pending duration outright, so the storm arrives on the earlier schedule and runs for the later request’s length.

When the countdown reaches zero the engine, in order:

  1. Cuts the power to every aircraft and hovercraft that is out of limbo — the objects whose locomotor is one of the two ion-sensitive ones — and crashes the aircraft among them.
  2. Sets the desired ambient light to IonAmbient and marks the player’s radar for re-evaluation.
  3. Remembers which music track is playing and stops it.
  4. Retints every terrain lighting table, and the shape remap table of every color scheme carrying more than one intensity level, to IonRed, IonGreen, and IonBlue. Screen static is tiled over the tactical view while those palettes are rebuilt.
  5. Starts the music track registered as IONSTORM and posts an on-screen ion-storm message for ten seconds. No EVA line accompanies the break itself — the approach warnings are the only spoken cue.

Every frame of a storm draws one number from 0 through 1000 inclusive and calls a bolt when it falls below ten times IonLightningFrequency. At the default of 25 that is a bolt on roughly one frame in four. The multiplication is part of how the value is read, so the figure written in [General] is a tenth of the threshold actually compared.

IonLightningRandomness is the percentage of bolts that land on a random cell. The remainder are aimed at an object.

A random bolt draws a cell from the map rectangle — the upright square of cells that encloses the playfield — and redraws until the cell lies inside the playfield, so a bolt never falls on a cell the map does not have.

An aimed bolt builds a candidate list by walking every active object on the map, regardless of house. Aircraft are dropped at once. Each of the rest is put through one exemption and then rolled against a chance that its own kind and state decide.

An object survives the exemption under any of:

  • it is a building, which is never on a team at all;
  • it is on no team, or its team’s TeamType is not IonImmune=yes;
  • its own type carries LightningRod=yes, which overrides the exemption whatever the TeamType says.

The table then gives the chance each survivor is rolled against. What to read off it is how much a lightning rod is worth and where it stops being worth anything: twenty-one times the base chance on a switched-on building, six times it on something that moves, and nothing at all once the thing carrying it goes dark, since a rod on a switched-off building and a rod on a vehicle or infantryman whose locomotor has lost power both fall back to the base figure rather than dropping the object out.

CandidateChance of entering the list
Any building, vehicle or infantryman not covered by a row below2%
Building with LightningRod=yes that is switched on42%
Vehicle or infantryman with LightningRod=yes whose locomotor still has power12%
Aircraftexcluded before the exemption is reached

One entry is then drawn from the finished list with equal probability and its center cell is struck. An empty list produces no bolt on that frame, so a storm over a map with no objects and IonLightningRandomness=0 never strikes anything.

The strike point is the cell’s ground level, raised by the bridge height when the cell lies under a bridge. At that point the engine:

  • plays LightningSound without a position, so the clap is at full volume wherever on the map the bolt lands;
  • creates the combat animation selected by IonLightningDamage, IonStormWarhead, and the cell’s land type;
  • adds a spotlight flash when that warhead carries Bright=yes;
  • applies IonLightningDamage through IonStormWarhead across the standard 1.5-cell explosion radius, with no source recorded, so no house is credited with a kill;
  • throws between two and six animations drawn from MetallicDebris under any of:
    • the building standing in the cell after the blast is not the one that stood there before it;
    • the vehicle, infantryman or aircraft in the cell is likewise not the one that was there before it;
    • the cell’s terrain height changed;
    • the cell held neither a building nor any such object to begin with and its land type is road, rock, wall or weeds — this last term asks for no change at all, so an empty stretch of road throws debris on every strike;
  • draws the bolt itself as a chain of laser segments climbing from the strike point to 200 height levels, each segment displaced by up to 128 leptons horizontally.

A vehicle, infantryman or aircraft on a team whose TeamType carries IonImmune=yes takes no damage from the blast. Unlike the candidate list above, this test does reach aircraft. It is also keyed to the warhead rather than to the storm: any weapon configured with the same warhead as IonStormWarhead skips such objects in the same way.

Lightning strike at… calls this same routine at its waypoint cell. It is independent of the storm state and works whether or not a storm is running.

Each of the two ion-sensitive locomotors carries its own exemption, and the two are not the same shape.

The flying one has a single term: an object on the flying locomotor whose type carries HunterSeeker=yes is never sensitive.

The hover one is two separate exemptions rather than one two-part test, and either alone spares the object. An object on the hover locomotor is exempt under any of:

  • it is in radio contact with a building whose type is WeaponsFactory=yes;
  • it stands on one of a WeaponsFactory=yes building’s own doorway cells — the second row of that building’s foundation, at zero, two, or three cells across.

Either way a storm cannot strand a newly built vehicle in the doorway. The exemption is re-tested rather than remembered: a hover object handed a move order while a storm is running puts itself through both terms again on the spot, and cuts its own power there and then if neither still holds.

An unpowered locomotor carries its object nowhere, which is also part of what an EM pulse does. A storm stops there: it does not stun, so a grounded hovercraft may still fire. An aircraft that was moving tumbles, stops, and sinks; a hovercraft abandons its move order, drifts as it settles, and comes to rest on the slope of the cell beneath it. An object created during a storm arrives with its locomotor already off.

Cutting the power to a sensitive flying locomotor also puts the aircraft through the crash path: one that is off the ground at all has its strength set to zero with no kill credited, kills its cargo, and starts tumbling. One that was already on the ground is only powered off, because the crash path does nothing at zero height.

For the rest of the storm no aircraft may fire at all, whatever its weapons, and a repair or reload building an aircraft is parked on will not restore its power. Aircraft are also skipped when lightning picks a target.

The jumpjet locomotor is not ion-sensitive and keeps its power, but a storm handles it separately and more harshly. A jumpjet that is moving and not on the ground takes damage equal to its whole current strength through the [CombatDamage] warhead C4Warhead with no source, which destroys it. Its locomotor ends that frame as soon as the damage destroys or otherwise removes the infantryman, without taking another flight-state step. A grounded jumpjet cannot take off: it never leaves its grounded flight state, and the decision to make a trip by air is refused for the duration. Move-order resolution demotes a flyer movement zone to the infantry movement zone while a storm runs, so surviving jumpjets route on foot.

The player’s house loses radar outright for the duration. The radar availability pass refuses the radar while a storm is running, before it looks at power or at radar buildings, and switches the map’s radar off. Only the player’s own house is evaluated, and coverage is recalculated on the first house pass after the storm ends.

  • A weapon with IonSensitive=yes cannot fire for the duration.
  • A factory that finishes an aircraft during a storm places it on a nearby free cell instead of docking it.
  • A service depot does not power a docked vehicle back on during a storm, and neither does a repair building the vehicle is standing on.

A scenario’s [Lighting] section carries two complete sets of values: the ordinary Ambient, Red, Green, Blue, Ground, and Level, and their Ion counterparts. While a storm is active, cell brightness is computed from IonLevel and IonGround in place of Level and Ground, the height bonus drawn onto aircraft and onto elevated vehicles and infantry uses IonLevel as well, and any lighting table built while the storm runs — the terrain one a newly lit cell asks for, or a color scheme’s shape remap table — is created with the ion tint already applied.

The two halves of the change do not run on the same clock. The palette tint is applied outright when the storm breaks and reversed outright when it ends. The ambient level is only a target: the storm sets the desired level to IonAmbient, and the ramp below carries the current level toward it over time.

Each ion key falls back to the ordinary key read earlier in the same section, so a map that sets only Ambient, Red, Green, and Blue gets ion values to match. The ground and level keys are the exception.

Whenever the current ambient level differs from the desired one, the engine waits AmbientChangeRate minutes — 900 frames to the minute — and then moves the current level by AmbientChangeStep times 100, clamped so it never passes the target. The storm’s darkening and the return to daylight both travel this way.

Every completed step raises the ambient-changed flag, which is what admits Ambient light <= … and Ambient light >= … to that frame’s trigger evaluation. Those events are therefore tested only while a fade is stepping, and a storm’s darkening and its return to daylight are each a run of such frames.

Set ambient light... stores its new level immediately but withholds the fade while a storm is running; the map travels to it once the storm clears. Set ambient rate… and Set ambient step… overwrite the ramp’s rate and step in the loaded rules, and those overwrites outlive the storm.

A storm ends when its duration elapses, or when Ion Storm stop... or Ion storn end runs. The engine then:

  1. Restores the power of every aircraft and hovercraft, including the ones in limbo that the opening pass skipped.
  2. Sets the desired ambient light back to Ambient, so the map fades home rather than snapping.
  3. Marks the player’s radar for re-evaluation.
  4. Stops the storm music track and resumes the one that was playing when the storm broke.
  5. Returns every terrain lighting table and every color scheme’s shape remap table to its remembered tint, again behind screen static.

Losses are permanent. Aircraft that crashed and jumpjets that were destroyed do not come back, and nothing schedules a repeat: another storm needs another trigger action or team mission.

Two settings look like ion-storm controls and are read into the engine, but nothing consults them. IonStormDuration in [General] is not a default storm length — every storm’s length comes from the number its trigger action or team mission carries. IonStorms in [SpecialFlags] does not gate storms; scripted storms run whether it is set or cleared. The ion-storm crate result is inert in the same way: drawing it consumes the crate and plays that row’s own animation, and no storm starts. Crates owns that result.

26 of 26

KeyDescriptionValueWhen omitted
AmbientscenariosThe scenario's overall light level, where 1 is full daylight.floating point1
AmbientChangeRateglobal rulesMinutes between one step of the ambient light fade and the next.floating point.2
AmbientChangeStepglobal rulesHow far the ambient light moves on each step of a fade, as a fraction of full ambient light.floating point.1
BluescenariosThe scenario's blue palette tint, where 1 leaves the blue channel unchanged.floating point1
GreenscenariosThe scenario's green palette tint, where 1 leaves the green channel unchanged.floating point1
GroundscenariosA flat darkening subtracted from every cell's brightness, as a fraction of full light.floating point0
HunterSeekerAircraftType, BuildingType, InfantryType, UnitTypeMakes the type a hunter-seeker drone that acquires its own target, moves straight at it, and is never grounded by an ion storm.booleanno
IonAmbientscenarios, random map generationThe overall light level in force while an ion storm is running, where 1 is full daylight.floating pointContext-dependent
IonBluescenarios, random map generationThe blue palette tint in force while an ion storm is running, where 1 leaves the blue channel unchanged.floating pointContext-dependent
IonGreenscenarios, random map generationThe green palette tint in force while an ion storm is running, where 1 leaves the green channel unchanged.floating pointContext-dependent
IonGroundscenarios, random map generationThe flat darkening subtracted from every cell while an ion storm is running, as a fraction of full light.floating pointContext-dependent
IonImmuneTeamTypeExempts the team's members from ion storm lightning damage and from being aimed at.booleanno
IonLevelscenarios, random map generationThe brightness added per height level while an ion storm is running, as a fraction of full light.floating pointContext-dependent
IonLightningDamageglobal rulesThe raw damage each ion storm lightning bolt delivers.integer500
IonLightningFrequencyglobal rulesTen times this value is the chance in 1001 that an ion storm calls down a lightning bolt on a frame.floating point25
IonLightningRandomnessglobal rulesThe percentage of ion storm lightning bolts that fall on a random cell rather than on an object.integer75
IonRedscenarios, random map generationThe red palette tint in force while an ion storm is running, where 1 leaves the red channel unchanged.floating pointContext-dependent
IonSensitiveWeaponTypeStops the weapon from firing while an ion storm is running.booleanno
IonStormWarheadglobal rulesSelects the WarheadType every ion storm lightning bolt detonates with.classnone
IonStormWarningglobal rulesSeconds of warning between a scripted ion storm being ordered and the storm breaking.integer31
LevelscenariosThe brightness added for each height level a cell stands above the ground, or the height added to every cell of the map.integer0
LightningRodAircraftType, BuildingType, InfantryType, UnitTypeRaises the type's chance of being picked as the target of an ion storm lightning bolt.booleanno
LightningSoundglobal rulesSelects the sound played by each ion storm lightning bolt.soundnone
MetallicDebrisglobal rulesThe animations three different paths throw up as wreckage — an ion storm strike, a collapsing bridge, and an object destroyed with no debris types of its own.typelist(empty)
RedscenariosThe scenario's red palette tint, where 1 leaves the red channel unchanged.floating point1
UseIonStormsrandom map generationWhether random map generation folds the ion storm file into the map it builds.booleanUnchanged

History

  1. Changed0.1.0In development

    Stop jumpjet flight processing after ion-storm destruction