Persistent campaign mode

State carries across sessions.

A multi-session campaign you can chip away at over weeks. Kills stay killed, captured bases stay captured, author flags carry across server restarts.

When persistence makes sense

Persistence is fundamentally a PvE pattern. Pure PvP is one-shot — fight the round, score it, done. The scenarios where persistence delivers real value:

  • PvE campaigns — squadron chips away at a fixed enemy IADS / force-package over multiple nights (the canonical use case)
  • PvP base-capture — WW2-style front line where captured airbases stay captured between sessions
  • Dynamic-faction wars — long-running scenarios with territorial state (think Liberation, but multi-night)

Pure dogfight PvP doesn't benefit — there's nothing to persist between sessions if the round is decided before the server stops.

The squadron-night flow

  1. Squadron flies the campaign mission Wednesday evening. Three SAMs killed, one airbase captured.
  2. End of night: drop to a training mission as a “parking spot” so the server stays online but doesn't advance the campaign.
  3. Saturday morning: load the campaign mission again. The framework finds the prior save, destroys the killed groups, restores the captured-base flag, picks up where Wednesday left off.
  4. Repeat over weeks. The squadron has an ongoing war they hop into when they have time.

What persists (v1)

  • Dead unit IDs — every unit destroyed during the session
  • Dead group IDs — when a whole group is wiped, the parent group is recorded too
  • Author-range flags 600-899 — captured-base flags, scoring counters, mission-state flags
  • Session counter — monotonic, tells you which session this is

What does NOT persist (v1)

  • Airborne unit positions (DCS hates re-spawning airborne — they'd come back at home base)
  • Per-player kills / scoreboards (defer to v2 once we have player-id tracking)
  • Damaged-but-alive units (DCS doesn't expose damage state cleanly)
  • SAM ammo counts (DCS doesn't expose magazine state)

How it works under the hood

Every persistent .miz bundles a Fox3Persistence.lua framework that:

  • Hooks S_EVENT_DEAD to track destroyed units in real-time
  • Writes the save file every 60 seconds (heartbeat) and on S_EVENT_MISSION_END (last-gasp save)
  • On mission load, reads the save file and calls Group:destroy() on the units that were dead, sets the saved flag values
  • Save file format: JSON, atomic write via .tmp + rename so a server crash mid-write can't corrupt the save
  • Save file location: Saved Games/DCS.openbeta_server/Fox3_Persistence/{mission_id}.json

The mission_id is derived at build time from map + era + scenario + player_composition hash — so if you re-build the same scenario with new fragments, the save file carries over. Different scenarios get different saves automatically.

⚠️ When triggers actually fire

Fox3Persistence loads via a DCS triggerStart rule. These rules fire once the simulation clock actually advances — which on a multiplayer server with pause_on_load = true (the default) means once the first player connects + slots in.

On a single-player editor open, or a server with pause_on_load = false, the trigger fires immediately. On a typical MP server, it fires the moment a real pilot slots in. Once it fires, the framework runs forever (heartbeat + event hooks), even after that pilot leaves — so the save-on-exit still works for a server that goes empty mid-session.

Server requirements

Fox3-fleet servers: nothing to do — your MissionScripting.lua already has os/io unsanitized (needed for SRS-TTS, MOOSE, MIST, etc.). Persistence works out of the box.

Non-Fox3 servers: edit Scripts/MissionScripting.lua in the DCS install — comment out the sanitizeModule('io') and sanitizeModule('os') lines. One-time setup. (Most communities running MOOSE/MIST/CTLD already have this done.)

How to use it

  1. On /build, expand the Build Options section.
  2. Toggle Persistent campaign mode.
  3. Build + download the .miz. Place it in your server's Missions folder.
  4. Load it for your first session. Fly. Save state writes automatically every 60s + at mission end.
  5. Next session: load the same mission. Watch the dcs.log for Fox3Persistence: vN.N.N loaded prior save: session 1 -> 2, destroyed K groups, restored M flags.

Resetting a campaign

Delete the save file at Saved Games/DCS.openbeta_server/Fox3_Persistence/{mission_id}.json on the server. Next mission load starts fresh.

Roadmap to v2

  • Per-player kill / score persistence (linked to player UCID)
  • Web visibility — your /history page shows current campaign state with a map view
  • Multi-server snapshot routing — campaign state can move between servers in your fleet
  • Auto-rotation — server alternates between campaign + training mission on a schedule
  • Discord webhook updates — “Blue captured Senaki at 21:14 UTC”