Economy: Store, Purchases & DLC
UCrimsonOnlineStoreService
Wraps IOnlineStoreV2. Browses the platform storefront catalog; it never purchases anything - hand the chosen OfferId to UCrimsonOnlinePurchaseService::Checkout.
| Member | Description |
|---|---|
| QueryCategories(LocalUserNum = 0) | Fetches the store category list. Completes on OnStoreCategoriesQueried, then read GetCachedCategories |
| QueryOffers(OfferIds, LocalUserNum = 0) | Fetches specific offers by platform offer ID. Completes on OnStoreOffersQueried |
| QueryOffersByKeyword(Keyword, LocalUserNum = 0) | Searches the catalog for offers matching a keyword. Completes on OnStoreOffersQueried |
| GetCachedCategories() | BlueprintPure. Returns the TArray<FCrimsonStoreCategory> from the last successful QueryCategories |
| GetCachedOffers() | BlueprintPure. Returns the TArray<FCrimsonStoreOffer> from the last successful offer query |
| OnStoreCategoriesQueried | Delegate: bool bSuccess |
| OnStoreOffersQueried | Delegate: bool bSuccess, const TArray<FCrimsonStoreOffer>& Offers |
FCrimsonStoreOffer reports RegularPriceCents and FinalPriceCents as int64 in the smallest currency unit, plus an ISO 4217 CurrencyCode. Format them yourself for display - there is no pre-formatted price string and no is-on-sale flag; compare the two values to detect a discount.UCrimsonOnlinePurchaseService
Wraps IOnlinePurchase. Opens the platform purchase flow and reads back receipts.
| Member | Description |
|---|---|
| Checkout(OfferIds, LocalUserNum = 0) | Opens the platform purchase dialog for one or more offer IDs. Completes on OnCheckoutComplete |
| QueryReceipts(LocalUserNum = 0, bRestoreReceipts = false) | Fetches purchase history; pass true to restore completed transactions on mobile/console. Completes on OnQueryReceiptsComplete |
| GetCachedReceipts() | BlueprintPure. Returns TArray<FCrimsonPurchaseReceipt> from the last successful QueryReceipts |
| OnCheckoutComplete | Delegate: bool bSuccess, const FCrimsonPurchaseReceipt& Receipt. Success means TransactionState == Purchased |
| OnQueryReceiptsComplete | Delegate: bool bSuccess |
| OnUnexpectedReceipt | Delegate with no parameters. The platform delivered a receipt outside a Checkout call - call QueryReceipts from the handler |
OnCheckoutComplete reports Purchased, and re-sync with QueryReceipts whenever OnUnexpectedReceipt fires - that is how a purchase made on another device, or a reversed refund, reaches this session.UCrimsonOnlineEntitlementService
Wraps IOnlineEntitlements. Queries what the player owns and answers DLC ownership questions using your own internal FName IDs.
| Member | Description |
|---|---|
| QueryEntitlements(LocalUserNum = 0) | Fetches the entitlement list from the platform and fills the cache. Completes on OnEntitlementsQueried |
| IsDLCOwned(InternalDLCId, LocalUserNum = 0) | BlueprintPure. Resolves the platform ID from the mapping table and returns true if it is owned and unconsumed. Returns false, with a warning, before QueryEntitlements has completed |
| CheckDLCOwnership(InternalDLCId, LocalUserNum = 0) | Runs the same check and reports it through OnDLCOwnershipChecked instead of returning it |
| GetCachedEntitlements() | BlueprintPure. Returns TArray<FCrimsonEntitlementInfo> from the last successful query |
| OnEntitlementsQueried | Delegate: bool bSuccess, const TArray<FCrimsonEntitlementInfo>& Entitlements |
| OnDLCOwnershipChecked | Delegate: FName InternalDLCId, bool bOwned |
IsDLCOwned reads a cache. Until QueryEntitlements has completed successfully it returns false and logs "IsDLCOwned called before QueryEntitlements has completed" - which is indistinguishable from genuinely not owning the DLC if you are not watching the log. Query once at boot, after login.UCrimsonAsyncAction_QueryEntitlements). Input pin: Local User Num (int32, default 0). Output pins On Success and On Failure, each carrying bSuccess and an Entitlements array. On the Null subsystem On Failure fires with an empty array - that is expected, not an integration error.DLC Mapping Table
Every platform names the same DLC differently, so the plugin resolves the name for you. Your code asks about one internal FName; the service reads the field matching the detected ECrimsonOnlinePlatform out of a DataTable row.
Setup steps
1. Create a DataTable asset using FCrimsonDLCMappingRow as the row struct.
2. Add one row per DLC. Name the row exactly as the internal ID you will pass in code - the lookup is FindRow(InternalDLCId) on the row name - and set the InternalId field to the same value so it reads clearly in the editor.
3. Fill the PlatformIds sub-struct with whichever platform fields apply: SteamDLCAppId, EOSOfferId, PSNProductId, XboxProductId, SwitchNsuid. Leave the rest empty.
4. Assign the DataTable to DLCMappingTable in Project Settings -> Crimson -> Crimson Online Subsystem. The property filters the asset picker to tables using this row struct.
5. Call QueryEntitlements(0) once after login, then IsDLCOwned(FName("DLC_BonusCampaign")) for the rest of the session.
FCrimsonDLCMappingRow
| Field | Type | Description |
|---|---|---|
| InternalId | FName | Mirrors the DataTable row name - the ID your game code passes |
| PlatformIds | FCrimsonDLCPlatformIds | Nested struct holding one ID per platform (see below) |
FCrimsonDLCPlatformIds
| Field | Type | Description |
|---|---|---|
| SteamDLCAppId | FString | Steam DLC App ID, from the Steamworks partner portal |
| EOSOfferId | FString | Epic Online Services catalog offer ID, from the EOS Developer Portal |
| PSNProductId | FString | PlayStation Network service entitlement or product ID |
| XboxProductId | FString | Xbox / Microsoft Store product ID |
| SwitchNsuid | FString | Nintendo eShop NSUID |
ResolvePlatformId returns an empty string and IsDLCOwned answers false with a warning in the log. Set DebugPlatformOverride while testing so PIE resolves against the field you actually filled in.