Skip to content
k-mods.com

Property Types

One working example for every supported property datatype, and the gotchas specific to each.

Every properties: entry inside a type: cdo patch (see Patching) targets one reflected UE property, and the value: you write has to match that property’s kind. KDataForge’s value codec recognizes each UE property class in turn: bool, enum, numeric, string, object/class reference, struct, container. It only falls through to raw UE text-import for anything it doesn’t special-case. This page walks through every kind it handles, in the order the codec checks them, so you know exactly what YAML shape to reach for. Pair this with Operations for what you can do to a value once you’ve written it, and Targeting for picking what object the patch applies to.

Booleans accept more than just true/false: yes/no and on/off (case-insensitive) and the bare digits 1/0 all parse too, so you can match whichever style reads best in context:

- path: mCanBeDiscarded
value: false # true/false, yes/no, on/off, 1/0

int32 / uint8 / int64 (all integer widths)

Section titled “int32 / uint8 / int64 (all integer widths)”

Every plain integer property takes a bare number, regardless of its bit width. You never need to worry about the exact C++ type:

- path: mResourceSinkPoints
value: 500
- path: mMenuPriority
value: 42

Floating-point properties take a decimal number. Setting mManufactoringDuration to a fraction halves the crafting time, since it’s read in seconds:

- path: mManufactoringDuration
value: 2.5
- path: mEnergyValue
value: 300.0

Unreal exposes two enum styles: the typed enum class and the older TEnumAsByte (a numeric property with an attached enum). Both are handled the same way. Write the value’s name, optionally qualified with the enum’s own name, or its numeric ordinal:

- path: mForm
value: RF_LIQUID # plain value name
- path: mForm
value: EResourceForm::RF_GAS # qualified form
- path: mForm
value: 2 # numeric value (the enum's underlying ordinal)
- path: mStackSize
value: SS_HUGE # EStackSize always use the name, not a raw count

bitmask (int32/uint8 with BitmaskEnum metadata)

Section titled “bitmask (int32/uint8 with BitmaskEnum metadata)”

Bitmask properties store several enum flags in one integer. Use a scalar for one flag and a YAML sequence for several flags:

- path: mParentTask
value: Above
- path: mParentTask
value:
- Above
- Left

KDataForge also accepts an inline sequence, a |-joined string, or a raw pre-computed integer mask. All named forms are Shipping-safe. Names are preferred because they remain readable:

- path: mParentTask
value:
- Above
- Left
- path: mParentTask
value: "Above|Left"
- path: mParentTask
value: 3 # Above (1) | Left (2)

Plain reflected strings take a quoted scalar as-is, no escaping beyond normal YAML quoting rules:

- path: mSomeString
value: 'Hello Ficsit'

FName properties look identical to FString in YAML. The codec just wraps the text in an FName before writing it. This matters for fields UE compares by name identity, like the quick-switch group below, rather than by string content:

- path: mQuickSwitchGroup
value: 'ingots'

A bare scalar for an FText property produces a culture-invariant literal text useful for internal/debug strings, but not localizable. For anything player-facing, prefer the keyed form below or route it through Localization:

- path: mDisplayName
value: 'Better Iron Ingot'

Passing a map instead of a scalar creates a properly keyed, localizable FText instead of an invariant literal. The key field is required, while ns and source are optional. A map containing only source is invalid; use a scalar for culture-invariant text. This uses the same runtime-safe construction path the localization system relies on:

- path: mDisplayName
value:
key: BetterIronIngot_Name
ns: MyPack
source: Better Iron Ingot

Hard object references (UObject* properties) take a full asset or object path, resolved and loaded immediately. Use none (or an empty string) to null one out:

- path: mCategory
value: /Game/FactoryGame/Resource/ItemCategories/Cat_Ingots.Cat_Ingots_C
- path: mSmallIcon
value: /Game/FactoryGame/Resource/Parts/IronIngot/UI/IconDesc_IronIngot_64.IconDesc_IronIngot_64
- path: mConveyorMesh
value: none # null out a reference with none or ""

Class references also take a path, but the codec tries several forms in order before giving up:

  1. The path as given.
  2. The path with a _C suffix appended (Blueprint class paths are frequently written without it).
  3. The asset-path-to-object-path expansion.
  4. For a bare name with no / or . at all, a generated-content id from the current pack first, then from every loaded pack.
  5. If no generated class matches, a search across every currently loaded class by short name (see Targeting for the same shortcut applied to target:).
- path: mOverriddenCategory
value: /Game/FactoryGame/Resource/ItemCategories/Cat_Ingots.Cat_Ingots_C # BP class (`_C` auto-retried)
- path: mClassToScanFor
value: /Script/FactoryGame.FGBuildableResourceExtractor # native class
- path: mProducedIn
value: Recipe_MyGeneratedRecipe # generated-content id from this pack, if present
- path: mFluidClass
value: Desc_Water # bare-name shortcut for Desc_Water.Desc_Water_C see Targeting

Soft references (TSoftObjectPtr / TSoftClassPtr)

Section titled “Soft references (TSoftObjectPtr / TSoftClassPtr)”

The value is stored as a path string and never force-loads the target. The referenced asset only loads if and when the game actually needs it:

- path: mPersistentBigIcon
value: /Game/FactoryGame/Resource/Parts/IronIngot/UI/IconDesc_IronIngot_256.IconDesc_IronIngot_256
# stored as a path, not loaded until the game needs it

For structs with a native text representation, like FLinearColor, FVector, FGuid, and FGameplayTag, a plain scalar is parsed through that format. This is the same round-trip form the editor’s “Copy” action produces:

- path: mFluidColor
value: '(R=255,G=100,B=0,A=255)'

Struct: map form (member names, Blueprint-authored names work too)

Section titled “Struct: map form (member names, Blueprint-authored names work too)”

Any struct also accepts a YAML map keyed by member name. This is resolved through the same flexible member lookup used elsewhere, so Blueprint-authored display names work, not just the raw C++ field name. Each value is recursively converted through this same codec for that member’s type:

- path: mFluidColor
value:
R: 255
G: 100
B: 0
A: 255

Struct: positional sequence form (members in declaration order)

Section titled “Struct: positional sequence form (members in declaration order)”

A YAML sequence assigns struct members positionally, in C++ declaration order. This is handy for terse, well-known structs, like a color or vector, where the member order never changes:

- path: mScannerLightColor
value:
- 1.0
- 0.5
- 0.0
- 1.0

Struct members that are themselves structs recurse through the same map/sequence/scalar rules to arbitrary depth. Deeply nested data, like a struct inside a struct inside an array, reads and writes exactly like the flat cases above, just indented:

- path: mCustomScannableDetails
value:
ScannableType: STY_Default
NewDetails:
Range: 500

Setting a TArray property, the default set operation, empties the array and rebuilds it from the given sequence element by element. The value you write always fully replaces whatever was there before, rather than merging into it:

- path: mIngredients
value: # `set` replaces the whole array
- ItemClass: /Game/FactoryGame/Resource/RawResources/OreIron/Desc_OreIron.Desc_OreIron_C
Amount: 2
- ItemClass: /Game/FactoryGame/Resource/RawResources/Coal/Desc_Coal.Desc_Coal_C
Amount: 1

Arrays whose elements are instanced UObject references also use a sequence, but each element can define a new instance with class: and nested properties:. KDataForge creates the instance as a subobject of the patched target. With the default set op, the array is replaced rather than merged:

- path: mSchematicDependencies
value:
- class: /Game/FactoryGame/AvailabilityDependencies/BP_SchematicPurchasedDependency.BP_SchematicPurchasedDependency_C
properties:
- path: mSchematics
value:
- /SatisfactoryPlus/Content/SchematicManager/Schematics/Milestones/T1/Schematic_SF+_T1_0.Schematic_SF+_T1_0_C
- path: mRequireAllSchematicsToBePurchased
value: true

The class: must be a concrete subclass accepted by the array. For example, mUnlocks accepts FGUnlock subclasses and mSchematicDependencies accepts FGAvailabilityDependency subclasses. Nested entries use the same property paths and operations as top-level patch entries.

The same instanced-object entry shape also works with array append, prepend, and insert when you want to add entries without replacing the whole array:

- path: mUnlocks
op: append
value:
class: /Game/FactoryGame/Unlocks/BP_UnlockRecipe.BP_UnlockRecipe_C
properties:
- path: mRecipes
value:
- Recipe_MyGeneratedRecipe

Rather than replacing a whole array, a path can index straight into one element, and from there into that element’s own members. This lets you tweak a single ingredient’s amount without re-listing every other ingredient:

- path: mIngredients[0].Amount
value: 3

TSet properties also take a plain YAML sequence. Entries collapse if the type’s equality would make them duplicates, since a set has no concept of ordering or repeated elements:

- path: mSubCategories # sets take sequences; duplicates collapse
value:
- /Game/FactoryGame/Resource/ItemCategories/SC_Smelted.SC_Smelted_C

A TMap property takes a YAML map. Each key is converted through the map’s own key property type before insertion, not just kept as a raw string. A bracketed key path lets you update a single entry in place instead of replacing the whole map:

- path: mSomeMap
value:
Iron: 10 # keys converted through the map's key property type
Copper: 20
- path: mSomeMap["Iron"] # single-entry access via key path
value: 15

A single gameplay tag is a struct with a native text importer under the hood, so it takes a plain dotted scalar just like any other native-text struct:

- path: mStatisticGameplayTag
value: KMods.AlternateRecipe

A tag container takes a sequence of tags. As with arrays, the default set operation replaces the whole container rather than adding to it. See Operations for the append/prepend/remove/clear variants that mutate a container instead, and Game Tags for registering your own tags before you reference them:

- path: mGameplayTags
value: # `set` replaces all tags
- KMods.WikiExclude
- MyPack.Special

Any reflected type not listed above still works. The codec falls back to UE’s own generic text import, so it accepts whatever text form the editor’s “Copy” action produces for that property. This holds even for exotic or third-party struct types this page doesn’t know about by name:

- path: mSomeExoticStruct
value: '(InnerValue=3,Flags=(bEnabled=True))'

Values from configuration, settings and templates

Section titled “Values from configuration, settings and templates”

Any value: (and min: and max:) can come from pack configuration or from the game itself instead of being a literal:

- path: mManufactoringDuration
op: divide
value: cfg:balance.ironSpeed # typed reference: the whole unquoted scalar
- path: mDescription
value: 'Smelts at {cfg:balance.ironSpeed}x speed' # template inside a string
- path: mManufactoringDuration
value: '{recipe:/Game/FactoryGame/Recipes/Smelter/Recipe_IngotIron.Recipe_IngotIron_C:mManufactoringDuration}'

The first form inserts the field’s typed value, the second inserts text, and the third reads a property or calls a function on game data and keeps the result’s type because it is the whole value. Templates and Typed References covers the syntax. The value then goes through the codec of the destination property, so the type of the field must fit the property:

Destination propertyConfig field that fits
boolboolean
integer typesnumber with an integer valueType (within range), or a numeric select
float, double, and the operands of add, subtract, multiply, divide, min, max, clampany number
FStringany text, or a string select
FNametext with valueType string, name or tag
FTexttext with valueType string, text or name
enuma string select whose option values are enum names, or a text field
class, soft class, object, soft objecttext (the path as a string)
FGameplayTagtext with valueType: tag
FGameplayTagContainera multiple tag list
array or set with seta multiple field with matching elements
array or set with append, prepend, insert, replace, removea single field of the element type
structs and maps as a wholenone; set the members one by one, each from its own field

A lossy match, such as a decimal number into an integer property, is a warning in the editor (config.type-mismatch); an impossible one is an error.