How-To: Expose Pop Options as User Settings (Optional)
Goal: put the per-player pop options into your own options menu. The visibility half is generated from the filter chain, not hand-authored - you enumerate the chain once and build one row per entry, so a filter you add later shows up in the menu with no code change and no storage key to invent.
UCrimsonCombatTextPlayerSettings component on your PlayerController, with a UCrimsonCombatTextFilterSet assigned on your registry (How-To: Filter Which Pops a Player Sees), and an options screen of your own to add rows to. This plugin ships no settings UI - it exposes the data a menu reads and the setters a menu calls.UCrimsonCoreCombatTextSettingsComponent, a default component on ACrimsonPlayerController - so a suite project skips to the verify. CrimsonCore is free to download, but compiles only with all Crimson plugins installed; the steps below are the standalone build of the same thing.1. Enumerate the rows
UCrimsonCombatTextSubsystem::GetFilterSet() returns the active chain, and GetUserConfigurableFilters() returns the rows a menu should offer, in chain order. Each row carries everything a widget needs: GetFilterDisplayName() for the label, Description for the tooltip, bEnabledByDefault for the starting state, and - when bHasScalarParameter is true - GetScalarDisplayName(), ScalarRange, ScalarStep and ScalarDefault for a slider.
In your options widget: Get Crimson Combat Text Subsystem (search Crimson Combat Text Subsystem, under World Subsystems) -> Get Filter Set -> Get User Configurable Filters -> For Each Loop. In the loop body, call your own "add a toggle row" function with Get Filter Display Name and Filter Id off the element; then Branch on the element's B Has Scalar Parameter and add a slider row on True, using Scalar Range, Scalar Step and Scalar Default.
One enumeration produces every row, so a filter you add later needs no extra wiring here.
GetFilterSet() returns null if you ask on BeginPlay on a fresh level. Build your rows when the options screen actually opens, and handle null anyway. In C++ you can subscribe to UCrimsonCombatTextSubsystem::OnRegistryLoaded and rebuild the list when it fires; it also fires again after a Project Settings change, because the filter set may have been swapped out from under you.2. Read and write the player's choice
Every choice lives on the local player's UCrimsonCombatTextPlayerSettings component, keyed by the row's FilterId tag. The tag is the identity, so there is no key list to keep in sync and a filter a project wrote itself needs no extra glue.
| Row control | Read | Write |
|---|---|---|
| On / off | IsFilterEnabled(Filter) | SetFilterEnabled(FilterId, bEnabled) |
| Tunable | GetFilterScalar(Filter) | SetFilterScalar(FilterId, Value) |
| Back to the authored default | the row's bEnabledByDefault / ScalarDefault | ClearFilterEnabledOverride(FilterId) |
Labels come from the filter's own DisplayName, falling back to the raw FilterId tag. Bind UCrimsonCombatTextFilter::TagLabelResolver() (C++) to supply project-wide labels keyed by FilterId - so renaming a label never means opening the asset. (CrimsonCore - requires all Crimson plugins) binds it to its tag-label settings automatically. GetFilterDisplayName() already does that resolution for you.
FilterEnabledOverrides and FilterScalarOverrides hold only the rows the player actually changed. A row with no entry uses its own bEnabledByDefault / ScalarDefault, so a player who never opens the menu keeps whatever the designer chose.3. The two display options
Scale and number format are not filters - they are plain BlueprintReadWrite properties on the same component, so your menu writes them directly.
| Property | Range | Drives |
|---|---|---|
WidgetScale | 0.5 - 2.0, default 1.0 | A per-player scale multiplier applied to every pop widget |
NumberFormatOverride | -1 to 2, default -1 | -1 uses the project's NumberFormat; 0 = Comma Separated, 1 = Abbreviated, 2 = Raw |
If you offer number format as a dropdown, author the options in the order Project Default, Comma Separated, Abbreviated, Raw and write SelectedIndex - 1 into NumberFormatOverride - that maps 0 -> -1, 1 -> 0, 2 -> 1, 3 -> 2.
4. Persist the choices yourself
Everything on UCrimsonCombatTextPlayerSettings is local-only and not replicated, and the plugin never saves it. Store the two override maps plus WidgetScale and NumberFormatOverride with whatever your project already uses for saved settings, and write them back onto the component once the local PlayerController exists. All of this happens on the owning client - the server never displays combat text, so it has nothing to restore.
IsActorFriendly team hook - see How-To: Bind Your Team System.See also
- How-To: Filter Which Pops a Player Sees - the chain these rows control.
- How-To: Write Your Own Filter - add a row and it appears here automatically.
- API Reference -
GetUserConfigurableFilters,SetFilterEnabled/SetFilterScalar, and the filter row fields a menu reads.