Skip to content
k-mods.com

Delivery Task Trees

A complete UKAPIDeliveryTask tree with every property set on every node five nodes including negative coordinates, multi-flag mParentTask, the full Endless field set, how completing a task unlocks more of the tree, and a schematic force-unlock example.

UKAPIDeliveryTask is KAPI’s 2D research-tree node type: a small reward/task, placed on an integer coordinate grid, that unlocks once its neighboring parent node(s) are completed. This feature has no Satisfactory Plus dependency it only needs KAPI + KPrivateCodeLib, so it’s usable from any mod that links those two.

This page builds one complete tree end to end. For every other KAPI data asset type, see Adding KAPI Data Assets; for the underlying YAML grammar mParentTask uses, see Value Forms.

Each node has an mCoordinate (FIntVector2 with X and Y fields; negative values are perfectly valid, the grid isn’t anchored to the origin) and an mParentTask bitmask using EKAPIDeliveryTaskParent. Each flag maps to a bit and fixed coordinate offset relative to the node itself:

FlagMaskParent is at
None0no parent
Above1(X, Y - 1)
Left2(X - 1, Y)
Right4(X + 1, Y)
Bottom8(X, Y + 1)
AboveLeft16(X - 1, Y - 1)
AboveRight32(X + 1, Y - 1)
BelowLeft64(X - 1, Y + 1)
BelowRight128(X + 1, Y + 1)

Every flag set on a node must point at a coordinate some other node in the tree actually occupies, or the node is rejected at load time. Use one flag name for one parent and a YAML sequence for multiple parents. KDataForge resolves and ORs names automatically. Scalar names, sequences, and |-joined strings ("Above|Left") are Shipping-safe. Raw integer masks such as 3 remain accepted.

mRequiredParentCompletions defaults to 1 and raises the completed-run threshold for every marked parent. This is useful behind an endless parent:

- path: mParentTask
value: Bottom
- path: mRequiredParentCompletions
value: 10

Values below 1 are rejected. A queued parent can satisfy default one-run topology so its child can be placed later in same queue. Thresholds above 1 count completed runs only; queued repeats do not unlock or pre-queue child.

The tree below sets every applicable property on every node, including the icon, ADA message, and Endless-only amount-multiplier curve those fields reference. Those three are generated by a small support file, include:-ed so they load first (dataasset/curve/asset all run in the same Assets stage, so ordering across document types is otherwise just file order, not implicit see Document Structure):

showcase-delivery-task-support.yml
type: asset
assets:
- id: DeliveryTaskIcon
file: mod-logo.png # pack-relative path any 2D image works as a placeholder
---
type: dataasset
conditions:
hasMod: KAPI
assets:
- id: AdaMessage_TaskComplete
class: /Script/FactoryGame.FGMessage # UFGMessage is a UPrimaryDataAsset, so `dataasset` builds it directly
properties:
- path: mTitle
value: "Delivery Complete"
- path: mMessage
value: "Another delivery task in the showcase tree has been completed."
---
type: curve
curveType: float
curves:
- id: DeliveryTaskAmountMultiplier
defaultValue: 1
preInfinityExtrap: constant
postInfinityExtrap: linear
isEventCurve: false
keys:
- time: 0
value: 1
interpMode: linear
- time: 5
value: 2.5
interpMode: linear

This tree deliberately starts off-origin, in negative coordinate space, to show the grid isn’t restricted to (0, 0)-anchored positive layouts. Every node sets every UKAPIDataAssetBase common field (mName/mDescription/mIcon/mIsDisabled/mPriority/mTags) and every UKAPIDeliveryTask field common to both variants (mAdaMessages/mToastIcon/mToastText). DeliveryTask_Right is switched to bIsEndless: true to demonstrate the complete Endless-only field set (mPoolElements/mTaskRewards/mMaxTasks/mAmountMultiplierCurve/ mAbsolutMaxItemAmount) that a One-Time node never sets; every other node stays One-Time (bIsEndless: false) and sets the complete One-Time field set (mRewards/mCosts, plus mSchematics on the last node):

showcase-delivery-task.dataasset.yml
type: dataasset
conditions:
hasMod: KAPI
include:
- showcase-delivery-task-support.yml
assets:
- id: DeliveryTask_Root
class: /Script/KAPI.KAPIDeliveryTask
properties:
# --- UKAPIDataAssetBase common fields ---
- path: mName
value: "Root Task"
- path: mDescription
value: "The starting node of the showcase tree. No parent required."
- path: mIcon
value: DeliveryTaskIcon
- path: mIsDisabled
value: false
- path: mPriority
value: 0
- path: mTags
value:
- KMods.EventOnly
# --- UKAPIDeliveryTask common fields ---
- path: mAdaMessages
value:
- AdaMessage_TaskComplete
- path: mToastIcon
value: DeliveryTaskIcon
- path: mToastText
value: "You completed the Root Task."
- path: mCoordinate
value:
X: -2
Y: -1
# mParentTask / bRequireAllParents intentionally omitted the root has no parent, and
# bRequireAllParents is ignored once there's nothing to require.
- path: bIsEndless
value: false
# --- One-Time fields (bIsEndless: false) ---
- path: mRewards
value:
- ItemClass: /Game/FactoryGame/Resource/Parts/IronIngot/Desc_IronIngot.Desc_IronIngot_C
Amount: 50
# mCosts omitted empty cost list makes this tree entry free.
- id: DeliveryTask_Above
class: /Script/KAPI.KAPIDeliveryTask
properties:
- path: mName
value: "Single-Parent Child"
- path: mDescription
value: "Requires only the Above parent (Root)."
- path: mIcon
value: DeliveryTaskIcon
- path: mIsDisabled
value: false
- path: mPriority
value: 0
- path: mTags
value:
- KMods.EventOnly
- path: mAdaMessages
value:
- AdaMessage_TaskComplete
- path: mToastIcon
value: DeliveryTaskIcon
- path: mToastText
value: "You completed the Single-Parent Child task."
- path: mCoordinate
value:
X: -2
Y: 0
# Above -> (-2, -1): Root
- path: mParentTask
value: Above
- path: bRequireAllParents
value: true
- path: bIsEndless
value: false
- path: mRewards
value:
- ItemClass: /Game/FactoryGame/Resource/Parts/IronPlate/Desc_IronPlate.Desc_IronPlate_C
Amount: 50
- path: mCosts
value:
- ItemClass: /Game/FactoryGame/Resource/Parts/IronIngot/Desc_IronIngot.Desc_IronIngot_C
Amount: 20
- id: DeliveryTask_Right
class: /Script/KAPI.KAPIDeliveryTask
properties:
- path: mName
value: "Endless Sibling Child"
- path: mDescription
value: "Requires only the Left parent (Root). Endless variant demonstrates
every Endless field."
- path: mIcon
value: DeliveryTaskIcon
- path: mIsDisabled
value: false
- path: mPriority
value: 0
- path: mTags
value:
- KMods.EventOnly
- path: mAdaMessages
value:
- AdaMessage_TaskComplete
- path: mToastIcon
value: DeliveryTaskIcon
- path: mToastText
value: "You completed another round of the Endless Sibling Child task."
- path: mCoordinate
value:
X: -1
Y: -1
# Left -> (-2, -1): Root
- path: mParentTask
value: Left
- path: bRequireAllParents
value: true
- path: bIsEndless
value: true
# --- Endless-only fields (bIsEndless: true) ---
- path: mPoolElements
value:
- mItem: /Game/FactoryGame/Resource/Parts/IronIngot/Desc_IronIngot.Desc_IronIngot_C
mAmountRange:
LowerBound:
Type: Inclusive
Value: 50
UpperBound:
Type: Exclusive
Value: 200
mRequiredTas: -1 # INDEX_NONE eligible from the very first roll
- path: mTaskRewards
value:
- mRewards:
- ItemClass: /Game/FactoryGame/Resource/Parts/IronPlate/Desc_IronPlate.Desc_IronPlate_C
Amount: 25
mRequiredTask: -1 # INDEX_NONE granted on every completion
- path: mMaxTasks
value: 10 # INDEX_NONE/-1 would mean uncapped concurrent slots
- path: mAmountMultiplierCurve
value: DeliveryTaskAmountMultiplier
- path: mAbsolutMaxItemAmount
value:
RF_SOLID: DeliveryTaskAmountMultiplier
RF_LIQUID: DeliveryTaskAmountMultiplier
- id: DeliveryTask_AboveAndLeft
class: /Script/KAPI.KAPIDeliveryTask
properties:
- path: mName
value: "Two-Parent Child"
- path: mDescription
value: "Requires both the Above and Left parents at once (AND semantics)."
- path: mIcon
value: DeliveryTaskIcon
- path: mIsDisabled
value: false
- path: mPriority
value: 0
- path: mTags
value:
- KMods.EventOnly
- path: mAdaMessages
value:
- AdaMessage_TaskComplete
- path: mToastIcon
value: DeliveryTaskIcon
- path: mToastText
value: "You completed the Two-Parent Child task."
- path: mCoordinate
value:
X: -1
Y: 0
# Above -> (-1, -1): Right, Left -> (-2, 0): Above
- path: mParentTask # multiple flags set in parallel
value:
- Above
- Left
- path: bRequireAllParents
value: true # AND: both parents must be completed first
- path: bIsEndless
value: false
- path: mRewards
value:
- ItemClass: /Game/FactoryGame/Resource/Parts/IronPlate/Desc_IronPlate.Desc_IronPlate_C
Amount: 100
- path: mCosts
value:
- ItemClass: /Game/FactoryGame/Resource/Parts/IronIngot/Desc_IronIngot.Desc_IronIngot_C
Amount: 40
- id: DeliveryTask_UnlockSuperIngot
class: /Script/KAPI.KAPIDeliveryTask
properties:
- path: mName
value: "Unlock: Pure Super Ingot"
- path: mDescription
value: "Force-unlocks the Pure Super Ingot schematic on completion."
- path: mIcon
value: DeliveryTaskIcon
- path: mIsDisabled
value: false
- path: mPriority
value: 0
- path: mTags
value:
- KMods.EventOnly
- path: mAdaMessages
value:
- AdaMessage_TaskComplete
- path: mToastIcon
value: DeliveryTaskIcon
- path: mToastText
value: "Pure Super Ingot production unlocked!"
- path: mCoordinate
value:
X: -1
Y: 1
# Above -> (-1, 0): AboveAndLeft
- path: mParentTask
value: Above
- path: bRequireAllParents
value: true
- path: bIsEndless
value: false
- path: mSchematics # force-unlocked by HandleUnlock on completion
value:
- /Game/YourMod/Schematics/Schematic_PureSuperIngot.Schematic_PureSuperIngot_C
- path: mRewards
value:
- ItemClass: /Game/FactoryGame/Resource/Parts/IronIngot/Desc_IronIngot.Desc_IronIngot_C
Amount: 500
- path: mCosts
value:
- ItemClass: /Game/FactoryGame/Resource/Parts/IronPlate/Desc_IronPlate.Desc_IronPlate_C
Amount: 100

Five nodes, four edges: Root has no parent (the tree’s entry point), Above/Right each depend on Root alone, AboveAndLeft depends on both Above and Right at once (the multi-flag case), and UnlockSuperIngot depends on AboveAndLeft.

Delivery-task data assets accept dedicated dependencies: and unlocks: lists alongside properties:. They append to mTaskDependencies and mUnlocks; generic property ops cannot construct these instanced subobjects.

assets:
- id: DeliveryTask_AboveAndLeft
class: /Script/KAPI.KAPIDeliveryTask
dependencies:
- class: /Script/FactoryGame.FGSchematicPurchasedDependency
properties:
- path: mSchematics
value:
- Schematic_MyPrerequisite
unlocks:
- class: /Script/FactoryGame.FGUnlockGiveItem
properties:
- path: mItemsToGive
value:
- ItemClass: /Game/FactoryGame/Resource/Parts/IronPlate/Desc_IronPlate.Desc_IronPlate_C
Amount: 25

Known native paths automatically remap to Blueprint implementations; exact Blueprint paths remain valid. See Base-Game Unlock Classes and Availability Dependency Classes.

How completing a task unlocks more of the tree

Section titled “How completing a task unlocks more of the tree”

A node becomes available once its mParentTask requirement is satisfied:

  • bRequireAllParents: true (the default) every flagged parent must be completed first (AND). DeliveryTask_AboveAndLeft above needs both Above and Right done.
  • bRequireAllParents: false any one flagged parent completing is enough (OR). Useful for a node reachable from more than one earlier branch, whichever the player finishes first.
  • mRequiredParentCompletions: 1 (the default) completion count each marked parent must reach. Raise it for branches behind repeatable tasks; AND/OR semantics then compare parents against same threshold.
  • mTaskDependencies (an availability-dependency list, checked via AreTaskDependenciesMet) adds further gating on top of the parent-tree check itself a schematic purchase, a research unlock, whatever the dependency subclass checks. Parent completion and mTaskDependencies are independent gates: both must pass.

For an endless node (bIsEndless: true), “unlocking more” also means more concurrent task slots: mMaxTasks caps how many of that node’s rolled tasks can be active/queued at once (INDEX_NONE/-1 for uncapped), and mAmountMultiplierCurve / mAbsolutMaxItemAmount scale the reward amounts up as the player completes more rounds of it so the effective “how much can I get from this node” grows over time even though the node itself doesn’t move in the tree.

Unlock example force-unlocking a schematic

Section titled “Unlock example force-unlocking a schematic”

DeliveryTask_UnlockSuperIngot above is the unlock example: its mSchematics force-unlocks Schematic_PureSuperIngot via HandleUnlock on completion, regardless of whether the player could normally research or purchase it another way the same mechanism unlocks: / dependencies: use on schematics themselves, just triggered from a delivery-task completion instead. mRewards/ mCosts on that same node are the plain item grant/cost, independent of the schematic unlock.