Item Modding Tutorial

This Tutorial will show you how to create your very own custom pickup that you can find throughout your run. There will also be information on what kind of events are possible to subscribe to and what the modding tools are capable of. *Note: This page is still under construction, so a lot of information may not be complete or may not be accurate because the modding tools are still changing a lot.*

**If you are new to modding, please first check out the Getting Started with modding Tutorial to set up everything correctly:** Getting started with modding ADVR

## Mod Folder Structure

The Structure of a mod folder is really straightforward, as they mimic the same structure as the base game has. *(Check StreamingAssets/gamedata for more information on how the structure looks like)*. With this knowledge in mind, the structure should be straightforward:

* Custom Items are put in *mods/my\_mod\_folder/items*
* Custom Potions are put in *mods/my\_mod\_folder/potions*
* And so on

You have to adhere to this folder structure, otherwise your mod files can't be loaded correctly and the game may not even start because it loads the files wrongly.

## Creating your first item

In order to create your first item, go into your mod folder that you previously created and create a new folder called *items* where we will put all our custom item files inside. Now, go into *items* and create a new folder where we will put our item inside.

*Item naming conventions should be used for your items. YOURNAME\_ITEMNAME --> in my case this would be erthu\_test\_item*

Now that we have our item folder, we go inside it and create a new .lua file that's called exactly like the folder. In my case this would be *erthu\_test\_item.lua*. Once you have created this item file, open it with a text editor of your choice. I recommend Notepad++ as it has built in lua highlighting. (Check image for path and naming info)

### The basics of the item.lua file

All items in the game work by subscribing to events that get fired when something in the game happens. For example, when the player picks up the item, the game will call the *onPickup()* function that is inside the .lua file. Some events have extra data that can be used for special purposes (more on that later).

ADVR uses Moonsharp to give access to a lot of game functions and properties that are also used internally, so you can have a lot of Control over the game via pickups. There are a lot of things that may not be implemented yet and if you are stuck or don't know how something is done, please go in the discord and ask me. If something is missing and it is useful I'll definitely put support for it in the game.

At the bottom of the page (still work in progress) is a table that lists a lot of fields / functions / methods that can be accessed via the modding api.

So, now that we know how items work in theory, lets add code to our own item.
All items need 2 functions to work properly. Without those, they do not work! Those are `onLoad()` and `onPickup()`, which are called when the game loads the item (so on startup) and when the item gets picked up by the player.

This is how a normal, basic item file without use looks like:

```
function onLoad()
	pickup.name = "Test Item"
	pickup.desc = "Instakills lol"
	pickup.probability = 1
	pickup.maxAmount = 1
	pickup.amountUses = -1
	pickup.price = 15
	pickup.spawnsIn = {"boss","podest","secret","goldenChest"}
end

function onPickup()
	pickup.registerItem()
end

```

Lets go through these one by one:

Those values define most of the item already. The line `pickup.registerItem()` registers the item as being picked up and also adds it to the inventory screen where you can see which items you have already found during your run. You should always call this method in your items.

Now we have a basic item that does nothing. But it will not load in the game yet, because we have no texture for it yet. This is what we are going to do now.

### Adding a texture to our item

Adding a texture for our item is an easy process. All you need to do is add a .png file of your sprite in the same folder as your item.lua file. *Important: Your .png file needs to have the exact same name as your .lua file in order to work correctly!*
It is also recommended to only have sprites with a maximum size of around 20x20 pixels. Bigger values work, but then your pickups will become huge in game and may eat up a lot of rendering performance. I recommend GIMP for creating sprites.

This is how the folder should look like (it looks a bit different in sidequest, but its the same idea):

*In order to see an example sprite, check out the testmod in the mods folder*.

### Testing our Item in game

Now that you have added an image and a .lua file to your mod it should work! In order to test it, start the game and open the options panel. On your right you can see a mods panel and you should see your mod that you created, with a red X. Just click the button to enable it and press the reload button to apply. You should now be able to find your item in the dungeon. It is also possible to apply your item via the ingame console for faster testing.

*If the game does not load (stuck in loading screen) there may be something wrong with your mod and you need to find out why.*

*In the future it is also possible to spawn the upgrade directly.*

Your custom item now works, but it does not do much, so lets spice it up a bit!

### Making our item do something interesting (Part 1)

Now that we have a basic item, we want to make it do something. First, lets do something extremely easy, like increase the players cash and the players keys. We only need to increase the amount of two variables for that. There are a lot of predefined variables that we can access to alter different parts of the game. The two most important ones are: `player` and `game`. Those two let you access most of the players variables and functions as well as control a lot of the game itself.

To increase the amount of keys and the amount of cash we need to manipulate the two field in the player that keep track of them. We want to give the player those keys and cash when he picks up the item, so we add code to our *onPickup()* method. After this our code should look like this:

```
function onPickup()
	pickup.registerItem()
	player.currentKeys = player.currentKeys + 3
	player.currentCash = player.currentCash + 10
end

```

And that's it. If you have the files in your mod folder, you're good to go! You can start the game. For fast testing you can open the ingame console (its in the options) and select: *applyupgrade -> your\_item\_name -> Enter* to test out the item. You should now have additional cash and keys and the sprite of your item should now show up in your inventory under *pickups found during run.*

### Making our item change the color and shape of our sword

It is possible to change the shape of the sword blade and the shape of the throwing knife. Because the sword blade uses the same mechanic to appear 3D as the pickups do, you can essentially draw the shape you want the sword blade to have. The collider generates automatically but it will always be the convex hull of the sprite.

But you don't just draw the sprite and are finished, because then other upgrade effects, like the dynamite blade or bloody blade won't appear on your sword when picked up (it does not change the color). These effects are applied procedurally according to special zones on your blade.

#### **1. Changing Color:**

First, lets not change the shape, but only change the colors of the sword.

There is a total of 7 zones that get colored in when the blade generates (those are the colors of the sword). All of these 7 zones can then individually be changed with other colors via method calls. You can see this in action in *erthu\_dynamite\_blade* for example.

Here is an image of the 7 zones and the blade of the standard sword:

The zones are numbered 0-6 and can be called via the *UpdateWeaponColors* method. Here is any example from the dynamite blade:

```
function onPickup()
	pickup.registerItem()
	bc = player.GetPlayerSword().bladeCreator
	bc.UpdateWeaponColors(0, 1.0, col(0.35, 0.0, 0.0, 1), false, false);
	bc.UpdateWeaponColors(1, 1.0, col(0.35, 0.0, 0.0, 1), false, false);
	bc.UpdateWeaponColors(2, 1.0, col(0.35, 0.0, 0.0, 1), false, false);
	bc.UpdateWeaponColors(3, 1.0, col(0.35, 0.0, 0.0, 1), false, false);
	bc.UpdateWeaponColors(4, 1.0, col(1, 0.43, 0.0, 1), false, false);
	bc.UpdateWeaponColors(5, 1.0, col(1, 0.65, 0.0, 1), false, false);
	bc.UpdateWeaponColors(6, 1.0, col(1, 0.88, 0.0, 1), false, true);
end

--newer code if code above doesn't work.
function onPickup()
    pickup.registerItem()
	weapons = {"sword", "knife", "dagger", "cbow"}
    helperMethods.UpdateWeaponColors(weapons, col(1, 0, 0, 1), col(1, 0, 0, 1), col(1, 0, 0, 1), col(1, 0, 0, 1), col(1, 0, 0, 1), col(1, 0, 0, 1), col(1, 0, 0, 1))
end
--The image below briefly explains what this code does.

```

As you can see, we update all 7 zones to change color. But its also possible to just change 1 zone for example. There are also some extra parameters that we are passing:

*UpdateWeaponColors(region, fillRatePercentage, color, randomizeColor, update)*

**Region:** The region that we update, can be seen in the left image

**fillRatePercentage:** How many pixels should we fill? For example, bloody blade adds a few blood particles to the sword, but does not color it in completely, so it has a lower value there (around 20%, so 0.2) **--Doesn't work for newer code if you are using newer code.**

**color:** The color of the region. Colors are in RGBA format (0-1) --There is a formula for this, firstly use a color picker to get rgb values of the color you want. then lets say you want to color a region orange. The rgb values would be 255R, 100G, and 0B. So to get it in a 0-1 format you would need to divide 255/255 to get 1, then 100/255 to get 0.39 and since B is 0 you don't need to divide it by anything. So the final value to get orange in a certain region would be (1, 0.39, 0, 1). Alpha always has to be at 1 if you want a solid color but if you want a transparent sword just put the value down.

**randomizeColor:** Adds a bit of random noise to the color **--Doesn't work for newer code if you are using newer code.**

**update:** Updates the weapon texture. Notice, how it is only set to true on the last statement. This is because we only want to update the mesh and texture, once all modifications are applied, otherwise we would be doing it 7 times instead of 1 which costs a lot of performance. So only set this to true on the last statement. **--Newer code automatically updates the code so no need for it if you are using the newer code.**

Now that you have added some code to change the color of your blade, you can test it out and check the results.

#### **2. Adding Trails and Emission**

After adding some color to your weapon adding trails would really make the weapons have that extra pzazz and makes it feel a lot better when swinging or shooting your crossbow.

**Firstly Lets start on the color of the trail:**

```
function onPickup()
	pickup.registerItem()
	weapons = {"sword", "knife", "dagger", "cbow"} --<--you should already know what this does if you'ved already colored your weapon
	player.GetCrossbow().SetTrailColor(col(1, 0, 0, 0.5))
	player.GetDagger().SetTrailColor(col(1, 0, 0, 0.5))
	player.GetSword().SetTrailColor(col(1, 0, 0, 0.5))
	player.GetKnife().SetTrailColor(col(1, 0, 0, 0.5))
	--The image below helps break down the code above.
end

```

Player.GetExample, The Player.Get is needed to make the code work, and you can choose which weapons you want to trail, if you want to trail all weapons then just put each individual weapon in 4 liens like the code in the code block.

The Set Trail color is also needed to have the code function properly, I recommend just straight up copying the code in the code block if your trying to get it done quick, it's pretty easy to figure out yourself.

Color is the same as the changing color tutorial but the only thing that changes is the alpha, the aplha affects the transparency of the trail and it is sitting at 0.5 right now because it's the exact middle of it.

**Emission tutorial will be coming soon(even I haven't figured out emission yet :( )**

### **3. Changing the Shape**

In order to change the shape, we need to add an extra sprite to our mod item, called a *bladeMod*. A blade mod is just a texture like the one you've seen previously, but with a different shape. In order to do this, open up an image editing program and draw the shape that you want. It is generally advised to use all 7 regions on your weapon in order to see all the procedural effects on the blade later. Also, be sure to have them in roughly the same location as above, because the purple pixels are darker than the cyan pixels in the final weapon for example because it is set up this way.

It is also important that you use exactly the right colors, as other ones do not get recognized by the mesh creator. These colors are:

White (255, 255, 255), Red (255, 0, 0), Blue (0, 0, 255), Green, (0, 255, 0), Yellow (255, 255, 0), Purple (255, 0, 255) and Cyan (0, 255, 255)

Those colors are then mapped to the default ones.

Here is a finished example of a bigger blade created with these colors.

Now that we have finished our sprite we need to save it as a .png with the same name as our item plus \_bladeMod.

Example: If our item is called *erthu\_nice\_item.lua* our blade mod would be called *erthu\_nice\_item\_bladeMod.png*

You now should have 3 files in your modded item folder: the item lua, the item sprite, and the item blade mod.

In order to apply the blademod you need to add one extra line of code to your item.lua file.

`player.GetPlayerSword().bladeCreator.CreateItemMesh()`

Its best to put this line of code in the *onPickup()* call

You're all set now. You can try out your item and enjoy a different looking blade!

#### **4. Differences with knives**

Knives work in exactly the same way as the blades do but in order to access the bladeCreator you need to type `player.GetPlayerKnife().bladeCreator.` Also, you need to change the name of the file. Its now called *erthu\_nice\_item\_knifeMod.*

## Functions / Variables / Useful method List

This section lists a lot of the fields and functions that you can access via the modding api, as well as how to use them

#### Functions you can subscribe to in the item.lua files

**onLoad()** gets executed when the game loads the item from the storage (on startup). Needs to be in the item file for it to work.

```
function onLoad()
	pickup.name = "Dynamite Blade"
	pickup.desc = "Chance to create an explosion when hitting an enemy"
	pickup.probability = 0.2
	pickup.maxAmount = 3
	pickup.amountUses = -1
	pickup.price = 30
	pickup.spawnsIn = {"secret","boss","podest"}
end

```

**onPickup()** gets executed when the player picks up the upgrade. Needs to be in the item file for it to work. Also, be sure to always call *registerItem()* to register the item in the active pickup list

```
function onPickup()
	pickup.registerItem()
    player.currentCash = player.currentCash + 10
end

```

**onSwordHitEntity(filter, infos)** gets executed when the player hits any entity that has health. It can be a pot, or barricade or monsters etc. The first parameter is the filter, which contains information on what got hit. The second parameter contains additional information, like the hit position of the entity. Hit infos contains: `entity` (the entity reference that got hit), `hitPosition` (a Vector3 with the world position of the hit), `damage` (how much damage was dealt, int)

Also, be sure to always return the damage value because this gets used by the game to determine if this item changes something about the damage that will get dealt.

```
function onSwordHitEntity(filter, infos)
	if checkFilter("monster", filter) then
		if math.random() < 0.33 \* amountItem() then
			game.spawnObject("effect\_explosion\_small", 1, infos.hitPosition)
		end
	end
	return infos.damage
end

```

**onPlayerHit(damage)** gets executed when the player gets hit by something. It contains a parameter *damage* that contains the damage the player will receive. Always be sure to return a damage value so the game knows if it has been changed by the item. Example from Blazing Aura:

```
function onPlayerHit(damage)
	enemies = game.getEnemiesInRadius(4, player.transform)
	for k, v in pairs(enemies) do
		v.applyEffect(attackType.FIRE, 3, 4)
	end
	return damage
end

```

**onKnifeHitEntity(filter, infos)** is the same as onSwordHitEntity (above) just for the throwing knife.

**onPreDungeonGenerated()** gets executed before the dungeon generates, so in the transition screen. It is often used to change paramaters for the upcoming dungeon. Example from Giants blessing, which increases the dungeon generation size:

```
function onPreDungeonGenerated()
	size = game.currentWorldGenerator.generationDetails.worldSize
	game.currentWorldGenerator.generationDetails.worldSize = vec2i(size[0] + 2, size[1] + 2)
end

```

**onDungeonGenerated()** gets executed just after the dungeon has finished generating. It can for example be used to change something at the start of the floor, but the floor needs to be generated for it already, for example revealing the minimap. Example from Dungeon Map item:

```
function onDungeonGenerated()
	game.minimap.RevealMap()
end

```

**onEntityDeath(filter, position)** gets executed once an entity dies, like a pot, enemy etc. It has two parameters: *filter*, that is just the living\_id of the entity in order to know what type it is and *position* which holds the position where the entity died. Example from lucky pot, which drops extra coins when pots are destroyed:

```
function onEntityDeath(filter, position)
	if filter == "prop\_pot" then
		if math.random() > 0.65 then
			game.SpawnObject("item\_coin", 1, position)
		end
	end
end

```

**onKnifeCollide(knife, collision)** gets executed when the knife collides with something. It can just be the environment or a monster or other entity. The parameter *knife* is just a reference to the throwing knife of the player and *collision* is a Unity Collision object that contains a lot of different fields that you can access. This example is of dynamite knives that explode on collision.

```
function onKnifeCollide(knife, collision)
	if collision.relativeVelocity.magnitude > 2 then
		game.SpawnObject("effect\_explosion\_small", 1, knife.transform.position)
	end
end

```

**onKnifeThrow()** gets executed once the player lets go of the knife when he throws it. This can be used for example to spawn extra knives like double or triple knives. This example shows the triple knives code:

```
function onKnifeThrow()
	player.throwingKnife.spawnAdditionalKnife(vec(0, -15, 0), vec(-0.25, 0, 0))
	player.throwingKnife.spawnAdditionalKnife(vec(0, 15, 0), vec(0.25, 0, 0))
end

```

#### Script Reference

*THIS SCRIPT REFERENCE IS NOT COMPLETE, IT IS ADVISED TO CHECK OUT OTHER ITEMS THAT ARE IN THE GAME AND LOOK AT THEIR CODE TO GET A BETTER UNDERSTANDING OF HOW THE ITEMS WORK. You can access these items by downloading the PCVR version of the game.*