Airtime docs Play ▸

The map format

An Airtime map is two layers (engine.md):

  • The collision layer (where you can run, jump, slide, swim and water-jump) is Quake 3 brushes and patches, simulated exactly like Urban Terror. It decides every time on every board.
  • The visual layer (everything you see) is modern: meshes, physically based materials, light, sky and effects. It can change at any time without touching a single record.

The map also carries what Quake 3's BSP never could: typed entities, routes, medals, rules and metadata. Section 3 is the collision layer (built from the pieces in section 4), section 5 the visual layer.

What a map holds#

1. Identity and metadata#

  • Name, authors, version, created / updated dates, license, credits (e.g. Rambetter's curve generators).
  • Description, tags, difficulty tier per route, levelshots and preview video.
  • Content hash of the collision and gameplay data. Boards and replays point at it. A change in looks only (light, materials) keeps the hash; a change in collision makes a new one.

2. Rules#

  • The rule set the map is played with: the settings (g_stamina, g_walljumps, g_gravity, g_allowPosSaving, …) and the moves the map uses (gravity zones, a jetpack, air jumps, …). The boards follow it automatically.
  • What is allowed: save / load, practice tools, styles, and weapons: the knife and pistol for shootable triggers, or a gun in sections built for it. Movement comes first; gunplay is secondary.

3. Collision (the exact part)#

  • Convex brushes and patches exactly as Quake 3 traces them: our collision is bit-identical to ioq3's cm_*. Stored compactly, loaded into the same structures.
  • Contents per brush: solid, player clip, water / slime / lava (swimming, water jumps), trigger.
  • Surface flags per side, named directly: normal, slick, icy (looks), ladder, no walljump, no fall damage, no impact, player clip vs. visible, and Airtime surfaces such as bounce and wall-run. (Classic maps encode these in Q3 shader names like _sl, _icy, SURF_SLICK; the importer translates them.)
  • The source of each brush: which piece or curve made it, for the editor, for error messages ("the curve at … has an open edge") and for the curve clip checks.
  • Checks at build time: no gaps or wrong clip strips on curves, no leaks, spawn present, every route complete.

4. Pieces (the editable source)#

  • What the editor works on: boxes, ramps, curves (Rambetter's generators and assemblies) and decorative meshes. Each has an id that never changes, so edits, undo and building together can refer to it.
  • The compiled collision is derived from pieces. A map holds both: the source for editing, the compiled part for playing without compiling.

5. Visuals (separate from collision)#

  • Materials: physically based (base colour, roughness, metal, normal, emissive), with the slick / icy look as material layers (gloss, frost). Q3 shaders stay supported for classic maps.
  • Render geometry: finer than collision (rounded edges, decorative meshes), as long as what you see never lies about where you can stand. Decoration that isn't solid is marked as such.
  • Light: the sun, sky and light entities as data. Baked light (lightmaps, light probes) as a build output, cached and rebuilt when geometry changes, plus real-time light.
  • Environment: sky, fog, time of day, weather, ambient sound zones, music.

6. Gameplay entities (typed, not key / value text)#

EntityFields
Spawnposition, yaw, which route
Timer gatessee timing/triggers.md: start, stop, cancel, checkpoint, stage, filters
Teleportvolume, destination, keep / set velocity (UrT: 400 ups exit, dest +1 z)
Jump pad, pushvolume, velocity or target
Mover, door, buttonpath, speed, trigger (shootable or touched)
Filtersspeed, stamina, run, team (from Fliserv, the UJM servers' custom server)
Move elementsgravity zones and switches, zones (shape, condition, effect: push, teleport, reset, gravity, stamina, …), power-ups (kind, respawn), route pads
Enemies (story)pursuer type, path (a recorded trace), weapon, seed
Print / guide textmessage, who sees it
Light, soundposition, colour, range / file, volume
Hint markersleet gates, runner-vision lines, camera spots for levelshots

Each entity has a stable id. Links between entities are ids, not target names.

7. Routes and the run structure#

  • A list of routes: name, colour, start gate, stop gate, checkpoints (required or not, in order or free), stages, tier, medal times (finished / bronze / silver / gold / author). Routes refer to gates by id, so several routes can share a start or a stop and differ only in their checkpoints (timing/triggers.md).
  • Bonuses, leets and secrets as named items.
  • This is data, so the HUD, the scoreboard and the boards read it directly.

8. Packaging#

  • One file per map version: a small manifest (metadata, rules, routes, hash) plus content blobs (collision, pieces, render data, light, textures, sounds).
  • Content-addressed blobs (hash names), so shared textures and sounds are downloaded once and a new map version only downloads what changed.
  • The manifest can be read without the rest (map browser, boards).
  • Streaming: the map is playable before all textures have loaded.

Classic maps#

  • Import UrT BSPs: the thousands of existing jump maps load as they are. Their entities map onto the typed entities (ut_jumpstart → start gate of route "type", and so on), and a timing overlay adds checkpoints or fixes broken timers without touching the BSP (like surf zones).
  • A modern visual layer for a classic map can be made without touching its collision, so its records stay valid.
  • Export to UrT: a map that stays within UrT's rules and stock entities exports to BSP and .map (Radiant) and plays in real UrT. Airtime-only features are listed when exporting.

Open questions#

  1. One file with everything, or source and compiled data separate (editor file vs. play file)?
  2. The BSP tree for collision, or a new acceleration structure that gives exactly the same traces? (Exactness first: only if it is proven bit-identical.)
  3. Mesh collision for decorative pieces: allowed, or only brushes and patches?
  4. How is the hash taken: per route (only that route's area), or the whole map?