Jump to content

Recommended Posts

Hey there!

I'm having some trouble figuring out how to port Craftable Tunnels to work with SW-compatible worlds. This amazing mod is basically craftable wormholes. The mod pairs tunnels crafted in order. However, all I've managed to do is add the recipe into SW-Compatible worlds. When the tunnels are constructed, any attempts to teleport will result in this:

UPDATE: Thanks to @Mobbstar showing me the DLC_0002 actions.lua, we're one step closer! Apparently the jumpin action is calling the teleporter component which is not used by the mod at all. So, let's see how we can solve this.

UPDATE 2: Managed to get Tunnels working. However, when I added this:

Spoiler

GLOBAL.ACTIONS.JUMPIN.strfn = function(act)
	-- if act.target.components.teleporter.getverb then
	-- 	return act.target.components.teleporter.getverb(act.target, act.doer)
	-- else
		if act.target.components.tunnelteleporter.getverb then
		return act.target.components.tunnelteleporter.getverb(act.target, act.doer)
	end
end

 

Wormholes get screwed. Log says attempt to index field "tunnelteleporter" (a nil value).

BUT, if I uncomment those 3 lines (so that jumpin action can accommodate teleporter and tunnelteleporter), Tunnels fail again. This time it says modmain.lua attempt to index field "teleporter" (a nil value).  Can someone help me understand this? Am I supposed to define getverb in tunnelteleporter.lua? How to do so? If that's so, how come approaching the wormhole crashes if I uncomment the 3 lines? 

I'll try to provide whatever help however I can:

modmain.lua

Spoiler

----------------------------------------------------------------------------------------
--Developer Mode
----------------------------------------------------------------------------------------

--GLOBAL.CHEATS_ENABLED = true
--GLOBAL.require( 'debugkeys' )

--[[
	DISCLAIMER:
	I am by no means a Lua programmer
	There is a lot of code in this mod that is probably done the WRONG way...
	If you are experienced with Lua and you want to help me understand it better, feel free to add me on Steam or email me: nossr50@gmail.com
	I started learning Lua while making mods for DS, and I'm still very much a newbie
--]]

----------------------------------------------------------------------------------------
--SOMETHING LIKE A HEADER I GUESS
----------------------------------------------------------------------------------------

local require 		= GLOBAL.require
_G 					= GLOBAL
local setmetatable 	= _G.setmetatable
local getmetatable 	= _G.getmetatable
local tonumber 		= _G.tonumber
require "class"
local Builder 		= require "components/builder"

----------------------------------------------------------------------------------------
--CONFIG VALUES
----------------------------------------------------------------------------------------
local config_CraftingDifficulty 			= GetModConfigData("Crafting_Difficulty")
--local config_SanityPenalty 				= GetModConfigData("Sanity_Penalty")

_G.TUNNELSANITYPENALTY = GetModConfigData("Sanity_Penalty")
----------------------------------------------------------------------------------------
--PREFAB FILES
----------------------------------------------------------------------------------------

PrefabFiles = 
{
	"tunnel",
	"flag",
}

----------------------------------------------------------------------------------------
--ASSETS
----------------------------------------------------------------------------------------
Assets = 
{
	Asset("ATLAS", 			"images/inventoryimages/tunnel.xml"),
	Asset("SOUNDPACKAGE", 	"sound/tunnel.fev"),
    Asset("SOUND", 			"sound/tunnel.fsb"),
	Asset( "IMAGE", 		"minimap/minimap_tunnel.tex" ),
	Asset( "ATLAS", 		"minimap/minimap_tunnel.xml" ),
}

AddMinimapAtlas("minimap/minimap_tunnel.xml")

----------------------------------------------------------------------------------------
--Utility Functions
----------------------------------------------------------------------------------------
_G.DebugMe = function(obj, levels, seen)
	prefix = "[PARENT]"
	
	if not seen then seen = {} end
	
	if not levels then levels = 0 else levels = levels + 1 end
	
	if levels > 0 then prefix = "["..tostring(levels).."]" end
	
	if obj then
		seen[obj] = true
		print("DebugMe: "..type(obj).."["..tostring(obj).."]")
		for k, v in pairs(obj) do
			print(prefix.."KV: "..type(k).."["..tostring(k).."] | "..type(v).."["..tostring(v).."]")
			if type(v) == "table" and not seen[v] then
				seen[v] = true
				_G.DebugMe(obj, levels, seen)
			end
		end
		
		if levels > 0 then levels = levels - 1 end
		print("End of OBJ [", obj, "]")
	else
		print("DebugMe: "..type(obj))
	end
	
	print("DEBUGME FINISH")
end

_G.Truncate = function(num)
  return tonumber(string.format("%." .. 0 .. "f", num))
end

----------------------------------------------------------------------------------------
--Functions that replace other functions
----------------------------------------------------------------------------------------

--We jump into our tunnels similarly (exactly) to wormholes
GLOBAL.ACTIONS.JUMPIN.fn = function(act)
    if act.target.components.teleporter then
	    act.target.components.teleporter:Activate(act.doer)
	    return true
	elseif act.target.components.tunnelteleporter then 
		act.target.components.tunnelteleporter:Activate(act.doer)
		return true
	end
end

GLOBAL.ACTIONS.JUMPIN.strfn = function(act)
	if act.target.components.tunnelteleporter.getverb then -- This part causes crash when approaching Wormhole
		return act.target.components.tunnelteleporter.getverb(act.target, act.doer)
	elseif act.target.components.teleporter.getverb then -- This part causes crash when approaching Tunnel
		return act.target.components.teleporter.getverb(act.target, act.doer)
	end
end

function Builder:CanBuildAtPoint(pt, recipe)
	local ground = _G.GetWorld()
    local tile = _G.GROUND.GRASS
    if ground and _G.GROUND.Map then
        tile = _G.GROUND.Map:GetTileAtPoint(pt:Get())
    end
	
	if recipe.name == "tunnel" and (_G.GetWorld():IsCave() or _G.GetWorld():IsRuins()) then
		return false
	end

	if tile == _G.GROUND.IMPASSABLE then
		return false
	else
		local ents = TheSim:FindEntities(pt.x,pt.y,pt.z, 6, nil, {'player', 'fx', 'NOBLOCK'}) -- or we could include a flag to the search?
		for k, v in pairs(ents) do
			if v ~= self.inst and (not v.components.placer) and v.entity:IsVisible() and not (v.components.inventoryitem and v.components.inventoryitem.owner ) then
				local min_rad = recipe.min_spacing or 2+1.2
				--local rad = (v.Physics and v.Physics:GetRadius() or 1) + 1.25
				
				--stupid finalling hack because it's too late to change stuff
				if recipe.name == "treasurechest" and v.prefab == "pond" then
					min_rad = min_rad + 1
				end

				local dsq = _G.distsq(_G.Vector3(v.Transform:GetWorldPosition()), pt)
				if dsq <= min_rad*min_rad then
					return false
				end
			end
		end
	end
	
	return true
end

----------------------------------------------------------------------------------------
--Character dialogue
----------------------------------------------------------------------------------------

GLOBAL.STRINGS.NAMES.TUNNEL = "Tunnel"
GLOBAL.STRINGS.RECIPE_DESC.TUNNEL = "Make a tunnel network"

GLOBAL.STRINGS.CHARACTERS.GENERIC.DESCRIBE.TUNNEL 			= "Two of these make a network"
GLOBAL.STRINGS.CHARACTERS.WAXWELL.DESCRIBE.TUNNEL 			= "Tch"
GLOBAL.STRINGS.CHARACTERS.WENDY.DESCRIBE.TUNNEL 			= "This hole... it was made for me"
GLOBAL.STRINGS.CHARACTERS.WICKERBOTTOM.DESCRIBE.TUNNEL 		= "Rather primitive"
GLOBAL.STRINGS.CHARACTERS.WILLOW.DESCRIBE.TUNNEL 			= "Shall we set it ablaze?"
GLOBAL.STRINGS.CHARACTERS.WOODIE.DESCRIBE.TUNNEL 			= "Mm.. Chewy"
GLOBAL.STRINGS.CHARACTERS.WOLFGANG.DESCRIBE.TUNNEL 			= "Large muscles; tiny hole"
GLOBAL.STRINGS.CHARACTERS.WX78.DESCRIBE.TUNNEL 				= "QUESTIONABLE PATHFINDING"

GLOBAL.STRINGS.CHARACTERS.GENERIC.ANNOUNCE_TUNNEL 			= "I only remember going in"
GLOBAL.STRINGS.CHARACTERS.WX78.ANNOUNCE_TUNNEL 				= "LOGIC CIRCUITS FRIGHTENED"

if GLOBAL.IsDLCEnabled(GLOBAL.REIGN_OF_GIANTS) then 
	GLOBAL.STRINGS.CHARACTERS.WATHGRITHR.DESCRIBE.TUNNEL 	= "I could fit so much blood in that"
	GLOBAL.STRINGS.CHARACTERS.WEBBER.DESCRIBE.TUNNEL 		= "A perfect place for my kind"
end

--[[
inst:ListenForEvent("tunneltravel", function(inst, data)
	inst.components.talker:Say(GetString(inst.prefab, "ANNOUNCE_TUNNEL"))
end)
--]]

----------------------------------------------------------------------------------------
--CONFIG SETUP
----------------------------------------------------------------------------------------
if GLOBAL.IsDLCEnabled(GLOBAL.CAPY_DLC) then
	if config_CraftingDifficulty  == "casual" then
		local tunnel = GLOBAL.Recipe("tunnel",
		{
			Ingredient("boards", 4), 
			Ingredient("rocks", 5), 
			Ingredient("rope", 1),
			Ingredient("twigs", 2),
			Ingredient("shovel", 1),
		},  
		GLOBAL.RECIPETABS.TOWN, GLOBAL.TECH.SCIENCE_ONE, GLOBAL.RECIPE_GAME_TYPE.COMMON, "tunnel_placer" )
		tunnel.atlas = "images/inventoryimages/tunnel.xml"
		tunnel.minspacing = 6.4
	elseif config_CraftingDifficulty  == "moderate" then
		local tunnel = GLOBAL.Recipe("tunnel",
		{
			Ingredient("boards", 4), 
			Ingredient("rocks", 5),
			Ingredient("rope", 1),
			Ingredient("papyrus", 1),
			Ingredient("goldenshovel", 1),
		},  
		GLOBAL.RECIPETABS.TOWN, GLOBAL.TECH.SCIENCE_ONE, GLOBAL.RECIPE_GAME_TYPE.COMMON, "tunnel_placer" )
		tunnel.atlas = "images/inventoryimages/tunnel.xml"
		tunnel.minspacing = 6.4
	elseif config_CraftingDifficulty  == "difficult" then
		local tunnel = GLOBAL.Recipe("tunnel",
		{
			Ingredient("boards", 8), 
			Ingredient("rocks", 10),
			Ingredient("rope", 1),
			Ingredient("papyrus", 2),
			Ingredient("goldenshovel", 1),
		},  
		GLOBAL.RECIPETABS.TOWN, GLOBAL.TECH.SCIENCE_ONE, GLOBAL.RECIPE_GAME_TYPE.COMMON, "tunnel_placer" )
		tunnel.atlas = "images/inventoryimages/tunnel.xml"
		tunnel.minspacing = 6.4
else
	if config_CraftingDifficulty  == "casual" then
		local tunnel = GLOBAL.Recipe("tunnel",
		{
			Ingredient("boards", 4), 
			Ingredient("rocks", 5), 
			Ingredient("rope", 1),
			Ingredient("twigs", 2),
			Ingredient("shovel", 1),
		},  
		GLOBAL.RECIPETABS.TOWN, GLOBAL.TECH.SCIENCE_ONE, "tunnel_placer" )
		tunnel.atlas = "images/inventoryimages/tunnel.xml"
		tunnel.minspacing = 6.4
	elseif config_CraftingDifficulty  == "moderate" then
		local tunnel = GLOBAL.Recipe("tunnel",
		{
			Ingredient("boards", 4), 
			Ingredient("rocks", 5),
			Ingredient("rope", 1),
			Ingredient("papyrus", 1),
			Ingredient("goldenshovel", 1),
		},  
		GLOBAL.RECIPETABS.TOWN, GLOBAL.TECH.SCIENCE_ONE, "tunnel_placer" )
		tunnel.atlas = "images/inventoryimages/tunnel.xml"
		tunnel.minspacing = 6.4
	elseif config_CraftingDifficulty  == "difficult" then
		local tunnel = GLOBAL.Recipe("tunnel",
		{
			Ingredient("boards", 8), 
			Ingredient("rocks", 10),
			Ingredient("rope", 1),
			Ingredient("papyrus", 2),
			Ingredient("goldenshovel", 1),
		},  
		GLOBAL.RECIPETABS.TOWN, GLOBAL.TECH.SCIENCE_ONE, "tunnel_placer" )
		tunnel.atlas = "images/inventoryimages/tunnel.xml"
		tunnel.minspacing = 6.4
	end
end
end

----------------------------------------------------------------------------------------
--Tunnel Manager keeps track of which tunnels are orphans and pairs up tunnels
----------------------------------------------------------------------------------------

function ForestPrefabPostInit(inst)
	inst:AddComponent("tunnel_manager")
end

AddPrefabPostInit("forest", ForestPrefabPostInit)

--For some reason the wormhole sound effect is in the player Jump stategraph...
_G.jumpintimeline = {}

function SimPostInit(player)
	--Store this timeline
	local state = player.sg.sg.states["jumpin"]
	_G.jumpintimeline = state.timeline
end

_G.DisableWormholeJumpNoise = function()
	local player = _G.GetPlayer()
	local state = player.sg.sg.states["jumpin"]
	state.timeline = nil
end

_G.EnableWormholeJumpNoise = function()
	local player = _G.GetPlayer()
	local state = player.sg.sg.states["jumpin"]
	state.timeline = _G.jumpintimeline
end

AddSimPostInit(SimPostInit)

 

tunnel.lua

Spoiler

require "prefabutil"

local assets =
{
	Asset("ANIM", 			"anim/tunnel.zip" ),
	Asset("SOUNDPACKAGE", 	"sound/tunnel.fev"),
    Asset("SOUND", 			"sound/tunnel.fsb"),
}

local prefabs =
{
    "prefabs/flag",
}   

local function GetStatus(inst)
	if inst.sg.currentstate.name ~= "idle" then
		return "OPEN"
	end
end

local function OnHit(inst, worker)
	if IsDLCEnabled(REIGN_OF_GIANTS) == "enabled" then 
		if not inst:HasTag("burnt") then
			inst.AnimState:PlayAnimation("hit")
		end
	else
		inst.AnimState:PlayAnimation("hit")
	end
end

local function OnHammered(inst, worker)
	if IsDLCEnabled(REIGN_OF_GIANTS) == "enabled" then 
		if inst:HasTag("fire") and inst.components.burnable then
			inst.components.burnable:Extinguish()
		end
	end
	
	inst.components.lootdropper:DropLoot()
	SpawnPrefab("collapse_big").Transform:SetPosition(inst.Transform:GetWorldPosition())
	inst.SoundEmitter:PlaySound("dontstarve/common/destroy_wood")
	
	inst:RemoveComponent("tunnelteleporter")
	inst:Remove()
end

local function onsave(inst, data)
	if inst:HasTag("burnt") or inst:HasTag("fire") then
        data.burnt = true
    end
end

local function onload(inst, data)
	if data and data.burnt then
        inst.components.burnable.onburnt(inst)
    end
	
	inst:ListenForEvent("onremove", OnRemove(inst))
end

local function onremove(inst)
	inst:RemoveEventCallback("onremove", onremove, inst)
end

local function onbuilt(inst)
	inst:RemoveEventCallback("onbuilt", onbuilt, inst)
	
	--We have to wait because they don't have coordinates yet
	inst:DoTaskInTime(1, function(inst) 
		GetWorld().components.tunnel_manager:InitTunnel(inst)
	end)
end



local function fn(Sim)
	local inst = CreateEntity()
	local trans = inst.entity:AddTransform()
	local anim = inst.entity:AddAnimState()
	
    inst.entity:AddSoundEmitter()
	inst:AddTag("tunnel") 
    
    local minimap = inst.entity:AddMiniMapEntity()
    minimap:SetIcon( "minimap_tunnel.tex" )
   
    anim:SetBank("tunnel")
    anim:SetBuild("tunnel")
	anim:SetRayTestOnBB(true)
	
	inst:AddComponent("paintable")
    inst.components.paintable:AddThing("flag")
	inst.components.paintable:SetParent(inst)
	inst.components.paintable:Paint()
	
	inst:SetStateGraph("SGtunnel")
	
	inst:AddTag("structure")
 
	inst:AddComponent("lootdropper")
	inst:AddComponent("workable")
    inst.components.workable:SetWorkAction(ACTIONS.HAMMER)
    inst.components.workable:SetWorkLeft(4)
	inst.components.workable:SetOnWorkCallback(OnHit)
	inst.components.workable:SetOnFinishCallback(OnHammered)
	
    inst:AddComponent("inspectable")
	inst.components.inspectable.getstatus = GetStatus
	inst.components.inspectable:RecordViews()

	inst:AddComponent("tunnelteleporter")
	--inst.components.teleporter.onActivate = OnActivate
	--inst.components.teleporter.onActivateOther = OnActivateOther

	inst:AddComponent("playerprox")
	inst.components.playerprox:SetDist(4,5)
	inst.components.playerprox.onnear = function()
		--if inst.components.teleporter.targetTeleporter ~= nil and not inst.sg:HasStateTag("open") then
			if inst.components.tunnelteleporter.target then
				inst.sg:GoToState("opening")
				_G.DisableWormholeJumpNoise()
			end
		--end
	end
	
	inst.components.playerprox.onfar = function()
		if inst.sg.currentstate.name == "open" then
			inst.sg:GoToState("closing")
			_G.EnableWormholeJumpNoise()
		end
		--inst.SoundEmitter:PlaySound("dontstarve/tunnel/common/close")
	end

	inst:AddComponent("inventory")

	inst:AddComponent("trader")
	inst.components.trader.onaccept = function(reciever, giver, item)
		-- pass this on to our better half
		reciever.components.inventory:DropItem(item)
		inst.components.tunnelteleporter:Activate(item)
	end
	
	if IsDLCEnabled(REIGN_OF_GIANTS) or IsDLCEnabled(CAPY_DLC) == "enabled" then 
		MakeLargeBurnable(inst, nil, nil, true)
		MakeLargePropagator(inst)

		inst.OnSave = onsave 
		inst.OnLoad = onload
	end
	
	inst:ListenForEvent( "onbuilt", onbuilt(inst))
	inst:ListenForEvent( "onremove", onremove(inst))
	
	--print("LOOKING...", StateGraphWrangler:Find())

    return inst
end

return Prefab( "common/objects/tunnel", fn, assets), 
	   MakePlacer( "common/tunnel_placer", "tunnel", "tunnel", "place" ) 

 

tunnelteleporter.lua

Spoiler

local TunnelTeleporter = Class(function(self, inst)
    self.inst = inst
	self.target = nil
end)

function TunnelTeleporter:CollectSceneActions(doer, actions)
	--print("numactions: ", #actions)
	if self.target ~= nil and self.target.components.tunnelteleporter then
		table.insert(actions, ACTIONS.JUMPIN)
	elseif #actions > 0 then
		table.remove(actions)
	end
end

function TunnelTeleporter:OnActivate(doer)
	if doer:HasTag("player") then
		doer.SoundEmitter:KillSound("wormhole_travel")
		doer.SoundEmitter:PlaySound("tunnel/common/travel")
		doer.components.health:SetInvincible(true)
		doer.components.playercontroller:Enable(false)

		GetPlayer().HUD:Hide()
		TheFrontEnd:SetFadeLevel(1)
		doer:DoTaskInTime(1, function() 
			TheFrontEnd:Fade(true,2)
			GetPlayer().HUD:Show()
			doer.sg:GoToState("wakeup")
			
			if doer.components.sanity then
				doer.components.sanity:DoDelta(_G.TUNNELSANITYPENALTY)
			end
			
		end)
		doer:DoTaskInTime(5, function()
			doer:PushEvent("tunneltravel")
			doer.components.health:SetInvincible(false)
			doer.components.playercontroller:Enable(true)
		end)
		
	elseif doer.SoundEmitter then
		--inst.SoundEmitter:PlaySound("dontstarve/common/teleportworm/swallow", "wormhole_swallow")
	end
end

function TunnelTeleporter:OnActivateOther(other, doer)
	other.sg:GoToState("open")
end

function TunnelTeleporter:Activate(doer)
	if self.target == nil then
		return
	end
	
	self:OnActivate(doer)
	self:OnActivateOther(self.target, doer)
	
	self:Teleport(doer)

	if doer.components.leader then
		for follower,v in pairs(doer.components.leader.followers) do
			self:Teleport(follower)
		end
	end

	local eyebone = nil

	--special case for the chester_eyebone: look for inventory items with followers
	if doer.components.inventory then
		for k,item in pairs(doer.components.inventory.itemslots) do
			if item.components.leader then
				if item:HasTag("chester_eyebone") then
					eyebone = item
				end
				for follower,v in pairs(item.components.leader.followers) do
					self:Teleport(follower)
				end
			end
		end
		-- special special case, look inside equipped containers
		for k,equipped in pairs(doer.components.inventory.equipslots) do
			if equipped and equipped.components.container then
				local container = equipped.components.container
				for j,item in pairs(container.slots) do
					if item.components.leader then
						if item:HasTag("chester_eyebone") then
							eyebone = item
						end
						for follower,v in pairs(item.components.leader.followers) do
							self:Teleport(follower)
						end
					end
				end
			end
		end
		-- special special special case: if we have an eyebone, then we have a container follower not actually in the inventory. Look for inventory items with followers there.
		if eyebone and eyebone.components.leader then
			for follower,v in pairs(eyebone.components.leader.followers) do
				if follower and (not follower.components.health or (follower.components.health and not follower.components.health:IsDead())) and follower.components.container then
					for j,item in pairs(follower.components.container.slots) do
						if item.components.leader then
							for follower,v in pairs(item.components.leader.followers) do
								if follower and (not follower.components.health or (follower.components.health and not follower.components.health:IsDead())) then
									self:Teleport(follower)
								end
							end
						end
					end
				end
			end
		end
	end
end

-- You probably don't want this, call Activate instead.
function TunnelTeleporter:Teleport(obj)
	if self.target ~= nil then
		local offset = 2.0
		local angle = math.random()*360
		local target_x, target_y, target_z = self.target.Transform:GetWorldPosition()
		target_x = target_x + math.sin(angle)*offset
		target_z = target_z + math.cos(angle)*offset
		if obj.Physics then
			obj.Physics:Teleport( target_x, target_y, target_z )
		elseif obj.Transform then
			obj.Transform:SetPosition( target_x, target_y, target_z )
		end
	end
end


function TunnelTeleporter:Target(otherTunnelTeleporter)
	self.target = otherTunnelTeleporter
end

function TunnelTeleporter:OnSave()
	if self.target ~= nil then
		return { target=self.target.GUID }, {self.target.GUID}
	end
	return {}
end

function TunnelTeleporter:LoadPostPass(newents, savedata)
	if savedata and savedata.target then
		local targEnt = newents[savedata.target]
		if targEnt and targEnt.entity.components.tunnelteleporter then
			self.target = targEnt.entity
		end
	end
end



return TunnelTeleporter

 

Help is very very (EDIT: VERY VERY) much appreciated haha

Edited by Gigadroid
Link to comment
https://forums.kleientertainment.com/forums/topic/65770-solved-craftable-tunnels/
Share on other sites

Remember to check the SW scripts when playing with SW. The actions.lua in DLC_00002 has >1400 lines of code.

ACTIONS.JUMPIN.strfn = function(act)
    if act.target.components.teleporter.getverb then
        return act.target.components.teleporter.getverb(act.target, act.doer)
    end
end

As you can see, the action "jumpin" now has a "strfn", as string-function. You need to edit that in a fashion similiar to the action-function.

Ah I see. I still don't know how to fix it but I'll be trying my best with trial and error. 

Would love more help from anyone haha :)

 

EDIT: HOLY HELL IT WORKED.

I just added this to modmain.lua:

GLOBAL.ACTIONS.JUMPIN.strfn = function(act)
	-- if act.target.components.teleporter.getverb then
	-- 	return act.target.components.teleporter.getverb(act.target, act.doer)
	-- else
	if act.target.components.tunnelteleporter.getverb then
		return act.target.components.tunnelteleporter.getverb(act.target, act.doer)
	end
end

Not sure if this will screw up wormholes, testing now.

EDIT: Yeah it screws it up. Hmmmmm

Edited by Gigadroid

Try this:

local fn_jumpin = GLOBAL.ACTIONS.JUMPIN.fn
GLOBAL.ACTIONS.JUMPIN.fn = function(act)
	local ret = fn_jumpin(act) --We want to return the return value of the old function...
	if act.target.components.tunnelteleporter then
		act.target.components.tunnelteleporter:Activate(act.doer)
		return true
	end
    return ret --But not before we run the new funtionality
end

 

Edited by Arkathorn
3 hours ago, Arkathorn said:

Try this:


local fn_jumpin = GLOBAL.ACTIONS.JUMPIN.fn
GLOBAL.ACTIONS.JUMPIN.fn = function(act)
	local ret = fn_jumpin(act) --We want to return the return value of the old function...
	if act.target.components.tunnelteleporter then
		act.target.components.tunnelteleporter:Activate(act.doer)
		return true
	end
    return ret --But not before we run the new funtionality
end

 

Oh cool thank you for the suggestion! I'm curious, what about strfn? Do we have to deal with that?

Will test the code above now

EDIT: Tested the code above by changing the actions handling (in modmain.lua) to:

Spoiler

--We jump into our tunnels similarly (exactly) to wormholes
-- GLOBAL.ACTIONS.JUMPIN.fn = function(act)
-- 	if act.target.components.tunnelteleporter then 
-- 		act.target.components.tunnelteleporter:Activate(act.doer)
-- 		return true
--     elseif act.target.components.teleporter then
-- 	    act.target.components.teleporter:Activate(act.doer)
-- 	    return true
-- 	end
-- end

-- GLOBAL.ACTIONS.JUMPIN.strfn = function(act)
-- 	if act.target.components.tunnelteleporter.getverb then -- This part causes crash when approaching Wormhole
-- 		return act.target.components.tunnelteleporter.getverb(act.target, act.doer)
-- 	elseif act.target.components.teleporter.getverb then -- This part causes crash when approaching Tunnel
-- 		return act.target.components.teleporter.getverb(act.target, act.doer)
-- 	end
-- end

local fn_jumpin = GLOBAL.ACTIONS.JUMPIN.fn
GLOBAL.ACTIONS.JUMPIN.fn = function(act)
	local ret = fn_jumpin(act) --We want to return the return value of the old function...
	if act.target.components.tunnelteleporter then
		act.target.components.tunnelteleporter:Activate(act.doer)
		return true
	end
    return ret --But not before we run the new funtionality
end

Effect: Wormholes work as normal. Tunnels once again cause actions.lua:1044: attempt to index field 'teleporter' (a nil value). In the stack traceback, it mentioned actions.lua:1044 in (field) strfn (Lua) <1043-1047>. Does that mean we have to define ACTIONS.JUMPIN.strfn just like Mobbstar said? 

 

Edited by Gigadroid
2 hours ago, Arkathorn said:

The error is likely being caused by the 'strfn', yes. Just override the function to do the same thing, but encased in the following code:


if act.target.components.teleporter then
	--Do the normal code
end

 

I'm not sure I get what you're saying. 

Override which function specifically? To do the same thing as which function? 

To encase it would mean it would check if the tunnel is a 'teleporter', right? What is the 'normal code' you meant -> The JUMPIN.fn in actions.lua or the code you mentioned above (the one with local and ret)?

Once again, thanks for replying and providing help! I'm STILL super psyched to get this working. 

19 hours ago, Gigadroid said:

The original ACTIONS.JUMPIN.strfn (in actions.lua) doesn't check if it's a teleporter to begin with? Why would that affect the tunnels (which use tunnelteleporter instead)?

Nope. It affects the tunnels because they still use the same action, despite having a different component. The only vanilla thing that uses the 'JUMPIN' action is the Wormholes, so it doesn't bother verifying that it has the component.

2 hours ago, KingZed said:

log still says  tunnel.lua:69: attempt to index field 'tunnel_manager' (a nil value)

@KingZed Over the course of this I may have changed a few things. Here's a working version (tested on a SW-Compatible world. Not SW):

CraftableTunnels.zip

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