Jump to content

Recommended Posts

I am making a DST character and I have having trouble making him able to only eat certain gems. This is what I have so far.

local function FoodTest(inst, food)
	if food.components.edible.foodtype ~= "ELEMENTAL" or food.prefab == "rocks" or food.prefab == "bluegem" or food.prefab == "purplegem" or food.prefab == "orangegem" then
		return true
	end
end


--masterpostinit
	inst.components.eater.caneatfn = FoodTest
	inst.components.eater.foodprefs = { "VEGGIE", "INSECT", "SEEDS", "MEAT", "GENERIC", "ELEMENTAL", "ROUGHAGE" }

Currently he cannot eat cutgrass or any mineral so something is conflicting

Link to comment
Share on other sites

@SomeoneStrange Neither "caneatfn" nor "foodprefs" are variables that are tied to the eater component, so you're not going to get too far assigning them like that :p 

Taking a quick look at Wigfrids code, it looks like you can assign the desired diet using the function "inst.components.eater:SetDiet()". The first argument contains a table of all of the types of foods that will have the "eat" action command on it, where the 2nd argument are the actual foods that your character will eat (and not make the grossed out emote at).

My suggestion (if you wanted to make your character make a grossed out face at real food) is to set up your own FOODGROUP table containing everything in the OMNI foodgroup table and whatever other FOODTYPES you'd like your character to actually eat. Then, pass through your specific FOODTYPES you want your character to actually eat in the 2nd argument. Otherwise, you can just set up your custom FOODGROUP table with the foods you want your character to eat and just pass it through as a single argument to SetDiet (it automatically sets it as edible to your character if no 2nd argument is provided).

For reference to a list of all of the possible food types and food groups, you can check the constants.lua file in the main scripts folder of DST.

Spoiler

local FOODTYPE = GLOBAL.FOODTYPE
local FOODGROUP = GLOBAL.FOODGROUP

FOODGROUP.<YOUR FOODGROUP NAME> = {}
FOODGROUP.<YOUR FOODGROUP NAME>.name = "<YOUR FOODGROUP NAME>"
FOODGROUP.<YOUR FOODGROUP NAME>.types =
{
	-- These are all of the food types listed in the OMNI food group
	FOODTYPE.MEAT,
	FOODTYPE.VEGGIE,
	FOODTYPE.INSECT,
	FOODTYPE.SEEDS,
	FOODTYPE.GENERIC,
	FOODTYPE.GOODIES,
	-- Continue to list your desired food types here
}


-- Put this in your char prefab
inst.components.eater:SetDiet({ FOODGROUP.<YOUR FOODGROUP NAME> }, { <LIST OF YOUR INTENDED EDIBLE FOOD TYPES FROM YOUR FOODGROUP> })
  

-- I believe if you want them to say specific line when they refuse the food they dont want to eat, you can include this string as well
local STRINGS = GLOBAL.STRINGS
STRINGS.CHARACTERS.<YOUR CHARACTER NAME>.ANNOUNCE_EAT.INVALID = "<Your string.>"

 

Hope this helps!

Edited by w00tyd00d
Link to comment
Share on other sites

@SomeoneStrange The latter is definitely your best option, I'd just make your own food type and assign whatever prefabs you want to your custom food type

EDIT: That's as easy as just assigning a string to the name of your food type. The way they've done it is just use the same string as the food type label, though I think it can be any arbitrary string; it's just used as a "tag" of sorts.

FOODTYPE.GEM = "GEM"

 

Edited by w00tyd00d
Link to comment
Share on other sites

it is possible to condense the char prefab line like


--Your version
inst.components.eater:SetDiet({ FOODGROUP.<YOUR FOODGROUP NAME> }, { <LIST OF YOUR INTENDED EDIBLE FOOD TYPES FROM YOUR FOODGROUP> })
  
--Does this work?
local NOMS = 
{
    FOODTYPE.GENERIC,
	FOODTYPE.VEGGIE, 
	FOODTYPE.MEAT, 
	FOODTYPE.INSECT, 
	FOODTYPE.SEEDS,
	FOODTYPE.HORRIBLE,
	FOODTYPE.ROUGHAGE,
	FOODTYPE.GEMS,
}
  
  inst.components.eater:SetDiet({ FOODGROUP.<YOUR FOODGROUP NAME> }, { NOMS })
  

  

or which version would be better to use?

 

Link to comment
Share on other sites

1 minute ago, SomeoneStrange said:

there was an error.

GLOBAL was not declared

Ohh actually my b, I forgot since you're writing directly in to the character prefab you're already in the GLOBAL scope. Just get rid of those local variables declaring the GLOBAL definitions and try it again. :D

Link to comment
Share on other sites

so I am not getting an error message but I cant actually eat the gems

FOODGROUP.DOLL = {}
FOODGROUP.DOLL.name = "DOLL"
FOODGROUP.DOLL.types =
{
    FOODTYPE.GENERIC,
	FOODTYPE.VEGGIE, 
	FOODTYPE.MEAT, 
	FOODTYPE.INSECT, 
	FOODTYPE.SEEDS,
	FOODTYPE.HORRIBLE,
	FOODTYPE.ROUGHAGE,
	FOODTYPE.GEMS,
}

local NOMS =
{
    FOODTYPE.GENERIC,
	FOODTYPE.VEGGIE, 
	FOODTYPE.MEAT, 
	FOODTYPE.INSECT, 
	FOODTYPE.SEEDS,
	FOODTYPE.HORRIBLE,
	FOODTYPE.ROUGHAGE,
	FOODTYPE.GEMS,
}
	inst.components.eater:SetDiet({FOODGROUP.DOLL}, {NOMS})

do I need to do more code to create the food tag?

 

EDIT: Oh also when I am eating cutgrass my game is crashing
         

Capture.PNG

Edited by SomeoneStrange
Link to comment
Share on other sites

@SomeoneStrange Ok, so to fix the crash you're getting. It's actually set up specifically to search through a FOODGROUP table, so it's looking for the key "types" to iterate through. An easy fix to this would just be to nest your table inside the key "types":

local NOMS =
{
	types =
	{
	    FOODTYPE.GENERIC,
		FOODTYPE.VEGGIE, 
		FOODTYPE.MEAT, 
		FOODTYPE.INSECT, 
		FOODTYPE.SEEDS,
		FOODTYPE.HORRIBLE,
		FOODTYPE.ROUGHAGE,
		FOODTYPE.GEMS,
	}
}

Next, you still need to assign the new food type to all of the gems' prefabs. Though after thinking on it, you're going to have to do a similar hack like they did for berries and smallbirds, because by reassigning the gems' food type you'll make them unedible to things that eat elemental type foods.

The hack they did was basically force assigning the "edible_" + food type tag to berries and then hard coded removing the tag in the OnRemoveFromEntity() function in the edible component. So what you're gunna wanna do first is make sure the tables you made for your food group to your modmain (which will require the GLOBAL definitions mentioned prior) to make sure they're defined first. Then, below those tables add this code:

function EdibleCompPostInit(comp)
	old_OnRemoveFromEntity = comp.OnRemoveFromEntity

	comp.OnRemoveFromEntity = function(self)
		old_OnRemoveFromEntity(self)
		self.inst:RemoveTag("edible_"..FOODTYPE.GEMS)
	end
end
AddComponentPostInit("edible", EdibleCompPostInit)

function GemPostInit(inst)
	inst:AddTag("edible_"..FOODTYPE.GEMS)
end
-- You can run a loop to iterate through each gem, this was just done quickly lol
AddPrefabPostInit("redgem", GemPostInit)
AddPrefabPostInit("bluegem", GemPostInit)
AddPrefabPostInit("purplegem", GemPostInit)
AddPrefabPostInit("orangegem", GemPostInit)
AddPrefabPostInit("yellowgem", GemPostInit)
AddPrefabPostInit("greengem", GemPostInit)
AddPrefabPostInit("opalpreciousgem", GemPostInit)

Try that and see if that fixes it for you :) 

Link to comment
Share on other sites

I did the thing of moving the FOODGROUP code in the modmain and I made the change with the local NOMS but I am still getting the same error message. 

EDIT: Nvm that works, thanks


I understand the code you have for the FOODTYPE.GEM but how would I divide and insert into my mod? 

Edited by SomeoneStrange
Link to comment
Share on other sites

2 hours ago, SomeoneStrange said:

I understand the code you have for the FOODTYPE.GEM but how would I divide and insert into my mod?

You mean how to define the FOODTYPE.GEM variable in your mod? All you have to do as far as that goes is assign FOODTYPE.GEM (or GLOBAL.FOODTYPE.GEM if you haven't already declared it in a local variable) a string. It honestly can be any string you like, but the devs just chose to name the string the same name as the key, so FOODTYPE.MEAT has the string "MEAT" as a value.

local FOODTYPE = GLOBAL.FOODTYPE
FOODTYPE.GEM = "GEM"

As long as you use the same address for it whenever you need to call it (in this case FOODTYPE.GEMS) your string will just get concatenated on to the "edible_" tag it receives through the edible component. Then the game tests whether or not your character can eat the particular item by setting tags to the player based on SetDiet's 1st argument via concatenating "_eater" on the end of your string, then comparing the "edible_" and the "_eater" tags of the same name. If its a match in the first table (1st argument passed in SetDiet), the game then determines which state to go to depending on the tables passed through in the second table (2nd argument of SetDiet, or just the 1st argument if the 2nd doesn't exist), if the item exists in the table to be eaten you'll eat it, if it doesn't your character will get grossed out and (should) say the ANNOUNCE_EAT.INVALID string attached to their character.

Edited by w00tyd00d
Link to comment
Share on other sites

I meant like what file do I put this into? like mycharacter.lua or gems.lua or modmain

I assumed it goes into the gems.lua but this line is not working 

inst.AddComponentPostInit("edible", EdibleCompPostInit)

Something about how its not a function

Edited by SomeoneStrange
Link to comment
Share on other sites

3 minutes ago, SomeoneStrange said:

Alright most of it runs smoothly except for:


function GemPostInit(inst)
	inst:AddTag("edible_"..FOODTYPE.GEMS)
end

its says GEMS is a nil value

Haha typo on my part, I had typed "FOODTYPE.GEM" in my example above, not "FOODTYPE.GEMS"

Change that up and it should work fine ;) 

Link to comment
Share on other sites

7 minutes ago, SomeoneStrange said:

Ah GEM is still a nil value.
Was I suppose to add anything to the gem.lua?

Nah you've already added what you needed to add to the gem prefabs.

Did you make sure to change all of your variables to have the same matching name? They should all either be FOODTYPE.GEM or FOODTYPE.GEMS (again, the string value attached to it is arbitrary so it doesn't matter what you call that)

Edited by w00tyd00d
Link to comment
Share on other sites

The GEM in modmain is still a nil value.
To be specific what was added to the gem.lua?

EDIT: NEVERMIND it works!

I forgot the line 

FOODTYPE.GEMS = "GEMS"

Thank you so much for all the help!

 

Oh one last thing to help with. Now that all the above is all set. Is there a way to remove that gem tag on a certain gem if an if statement for the character is fulfilled?
something like
 

	if food and food.components.edible and food.components.edible.foodtype == FOODTYPE.GEMS then
        if food.prefab == "redgem" then
			if inst.components.temperature.inherentinsulation < 200 then
				inst.components.temperature.inherentinsulation = inst.components.temperature.inherentinsulation + 20
			elseif inst.components.temperature.inherentinsulation == 200 then
				--REMOVE TAG FOR RED GEM
			end

Ya this mod is complex but I think it's something different to put on the work shop

Edited by SomeoneStrange
Link to comment
Share on other sites

2 minutes ago, SomeoneStrange said:

The GEM in modmain is still a nil value.

Do you mind posting the crash log you're getting? I'll need to see where the crash is stemming from

4 minutes ago, SomeoneStrange said:

To be specific what was added to the gem.lua?

Gem.lua is only a root script for all of the gem prefabs. Since all of the gems pretty much have the same traits and characteristics, other than their sprites, they all just use the same initialization tree. However, at the bottom of the script you'll notice that it generates 7 different prefabs, all with their own prefix (all inheriting the "gem" or "preciousgem" concatenation on the end of their name), so you must identify each gem by the name of their prefab even though they all share, more or less, the same exact code under the hood.

For your particular case, all you needed to add to your script as far as the gems go was the "edible_"..FOODTYPE.GEM(S) tag as mentioned above. But yeah if I can get a copy of your crashlog I can try to see why it's still coming up as nil.

Link to comment
Share on other sites

52 minutes ago, SomeoneStrange said:

Oh no the code actually works I just forgot one line as seen above in my edit.

Ah okay, great! :) 

1 hour ago, SomeoneStrange said:

Oh one last thing to help with. Now that all the above is all set. Is there a way to remove that gem tag on a certain gem if an if statement for the character is fulfilled?

This should do the trick for you, unforunately I don't have time to test it atm but this should be what you're looking for:

function EaterCompPostInit(comp)
	local old_Eat = comp.Eat

	comp.Eat = function(self, food, feeder)
		if self.inst:HasTag("<TAG UNIQUE TO YOUR CHAR>") then
      			if food.prefab == "redgem" then
				if self.inst.components.temperature.inherentinsulation < 200 then
					self.inst.components.temperature.inherentinsulation = self.inst.components.temperature.inherentinsulation + 20
					if inst.components.temperature.inherentinsulation >= 200 then -- switched this to >= for overflow failsafe
						food:RemoveTag("edible_"..FOODTYPE.GEMS)
					end
				end
        		end
		end
		return old_Eat(self, food, feeder)	-- must return for actionfail callback
	end
end
AddComponentPostInit("eater", EaterCompPostInit)

Keep in mind this assumes the prefab item listed is intended to be edible. Be careful of what prefabs you put there and make sure they're only ones you want your character to consume (else the effect will still go through even though the item doesn't get eaten). Any other specific prefabs you would want to have an effect applied you can just write another if statement using the prefab's name like the example above.

Edited by w00tyd00d
Link to comment
Share on other sites

Ya I can't get a crash report for this one, my game keeps crashing. Isn't there a way to do something like
 

function RemoveGemPostInit(inst)
	inst:RemoveTag("edible_"..FOODTYPE.GEMS)
end

if self.inst:HasTag("DOLL") and self.inst.components.temperature.inherentinsulation >= 100
	RemovePrefabPostInit("redgem", RemoveGemPostInit)
end

 

Link to comment
Share on other sites

@SomeoneStrange Are you testing on a world that has caves or no?

If the world doesn't have caves, post the client_log.txt located in the path: "Documents\Klei\DoNotStarveTogether\client_log.txt"

If the world has caves, send me the server_log.txt located in the path: "Documents\Klei\DoNotStarveTogether\Cluster_#\Master\server_log.txt"
where "Cluster_#" is the number of what world slot you're working from.

Post either of those once you get the crash and are booted out of game

(also try to mention or quote me so I get the forum notification that you've responded ;) )

Edited by w00tyd00d
Link to comment
Share on other sites

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
 Share

×
  • Create New...