Jump to content

Recommended Posts

Hello, I need help trying to make a keyhandler action work better :)..

So, the code I need help with is

local BARRICADE = GLOBAL.Action()
BARRICADE.str = "Barricade"
BARRICADE.id = "BARRICADE"
BARRICADE.fn = function(act)

act.target.sg:GoToState("doshortaction")

act.target:DoTaskInTime(0.3, function()
local x, y, z = act.target.Transform:GetWorldPosition()
local barricade = GLOBAL.SpawnPrefab("wall_wood")
barricade.Transform:SetPosition(x, y, z)
end)

end

AddAction(BARRICADE)

i'm trying to make it that my character can place wood walls with the press of a button.

The problem is that spawning walls this way makes it spawn right where my character's standing causing movement glitches... So, I was wondering is there a way to make it that when my character activates this action it makes as if she's actually placing a wall? Like when you want to place a wall on the ground & there's some green wall holograph thingy, would that be possible?

EDIT: Can someone at least tell me if I can make walls spawn in a way that doesn't cause glitches :(? Anyone.....? *sobs*

Edited by SuperDavid

Can someone please help me fix a crash :)?

So, I wanna make my character be able to spawn walls without no glitchyness... So, I took code from ondeploy from walls.lua

and did this

local BARRICADE = GLOBAL.Action()
BARRICADE.str = "Barricade"
BARRICADE.id = "BARRICADE"
BARRICADE.fn = function(act, pt, deployer)

        local wall = GLOBAL.SpawnPrefab("wall_wood") 
        if wall ~= nil then 
            local x = math.floor(pt.x) + .5
            local z = math.floor(pt.z) + .5
            wall.Physics:SetCollides(false)
            wall.Physics:Teleport(x, 0, z)
            wall.Physics:SetCollides(true)
            inst.components.stackable:Get():Remove()

            TheWorld.Pathfinder:AddWall(x, 0, z)

            if data.buildsound ~= nil then
                wall.SoundEmitter:PlaySound(data.buildsound)
            end
        end
end

AddAction(BARRICADE)

but the game crashes saying there's no local pt but in the walls.lua there was no local pt so i'm sooo confused :shock:!?!?! Can someone please tell me why this's happening :shock:?

Thanks a lot for reading my problem, have great day :D!!!

You don't really think it's a bit weird to just add new arguments to the action function and expect them to appear and work out of thin air?

local BARRICADE = GLOBAL.Action()
BARRICADE.str = "Barricade"
BARRICADE.id = "BARRICADE"
BARRICADE.fn = function(act)
	local pt = act.pos
	local deployer = act.doer
	if pt and deployer then
		local wall = GLOBAL.SpawnPrefab("wall_wood")
		if wall ~= nil then
			local x = math.floor(pt.x) + 0.5
			local z = math.floor(pt.z) + 0.5
			wall.Physics:SetCollides(false)
			wall.Physics:Teleport(x, 0, z)
			wall.Physics:SetCollides(true)

			GLOBAL.TheWorld.Pathfinder:AddWall(x, 0, z)

			wall.SoundEmitter:PlaySound("dontstarve/common/place_structure_wood")
		end
	end
end

AddAction(BARRICADE)

 

Thank you very much DarkXero :D!

14 minutes ago, DarkXero said:

You don't really think it's a bit weird to just add new arguments to the action function and expect them to appear and work out of thin air?

I'm sorry i'm not really smart so I hope I be able to learn :)!

Also, i'm sorry to bother you but can I maybe ask when I use this code

local BARRICADE = GLOBAL.Action()
BARRICADE.str = "Barricade"
BARRICADE.id = "BARRICADE"
BARRICADE.fn = function(act, pt, deployer, doer)
	local pt = act.pos
	local deployer = act.doer
	if pt and deployer then
		local wall = GLOBAL.SpawnPrefab("wall_wood")
		if wall ~= nil then
			local x = math.floor(pt.x) + 0.5
			local z = math.floor(pt.z) + 0.5
			wall.Physics:SetCollides(false)
			wall.Physics:Teleport(x, 0, z)
			wall.Physics:SetCollides(true)

			GLOBAL.TheWorld.Pathfinder:AddWall(x, 0, z)

			wall.SoundEmitter:PlaySound("dontstarve/common/place_structure_wood")
		end
	end
end

AddAction(BARRICADE)

and I try to preform the action by pressing the key nothing happens? No wall spawns..do you maybe know why? Sorry to annoy you :D...

Stop adding new parameters to the action function. It doesn't work that way.

I removed deployer, in case that was causing a problem.

local BARRICADE = GLOBAL.Action()
BARRICADE.str = "Barricade"
BARRICADE.id = "BARRICADE"
BARRICADE.fn = function(act)
	local pt = act.pos
	if pt then
		local wall = GLOBAL.SpawnPrefab("wall_wood")
		if wall ~= nil then
			local x = math.floor(pt.x) + 0.5
			local z = math.floor(pt.z) + 0.5
			wall.Physics:SetCollides(false)
			wall.Physics:Teleport(x, 0, z)
			wall.Physics:SetCollides(true)

			GLOBAL.TheWorld.Pathfinder:AddWall(x, 0, z)

			wall.SoundEmitter:PlaySound("dontstarve/common/place_structure_wood")
		end
	end
end

AddAction(BARRICADE)

But you should post how do you call the BufferedAction:Do() to run the action.

You should be sending the correct arguments in the correct order.

I use the code you gave me

local BARRICADE = GLOBAL.Action()
BARRICADE.str = "Barricade"
BARRICADE.id = "BARRICADE"
BARRICADE.fn = function(act)
	local pt = act.pos
	if pt then
		local wall = GLOBAL.SpawnPrefab("wall_wood")
		if wall ~= nil then
			local x = math.floor(pt.x) + 0.5
			local z = math.floor(pt.z) + 0.5
			wall.Physics:SetCollides(false)
			wall.Physics:Teleport(x, 0, z)
			wall.Physics:SetCollides(true)

			GLOBAL.TheWorld.Pathfinder:AddWall(x, 0, z)

			wall.SoundEmitter:PlaySound("dontstarve/common/place_structure_wood")
		end
	end
end

AddAction(BARRICADE)

and still nothing happened :shock:!

12 minutes ago, DarkXero said:

But you should post how do you call the BufferedAction:Do() to run the action.

By this you mean how this action gets activated, right? If that's what you saying then the actions get activated from this in amazon.lua

local function OnKeyPressed(inst, data)
  if data.inst == ThePlayer then
    if data.key == KEY_LALT then
      if TheWorld.ismastersim then
      BufferedAction(inst, inst, ACTIONS.AMAZON_DODGE):Do()
      else
      SendRPCToServer(RPC.DoWidgetButtonAction, ACTIONS.AMAZON_DODGE.code, inst, ACTIONS.AMAZON_DODGE.mod_name)
      end
	  elseif data.key == KEY_LEFTBRACKET then
      if TheWorld.ismastersim then
      BufferedAction(inst, inst, ACTIONS.LIGHTNING):Do()
      else
      SendRPCToServer(RPC.DoWidgetButtonAction, ACTIONS.LIGHTNING.code, inst, ACTIONS.LIGHTNING.mod_name)
      end
	  elseif data.key == KEY_RIGHTBRACKET then
      if TheWorld.ismastersim then
      BufferedAction(inst, inst, ACTIONS.BARRICADE):Do()
      else
      SendRPCToServer(RPC.DoWidgetButtonAction, ACTIONS.BARRICADE.code, inst, ACTIONS.BARRICADE.mod_name)
      end 
    end
  end
end

 

Nothing happened because the action requires a position.

And you send no such thing.

The only thing you send on the RPC is the doer (implied inst) and the target (inst).

The BufferedAction also gets inst as doer and target.

So all the action has to work with is the doer parameter on act.

local BARRICADE = GLOBAL.Action()
BARRICADE.str = "Barricade"
BARRICADE.id = "BARRICADE"
BARRICADE.fn = function(act)
	local doer = act.doer
	local pt = doer and doer:GetPosition()
	if pt then
		local wall = GLOBAL.SpawnPrefab("wall_wood")
		if wall ~= nil then
			local x = math.floor(pt.x) + 0.5
			local z = math.floor(pt.z) + 0.5
			wall.Physics:SetCollides(false)
			wall.Physics:Teleport(x, 0, z)
			wall.Physics:SetCollides(true)

			GLOBAL.TheWorld.Pathfinder:AddWall(x, 0, z)

			wall.SoundEmitter:PlaySound("dontstarve/common/place_structure_wood")
		end
	end
end

AddAction(BARRICADE)

 

Thank you very much DarkXero everything works great now :D! Thank you, thank you!!!

@DarkXero I'm super sorry! But...if I can just ask 2 more things, i'm super sorry for pestering you a lot :(...

Would it be possible to make it that when this action's activated it checks her inventory to see if she has 1 gold nugget in it and delete the gold nugget & if she has no gold nugget it just does "return"?

Also, would it be possible to make that she can't build walls near the ocean or darkness of caves because she can glitch out of the world (this would probably not be possible, right)?

 

Edited by SuperDavid
1 hour ago, SuperDavid said:

Would it be possible to make it that when this action's activated it checks her inventory to see if she has 1 gold nugget in it and delete the gold nugget & if she has no gold nugget it just does "return"?

Also, would it be possible to make that she can't build walls near the ocean or darkness of caves because she can glitch out of the world (this would probably not be possible, right)?

local BARRICADE = GLOBAL.Action()
BARRICADE.str = "Barricade"
BARRICADE.id = "BARRICADE"
BARRICADE.fn = function(act)
	local doer = act.doer
	local pt = doer and doer:GetPosition()
	if pt == nil then
		return
	end

	local inventory = doer.components.inventory
	if inventory and inventory:Has("goldnugget", 1) then
		inventory:ConsumeByName("goldnugget", 1)
	else
		return
	end

	local water_offset = GLOBAL.FindValidPositionByFan(0, 8, 8, function(offset)
		local run_point = pt + offset
		return not GLOBAL.TheWorld.Map:IsAboveGroundAtPoint(run_point.x, run_point.y, run_point.z)
	end)
	if water_offset ~= nil then
		return
	end

	local wall = GLOBAL.SpawnPrefab("wall_wood")
	if wall ~= nil then
		local x = math.floor(pt.x) + 0.5
		local z = math.floor(pt.z) + 0.5
		wall.Physics:SetCollides(false)
		wall.Physics:Teleport(x, 0, z)
		wall.Physics:SetCollides(true)

		GLOBAL.TheWorld.Pathfinder:AddWall(x, 0, z)

		wall.SoundEmitter:PlaySound("dontstarve/common/place_structure_wood")
	end
end

AddAction(BARRICADE)

Try this.

FindValidPositionByFan(start_angle, radius, attempts, test_fn)

You can edit the first 8 if the radius is too big.

23 minutes ago, DarkXero said:

local BARRICADE = GLOBAL.Action()
BARRICADE.str = "Barricade"
BARRICADE.id = "BARRICADE"
BARRICADE.fn = function(act)
	local doer = act.doer
	local pt = doer and doer:GetPosition()
	if pt == nil then
		return
	end

	local inventory = doer.components.inventory
	if inventory and inventory:Has("goldnugget", 1) then
		inventory:ConsumeByName("goldnugget", 1)
	else
		return
	end

	local water_offset = GLOBAL.FindValidPositionByFan(0, 8, 8, function(offset)
		local run_point = pt + offset
		return not GLOBAL.TheWorld.Map:IsAboveGroundAtPoint(run_point.x, run_point.y, run_point.z)
	end)
	if water_offset ~= nil then
		return
	end

	local wall = GLOBAL.SpawnPrefab("wall_wood")
	if wall ~= nil then
		local x = math.floor(pt.x) + 0.5
		local z = math.floor(pt.z) + 0.5
		wall.Physics:SetCollides(false)
		wall.Physics:Teleport(x, 0, z)
		wall.Physics:SetCollides(true)

		GLOBAL.TheWorld.Pathfinder:AddWall(x, 0, z)

		wall.SoundEmitter:PlaySound("dontstarve/common/place_structure_wood")
	end
end

AddAction(BARRICADE)

Try this.

Thank you so much DarkXero it works perfectly!! If you can just make it that it doesn't consume goldnuggets when you're in the radius where walls won't spawn that can be great, instead can you make it say something " act.target.components.talker:Say("I'm too close to the edge!") " that would be so perfect, seriously your amazing! Klei should hire you to work as a Don't Starve developer it's almost like there's nothing you don't know when it comes to coding xD!!

And again... Thank you, thank you, thank you :D:D!!!!!

 

PS. I'm kinda dumb so just another question.. 

FindValidPositionByFan(start_angle, radius, attempts, test_fn)

Am I supposed to put that somewhere or it was just a example for changing the radius of not placing walls at the edge?

Edited by SuperDavid

Oh yeah, I botched the code structure because I rewrote it at the last moment.

local BARRICADE = GLOBAL.Action()
BARRICADE.str = "Barricade"
BARRICADE.id = "BARRICADE"
BARRICADE.fn = function(act)
	local doer = act.doer
	local pt = doer and doer:GetPosition()
	if pt == nil then
		return
	end

	local water_offset = GLOBAL.FindValidPositionByFan(0, 8, 8, function(offset)
		local run_point = pt + offset
		return not GLOBAL.TheWorld.Map:IsAboveGroundAtPoint(run_point.x, run_point.y, run_point.z)
	end)
	if water_offset ~= nil then
		return
	end

	local inventory = doer.components.inventory
	if inventory and inventory:Has("goldnugget", 1) then
		inventory:ConsumeByName("goldnugget", 1)
	else
		return
	end

	local wall = GLOBAL.SpawnPrefab("wall_wood")
	if wall ~= nil then
		local x = math.floor(pt.x) + 0.5
		local z = math.floor(pt.z) + 0.5
		wall.Physics:SetCollides(false)
		wall.Physics:Teleport(x, 0, z)
		wall.Physics:SetCollides(true)

		GLOBAL.TheWorld.Pathfinder:AddWall(x, 0, z)

		wall.SoundEmitter:PlaySound("dontstarve/common/place_structure_wood")
	end
end

AddAction(BARRICADE)

This should be the proper order.

32 minutes ago, SuperDavid said:

Am I supposed to put that somewhere or it was just a example for changing the radius of not placing walls at the edge?

An example. It was so you understood the parameters of that function.

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