Campaign System
Core campaign orchestration module. Manages campaign lifecycle, scenario sequencing, location status tracking, rewards, achievements, and UI flow between campaign scenarios and exploration.
Core campaign orchestration module. Manages campaign lifecycle, scenario sequencing, location status tracking, rewards, achievements, and UI flow between campaign scenarios and exploration.
Dependencies
M.dependencies = {'scenario_scenarios'}Overview
Depends on scenario_scenarios. Tracks a single active campaign with subsections containing scenario locations. Handles scenario start/finish events, reward selection, end-screen UI, save/resume, and exploration transitions.
Public API
| Function | Args | Returns | Description |
|---|---|---|---|
M.startCampaign | newCampaign | - | Starts a processed campaign from its starting location |
M.stop | - | - | Stops the active campaign and cleans up |
M.getCampaign | - | table/nil | Returns the active campaign object |
M.getCampaignActive | - | boolean | Whether a campaign is currently active |
M.getCampaignTitle | - | string/nil | Title of the active campaign |
M.getCurrentLocation | - | string/nil | Current subsection.location key |
M.startScenarioFromKey | key, [scenario] | - | Loads and executes a scenario by location key |
M.canStartScenario | scenarioKey | boolean | Checks if all requirements (scenarios, vehicles) are met |
M.isLocationCompleted | locationKey | boolean | Whether the location has been completed |
M.canImproveResult | locationKey | boolean | Whether the location medal can be improved (not gold) |
M.markCompleted | subsection, locationKey | - | Marks a location as completed |
M.isCampaignOver | scenario | boolean | Whether the campaign has no more scenarios |
M.getSubsection | subsectionKey | table/nil | Gets subsection data by key |
M.getActiveSubsection | - | table/nil | Gets the currently active subsection |
M.getLocationData | subsectionKey, locationKey | table/nil | Gets location data from a specific subsection |
M.getActiveSubsectionLocationData | locationKey | table/nil | Gets location data from the active subsection |
M.getOwningSubsection | locationKey | table/nil | Finds which subsection owns a location |
M.isSubsectionMarker | subsectionKey, markerName | boolean | Checks if a marker belongs to a subsection |
M.isTransitionPoint | subsectionKey, locationKey | boolean | Whether location is a transition point |
M.isMissionGiver | subsectionKey, locationKey | boolean | Whether location is a mission giver |
M.isPlayerHQ | subsectionKey, locationKey | boolean | Whether location is player HQ |
M.isSiteLocation | subsectionKey, locationKey | boolean | Whether location is a site (non-race) |
M.isScenarioLocation | subsectionKey, locationKey | boolean | Whether location is a playable scenario |
M.scenarioStarted | scenario | - | Hook: processes intro events and increments attempts |
M.scenarioFinished | scenario | - | Hook: processes results, rewards, achievements, end UI |
M.uiEventNext | - | - | UI callback: advance to next scenario |
M.uiEventCancel | - | - | UI callback: cancel and return to exploration |
M.execEndCallback | - | - | Executes the campaign end callback |
M.rewardSelectionCallback | itemIndex | - | Processes player's reward choice |
M.resumeCampaign | campaignInProgress, data | - | Resumes a campaign from saved state |
M.getLocationStatusTable | - | table | Returns the location status tracking table |
M.onSerialize | - | table | Serializes campaign state |
M.onDeserialized | data | - | Stub for deserialization |
M.onExtensionUnloaded | - | - | Stops campaign on unload |
M.onScenarioChange | scenario | - | Unloads extension if no campaign is active |
M.onSaveCampaign | saveCallback | - | Provides campaign state for save system |
M.onResetGameplay | playerID | - | Resets vehicle during exploration |
Campaign State Structure
campaign = {
meta = {
title = "Campaign Name",
subsections = { [key] = { locations = {...}, triggers = {...}, level = "..." } },
startingLocation = "subsection.location",
defaultVehicle = { model = "...", config = "...", color = "..." },
sourceFile = "path/to/campaign.json"
},
state = {
campaignActive = true,
currentLocation = "subsection.location",
activeSubsection = "subsectionKey",
scenarioKey = "locationKey",
scenarioExecutionOrder = {"scenario1", "scenario2"},
locationStatus = { ["sub.loc"] = {attempts = 0, state = "ready", medal = ""} },
selectedRewardIndex = nil
}
}Location Status Values
| State | Description |
|---|---|
ready | Not yet attempted |
completed | Successfully finished |
failed | Last attempt failed |
Notes
- Campaigns are mutually exclusive - starting a new one stops the current
- Scenario flow:
startScenarioFromKey→scenarioStarted→scenarioFinished→processNextScenario - End screen buttons are dynamically built based on
endOptionsin location data - Comics can play between scenarios via
campaign_comics - Achievements are unlocked via
OnlineServiceProvider.unlockAchievement() - The
whiteListActionsdefault is"default_whitelist_campaign"
See Also
- Campaigns Loader - Campaign file loading and save management
- Campaign Exploration - Free-roam between scenarios
- Campaign Comics - Comic cutscene playback
- Campaign Dealer - Vehicle stock management
C2 Vehicle Manager
Real-time vehicle data streaming plugin for the C2 WebSocket system. Subscribers receive position, rotation, and velocity updates each frame.
Campaign Loader
Campaign file loading, validation, save management, and campaign start orchestration. Handles the full lifecycle from JSON file to running campaign.