Jump to content

How to make a prefab postinit for a specific function within a prefab?


Recommended Posts

I'm trying to make postinits to replace several existing functions inside prefab files, and I'm wondering how to do this properly. These are the files/functions in question:
 

Spoiler

 


townportal.lua


local function OnStartChanneling(inst, channeler)
    inst.AnimState:PlayAnimation("turn_on")
    inst.AnimState:PushAnimation("idle_on_loop")
    StartSoundLoop(inst)
    TheWorld:PushEvent("townportalactivated", inst)

    inst.MiniMapEntity:SetIcon("townportalactive.png")
    inst.MiniMapEntity:SetPriority(20)

    if inst.icon ~= nil then
        inst.icon.MiniMapEntity:SetIcon("townportalactive.png")
        inst.icon.MiniMapEntity:SetPriority(20)
        inst.icon.MiniMapEntity:SetDrawOverFogOfWar(true)
    end

    inst.channeler = channeler.components.sanity ~= nil and channeler or nil
    if inst.channeler ~= nil then
        inst.channeler.components.sanity:DoDelta(-TUNING.SANITY_MED)
        inst.channeler.components.sanity.externalmodifiers:SetModifier(inst, -TUNING.DAPPERNESS_SUPERHUGE)
    end
end



staff.lua

purple:


local function teleport_start(teleportee, staff, caster, loctarget, target_in_ocean)
    local ground = TheWorld

    --V2C: Gotta do this RIGHT AWAY in case anything happens to loctarget or caster
    local locpos = teleportee.components.teleportedoverride ~= nil and teleportee.components.teleportedoverride:GetDestPosition()
				or loctarget == nil and getrandomposition(caster, teleportee, target_in_ocean)
				or loctarget.teletopos ~= nil and loctarget:teletopos()
				or loctarget:GetPosition() 

    if teleportee.components.locomotor ~= nil then
        teleportee.components.locomotor:StopMoving()
    end

    staff.components.finiteuses:Use(1)

    if ground:HasTag("cave") then
        -- There's a roof over your head, magic lightning can't strike!
        ground:PushEvent("ms_miniquake", { rad = 3, num = 5, duration = 1.5, target = teleportee })
        return
    end

    local isplayer = teleportee:HasTag("player")
    if isplayer then
        teleportee.sg:GoToState("forcetele")
    else
        if teleportee.components.health ~= nil then
            teleportee.components.health:SetInvincible(true)
        end
        if teleportee.DynamicShadow ~= nil then
            teleportee.DynamicShadow:Enable(false)
        end
        teleportee:Hide()
    end

    --#v2c hacky way to prevent lightning from igniting us
    local preventburning = teleportee.components.burnable ~= nil and not teleportee.components.burnable.burning
    if preventburning then
        teleportee.components.burnable.burning = true
    end
    ground:PushEvent("ms_sendlightningstrike", teleportee:GetPosition())
    if preventburning then
        teleportee.components.burnable.burning = false
    end

    if caster ~= nil and caster.components.sanity ~= nil then
        caster.components.sanity:DoDelta(-TUNING.SANITY_HUGE)
    end

    ground:PushEvent("ms_deltamoisture", TUNING.TELESTAFF_MOISTURE)

    if isplayer then
        teleportee.sg.statemem.teleport_task = teleportee:DoTaskInTime(3, teleport_continue, locpos, loctarget)
    else
        teleport_continue(teleportee, locpos, loctarget)
    end
end

Orange:


local function onblink(staff, pos, caster)
    if caster.components.sanity ~= nil then
        caster.components.sanity:DoDelta(-TUNING.SANITY_MED)
    end
    staff.components.finiteuses:Use(1) 
end

 


wormhole.lua


local function OnActivate(inst, doer)
    if doer:HasTag("player") then
        ProfileStatsSet("wormhole_used", true)
        AwardPlayerAchievement("wormhole_used", doer)

        local other = inst.components.teleporter.targetTeleporter
        if other ~= nil then
            DeleteCloseEntsWithTag({"WORM_DANGER"}, other, 15)
        end

        if doer.components.talker ~= nil then
            doer.components.talker:ShutUp()
        end
        if doer.components.sanity ~= nil and not doer:HasTag("nowormholesanityloss") and not inst.disable_sanity_drain then
            doer.components.sanity:DoDelta(-TUNING.SANITY_MED)
        end

        --Sounds are triggered in player's stategraph
    elseif inst.SoundEmitter ~= nil then
        inst.SoundEmitter:PlaySound("dontstarve/common/teleportworm/swallow")
    end
end

 

 

how would I set these up properly as a postinit so that the postinit would replace these functions with my custom code? (the code posted is the original code)

  • Like 1
Link to comment
Share on other sites

So, this is going into the trickier side of Lua.

These local functions are all referenced (you better hope so anyway) in some accessible way through the prefab. This means that they are upvalues.
(If you don't know how upvalues and stuff work, you'll want to read up on them).

Rezecib's upvalue hacker should provide a sufficient explanation to your needs: https://github.com/rezecib/Rezecib-s-Rebalance/blob/master/scripts/tools/upvaluehacker.lua, since he provides examples where he tries to do essentially the same thing as you.

Spoiler

Alternately, you can use the Lua wiki. This is usually my go-to, but Rezecib makes things easier for beginners.


 

  • Like 1
Link to comment
Share on other sites

So, for a prefab, what you wanna do is something like

AddPrefabPostInit("prefab_name", FunctionThatWillGetCalledOnInit(PrefabInstanceIsProvided))

A live example:

AddPrefabPostInit("player_classified", function(inst)
	print("HELLO post prefab init player_classified") -- on transition exit
	inst:DoTaskInTime(0, RegisterNetListeners)
end)

You can add this to your modmain, or derivative files.

the (inst) will the the instance of that prefab

You can then do something like

local OriginalFunction = inst.Function

if you wanna preserve / reuse / add to that function.

For compatibility, I'd recommend this option. But you can just straight up replace it.

Then you do

inst.Function = 

and declare your new function. If you wanted to include the old one it'd look something like

inst.Function = function(the same variables it took origially)
	local returnValue = OriginalFunction(the same variables it took origially)
	
	Your code that runs after the original function's done its own thing

	return returnValue
end

Remember, if something is declared as

Something:DoesStuff(...)

it's the same as

Something.DoesStuff(Something, ...)

 

Hope this helps :)

Also, hi penguin :D (I was typing as you posted :P )

  • Wavey 1
Link to comment
Share on other sites

If you look at townportal.lua you can see that the local function is used:

inst.components.channelable:SetChannelingFn(OnStartChanneling, OnStopChanneling)

So look at the channelable component:

function Channelable:SetChannelingFn(startfn, stopfn)
    self.onchannelingfn = startfn
    self.onstopchannelingfn = stopfn
end

So create a prefabpostinit for the townportal, and then hook the inst's channelable component's onchannelingfn in your case.

 

Note that if you're adding functionality or changing the arguments/return values, then you should hook the function.  Otherwise you break other mods and/or your own mod when Klei updates things.

 

Same idea applies to the other cases, check out where they're getting stored to.  If they are never stored, then you'll use the debug upvalue stuff to access the function.

Link to comment
Share on other sites

17 hours ago, penguin0616 said:

So, this is going into the trickier side of Lua.

These local functions are all referenced (you better hope so anyway) in some accessible way through the prefab. This means that they are upvalues.
(If you don't know how upvalues and stuff work, you'll want to read up on them).

Rezecib's upvalue hacker should provide a sufficient explanation to your needs: https://github.com/rezecib/Rezecib-s-Rebalance/blob/master/scripts/tools/upvaluehacker.lua, since he provides examples where he tries to do essentially the same thing as you.

  Reveal hidden contents

Alternately, you can use the Lua wiki. This is usually my go-to, but Rezecib makes things easier for beginners.


 

I can already tell I'm doing something wrong with setting this up for the purple staff code, but this is what I have so far for the orange staff code and I want to make sure I'm doing this right:

 

local UpvalueHacker = GLOBAL.require "upvaluehacker"

AddPrefabPostinit("staff" onblink(staff, pos, caster)
	local function onblink(staff, pos, caster)
		if caster ~= nil and caster.components.sanity ~= nil and not caster:HasTag("warptraveller") then
				caster.components.sanity:DoDelta(-TUNING.SANITY_MED)
			end	
			if caster ~= nil and caster.components.sanity ~= nil and caster:HasTag("warptraveller") then
				caster.components.sanity:DoDelta(TUNING.SANITY_TINY)	
			end
			staff.components.finiteuses:Use(1) 
		end
		UpvalueHacker.SetUpvalue(GLOBAL.Prefabs.staff.fn, onblink, "onblink")
end)

From what I understand, I put the upvaluehacker.lua into the scripts folder and then reference it in modmain, is this the correct way to do that?

Link to comment
Share on other sites

You reference it fine, but the rest of your code has some syntax issues.

For specifically (what I assume is, based on your code) The Lazy Explorer, replacing onblink would use the same concept that CarlZalph outlined for you.

10 hours ago, CarlZalph said:

If you look at townportal.lua you can see that the local function is used:


inst.components.channelable:SetChannelingFn(OnStartChanneling, OnStopChanneling)

So look at the channelable component:


function Channelable:SetChannelingFn(startfn, stopfn)
    self.onchannelingfn = startfn
    self.onstopchannelingfn = stopfn
end

So create a prefabpostinit for the townportal, and then hook the inst's channelable component's onchannelingfn in your case.

In the case of the Lazy Explorer, we care about "blinkstaff" instead of "channelable". (prefabs/staff.lua:895 in function orange()) 

local function onblink(staff, pos, caster)
	if caster ~= nil and caster.components.sanity ~= nil and not caster:HasTag("warptraveller") then
		caster.components.sanity:DoDelta(-TUNING.SANITY_MED)
	end	
	if caster ~= nil and caster.components.sanity ~= nil and caster:HasTag("warptraveller") then
		caster.components.sanity:DoDelta(TUNING.SANITY_TINY)	
	end
	staff.components.finiteuses:Use(1) 
end

-- assuming you are trying to modify the lazy explorer
AddPrefabPostInit("orangestaff", function(inst)
	inst.components.blinkstaff.onblinkfn = onblink 
end)

 

For other functions, like "teleport_start", you would use the upvalue hacker. Generally, If the function is accessible easily (and isn't mean to be a global change), then AddPrefabPostInit/AddComponentPostInit is suitable. Otherwise:

10 hours ago, CarlZalph said:

Note that if you're adding functionality or changing the arguments/return values, then you should hook the function.  Otherwise you break other mods and/or your own mod when Klei updates things.

 

Same idea applies to the other cases, check out where they're getting stored to.  If they are never stored, then you'll use the debug upvalue stuff to access the function.

 

Edited by penguin0616
  • Like 1
Link to comment
Share on other sites

5 minutes ago, penguin0616 said:

You reference it fine, but the rest of your code has some syntax issues.

For specifically (what I assume is, based on your code) The Lazy Explorer, replacing onblink would use the same concept that CarlZalph outlined for you.

In the case of the Lazy Explorer, we care about "blinkstaff" instead of "channelable". (prefabs/staff.lua:895 in function orange()) 


local function onblink(staff, pos, caster)
	if caster ~= nil and caster.components.sanity ~= nil and not caster:HasTag("warptraveller") then
		caster.components.sanity:DoDelta(-TUNING.SANITY_MED)
	end	
	if caster ~= nil and caster.components.sanity ~= nil and caster:HasTag("warptraveller") then
		caster.components.sanity:DoDelta(TUNING.SANITY_TINY)	
	end
	staff.components.finiteuses:Use(1) 
end

-- assuming you are trying to modify the lazy explorer
AddPrefabPostInit("orangestaff", function(inst)
	inst.components.blinkstaff.onblinkfn = onblink 
end)

 

For other functions, like "teleport_start", you would use the upvalue hacker. Generally, If the function is accessible easily (and isn't mean to be a global change), then AddPrefabPostInit/AddComponentPostInit is suitable. Otherwise:

 

So I'm assuming then that the orangestaff postinit would look like this?
 


local function onblink(staff, pos, caster)
	if caster ~= nil and caster.components.sanity ~= nil and not caster:HasTag("warptraveller") then
			caster.components.sanity:DoDelta(-TUNING.SANITY_MED)
		end	
		if caster ~= nil and caster.components.sanity ~= nil and caster:HasTag("warptraveller") then
			caster.components.sanity:DoDelta(TUNING.SANITY_TINY)	
		end
		staff.components.finiteuses:Use(1) 
	end
		
AddPrefabPostInit("orangestaff", function(inst)
	inst.components.blinkstaff.onblinkfn = onblink 
end)

with the function to be changed and then the postinit?
And it doesn't need the upvalue hacker in this case? What determines whether that is needed or not?

Link to comment
Share on other sites

2 minutes ago, MF99K said:

So I'm assuming then that the orangestaff postinit would look like this?

Yep.

2 minutes ago, MF99K said:

And it doesn't need the upvalue hacker in this case? What determines whether that is needed or not?

 

10 minutes ago, penguin0616 said:

For other functions, like "teleport_start", you would use the upvalue hacker. Generally, If the function is accessible easily (and isn't mean to be a global change), then AddPrefabPostInit/AddComponentPostInit is suitable. Otherwise:

10 hours ago, CarlZalph said:

Note that if you're adding functionality or changing the arguments/return values, then you should hook the function.  Otherwise you break other mods and/or your own mod when Klei updates things.

 

Same idea applies to the other cases, check out where they're getting stored to.  If they are never stored, then you'll use the debug upvalue stuff to access the function.

 

 

  • Like 1
Link to comment
Share on other sites

So from what I understand, whether the upvalue hacker is needed depends on where the function is getting called? so any function that's called with something along the lines of "inst.components.[component].[component function] = [function name]" shouldn't need it?

Link to comment
Share on other sites

3 minutes ago, MF99K said:

And it doesn't need the upvalue hacker in this case? What determines whether that is needed or not?

If a file contained:

local superprivatefunction = function(...)
    -- Do stuff
end

local obj = {}
obj.publicfunction = function(...)
    superprivatefunction(...)
end

return obj

Then when the file were require'd you'd have access to obj and obj.publicfunction.

However, with how superprivatefunction was written there's no scope where you can touch it directly.

In this case you must use the debug library and upvalues to access the function itself, looking for upvalues with name "superprivatefunction" inside the function obj.publicfunction.

  • Thanks 1
  • Sanity 1
Link to comment
Share on other sites

4 minutes ago, CarlZalph said:

If a file contained:


local superprivatefunction = function(...)
    -- Do stuff
end

local obj = {}
obj.publicfunction = function(...)
    superprivatefunction(...)
end

return obj

Then when the file were require'd you'd have access to obj and obj.publicfunction.

However, with how superprivatefunction was written there's no scope where you can touch it directly.

In this case you must use the debug library and upvalues to access the function itself, looking for upvalues with name "superprivatefunction" inside the function obj.publicfunction.

ah yea, I had a feeling it was something along those lines, where if it was a function called from within another function (or object) it would need to be set up differently

I would assume this also means that only teleport_start would need the upvalue hacker?

Edited by MF99K
Link to comment
Share on other sites

I was able to get the code for the wormhole and orangestaff to work fine, but the purple staff and lazy deserter code causes an errorless crash

this is the code for those

local UpvalueHacker = GLOBAL.require "upvaluehacker"	
	--UpvalueHacker.SetUpvalue(GLOBAL.Prefabs.staff.fn, onblink, "onblink")

AddPrefabPostInit("purplestaff" teleport_start, function(inst)
		
	local function teleport_start(teleportee, staff, caster, loctarget, target_in_ocean)
		local ground = TheWorld

		--V2C: Gotta do this RIGHT AWAY in case anything happens to loctarget or caster
		local locpos = teleportee.components.teleportedoverride ~= nil and teleportee.components.teleportedoverride:GetDestPosition()
					or loctarget == nil and getrandomposition(caster, teleportee, target_in_ocean)
					or loctarget.teletopos ~= nil and loctarget:teletopos()
					or loctarget:GetPosition() 

		if teleportee.components.locomotor ~= nil then
			teleportee.components.locomotor:StopMoving()
		end

		staff.components.finiteuses:Use(1)

		if ground:HasTag("cave") then
			-- There's a roof over your head, magic lightning can't strike!
			ground:PushEvent("ms_miniquake", { rad = 3, num = 5, duration = 1.5, target = teleportee })
			return
		end

		local isplayer = teleportee:HasTag("player")
		if isplayer then
			teleportee.sg:GoToState("forcetele")
		else
			if teleportee.components.health ~= nil then
				teleportee.components.health:SetInvincible(true)
			end
			if teleportee.DynamicShadow ~= nil then
				teleportee.DynamicShadow:Enable(false)
			end
			teleportee:Hide()
		end

		--#v2c hacky way to prevent lightning from igniting us
		local preventburning = teleportee.components.burnable ~= nil and not teleportee.components.burnable.burning
		if preventburning then
			teleportee.components.burnable.burning = true
		end
		ground:PushEvent("ms_sendlightningstrike", teleportee:GetPosition())
		if preventburning then
			teleportee.components.burnable.burning = false
		end

		if caster ~= nil and caster.components.sanity ~= nil and not caster:HasTag("warptraveller") then
				caster.components.sanity:DoDelta(-TUNING.SANITY_HUGE)
			end	
			if caster ~= nil and caster.components.sanity ~= nil and caster:HasTag("warptraveller") then
				caster.components.sanity:DoDelta(TUNING.SANITY_TINY)	
			end

		ground:PushEvent("ms_deltamoisture", TUNING.TELESTAFF_MOISTURE)

		if isplayer then
			teleportee.sg.statemem.teleport_task = teleportee:DoTaskInTime(3, teleport_continue, locpos, loctarget)
		else
			teleport_continue(teleportee, locpos, loctarget)
		end
	end
	
	UpvalueHacker.SetUpvalue(GLOBAL.Prefabs.staff.fn, teleport_start, "teleport_start")
end)	
	

--lazy deserter (townportal)

local function OnStartChanneling(inst, channeler)
		inst.AnimState:PlayAnimation("turn_on")
		inst.AnimState:PushAnimation("idle_on_loop")
		StartSoundLoop(inst)
		TheWorld:PushEvent("townportalactivated", inst)

		inst.MiniMapEntity:SetIcon("townportalactive.png")
		inst.MiniMapEntity:SetPriority(20)

		if inst.icon ~= nil then
			inst.icon.MiniMapEntity:SetIcon("townportalactive.png")
			inst.icon.MiniMapEntity:SetPriority(20)
			inst.icon.MiniMapEntity:SetDrawOverFogOfWar(true)
		end

		inst.channeler = channeler.components.sanity ~= nil and channeler or nil
		if inst.channeler ~= nil and inst.channeler:HasTag("warptraveller") then
			inst.channeler.components.sanity:DoDelta(-TUNING.SANITY_SMALL)
			inst.channeler.components.sanity.externalmodifiers:SetModifier(inst, -TUNING.DAPPERNESS_TINY)
		else if inst.channeler ~= nil then
			inst.channeler.components.sanity:DoDelta(-TUNING.SANITY_MED)
			inst.channeler.components.sanity.externalmodifiers:SetModifier(inst, -TUNING.DAPPERNESS_SUPERHUGE)
		end
	end)


AddPrefabPostInit("townportal", function(inst)
	inst.components.channelable.onchannelfn = OnStartChanneling
end)

 

Link to comment
Share on other sites

15 minutes ago, penguin0616 said:

@MF99K You have syntax error(s). Those don't get errors that you are familiar with, since there's not a lot to trace with them.


AddPrefabPostInit("purplestaff" teleport_start, function(inst)

That line has invalid syntax. I recommend double checking the rest of your code too.

I tried both 
 

AddPrefabPostInit("purplestaff", teleport_start, function(inst)

and

AddPrefabPostInit("purplestaff", function(inst)

neither of them crash the game, but neither of them use the modded function either

The actual crash is that the game reverts to the character select screen and then freezes. I know that this type of crash doesn't usually produce error logs, but the same thing occurs for both the postinits I posted earlier

Link to comment
Share on other sites

You don't have enough brackets.

AddPrefabPostInit("purplestaff", function(inst)

Will crash and fail without telling you why because it can't even be parsed (read) as code.

AddPrefabPostInit("purplestaff", function(inst))

Should tell you if it works or not.

Link to comment
Share on other sites

1 minute ago, Bigfootmech said:

You don't have enough brackets.


AddPrefabPostInit("purplestaff", function(inst)

Will crash and fail without telling you why because it can't even be parsed (read) as code.

thing is, it doesn't crash

the bracket is lower down in the code, it just doesn't do anything at all

Link to comment
Share on other sites

Syntax errors don't usually cause crashes, they just break the rest of the scripts. If you don't crash from a different script breaking, then I expect you to have some strange behavior. 

If you believe your syntax valid, I suggest adding prints throughout key points of your scripts and seeing which ones run and which ones don't.
Hasn't failed me yet.

  • Like 2
Link to comment
Share on other sites

Oh, I misread it. And got it wrong to boot. My bad.

He was pointing out missing comma

The bracket lower down in the code closes the AddPrefabPostInit () function call

With the arguments "purplestaff", and another function

the
 

function(inst)

...

end

is an anonymous function (it's declared, and used in-place)

 

So the whole code block should end up looking something like

AddPrefabPostInit("purplestaff", function(inst)
	-- code inside the anonymous function
end)

 

Edited by Bigfootmech
Link to comment
Share on other sites

1 minute ago, penguin0616 said:

Syntax errors don't usually cause crashes, they just break the rest of the scripts. If you don't crash from a different script breaking, then I expect you to have some strange behavior. 

If you believe your syntax valid, I suggest adding prints throughout key points of your scripts and seeing which ones run and which ones don't.
Hasn't failed me yet.

most of the crashes I get are usually syntax errors, so if that is what is happening, something about the context of the error is what's preventing an error log. I don't know enough about when stuff is accessed to know why there are different kinds of crashes.

I've added several prints, and none of them have showed up in console, which shows me something isn't connected.

As it currently stands, this is the purple staff postinit stuff:

 

	
local UpvalueHacker = GLOBAL.require "upvaluehacker"	
	--UpvalueHacker.SetUpvalue(GLOBAL.Prefabs.staff.fn, onblink, "onblink")

AddPrefabPostInit("purplestaff", teleport_start, function(inst)
		
	local function teleport_start(teleportee, staff, caster, loctarget, target_in_ocean)
		local ground = TheWorld

		--V2C: Gotta do this RIGHT AWAY in case anything happens to loctarget or caster
		local locpos = teleportee.components.teleportedoverride ~= nil and teleportee.components.teleportedoverride:GetDestPosition()
					or loctarget == nil and getrandomposition(caster, teleportee, target_in_ocean)
					or loctarget.teletopos ~= nil and loctarget:teletopos()
					or loctarget:GetPosition() 

		if teleportee.components.locomotor ~= nil then
			teleportee.components.locomotor:StopMoving()
		end

		staff.components.finiteuses:Use(1)

		if ground:HasTag("cave") then
			-- There's a roof over your head, magic lightning can't strike!
			ground:PushEvent("ms_miniquake", { rad = 3, num = 5, duration = 1.5, target = teleportee })
			return
		end

		local isplayer = teleportee:HasTag("player")
		if isplayer then
			teleportee.sg:GoToState("forcetele")
		else
			if teleportee.components.health ~= nil then
				teleportee.components.health:SetInvincible(true)
			end
			if teleportee.DynamicShadow ~= nil then
				teleportee.DynamicShadow:Enable(false)
			end
			teleportee:Hide()
		end

		--#v2c hacky way to prevent lightning from igniting us
		local preventburning = teleportee.components.burnable ~= nil and not teleportee.components.burnable.burning
		if preventburning then
			teleportee.components.burnable.burning = true
		end
		ground:PushEvent("ms_sendlightningstrike", teleportee:GetPosition())
		if preventburning then
			teleportee.components.burnable.burning = false
		end

		if caster ~= nil and caster.components.sanity ~= nil and not caster:HasTag("warptraveller") then
				caster.components.sanity:DoDelta(-TUNING.SANITY_HUGE)
				print("not warper")
			end	
			if caster ~= nil and caster.components.sanity ~= nil and caster:HasTag("warptraveller") then
				caster.components.sanity:DoDelta(TUNING.SANITY_TINY)	
				print("warper")
			end

		ground:PushEvent("ms_deltamoisture", TUNING.TELESTAFF_MOISTURE)

		if isplayer then
			teleportee.sg.statemem.teleport_task = teleportee:DoTaskInTime(3, teleport_continue, locpos, loctarget)
		else
			teleport_continue(teleportee, locpos, loctarget)
		end
	end
	
	UpvalueHacker.SetUpvalue(GLOBAL.Prefabs.staff.fn, teleport_start, "teleport_start")
end)	

right now, this code does not crash, but also does nothing

Link to comment
Share on other sites

@MF99K 

1 minute ago, MF99K said:

I've added several prints, and none of them have showed up in console, which shows me something isn't connected.

That means you need even more prints :angel:

 

This is actually a very reliable way of debugging situations like these, albeit some people find it tedious. If the prints you initially have aren't showing up, then you need more until at least one shows up. If you've added what you believe to be enough prints (you haven't), then there are other issues that need working out.

  • Like 2
Link to comment
Share on other sites

1 minute ago, penguin0616 said:

@MF99K 

That means you need even more prints :angel:

 

This is actually a very reliable way of debugging situations like these, albeit some people find it tedious. If the prints you initially have aren't showing up, then you need more until at least one shows up. If you've added what you believe to be enough prints (you haven't), then there are other issues that need working out.

I'd assume adding a print here would be a good place to start?
 

AddPrefabPostInit("purplestaff", teleport_start, function(inst)
	print("postinit on")
	local function teleport_start(teleportee, staff, caster, loctarget, target_in_ocean)

 

Link to comment
Share on other sites

I would start with

print("EASILY_SEARCHABLE_STRING Is the file being loaded correctly?")
AddPrefabPostInit("purplestaff", teleport_start, function(inst)
	print("EASILY_SEARCHABLE_STRING purple staff post init called")
	local function teleport_start(teleportee, staff, caster, loctarget, target_in_ocean)

but the main thing is testing.

Try it.

See if it works

See if/how it breaks.

Iterate :)

You can always take out the clutter later.

Link to comment
Share on other sites

currently this is the purple staff postinit

local UpvalueHacker = GLOBAL.require "upvaluehacker"	
	--UpvalueHacker.SetUpvalue(GLOBAL.Prefabs.staff.fn, onblink, "onblink")
AddPrefabPostInit("telestaff", function(inst)
	print("postinit on")
	local function teleport_start(teleportee, staff, caster, loctarget, target_in_ocean)
		local ground = TheWorld

		--V2C: Gotta do this RIGHT AWAY in case anything happens to loctarget or caster
		local locpos = teleportee.components.teleportedoverride ~= nil and teleportee.components.teleportedoverride:GetDestPosition()
				or loctarget == nil and getrandomposition(caster, teleportee, target_in_ocean)
				or loctarget.teletopos ~= nil and loctarget:teletopos()
				or loctarget:GetPosition() 

		if teleportee.components.locomotor ~= nil then
			teleportee.components.locomotor:StopMoving()
		end

		staff.components.finiteuses:Use(1)

		if ground:HasTag("cave") then
			-- There's a roof over your head, magic lightning can't strike!
			ground:PushEvent("ms_miniquake", { rad = 3, num = 5, duration = 1.5, target = teleportee })
			return
		end

		local isplayer = teleportee:HasTag("player")
		if isplayer then
			teleportee.sg:GoToState("forcetele")
		else
			if teleportee.components.health ~= nil then
				teleportee.components.health:SetInvincible(true)
			end
			if teleportee.DynamicShadow ~= nil then
				teleportee.DynamicShadow:Enable(false)
			end
			teleportee:Hide()
		end

		--#v2c hacky way to prevent lightning from igniting us
		local preventburning = teleportee.components.burnable ~= nil and not teleportee.components.burnable.burning
		if preventburning then
			teleportee.components.burnable.burning = true
		end
		ground:PushEvent("ms_sendlightningstrike", teleportee:GetPosition())
		if preventburning then
			teleportee.components.burnable.burning = false
		end

		if caster ~= nil and caster.components.sanity ~= nil and not caster:HasTag("warptraveller") then
				caster.components.sanity:DoDelta(-TUNING.SANITY_HUGE)
				print("not warper")
			end	
			if caster ~= nil and caster.components.sanity ~= nil and caster:HasTag("warptraveller") then
				caster.components.sanity:DoDelta(TUNING.SANITY_TINY)	
				print("warper")
			end

		ground:PushEvent("ms_deltamoisture", TUNING.TELESTAFF_MOISTURE)

		if isplayer then
			teleportee.sg.statemem.teleport_task = teleportee:DoTaskInTime(3, teleport_continue, locpos, loctarget)
		else
			teleport_continue(teleportee, locpos, loctarget)
		end
	end
	
	UpvalueHacker.SetUpvalue(GLOBAL.Prefabs.telestaff.fn, teleport_start, "teleport_start")
end)


Alborgo on the discord pointed out that the correct prefab name is "telestaff" so I fixed that, but the code still appears to do nothing and doesn't provide the prints inside the function

 

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