Campaign Loader
Campaign file loading, validation, save management, and campaign start orchestration. Handles the full lifecycle from JSON file to running campaign.
Campaign file loading, validation, save management, and campaign start orchestration. Handles the full lifecycle from JSON file to running campaign.
Overview
Loads campaign JSON files from /campaigns/, validates their structure, manages save files in /saves/campaigns/, and orchestrates the start/resume flow including extension loading.
Public API
| Function | Args | Returns | Description |
|---|---|---|---|
M.getCampaignFilenames | - | table | Scans /campaigns/ for JSON files with campaign header type |
M.getList | - | table | Loads and returns all campaign entries |
M.getCampaignScenarios | - | table | Returns cached list of all campaign scenario paths |
M.loadCampaign | campaignfile | table | Loads a single campaign JSON, adds metadata (mod info, previews) |
M.start | newCampaign, [endCallback] | - | Full campaign start: unloads level, loads extensions, starts/resumes |
M.startByFolder | path, [endCallback] | - | Starts a campaign by its source folder path |
M.splitFieldByToken | field, token | table | Splits a dotted string (e.g., "sub.loc") into parts |
M.checkSaveExists | title, savesEnabled | string/nil | Checks if a save file exists for the given campaign title |
M.saveCampaign | campaign | - | Saves campaign state to JSON if saves are enabled |
M.resumeSavedCampaign | campaign, saveFilename | - | Resumes a campaign from a save file |
M.onInit | - | - | Initialization hook (referenced but not defined in source) |
Internal State
| Field | Type | Description |
|---|
Campaign Modules
The loader loads these extensions as a group:
M.campaignModules = {
'campaign_campaigns',
'campaign_exploration',
'campaign_comics',
'campaign_rewards',
'campaign_dealer',
'campaign_photoSafari'
}Campaign File Structure
{
"header": { "type": "campaign" },
"meta": {
"title": "My Campaign",
"startingLocation": "section1.mission1",
"subsections": {
"section1": {
"locations": {
"mission1": {
"path": "/path/to/scenario.json",
"info": { "title": "...", "type": "race", "subtype": "timeTrial" },
"onEvent": { "onSucceed": {...}, "onFail": {...} }
}
},
"triggers": ["/path/to/prefab.prefab"]
}
}
}
}Save System
| Function | Description |
|---|---|
saveCampaign | Hooks all modules via onSaveCampaign, writes to /saves/campaigns/slotN.json |
resumeSavedCampaign | Reads save, calls onResumeCampaign on each module, then resumes campaign |
checkSaveExists | Scans save directory for matching campaign title |
Save file header: { version: 1, type: "campaignSave", title: "..." }
Validation
The validate function ensures:
- Campaign has a title (defaults to
<missing title>) - Subsections have
locationstables - Locations have
infowithtitle,type,typeName - Location types are split into
typeandsubtype(e.g.,"race.timeTrial") disableEndUIrequires exactly 1 entry inendOptions
Start Flow
- If a level is loaded (
MissionGroupexists), delays start until unloaded - Unloads auto extensions, loads preset + scenario + campaign modules
- Processes campaign structure via
processCampaignStartInternal - Checks for existing save file → resume or fresh start
- Calls
campaign_campaigns.startCampaign()orresumeSavedCampaign()
Notes
- Campaign metadata includes mod info via
core_modmanager.getModFromPath() - Preview images are auto-discovered from the campaign source folder
- Official content is detected via
isOfficialContentVPath() - The
triggerDelayedStartpattern handles async level unloading
See Also
- Campaign System - Core campaign orchestration
- Campaign Exploration - Free-roam exploration mode
Additional Exports
M.saveDataTable- (undocumented)M.triggerDelayedStart- (undocumented)
Campaign System
Core campaign orchestration module. Manages campaign lifecycle, scenario sequencing, location status tracking, rewards, achievements, and UI flow between campaign scenarios and exploration.
Campaign Comics
Comic/cutscene playback system for campaign narrative sequences. Displays Spine-animated comic panels with background audio between campaign scenarios.