Missions¶
Missions are bite-sized objectives a player accepts in exchange for credits, reputation, or items. They give the open-world economy a guided spine: when a player isn't sure what to do next, the mission board has an answer.
Three families of mission share the same accept / track / complete pipeline:
| Family | Issuer | Persistence | Notable trait |
|---|---|---|---|
| Faction missions | NPC factions (FactionMission) |
Persistent table; admin or generator-created | Affect faction standing |
| Random missions | Procedurally generated, pulled from a hat | Generated on demand, pinned for the duration | Capped per player |
| Daily quests | System-issued, refreshed each game day | One per slot, per player | Expire at next refresh |
✅ Shipped — FactionMission model, mission availability API (get_available_missions), reputation-gated filtering, basic acceptance / completion endpoints.
🚧 Partial — random mission generator, daily-quest scheduler, in-game mission journal UI, mission-chain branching.
📐 Design-only — escort missions, time-limited racing missions, multi-player co-op missions.
Faction missions¶
models/faction.py:FactionMission defines the persistent record:
id, faction_id, title, description,
mission_type in {cargo_delivery, combat, exploration, diplomatic}
min_reputation gates acceptance (default -800: anyone)
min_level gates acceptance (default 1)
credit_reward, reputation_reward, item_rewards
target_sector_id, cargo_type, cargo_quantity, target_faction_id
is_active, expires_at, created_at
Mission types¶
| Type | Objective | Typical reward | Notable side-effect |
|---|---|---|---|
cargo_delivery |
Move cargo_quantity of cargo_type to target_sector_id |
Credits + small rep | Mercantile Guild favors this type |
combat |
Destroy a target (NPC, drone field, or player faction enemy) | Credits + meaningful rep | Federation / Military faction missions |
exploration |
Visit target_sector_id and scan |
Smaller credits + rep + map data | Nova Scientific / Frontier favor this |
diplomatic |
Carry a courier package between factions | Credits + rep with both faction and target_faction_id |
Cross-faction; check rivalry caps |
✅ Shipped — model + types. 🚧 Partial — completion verification per mission type (cargo manifest checking, scan-confirmation, kill verification all need the in-game integration glue).
Acceptance flow¶
GET /api/v1/missions/available?faction_id=...
→ returns missions where:
is_active = 1
expires_at IS NULL OR expires_at > now
reputation[faction_id] >= min_reputation
player.level >= min_level
POST /api/v1/missions/{mission_id}/accept
→ checks reputation gate again (TOCTOU)
→ marks mission as accepted by this player
→ records acceptance timestamp
A player can carry a small number of active missions concurrently (target cap: 5). When at cap, the accept call is rejected. ✅ Shipped (acceptance) — 📐 Design-only (concurrent cap enforcement).
Completion flow¶
POST /api/v1/missions/{mission_id}/complete
→ verify acceptance
→ verify objective (type-specific)
→ award credit_reward
→ update_reputation(player, faction, reputation_reward, "mission_complete")
→ grant item_rewards (if any)
→ emit mission_completed
🚧 Partial — completion verification per mission type. Cargo and exploration missions can be wired to existing trade and movement events; combat and diplomatic require richer hooks.
Abandonment flow¶
POST /api/v1/missions/{mission_id}/abandon
→ verify acceptance
→ drop without reward
→ small reputation penalty (target spec: -5 with the issuing faction)
→ emit mission_abandoned
📐 Design-only — abandonment penalty (currently a no-op apart from removing acceptance).
Random missions¶
A pool of templates seeds short-form missions on demand. The generator picks a template, fills in parameters from the player's current sector and recent activity, and offers the result through the same API surface as faction missions.
📐 Design-only.
Template pool seeds: - "Bounty hunt" — pick a low-reputation NPC or pirate captain in current cluster. - "Salvage" — visit a wreck sector and recover X. - "Smuggling" — Fringe Alliance only; carry contraband while avoiding patrols. - "Distress beacon" — dynamic event-tied; finite window.
Daily quests¶
A small set of quests refreshes every game day at a fixed wall-clock hour (target: 00:00 UTC, configurable per region). Each player gets the same set; completion is per-player.
Slots (target spec):
| Slot | Objective shape | Reward |
|---|---|---|
| Trade | Complete N trades | Credits + small faction rep |
| Combat | Win N PvE encounters | Credits + reputation |
| Travel | Visit N sectors | Credits + ARIA exploration map data |
| Social | Send N messages or join a fleet action | Small credits |
📐 Design-only — daily-quest scheduler, refresh job, slot definitions.
Reward structure¶
All rewards funnel through three channels:
credits -> Player.credits += credit_reward
reputation -> FactionService.update_reputation(player, faction, delta, reason)
item_rewards -> attached to player inventory (cargo / equipment / special items)
Reputation rewards interact with rivalry caps — gaining standing with one faction can be capped by current standing with its rival (see factions-and-teams.md).
Diplomatic missions can award reputation with two factions — typically a small positive with the issuer and a small negative with the target faction. The rivalry cap is checked separately for each.
Mission state machine¶
AVAILABLE --(accept)--> ACTIVE
^ |
| (objective met)
| v
| COMPLETED
| |
| (reward paid)
+--(abandon)----<-- ABANDONED
|
(rep penalty)
A mission row exists once and can be in any of these states. For per-player tracking the target spec uses a MissionAcceptance(player_id, mission_id, status, accepted_at, completed_at) join table.
📐 Design-only — MissionAcceptance model is not yet implemented; current code only checks reputation gates without persisting per-player acceptance.
Expiration¶
FactionMission.expires_at is honored by get_available_missions (mission filtered out once expired). A scheduled job should also mark expired missions inactive to prevent log clutter.
📐 Design-only — expiration sweeper.
Mission UI surface¶
In the player client, missions live in a dedicated panel: - Available list (filterable by faction, type). - Active list with progress markers (cargo counts, sector visit checklist, kill counters). - Completion modal with reward animation.
🚧 Partial — the API exists; the client surface is rudimentary.
Source map¶
| Concern | Path (target) |
|---|---|
| Faction mission model | services/gameserver/src/models/faction.py (FactionMission) |
| Faction service (availability, create) | services/gameserver/src/services/faction_service.py |
| Mission acceptance/completion service | services/gameserver/src/services/mission_service.py (target — not yet split out) |
| REST routes | services/gameserver/src/api/routes/missions.py (target) |
| Random mission generator | services/gameserver/src/services/mission_generator.py (target) |
| Daily quest scheduler | services/gameserver/src/services/daily_quest_scheduler.py (target) |
Related¶
factions-and-teams.md— faction standing, rivalries, and the reputation table that gates mission access.bounties.md— bounty hunting overlaps with combat-type faction missions but uses a separate mechanism.SYSTEMS/turn-regeneration.md— daily-quest refresh shares scheduling infrastructure with turn ticks.