Skip to content

Custom Item and Recipe Creation

kenx00x edited this page Jun 4, 2021 · 11 revisions

Custom Item Creation

Software Requirements

Creation Tools

  • Unity 2019.4.24 - Game engine that Valheim runs in
  • Visual Studio (installable with Unity) - editor for our plugin code
  • uTinyRipper - tool to rip assets and scripts from the release version of the game

Game Mods (install these into your game as our mod has dependencies on them)

  • ValheimLib - Mod with convenience methods we will use
  • HookGenPatcher - Patcher that adds convenient hooks to execute our mod code at the right times, that ValheimLib relies on

Summary of Steps

To add an item to the game, a mod maker will have to:

  • Create an item asset in Unity
  • Connect the required Valheim game scripts to the asset so that the game can interact with it
  • Build the item into an Asset Bundle for importation into the Visual Studio project where they build the mod
  • Retrieve the asset from the bundle in the mod code
  • And add that item (and relevant recipes to make it) to the game's object database when it launches

Throughout the code, we will reference code snippets from an example project. That project has a clear example of how to add a new, craftable item to the game with custom assets. You can get that project in its entirety here. You can download that repository and open the Lead.sln file in Visual Studio in order to see the way our mod will be structured.

Useful Info About Valheim Items

To add the item into the game, we are going to be relying on convenience methods provided by ValheimLib (a library that our mod will depend on). You will do the actual addition to the game database like so:

ObjectDBHelper.Add(CustomItem item) method. But what is a CustomItem ?

  • CustomItem

    A CustomItem instance holds 3 variables :

    • A GameObject that will hold a reference to the item prefab
    • An ItemDrop that should be an ItemDrop Component attached to the item prefab
    • A bool called FixReferences

    ItemDrop is a class from the game code, they basically hold all the needed information for the game to define an item, its name, its functionalities, the text that will show up when hovering it, and so on.

Valheim uses Unity Version 2019.4.24, so let's download that and install it.

We will want to have two instances of the Unity Editor running, I know that it can be a bit annoying but it's better for how things will be setup, you'll see shortly.

  • One unity project that will be made entirely by uTinyRipper (explained below in the Making our Item Prefab chapter)
  • One unity project that we will be at first entirely empty, that is made like so :

Launch the editor and create a new project. Click on Window -> PackageManager and search for AssetBundleBrowser and install it.

Now let's put the game assemblies into the project so that we reference the game code on our item prefab. The assemblies are located in the Valheim\valheim_Data\Managed folder.

Game Assemblies

Copy them and put them in a fresh folder in your project called Assemblies

Assemblies Folder

Making our Item Prefab

Now we want to make a prefab that is setup similarly as the item prefabs that IronGate did, for that, whats best than looking directly at one of them.

If you havent already used uTinyRipper on the game folder to get the prefabs showing up in the ripped game unity project, please do so.

A tutorial is available here (You only need to follow it up to the ILSpy part which is optional for what we do here)

Let's open the SpearChitin prefab as an example. Should get something like this after opening it

Assemblies Folder

As you can see, the root GameObject has multiple components.

  • A rigidbody, for collision handling
  • ZNetView for making the prefab network compatible
  • ZSyncTransform, same as above
  • ItemDrop

The last one holds the most interesting stuff, whats above Shared is non-important and is used for an actual item once its spawned, the meta-data we want to edit is stored under SharedData, so let's focus on that.

Since there is a stupid amount of fields, let's go over the one that I edited for my custom item Lead

I chose this prefab as a base because almost everything is copied from it, except that I remove the model because its not a spear and remove a child on the projectile prefab that we'll see soon.

The name, as you can see its a token that is prefixed with $ . This is very important for the token lookup and their localization system so you'll also want one at the beginning.

In my case I changed it to $custom_item_lead

Icons : Its an array that is the same size as the number of variant you'll want for you item, if there is only 1 variant, have a single entry in there and drag and drop your 2D Sprite at the Element 0 field.

Description Token, same thing for the name, mine is $custom_item_lead_description

Damages my item was dealing no damage and had no scaling per level so everything was set to 0.

Attack Status Effect, Status Effect can be used for items, the chitin spear has the Harpooned Status Effect for, well, harpooning stuff.

Bringing Over Item

Bring the item prefab you've created in the ripped project over into the new project, with ALL linked assets (mesh, texture, sound, material, etc). This will be the project from which we make the Asset Bundle to package with our plugin. When you bring it over, if your script references break, re-apply them and ensure your fields are populated with the desired data.

Before we actually create our bundle, though, you might be wondering - how am I gonna reference game assets in my Unity Project? If I were to copy paste those, I'd need to fix shaders, and now I'd also have to be worried about copyright infringement, bad.

The solution is easy though, thanks to ValheimLib that introduces a mock system.

Mock System

The mock system allows us to reference a placeholder version of an asset from the vanilla game, using a modified version of the name. That way, we don't package any game assets into our own plugins. Instead, the mock system will replace the placeholder with the version from the game at runtime.

We'll start by creating a folder that will hold all our mocks, let's call it Mock, we now want to drag and drop the existing asset from the ripped game project to our custom item project. Let's do that for the Harpooned Status Effect, you should end up with the Harpooned ScriptableObject asset like this :

Copied Asset

Now we want to fix the script references like so

Fix the Script Ref

Be sure to fix the script references for all items that you've brought into the new project including ItemDrop, etc.

We also want to prefix the asset name with VLmock_ so we now we end up with an asset called VLmock_Harpooned

One last thing, we need to tell ValheimLib to fix the references for us, for that, when creating the instance of our CustomItem in code, we want to have the FixReference parameter set to true, like so :

CustomItem = new CustomItem(AssetHelper.LeadPrefab, fixReference : true);

Good, we now have our mock and we can use it for reference in our ItemDrop component ! That was easy.

Attack Projectile, the SharedData can also reference an attack projectile, and we happen to want one here, but this time we want it a bit modified, I only want the trail, without the fangspear in its GameObject hierarchy, we could hack it up directly from the Unity Project, but I found it easier to do from code, so let's do that here :

The relevant piece of code

We use the OnAfterInit provided by ValheimLib, that event is fired once after the ObjectDB is properly init the first time. That's perfect for us ! We want to do this just once : clone the prefab, so that we don't modify the original, remove the GameObject in the hierarchy that we don't want, and then we do the m_attackProjectile assignment.

AssetBundle

Now we want to make our AssetBundle so that we later inject it with our BepinEx plugin dll

Let's create an Asset Label for the AssetBundle that we'll call item_lead

AssetBundle Label

Now, let's use the AssetBundle Browser made by Unity to create our AssetBundle.

Window -> AssetBundle Browser -> Build Tab -> Build

Click Build

We now want to put our AssetBundle in the BepinEx plugin so that we can later inject it.

Freshly made AB

C# BepinEx Plugin Code

Now we will move on to actually creating our plugin code. Our goal will be to create the new C# class library project, bundle our new asset with it, and create a DLL file that we can drop into our BepInEx/plugins folder to see it in-game. The first step will be creating a new solution in Visual Studio and ensuring it has libraries from the game, as well as other mods our mod depends on (ValheimLib and MonoMod hooks). The easiest way to get started is to grab this Lead project which already includes all of the required DLL's as references in the project. Otherwise, you can make a new project of type C# class library and manually add dependencies. This guide includes detailed information on getting started. You will also need to establish basic entry points for BepInEx code to begin executing, which is outside

Once you have your Visual Studio project open, be sure you have DLL references for ValheimLib and MonoMod (ValheimLib.dll and MMHOOK_*.dll) similar to the example repository as well as all of the UnityEngine modules that Valheim relies on. If you need any of these DLL's:

  • Grab them from the repository
  • In Visual Studio, right-click your Project in the Solution Explorer window
  • Click Add Reference
  • Browse to where you downloaded the DLL
  • Add it to the project and hit OK

Now that we have a plugin project, we can actually bring in the Asset Bundle we created.

Importing the assetbundle into the Visual Studio Project :

  • Right click the project name in the solution explorer
  • Add
  • Existing item
  • Add the assetbundle
  • Properties of assetbundle
  • Select Embedded resource

Now get a reference to the AssetBundle Stream using GetManifestResourceStream in your code

Example shown here

Paths of your Assets

The Asset Bundle Browser in the Unity Editor can print the exact paths of your assets that are inside your asset bundle if you are struggling figuring it manually for loading them in code.

Language Tokens

We need to tell ValheimLib that we want new language tokens for localization, we can do like so :

Example shown here

Custom Recipes

Those ones are done from code since they are very straightforward

Example shown here

One thing to note for adding crafting / repair station requirement :

recipe.m_craftingStation = Mock<CraftingStation>.Create("piece_workbench");

// And making sure that fixReference is set to true so that ValheimLib fix the mock for the workbench !
CustomRecipe = new CustomRecipe(recipe, fixReference : true, true);
Clone this wiki locally