Type: resource and Resource Nodes
Generate resource descriptors, remove matching world Resource Nodes, unlock scanner visibility, and patch node actor classes.
The resource type runs in the Items stage at priority 25, after item (30) and before
building (20). Its entries key is resources. The default and required base class is
/Script/FactoryGame.FGResourceDescriptor. Register-only mode (class:) is not supported, so
entries use id:. YAML files are scanned during GameInstance initialization and again through
/kdf reload. Existing generated resource classes keep their runtime identity, so restart the
session when removing or structurally replacing a generated resource definition.
The similar names hide four separate systems:
| Concept | FactoryGame type | What KDataForge does |
|---|---|---|
| Resource definition | UFGResourceDescriptor | type: resource generates a new descriptor class |
| Resource Node removal | AFGResourceNodeBase and subclasses | type: resourcenode destroys matches by descriptor and optional node type |
| Resource Node property patch | AFGResourceNodeBase and subclasses | A cdo actor patch modifies a node class and all matching instances |
| Scanner visibility | UFGUnlockScannableResource | A schematic unlocks: entry registers descriptor and node-type pairs |
| AWESOME Sink value | AFGResourceSinkSubsystem data | type: sinkpoints sets item scores and has no node-placement behavior |
type: resource does not spawn, place, move, or remove Resource Node actors. A generated
descriptor becomes mineable only when a map or another mod assigns it to a compatible node.
Removal is a separate, destructive capability under type: resourcenode.
Generate a resource descriptor
Section titled “Generate a resource descriptor”resource uses the same class-generation mechanism as
Items, but defaults to FGResourceDescriptor and
rejects parents outside that hierarchy.
type: resourceresources: - id: MySuperCoolant parent: /Game/FactoryGame/Resource/RawResources/Water/Desc_Water.Desc_Water_C properties: - path: mDisplayName value: Super Coolant - path: mForm value: RF_LIQUID - path: mFluidColor value: R: 40 G: 200 B: 255 A: 255Parenting from Desc_Water inherits its fluid-oriented defaults. The generated class has the
canonical path /KDataForge/Gen/<PackRef>.Gen_<PackRef>_<Id> with no _C suffix. You can also
reference it by the short id MySuperCoolant when resolution is unambiguous.
FGResourceDescriptor adds these reflected defaults on top of FGItemDescriptor:
| Property | Purpose |
|---|---|
mDepositMesh, mDepositMaterial | Loose resource-deposit visuals |
mDecalMaterial, mDecalSize | Ground decal and collision footprint |
mPingColor, mCompassTexture | Scanner and map presentation |
mCollectSpeedMultiplier | Manual collection speed multiplier |
mManualMiningParticle, mFactoryMiningParticle, mDestroyedParticle | Mining effects |
mManualMiningAudioName | Manual-mining audio event name |
mFrackingHighlightParticleSystemTemplate | Resource-well highlight effect |
Inherited item fields such as mForm, display texts, icons, category, stack size, and gameplay
tags remain available through the same properties: grammar.
Make mForm match the use case
Section titled “Make mForm match the use case”mForm controls whether belts, pipes, extractors, and recipes accept the resource. Generating a
liquid descriptor does not create a pipe-compatible producer or a world node. KDataForge validates
the enum and property types, but it cannot validate the rest of your gameplay chain.
Removing Resource Nodes (type: resourcenode)
Section titled “Removing Resource Nodes (type: resourcenode)”resourcenode runs in the SubsystemMods stage, after generated resource descriptors exist. Its
remove: sequence registers world-purge rules. A scalar entry removes every node whose effective
resource descriptor matches. A map adds filters and safety controls:
type: resourcenoderemove: # Scalar shorthand: all node types, occupied nodes protected, scanner entries removed. - /Game/FactoryGame/Resource/RawResources/Uranium/Desc_OreUranium.Desc_OreUranium_C
- resource: MyCustomOre # generated-content short ids work nodeTypes: - Node - Deposit allowOccupied: false removeFromScanner: true| Field | Default | Meaning |
|---|---|---|
resource | required¹ | UFGResourceDescriptor class path or generated-content short id |
nodeTypes | all | Sequence of Node, FrackingSatellite, FrackingCore, Geyser, or Deposit |
allowOccupied | false | When false, skips a node group used by an extractor |
removeFromScanner | true | Also removes scanner pairs and matching KAPI extractor allow-list data |
¹ Instead of resource:, an entry may carry an ofClass: scope (default FGResourceDescriptor)
plus the scope filters
(matchName:, matchTag:, where:, …); the entry’s options then apply to every loaded descriptor
class that passes, and the load report says how many matched:
type: resourcenoderemove: - ofClass: /Script/FactoryGame.FGResourceDescriptor matchName: Desc_OreUranium* # vanilla uranium plus any modded variant named like it nodeTypes: [Node]Qualified node-type names such as EResourceNodeType::Geyser also work. An omitted or empty
nodeTypes sequence matches every type. Matching uses each node’s effective resource class,
including a runtime resource override; it is exact by descriptor class and does not match
descriptor subclasses implicitly. There is no filter for transform, purity, amount, or level name.
Purge rules run before world BeginPlay, for later actor spawns and streamed levels, and once more
on the next tick to catch nodes retargeted by the vanilla randomizer or KBFL. Destruction is
server-authoritative. Clients remove the separate local mesh actor and rebuild scanner clusters;
radar-tower resource caches are rebuilt on the server. Removing a fracking core also removes its
satellites so no satellite keeps a dead core reference.
With allowOccupied: false, KDataForge checks the whole fracking group and skips it when an
extractor is attached. allowOccupied: true overrides that protection and can leave the extractor
holding an invalid node reference. Use it only after removing affected extractors.
When removeFromScanner is true, KDataForge removes every vanilla scanner pair for the descriptor,
updates KAPI allow/deny data when KAPI is installed, and reapplies the exclusion after schematic
purchases repopulate unlock data. Set it to false only when a scanner entry with no matching node is
intentional.
Patching Resource Node actor classes (type: cdo)
Section titled “Patching Resource Node actor classes (type: cdo)”The built-in cdo handler selects classes, standalone asset objects, asset families, or gameplay
tags. Runtime actor patches then match actors by class. Unlike resourcenode, property patches have
no selector for actor transform, current resource, purity, node type, or level-instance name.
| Goal | Current support |
|---|---|
| Patch the CDO of one custom Resource Node actor class | Yes, with type: cdo |
| Apply properties to every instance of that class | Yes, with applyToSpawnedActors: true |
| Include every derived node class | Yes, with applyToSubclasses: true; this is very broad |
| Patch one pre-placed node by map location or object path | No; world actors do not exist during initial target resolution |
| Select nodes by descriptor for property writes | No; descriptor selection is available only for resourcenode removal |
| Place, move, or clone world nodes | No |
| Remove nodes by descriptor and optional node type | Yes, with type: resourcenode |
| Create or wire fracking cores and satellites | No |
For a custom mod where every desired node has its own actor class, a class-scoped patch is useful:
type: cdoconditions: hasMod: YourNodeModpatches: - target: /YourNodeMod/World/BP_MyOreNode.BP_MyOreNode_C applyToSpawnedActors: true applyToSubclasses: false properties: - path: mExtractMultiplier value: 2 - path: mCanPlaceResourceExtractor value: trueThe patch first writes the class default. At world begin play, it also writes the same properties to every matching pre-existing actor. Every later matching spawn receives them as well. These instance writes do not preserve player-modified or save-restored values.
Targeting /Script/FactoryGame.FGResourceNode with applyToSubclasses: true would affect nearly
every ordinary node, including nodes added by other mods. Use that only when the global scope is
intentional.
Reflectable fields and runtime caveats
Section titled “Reflectable fields and runtime caveats”FactoryGame exposes relevant UPROPERTY fields including mResourceClass,
mResourceClassOverride, mResourceNodeType, mPurity, mPurityOverride, mAmount,
mResourcesLeft, mCanPlaceResourceExtractor, and mExtractMultiplier. Fracking satellites also
carry an instance-only mCore link.
Scanner visibility and removal
Section titled “Scanner visibility and removal”Use an instanced FGUnlockScannableResource on a schematic to add a descriptor and node-type pair
to the scanner:
type: schematicschematics: - id: Schematic_MyCustomOre unlocks: - class: /Game/FactoryGame/Unlocks/BP_UnlockScannableResource.BP_UnlockScannableResource_C properties: - path: mResourcePairsToAddToScanner value: - ResourceDescriptor: MyCustomOre ResourceNodeType: NodeResourceNodeType accepts Node, FrackingSatellite, FrackingCore, Geyser, or Deposit.
This only makes matching existing nodes scannable. It does not place them. See
Schematics
and the Base-Game Unlock Classes.
This unlock is additive. To remove a descriptor from scanner data while purging its nodes, keep
removeFromScanner: true on the corresponding type: resourcenode rule.
Advanced Resource Node visual metadata
Section titled “Advanced Resource Node visual metadata”FactoryGame stores randomized-node mesh overrides in UFGResourceNodeData. This
UPrimaryDataAsset contains mResourceDescriptor and an mNodeMeshOverrides map keyed by
ENodeMeshType: MT_Node, MT_Core, MT_Crack, MT_Satellite, and the desert variants.
Existing assets can be edited through cdo, and KDataForge can create a dataasset instance of
that class. Override values reference cooked meshes and materials. type: asset only creates 2D
textures. This metadata changes visuals, not world placement, and its startup timing must be tested
against the Resource Node Manager in the target game build.
Troubleshooting
Section titled “Troubleshooting”- The descriptor exists but there is nothing to mine: A descriptor is not a world actor. Place or spawn a compatible node in a map or dedicated mod.
- The Object Scanner cannot find it: Add
FGUnlockScannableResourcewith the correctResourceNodeType, and make sure matching nodes exist. - An actor patch changed too many nodes: Narrow
target:to a dedicated custom node class and keepapplyToSubclasses: false. - A removed node did not come back after deleting the pack: Vanilla persisted its destruction. Restore a backup or use a purpose-built save repair workflow; KDataForge cannot recreate the original level actor from YAML.
- An occupied node was skipped: Remove its extractor first. Avoid
allowOccupied: trueunless invalidating the extractor’s saved node reference is intentional. - The scanner still lists a removed resource: Use
removeFromScanner: trueand confirm the same pack is installed on every process. Purchased schematic unlocks are filtered again at runtime. - Descriptor or purity changed but visuals or extraction did not: The game may already have initialized or cached related state. Direct reflection does not invoke setters or notifications.
- Sink points did not help: Sink Points only control AWESOME Sink scoring. They have no Resource Node or scanner behavior.
- Need the resource in a recipe?
Itemscompletes beforeRecipes, so reference the short id or/KDataForge/Gen/<PackRef>.Gen_<PackRef>_<Id>directly. Noinclude:is needed across stages.
