Arcbound Data Modding Spec (EA v1)
This spec covers JSON data modding via ModManager (Add, Override, Patch).
1. Mod Package Model
Folder Layout
Mods/
<modId>/
mod.json
*.json (operation files, any name)
subfolders/*.json
Scripts/init.lua (optional, see Lua API doc)
All *.json files under a mod folder are scanned recursively, except mod.json.
Manifest (mod.json)
{
"modId": "author.my-mod",
"version": "1.0.0",
"displayName": "My Mod",
"dependencies": ["core.required.mod"],
"loadAfter": ["another.mod"]
}
Fields:
modIdrequired and unique.dependencieshard requirements.loadAftersoft ordering preference.
Load Order
- Base game defs load first.
- Enabled mods are dependency-checked.
- Missing dependency => mod is disabled with warning.
- Remaining mods are topologically sorted (
dependencies+loadAfteredges). - Operations apply in sorted order.
- Last writer wins for same
<defType>/<stableId>.
If dependency cycles exist, a warning is emitted and load order may be reduced.
Runtime Policy
- Mods apply at boot/main menu only.
- No runtime hot reload during active gameplay.
- Toggling mods sets
RestartRequired.
2. Operation File Schema
Each operation file is:
{
"operations": [
{
"defType": "resources",
"action": "Patch",
"stableId": "alloys",
"fields": [
{ "field": "displayName", "value": "Alloys+" }
]
}
]
}
Operation Fields
defType: target family key (case-insensitive).action:Add,Override, orPatch(case-insensitive).stableId: target identity key.fields: list of field writes.field: public field path.value: string value converted to target type.
Action Semantics
Add- Fails (warning) if
stableIdalready exists. - Creates a new def instance, sets stable id, applies fields.
- Fails (warning) if
Override- Requires target exists.
- Applies provided fields onto existing def.
Patch- Requires target exists.
- Applies provided fields onto existing def.
Current implementation treats Override and Patch identically (partial field updates).
3. Supported defType Families
Use these keys consistently:
buildablescropsresearchrecipesdoctrineseventsresourcesmissions
These map to runtime registries and save validation.
4. Stable ID Contract
Gameplay/save logic must key defs by stableId (or canonical legacy alias fallback during migration), never by Unity asset object name for new content.
Recommended stable id format:
- lowercase
a-z0-9._-- immutable once shipped
Example: build.storage.demo_crate.
5. Field Path Rules
Field writes use reflection on public instance fields.
Path syntax
- Simple:
displayName - Nested object:
requirements.minEngineering - Indexed list/array:
focusOptions[0] - Nested indexed:
variants[0].messageOverride
Invalid path segments produce warnings and are skipped.
List behavior
- Writing
list[index]auto-expands list with default values up toindex. - Negative indices are invalid.
6. Value Conversion Rules
All input values are strings; conversion is type-based.
Supported target types:
stringintfloat(invariant culture)bool(true/false, also1/0)enum(case-insensitive parse)Vector2as"x,y"Vector3as"x,y,z"Vector2Intas"x,y"Vector3Intas"x,y,z"Coloras HTML color string (e.g.#FFAA00)UnityEngine.Objectrefs:nullor empty => nullres:Path/To/Assetor plainPath/To/Asset- resolved with
Resources.Load(path, targetType)
Unsupported type conversion => warning and field not applied.
7. Conflict Diagnostics
Conflicts are tracked by <defType>/<stableId> as:
<defType>/<stableId>: <previousModId> -> <newModId>
This indicates last-writer override order.
8. Error and Warning Model
Non-fatal by design:
- malformed operation file
- unknown action
- missing target for
Override/Patch - duplicate
Add - invalid path/value conversion
Errors produce warnings; game continues loading.
9. Save/Load Expectations
Save references
Defs should be saved using stable ids, not list indices.
Missing mod set handling
On load, saved enabled mod ids are compared to current enabled mods:
- missing mods are tracked and surfaced as warnings/UI prompts.
Provenance
sourceModId tracking is available for mod-applied defs by <defType>/<stableId> lookup.
Missing def fallback
Missing defs should degrade gracefully where possible (warning + placeholder behavior), not hard-crash saves.
10. Authoring Examples
Example A: Add a new buildable
{
"operations": [
{
"defType": "buildables",
"action": "Add",
"stableId": "build.storage.demo_crate",
"fields": [
{ "field": "displayName", "value": "Demo Crate" },
{ "field": "category", "value": "StorageAndLogistics" },
{ "field": "storageStackSlots", "value": "4" }
]
}
]
}
Example B: Patch a resource display name
{
"operations": [
{
"defType": "resources",
"action": "Patch",
"stableId": "alloys",
"fields": [
{ "field": "displayName", "value": "Alloys (Refined)" }
]
}
]
}
Example C: Patch event variant text
{
"operations": [
{
"defType": "events",
"action": "Patch",
"stableId": "phase2_event_derelict_arcship",
"fields": [
{ "field": "variants[0].messageOverride", "value": "The derelict emits a faint civil distress loop." }
]
}
]
}
11. Best Practices
- Keep
stableIdimmutable after public release. - Prefer
Patchfor compatibility. - Use
loadAfteronly when needed; prefer explicit dependencies for hard requirements. - Validate mods after edits and check warnings list in mod manager.
- For asset refs, prefer
Resourcespaths that exist in both Editor and builds. - Use starter files under
Docs/examples/mods/example.mod/as copy/paste templates.
See also: Docs/modding_lua_api.md for scripting hooks and runtime API.
12. Per-SO Mod Schema (Exact Field Catalog)
This section is the exact modding field surface for supported defType families.
Conventions:
fields[].fieldcan target any public instance field listed below.- Enum fields accept enum-name strings (case-insensitive).
UnityEngine.Objectreferences useres:Path/Inside/Resources.
12.1 buildables (BuildItemSO)
Identity/UI:
stableIddisplayNameiconcategory(BuildCategory)requiredResearchIdphase2Only
Placement/shape:
placementKind(BuildPlacementKind:Tile,Object,Tool)requiresFloorSupporttaskType(TaskType)rotatablerotations(Rotations4SO)size(Vector2Int)pivot(Vector2Int)
Tile/object visuals:
placeCellType(CellType)tile(TileBase)placeObjectType(ObjectType)objectTile(TileBase)wallVisuals(WallVisualSetSO)doorVisuals(DoorVisualSetSO)airTightDoorblocksWalkabilityisVerticalConnectorverticalConnectorSteptoggledOffObjectTile(TileBase)emitsLightlightRadiuslightOnObjectTile(TileBase)lightRequiresPowerisOxygenVentisFireSuppressorfireSuppressionRadius
Costs/work/stats:
costAlloyscostElectronicscostSubstratecostFuelbuildWorkSecondsdeconstructWorkSecondsrequiredConstructionSkillpowerDeltatag
Durability/maintenance/comfort:
maxDurabilityarmorPctrequiresMaintenancemaintenanceDurabilityLossPerDaytaskMustWorkOnCellprovidesMaintenanceAnchormaintenanceAnchorRadiusmaintenanceWorkSpeedBonusPctmaintenanceResourceEfficiencyPctroomMoralePerDay
Utility topology:
isUtilityutilityType(UtilityType)isConduitisDeviceisPowerSwitchcapacitythroughputconduitVisuals(ConduitVisualSetSO)waterPorts(DirMask4)wastePorts(DirMask4)powerPorts(DirMask4)
Per-day utility IO:
powerUsePerDayallowUnpoweredOperationunpoweredOperationWorkSpeedMultiplierpowerGenPerDaywaterUsePerDaywaterGenPerDaywasteGenPerDaywasteUsePerDayoxygenUsePerDayoxygenGenPerDay
Per-use utility IO:
usePerUseUtilityIopowerUsePerUsewaterUsePerUsewasteGenPerUse
Storage/crafting:
storageStackSlotscraftRecipeIds(List<string>)
Civilian systems:
isCivilianHabitatcivilianHabitatCapacitycivilianComfortContributionisCivilianSupplyIntakecivilianSupplyFoodCapacitycivilianSanitationContributioncivilianCommonsContributioncivilianComfortAuraRadiuscivilianFoodEfficiencyBonusPctcivilianSecurityContributioncivilianSecuritySuppressionBonusPctcivilianEnablesLockdown
Civilian security supplies:
isCivilianSecurityCheckpointsecurityBatonCapacityriotShieldCapacitystunSidearmCapacitysecurityEnergyCellCapacitysecurityBatonCoveragePerUnitsecurityBatonSuppressionPerUnitsecurityBatonUnrestDecayPerUnitriotShieldCoveragePerUnitriotShieldSuppressionPerUnitriotShieldUnrestDecayPerUnitpoweredStunSidearmCoveragePerUnitpoweredStunSidearmSuppressionPerUnitpoweredStunSidearmUnrestDecayPerUnit
Civilian recovery/production:
civilianHealthLossReductionPctcivilianCrisisMortalityReductionPctcrewInjuryRecoveryBoostPctcivilianCrewCandidateQualityBonusPctcivilianFabricationAlloysPerDaycivilianFabricationElectronicsPerDaycivilianFabricationSubstratePerDaycivilianHydroYieldBonusPctcivilianResearchPointsPerDay
Fuel/resource IO:
fuelUsePerDayresourceCapacityfuelCapacityalloysUsePerDayelectronicsUsePerDaysubstrateUsePerDayalloysGenPerDayelectronicsGenPerDaysubstrateGenPerDayfuelGenPerDay
12.2 crops (CropDefSO)
Identity/visuals:
stableIdcropIddisplayNameiconplantedSprite
Growth/harvest:
stages(StageDef[])stages[i].stage(GrowthStage)stages[i].durationDaysstages[i].o2PerTickstages[i].maintenanceIntervalDaysstages[i].yieldAmount
harvestMode(HarvestMode:None,AutoAtBestStage,ManualAnytime)bestHarvestStage(GrowthStage)harvestEndsPlantyieldType(ResourceType)baseYieldAmount
12.3 research (ResearchDefSO)
Identity/core:
stableIdiddisplayNamedescriptioncategory(ResearchCategory:Engineering,Society,Archives,Signal)phase2OnlytiercostPointsiconprerequisiteIds(List<string>)
Requirements:
requirements.requiredBuildings(List<ResearchBuildingRequirement>)requirements.requiredBuildings[i].buildItemIdrequirements.requiredBuildings[i].objectType(ObjectType)requirements.requiredBuildings[i].count
requirements.minEngineeringrequirements.minSocialrequirements.requiresPoweredDeskrequirements.minCivilianPopulationrequirements.minContinuumInstabilityrequirements.requiredArchiveFragmentsrequirements.requiredSignalFragmentsrequirements.consumeRequiredFragmentsOnStartrequirements.requiresWaterNetworkrequirements.requiredZoneType(ZoneType)requirements.minRequiredZoneCells
Effects:
effects.unlockBuildItemIds(List<string>)effects.researchSpeedBonusPcteffects.hydroYieldBonusPcteffects.batteryCapacityBonusPcteffects.maintenanceFrequencyReductionPcteffects.waterRecyclingEfficiencyBonusPcteffects.missionConsequenceSeverityReductionPcteffects.reactorFuelUseReductionPcteffects.engineFuelUseReductionPcteffects.collapsePressureDeltaReductionFlateffects.collapseEventFrequencyReductionPcteffects.civilianFoodEfficiencyBonusPcteffects.civilianDeliveryWasteReductionPcteffects.civilianHygieneDecayReductionPcteffects.civilianUnrestGrowthReductionPcteffects.civilianComfortFlatBonuseffects.civilianSecuritySuppressionBonusPcteffects.civilianDoctrineStabilityBonusPcteffects.civilianUnrestSpikeReductionPcteffects.enablesCivilianPromotioneffects.highMoraleCiGrowthReductionPcteffects.unlocksAnomalySocietyEventseffects.roomBonusMultiplierPcteffects.stablePopulationShipStrainReductionPerDayeffects.recipeOutputBonuses(List<RecipeOutputBonus>)effects.recipeOutputBonuses[i].recipeIdeffects.recipeOutputBonuses[i].bonusPct
effects.mealQualityMoraleBonusPerDayeffects.hygieneNegativeStatusDurationReductionPcteffects.missionFoodConsumptionReductionPcteffects.unlocksMissionEventChainseffects.enablesEssenceMissionRewardseffects.relationshipGrowthRateBonusPcteffects.psychologicalBreakChanceReductionPcteffects.moraleRecoveryBonusPcteffects.doctrineAlignmentDecayReductionPcteffects.culturalInstabilityGrowthReductionPcteffects.civilianResearchPointsPerDayeffects.promotionStartingSkillBonusPcteffects.promotionStartingDoctrineAlignmentBonusPcteffects.crisisRecoverySpeedBonusPcteffects.doctrineStrengthBonusPcteffects.relationshipDamageReductionPcteffects.culturalTransitionDurationReductionPcteffects.stableShipMoralePerDayeffects.stressAccumulationReductionPcteffects.unlocksArchiveEventseffects.unlocksPeacefulResolutionEventseffects.crewDeathMoralePenaltyReductionPcteffects.unlocksTransitSignalMissionseffects.improvesMissionRewardPreviewseffects.signalEventFrequencyBonusPcteffects.enablesHiddenMissionOfferseffects.anomalyBadOutcomeReductionPcteffects.archiveResearchSpeedBonusPcteffects.signalResearchSpeedBonusPcteffects.unlocksDerelictArcshipEncounterseffects.continuumInstabilityGrowthReductionPcteffects.unlocksHighRiskSignalMissionseffects.anomalyPositiveOutcomeBonusPcteffects.shipStrainGrowthReductionPcteffects.majorDisasterFrequencyReductionPcteffects.unlocksLateGameContactEvents
12.4 recipes (CraftRecipeSO)
Identity/unlock:
stableIdiddisplayNamedescriptionrequiredResearchIdrequiredBenchTag
Crafting:
workSecondsprimarySkill(SkillType)baseFailChanceinputs(List<ResourceAmount>)inputs[i].type(ResourceType)inputs[i].amount
outputs(List<ResourceAmount>)outputs[i].type(ResourceType)outputs[i].amount
powerUsePerCraftwaterUsePerCraftwasteGenPerCraft
12.5 doctrines (DoctrineDefinitionSO)
Identity/copy:
stableIddoctrineIddisplayNameshortDescriptioncardIconbonusesSummaryweaknessSummary
Modifiers:
moraleRecoveryMultiplierrelationshipGainMultiplierrelationshipLossMultiplierbreakDurationMultiplierbreakRiskMultipliercomfortMoraleMultipliermissionRewardMultipliermissionConsequenceSeverityMultipliercollapsePressureMultiplierengineeringXpMultiplierhydroEfficiencyMultiplierwaterEfficiencyMultiplierconstructionSpeedMultipliermaintenanceSpeedMultiplierresearchSpeedMultiplierarchiveDiscoveryMultiplierbreakdownChanceMultiplierinstabilitySensitivityMultiplierstartingMoraleOffsetpersonnelExtractionSeverityMultipliercrewDeathMoraleLossMultiplierfoodSecurityExpectationMultipliermissionTurnaroundMultiplierfuelRaidRewardMultiplierfuelRaidCollapsePressureMultipliersocialRecoveryBonusMultiplierconflictMoraleCollapseMultiplier
12.6 events (Phase2TransitEventDefinitionSO)
Identity/director:
stableIdeventIddisplayNamedefaultMessagecategory(Phase2EventCategory:ShipSystem,Social,CivilianSociety,TransitExternal,ContinuumAnomaly)baseWeightcooldownDaysminDaymaxDayminPressure01maxPressure01minEventBudget01maxEventBudget01earlyTransitWeightmidTransitWeightlateTransitWeightpreferLeastRecentlySeen
Conditions/execution:
requiresCivilianPopulationrequiresUnrestrequiresContinuumResearchUnlockminCivilianUnrestmaxCivilianUnrestminShipStrainmaxShipStrainminContinuumInstabilitymaxContinuumInstabilityminFoodDaysminWaterDaysrequiredContextTags(List<string>)blockedContextTags(List<string>)actionType(Phase2EventActionType:LegacyOperationalIncident,LegacyCivilianUnrest,LegacyCivilianIdeology,LegacyContinuumIncident,NarrativeAlert)triggerChanceseverityMin01severityMax01consumeCategoryBudget
Variants/chains:
variants(List<Phase2TransitEventVariant>)variants[i].variantIdvariants[i].weightMultipliervariants[i].messageOverridevariants[i].requiredContextTagsvariants[i].blockedContextTagsvariants[i].followupEventIds
followupMinDelayDaysfollowupMaxDelayDays
12.7 resources (ResourceDefSO)
stableIdiddisplayNameiconresourceType(ResourceType)stackablestackLimittint(Color)
12.8 missions (MissionSiteDefinition)
Identity/core:
stableIdsiteIdphase(RunPhase; commonlyPhase1/Phase2, boot fallback also supported)titledescriptionimagemapPosNormalized(Vector2)focus(MissionFocus)focusOptions(List<MissionFocus>)allowedDurations(List<int>)rewardPreview
Taxonomy reward fields:
useRewardTaxonomyresourceRewards(List<MissionResourceRewardEntry>)resourceRewards[i].type(ResourceType)resourceRewards[i].minAmountresourceRewards[i].maxAmountresourceRewards[i].scaleWithCrew
archiveFragmentsMinarchiveFragmentsMaxsignalFragmentsMinsignalFragmentsMaxcivilianPickupMincivilianPickupMaxrareModuleChance01rareModuleRewards(List<MissionRareModuleRewardEntry>)rareModuleRewards[i].buildItemIdrareModuleRewards[i].weight
MissionFocus options:
IndustrialElectronicsBioPersonnelExtractionFuelRaidDerelictArcshipSalvageFrozenInfrastructureFieldCryosleepLifepodDetectionFuelExtractionPlatformUnknownSignalSourceArcshipEncounterDistressBeaconResponseHazardousSalvageZoneHostileInterceptionContinuumDistortionSiteCivilianRecovery
13. Practical Authoring Notes Per SO
- For
Add, define enough fields for valid gameplay behavior; otherwise objects may load but be unusable in UI/sim. - For array/list structs (for example
stages,variants,inputs,outputs), patch with explicit indices (variants[0].variantId). - For Unity asset refs (
Sprite,TileBase,*SOrefs), useres:Path/Inside/Resources. - Keep cross-def links on stable ids when possible (
requiredResearchId,craftRecipeIds, followup event ids).