Event authoring
More actions
New Stars game events — the discoveries and disasters that fire as the galaxy lives — are written as plain YAML files. The same format powers the game's own built-in events and any events you ship in a content pack, so anything the base game does, your pack can do too.
This page is the full reference: where event files go, the anatomy of an event, and every condition, selector and effect you can use.
For the panels that publish and toggle packs, see Modding.
Where event files go
Put one event per .yaml (or .yml) file in your pack's Events/ folder:
My Pack/
Events/
meteor_shower.yaml
rogue_ai_uprising.yaml
- One event per file. The file name is up to you; the event's identity is the
idfield inside. - Files in
Events/andEvents/Game/are both scanned (use the subfolder only if you like to keep things tidy). - Enabling or disabling the pack in the Mod Manager adds or removes its events immediately — no restart.
- Unknown fields are ignored, so a pack authored against a newer version of the game still loads on an older one.
The game's built-in events live the same way, shipped inside the game and seeded into your save folder on launch; a pack can override a built-in by declaring the same id.
Anatomy of an event
```yaml id: mypack:meteor_shower # required — unique, namespace it to your pack type: natural # natural | colony roll:
scope: per_system # per_system | per_colony once_in_years: 8 # average cadence; OR a flat `probability: 0.05`
can_instigate: "is_colonized and is_disaster_prone" meta: system.world # the subject shown in text/UI sfx: Game_Event_Fail # optional SFX clip name text:
title: "Meteor Shower"
description: "A meteor shower batters {meta}."
on_instigate: # effects applied when the event fires
- op: damage_buildings
options: # the player's choices (optional)
- title: "Unfortunate."
```
| Field | Required | Meaning |
|---|---|---|
id |
yes | Unique identity, namespaced to your pack — e.g. mypack:meteor_shower. Built-in events use the core: namespace; reuse a core: id to override a built-in.
|
type |
yes | Event category. natural and colony events are rolled each in-game month. (global and planet are reserved for future use.)
|
roll |
no | How often the event is considered (see below). |
can_instigate |
no | A condition that must hold for the event to fire. Empty means "always". |
meta |
no | A selector picking the event's subject (a planet or star), shown via the {meta} text token.
|
sfx |
no | Name of the sound clip to play (e.g. Game_Event_Normal, Game_Event_Fail, Game_Event_Success).
|
text |
no | title and description shown on the event pop-up.
|
on_instigate |
no | Effects applied on the server the moment the event fires. |
options |
no | The player's choices. If omitted, a single "Interesting." acknowledgement is shown. |
roll
| Key | Meaning |
|---|---|
scope |
per_system or per_colony — documents the intent; the real gate is can_instigate.
|
once_in_years |
The event averages once every N in-game years. Use this or probability.
|
probability |
A flat per-roll chance, 0–1. Set probability: 0 for an event that only ever fires as a chain outcome (never on its own).
|
Conditions
can_instigate is a short expression. Combine atoms with and / or, and negate any atom with not. and binds tighter than or, so a and b or c means (a and b) or c. An empty expression is always true; an unrecognised atom is treated as false.
| Atom | True when… |
|---|---|
is_owned |
the system has an owner |
is_colonized |
the system has a colony |
world_exists |
the system has a colonisable world |
is_disaster_prone |
the world is disaster-prone |
has_star(TYPE) |
a star of TYPE is present (e.g. has_star(M))
|
has_feature(FEATURE) |
the world has a planet feature (e.g. has_feature(Dangerous_Wildlife))
|
|
the world's climate is X (also for "isn't")
|
A leading system. or world. on the flag atoms is accepted and ignored.
Example:
Selectors
A selector picks an object for meta or for an effect's target.
| Selector | Resolves to |
|---|---|
system.world / world / planet |
the system's colonisable world |
system.colony.world / colony |
the colony's world |
system.first_star |
the first star in the system |
system.first_star(TYPE) / star(TYPE) |
the first star of TYPE
|
owner / explorer |
the system's owner (a player) |
Effects
Each entry in on_instigate (and in an option's effects) is an op plus its parameters. Effects run on the server, and their world changes replicate to every player. An unknown op, or an out-of-range value, is skipped safely — it never crashes the game.
| op | Parameters | Effect |
|---|---|---|
grant_resources |
to: owner or world, resources: |
Adds resources to the owner's balance, or to a world's trade value |
add_collection_value |
target:, resources: |
Adds to a planet's trade value |
damage_buildings |
— | Damages the colony's buildings |
set_climate |
target:, climate: or random_of: [ … ] |
Sets a planet's climate (or picks one at random) |
set_planet_type |
target:, planet_type: |
Sets a planet's type |
set_star_type |
target: (or all_stars), star_type: |
Sets a star's type — or every star's, with target: all_stars
|
regenerate_trade_value |
target: |
Re-rolls a planet's or star's trade value |
start_storm |
storm:, radius: self or neighbours |
Starts a storm in the system (optionally its neighbours too) |
remove_feature |
feature: |
Removes a planet feature from the world |
If target is omitted, world-targeting effects act on system.world.
Resource names
Resource tables use these names (case-insensitive):
gold energy minerals metals food power science antimatter pink_plasma crimson_stardust golden_spice
```yaml resources:
minerals: 200 science: 25 crimson_stardust: 10
```
Value names
climate, planet_type, star_type, storm and feature take the game's own names (the same words shown in-game, with spaces written as underscores). A few common ones:
| Kind | Examples |
|---|---|
| Star type | M, A, O, White_Dwarf, Neutron_Star, Black_Hole, Pulsar
|
| Climate | Pristine, Arid, Ice, Rocky, Molten, Toxic, Void
|
| Planet type | World, Barren, Asteroid
|
| Storm | Solar_Storm
|
| World features | Exotic_Planet_Life, Unpredictable_Weather_Patterns, Unique_Wildlife, Dangerous_Wildlife, Dense_Forests, Abandoned_Alien_Colony, Geothermal_Hot_Springs, Abundant_Natural_Wonders, Widespread_Volcanic_Regions, Extreme_Polar_Regions
|
An unrecognised value makes that effect a no-op, so a typo fails quietly rather than breaking the game.
Text tokens
In title and description, these tokens are replaced with highlighted in-game names:
| Token | Becomes |
|---|---|
{meta} |
the event's subject (from the meta selector)
|
{subject} |
the star system |
{species} |
the owner's species |
Anything else is shown literally.
Options and chains
Options are the buttons on the event pop-up. They surface to the player exactly like built-in events, in single-player and multiplayer (events are rolled on the server and shown on every client). An option can do one of two things:
- Instant — apply
effectsthe moment it's chosen. - Timed branch — wait
durationmonths, then roll one of a weighted set of follow-up events (chain), which may be your own events.
| Option field | Meaning |
|---|---|
title |
Button label. |
summary |
Tooltip line. If omitted, one is derived from the option's reward effects ("Get 50 Science."). |
cost |
A resource table the player pays when choosing. |
duration |
Months to wait before the chain rolls (omit for an instant option). |
effects |
Effects applied when chosen (instant options). |
chain |
A weighted map of weight: "event id" outcomes.
|
```yaml options:
- title: "Ignore it."
duration: 2 # months
chain:
0.65: "mypack:bad_outcome"
0.35: "mypack:good_outcome"
- title: "Pay to fix it."
cost: { energy: 150 }
effects:
- op: grant_resources
to: owner
resources: { science: 50 }
```
A chain ends when it reaches an event whose options don't branch any further: that outcome's effects apply and the quest closes. Give each chain-outcome event roll: { probability: 0 } so it only ever fires through the chain, never on its own.
Worked examples
A colony disaster
```yaml id: mypack:reactor_meltdown type: colony roll:
scope: per_colony once_in_years: 40
can_instigate: "is_colonized" meta: system.world sfx: Game_Event_Fail text:
title: "Reactor Meltdown"
description: "A containment failure devastates {meta}."
on_instigate:
- op: damage_buildings - op: set_climate target: world climate: Toxic
options:
- title: "Rebuild."
```
A reward gated on a feature
```yaml id: mypack:crystal_caverns type: colony roll:
scope: per_colony once_in_years: 2
can_instigate: "is_colonized and has_feature(Rare_Crystals)" meta: system.world text:
title: "Crystal Caverns"
description: "Surveyors find rich crystal seams under {meta}."
options:
- title: "Mine them."
effects:
- op: grant_resources
to: owner
resources: { minerals: 200 }
- title: "Study them."
effects:
- op: add_collection_value
target: world
resources: { science: 2 }
```
A branching disaster
```yaml id: mypack:gamma_burst type: natural roll:
scope: per_system once_in_years: 50
can_instigate: "is_owned and has_star(M)" meta: system.first_star(M) sfx: Game_Event_Fail text:
title: "Gamma Burst Warning"
description: "{meta} is about to flare. {subject} has little time to react."
options:
- title: "Shield the colony. (costs energy)"
duration: 1
cost: { energy: 200 }
chain:
0.80: "mypack:gamma_burst_averted"
0.20: "mypack:gamma_burst_impact"
- title: "Do nothing."
duration: 1
chain:
0.50: "mypack:gamma_burst_impact"
0.50: "mypack:gamma_burst_averted"
---
- (in its own file: gamma_burst_impact.yaml)
id: mypack:gamma_burst_impact type: natural roll: { probability: 0 } meta: system.world text:
title: "Gamma Burst"
description: "The flare scorches {meta}."
on_instigate:
- op: damage_buildings
options:
- title: "Unfortunate."
```
(Reminder: keep each event in its own file — the --- above is only to show the two together.)
Tips and troubleshooting
| Symptom | Cause / fix |
|---|---|
| The event never fires | Check can_instigate actually passes (e.g. the system is colonized), and that roll isn't probability: 0 unless it's a chain outcome. Events only roll during play — give them time.
|
| A reward or climate change does nothing | A misspelled resource, climate, star type or feature name makes that effect a no-op. Use the in-game names with underscores for spaces. |
| The whole event doesn't load | It needs a unique id and a type of natural or colony; otherwise it's skipped. Confirm the pack is enabled in the Mod Manager.
|
| A chain never ends | Make sure the final outcome's options have no chain — that's what closes the quest.
|
| My event clashes with a built-in | Reusing a core: id overrides that built-in; use your own mypack: namespace to add alongside instead.
|