API Reference

Public types. Everything here is in the CrimsonCombatText module unless noted.

UCrimsonCombatTextSubsystem

UTickableWorldSubsystem. Owns the simulation - queue, live instances, aggregation, scopes, motion evaluation - and hands each frame to a renderer. Never created on a dedicated server.

MemberKindPurpose
RequestCombatText(Target, Tags, Value, Prefix, Custom, Instigator, bApplyFilters)Local/singleplayer entry point. Supply Instigator so relationship rules can judge it; clear bApplyFilters for pops that must always appearQueue combat text locally. Singleplayer, or client-side effects
HandleIncomingEvent(Event)UFUNCTIONEntry point from the replication path; applies per-player filters
GetFilterSet()The active UCrimsonCombatTextFilterSet, or null. What the settings layer and the dev tools enumerate
OnRegistryLoadedFires when the async-loaded registry (and its filter set) is ready. Subscribe rather than polling
ShouldDisplayEvent(Event, OutTrace)Runs the chain against one event without spawning anything. OutTrace reports which row decided
BeginCombatTextScope(Target, ScopeTag)BlueprintCallableOpen an accumulation window without GAS
EndCombatTextScope(Target, ScopeTag)BlueprintCallableClose it and emit the summary
GetCombatTextScopeTotal(Target, ScopeTag)BlueprintPureRunning total of an open scope, or 0

UCrimsonCombatTextRegistry

UDataAsset. Maps tags to styles.

MemberTypePurpose
StylesTMap<FGameplayTag, FCrimsonCombatTextStyle>Tag to style. Hierarchical; most specific match wins
DefaultStyleFCrimsonCombatTextStyleUsed when nothing matches
ModifiersTMap<FGameplayTag, FCrimsonCombatTextStyleModifier>Orthogonal overlays, applied in ApplyOrder
MotionSetUCrimsonCombatTextMotionSet*Shared motion library styles resolve presets against
PlacementSetUCrimsonCombatTextPlacementSet*Shared placement library styles resolve presets against. Optional - unset anchors everything over its target
FilterSetThe ordered visibility chain. Unset means nothing is ever filtered
AdvancedRulesTArray<FCrimsonCombatTextStyleRule>Query escape hatch. Empty by default, never scanned unless populated
ResolveStyle(Tags)BlueprintNativeEventReturns FCrimsonCombatTextResolvedStyle. Override for custom selection

UCrimsonCombatTextMotionSet

UDataAsset. A shared library of curve-authored motion presets, seeded with built-ins on creation.

MemberTypePurpose
PresetsTMap<FGameplayTag, FCrimsonCombatTextMotion>Named motions. Add rows to define your own
FindPreset(Tag, OutMotion)BlueprintCallableLookup; false when the tag has no row

FCrimsonCombatTextStyle

FieldPurpose
FormatStringRich text. Tokens: {Value}, {Prefix}, {Custom}, {ValueStyle}, {PrefixStyle}
PrefixStyleTag / ValueStyleTagRich-text style rows applied to those segments
AnimationNameUWidgetAnimation the widget may play
MotionPresetTag resolved against the registry's MotionSet
MotionInline motion, used only when MotionPreset is unset
PlacementPresetTag resolved against the registry's PlacementSet. Unset anchors over the target
PlacementOffsetExtra offset on top of the placement, in layout units. Slate +Y is DOWN
AggregationWindowSeconds; merge repeat hits into one climbing number. 0 = off
ScopeTagWhile the target holds this tag, accumulate into one running total
ScopeSummaryStyleStyle key for the summary emitted on scope close
ValueEmphasisScaleCurve: raw value to extra scale multiplier
ValueEmphasisColorCurve: raw value to tint

FCrimsonCombatTextStyleModifier

FieldPurpose
ApplyOrderApplication order when several match, lowest first
ValueStyleTagReplaces the style's value row (guarded by its toggle)
TintMultiplied into the instance tint (guarded by its toggle)
FormatWrapperWraps the resolved text; {0} is the base result
ScaleMultiplierMultiplies the instance's base render scale
DurationMultiplierMultiplies the resolved motion's Duration
MotionPresetOverrideSwaps the motion wholesale
PlacementPresetOverrideRe-routes the pop to a different placement
PlacementOffsetAdded to the style's placement offset. Additive across modifiers

FCrimsonCombatTextMotion

FieldPurpose
DurationLifetime in seconds
RiseDistance / SpreadDistanceAmplitudes in layout units (post-DPI)
RiseCurve / SpreadCurveNormalized alpha to 0..1 progress. Empty = linear
ScaleCurveAlpha to scale multiplier. Empty = constant 1
OpacityCurveAlpha to opacity. Empty = opaque until 80%, then linear to 0
bUseSpreadFan / FanWidth / FanSlotsDeterministic anti-overlap fan
RandomJitterWobble as a fraction of SpreadDistance. 0 = fully deterministic

UCrimsonCombatTextRenderer

Abstract presentation strategy, selected by RendererClass. Subclasses key their view state off FCrimsonCombatTextInstance::Handle, never off array position.

MemberPurpose
InitializeRenderer(World, PC)Returns false if it cannot run; the subsystem then falls back to the widget renderer
OnTextStarted / OnTextUpdated / OnTextFinishedPer-instance lifecycle
RenderTexts(Instances, Frames)Per-frame, all live instances at once. Parallel arrays
SupportsRichText()False on the Niagara path; the subsystem warns once
PreWarm(Count) / GetPooledViewCount()Optional pooling hooks
ImplementationNotes
UCrimsonCombatTextRenderer_WidgetDefault. One pooled UUserWidget per instance; full rich text. ZOrder sets the viewport layer, so pops can draw over or under your HUD
UCrimsonCombatTextRenderer_NiagaraOne batched Niagara system. No rich text. Needs authored content. Screen-space pops are deprojected onto a camera plane at ScreenSpacePlaneDistance, which world geometry can occlude

UCrimsonCombatTextWidget

UUserWidget, Abstract, DisableNativeTick. A passive view - no motion, no timing, no lifetime of its own.

MemberKindPurpose
ApplyCombatText(Text, StyleKey, AnimationName)BlueprintNativeEventCalled when the widget is assigned to a new instance
OnCombatTextApplied(...)BlueprintImplementableEventHook for custom visuals or animations
TextBorder / TextBlockBindWidgetOptionalOptional stock widgets. TextBlock receives the rich text

UCrimsonCombatTextReplicationComponent

Lives on the GameState. The server-side broadcast entry point.

MemberKindPurpose
BroadcastCombatText(Event)BlueprintCallableServer only. Validates authority, resolves location, multicasts
OnCombatTextReceivedBlueprintAssignableFires on each client; the subsystem binds automatically

UCrimsonCombatTextTargetComponent

Optional per-actor anchor override.

MemberPurpose
RelativeOffset / SocketNameWhere text appears. A valid socket wins over the offset
ResolveAnchorLocation(Actor)One-shot world anchor. Used by the server for the event's fallback location and by UCrimsonCombatTextPlacement_WorldActor for its first frame
ResolveAnchor(...) / EvaluateAnchor(...)Re-evaluatable anchor so text can follow a moving or animating target

UCrimsonCombatTextPlacement

Abstract, Blueprintable, EditInlineNew. Decides where one pop sits. Instances are shared by every pop routed to them, so both entry points are const and all per-pop data lives in the state struct.

MemberKindPurpose
PlacementIdFGameplayTagKey styles route to. Restricted to CrimsonCombatText.Placement
ScreenOffsetFVector2DAdded to the resolved anchor every frame, in layout units
FallbackUCrimsonCombatTextPlacement* (Instanced)Tried when this placement declines. Chains walk up to 4 deep
AcquirePlacement(Context, OutState)BlueprintNativeEventSpawn time. Return false to decline the pop
UpdatePlacement(Context, State)BlueprintNativeEventPer frame while bUpdateEveryFrame. Returns the new state
GetPlacementDescription()virtualShort description shown in the dev tools
Built-inNotes
UCrimsonCombatTextPlacement_WorldActorThe default. AnchorActor, SocketOverride, WorldOffset, bFollowTarget, bFallBackToEventLocation, bClampToViewportEdge, ViewportEdgePadding
UCrimsonCombatTextPlacement_ScreenAnchorFixed HUD spot. ViewportAnchor, AnchorOffset
UCrimsonCombatTextPlacement_WidgetAnchored to registered UI. AnchorId, bUseTargetActorContext, WidgetAlignment, AnchorOffset, bHideWhenAnchorLost

FCrimsonCombatTextPlacementContext

What a placement is told. Its actor pointers are raw and rewritten each frame - never store a copy.

FieldPurpose
TargetActor / InstigatorActorWho was hit, and who hit them. Either may be null on a client
EventWorldLocation / bHasEventWorldLocationThe network fallback location carried by the event
ContextTags / StyleKey / ValueWhat the pop was requested with, and which style won
ViewingPlayerThe player this pop is drawn for
ViewportSize / ViewportScaleViewport in layout units, and the DPI scale that produced it
TimeAlive / AlphaAge in seconds, and normalized 0..1 lifetime progress. Both 0 during acquire

FCrimsonCombatTextPlacementState

What a placement returns, and its entire per-pop memory.

FieldPurpose
SpaceWorld or Screen. Screen is exempt from camera-distance culling
WorldAnchorWorld anchor. Meaningless in Screen space
ScreenPositionFinal anchor in layout units. Filled in both spaces
ScreenOffsetConstant offset folded into the motion offset each frame
bOnScreenfalse hides the pop this frame
bUpdateEveryFramefalse freezes this state for the rest of the pop's life
bFollowAnchorKeep re-resolving the world anchor. Distinct from bUpdateEveryFrame: a pinned pop still re-projects because the camera moves
AnchorComponent / AnchorSocket / AnchorOffsetThe world-follow cache, so an animated socket costs no component search per frame
SpreadOwner / SpreadGroupAnti-overlap fan grouping. Pops sharing both deflect away from each other
UserVector / UserScalarScratch for custom placements. Ignored by the plugin

UCrimsonCombatTextPlacementSet

Data asset holding the named placements. An Instanced array rather than a map, because instancing is reliable on array elements and unreliable on map values.

MemberKindPurpose
PlacementsTArray<UCrimsonCombatTextPlacement*> (Instanced)The rows. Each carries its own PlacementId
FindPlacement(Tag)BlueprintCallableNull when the tag is unset or no row carries it
SeedBuiltInPlacements()CallInEditorAdds any missing built-in rows. Never overwrites an id you authored

UCrimsonCombatTextPlacementLibrary

The maths a placement needs, exposed to Blueprint so custom placements are not C++-only.

FunctionPurpose
ProjectWorldToLayout(Context, World, OutLayout)World point to layout units. false behind the camera
ClampToViewportEdge(Context, World, Layout, bProjected, Padding)Pushes an off-screen position to the padded viewport edge, handling anchors behind the camera
ViewportAnchorToLayout(Context, NormalizedAnchor, PixelOffset)Normalized viewport anchor to layout units
GetActorAnchorLocation(Actor)The actor's combat text anchor: target component socket, its offset, else 100 cm above the root

UCrimsonCombatTextAnchorSubsystem

World subsystem making UI widgets addressable by tag. Local and cosmetic - never created on a dedicated server. Holds weak pointers, so a destroyed widget cannot dangle.

MemberKindPurpose
RegisterAnchorWidget(Id, Widget, ContextActor)BlueprintCallableNull ContextActor registers the global anchor for that id
UnregisterAnchorWidget(Id, ContextActor)BlueprintCallableDrops one registration
UnregisterAllAnchorsForWidget(Widget)BlueprintCallableDrops every id a widget registered
FindAnchorWidget(Id, ContextActor)BlueprintPurePer-actor registration wins over the global one
GetAnchorViewportPosition(Id, ContextActor, Alignment, OutPos)BlueprintCallableLayout-unit position. false when unregistered, hidden, destroyed, or never painted

UCrimsonCombatTextAnchorWidget

A USizeBox that registers itself as an anchor for its lifetime. Palette category Crimson.

MemberKindPurpose
AnchorIdFGameplayTagThe id to register under. Deliberately unrestricted - these name your widgets
SetAnchorId(Id)BlueprintCallableRe-registers under a new id
SetAnchorContextActor(Actor)BlueprintCallableMakes this a per-actor anchor, for nameplates

FCrimsonCombatTextEvent

FieldPurpose
ValueThe number to display
TagsSelects style and modifiers; also drives per-player filtering
WorldLocation / bHasWorldLocationServer-resolved position, FVector_NetQuantize (1cm)
Instigator / TargetMay be null on clients where the actor is not net-relevant
PrefixText / CustomTextSubstituted into {Prefix} and {Custom}

UCrimsonCombatTextSettings

Project Settings > Crimson > Crimson Combat Text.

SettingPurpose
RegistryPathThe style registry data asset
WidgetClassPathWidget Blueprint for the widget renderer
RendererClassPresentation strategy. Unset falls back to the widget renderer
NumberFormatCommaSeparated / Abbreviated / Raw
DistanceScaleCurvePathOptional camera-distance to scale multiplier
ServerCullDistance0 = multicast to all; > 0 = per-client RPCs within range
InitialPoolSize / MaxActiveTextsPool pre-warm and concurrent cap (0 = unlimited)
SpreadDecayTimeHow long a burst keeps fanning before resetting to center
DefaultAggregationWindow / MergeRewindAlphaAggregation defaults and merge re-punch point
bVerboseLoggingPer-dispatch logging. Off in shipping

UCrimsonCombatTextFilter

Abstract, Blueprintable, EditInlineNew. One rule in the visibility chain. Instances are shared by every pop that runs through the set and must stay stateless, which is why Matches is const.

MemberPurpose
Matches(Context)BlueprintNativeEvent. Does this rule describe this event? - not a verdict. Override this
FilterIdIdentity, under CrimsonCombatText.Filter. Also the settings storage key and the player-override key
DisplayName / DescriptionLabel fallback and tooltip. A Crimson Tag Labels entry for FilterId wins over DisplayName
bUserConfigurableFalse hides the row from the settings screen and pins it to bEnabledByDefault
bEnabledByDefaultThe state the row starts in
MatchResultVerdict when the row is ON and Matches returns true
DisabledResultVerdict when the row is OFF and Matches returns true
bHasScalarParameterRow exposes one tunable. Read it in Matches from Context.ScalarParameter, never from ScalarDefault
ScalarDisplayName / ScalarRange / ScalarStep / ScalarDefaultSlider label, bounds, step and starting value
GetFilterDisplayName() / GetScalarDisplayName()Resolved labels: Tag Labels, then DisplayName, then the raw tag
GetFilterDescription()One-line summary for the dev tools and the MCP toolset
Built-inMatches when
UCrimsonCombatTextFilter_RelationshipThe actor in Role (Instigator / Target) is in RelationshipMask. bRequireViewerIsNotOtherRole excludes self-inflicted events
UCrimsonCombatTextFilter_TagQueryQuery matches the event's context tags. An empty query matches nothing
UCrimsonCombatTextFilter_DistanceFurther from the viewer than the scalar. bExemptWhenViewerIsTarget spares events aimed at you

UCrimsonCombatTextFilterSet

UDataAsset. The ordered chain, assigned on the registry. An Instanced array with an id on each row rather than a TMap - a map has no order, and UPROPERTY(Instanced) is unreliable on map values.

MemberPurpose
FiltersThe chain, evaluated top to bottom. First non-Ignore verdict wins
DefaultResultVerdict when no row had an opinion. Hide by default
FindFilter(FilterId)Row lookup by tag, through a rebuilt index
GetUserConfigurableFilters()The rows a settings screen should offer, in chain order
SeedDefaultFilters()CallInEditor. Adds the seven built-in rows; never overwrites an id you already authored

FCrimsonCombatTextFilterContext

What a filter is told. Built once per event, before the chain runs, and handed to every row unchanged - so relationship is resolved once no matter how long the chain is.

FieldMeaning
InstigatorActor / TargetActorWeak pointers, normalized to the avatar pawn. Frequently null on clients
InstigatorRelationship / TargetRelationshipSelf / Ally / Enemy / Unknown. A null side goes to the team hook and reads as Ally; Unknown means there was no viewing pawn
bViewerIsInstigator / bViewerIsTargetDirect identity against the viewing pawn
ContextTags / ValueThe pop as requested, before style resolution
EventWorldLocation / bHasEventWorldLocationServer-resolved anchor; survives a null target
ViewingPawn / ViewingPlayerWho the text is being drawn for
ScalarParameterThe tunable for the row being evaluated - the player's override, or its ScalarDefault

UCrimsonCombatTextPlayerSettings

PlayerController component. Per-player filter choices, display overrides and placement re-routing. Local only, never replicated, and the plugin does not persist it.

MemberPurpose
FilterEnabledOverridesFilterId -> on/off. No entry means the row's bEnabledByDefault
FilterScalarOverridesFilterId -> tunable. No entry means the row's ScalarDefault
SetFilterEnabled(FilterId, bEnabled) / ClearFilterEnabledOverride(FilterId)Set or clear the player's choice for one row
IsFilterEnabled(Filter) / GetFilterScalar(Filter)The values actually in effect. A non-configurable row always reports its authored default
ResolveEventActor(Actor)Static. Normalizes an event actor to its avatar pawn - a GAS instigator is the ASC owner (the PlayerState), the target is the pawn. Without this a player's own damage never reads as Self
BuildFilterContext(Event, LocalPawn)Builds the context the chain runs against, resolving both relationships up front
PassesFilter(Event, LocalPawn, FilterSet, OutTrace)Walks the chain. A null FilterSet passes everything
IsActorFriendly(LocalPawn, Other)BlueprintNativeEvent team hook. Asked at most twice per event
IsActorFriendlyDelegateC++ binding for the same hook. Unbound treats every actor as an ally
WidgetScale / NumberFormatOverridePer-player render scale and number format (-1 = project default)
PlacementOverridesStyle key -> placement id, matched hierarchically. Most specific entry wins
ApplyPlacementOverride(Resolved, PlacementSet)Applied after style resolution, before the placement is acquired. A stale id warns and keeps the authored placement