Jump to content

Perk help!


Recommended Posts

So I’m working on my very first character mod. At the moment, I’m doing the script, but I know that afterwards comes the more complex parts. What I need is some help.

This character loses sanity when there’s more than two people around, slowly restores sanity when alone, and the stuff they make in the crock pot restores more than it usually does. The stats are going to be 150 health, 200 sanity, and 150 hunger. Damage will be average and starting items are going to be 3 trail mixes and winter hat. If someone could help me out with the perks and stuff, that’d be great!

Link to comment
Share on other sites

Firstly, welcome to modding for Don't Starve (Together) :) The path onto which you are about to tread will be annoying and fraught with frustration lest you acquire the proper training. If you aren't versed in LUA and haven't done any modding for DS/DST before, I highly recommend you take a run through my newcomer post. I compiled a bunch of starter information, like a link to a great LUA Crash Course, and where to find tutorials and more information on the forums and, probably most important of all, how you can debug your code and how to find the logs with information about crashes and other errors concerning your mod.

Now that that's out of the way, the perks aren't too crazy, so we should be able to help with those. Let's tackle the food first. I have some questions about what you wrote. You could mean, that any food made in a crockpot (also by other players) will give the character more stats (so we change the character to receive extra stats when eating certain items, which is easy).

You could also mean that your character has to be the one making the food in order to infuse it with increased stats. This is not trivial, since food is stackable, and any changes to a food item will be erased when added to an existing stack, or you can add some code that then applies your changes to the entire stack. Both of which are not favorable. Fixing that will require much more work, if it is at all possible. In order to achieve exactly what you want, I'd like more details about this perk. Some solutions will be significantly more difficult to implement than others, but try to describe your ideal scenario, and then we can see about how to find a good compromise.

The sanity aura thing is something we've done many times on the forum. Put this at the bottom of your character's master_postinit.

	-- DoPeriodicTask calls the given function every X seconds.
	-- I set it to 1.0. You can set it to e.g. 0.5 seconds if you want.
	inst:DoPeriodicTask(1.0, function(inst)
		-- Do nothing if the player is dead.
		if inst.components.health:IsDead() or inst:HasTag("playerghost") then
			return
		end
		
		-- Store the position of the player in x, y, z variables.
		local x,y,z = inst.Transform:GetWorldPosition()
		
		-- Description of important function, which finds specific entities within a range:
		-- TheSim:FindEntities(x, y, z, radius, mustHaveTags, cantHaveTags, mustHaveOneOfTheseTags)
		
		-- We have limited it to entities with the "player" tag, that are also not ghosts or otherwise in limbo.
		-- I have set the radius to be 10. You can set it to whatever radius you want.
		local players = TheSim:FindEntities(x, y, z, 10, {"player"}, {"playerghost", "INLIMBO"}, nil)

		-- We want to count the list of entities we have found. (I don't trust the # counting method of tables)
		local count = 0
		for _ in pairs(players) do count = count + 1 end
		
		-- The player himself/herself is always there, so if three players are there, then there are two others.
		-- If there is only one, then they are alone. SMALL is a tiny bonus, where MED is larger.
		-- You can use whichever numbers you want here e.g. DoDelta(-2.5)
		if count > 2 then
			inst.components.sanity:DoDelta(-TUNING.SANITYAURA_MED)
		elseif count == 1 then
			inst.components.sanity:DoDelta(TUNING.SANITYAURA_SMALL)
		end
	end)

 

Edited by Ultroman
Link to comment
Share on other sites

24 minutes ago, Ultroman said:

Sorry! Forgot to link to the newcomer post. Added a link. It is also here.

Thank you so much! I’m about halfway done with the script. Once I’m done, I’ll get right onto everything else! I’m hoping to graduate into making other characters from other games/shows. For now, I’m making as humble of a character for myself as possible.

Link to comment
Share on other sites

As for the food, I think it’s best if anything cooked in the crockpot would be more beneficial for my character. I don’t want this to be extremely overpowered and I want it to be as balanced as possible. I’m hoping that it would have Wortox’s voice too, but that should come later

Link to comment
Share on other sites

This should take care of the food perk. Just fill out the dictionary with values for all the different food prefabs you want to affect. If you just wanted all crockpot foods to give the same bonus, then there's a simpler way. But this is more flexible.

NOTE: The way eating is coded in the game, we can only apply alternate values AFTER the original food values have been applied to the player, so there may be some small error if the effect of original food value got clamped to min/max of sanity/health/hunger. Not much we can do about that without a substantial amount of extra code, but it could be corrected for.

-- Put this in your the master_postinit of you character LUA
inst.components.eater:SetOnEatFn(OnEat)


-- Put this somewhere above your character's master_postinit

-- food_bonuses is a dictionary with food prefab names as keys and other dictionaries as values.
-- The values are dictionaries which have stat-names as keys and the bonuses to each stat as values.
local food_bonuses = {
	twigs = { sanity = 10 },
	monsterlasagna = { health = 25, sanity = -10 },
	fishsticks = { health = 20, sanity = 20, hunger = 20 },
}

local function OnEat(inst, food)
	-- We look up the food bonus in out dictionary, using the prefab-variable (prefab identifier)
	-- of the item we are eating.
	local food_bonus = food_bonuses[food.prefab]
	
	-- If we found an entry in our food_bonuses dictionary for the food, apply the bonuses.
	if food_bonus ~= nil then
		-- For each of the stat-bonuses we check that there is actually a stat entry
		-- in the dictionary, before trying to apply it.
		
		if food_bonus["health"] then
			inst.components.health:DoDelta(food_bonus["health"])
		end
		if food_bonus["sanity"] then
			inst.components.sanity:DoDelta(food_bonus["sanity"])
		end
		if food_bonus["hunger"] then
			inst.components.hunger:DoDelta(food_bonus["hunger"])
		end
	end
end

 

Edited by Ultroman
Link to comment
Share on other sites

3 hours ago, Ultroman said:

This should take care of the food perk. Just fill out the dictionary with values for all the different food prefabs you want to affect. If you just wanted all crockpot foods to give the same bonus, then there's a simpler way. But this is more flexible.


-- Put this in your the master_postinit of you character LUA
inst.components.eater:SetOnEatFn(OnEat)


-- Put this somewhere above your character's master_postinit

-- food_bonuses is a dictionary with food prefab names as keys and other dictionaries as values.
-- The values are dictionaries which have stat-names as keys and the bonuses to each stat as values.
local food_bonuses = {
	twigs = { sanity = 10 }
	monsterlasagna = { health = 25, sanity = -10 },
	fishsticks = { health = 20, sanity = 20, hunger = 20 },
}

local function OnEat(inst, food)
	-- We look up the food bonus in out dictionary, using the prefab-variable (prefab identifier)
	-- of the item we are eating.
	local food_bonus = food_bonuses[food.prefab]
	
	-- If we found an entry in our food_bonuses dictionary for the food, apply the bonuses.
	if food_bonus ~= nil then
		-- For each of the stat-bonuses we check that there is actually a stat entry
		-- in the dictionary, before trying to apply it.
		
		if food_bonus["health"] then
			inst.components.hunger:DoDelta(food_bonus["health"])
		end
		if food_bonus["sanity"] then
			inst.components.hunger:DoDelta(food_bonus["sanity"])
		end
		if food_bonus["hunger"] then
			inst.components.hunger:DoDelta(food_bonus["hunger"])
		end
	end
end

 

Hey, uh, does this look good so far?

Screen Shot 2019-04-18 at 6.26.52 PM.png

Edited by MetaGiga
... oops. my name's there
Link to comment
Share on other sites

Not at all. You've destroyed your master_postinit by copy/pasting 80% my code into the middle of the master_postinit declaration :)

It's supposed to be something like this:

-- food_bonuses is a dictionary with food prefab names as keys and other dictionaries as values.
-- The values are dictionaries which have stat-names as keys and the bonuses to each stat as values.
local food_bonuses = {
	twigs = { sanity = 10 },
	monsterlasagna = { health = 25, sanity = -10 },
	fishsticks = { health = 20, sanity = 20, hunger = 20 },
}

local function OnEat(inst, food)
	-- We look up the food bonus in out dictionary, using the prefab-variable (prefab identifier)
	-- of the item we are eating.
	local food_bonus = food_bonuses[food.prefab]
	
	-- If we found an entry in our food_bonuses dictionary for the food, apply the bonuses.
	if food_bonus ~= nil then
		-- For each of the stat-bonuses we check that there is actually a stat entry
		-- in the dictionary, before trying to apply it.
		
		if food_bonus["health"] then
			inst.components.health:DoDelta(food_bonus["health"])
		end
		if food_bonus["sanity"] then
			inst.components.sanity:DoDelta(food_bonus["sanity"])
		end
		if food_bonus["hunger"] then
			inst.components.hunger:DoDelta(food_bonus["hunger"])
		end
	end
end


local function master_postinit(inst)
	-- lots of other code that you had in here

	-- Add this line at the bottom of master_postinit (just before the "end" that closes it)
	inst.components.eater:SetOnEatFn(OnEat)
end

 

Edited by Ultroman
Link to comment
Share on other sites

6 minutes ago, Ultroman said:

Not at all. You've destroyed your master_postinit by copy/pasting 80% my code into the middle of the master_postinit declaration :)

It's supposed to be something like this:


-- food_bonuses is a dictionary with food prefab names as keys and other dictionaries as values.
-- The values are dictionaries which have stat-names as keys and the bonuses to each stat as values.
local food_bonuses = {
	twigs = { sanity = 10 },
	monsterlasagna = { health = 25, sanity = -10 },
	fishsticks = { health = 20, sanity = 20, hunger = 20 },
}

local function OnEat(inst, food)
	-- We look up the food bonus in out dictionary, using the prefab-variable (prefab identifier)
	-- of the item we are eating.
	local food_bonus = food_bonuses[food.prefab]
	
	-- If we found an entry in our food_bonuses dictionary for the food, apply the bonuses.
	if food_bonus ~= nil then
		-- For each of the stat-bonuses we check that there is actually a stat entry
		-- in the dictionary, before trying to apply it.
		
		if food_bonus["health"] then
			inst.components.hunger:DoDelta(food_bonus["health"])
		end
		if food_bonus["sanity"] then
			inst.components.hunger:DoDelta(food_bonus["sanity"])
		end
		if food_bonus["hunger"] then
			inst.components.hunger:DoDelta(food_bonus["hunger"])
		end
	end
end


local function master_postinit(inst)
	-- lots of other code that you had in here

	-- Add this line at the bottom of master_postinit (just before the "end" that closes it)
	inst.components.eater:SetOnEatFn(OnEat)
end

 

Ahh okay! I luckily haven’t saved. I was suspicious about it, so I wanted to ask you first. Glad to know my hunch was right before I did the deed! I’ll fix it up now!

Link to comment
Share on other sites

3 minutes ago, Ultroman said:

Oh, and I forgot to add a comma at the end of the "twigs" line.

It's supposed to be


twigs = { sanity = 10 },

not


twigs = { sanity = 10 }

 

To confirm, the '--' is to be included, yeah?

Link to comment
Share on other sites

Just now, Ultroman said:

-- means that the rest of the line is to be considered a comment and thus should be ignored by the code compiler. Not sure which -- you're talking about, but the lines I included with -- are just comments for you.

Okay! Thanks! Now to get back to work! You're a really big help!

Link to comment
Share on other sites

On 19.4.2019 at 3:09 AM, MetaGiga said:

Okay! Thanks! Now to get back to work! You're a really big help!

Hey m8. I made an error when I wrote the code originally. I had put

		if food_bonus["health"] then
			inst.components.hunger:DoDelta(food_bonus["health"])
		end
		if food_bonus["sanity"] then
			inst.components.hunger:DoDelta(food_bonus["sanity"])
		end
		if food_bonus["hunger"] then
			inst.components.hunger:DoDelta(food_bonus["hunger"])
		end

when it should be

		if food_bonus["health"] then
			inst.components.health:DoDelta(food_bonus["health"])
		end
		if food_bonus["sanity"] then
			inst.components.sanity:DoDelta(food_bonus["sanity"])
		end
		if food_bonus["hunger"] then
			inst.components.hunger:DoDelta(food_bonus["hunger"])
		end

I have corrected it in my other posts.

Edited by Ultroman
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...