What is a Workstation?
A workstation is an intractable actor the player can use to craft recipes.
Workstations have their own storage component, and optionally support equipping tools and consuming fuels while crafting. When the player wants to craft with a workstation they interact with it to open the UI, then from there they add the ingredients to the station, and start crafting the recipe, which adds it to its crafting queue. When added to the queue the ingredients are consumed, and when crafting finishes for that queue item, the new item it produces is added back into the workstation storage. The player can then withdraw the item to their inventory.
Workstation Technical Overview
A workstation is an interactable blueprint actor, inherited from BP_Interactable_Workstation an abstract class in the Blueprints/Interactables/ folder. This blueprint actor inherits from and extends the functionality of our container blueprint.
In addition to all the normal functionality of a container, the workstation also implements the crafting component, AC_Inventory_Crafting. This is where we define the context of the workstation and is also what handles the actual crafting. In addition to the component we also attach the workstation component, AC_Inventory_Workstation, which is responsible for maintaining the on/off state of the workstation, as well as tracking the fuel, and tools.
Finally the blueprint actor also implements the BPI_Crafting and BPI_Crafting_Workstation blueprint interfaces. Which is how the AC_Inventory_Crafting and AC_Inventory_Workstation components relay information to and from the Actor.
The Actor is where everything related to the visual experience is handled. This includes showing our equipped tools (and any supporting meshes), as well as playing our VFX and/or SFX when the workstation is on.
This combination of components, interfaces and systems work together to provide the full workstation experience.
How it all flows together ...
- The player interacts with the Actor, and the Actor spawns the UI for the workstation and adds it to the the player’s viewport (through the HUD).
- The player uses the UI to select and starts crafting recipes.
- The crafting component handles receiving the requests to start crafting from the UI and in turn talks with the workstation actor to see if it is available for crafting.
- The workstation actor takes this opportunity to communicate with the workstation component to make sure it has fuel (if it uses it), and any tool requirements for the recipe.
- If all checks out, the workstation actor responds to the crafting component and lets it know it is good to go.
- The crafting component then takes the ingredient items from the storage component and adds the recipe to the crafting queue.
- When the crafting component starts working through the queue it reaches back out to the workstation to let it know it has started. At this point the workstation turns its self on and starts consuming fuel.
- When crafting finishes the crafting component adds it to the storage component and lets the actor know, if nothing else is in the queue the workstation shuts off.
There is a bit more going on in-between the lines, but this is the general flow of how the components, interfaces, and actors connect together.
Just remember, the Workstation component is there to manage on/off state, fuel and tools, and the Crafting component is for starting recipes. The actor is what leverages both components, and uses the BPI to bridge the data together. The two components are actually decoupled from each other, meaning they don’t actually know or interact with each other. This makes the workstation system completely optional to use without any heavy overhead.
Linking Recipes to a Workstation
We assign recipes to the workstation using the recipe’s Contexts array variable. A context lets us define where the recipe can be crafted from. Open up the DT_Recipes data table in the Blueprints/Variables/DataTables/ folder and select the recipe you want to assign to the workstation. Then under the Contexts array add and then select the data asset associated with your workstation.
If you have not made your context yet you can do so by right clicking in the content browser, selecting Miscellaneous and then selecting Data Asset. Select the DA_CraftingContext as your primary data asset. Then open the data asset you created and set the label for your context. This label is shown when multiple contexts are used on a single crafting component as a header for the group of recipes associated with this context.
You can have multiple contexts on your workstation, for example maybe you have a simple smithy table, and then a more advanced smithy table. The advanced smithy table can have its own context which is used to associate with just the new recipes, and it can also use the original context associated with the normal smithy table, to inherit all of its recipes as well.
Customizing the Workstation Crafting Window
The UI_Workstation_Crafting widget is what is shown in a window when the workstation crafting UI is toggled (via interacting with a class inherited from BP_Interactable_Workstation).
For workstations you can customize the Window Title Text, Icon, Open and Close Sounds using the WindowTitle, WindowIcon, WindowOpenSound and , WindowCloseSound variables found in the Workstation Blueprint. If you don’t see them in the My Blueprint panel you will need to enable inherited variables (click the gear icon then enable Show Inherited Variables).
View the Sounds chapter to learn how to customize the sounds that play when you craft something.
Fuel Slots
Fuel slots, like tool slots, are built using specialty slots. We define what fuel slots are connected to our workstation on the AC_Inventory_Workstation component using the WorkstationFuelSlots array variable. This array contains the Row Names of our fuel specialty slots.
The workstation is looking for fuel.duration on items in the fuel slots. The value is the number of seconds worth of fuel the item produces. The AC_Inventory_Workstation component is what converts and tracks our fuel. The specialty slot for our fuel example is also checking for this fuel.duration key.
If you want to assign different types of fuels for different workstations you would set up unique specialty slots for each one to use on each of your workstations. All items would still have the fuel.duration dynamic data key, but they should also use an additional item of criteria in your specialty slot definition, perhaps a gameplay tag, or another dynamic data key. With this extra piece of criteria you can limit the items to the specific workstations.
Tool Slots
Tools are built using specialty slots. We define what tool slots are connected to our workstation on the AC_Inventory_Workstation component using the WorkstationToolSlots array variable. This array contains the Row Names of our tool specialty slots.
Crafting Speed and Yield multipliers on tools is defined through the Dynamic Data of the items.
crafting.speed for the crafting speed reduction. A value of 0.5 is a 50% reduction in time to craft.crafting.yield applies to the quantity multiplier applied to the item produced. A value of 1 equals +100% yield.If you want to require a tool in a recipe you would set the WorkstationToolRequirements in the Requirements structure of the DT_Recipes for the recipe. They key you enter should match a key found in your item’s DynamicData, and the value is the minimum value the item should have for that matching key.
See the cooking_pot, cooking_grill and cooking_pot_exceptional items in the demo world for some examples of tools used on the campfire.
Toggling Tool Meshes
To toggling showing mesh on our workstation we need to link our tool dynamic data key to our static mesh component. In our campfire example we do this using the RegisterToolMesh function inside of our onRegisterToolMeshes override. This override is designed to tell your workstation when it is time to register its tool meshes. You respond by using the registerToolMesh function calls. For each call to registerToolMesh you will provide the static mesh component, and the tool data identifier. You also have the option to useItemMesh? which will override the mesh shown on the static mesh component with the mesh set for the actual item in the items data table.
This is how in our campfire example the cooking pot turns gold when we equip the exceptional version. The exceptional cooking pot, although the same mesh as the cooking pot (and the default on our campfire), also has a StaticMeshMaterialOverride, this is where the gold coloring comes in.
Toggling Supportive Tool Meshes
You will want to override the onToolExtras function in the workstation blueprint actor. It is when this is called that the data is fully replicated and can be analyzed for performing additional functionality related to the available tools.
In our campfire example we use this function to analyze the equipped tools, and toggle showing additional static mesh components used as the stand for the grill, and the holder for the pot. These mesh components already exist on the workstation, the visibility of the mesh is controlled by what we do in this onToolExtras function.
Toggling VFX & SFX
You will want to override the onTurnOn and onTurnOff functions in the workstation blueprint actor and use these to toggle your VFX and SFX. With the included examples we manually added Audio and Niagara components on our actor with our media. We use these override functions to toggle turning those on and off.
Workstation BP Function Overrides
Awarding the player experience from crafting
Implement the BPI_Crafting_Awards blueprint interface into your player controller, and when crafting occurs (success or fail) in both player crafting and workstation crafting this craftedRecipe function will be called. It will provide the following details:
In multiplayer, the workstation is designed to track what player starts the craft. When the workstation's crafting component sends this craftedRecipe to the workstation actor it uses this playerID, to then relay that data, through the same craftedRecipe call, to the player controller associated with that player id.
Campfire Example
You can find the BP_Interactable_Workstation_Campfire in the Demo/Interactables/Workstations/Campfire/ folder.
How the Campfire Works
Open the campfire and take a look at the Viewport. You should see the campfire in all its glory, with all possible tools shown. Now if you take a look at the Components tab you will see a number of new meshes as well as Audio and Niagara components.
The StaticMesh is the base mesh, and is the only one that is inherited from the base workstation. We use this static mesh component to set our campfire mesh (the logs & stones).
The smPot and smGrill static mesh components are for the tool meshes which are only shown when we have a cooking pot and/or grill equipped. We register these mesh components with the associated tool using the registerToolMesh functions which we call from the onRegisterToolMeshes overridden function. With registerToolMesh we have the option to use the actual Items mesh instead, which we have enabled for both the cooking grill and cooking pot. If we didn’t have this enabled it would fall back and use whatever we have set as our defaults for the components.
smGrillExtras and smPotExtras are supporting meshes that are only shown when the related tool mesh is shown. These mesh components are toggled through the onToolExtras function override.
The Audio and Niagara components both have their media selected and set on the actual component, and the playing of these is handled through our onTurnOn and onTurnOff overrides. The workstation component calls the on function when crafting is in progress, and when it is done will call the off function.
The title and icon that appear in the window when the UI is shown is set through the WorkstationWindowTitle and WorkstationWindowIcon variables inherited from the base workstation class.
What recipes we can access from the campfire is set on the AC_Inventory_Crafting components ContextTypes array. We added the DA_CC_Campfire data asset to this array. This is the same data asset associated with the Contexts array for certain recipes in our DT_Recipes data table. These recipes are the ones that will show here. The data asset is the link between the crafting component and the recipes it loads.
We also define the tools and fuel we use for this workstation on the AC_Inventory_Workstation component through the WorkstationToolSlots and WorkstationFuelSlots, which are arrays of specialty slot row names (where you would define the actual criteria for what tools and fuel can be equipped in the slot).
We use Wood Logs for fuel in our campfire, and these can be equipped to our fuel specialty slot because it is looking for dynamic data key of fuel.duration with a positive value. Our wood logs have a fuel.duration of 30, which means each log will last for 30 seconds. This linking of fuel.duration to the fuel slot is handled using the specialty slots system.
To unlock the Meat Feast recipe in the Demo World press the Blue button on the wall next to the table that had all the campfire ingredients on it.
Campfire Credits
The meshes for the Wood Log, Cooking Pot, and Cooking Grill as well as the Fire VFX used in the campfire workstation example were provided courtesy of beaudiangelo (on discord) of CYGY Studios. These meshes and the VFX are from a medieval camp asset pack they are offering on Fab, the pack is loaded with a bunch more. Here is a link to check it out: Medieval Survival Camp
Thank you Beau for granting permission to include and distribute these meshes and the VFX!Beau was also commissioned to create the butterflies, player on fire, and healing leaf VFXs shown with the usable items in the demo world.
Create a Workstation
- Navigate to the Blueprints/Interactables/ folder and right click on the BP_Interactable_Workstation blueprint, then select Create Child Blueprint Class. Name your new blueprint.
- Next open up your new blueprint and navigate to the Viewport. Set the static mesh for your workstation to the StaticMesh component that was inherited from the base workstation blueprint.
-
Next select the AC_Inventory_Crafting component that is already on the blueprint and navigate to the Configuration section, add your workstations context to the ContextTypes array. If you need to create a context type:
- Right click in your content browser and select Miscellaneous then Data Asset.
- Select the DA_CC_CraftingContext primary data asset and name your context.
- Open the asset up and set your Context Label.
- You should also add a recipe if you haven’t yet, and set the Contexts for the recipe to include your new crafting context.
That is the bare minimum to get a workstation up and running. If you drop a copy of your blueprint in your world now you should be able to run up to it and interact with it. The fun doesn’t stop there. Follow the sections below that apply to your workstation.
Adding a Tool Slot to the Workstation
- Create your specialty slot for your tool slot.
- Assign your specialty slot by adding it to the WorkstationToolSlots array on the AC_Inventory_Workstation attached to the workstation.
At this point you should confirm that your workstation shows your specialty slot’s icon, and that your criteria is working properly for your tool item.
Showing a Tool Mesh on the Workstation when one is Equipped
- Add a static mesh component to your workstation blueprint. Set your tool mesh as the default and then position it using the Viewport.
- Override the onRegisterToolMeshes function if you haven’t already, and then open it.
- Call the RegisterToolMesh function and attach your tool’s static mesh component to the Static Mesh Component input pin. Set the Tool Data Identifier to a dynamic data key that also exists on your tool item. If you want to use the mesh saved for the item make sure to enable the useItemMesh? Boolean. If you leave this as false it will use whatever mesh you set as the default on the static mesh component.
Take a look at how this function is handled in the campfire blueprint if you need an example.You can find it in the Demo/Interactables/Workstations/Campfire/ folder.
Showing Extra Supportive Meshes when a tool is Equipped
- Add your extra static mesh component and set your mesh.
- Override the onToolExtra function if you haven’t already, and then open it.
At this point it is safe to analyze the AC_Inventory_Workstation components ToolData variable. Check to see if your tool identifier exists. If it does then toggle showing your mesh. If it doesn’t hide the mesh.
Take a look at how this function is handled in the campfire blueprint if you need an example. You can find it in the Demo/Interactables/Workstations/Campfire/ folder.
Adding a Fuel Slot to the Workstation
- Create your specialty slot for your fuel slot.
- Assign your fuel slot by adding it to the WorkstationFuelSlots array on the AC_Inventory_Workstation component attached to the workstation.
The fuel system will look for the fuel.duration dynamic data key on your item. The value is the number of seconds worth of fuel the item provides. Make sure your fuel item has this dynamic data key set.
At this point you should confirm that your workstation shows your specialty slot’s icon, and that your criteria is working properly for your fuel item.
Adding VFX to the Workstation
- Add a Niagara component to your workstation and set your Niagara System Asset to the Niagara VFX you want to use. Also disable Auto Activate on the component.
- Position your Niagara component using the Viewport.
- Next we want to play our Niagara when our workstation is turned on. To do this we override the onTurnOn function and inside we get a reference to our niagara component and call Deactivate, and then Activate with Reset checked.
- We also want to stop our Niagara when our workstation is turned off. To do this we override the onTurnOff function and inside we get a reference to our Niagara component and call Deactivate.
When you start crafting your VFX should appear, and when crafting finishes it should stop.
Adding SFX to the Workstation
- Add an Audio component to your workstation blueprint and set your Sound, Attenuation Settings, Component Replicates enabled, and Auto Activate disabled.
- Next we want to play our sound when we turn the workstation on. To do this we override the onTurnOn function and inside we drag in a reference to our Audio component and call the fadeIn function, setting a short duration (the campfire uses 3 seconds).
- Next we want to stop our sound when the workstation turns off. To do this we override the onTurnOff function and inside we drag in a reference to our Audio component and call the fadeOut function, you can also call a stopDelayed with the same duration you set to the fadeOut for safe measure.
When you start crafting you should hear your SFX, and when crafting finishes it should stop.
Using a Workstation Tool as a Recipe Requirement
To set a recipe to require a workstation tool you would do this inside the DT_Recipes data tables. Expand the Requirements structure and then add a row to the WorkstationToolRequirements string map. The key should be the unique dynamic data key that you also added to your tool item. The value should be a numeric indicating the minimum level of the tool.
For example, the campfire uses cooking.pot and cooking.grill. Both of those Items also have the dynamic data keys with a value for the level of the tool, where higher level is better.
Take a look at the meat_feast recipe to see an example that requires multiple tools (both our cooking.pot and cooking.grill). It also requires a cooking pot of at least level 3. Now take a look at the cooking_pot and cooking_pot_exceptional. Notice how the normal one is level 1 and the exceptional is 3 for the value in the dynamic data key? The exceptional cooking pot is level 3, thus will work for our recipe, but the normal one is just level 1 which is too low, and thus will not work.