-
Notifications
You must be signed in to change notification settings - Fork 949
Modding
This page and the linked branch with changes to the source code of DevilutionX are intended to serve as a guide for creating mods.
Requires version 1.6.0+
This is the simplest way to create a mod. The main advantage is that you can quickly create mods even without programming knowledge, the disadvantage is you can only change attributes that are available into the .tsv files (Those files represent spreadsheets where columns are separated by TAB \t).
Making changes to the .tsv files is straightforward, you can use any spreadsheet editor for that or even use Notepad. You must find the .tsv file you want to modify, download it, modify it and follow the process below.
You must follow the steps:
- Create a folder for your mod (inside: mods) at the directory
<PrefPath> - Create a init.lua file
- Add your mod logic
- Enable the mod in-game (Settings -> Mods)
For example, let's create a mod to move Wirt to the town:
- Download the devilution binary
- Create a folder for your mod e.g:
wirt_in_town(inside the folders:asset/lua/mods) - Create a folder for the
txtdataand a foldertownersinside it - Create a file called towners.tsv
- Enable the mod in the settings
The file structure should look like this:
<PrefPath>/mods/wirt_in_town/
├── lua/
│ └── mods/
│ └── wirt_in_town/
│ └── init.lua
└── txtdata/
└── towners/
└── towners.tsv
- Windows:
%APPDATA%\diasurgical\devilutionx\ - Linux:
~/.local/share/diasurgical/devilutionx/
Those mods are the most flexible mods and do not require any changes to the binary files, which means you can just drop your files in the mods folder and everything will magically works (hopefully).
The main flow of the lua mod is:
In the code, there are a lot of places where a lua event is triggered. They look like this:
LuaEvent("StoreOpened", "adria");In this example the lua event is triggered when the player talks to Adria the Witch
Now, on the lua side, we need to listed to the even so we can process it.
E.g:
events.StoreOpened.add(function(townerName)
-- Do something
end)That's when your mod actually do something. When your mod receives a lua event it will trigger the logic defined inside the event listener.
-- Adria Refills Mana Mod
-- When you visit Adria's shop, your mana is restored to full.
local events = require("devilutionx.events")
local player = require("devilutionx.player")
local audio = require("devilutionx.audio")
events.StoreOpened.add(function(townerName)
if townerName ~= "adria" then
return
end
local p = player.self()
if p == nil then
return
end
-- Restore mana if player has mana capacity and it's not already full
if p.maxMana > 0 and p.mana < p.maxMana then
audio.playSfx(audio.SfxID.CastHealing)
p:restoreFullMana()
end
end)The file structure should look like this:
<PrefPath>/mods/adria_refills_mana/
├── lua/
│ └── mods/
│ └── adria_refills_mana/
│ └── init.lua
- Enable the mod in the settings
- That's it! Now when your player talks to Adria, she will refill the player's mana and your will be considered a cheater.
To create binary mods, you need to make changes to the source code and recompile the project. The main advantage of this method is to give you full control of code the downside is that depending on what you are changing you can break compatibility with Diablo/Hellfire or even DevilutionX.
The following is a list of the bare minimum changes that need to be made in order to create a mod and compile a functioning build for Windows.
- the name of the project, also used for the name of the program (CMakeLists.txt)
- game ID, also used to distinguish different builds for Multi Player (Source/diablo.h)
- game ID for Discord (Source/discord/discord.cpp)
- names for character and stash files with a password that allows control of compatibility between builds (Source/pfile.cpp)
- name of the folder used for saving character, stash and user configuration files (Source/utils/paths.cpp)
Compiling builds for all operating systems supported by DevilutionX is possible, but requires additional changes.
Example (DiabloX is only used as an example for the name of the mod.)