Jump to content

Recommended Posts

Howdy, I'm making a custom character and I need help. (Big surprise) I'm not exactly great at coding either, but I've come this far, SO!

Basically I'm making a dragon. In trying to make him more balanced, I thought that the only way to make him gain sanity could be...from hoarding treasures? I mean, I don't think I've seen this before. Maybe like if there's a chest nearby with gold or gems inside, or even if you just put them on the ground, the character could regain a little sanity over time. Is that possible? if all else fails, I could just make him regain sanity from just picking up treasures, but that'd be less interesting to me. I mean, just think of how cute it would be to see screenshots of people's hoards. Anyway, is that possible? And if so, could someone be kind enough to help me with it? :D

Well, after some research I tried something (so you guys don't have to do the whole work while I sit back)

I took Willow's fire sanity gain thing and put it under my master_postinit. it doesn't seem to do anything though, or if it is, it's not big enough to notice for one gold nugget. here's the code:

	--Hoard sanity buff	local function sanityfn(inst)	local x,y,z = inst.Transform:GetWorldPosition()        local delta = 0    local max_rad = 10    local ents = TheSim:FindEntities(x,y,z, max_rad, {"goldnugget","redgem","bluegem","purplegem","orangegem","yellowgem","greengem",})    for k,v in pairs(ents) do        local sz = TUNING.SANITYAURA_TINY * math.min(max_rad, rad) / max_rad                            local distsq = inst:GetDistanceSqToInst(v)        delta = delta + sz/math.max(1, distsq)     end         return delta

if I ever get this to work, I'd still have to find a way to adjust the rate of the sanity increase, and if possible, to give slightly higher sanity increase rates to rarer items (like gems) or lower ones to less valuable items.

Alright, okay, whew. so after a lot of digging and experimenting, I've got something that works.

local function sanityfn(inst)    local x,y,z = inst.Transform:GetWorldPosition()        local delta = 0    local max_rad = 10    local ents = TheSim:FindEntities(x,y,z, max_rad, {"goldnugget"})    for k,v in pairs(ents) do        local sz = -TUNING.SANITYAURA_TINY                            local distsq = inst:GetDistanceSqToInst(v)        delta = delta + sz/math.max(1, distsq)     end         return delta	end	local function CalcSanityAura(inst, observer)	if observer.prefab == "toaster" then       return GLOBAL.TUNING.SANITYAURA_TINY	endendlocal function AddSanityAura(inst)    inst:AddComponent("sanityaura")    inst.components.sanityaura.aurafn = CalcSanityAura end

and then I added "AddPrefabPostInit("goldnugget", AddSanityAura)" at the end of my modmain.

 

I'm not sure how big the aura is, I don't even know if the sanity gain stacks or not, I also don't know how to tune the rate of the sanity gain more precisely and if the gain actually affects my character (toaster) and not everyone, but I do know that there was a gold nugget on the ground and it gave me back sanity. That's a start! 

Now I just need some help figuring out how to adjust all that depending on the item. I'm guessing I'll have to put multiple CalcSanityAura's with a different rate for every item, except all I know is tiny, med and huge, and I don't think that'll be enough... is it something about dapperness? 

To my knowledge your sanityfn function is doing nothing, unless you have this in your master_postinit:

    inst.components.sanity.custom_rate_fn = sanityfn

 
Looking at spider.lua this is what it uses:

local function CalcSanityAura(inst, observer)    return observer:HasTag("spiderwhisperer") and 0 or inst.components.sanityaura.auraend    inst:AddComponent("sanityaura")    inst.components.sanityaura.aurafn = CalcSanityAurainst.components.sanityaura.aura = -TUNING.SANITYAURA_SMALL

 
So one way of doing it would be this:
In your modmain.lua

local function CalcSanityAura(inst, observer)    if observer.prefab == "toaster" then       return GLOBAL.TUNING.SANITYAURA_TINY    endendlocal function AddSanityAura(inst)    inst:AddComponent("sanityaura")    inst.components.sanityaura.aurafn = CalcSanityAuraendAddPrefabPostInit("goldnugget", AddSanityAura)

And repeating that for other kinds of treasures.
To change the sanity value all you would need to do is change the third line to one of the other tuning values, such as GLOBAL.TUNING.SANITYAURA_MEDIUM, you can even do something like (GLOBAL.TUNING.SANITYAURA_MEDIUM * 0.5).

 

For reference, in the tuning.lua:

		SANITYAURA_TINY = 100/(seg_time*32),		SANITYAURA_SMALL_TINY = 100/(seg_time*20),		SANITYAURA_SMALL = 100/(seg_time*8),		SANITYAURA_MED = 100/(seg_time*5),		SANITYAURA_LARGE = 100/(seg_time*2),		SANITYAURA_HUGE = 100/(seg_time*.5),

For comparison there are the dapperness values:

		DAPPERNESS_TINY = 100/(day_time*15),		DAPPERNESS_SMALL = 100/(day_time*10),		DAPPERNESS_MED = 100/(day_time*6),		DAPPERNESS_MED_LARGE = 100/(day_time*4.5),		DAPPERNESS_LARGE = 100/(day_time*3),		DAPPERNESS_HUGE = 100/(day_time),

Which for dapperness values translate to:

Tiny: 1.33:60s
Small: 2:60s
Med: 3.33:60s
Large: 6.66:60s
Huge: 20:60s

 
Another way would be with Willow's function (which I don't know for sure if this second way is going to work):
In your character's mod file

local GOLD_NUGGET_SANITY = TUNING.SANITYAURA_TINYlocal REDGEM_SANITY = TUNING.SANITYAURA_MEDIUMlocal function sanityfn(inst)    local x, y, z = inst.Transform:GetWorldPosition()     local delta = 0    local max_rad = 10    local ents = TheSim:FindEntities(x, y, z, max_rad, { "goldnugget" }, { "redgem" })    for i, v in ipairs(ents) do        if v.prefab == "goldnugget" then            local rad = 1            local sz = TUNING.SANITYAURA_TINY * math.min(max_rad, rad) / max_rad            local distsq = inst:GetDistanceSqToInst(v) - 9            -- shift the value so that a distance of 3 is the minimum            delta = delta + sz / math.max(1, distsq)        elseif v.prefab == "redgem" then		    local rad = 1            local sz = TUNING.SANITYAURA_TINY * math.min(max_rad, rad) / max_rad            local distsq = inst:GetDistanceSqToInst(v) - 9            delta = delta + sz / math.max(1, distsq)		end	end    return deltaendlocal function master_postinit(inst)    inst.components.sanity.custom_rate_fn = sanityfnend
Edited by DrSmugleaf

 

To my knowledge your sanityfn function is doing nothing, unless you have this in your master_postinit:

    inst.components.sanity.custom_rate_fn = sanityfn

 

Looking at spider.lua this is what it uses:

local function CalcSanityAura(inst, observer)    return observer:HasTag("spiderwhisperer") and 0 or inst.components.sanityaura.auraend    inst:AddComponent("sanityaura")    inst.components.sanityaura.aurafn = CalcSanityAurainst.components.sanityaura.aura = -TUNING.SANITYAURA_SMALL

 

So one way of doing it would be this:

In your modmain.lua

local function CalcSanityAura(inst, observer)    if observer.prefab == "toaster" then       return GLOBAL.TUNING.SANITYAURA_TINY    endendlocal function AddSanityAura(inst)    inst:AddComponent("sanityaura")    inst.components.sanityaura.aurafn = CalcSanityAuraendAddPrefabPostInit("goldnugget", AddSanityAura)

And repeating that for other kinds of treasures.

To change the sanity value all you would need to do is change the third line to one of the other tuning values, such as GLOBAL.TUNING.SANITYAURA_MEDIUM, you can even do something like (GLOBAL.TUNING.SANITYAURA_MEDIUM * 0.5).

 

For reference, in the tuning.lua:

		SANITYAURA_TINY = 100/(seg_time*32),		SANITYAURA_SMALL_TINY = 100/(seg_time*20),		SANITYAURA_SMALL = 100/(seg_time*8),		SANITYAURA_MED = 100/(seg_time*5),		SANITYAURA_LARGE = 100/(seg_time*2),		SANITYAURA_HUGE = 100/(seg_time*.5),

For comparison there are the dapperness values:

		DAPPERNESS_TINY = 100/(day_time*15),		DAPPERNESS_SMALL = 100/(day_time*10),		DAPPERNESS_MED = 100/(day_time*6),		DAPPERNESS_MED_LARGE = 100/(day_time*4.5),		DAPPERNESS_LARGE = 100/(day_time*3),		DAPPERNESS_HUGE = 100/(day_time),

Which for dapperness values translate to:

Tiny: 1.33:60s

Small: 2:60s

Med: 3.33:60s

Large: 6.66:60s

Huge: 20:60s

 

Another way would be with Willow's function (which I don't know for sure if this second way is going to work):

In your character's mod file

local GOLD_NUGGET_SANITY = TUNING.SANITYAURA_TINYlocal REDGEM_SANITY = TUNING.SANITYAURA_MEDIUMlocal function sanityfn(inst)    local x, y, z = inst.Transform:GetWorldPosition()     local delta = 0    local max_rad = 10    local ents = TheSim:FindEntities(x, y, z, max_rad, { "goldnugget" }, { "redgem" })    for i, v in ipairs(ents) do        if v.prefab == "goldnugget" then            local rad = 1            local sz = TUNING.SANITYAURA_TINY * math.min(max_rad, rad) / max_rad            local distsq = inst:GetDistanceSqToInst(v) - 9            -- shift the value so that a distance of 3 is the minimum            delta = delta + sz / math.max(1, distsq)        elseif v.prefab == "redgem" then		    local rad = 1            local sz = TUNING.SANITYAURA_TINY * math.min(max_rad, rad) / max_rad            local distsq = inst:GetDistanceSqToInst(v) - 9            delta = delta + sz / math.max(1, distsq)		end	end    return deltaendlocal function master_postinit(inst)    inst.components.sanity.custom_rate_fn = sanityfnend

First of all, thank you for having taken the time to help with this. I had pretty much given up until you replied.

The problem with the first method is that the radius for the nuggets is way too small. having a hoard would require a bigger radius. I haven't tested it online yet.

the second method seemed to work, until I went online and tested it with a friend. he crashed (he was host) and It said there was a lua error because there was "an attempt to perform arithmetic on a nil value" in sanityfn. I think it was because I tried to change the rate of sanity in the second code, but it wasn't written the same way. why it worked as host but not as client is beyond me. 

 

there's one thing I'm not quite getting. the second code does not work on its own. it will only work with the first and second code combined. Is that intended?

like I said, I'm still kinda new, and I'm not sure if the second code is meant to be placed entirely inside master_postinit, but that's what I did anyway.

radius

 

local max_rad = 10

 

The max_rad in willows sanity code is basically limiting the distance at which fire actually effects willows sanity, if you raise this number, it causes the effect at a closer distance.  The arithmetic going on is basically making the effect weaker or stronger based on the distance to the fire (in willows case) or the treasure (in your characters case)

 

Raise your max_rad to a radius that you would want the hoard to reach out for.  It can be as big as you want, though you probably also want to check if the items are in the inventory of a chest correct?

 

chests and backpacks have an inventory component called container, while players and other entities in the world like pigmen have regular inventory's.

 

I believe if you do 

if v.components.inventoryitem.owner and v.components.inventoryitem.owner.components.container then

That will check to see if the item itself is inside a type of container, whether it's a backpack or a chest.  I haven't tested it though but generally speaking it checks to see if the item has an owner and whether that owner has the container component.  But more importantly, it will not do anything if it's either on the floor or being held by someone unless it's in their backpack.  And if you want to double check on that, you can see if the backpack has an owner as well, it ends up looking complicated at that point though.

 

Also, when you get a crash with a lua error, posting the log helps us find the cause of it directly.  I look at the code but I can't immediately find the cause of the crash, I could probably notice it if I study it long enough but the error log points directly to the section of code where the error occur's which is how us modders find the exact cause of the problem.

 

 

 

like I said, I'm still kinda new, and I'm not sure if the second code is meant to be placed entirely inside master_postinit, but that's what I did anyway.

 

 

No big deal, if your wondering how the code works or why it wouldn't work, post your character prefab file and modmain so we can see what you did and explain whats happening.  It's not uncommon for some code to be put in improperly and the whole thing gets messed up.  I just helped klei find a bug they did with the lightning rod in the caves beta, even the pro's make mistakes.

 

The important part is know how to read the error logs so you can look exactly where the problem is, find out whats wrong, and fix it.

 

 

Edit:

local ents = TheSim:FindEntities(x, y, z, max_rad, { "goldnugget" }, { "redgem" })
 

I just noticed that this is being done wrong, you have Find entities looking for item's that have the "tag" goldnugget, while ignoring anything that has the tag "redgem"

 

See willow isn't looking for prefabs called fire, she's looking for anything with the fire tag, which is anything that is currently burning no matter what it is.

 

Instead what you should do is something like this

local ents = TheSim:FindEntities(x, y, z, max_rad, { "dragontreasure" })

While in modmain have this

local treasurelist = {    "goldnugget",    "redgem",    "bluegem",}for k,v in pairs(treasurelist) doAddPrefabPostInit(v,function(inst)    inst:AddTag("dragontreasure")end)end

This will have your character look for prefabs in the area that have the dragontreasure tag.  While ignoring every other prefab.

Edited by Zackreaver

Also, when you get a crash with a lua error, posting the log helps us find the cause of it directly. 

 

Alright, so I was finally able to save up a little time to test it online with a friend, as client. 

 

Repro steps

>start the game and have a friend start the server while both have the mod activated.

>Join game as client and select "Toaster" character.

>craft pickaxe, find gold nugget rock.

>mine it

>notice that the game crashes.

 

Crash log: 

[00:05:11]: [string "scripts/components/sanity.lua"]:293: attempt to perform arithmetic on a nil valueLUA ERROR stack traceback:scripts/components/sanity.lua:293 in (method) Recalc (Lua) <262-319>   self =      rate_modifier = 1      dapperness_mult = 1      _oldpercent = 1      neg_aura_mult = 0      rate = 0      _oldissane = true      night_drain_mult = 0      inst = 115622 - xenomorph (valid:true)      fxtime = 0      dapperness = 0      _ = table: 25561570      sanity_penalties = table: 25561818   dt = 0.033333335071802   total_dapperness = 0   dapper_delta = 0   moisture_delta = 0   light_delta = 0   aura_delta = 0   x = -118.72571563721   y = 0   z = 57.610095977783   ents = table: 0E716698   i = 5   v = 116910 - goldnugget (valid:true)scripts/components/sanity.lua:236 in (method) OnUpdate (Lua) <231-245>   self =      rate_modifier = 1      dapperness_mult = 1      _oldpercent = 1      neg_aura_mult = 0      rate = 0      _oldissane = true      night_drain_mult = 0      inst = 115622 - xenomorph (valid:true)      fxtime = 0      dapperness = 0      _ = table: 25561570      sanity_penalties = table: 25561818   dt = 0.033333335071802scripts/update.lua:183 in () ? (Lua) <146-219>   dt = 0.033333335071802   tick = 3963   k = 115622   v = 115622 - xenomorph (valid:true)   cmp = table: 255617A0[00:05:11]: [string "scripts/components/sanity.lua"]:293: attempt to perform arithmetic on a nil valueLUA ERROR stack traceback:    scripts/components/sanity.lua:293 in (method) Recalc (Lua) <262-319>    scripts/components/sanity.lua:236 in (method) OnUpdate (Lua) <231-245>    scripts/update.lua:183 in () ? (Lua) <146-219>

My friend was trying out a Xenomorph character mod, so that's why there's xenomorph all over.

 

And here's my modmain and prefab, because why not.

 

Modmain:

PrefabFiles = {	"toaster",}Assets = {    Asset( "IMAGE", "images/saveslot_portraits/toaster.tex" ),    Asset( "ATLAS", "images/saveslot_portraits/toaster.xml" ),    Asset( "IMAGE", "images/selectscreen_portraits/toaster.tex" ),    Asset( "ATLAS", "images/selectscreen_portraits/toaster.xml" ),	    Asset( "IMAGE", "images/selectscreen_portraits/toaster_silho.tex" ),    Asset( "ATLAS", "images/selectscreen_portraits/toaster_silho.xml" ),    Asset( "IMAGE", "bigportraits/toaster.tex" ),    Asset( "ATLAS", "bigportraits/toaster.xml" ),		Asset( "IMAGE", "images/map_icons/toaster.tex" ),	Asset( "ATLAS", "images/map_icons/toaster.xml" ),		Asset( "IMAGE", "images/avatars/avatar_toaster.tex" ),    Asset( "ATLAS", "images/avatars/avatar_toaster.xml" ),		Asset( "IMAGE", "images/avatars/avatar_ghost_toaster.tex" ),    Asset( "ATLAS", "images/avatars/avatar_ghost_toaster.xml" ),	Asset( "SOUNDPACKAGE", "sound/toaster.fev"),    Asset( "SOUND", "sound/toaster.fsb"),}local require = GLOBAL.requirelocal STRINGS = GLOBAL.STRINGS -- The character select screen linesSTRINGS.CHARACTER_TITLES.toaster = "The toasty lizard"STRINGS.CHARACTER_NAMES.toaster = "Toaster"STRINGS.CHARACTER_DESCRIPTIONS.toaster = "\nImmune to fire\n.", "\nCan hoard treasure to restore sanity\n.", "\nCarnivorous\n."STRINGS.CHARACTER_QUOTES.toaster = "\"Unless it's meat, it's for the weak!\""-- Custom speech stringsSTRINGS.CHARACTERS.TOASTER = require "speech_toaster"-- The character's name as appears in-game STRINGS.NAMES.TOASTER = "Toast"-- The default responses of examining the characterSTRINGS.CHARACTERS.GENERIC.DESCRIBE.TOASTER = {	GENERIC = "A handsome dragon.",	ATTACKER = "As quick as an arrow",	MURDERER = "TRAITOR!!",	REVIVER = "YEAAAH TEAMWORK!",	GHOST = "Welp, he died.",}AddMinimapAtlas("images/map_icons/toaster.xml")-- Add mod character to mod character list. Also specify a gender. Possible genders are MALE, FEMALE, ROBOT, NEUTRAL, and PLURAL.--Hoard testlocal function CalcSanityAura(inst, observer)    if observer.prefab == "toaster" then       return GLOBAL.TUNING.SANITYAURA_TINY    endend local function AddSanityAura(inst)    inst:AddComponent("sanityaura")    inst.components.sanityaura.aurafn = CalcSanityAuraendlocal treasurelist = {    "goldnugget",    "redgem",    "bluegem",} for k,v in pairs(treasurelist) do	AddPrefabPostInit(v,function(inst)    inst:AddTag("dragontreasure")end)endAddPrefabPostInit("goldnugget", AddSanityAura)AddModCharacter("toaster", "MALE")RemapSoundEvent( "dontstarve/characters/toaster/death_voice", "toaster/characters/toaster/death_voice" )RemapSoundEvent( "dontstarve/characters/toaster/hurt", "toaster/characters/toaster/hurt" )RemapSoundEvent( "dontstarve/characters/toaster/talk_LP", "toaster/characters/toaster/talk_LP" )

Prefab:

local MakePlayerCharacter = require "prefabs/player_common"local assets = {        Asset( "ANIM", "anim/player_basic.zip" ),        Asset( "ANIM", "anim/player_idles_shiver.zip" ),        Asset( "ANIM", "anim/player_actions.zip" ),        Asset( "ANIM", "anim/player_actions_axe.zip" ),        Asset( "ANIM", "anim/player_actions_pickaxe.zip" ),        Asset( "ANIM", "anim/player_actions_shovel.zip" ),        Asset( "ANIM", "anim/player_actions_blowdart.zip" ),        Asset( "ANIM", "anim/player_actions_eat.zip" ),        Asset( "ANIM", "anim/player_actions_item.zip" ),        Asset( "ANIM", "anim/player_actions_uniqueitem.zip" ),        Asset( "ANIM", "anim/player_actions_bugnet.zip" ),        Asset( "ANIM", "anim/player_actions_fishing.zip" ),        Asset( "ANIM", "anim/player_actions_boomerang.zip" ),        Asset( "ANIM", "anim/player_bush_hat.zip" ),        Asset( "ANIM", "anim/player_attacks.zip" ),        Asset( "ANIM", "anim/player_idles.zip" ),        Asset( "ANIM", "anim/player_rebirth.zip" ),        Asset( "ANIM", "anim/player_jump.zip" ),        Asset( "ANIM", "anim/player_amulet_resurrect.zip" ),        Asset( "ANIM", "anim/player_teleport.zip" ),        Asset( "ANIM", "anim/wilson_fx.zip" ),        Asset( "ANIM", "anim/player_one_man_band.zip" ),        Asset( "ANIM", "anim/shadow_hands.zip" ),        Asset( "SOUND", "sound/sfx.fsb" ),        Asset( "SOUND", "sound/wilson.fsb" ),        Asset( "ANIM", "anim/beard.zip" ),        Asset( "ANIM", "anim/toaster.zip" ),        Asset( "ANIM", "anim/ghost_toaster_build.zip" ),}local prefabs = {}-- Custom starting itemslocal start_inv = {}-- When the character is revived from humanlocal function onbecamehuman(inst)	-- Set speed when loading or reviving from ghost (optional)	inst.components.locomotor.walkspeed = 4	inst.components.locomotor.runspeed = 6end-- When loading or spawning the characterlocal function onload(inst)    inst:ListenForEvent("ms_respawnedfromghost", onbecamehuman)    if not inst:HasTag("playerghost") then        onbecamehuman(inst)    endend-- This initializes for both the server and client. Tags can be added here.local common_postinit = function(inst) 	-- Minimap icon	inst.MiniMapEntity:SetIcon( "toaster.tex" )	end-- This initializes for the server only. Components are added here.local master_postinit = function(inst)	-- choose which sounds this character will play	inst.components.eater:SetDiet({ FOODGROUP.OMNI }, { FOODTYPE.MEAT })	inst.components.eater.strongstomach = true	inst.soundsname = "toaster"	inst.components.sanity.night_drain_mult = 1.25	inst.components.temperature.mintemp = -30	inst.components.temperature.maxtemp = 60	-- Uncomment if "wathgrithr"(Wigfrid) or "webber" voice is used    --inst.talker_path_override = "dontstarve_DLC001/characters/"		-- Stats		inst.components.health:SetMaxHealth(150)	inst.components.hunger:SetMax(150)	inst.components.sanity:SetMax(100)	-- Damage multiplier (optional)    inst.components.combat.damagemultiplier = 1.25	--Fire Resistance	inst.components.health.fire_damage_scale = 0		inst.OnLoad = onload    inst.OnNewSpawn = onload	--Treasure Hoarding	local function sanityfn(inst)    local x, y, z = inst.Transform:GetWorldPosition()     local delta = 0    local max_rad = 10    local ents = TheSim:FindEntities(x, y, z, max_rad, { "dragontreasure" })       for i, v in ipairs(ents) do        if v.prefab == "goldnugget" then            local rad = 10            local sz = TUNING.SANITYAURA_TINY * math.min(max_rad, rad) / max_rad            local distsq = inst:GetDistanceSqToInst(v) - 9            -- shift the value so that a distance of 3 is the minimum            delta = delta + sz / math.max(1, distsq)        elseif v.prefab == "redgem" then            local rad = 10            local sz = TUNING.SANITYAURA_TINY * math.min(max_rad, rad) / max_rad            local distsq = inst:GetDistanceSqToInst(v) - 9            delta = delta + sz / math.max(1, distsq)        end    end    return deltaendlocal function master_postinit(inst)    inst.components.sanity.custom_rate_fn = sanityfnendend return MakePlayerCharacter("toaster", prefabs, assets, common_postinit, master_postinit, start_inv)
Edited by ToasterRepairUnit

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