Career Missions
Create custom career challenges with win conditions
The career API lets you create custom missions with star-based goals. Players can play your missions from the career map, earning stars by completing your defined objectives.
Register a Mission#
javascript
const api = window.SubwayBuilderAPI;
api.career.registerMission({
id: 'my-mod.speed-run',
cityCode: 'NYC',
name: 'NYC Speed Run',
description: 'Build a profitable network in record time!',
tier: 'starter', // 'starter' | 'growth' | 'mega'
stars: [
{
id: 'star1',
label: 'Build 5 stations within 5 game-days',
shortLabel: '5 Stations',
icon: '🚉',
metric: api.career.METRICS.STATIONS_COUNT,
target: 5,
operator: api.career.OPERATORS.GREATER_OR_EQUAL,
howTo: [
'Open the BUILD panel at the bottom',
'Click on the map to place stations',
'Focus on high-demand areas'
],
actionPanel: 'construction',
actionLabel: 'Start Building'
},
{
id: 'star2',
label: 'Run 8 trains simultaneously',
shortLabel: '8 Trains',
icon: '🚃',
metric: api.career.METRICS.TRAINS_COUNT,
target: 8
},
{
id: 'star3',
label: 'Achieve $250K daily profit',
shortLabel: '$250K Profit',
icon: '💰',
metric: api.career.METRICS.DAILY_PROFIT,
target: 250000
}
]
});Star Definition Properties#
| Property | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Must be 'star1', 'star2', or 'star3' |
label | string | Yes | Full description of the goal |
shortLabel | string | Yes | Compact label (e.g., "10 Stations") |
icon | string | No | Emoji icon for the goal |
metric | string | Yes | Metric to track |
target | number | Yes | Target value to reach |
operator | string | No | Comparison operator (default: '>=') |
howTo | string[] | No | Step-by-step instructions |
actionPanel | string | No | Panel to open: 'construction', 'routes-list', 'demand-stats' |
actionLabel | string | No | Label for the action button |
Available Metrics#
Use api.career.METRICS.* for type-safe metric names:
| Constant | Value | Description |
|---|---|---|
STATIONS_COUNT | 'stations_count' | Number of stations |
TRAINS_COUNT | 'trains_count' | Number of active trains |
ROUTES_COUNT | 'routes_count' | Number of routes |
TRACKS_COUNT | 'tracks_count' | Number of track segments |
TOTAL_PASSENGERS | 'total_passengers' | Passengers served today |
RIDERSHIP_PERCENTAGE | 'ridership_percentage' | % using transit |
DAILY_PROFIT | 'daily_profit' | Today's profit |
TOTAL_REVENUE | 'total_revenue' | Today's revenue |
TOTAL_DEBT | 'total_debt' | Sum of all bonds |
MONEY | 'money' | Current cash |
| `PLAYTIMEMINUTES` | `'playtimeminutes'` | Real-world minutes |
ELAPSED_DAYS | 'elapsed_days' | In-game days |
Geographic Metrics#
These require params with bounding boxes:
| Constant | Description |
|---|---|
| `PASSENGERSBETWEENREGIONS` | Passengers from one region to another |
| `PASSENGERSFROMREGION` | Passengers originating from region |
| `PASSENGERSTOREGION` | Passengers traveling to region |
| `STATIONSINREGION` | Stations within bounding box |
Pre-defined NYC Regions#
Use api.career.REGIONS.NYC.* for common neighborhoods:
Brooklyn:
BUSHWICK,WILLIAMSBURG,BEDSTUY,GREENPOINT,DUMBO,DOWNTOWN_BROOKLYN
Manhattan:
- `LOWERMANHATTAN`, `FINANCIALDISTRICT
,TRIBECA,SOHO,EAST_VILLAGE` - `MIDTOWN`, `TIMESSQUARE`, `UPPEREASTSIDE`, `UPPERWEST_SIDE
,HARLEM`
Queens:
- `LONGISLANDCITY
,ASTORIA`
Using Geographic Metrics#
javascript
// Track passengers between regions
{
id: 'star1',
label: 'Transport 1,000 passengers from Bushwick to Manhattan',
shortLabel: '1K Bushwick→Manhattan',
metric: api.career.METRICS.PASSENGERS_BETWEEN_REGIONS,
target: 1000,
params: {
originBbox: api.career.REGIONS.NYC.BUSHWICK,
destBbox: api.career.REGIONS.NYC.LOWER_MANHATTAN
}
}
// Count stations in a region
{
id: 'star2',
label: 'Build 3 stations in Bushwick',
shortLabel: '3 Bushwick Stations',
metric: api.career.METRICS.STATIONS_IN_REGION,
target: 3,
params: {
bbox: api.career.REGIONS.NYC.BUSHWICK
}
}
// Custom bounding box: [minLng, minLat, maxLng, maxLat]
{
id: 'star3',
metric: api.career.METRICS.PASSENGERS_FROM_REGION,
target: 500,
params: {
bbox: [-73.95, 40.70, -73.90, 40.75]
}
}Comparison Operators#
Use api.career.OPERATORS.*:
| Constant | Value | Description |
|---|---|---|
| `GREATEROREQUAL` | '>=' | Value >= target (default) |
GREATER | '>' | Value > target |
| `LESSOREQUAL` | '<=' | Value <= target |
LESS | '<' | Value < target |
EQUAL | '==' | Value == target |
NOT_EQUAL | '!=' | Value != target |
Mission Tiers#
| Tier | Required Stars | Description |
|---|---|---|
starter | 0 | Available immediately |
growth | 4+ | Unlocked after 4 stars |
mega | 10+ | Unlocked after 10 stars |
Query Missions#
javascript
// Get your mod's missions
const myMissions = api.career.getMyMissions();
// Get all missions (including other mods)
const allMissions = api.career.getAllMissions();
// Get missions for a specific city
const nycMissions = api.career.getMissionsForCity('NYC');
// Unregister a mission
api.career.unregisterMission('my-mod.speed-run');Example: Debt-Free Challenge#
javascript
api.career.registerMission({
id: 'my-mod.debt-free',
cityCode: 'CHI',
name: 'Chicago Debt-Free',
description: 'Build a transit empire without drowning in debt.',
tier: 'growth',
stars: [
{
id: 'star1',
label: 'Build 10 stations',
shortLabel: '10 Stations',
icon: '🏗️',
metric: api.career.METRICS.STATIONS_COUNT,
target: 10
},
{
id: 'star2',
label: 'Keep total debt under $100K',
shortLabel: 'Debt < $100K',
icon: '📉',
metric: api.career.METRICS.TOTAL_DEBT,
target: 100000,
operator: api.career.OPERATORS.LESS_OR_EQUAL,
howTo: [
'Avoid taking bonds when possible',
'Build incrementally',
'Focus on profitable routes first'
]
},
{
id: 'star3',
label: 'Serve 5% of the population',
shortLabel: '5% Ridership',
icon: '👥',
metric: api.career.METRICS.RIDERSHIP_PERCENTAGE,
target: 5,
actionPanel: 'demand-stats',
actionLabel: 'View Demand Map'
}
]
});How It Works#
- Registration: Your mission is added to the career registry
- UI Integration: Mission appears with a purple "MOD" badge
- Progress Tracking: Game automatically tracks progress
- Custom Instructions: Your
howTosteps appear in the UI - Action Buttons: Quick-action buttons open specified panels
Notes:
- Mission IDs should use reverse-domain style (e.g.,
my-mod.mission-name) - Each mission can have 1-3 stars
- Stars are evaluated in real-time and persisted to career profile
- If no
howTois provided, game generates default instructions