Skip to content

AI and StateTree ability requests

Mass Forge provides a bounded, pollable ability-request contract for StateTree tasks, behavior systems, utility AI, and project-owned C++ controllers. It does not require delegate ownership and it does not add a hard dependency on Unreal's experimental Mass AI or StateTree plugins.

The API works for actorless Mass entities and represented entities through the same stale-safe handles. A request queues normal Mass Forge activation; it never bypasses grant, target, targeting-policy, tag, cooldown, charge, requirement, cost, transaction, or one-active-lifecycle rules.

Blueprint nodes

  • Request Mass Forge Ability Activation for AI returns an acceptance result and stable request ID.
  • Request Mass Forge Ability Activation for AI from Actors performs the same request after resolving represented source and optional target Actors.
  • Get Mass Forge AI Ability Request State retrieves the current state for that ID.
  • Cancel Mass Forge AI Ability Request cancels pending admission or asks the active cast/channel to follow its authored cancellation rule.
  • Forget Mass Forge AI Ability Request explicitly releases a terminal record.

These are world-context nodes, so Blueprint tasks do not need to cache the subsystem. Equivalent methods are available directly on UMF_AbilitySubsystem for C++ tasks.

StateTree task pattern

Store the returned RequestId as task instance data rather than on the entity.

  1. Enter State: call Request Mass Forge Ability Activation for AI. Return failure immediately if the receipt was not accepted.
  2. Tick: call Get Mass Forge AI Ability Request State with the stored ID.
  3. Return Running for Pending or Active.
  4. Return Succeeded for Succeeded.
  5. Return Failed for Failed, Cancelled, or Interrupted, unless the project's tree deliberately routes those outcomes differently.
  6. Exit State: if the task is leaving while the ticket is Pending or Active, call cancel. Once it is terminal, call forget.

Do not treat the poll function's Success result as ability success. It means only that the ticket exists. Read State.Status, then use State.Activation, State.Lifecycle, and State.EndReason for detail.

Status contract

StatusMeaningStateTree default
PendingAccepted by the bounded queue but not executed yetRunning
ActiveA cast or channel lifecycle is activeRunning
SucceededAn instant ability committed, or a cast/channel completed successfullySucceeded
FailedAdmission execution or lifecycle commit failedFailed
CancelledPending admission was suppressed or the lifecycle was cancelledFailed or project-specific
InterruptedThe lifecycle was interrupted, revoked, or lost its source entityFailed or project-specific

Activation retains the machine-readable ability result. While active, Lifecycle exposes its world-local instance ID, phase, remaining time, completed channel ticks, target, and commit state. Terminal lifecycle tickets also expose EndReason. This lets a task distinguish an unaffordable request from an invalid target, a user cancellation from an interruption, or a normal completion from a commit-time revalidation failure.

Timing and cancellation

New requests begin as Pending. The shared deferred coordinator executes ability requests in its normal final phase, after queued attribute changes, Instant Effects, and damage. Existing lifecycles advance before new requests are admitted, so a newly started cast never consumes the frame delta that admitted it.

Cancelling Pending changes the ticket to Cancelled immediately and guarantees that its queued gameplay operation is suppressed. The ticket may safely be forgotten before the queue drains; cancellation is retained internally until that queue item is consumed.

Cancelling Active delegates to the ability lifecycle. An ability with Can Be Cancelled disabled returns Cancellation Blocked and remains active. Cancellation does not refund an already committed channel; see ABILITY_LIFECYCLE_GUIDE.md.

Bounded retention

Max Tracked AI Ability Requests under Project Settings > Mass Forge > Global Attribute Schemas > Runtime limits retained tickets. Pending and active tickets are never evicted. When the limit is reached, the oldest terminal ticket is evicted to admit new work. If every slot is live, a new request returns Queue Full without entering the ability queue.

Call forget after consuming a terminal outcome when practical. Polling an evicted or forgotten positive ID returns Request Not Found; zero and negative IDs return Invalid Request ID. Forgetting live work returns Request Not Terminal.

Ticket records are runtime coordination state, not SaveGame data and are not included in replicated gameplay state. The owner-only network state stream exposes the entity's granted abilities, cooldowns, charges, and active lifecycle, but AI request tickets remain authority-local. Opt-in network Ability prediction is a separate presentation-only request ledger and never replicates or predicts AI tickets.

C++ sketch

cpp
if (RequestId == 0)
{
	const FMFAbilityRequestReceipt Receipt = AbilitySubsystem->RequestAbilityActivationForAI(Source, Target, Ability);
	if (!Receipt.WasAccepted())
	{
		return EStateTreeRunStatus::Failed;
	}
	RequestId = Receipt.RequestId;
}

FMFAbilityAIRequestState State;
if (AbilitySubsystem->GetAIAbilityRequestState(RequestId, State) != EMFAbilityResult::Success)
{
	return EStateTreeRunStatus::Failed;
}

return State.Status == EMFAbilityAIRequestStatus::Succeeded
	? EStateTreeRunStatus::Succeeded
	: State.IsTerminal() ? EStateTreeRunStatus::Failed : EStateTreeRunStatus::Running;

The sketch intentionally leaves task-exit policy to the host project. A task that owns the gameplay request should cancel it on early exit; an observer-only task should not.

Mass Forge documentation — generated from the shipping Markdown source.