Jump to content

Recommended Posts

I want to redefine the function turnon in lantern prefab. That is what I do (no effect)

AddPrefabPostInit("lantern", function(inst)
	if not GLOBAL.TheWorld.ismastersim then
		return inst
	end
	print("DEBUG: PostInit ready")
	inst.turnon = function(inst)
		if not inst.components.fueled:IsEmpty() then
			--inst.components.fueled:StartConsuming()
			local owner = inst.components.inventoryitem.owner
			if inst._light == nil then
				inst._light = SpawnPrefab("lanternlight")
				inst._light._lantern = inst
				inst:ListenForEvent("onremove", onremovelight, inst._light)
				fuelupdate(inst)
				PlayTurnOnSound(inst)
			end
			inst._light.entity:SetParent((owner or inst).entity)
			inst.AnimState:PlayAnimation("idle_on")
			if owner ~= nil and inst.components.equippable:IsEquipped() then
				owner.AnimState:Show("LANTERN_OVERLAY")
			end
			inst.components.machine.ison = true
			inst.components.inventoryitem:ChangeImageName((inst:GetSkinName() or "lantern").."_lit")
			inst:PushEvent("lantern_on")
		end
	end
end)

I just need to remove one line and don't want to load the whole prefab again. Also this should help with compatibility.

I have no idea if this will work but I had to do something similar with my mod changing the OnSave and OnLoad functions.

 

function lanternpostinit(inst)

	function newturnon(inst)
    	if not inst.components.fueled:IsEmpty() then
			--inst.components.fueled:StartConsuming()
			local owner = inst.components.inventoryitem.owner
			if inst._light == nil then
				inst._light = SpawnPrefab("lanternlight")
				inst._light._lantern = inst
				inst:ListenForEvent("onremove", onremovelight, inst._light)
				fuelupdate(inst)
				PlayTurnOnSound(inst)
			end
			inst._light.entity:SetParent((owner or inst).entity)
			inst.AnimState:PlayAnimation("idle_on")
			if owner ~= nil and inst.components.equippable:IsEquipped() then
				owner.AnimState:Show("LANTERN_OVERLAY")
			end
			inst.components.machine.ison = true
			inst.components.inventoryitem:ChangeImageName((inst:GetSkinName() or "lantern").."_lit")
			inst:PushEvent("lantern_on")
		end
	end

	function newondropped(inst)
		turnoff(inst)
		newturnon(inst)
	end
	
	function newonequip(inst, owner)
		owner.AnimState:Show("ARM_carry")
		owner.AnimState:Hide("ARM_normal")
		owner.AnimState:OverrideSymbol("swap_object", "swap_lantern", "swap_lantern")
		owner.AnimState:OverrideSymbol("lantern_overlay", "swap_lantern", "lantern_overlay")

		if inst.components.fueled:IsEmpty() then
			owner.AnimState:Hide("LANTERN_OVERLAY")
		else
			owner.AnimState:Show("LANTERN_OVERLAY")
			newturnon(inst)
		end
	end

	function newontakefuel(inst)
		if inst.components.equippable:IsEquipped() then
		newturnon(inst)
		end
	end
	
	local function fuelupdate(inst)
    	if inst._light ~= nil then
    	    local fuelpercent = inst.components.fueled:GetPercent()
			inst._light.Light:SetIntensity(Lerp(.4, .6, fuelpercent))
			inst._light.Light:SetRadius(Lerp(3, 5, fuelpercent))
			inst._light.Light:SetFalloff(.9)
		end
	end
	
	local function PlayTurnOnSound(inst)
		if inst._soundtask ~= nil then
			inst._soundtask:Cancel()
			inst._soundtask = nil
		elseif not POPULATING then
			inst._light.SoundEmitter:PlaySound("dontstarve/wilson/lantern_on")
		end
	end
end

	
	inst.components.machine.turnonfn = newturnon
	inst.components.inventoryitem:SetOnDroppedFn(newondropped)
	inst.components.equippable:SetOnEquip(newonequip)
	inst.components.fueled:SetTakeFuelFn(newontakefuel)
end

AddPrefabPostInit("lantern", lanternpostinit)

I didn't test this and there is probably a better way to modify a function but after hours of searching and testing I couldn't find an easy way for my mod.  Not sure if you need a "if not TheWorld.ismastersim then..." in there.

Edited by Wolf_EX

Thank you! After some polish I get it to work. But it start require even more function as we call them. Like turnoff, PlayTurnOffSound, stoptrackingowner and more. So in this case no point to go this way, it will lose any compatibility at the end.

May be it will be interesting to you. I've found library (or whatever it is) upvaluehacker. it allow us to get or set values of local variables. Though it may look too overwhelming for this task, it does its job well.

Spoiler

local UpvalueHacker = GLOBAL.require("tools/upvaluehacker")

local function turnon(inst)
    if not inst.components.fueled:IsEmpty() then
       -- inst.components.fueled:StartConsuming()
        local owner = inst.components.inventoryitem.owner
        if inst._light == nil then
            inst._light = GLOBAL.SpawnPrefab("lanternlight")
            inst._light._lantern = inst
            inst:ListenForEvent("onremove", onremovelight, inst._light)
            fuelupdate(inst)
            PlayTurnOnSound(inst)
        end
        inst._light.entity:SetParent((owner or inst).entity)
        inst.AnimState:PlayAnimation("idle_on")
        if owner ~= nil and inst.components.equippable:IsEquipped() then
            owner.AnimState:Show("LANTERN_OVERLAY")
        end
        inst.components.machine.ison = true
        inst.components.inventoryitem:ChangeImageName((inst:GetSkinName() or "lantern").."_lit")
        inst:PushEvent("lantern_on")
    end
end

AddPrefabPostInit("world", function(inst)
	PlayTurnOnSound = UpvalueHacker.GetUpvalue(GLOBAL.Prefabs.lantern.fn, "turnon", "PlayTurnOnSound")
	fuelupdate = UpvalueHacker.GetUpvalue(GLOBAL.Prefabs.lantern.fn, "fuelupdate")
	UpvalueHacker.SetUpvalue(GLOBAL.Prefabs.lantern.fn, turnon, "turnon")
end)

 

Link to github

Edited by thezotikrus

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