Jump to content

Recommended Posts

just trying out that, and i want to know to setup an genetic mod, and this hello world mod will be smth like an stat change or smth like that. I did read some basics, i do have VS code and i unziped the game's scripts. I will now want some guidance on setting up a mod from scratch! :>

I would say that Modding Tools and the API Examples mod is a good place to start. Though it's very old, so not everything is up to date.

The basics:

If you need to learn the lua language, I think any tutorial would work fine. I used https://www.lua.org/pil/contents.html but I'm sure there's better documentation out there. DST uses Lua 5.1, if you do print(_VERSION).

modutil.lua is the main script you'd want to read because it has all the environment functions that mods would normally use. Anything with env. before it is meant for your environment. In mods.lua, the fns and tables available at your disposal are shown below. If youre looking for other useful fns, maybe look in util.lua.

Spoiler
local env =
{
  -- lua
  pairs = pairs,
  ipairs = ipairs,
  print = print,
  math = math,
  table = table,
  type = type,
  string = string,
  tostring = tostring,
  require = require,
  Class = Class,

  -- runtime
  TUNING=TUNING,

  -- worldgen
  LEVELCATEGORY = LEVELCATEGORY,
  GROUND = GROUND,
  WORLD_TILES = WORLD_TILES,
  LOCKS = LOCKS,
  KEYS = KEYS,
  LEVELTYPE = LEVELTYPE,

  -- utility
  GLOBAL = _G,
  modname = modname,
  MODROOT = MODS_ROOT..modname.."/",
}

In order to access something outside of your environment, you're meant to use GLOBAL.fn (for example the util.lua fns). There is something that makes it so you don't have to use GLOBAL anymore, but I'd recommend using GLOBAL at first so you get a feel for what's DST and what's not. This is the code that makes it so you don't have to use GLOBAL.

Spoiler
-- ++ penguin
GLOBAL.setmetatable(GLOBAL.getfenv(1), {__index = function(self, index) -- makes GLOBAL unneccesary, use _G instead if needed
	return GLOBAL.rawget(GLOBAL, index)
end})

A really important principle that comes up in DST modding a lot is function hooking. It's basically extending other fns with your code.

I like to use this code a friend made for fn hooking, but for most examples here I usually do the manual way. You have to understand how require works to use overwrite. Require is basically taking another script and putting it in your own script, DST looks in your mod folder first for the script you're talking about, and then its own scripts.

Spoiler
-- ++ mort
local unpack = GLOBAL and GLOBAL.unpack or _G.unpack
local function results(data, ...) 
	return type(data) == "function" and {data(...)}
	or type(data) == "table" and data
	or {data}
end

local function sandwich(func, ante, post)
	return function(...)
		local results_ante = results(ante, ...)
		if #results_ante > 0 then return unpack(results_ante) end

		local results_original = results(func, ...)

		local results_post = results(post, ...)
		if #results_post > 0 then return unpack(results_post) end

		return unpack(results_original)
	end
end

overwrite = function(tabula, name, ante, post, ifnil) -- tabula needs require"thing" most likely... 
	if type(tabula) ~= "table" then return end
	local old = tabula[name]
	if old == nil and ifnil ~= nil then old = ifnil end
	tabula[name] = sandwich(old, ante, post)
end
-- _G.overwrite/GLOBAL.overwrite = overwrite -> makes it so even scripts outside your environment (likely components and widgets) can use it

 

Here's an example of me using overwrite to make Wolfgang's mighty damage weaker

Spoiler
--[wolfgang]
--Change mightiness damage
overwrite(require"components/mightiness", "BecomeState", nil, function(self, state)
	if state == "mighty" then
		self.inst.components.combat.externaldamagemultipliers:SetModifier(self.inst, 4/3) -- 133%
	end
end)

 

Response:

Now, onto what you've asked. Make a modinfo.lua and modmain.lua file in your mods folder (likely in Steam\steamapps\common\Don't Starve Together\mods) and put in the relevant info for your need

In modmain.lua:

Print hello world

print"[EXAMPLEMOD] Hello world"

This shows up, but not when you're loaded in, only when the script is being read. In order print after you're loaded in, you'd need to do

Spoiler
AddPlayerPostInit(function(inst)
    inst:ListenForEvent("playeractivated", function(inst)
        print(inst, "I'm loaded in completely!")
     end)
 end)

If you want to listen for a stat change, this is how you do it with a client mod

local function OnStatChanged(inst, data) 
	print(inst:GetDisplayName()..": My stats changed! ("..tostring(data)..")")
	GLOBAL.dumptable(data) -- Notice that they return similar data keys and none are identifying of what stat it's for. You will need to make a function for each event listener if you want to do something more specific with them.
end

local function AddDeltaListeners(inst)
	inst:ListenForEvent("healthdelta", OnStatChanged, inst)
	inst:ListenForEvent("sanitydelta" , OnStatChanged, inst)
	inst:ListenForEvent("hungerdelta" , OnStatChanged, inst)
end
AddPlayerPostInit(AddDeltaListeners)
Edited by oregu
  • Like 1

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
  • Create New...