This tutorial I will show you
- how file load order works
- how to think and structure lua mods
- how to modify vanilla behaviour
- how to use
require
with passion - and more...
Project Zomboid uses globals mostly everywhere, this make it easy for modders to use the objects anywhere but it also make it easy to break things by assiging an existing global with something that it shouldn't.
Other mods sometime uses globals too and when players runs 200+ mods at the same time, bet there is possibly conflicts, but also the global environment will be a real mess.
There is a solution to prevent using globals and this is exactly what we will be looking at here! But before that let's get to the most basic stuff.
Bear with me. π»
It may be confusing when we first start modding Project Zomboid so... Let's break this down once for all!
shared
files must be agnostic (Contains classes and/or functions that may be needed intoclient
and/orserver
files)
client
files cannot requireserver
files- in multiplayer
client
files runs only on theclient machine
server
file cannot requireclient
files- in singleplayer
server
files runs only when booting a savegame - in multiplayer
server
files runs on both theclient machine
andserver machine
- Is there objects, functions or classes that can help me creating my feature?
- Is my feature going to be networked in multiplayer, is it transmitted automatically under the hood or I will need to handle transmition myself?
- Do I need to store data on the player, in an object, in an item or globally in the world itself?
- Can I take advantage of existing functions or objects such as the 150+ available timed actions?
- Do I need to overwrite a base feature or can I hook into it and extend it's behaviour?
- Do I need something that is not exposed by the Java engine into lua?
I want to make it so the player cannot do a specific action for a some new reasons.
-
Do I need to think about networking?
No, timed action are client sided. -
Do I need to overwrite something?
Yes but more specifically, I need to Hook into a timed action. -
Can we just skip the talk and see code example?
Wait no more!
Let's create a client
file into
C:/Zomboid/mods/examplemod/media/lua/client/MyScriptName.lua
Now let's choose a timed action to Hook into by browsing into
C:/Program Files (x86)/Steam/steamapps/common/ProjectZomboid/media/lua/client/TimedActions
I chose ISBuryCorpse.lua
and I want to prevent the player from being able to bury a corpse if he is too hungry.
So let's open MyScriptName.lua
and also ISBuryCorpse.lua
into a code editor
By reading the timed action script we learned that isValid
method return a boolean that define if the action can run or not.
ISBuryCorpse.lua
function ISBuryCorpse:isValid()
local playerInv = self.character:getInventory()
return playerInv:containsType("CorpseMale") or playerInv:containsType("CorpseFemale")
end
Let's Hook into and add our new condition to the pile.
MyScriptName.lua
--- Save a reference to the original method
local ISBuryCorpse_isValid = ISBuryCorpse.isValid
--- Now overwrite the vanilla method
function ISBuryCorpse:isValid()
--- We return the original method result
--- But we also add our own condition
return ISBuryCorpse_isValid(self) and self.character:getStats():getHunger() < 0.75
end
Crazy! We just modified the behaviour of an action in 10 seconds.
But this didn't require anything?
No the timed action is a global object from the vanilla game so we did not need anything.
To be continued...