five-on-it / packages/missions/src/runtime
packages/missions/src/runtime
The mission interpreter (TECHNICAL_SPECS §9.5). It owns no simulation: every step the host (the game server) hands it the facts (the tick, where each player is and how healthy and what they carry, where each mission vehicle is, how healthy, who drives it, whether it is locked and what was done to it (carjacked, picked, resprayed, stored), the mission's garages and who and what stands in their bays, where each member of a mission's groups of enemies is and whether it is still standing, the mission's items on the ground, containers, doors, people and terminals, what the players did with items since the last step, and what they asked of their phones and of the people, terminals and keypads in the world) and it answers with commands for the host (spawn a mission vehicle (locked or not, whose, its key), some of a group, items, a container, a person or a terminal at a place, bind a door or a garage, lock a door (by a key or a keypad) or a vehicle or unlock it, give or take items, despawn an actor) and, per player, the view for the mission tracker (when it changed), the notices to show (a line of text, a phone message, a mission started, completed or failed) and the phone (when it changed: phone.ts). Stealth adds its facts (each NPC actor's alert phase and status, each camera actor's state and spots, the compound's alert, the player's kills, alarms and sightings) and its commands (a guard or a civilian put in the level, a camera bound, switched off or on, the alarm raised or called off). The city adds its own (GAME_DESIGN §5.3–§5.7, §14): the facts of the room clock, each player's Cash and the role NPCs (a target threatened or safe, a driver arrived, a VIP's leader and ride, a racer's gates), and the commands of a driver, a target or a VIP put in the level, a shop put at a place, the clock set or run at a pace, a junction's signal switched by hand, a race started for its rivals and a reward paid in Cash. Restricted zones raise zone:<id>.trespass, the clock time:HH:MM as it passes.
The verbs past v1 (GAME_DESIGN §20) add their own: a person handed items at the interaction key (give: the handOver command, the host's handed item event), a VIP brought along (escort: its health, its leader), a target run down (chase: the flee command as it starts, its speed, whether it got away), a photo framed by the host (photograph: what was in it, where it was taken; the phone's camera says how it went), a hold clock (wait), the police or watchers left behind (escape: the stars, an arrest, who sees the player), things destroyed (destroy: wrecks, deaths, a light piece knocked loose, a prop actor's bindProp). A step may be a group of objectives in parallel, each member under way at once with its own progress and events, the group done once enough of them are; the tracker lists them and every target of those under way, and a party's members see each other on it. Rules hear the Wanted level change (wanted:changed|up|down|<stars>), a message with an id read (message:<id>.read) and a prop knocked loose (prop:<id>.destroyed).
Each player plays the game's missions on their own, or with their party (GAME_DESIGN §13: up to four players who joined the room together): a party plays one mission at a time, held by its first member and stepped once with every member's facts, so what one member does advances everyone (anyone of them reaching a zone, driving the vehicle, picking up the item, carrying the items; a hold lasting while any of them stands), they share its objectives, counters, timers, tracker and phone messages, and its reward is paid to each, whole or split (rules.partyRewards); each keeps their own wallet and phone. When the first member leaves, the next takes the mission over, actors and all. A mission that starts on: join starts when the player joins, the next one (in document order, a failed one again) a few seconds after the previous one ended, the tracker saying how it ended meanwhile; a mission that starts on: enter starts when the player walks or drives into its zone with no mission running. Its objectives run one at a time, from the first, along their next when they say where (else in document order; a failure fails the mission); its when rules run on the events of the step (the mission's start, an objective's start, completion or failure, a zone entered or left, a mission vehicle entered, left, wrecked, carjacked, unlocked, picked, stored or resprayed, a garage entered, a timer run out, a group cleared or onto the player, an item picked up, dropped or given, a door opened, shut or unlocked, a container or a terminal opened, a conversation ended, declined or one of its choices picked, an app's button pressed), then its while rules are checked; then the player's phone takes what they asked of it, each choice, reply and button checked against the mission's conditions.
A room's missions are its hub's (the open city: solo missions only, a mission whose play says another mode never starts there) unless the room is a run (TECHNICAL_SPECS §9.5: a room of its own for one mission and its roster of seats, each seat bound to the client that sits in it; RunOptions). A run is held by a stand-in holder, client id 0 (client ids start at 1), for every seat at once: its actors are keyed by owner 0, a player who leaves never takes them or the run away, and a player who comes back takes their seat again under their new client id (MissionRuntime.rebind). Only the run's mission starts, whatever its start says. It keeps the run's lives (per seat or for the team: a seat going down uses one, and the last one used fails the attempt), its retries (a failed attempt goes back to its last checkpoint, or starts over, until they are used up and the run ends failed) and each seat's book (the kills, alarms and sightings of every client that sat in it, so a leaver's stay still counts), its downs and its credit (the objectives it did, the mission's enemies it hit); an action aimed at "the player" goes to the seat that caused the event the rule heard, else to the present seat with the lowest client id. The step that ends the run says so once (MissionOutput.runEnded). A run that takes players under way (joinInProgress) gets a seat added at the end of its roster for each late joiner (MissionRuntime.addSeat): it plays on from the objective under way, its tracker the run's; the run counts the checkpoints its mission saved (RunView.checkpoints: under untilCheckpoint the first closes its seats).
A versus run (GAME_DESIGN §13) plays teams against each other: an objective with a team is checked with that team's members alone and shown on their tracker alone; the run ends won by a team (win:<team> where an objective leads, the action win, the mission completed by one of its players, the last team with anybody left, a forfeit when the others' players left) or a draw (a failure no rule turns into a win), never going back to a checkpoint. A down (or a catch: catch holds a stopped rival near a catcher) uses a life, per seat or per team; a seat out of lives, or caught or down under onDeath: spectate, is out of the run (the host takes it out of the world: spectate), a caught one not out is sent back to its team's spawn (respawn). {team} refs and queries see a team's members standing; the rules hear team:<id>.down|out|caught|wiped; a race is run per seat and places every seat. Co-op's players out to watch fail the attempt only once all of them are.
Deterministic and bounded: time is the tick the facts carry, nothing is random, players are stepped in the order the facts list them (a run's holder first), rules in document order, each while condition once per step. The events an action causes (complete, fail) are handled on the next step and what it spawns appears in the next step's facts, so a rule can never trigger itself within one; the language has no loops (the objectives form no cycle, the validator checks), and a step runs at most MAX_ACTIONS_PER_STEP actions per player.
Classes
Interfaces
- ActorFacts
- AlertCommand
- BindCameraCommand
- BindDoorCommand
- BindGarageCommand
- BindPropCommand
- CameraFacts
- ClockCommand
- ContainerFacts
- DespawnCommand
- DoorFacts
- EnemyFacts
- FleeCommand
- GarageFacts
- GiveCommand
- HandOverCommand
- HitFacts
- ItemEventFacts
- LockDoorCommand
- LockVehicleCommand
- MemberView
- MissionFacts
- MissionOutput
- MissionView
- Notice
- NpcFacts
- PayCommand
- PhotoFacts
- PickupFacts
- PlayerFacts
- PropFacts
- RaceCommand
- RespawnCommand
- RunOptions
- RunSeat
- RunSeatView
- RunTeamView
- RunView
- ScheduleHourSpot
- SetCameraCommand
- SetSignalCommand
- SetWantedCommand
- SkipTimeCommand
- SpawnContainerCommand
- SpawnGroupCommand
- SpawnItemCommand
- SpawnNpcCommand
- SpawnShopCommand
- SpawnTerminalCommand
- SpawnVehicleCommand
- SpectateCommand
- StackFacts
- TakeCommand
- ViewTarget
- WeatherCommand