Jump to content

[Help] Disallow feeding birds with meat


Recommended Posts

@IcyTheWhite, you would use AddPrefabPostInit for the birdcage prefab.

 

Inside the function which you call from AddPrefabPostInit, you need to call the SetAcceptTest function on the trader component; the argument to pass is a new function.

 

Inside the new function you'd alter the following (copied directly from the birdcage prefab file):

local function ShouldAcceptItem(inst, item)	local seed_name = string.lower(item.prefab .. "_seeds")	local can_accept = item.components.edible and (Prefabs[seed_name] or item.prefab == "seeds" or item.components.edible.foodtype == FOODTYPE.MEAT) 		if item.prefab == "egg" or item.prefab == "bird_egg" or item.prefab == "rottenegg" or item.prefab == "monstermeat" then		can_accept = false	end		return can_acceptend 

 

After you've called the SetAcceptTest function, you should return the instance of the new birdcage. It should be 5 lines of code, minus the code you have to edit above. If you need further assistance then check the birdcage.lua file located in scripts/prefabs search for SetAcceptTest and ShouldAcceptItem.

Link to comment
Share on other sites

Adding on to what Kzisor said, it's usually a good idea to preserve the previous function to improve compatibility.

-- Where inst refers to the birdcage instancelocal old_ShouldAcceptItem = inst.components.trader.testlocal function NewShouldAcceptItem(inst, item)    local oldResult = old_ShouldAcceptItem(inst, item)    -- Check your condition here (if item is meat)    -- Return oldResult if your condition doesn't matchendinst.components.trader:SetAcceptTest(NewShouldAcceptItem)
Link to comment
Share on other sites

Why some people make mods without the main.lua file and just past modified prefabs into their /scripts/prefabs folder?

 

How does the game work with these files?

Does it simply override every line, that was first loaded in the game's prefab folder and then mod's prefab folder??

---

Also, I know you guys are trying to help me in a way where I have to figure out the code for myself, but I don't understand most of the things you're saying. I would learn much more from the finished code, rather then from searching and figuring it out for myself over several hours..

 

I just want to play the game without that ridiculous option, where you can feed the birds with bunch of monster meat and get valuable eggs out of it.

Link to comment
Share on other sites

Ok, so after little fiddling, I want to do ONLY one thing.

Using the main.lua file, I want to alter some information of any .lua file located in "scripts" and "prefabs" folder.

What is the simplest way to do it?

 

For example in "veggies.lua" file, I want to alter this line (105th line):

inst.components.edible.hungervalue = TUNING.CALORIES_TINY

into:

inst.components.edible.hungervalue = TUNING.CALORIES_TINY/2

That's it.

 

But I don't know how to do it as a mod, rather than editing it in the main file itself.

Any help?

Link to comment
Share on other sites

Why some people make mods without the main.lua file and just past modified prefabs into their /scripts/prefabs folder?

 

How does the game work with these files?

Does it simply override every line, that was first loaded in the game's prefab folder and then mod's prefab folder??

 

That method essentially replaces the entire file internally. It's generally not a good idea to do it like that because your mod will have compatibility issues with game updates and other mods. While it does have its own uses, those are irrelevant for most mods.

 

 

Also, I know you guys are trying to help me in a way where I have to figure out the code for myself, but I don't understand most of the things you're saying. I would learn much more from the finished code, rather then from searching and figuring it out for myself over several hours..

 

We don't actually have the code for every possible mod sitting around, waiting for someone to ask for it. We provided the information that we do have. It would take more time and effort to actually put it all together and debug it.

 

It might be easier to learn from finished code, but researching and figuring it out has its own benefits. It will give you a better understanding of how everything works, and you'll be able to make mods faster on your own next time.

Also, people are usually more inclined to help someone when they're trying to put in their own effort too.

 

If you don't understand anything, feel free to ask about it and we'll elaborate. You don't have to look for everything on your own, just try a few searches, skim through results, then if you don't find what you need, ask.

 

 

Ok, so after little fiddling, I want to do ONLY one thing.

Using the main.lua file, I want to alter some information of any .lua file located in "scripts" and "prefabs" folder.

What is the simplest way to do it?

 

For example in "veggies.lua" file, I want to alter this line (105th line):

inst.components.edible.hungervalue = TUNING.CALORIES_TINY

into:

inst.components.edible.hungervalue = TUNING.CALORIES_TINY/2

That's it.

 

But I don't know how to do it as a mod, rather than editing it in the main file itself.

Any help?

 

There are multiple ways you can do this. In most cases, whenever you see "TUNING", you can modify it quite easily. (in modmain)

TUNING = GLOBAL.TUNINGTUNING.CALORIES_TINY = TUNING.CALORIES_TINY / 2 

Note that this will affect every place that uses TUNING.CALORIES_TINY

 

In your case, I assume you only want to change the hunger value of all vegetable seeds.

local function VeggieSeedsHunger(inst)    -- "inst" refers to the prefab's instance    -- Check if we have the right prefab (anything ending with _seeds)    if inst and (string.sub(inst.prefab, -6) == "_seeds") then        inst.components.edible.hungervalue = TUNING.CALORIES_TINY / 2    endend-- Will call the above function on all prefabsAddPrefabPostInitAny(VeggieSeedsHunger)

Edit: Fixed mistake mentioned below. (See below for alternate code)

 

Link to comment
Share on other sites

Ah, well thanks for a quick reply, but again that didn't solve my problem...

As far as I understand, you've made a function that searches through all the prefabs for the right prefab. But it still didn't change the value of that line. (at least for me it didn't work when I tested it..)

 

All I want to do is to tweak some values of the game (like crock pot values, food values and seed values) without having to do it in the main data folder to prevent issues on the game update or smth.

I know I'm not a programmer and probably won't ever be, I'm just a fan of this game and want to make some thing more reasonable for me...

 

 

-

And what is the difference between "local function" and "function"?

Link to comment
Share on other sites

Ah, well thanks for a quick reply, but again that didn't solve my problem... As far as I understand, you've made a function that searches through all the prefabs for the right prefab. But it still didn't change the value of that line. (at least for me it didn't work when I tested it..)

Hmm. Hold on, I'll test it and see what's wrong.

Just to point out, these are the kinds of things that you need to do when you're actually making the mod. You make something, test it, it doesn't work. Throw in some print statements, try to find out what's wrong, try it again, etc. Having an idea for a mod isn't enough to bring it to existence, you need to be willing to put effort into creating it.

 

 

All I want to do is to tweak some values of the game (like crock pot values, food values and seed values) without having to do it in the main data folder to prevent issues on the game update or smth. I know I'm not a programmer and probably won't ever be, I'm just a fan of this game and want to make some thing more reasonable for me...

Many things can be easily modified using the TUNING variable, as I demonstrated previously.

Check the file "..\scripts\tuning.lua" in your DS folder. It contains everything that can be modified in this way.

Read about lua table syntax if you are unsure how to access them. The TUNING variable is a table. It uses the curly bracket syntax in tuning.lua, but you should modify it using the dot syntax in your modmain.

Remember to put "TUNING = GLOBAL.TUNING" at the top of your modmain.

 

 

And what is the difference between "local function" and "function"?

Just the scope. Using the local modifier limits where the function (or variable) can be used.

Link to comment
Share on other sites

@IcyTheWhite

 

I wrote "strings" instead of "string". That was the problem. Using another syntax this time, but it's the same idea. Should be working now.

local function VeggieSeedsHunger(inst)	-- "inst" refers to the prefab's instance	-- Check if we have the right prefab (anything ending with _seeds)	if inst and (inst.prefab:sub(-6) == "_seeds") then		inst.components.edible.hungervalue = TUNING.CALORIES_TINY / 2	endend-- Will call the above function on all prefabsAddPrefabPostInitAny(VeggieSeedsHunger)
Link to comment
Share on other sites

Ok, so I guess I'm onto something thanks to your help.

But I still have few questions.

 

Here we go:

AddPrefabPostInit ("veggies",VeggieSeedsHunger)

vs

AddPrefabPostInitAny (VeggieSeedsHunger)

So writing out this line creates a new function (that we will later specify) and adds it to the "veggies.lua" prefab [1st code] or to all prefabs in the game's prefabs folder [2nd code]. Am I right or is there still something I'm missing?

 

 

Now about the function by itself:

local function VeggieSeedsHunger(inst)    -- "inst" refers to the prefab's instance    -- Check if we have the right prefab (anything ending with _seeds)    if inst and (inst.prefab:sub(-6) == "_seeds") then        inst.components.edible.hungervalue = TUNING.CALORIES_TINY / 2    endend

How it would affect this little mod, if we changed "local function" into "global function"?

Also, I still don't understand the whole "inst" thing and why is it used so often...

~

if inst and (inst.prefab:sub(-6) == "_seeds") then

Now I quite don't understand this line, but at least I know that it's searching for the function with name "_seeds" and if it finds it, it will change the value in it. Right?

But in the world does this part mean: inst.prefab:sub(-6)

 

Well, thanks for all your effort you're putting in helping me.

Appreciate that. Heh..

Link to comment
Share on other sites

@IcyTheWhite,
 
If some of these concepts still seem a little hazy in terms of what is actually happening, feel free to ask.
 
Ultimately, when using "AddPrefabPostInit" is used to "add on" to prefabs "post initialization", or in other words, after they're already created using the built-in code.  Here's what happens(for the most part):
 
1.  The game creates a prefab and builds it as it normally would had your mod not been loaded.
 
2.  The game checks to see if any mods have registered "PostInit" functions for that prefab. 
 
3.  If it finds any, all that the game does is call the function registered by AddPrefabPostInit, passing a reference to the instance of the newly created prefab( normally this is the "inst" parameter" of your mod's PostInit function ):


local function VeggieSeedsHunger(inst) <--

 
So whenever you manipulate "inst", you are just modifying the prefab after it has already been created.  It's almost the same as if you were to spawn the item while in game and then manipulated it via the console(the only difference being that when doing it via a mod, the game waits for your mod to modify the item before "giving" it to you or placing it in the world").
 
------
 
As for the difference between "function" and "local function" (and also for variables declared the same way)... Without trying to get too technical, you can (kind of) think of it this way:
 
Klei gives us a space in which every variable and every object is stored.  All functions that are defined in this space have their own little spaces carved out. You can think of this as a gigantic box that holds a bunch of boxes containing more boxes.  Or a tree with branches that branch off multiple times.  Both analogies fail at one point or another, so I wont bother going farther than that.

 

When you declare a function using function, the function gets created in that big global space that is shared by everything else.  This means that all code, no matter where, will be able to call the function.  This sounds good, but if this were the case, then every object would have to have uniquely named functions.  You'd need to create function onequip_backpack, function onequip_axe, function onequip_piggyback, etc. for EVERY function of EVERY prefab and EVERY object in the game.  The amount of variables stored in that main/global table would be absurdly large.

 

Instead, lua, like most high-level languages offers the local keyword.  This tells the lua engine that the function that is being declared should only be accessible in the current scope(also sometimes called "namespace").  Scope is loosely defined as "within the current function", or functions above it.  Here's an example:

function main_scope()    local main_var = true    local function scope_1()            local var_1 = true        local function scope_1_1()          local var_1_1 = true          print(var_1_1)  --valid          print(var_1)    --valid        end        local function scope_1_2()            local var_1_2 = true                        print(var_1_2) --valid            print(var_1)   --valid                        print(var_1_1) --invalid        end        print(var_1) --valid        print(var_1_1) --invalid        print(var_1_2) --invalid            endend

var_1 is accessible from both scope_1_1 and scope_1_2 because it is declared "above" each of those functions.

 

 

 

 

 

 

Link to comment
Share on other sites

@IcyTheWhite,

	    inst:AddTag("preparedfood")

see how preparedfoods has this line in the initialization function?

 

You can use AddPrefabPostInitAny.  Inside the function that you pass to it, all you would need to do is check for that tag using

if inst:HasTag("preparedfood") then...

That way, the code is only run those prefabs that have the tag, while doing nothing to other prefabs.

Link to comment
Share on other sites

But in the world does this part mean: inst.prefab:sub(-6)

 

"sub" is a method( methods are just functions that are "attached" to certain objects ) of string objects.  It effectively takes whatever string its passed and gives you a "substring" from it.  Substring is just a fancy word for "part".  In this case, it's returning the last 6 characters of the string.

 

Edit: whoops, meant to append this to my last post.  Oh well.

Link to comment
Share on other sites

@IcyTheWhite

 

Alternate way to modify prepared foods.

 

More on the "sub" method. ( ctrl+f > "s:sub" )

 

"inst" is short for "instance". Someone wrote a long explanation about it some time ago.. I think it was Corrosive. But I can't find it now.

Basically, it stores the instance data of something, usually a prefab. It's used so often because it's more convenient than writing the actual name of the prefab. This way we can easily reuse code for other prefabs.

Ex, We can use "inst.components.finiteuses.Use(1)" for everything that has the finiteuses component. Otherwise we would have to write "healing_salve.components.finiteuses.Use(1)" for healing salves, and "fishing_rod.components.finiteuses.Use(1)" for the fishing rod. (Technically, we can still use the either of those, but it looks strange and can get very confusing, very fast)

Link to comment
Share on other sites

@Blueberrys, @IcyTheWhite,

 

I did, but it was in a post differentiating between inst and self, so I don't think that  would be useful to link currently <.<

 

Anyway, to expand on what Blueberrys said, an "inst" is just an instance of something.  A prefab definition describes how to create a prefab.  Every prefab that gets created is an instance of that prefab.  Consider this simple code:

function MakeAFruit()    local fruit = {} -- this creates a blank table.        fruit.isfruit = true -- so we can distinguish that this object is a fruit and not, say, a rusty nail        return fruitendfunction MakeABanana()    local newbanana = MakeAFruit()        newbanana.type = "banana"    return newbananaendfunction MakeAKiwi()    local newkiwi = MakeAFruit()    newkiwi.type = "kiwi"    return newkiwiend

We now have the ability to create Bananas and Kiwis, as well as generic fruits that don't have a type.  Lets say we wanted to end up with 2 different Bananas and 2 different Kiwis:

banana1 = MakeABanana()banana2 = MakeABanana()kiwi1 = MakeAKiwi()kiwi2 = MakeAKiwi()

We have now created 2 instances of bananas, and 2 instances of kiwis.  We could also consider this to be 4 instances of fruits, since both Bananas and Kiwis are derived from MakeAFruit().

 

Now, how does "inst" play into all this? Simple! We could also have created the following code, which does pretty much the same thing:

function MakeAFruit()    fruit = {}    fruit.isfruit = true    return fruitendfunction  TurnIntoBanana(inst)    if inst.isfruit then        inst.type = "banana"    endendfunction TurnIntoKiwi(inst)    if inst.isfruit then      inst.type = "kiwi"    endend

Now we have the same basic fruit-making function, but instead of two functions that use it to make the fruits from scratch, we have two functions that accept instances of fruits and turn them into either instances of bananas or instances of kiwis.  Here's how you would achieve the same goal as last time-- 2 different Bananas and 2 different Kiwis:

banana1 = MakeAFruit()banana2 = MakeAFruit()kiwi1 = MakeAFruit()kiwi2 = MakeAFruit()TurnIntoBanana(banana1)TurnIntoBanana(banana2)TurnIntoKiwi(kiwi1)TurnIntoKiwi(kiwi2)

"But wait, that seems like more work than the first one for the same effect!," you might think.  In this case it is, but it is often a much more flexible way to do things.  For example, we can create a new type of fruit that is plastic, which we can then pass into the "TurnInto..." functions to produce plastic Bananas and plastic Kiwis.  Without the ability to take an existing fruit and turn it into the type you desire, you would have to create the functions:  MakeABanana(), MakeAKiwi(), MakeAPlasticBanana(), and MakeAPlasticKiwi().  You can see how this would quickly start getting crazy when adding more and more features to your fruit objects!

 

It also lets you do this:

superfruit = MakeAFruit()TurnIntoKiwi(superfruit) -- Our superfruit is currently a Kiwi.TurnIntoBanana(superfruit) -- Our superfruit is now a Banana!

Hope this helps!

 

Edit: A bit more clarification at the end.

 

Link to comment
Share on other sites

Thanks Corrosive for all your detailed info, and thank you too Blueberrys - you guys helped me a lot!

Keep up that good attitude.

 

I might still ask more, but for now I think I'm good.

Right now, I'm working on those tweak mods with deep detailed configuration and so far it's looking pretty well.

Should be useful..

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

Please be aware that the content of this thread may be outdated and no longer applicable.

×
  • Create New...