Constraints
UCrimsonInventoryConstraint is the rule object. The manager component owns a replicated ActiveConstraints array of instanced constraints - add and remove at runtime as the player equips bags, switches loadouts, enters restricted zones, etc. Constraints can also be attached per-item via UCrimsonInventoryItemFragment_Constraint.
Virtual surface
UCLASS(Abstract, Blueprintable, EditInlineNew, DefaultToInstanced)class UCrimsonInventoryConstraint : public UObject{/** Tag for runtime lookup via GetConstraintsByTag(). */UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)FGameplayTag ConstraintTag;UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)FText DisplayName;/** Early veto: can this rule accept the item in principle? */UFUNCTION(BlueprintNativeEvent)FCrimsonConstraintCheckResult CanAcceptItem(const FCrimsonPlacementContext& Context,const FCrimsonPlacementQuery& Query) const;/** Position-specific veto: can this rule accept the item at this exact target? */UFUNCTION(BlueprintNativeEvent)FCrimsonConstraintCheckResult CanAcceptAt(const FCrimsonPlacementContext& Context,const FCrimsonPlacementQuery& Query,const FCrimsonPlacementTarget& Target) const;/** Maximum quantity that could be added before this rule would veto. */UFUNCTION(BlueprintNativeEvent)int32 CalculateMaxAllowedQuantity(const FCrimsonPlacementContext& Context,const FCrimsonPlacementQuery& Query) const;/** Server-side notification after an item was added; update internal counters here. */UFUNCTION(BlueprintNativeEvent)void OnItemAdded(UCrimsonInventoryManagerComponent* Component,const UCrimsonInventoryItemDefinition* ItemDef,int32 Quantity, bool bIsNewInstance);UFUNCTION(BlueprintNativeEvent)void OnItemRemoved(UCrimsonInventoryManagerComponent* Component,const UCrimsonInventoryItemDefinition* ItemDef,int32 Quantity, bool bWasInstanceRemoved);/** Per-constraint save state (key-value records); mirrors UCrimsonInventoryStateFragment. */UFUNCTION(BlueprintNativeEvent)TArray<FCrimsonInventoryStateData> SaveState() const;UFUNCTION(BlueprintNativeEvent)void LoadState(const TArray<FCrimsonInventoryStateData>& SavedData);};USTRUCT(BlueprintType)struct FCrimsonConstraintCheckResult{bool bPassed = true;FText FailureReason;int32 MaxAllowedQuantity = INT32_MAX;};
Built-in constraints
| Class | Description |
|---|---|
UCrimsonInventoryConstraint_Slot | Slot-count cap. Reads/updates the tag stack named by MaxSlotsTag (set it to your slots tag; the _FlatSlot layout defaults it to Crimson.Inventory.Constraint.Slots). Stacking-aware: merging into an existing stack does not consume a new slot. |
UCrimsonInventoryConstraint_IntTag | Tag-keyed integer cap. Each added item contributes ValueContributedPerItem to TrackedTag, checked against TrackedTag.Max. Useful for limited-quantity items (max 3 banners, etc.). |
UCrimsonInventoryConstraint_FloatTag | Tag-keyed float cap (weight). When bReadFromFootprintFragment is true (default), reads the per-item contribution from UCrimsonInventoryItemFragment_Footprint::Weight. |
UCrimsonInventoryConstraint_TypeFilter | Item must match RequiredTags (any) and must not match BlockedTags (any). Implements 'weapons only' pockets, 'no quest items' bags, etc. |
UCrimsonInventoryConstraint_GridCellRule | Per-cell-region allow/block tags for grid layouts. Gem sockets, 'potions only' belt cells, alchemy slots. |
UCrimsonInventoryConstraint_StackLimit | Aggregates total quantity across the inventory for items matching ItemTagFilter; caps at MaxTotalQuantity. 'Max 5 healing potions of any kind'. |
UCrimsonInventoryConstraint_CustomRule | Blueprint-extension base. Game projects subclass and override the virtuals to express any custom rule without C++. |
Runtime management API
// Add a constraint at runtime (e.g. when a bag is equipped)UCrimsonInventoryConstraint_TypeFilter* AlchemyOnly =NewObject<UCrimsonInventoryConstraint_TypeFilter>(InventoryComponent);AlchemyOnly->RequiredTags.AddTag(TAG_Item_Type_Herb);InventoryComponent->AddConstraint(AlchemyOnly);// Remove it later (bag unequipped)InventoryComponent->RemoveConstraint(AlchemyOnly);// Tag-keyed lookupTArray<UCrimsonInventoryConstraint*> WeightRules =InventoryComponent->GetConstraintsByTag(TAG_Inventory_RuleClass_Weight);// Read all active rules (e.g. for debug UI)TArray<UCrimsonInventoryConstraint*> Rules = InventoryComponent->GetActiveConstraints();
Simple numeric caps via tag stacks
For simple int/float caps you can skip the constraint object and just mutate the tag-stack containers directly. The slot constraint and float-tag constraint both read these stacks.
// Read current/maxint32 UsedSlots = InventoryComponent->GetCurrentIntConstraintValue(TAG_Crimson_Inventory_Constraint_Slots);int32 MaxSlots = InventoryComponent->GetMaxIntConstraintValue(TAG_Crimson_Inventory_Constraint_Slots);float UsedWeight = InventoryComponent->GetCurrentFloatConstraintValue(TAG_Crimson_Inventory_Constraint_Weight);float MaxWeight = InventoryComponent->GetMaxFloatConstraintValue(TAG_Crimson_Inventory_Constraint_Weight);// Bag Extension: bump the caps at runtime - both replicate automaticallyInventoryComponent->ModifyIntConstraintValue(TAG_Crimson_Inventory_Constraint_Slots, +10);InventoryComponent->ModifyFloatConstraintValue(TAG_Crimson_Inventory_Constraint_Weight, +50.f);
Partial add
Call
CalculateAddableQuantity(ItemDef, Requested, OutReason) to know how many will actually fit. The async pickup nodes use this internally to split pickups into full/partial/failed.