Jump to content

How to make character not lose sanity from digging up graves


Recommended Posts

Hello, I'm trying to do as title says, but probably failed really bad :D!

Here's code I have now, probably doesn't make any sense lol

Spoiler

AddPrefabPostInit("mound", function(inst)
	if inst.components.workable~=nil then
		local _onfinishcallback_Old = inst.components.workable.onfinishcallback
		
		inst.components.workable.onfinishcallback = function(inst, worker)
			if worker.components.sanity ~= nil and worker.grave_sanity_loss == true then
				worker.components.sanity:DoDelta(-TUNING.SANITY_SMALL)
			end
			return _onfinishcallback_Old and _onfinishcallback_Old(inst, worker)
		end
	end
end)

 

I'm trying to make if a character has certain value doesn't lose sanity from digging up a grave, but it doesn't seem to work :(..

Thanks for your time and any help, have a great day/night :D!

Link to comment
Share on other sites

The code makes complete sense. Where do you set grave_sanity_loss to true?

It's always a good debugging method to just put in print-statements every step of the way e.g. as the first line in your AddPrefabPostInit, just to make sure it's getting called, and also immediately inside every if-statement, so you can see which of them are entered, and whether your onfinishcallback function is even called.

Link to comment
Share on other sites

20 minutes ago, Ultroman said:

The code makes complete sense. Where do you set grave_sanity_loss to true?

It's added to all players with playerpostinit.

 

I just tested and the print inside 

Spoiler

inst.components.workable.onfinishcallback = function(inst, worker)
			if worker.components.sanity ~= nil and worker.grave_sanity_loss == true then
				print("hello")
				worker.components.sanity:DoDelta(-TUNING.SANITY_SMALL)
			end
			return _onfinishcallback_Old and _onfinishcallback_Old(inst, worker)
		end

 

didn't trigger

Link to comment
Share on other sites

Then make a print outside that if-statement and print the variables you're checking in the coming if-statement, so you can see what grave_sanity_loss is set to and whether your worker.components.sanity is not nil.

print("grave_sanity_loss : "..(worker.grave_sanity_loss and tostring(worker.grave_sanity_loss) or "nil").." || sanity component: "..(worker.components.sanity and "present" or "nil"))

 

Edited by Ultroman
Link to comment
Share on other sites

I don't think your code will work without a hard-fix. But first, SetOnFinishCallback() in workable component does set self.onfinish not self.onfinishcallback 

function Workable:SetOnFinishCallback(fn)
    self.onfinish = fn
end

But after correcting this, it is not enough to let it work as you want.
Because you return the old function.

return _onfinishcallback_Old and _onfinishcallback_Old(inst, worker)

which means the old function(onfinishcallback in mount.lua) in the block

if worker.components.sanity ~= nil then
  worker.components.sanity:DoDelta(-TUNING.SANITY_SMALL)
end

will run no matter what. You just make the sanity loss double or the original.
Unless you leave the old function's reference, that issue is inevitable.

In this case, I suggest doing kind of a tricky way. In short, save current sanity, execute the old callback, set it back. 
You may have already thought this way and unwilling to do, but I think this is the simplest way.

AddPrefabPostInit("mound", function(inst)
	if not GLOBAL.TheWorld.ismastersim then
		return
	end

	local DoOldFinishCallback = inst.components.workable.onfinish
		
	inst.components.workable.onfinish = function(inst, worker)
		if not worker.grave_sanity_loss then 
			return DoOldFinishCallback(inst, worker) 
		end

		local sanity_old = worker.components.sanity.current
		DoOldFinishCallback(inst, worker)
		worker.components.sanity.current = sanity_old
	end
end)

And surprisingly, it does not cause the client HUD issue(like unwanted sanity loss sound or visual effect) in DST. Because DST developers have done enough optimization on triggering client&server information exchanges. I assume that the HUD effects only trigger when a delta value exists on every frame. In this case, it does not exist.

Link to comment
Share on other sites

I ended up doing this then the sanity loss can be different depending on the player

Spoiler

AddPrefabPostInit("mound", function(inst)
	if not G.TheWorld.ismastersim then return inst end
	
	for k = 1, NUM_HALLOWEEN_ORNAMENTS do
		table.insert(prefabs, "halloween_ornament_"..tostring(k))
	end
	
	local LOOTS =
	{
		nightmarefuel = 1,
		amulet = 1,
		gears = 1,
		redgem = 5,
		bluegem = 5,
	}
	
	local function spawnghost(inst, chance)
		if inst.ghost == nil and math.random() <= (chance or 1) then
			inst.ghost = SpawnPrefab("ghost")
				if inst.ghost ~= nil then
				local x, y, z = inst.Transform:GetWorldPosition()
				inst.ghost.Transform:SetPosition(x - .3, y, z - .3)
				inst:ListenForEvent("onremove", function() inst.ghost = nil end, inst.ghost)
				return true
			end
		end
		return false
	end
	
	local function onfinishcallback(inst, worker)
		inst.AnimState:PlayAnimation("dug")
		inst:RemoveComponent("workable")

		if worker ~= nil then
			if worker.components.sanity ~= nil then
				worker.components.sanity:DoDelta(-TUNING.SANITY_SMALL * worker.sanity_grave_mult)--All of this code just to edit this line..
			end
			if not spawnghost(inst, .1) then
				local item = math.random() < .5 and G.PickRandomTrinket() or G.weighted_random_choice(LOOTS) or nil
				if item ~= nil then
					inst.components.lootdropper:SpawnLootPrefab(item)
				end

				if G.IsSpecialEventActive(G.SPECIAL_EVENTS.HALLOWED_NIGHTS) then
					local ornament = math.random(NUM_HALLOWEEN_ORNAMENTS * 4)
					if ornament <= NUM_HALLOWEEN_ORNAMENTS then
						inst.components.lootdropper:SpawnLootPrefab("halloween_ornament_"..tostring(ornament))
					end
					if TheWorld.components.specialeventsetup ~= nil then
						if math.random() < TheWorld.components.specialeventsetup.halloween_bat_grave_spawn_chance then
							local num_bats = 3
							for i = 1, num_bats do
								inst:DoTaskInTime(0.2 * i + math.random() * 0.3, function()
									local bat = SpawnPrefab("bat")
									local pos = FindNearbyLand(inst:GetPosition(), 3)
									bat.Transform:SetPosition(pos:Get())
									bat:PushEvent("fly_back")
								end)
							end

							TheWorld.components.specialeventsetup.halloween_bat_grave_spawn_chance = 0
						else
							TheWorld.components.specialeventsetup.halloween_bat_grave_spawn_chance = TheWorld.components.specialeventsetup.halloween_bat_grave_spawn_chance + 0.1 + (math.random() * 0.1)
						end
					end
				end
			else
				if G.IsSpecialEventActive(G.SPECIAL_EVENTS.HALLOWED_NIGHTS) then
					inst.components.lootdropper:SpawnLootPrefab("halloween_ornament_1") -- ghost
				end
			end
		end
	end
	
	inst.components.workable:SetOnFinishCallback(onfinishcallback)
end)

 

basically copy-pasted a lot of the code from mound.lua just to make the sanity loss get multiplied by a value wish it could be smaller, but at least it works.. but thanks for all the help :D!!

Link to comment
Share on other sites

And the code crashes thanks to this line on dedicated servers, great :(..

for k = 1, NUM_HALLOWEEN_ORNAMENTS do -- this line
	table.insert(prefabs, "halloween_ornament_"..tostring(k))
end

"'for' limit must be a number", welp.. Any more help would be appreciated :wilson_ecstatic: 

or I guess I'll just delete all the Halloween code :wilson_resigned:

Edited by Warbucks
Link to comment
Share on other sites

39 minutes ago, Warbucks said:

And the code crashes thanks to this line on dedicated servers, great :(..


for k = 1, NUM_HALLOWEEN_ORNAMENTS do -- this line
	table.insert(prefabs, "halloween_ornament_"..tostring(k))
end

"'for' limit must be a number", welp.. Any more help would be appreciated :wilson_ecstatic: 

or I guess I'll just delete all the Halloween code :wilson_resigned:

Did you forget to do the "GLOBAL." prefix for modmain.lua stuff?

Link to comment
Share on other sites

3 minutes ago, CarlZalph said:

Did you forget to do the "GLOBAL." prefix for modmain.lua stuff?

I have this above in modmain where this code is in

local G = GLOBAL

so probably not because whatever crashed because it wasn't global I added a G next to it

Edited by Warbucks
Link to comment
Share on other sites

5 minutes ago, Warbucks said:

I have this above in modmain where this code is in


local G = GLOBAL

so probably not because whatever crashed because it wasn't global I added a G next to it

A "G" with a dot, yeah?  "G."?

It's a table that you're needing to reference.

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