Skip to content
k-mods.com

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:

ConceptFactoryGame typeWhat KDataForge does
Resource definitionUFGResourceDescriptortype: resource generates a new descriptor class
Resource Node removalAFGResourceNodeBase and subclassestype: resourcenode destroys matches by descriptor and optional node type
Resource Node property patchAFGResourceNodeBase and subclassesA cdo actor patch modifies a node class and all matching instances
Scanner visibilityUFGUnlockScannableResourceA schematic unlocks: entry registers descriptor and node-type pairs
AWESOME Sink valueAFGResourceSinkSubsystem datatype: 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.

resource uses the same class-generation mechanism as Items, but defaults to FGResourceDescriptor and rejects parents outside that hierarchy.

super-coolant.resource.yml
type: resource
resources:
- 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: 255

Parenting 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:

PropertyPurpose
mDepositMesh, mDepositMaterialLoose resource-deposit visuals
mDecalMaterial, mDecalSizeGround decal and collision footprint
mPingColor, mCompassTextureScanner and map presentation
mCollectSpeedMultiplierManual collection speed multiplier
mManualMiningParticle, mFactoryMiningParticle, mDestroyedParticleMining effects
mManualMiningAudioNameManual-mining audio event name
mFrackingHighlightParticleSystemTemplateResource-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.

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: resourcenode
remove:
# 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
FieldDefaultMeaning
resourcerequired¹UFGResourceDescriptor class path or generated-content short id
nodeTypesallSequence of Node, FrackingSatellite, FrackingCore, Geyser, or Deposit
allowOccupiedfalseWhen false, skips a node group used by an extractor
removeFromScannertrueAlso 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: resourcenode
remove:
- 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.

GoalCurrent support
Patch the CDO of one custom Resource Node actor classYes, with type: cdo
Apply properties to every instance of that classYes, with applyToSpawnedActors: true
Include every derived node classYes, with applyToSubclasses: true; this is very broad
Patch one pre-placed node by map location or object pathNo; world actors do not exist during initial target resolution
Select nodes by descriptor for property writesNo; descriptor selection is available only for resourcenode removal
Place, move, or clone world nodesNo
Remove nodes by descriptor and optional node typeYes, with type: resourcenode
Create or wire fracking cores and satellitesNo

For a custom mod where every desired node has its own actor class, a class-scoped patch is useful:

type: cdo
conditions:
hasMod: YourNodeMod
patches:
- target: /YourNodeMod/World/BP_MyOreNode.BP_MyOreNode_C
applyToSpawnedActors: true
applyToSubclasses: false
properties:
- path: mExtractMultiplier
value: 2
- path: mCanPlaceResourceExtractor
value: true

The 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.

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.

Use an instanced FGUnlockScannableResource on a schematic to add a descriptor and node-type pair to the scanner:

type: schematic
schematics:
- id: Schematic_MyCustomOre
unlocks:
- class: /Game/FactoryGame/Unlocks/BP_UnlockScannableResource.BP_UnlockScannableResource_C
properties:
- path: mResourcePairsToAddToScanner
value:
- ResourceDescriptor: MyCustomOre
ResourceNodeType: Node

ResourceNodeType 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.

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.

  • 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 FGUnlockScannableResource with the correct ResourceNodeType, and make sure matching nodes exist.
  • An actor patch changed too many nodes: Narrow target: to a dedicated custom node class and keep applyToSubclasses: 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: true unless invalidating the extractor’s saved node reference is intentional.
  • The scanner still lists a removed resource: Use removeFromScanner: true and 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? Items completes before Recipes, so reference the short id or /KDataForge/Gen/<PackRef>.Gen_<PackRef>_<Id> directly. No include: is needed across stages.