Jump to content

Custom sanity system for character?


Recommended Posts

I recently got back into modding for this game after a several year hiatus. I'm currently making a character mod and I want to implement a sanity system where killing a mob grants a non-stacking buff of slight sanity gain for 12 hours. If the character has gone 24 hours without killing they speak a line of dialogue and they lose sanity at a fixed rate. If the character has gone 48 hours without killing they speak a different line of dialogue and lose sanity at a greater rate indefinitely. Killing immediately resets the timer on this system to 0, at which point the sanity loss will start again after another 24 hours. Is there a way I can implement such a dynamic into my character mod?

Link to comment
Share on other sites

I whipped up this code right now so IDK 100% if it will work or crash, but you can test it hopefully it work

 

put all this code inside yourcharacter.lua inside the master_postinit

Spoiler

if inst.secs_since_killed == nil then inst.secs_since_killed = 0 end -- Add value if doesn't exist

inst:DoPeriodicTask(1, Secs_Since_Killed)
inst.components.sanity.custom_rate_fn = SanityFN

inst:ListenForEvent("killed", Killed)
inst:ListenForEvent("murdered", Killed)

inst.OnSave = OnSave
inst.OnLoad = OnLoad

and put all these code inside yourcharacter.lua above the master_postinit

Spoiler

local KILL_DEBUFF1 = 480 -- 480 seconds = 8 minutes = full DST day
local KILL_DEBUFF2 = 960 -- 960 seconds = 16 minutes = 2 DST day

local function Killed(inst)
	inst.secs_since_killed = 0 -- Reset
end

local function Secs_Since_Killed(inst)
	inst.secs_since_killed = inst.secs_since_killed + 1
end

local function SanityFN(inst)
	local delta = 0
	
	if inst.secs_since_killed < KILL_DEBUFF1 then
		delta = TUNING.SANITYAURA_TINY * 1 -- You can replace 1 with a higher value to make it stronger or a smaller value to make it weaker
	elseif inst.secs_since_killed >= KILL_DEBUFF2 then
		delta = -TUNING.SANITYAURA_TINY * 2 -- You can replace 2 with a higher value to make it stronger or a smaller value to make it weaker
	elseif inst.secs_since_killed >= KILL_DEBUFF1 then
		delta = -TUNING.SANITYAURA_TINY * 1 -- You can replace 1 with a higher value to make it stronger or a smaller value to make it weaker
	end
	
	return delta
end

local function OnSave(inst, data)
	data.secs_since_killed = inst.secs_since_killed
end

local function OnLoad(inst, data)
	if data ~= nil and data.secs_since_killed then inst.secs_since_killed = data.secs_since_killed end
end

 

if yourcharacter.lua already has an "OnLoad" or "OnSave" function then take the code of the OnLoad and OnSave functions here and put it in those instead

with this code your character will gain tiny sanity for a day upon killing something and if didnt kill something for a day you will start lose sanity and if 2 day past you lose even more sanity.

If you kill a mob or murder a critter in your inventory it resets that. I couldn't think of a easy way to make char say something without spamming it so hopefully somebody else can help you with that, hopefully the code will work for you

 

also the time you last killed a mob should save when you go in cave or exit server so the sanity gain/drain should remain

Edited by . . .
Link to comment
Share on other sites

3 hours ago, . . . said:

I whipped up this code right now so IDK 100% if it will work or crash, but you can test it hopefully it work

 

put all this code inside yourcharacter.lua inside the master_postinit

  Hide contents


if inst.secs_since_killed == nil then inst.secs_since_killed = 0 end -- Add value if doesn't exist

inst:DoPeriodicTask(1, Secs_Since_Killed)
inst.components.sanity.custom_rate_fn = SanityFN

inst:ListenForEvent("killed", Killed)
inst:ListenForEvent("murdered", Killed)

inst.OnSave = OnSave
inst.OnLoad = OnLoad

and put all these code inside yourcharacter.lua above the master_postinit

  Hide contents


local KILL_DEBUFF1 = 480 -- 480 seconds = 8 minutes = full DST day
local KILL_DEBUFF2 = 960 -- 960 seconds = 16 minutes = 2 DST day

local function Killed(inst)
	inst.secs_since_killed = 0 -- Reset
end

local function Secs_Since_Killed(inst)
	inst.secs_since_killed = inst.secs_since_killed + 1
end

local function SanityFN(inst)
	local delta = 0
	
	if inst.secs_since_killed < KILL_DEBUFF1 then
		delta = TUNING.SANITYAURA_TINY * 1 -- You can replace 1 with a higher value to make it stronger or a smaller value to make it weaker
	elseif inst.secs_since_killed >= KILL_DEBUFF2 then
		delta = -TUNING.SANITYAURA_TINY * 2 -- You can replace 2 with a higher value to make it stronger or a smaller value to make it weaker
	elseif inst.secs_since_killed >= KILL_DEBUFF1 then
		delta = -TUNING.SANITYAURA_TINY * 1 -- You can replace 1 with a higher value to make it stronger or a smaller value to make it weaker
	end
	
	return delta
end

local function OnSave(inst, data)
	data.secs_since_killed = inst.secs_since_killed
end

local function OnLoad(inst, data)
	if data ~= nil and data.secs_since_killed then inst.secs_since_killed = data.secs_since_killed end
end

 

if yourcharacter.lua already has an "OnLoad" or "OnSave" function then take the code of the OnLoad and OnSave functions here and put it in those instead

with this code your character will gain tiny sanity for a day upon killing something and if didnt kill something for a day you will start lose sanity and if 2 day past you lose even more sanity.

If you kill a mob or murder a critter in your inventory it resets that. I couldn't think of a easy way to make char say something without spamming it so hopefully somebody else can help you with that, hopefully the code will work for you

 

also the time you last killed a mob should save when you go in cave or exit server so the sanity gain/drain should remain

The mod crashes the game with this error. Specifically referring to the line "if data ~= nil and data.secs_since_killed then inst.secs_since_killed = data.secs_since_killed end"

image.thumb.png.02d9dd89371cef5016b5bc41f53be06a.png

Link to comment
Share on other sites

1 hour ago, . . . said:

can you post yourcharacter.lua file here then i can see what it looks like

local MakePlayerCharacter = require "prefabs/player_common"

local assets = {
    Asset("SCRIPT", "scripts/prefabs/player_common.lua"),
}

-- Your character's stats
TUNING.KOUSAI_HEALTH = 150
TUNING.KOUSAI_HUNGER = 125
TUNING.KOUSAI_SANITY = 175

-- Custom starting inventory
TUNING.GAMEMODE_STARTING_ITEMS.DEFAULT.KOUSAI = {

}

local start_inv = {}
for k, v in pairs(TUNING.GAMEMODE_STARTING_ITEMS) do
    start_inv[string.lower(k)] = v.KOUSAI
end
local prefabs = FlattenTree(start_inv, true)

-- When the character is revived from human
local function onbecamehuman(inst)
	-- Set speed when not a ghost (optional)
	inst.components.locomotor:SetExternalSpeedMultiplier(inst, "kousai_speed_mod", 1)
end

local function onbecameghost(inst)
	-- Remove speed modifier when becoming a ghost
   inst.components.locomotor:RemoveExternalSpeedMultiplier(inst, "kousai_speed_mod")
end

-- When loading or spawning the character
local function onload(inst)
    inst:ListenForEvent("ms_respawnedfromghost", onbecamehuman)
    inst:ListenForEvent("ms_becameghost", onbecameghost)

    if inst:HasTag("playerghost") then
        onbecameghost(inst)
    else
        onbecamehuman(inst)
    end
	
	if data ~= nil and data.secs_since_killed then inst.secs_since_killed = data.secs_since_killed end
end

-- Sanity Implementation
local KILL_DEBUFF1 = 480 -- 480 seconds = 8 minutes = full DST day
local KILL_DEBUFF2 = 960 -- 960 seconds = 16 minutes = 2 DST day

local function Killed(inst)
	inst.secs_since_killed = 0 -- Reset
end

local function Secs_Since_Killed(inst)
	inst.secs_since_killed = inst.secs_since_killed + 1
end

local function SanityFN(inst)
	local delta = 0
	
	if inst.secs_since_killed < KILL_DEBUFF1 then
		delta = TUNING.SANITYAURA_TINY * 1 -- You can replace 1 with a higher value to make it stronger or a smaller value to make it weaker
	elseif inst.secs_since_killed >= KILL_DEBUFF2 then
		delta = -TUNING.SANITYAURA_TINY * 2 -- You can replace 2 with a higher value to make it stronger or a smaller value to make it weaker
	elseif inst.secs_since_killed >= KILL_DEBUFF1 then
		delta = -TUNING.SANITYAURA_TINY * 1 -- You can replace 1 with a higher value to make it stronger or a smaller value to make it weaker
	end
	
	return delta
end

local function OnSave(inst, data)
	data.secs_since_killed = inst.secs_since_killed
end


-- This initializes for both the server and client. Tags can be added here.
local common_postinit = function(inst) 
	-- Minimap icon
	inst.MiniMapEntity:SetIcon( "kousai.tex" )
end

-- This initializes for the server only. Components are added here.
local master_postinit = function(inst)
	-- Set starting inventory
    inst.starting_inventory = start_inv[TheNet:GetServerGameMode()] or start_inv.default
	
	-- choose which sounds this character will play
	inst.soundsname = "kousaievent"
	inst.talker_path_override = "customvoice/"
	
	-- Uncomment if "wathgrithr"(Wigfrid) or "webber" voice is used
    --inst.talker_path_override = "dontstarve_DLC001/characters/"
	
	-- Stats	
	inst.components.health:SetMaxHealth(TUNING.KOUSAI_HEALTH)
	inst.components.hunger:SetMax(TUNING.KOUSAI_HUNGER)
	inst.components.sanity:SetMax(TUNING.KOUSAI_SANITY)
	
	-- Damage multiplier (optional)
    inst.components.combat.damagemultiplier = 2
	
	-- Hunger rate (optional)
	inst.components.hunger.hungerrate = 1.2 * TUNING.WILSON_HUNGER_RATE
	
	-- Sanity modifiers
	inst.components.sanity.night_drain_mult = 0.5
	
	-- Sanity Implementation
	if inst.secs_since_killed == nil then inst.secs_since_killed = 0 end -- Add value if doesn't exist

	inst:DoPeriodicTask(1, Secs_Since_Killed)
	inst.components.sanity.custom_rate_fn = SanityFN

	inst:ListenForEvent("killed", Killed)
	inst:ListenForEvent("murdered", Killed)
	
	inst.OnLoad = onload
    inst.OnNewSpawn = onload
	inst.OnSave = OnSave
	
end

return MakePlayerCharacter("kousai", prefabs, assets, common_postinit, master_postinit, prefabs)

For the dialogue, would it be possible to make a check like this to prevent spamming:
if inst.secs_since_killed = 0
     dialogue 0 (I'm not sure what code is used to create dialogue)
if inst.secs_since_killed = 480
     dialogue 1
if inst.secs_since_killed = 960
     dialogue 2

Link to comment
Share on other sites

Your "onload" function is missing data you need to change it from this

local function onload(inst)

to this

local function onload(inst, data)

 

and for dialogue maybe it can work use this and replace the old one

local function Secs_Since_Killed(inst)
	inst.secs_since_killed = inst.secs_since_killed + 1
	if inst.secs_since_killed == KILL_DEBUFF1 then
		inst.components.talker:Say("ah, i want to kill something dangit")
	elseif inst.secs_since_killed == KILL_DEBUFF2 then
		inst.components.talker:Say("im itching to KILLLLLLLLLLLLllll")
	end
end

 

Link to comment
Share on other sites

3 hours ago, . . . said:

Your "onload" function is missing data you need to change it from this


local function onload(inst)

to this


local function onload(inst, data)

 

and for dialogue maybe it can work use this and replace the old one


local function Secs_Since_Killed(inst)
	inst.secs_since_killed = inst.secs_since_killed + 1
	if inst.secs_since_killed == KILL_DEBUFF1 then
		inst.components.talker:Say("ah, i want to kill something dangit")
	elseif inst.secs_since_killed == KILL_DEBUFF2 then
		inst.components.talker:Say("im itching to KILLLLLLLLLLLLllll")
	end
end

 

After doing some testing, this works! Thank you!

  • GL Happy 1
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...