Jump to content

Recommended Posts

A friend of mine got me into DS maybe two weeks ago and I've been hooked on mods. Naturally I want to create my own character. It seems everyone goes through that pattern. I learned a lot about Lua in the last week and I certainly understand what I'm seeing a lot more now than I did when first I downloaded the extended character template. 

I am not understanding the references to "inst" and "self". I can tell they are relative, but there is clearly something I'm not catching. I get the feeling I'm going to face palm a bit when I finally do understand this. I find I have more questions than answers at this point, but I'm also certain understanding this one issue better when help me to advance further on my quest. 

In Lua, functions can be declared and called as members of a table. For example:

local ParentTable = {}

--This method of declaration adds an invisible first argument, 'self'
function ParentTable:MemberFunction(a,b,c)
	print(self)
	print(a,b,c)
end

--This passes 'ParentTable' as an invisible argument 'self'. Note that you can still do this with a member function that was normally declared (The first argument will be set to 'ParentTable', and 'a', 'b', and 'c' will be passed as second, third and fourth arguments.)
ParentTable:MemberFunction(a,b,c)

--This calls the function on it's own, and sets 'self' to "Potato"
ParentTable.MemberFunction("Potato",a,b,c)

(Sorry if that example is too verbose, I'm happy to clarify.)

 

So that's what is happening in components and other functions declared like that.

 

Prefabs are registered in some background code that loads the files specified in the 'PrefabFiles' table in 'modmain.lua'. Each of these files needs to return one or more Prefab Definitions, which are created by the 'Prefab()' function. The 'fn' function, which is passed to 'Prefab()', will be called every time a new prefab of that type is created, and is expected to return a new instance of the prefab.

local inst = CreateEntity()

This code creates a new, generic prefab instance. Everything after that is to add the features of the specific prefab you want to make. Then, 'fn' returns it.

 

Hopefully that answers your question, if not please ask more specifically.

That helps a lot actually, thank you. I'll be heading back into Lua study and then some more browsing game files. I'm really liking Lua and the more I practice the more I see where I will certainly use it on other projects in the future. I think so far I'm really just struggling with the complexity of the DS tables. Being new to it there is a lot to take in. 

I'm sure I'll be back here with more questions, give me a day or two to study more of these things and I'm sure I'll be back with more questions.

So how does one bounce around in the code? For example, if I wanted to take something in the game that is not edible and make a character able to eat it for some special effect, how do I make that item edible? I understand that I need to add the "edible" component to the item, we will use flint as an example. It seems like I would then need to add flint to a foodpref, or create a new foodpref, then tell the character it can eat that food type. What I'm not grabbing is how best to add that to the needed tables. 

I read the prefab for WX78 and found 'inst.components.eater:SetOnEatFn(oneat)" which seems to telling the game when this character eats instead of the normal eat function use the oneat function coded special for this character. 

Sorry if these are all really stupid questions. If you would prefer to point to a link that might help me figure these things out myself a little more effectively I'm completely ok with that. I almost feel like I need a list of built in functions or something like it to go on here to put together how this already run in order to best know how to alter them.

EDIT: So I'm still trying to solve this solo and I find that flint already has the edible component. Poop isn't edible, lets make poop edible. How do I add the edible component and such to poop?

Edited by HatefulGravey

The closest thing there is to API documentation is this unofficial project (Personally I don't find it helpful, but that could just be me).

 

Almost anything you want to do can be figured out by looking at existing code. Regardless, I'll look into it and post an example shortly.

Looks like edibles are just made like this:

--Code goes in the 'fn' function in a prefab definition file
inst:AddComponent('edible')
inst.components.edible.healthvalue = 50
inst.components.edible.hungervalue = 50
inst.components.edible.sanityvalue = 50
inst.components.edible.foodtype = "VEGGIE" --More info to come on making custom food groups (pending investigation)

 

12 hours ago, Arkathorn said:

Looks like edibles are just made like this:


--Code goes in the 'fn' function in a prefab definition file
inst:AddComponent('edible')
inst.components.edible.healthvalue = 50
inst.components.edible.hungervalue = 50
inst.components.edible.sanityvalue = 50
inst.components.edible.foodtype = "VEGGIE" --More info to come on making custom food groups (pending investigation)

 

This is also how I understand it would look. How does that point to a certain item though? From what I can see that would need to be added to the prefab file for the item itself. If I wanted to add those options to an item from my character's prefab file, instead of modifying the original file, how would I get that done?

I think you need to table.insert your code into the item in question, much like your proposal for adding a food type. However I don't know how to point to that item in the file structure. 

Is there a complete API reference available? I looked around awhile and the best I found was a broken link to an unofficial API and some listings of changes made to the API (on this forum, and the formatting was off to such a degree that I couldn't really read the code). 

All of my prior programming experience has been for micro controllers for different electronics projects over the years. So I have never dealt with an API, but after a little more reading it looks like that is something we would need to know how to really move around in this software.

There is no formal or comprehensive API, but there is an unofficial documentation project.

 

So you want to add edibility to an existing item? Just put the code I posted in 'modmain.lua', inside this function:

--Calling 'AddPrefabPostInit' causes this function to be run after 'fn' when initializing new "itemname" prefabs
AddPrefabPostInit("itemname",function(inst)
	--The code from before
end)

 

I could not get the above code to work. That said I did find a way to make it work, kind of. I copied the contents of the poop prefab and pasted that into a new file, to which I added the edible component and needed effect states. 

Like so:

--add this to the new prefab under local function fn=(sim)	

inst:AddComponent("edible")
inst.components.edible.hungervalue = (DESIRED VALUE)
inst.components.edible.sanityvalue = (DESIRED VALUE)
inst.components.edible.healthvalue = (DESIRED VALUE)
inst.components.edible.foodtype = "DESIRED FOODTYPE"

That got the job done. As I was thinking about how to get this done, I figured the mod handling part of the game had to load the prefabs from your mod folder into the game in the same place in memory as the files that are already in the game. If that were the case, it would be a matter of which prefabs the game grabbed first. I assumed the game would love the original files before looking for mod information, so the new prefab would be copied over the original in memory. As far as I can tell that is exactly what as happened. If I remove the new prefab and reload the game the original prefab takes over and everything works like normal. 

I might be able to pull off this same copy, paste,  and alter approach with the edible components file to create a new foodpref and then assign that foodpref to the character I want to be able to eat this item. I'm thinking I would have to create a components sub-directory in the mod folder and put the new edible file there to get it to load into the right place in memory. I just feel like there is a better way to be doing all of this.

There is a potential problem here as well. If more than one mod has this ability, the components file for each mod would come into conflict. Likely resulting the last file being loaded being the only file used. 

Not sure what this really does for the conversation in question but I thought I would share what I have learned.

You are correct: Files in your mod will overwrite default files at runtime.

You are also correct in assuming that this is not the best way to do this. The best practice in modding would be to never use this feature, only modifying functionality using the tools that Lua and the API provide (which are numerous and extensive).

 

I completely forgot to tell you about 'GLOBAL' (sorry)!

Code run in 'modmain.lua' is run in a special environment. This means that it has access to some special functions exclusive to that file (Like 'AddPrefabPostInit'), but the normal environment (which has all normal global variables and functions) has to be referred to as 'GLOBAL'. The reason the code wasn't working was probably because it needed to read 'GLOBAL.GetPlayer()' instead of 'GetPlayer()'.

 AddPrefabPostInit("poop", function(inst)
    if GLOBAL.GetPlayer().prefab == "hatefulgravey" then
    inst:AddComponent("edible")
    inst.components.edible.hungervalue = (50)
    inst.components.edible.sanityvalue = (50)
    inst.components.edible.healthvalue = (50)
    inst.components.edible.foodtype = "MEAT"
    end
end)

This is the code that makes what I have been talking about work correctly (for anyone that sees this looking to do things like in the future.) It is a combination of many things talked about so far in this thread. So far I have not been able to add a new food type to the game through this mod, so the poop is currently in the meat group, but using this code my test character can now eat poop, and no one else in the game is effected by this, except maybe having to watch him do it. 

Thanks for the help so far, stick with me, one more challenge still ahead on this one.

Edited by HatefulGravey

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...