Skip to content

Context Sensitive Radio

Will edited this page Aug 27, 2026 · 1 revision

Context-Sensitive Radio

Context rules select station content by game time, weather, city happiness, or active disasters. Turn on Context-sensitive content under the mod's Content settings.

Schema

filters object   OPTIONAL

Use filters when several contexts share a condition. Each key defines a case-sensitive name that a conditions branch can reference.

{
  "filters": {
    "filterName": { "type": "time", "from": 0, "to": 24 }
  },
  "contexts": [
    {
      "conditions": [["filterName"]],
      "collections": ["string"]
    }
  ]
}

You can place a condition object inside a branch instead of naming it:

{
  "conditions": [
    [
      { "type": "time", "from": 0, "to": 24 }
    ]
  ]
}
contexts object[]

Selects collections and songs through named or inline conditions.

conditions array[]   REQUIRED

conditions uses disjunctive normal form. The outer array contains OR branches; every term inside one branch must match.

{
  "conditions": [
    ["filterName1", "filterName2"],
    ["filterName3"]
  ]
}

This example means:

(filterName1 AND filterName2) OR filterName3

The loader checks contexts in array order and returns songs from the first match. Put narrow rules before broad rules. With no match, the station can use all assigned content.

not boolean   OPTIONAL

Add not to any condition object and set it to true to invert that condition's result.

{ "type": "time", "from": 0, "to": 24, "not": true }
songs string[]   OPTIONAL

Restricts a context to exact display names. A display name omits .ogg and any recognized content-type suffix from the filename.

{
  "conditions": [["filterName"]],
  "collections": ["string"],
  "songs": ["string"]
}

Omit songs or leave it empty to include each song in the selected collections.

{
  "contexts": [
    {
      "conditions": [["filterName"]],
      "collections": ["string"],
      "songs": ["string"]
    }
  ]
}

A condition term can reference filters by name or contain an inline condition object. The loader logs an unknown filter name and adds no condition to that branch.

The loader checks contexts in array order and uses the first match. With no match, it permits all content assigned to the station.

Condition types

time condition object
Field Type Required Behavior
type string Yes Must be time.
from integer Yes Start hour from 0 through 24.
to integer Yes End hour from 0 through 24.
not boolean No Inverts the condition result when true.

The loader includes both endpoints. A from value greater than to crosses midnight, so 20 to 6 covers the night. Equal values cover the full day in the current loader.

{ "type": "time", "from": 0, "to": 24, "not": false }
weather condition object
Field Type Required JSON scale Loader comparison
type string Yes weather Selects this condition type.
temperature integer[2] No -100 to 100 No scaling.
rain integer[2] No 0 to 10 Divides each value by 10.
cloudy integer[2] No 0 to 10 Divides each value by 10.
foggy integer[2] No 0 to 10 Divides each value by 10.
rainbow integer[2] No 0 to 10 Divides each value by 10.
northernlights integer[2] No 0 to 10 Divides each value by 10.
not boolean No true or false Inverts the condition result when true.

The loader gives omitted weather fields their full default ranges. Each specified range must match.

{
  "type": "weather",
  "temperature": [-100, 100],
  "rain": [0, 10],
  "cloudy": [0, 10],
  "foggy": [0, 10],
  "rainbow": [0, 10],
  "northernlights": [0, 10],
  "not": false
}
mood condition object
Field Type Required Behavior
type string Yes Must be mood.
from integer Yes Minimum city happiness percentage.
to integer Yes Maximum city happiness percentage.
not boolean No Inverts the condition result when true.

The loader includes both endpoints when it compares the range with the city's final happiness value.

{ "type": "mood", "from": 0, "to": 100, "not": false }
disaster condition object
Field Type Required Behavior
type string Yes Must be disaster.
from integer Yes Minimum active-disaster count.
to integer Yes Maximum active-disaster count.
of string[] No Restricts the count to exact internal disaster prefab names.
not boolean No Inverts the condition result when true.

The loader includes both count endpoints. If you omit of or leave it empty, the loader counts each active disaster.

Enable Detailed logging, load a city, and search the game log for [DisasterContext] Disaster names to find names available in your installed game and DLC set.

{
  "type": "disaster",
  "from": 0,
  "to": 256,
  "of": ["string"],
  "not": false
}

Examples

The examples below use JSONC-style // comments for explanation. Remove the comments before saving a strict JSON file.

Example (from schema)
{
  "name": "string", // Required station identifier.
  "collections": ["string"], // Optional base collections.
  "filters": {
    "timeFilter": {
      "type": "time", // Time range includes both endpoints.
      "from": 0,
      "to": 24,
      "not": false
    },
    "weatherFilter": {
      "type": "weather", // Omitted weather ranges use their full defaults.
      "temperature": [-100, 100],
      "rain": [0, 10],
      "cloudy": [0, 10],
      "foggy": [0, 10],
      "rainbow": [0, 10],
      "northernlights": [0, 10],
      "not": false
    },
    "moodFilter": {
      "type": "mood", // Compare the city's final happiness percentage.
      "from": 0,
      "to": 100,
      "not": false
    },
    "disasterFilter": {
      "type": "disaster", // Count active disasters; add "of" to filter by prefab name.
      "from": 0,
      "to": 256,
      "of": ["string"],
      "not": false
    }
  },
  "contexts": [
    {
      "conditions": [["timeFilter", "weatherFilter"], ["disasterFilter"]], // (time AND weather) OR disaster.
      "collections": ["string"], // Collections enabled by this context.
      "songs": ["string"] // Optional exact display-name filter.
    }
  ]
}
Example
{
  "name": "Responsive Radio", // Station identifier.
  "collections": ["Day", "Night", "Emergency"], // All collections the contexts may use.
  "filters": {
    "night": { "type": "time", "from": 20, "to": 6 }, // Night crosses midnight.
    "unhappy": { "type": "mood", "from": 0, "to": 35 }, // Happiness from 0% through 35%.
    "disaster": { "type": "disaster", "from": 1, "to": 256 } // At least one active disaster.
  },
  "contexts": [
    {
      "conditions": [["disaster"]], // Highest priority: emergency content.
      "collections": ["Emergency"]
    },
    {
      "conditions": [["night", "unhappy"]], // Nighttime and low happiness.
      "collections": ["Night"]
    },
    {
      "conditions": [["night"]], // Other nighttime situations.
      "collections": ["Night"]
    }
  ]
}

The loader chooses the disaster context first. Daytime without a disaster matches no context, which permits content from Day, Night, and Emergency. Add a broad daytime context at the end to block that fallback.

Clone this wiki locally