Items / Spoilable Items

What is a spoilable item?

A spoilable item is an item that after a certain amount of time expires, removing its self from the storage component holding it. Spoilable items are an advanced example of using the Dynamic Data system. I'll give you a breakdown of how Spoilables leverage Dynamic Data in the How Spoilable Items Work section below.

Create a Spoilable Item

  1. Open the Items data table and select your item.
  2. Add a new element to the DynamicData map. Set the key as spoil and set the value as the number of seconds you would like the item to take before it spoils.
  3. (Optional) If you would like a new item to spawn when this one spoils add another element to the DynamicData map for your first item and set the key to onspoil and the value to the ItemRowName of the new spawned item.

That is it! your item is now integrated into the spoil system. You will however need to drop any current instances of the items and pickup (not the one you dropped) or add a new copy of it. Remember Dynamic Data lives on the instance, and since we just added spoil to our data, it will only apply to new instances of the items.

Freezer & Rapid Spoiler Examples

The demo content includes a Freezer and Rapid Spoiler container blueprint. These are normal containers with the added benefit of implementing our BPI_SpoilSpeedMultiplier blueprint interface which lets us customize the spoil speed multiplier for any items added to our container. With these specialized containers using this interface, when a spoilable is added to it we either slow down or speed up the spoiling process. This is handled by the onTransfer event for the Spoilable Dynamic Data State Event.

The Freezer & Rapid spoiler inherit from the BP_Interactable_SpoilMultiplierContainer which inherits from the base BP_Interactable_Container. The only difference with the SpeedMultiplier one is that it includes this BPI already intergrated.

Change the Spoil Speed Multiplier

If you are using the included Freezer or Rapid Spoiler you can change the SpoilSpeedMultiplier variable in the blueprint, or if you are using the interface on your own implementation you will return the SpoilSpeedMultiplier float value from the getSpoilSpeedMultiplier implemented function (from the BPI_SpoilSpeedMultiplier). You will want to implement on the same actor that has the storage component(s). If you wanted to control the speed while in the player storage you would implement this blueprint interface on your player controller.

To slow down spoiling you would use a value lower then 1.0. The Freezer's value is 0.1. Compared to our default value of 1 it would take 10x longer for an item to spoil in the freezer compared to our inventory.

To speed up spoiling you would use a value higher then 1.0. The Rapid Spoiler value is set to 10.0. Compared to our default value of 1 it would take 1/10th the amount of time for an item to spoil in the rapid spoiler compared to our inventory.

To change the default spoil speed multiplier of 1.0 open the BPO_DDSE_Spoilables object in the Blueprint/Objects/DynamicDataStateEvents/ folder. The currentSpoilSpeedMultiplier float variable is where you would set the default. Remember though, this value is overriden by a call to the owner with getSpoilSpeedMultiplier.

The spoil speed multiplier is not implemented into the default container, as spoilables is an optional feature that not all developers will need. So items in containers will spoil at the default rate. If you wanted to upgrade all containers to support different spoil speed multiplier values you can add the interface to the BP_Interactable_Container actor since that is the one that has the storage component. If you don't want to upgrade all containers but only the workstation you would implement it in the BP_Interactable_Workstation instead.

How Spoilable Items Work

Spoilables are built on top of the Dynamic Data system. This allows us to keep it completely optional without taking on the overhead to power the system if we don't actually want to use it. It only activates if it detects our trigger in the DynamicData of items added to our storage components. For spoilables that trigger is spoil, which we also use to define how much time it should take to spoil.

Dynamic Data Variables

We set these in the DynamicData field for the Item in the Items data table.

spoil Required the number of seconds (at a default spoil rate of 1.0) it should take to spoil this item.
onspoil (optional) the ItemRowName of the item to spawn when the item with this dynamic data spoils.

Dynamic Data State Events

These are the dynamic data state events as defined in our DT_DynamicDataHelpers. All of them are handled with BPO_DDSE_Spoilable object in the Blueprints/Objects/DynamicDataStateEvents/ folder. This handler is linked to the spoil dynamic data key on our item through the Dynamic Data Helpers data table, DT_DynamicDataHelpers in the Blueprints/Variables/DataTables/DynamicData/ folder.

Visit the dynamic data page to learn more about dynamic data helpers.

onInitialize / onFirstLoad
The functionality that occurs as soon as the spoilable hits a storage component for the first time.

We use this function to initilize our spoilable item, by calculating our first expiration date based on our spoil speed multiplier. We save this expiration date, and our current spoil speed multiplier back to the item's dynamic data. By default these extra variables are hidden on the player UI.

onInitialize / onTransfer
The functionality that occurs when the item moves from one slot to another, this can be in the same component or another.

We use this function to see our spoil speed multiplier has changed, if it has we recalculate our new spoil expiration based on the new multiplier, our starting time, and current percentage of spoil completed. We save this new expiration date, and our new spoil speed back to the item dynamic data.

onPing
The functionality that occurs over a fixed interval, which by default is 5 seconds (you can change the default speed inside AC_InventorySystem look for and change the DynamicDataPingRate variable).

We use this function to check and see if our item spoiled. If it did we remove it and reset the spoil timer for the next item in the stack. If we are using the onspoil dynamic data variable to create a new item in the spoiled items place we also handle adding that at this time.

Customized Spoilable Item UI Widgets

The UIs/Shared/DynamicData/Spoilables/ folder contains two twidgets, UI_Spoilable_Item and UI_Spoilable_Tooltip. These are the widgets that are appended to our UI_Item and UI_Item_Tooltip to show the spoil time remaining. For the UI_Item it is a simple progress bar. For the Tooltip it is a seconds remaining countdown.

These UIs are also added automatically to any item that has the spoil dynamic data key through the Dynamic Data Helpers data table, DT_DynamicDataHelpers in the Blueprints/Variables/DataTables/DynamicData/ folder. Visit the dynamic data page to learn more about dynamic data helpers.

Most Common Spoilable Related Questions

How can I spawn another item when the first item spoils? (Raw meat to spoiled meat example)
How can I expire multiple items at a time (like the old version)?
How do I change the way time is tracked and used?
How come when I split a stack the spoil time carries over to the new item?