Block projection problems

Post Reply
User avatar
Extex
Member
Posts: 244
Joined: Wed Mar 14, 2018 23:14
GitHub: Extex101
In-game: Extex

Block projection problems

by Extex » Post

I'm working on a mod that when holding a specific item it projects a beam of blocks that is removed later
Just make a mod called blockbeam and use this code:

Code: Select all

minetest.register_globalstep(function()
	for _, user in ipairs(minetest.get_connected_players()) do
		local stack = ItemStack(user:get_wielded_item())
		local wielded = stack:get_definition()
		if wielded.name == "blockbeam:beam_rod" then
			local dir = user:get_look_dir()
	        local pos = user:get_pos()
			

	        for i = 0, 20 do
	            local new_pos = {
	               x = pos.x + (dir.x * i),
	               y = pos.y + 1 + (dir.y * i),
	               z = pos.z + (dir.z * i),
	            }
	            if minetest.get_node(new_pos).name == "air"  then
	                minetest.set_node(new_pos, {name = "blockbeam:block"})
	            end
	         end
		end
	end
end)
minetest.register_node("blockbeam:block", {
	drawtype = "glasslike",
	tiles = {"blank.png"},
	paramtype = "light",
	walkable = false,
	is_ground_content = true,
	light_propagates = true,
	sunlight_propagates = true,
	light_source = 6,
	pointable = false,
	buildable_to = true, 
    on_construct = function(pos)
		minetest.after(0.1, function()
	        minetest.set_node(pos, {name = "air"})
	    end)
    end,
})
minetest.register_tool("blockbeam:rod", {
	description = "Beam Rod",
	inventory_image = "default_stick.png",
})
minetest.register_lbm({
	name = "blockbeam:remove_after_reload",
	nodenames = {"blockbeam:block"},
	run_at_every_load = true, 
	action = function(pos, node)
		minetest.set_node(pos, {name = "air"})
	end,
})
OK so it works just the way I want it to but how do I make the beam stop when it comes in contact with a solid block

I made a version using line_of_sight but when pointed down it glitches

Use this instead of the other globalstep to see my try at it

Code: Select all

local distance = function(pos1, pos2)
  local dx = pos1.x - pos2.x
  local dy = pos1.y - pos2.y
  local dz = pos1.z - pos2.z
  return math.floor( math.sqrt ( dx * dx + dy * dy + dz * dz))
end
minetest.register_globalstep(function()
	for _, user in ipairs(minetest.get_connected_players()) do
		local stack = ItemStack(user:get_wielded_item())
		local wielded = stack:get_definition()
		if wielded.name == "blockbeam:beam_rod" then
			local dir = user:get_look_dir()
	        local pos = user:get_pos()
			local new_pos1 = {
               x = pos.x + (dir.x * 20),
               y = pos.y + 1 + (dir.y * 20),
               z = pos.z + (dir.z * 20),
            }
            local a,b = minetest.line_of_sight(pos, new_pos1, 2)
            local dist = nil
            if b then
	            dist = distance(pos,b)
            elseif b == nil then
	            dist = nil
            end
            local range = 20
            if dist == nil then
	            range = 20
            elseif dist then
	            range = dist+1
            end
	        for i = 0, range do
	            local new_pos2 = {
	               x = pos.x + (dir.x * i),
	               y = pos.y + 1 + (dir.y * i),
	               z = pos.z + (dir.z * i),
	            }
	            if minetest.get_node(new_pos2).name == "air"  then
	                minetest.set_node(new_pos2, {name = "blockbeam:block"})
	            end
	         end
		end
	end
end)
Creator of jelys_pizzaria and motorbike, and player of persistent kingdoms. RIP

Eran
Member
Posts: 123
Joined: Fri May 03, 2019 16:46

Re: Block projection problems

by Eran » Post

Stopping the for loop using a break statement when a non-air node is encountered should work.

Code: Select all

minetest.register_globalstep(function()
   for _, user in ipairs(minetest.get_connected_players()) do
      local stack = ItemStack(user:get_wielded_item())
      local wielded = stack:get_definition()
      if wielded.name == "blockbeam:beam_rod" then
         local dir = user:get_look_dir()
           local pos = user:get_pos()
         

           for i = 0, 20 do
               local new_pos = {
                  x = pos.x + (dir.x * i),
                  y = pos.y + 1 + (dir.y * i),
                  z = pos.z + (dir.z * i),
               }
               if minetest.get_node(new_pos).name == "air"  then
                   minetest.set_node(new_pos, {name = "blockbeam:block"})
               else
                   break --my change
               end
            end
      end
   end
end)

neoh4x0r
Member
Posts: 82
Joined: Wed Aug 29, 2018 20:16
GitHub: neoh4x0r

Re: Block projection problems

by neoh4x0r » Post

Eran wrote:Stopping the for loop using a break statement when a non-air node is encountered should work.
Yes checking if the node is not air would work. Howevre, minetest.line_of_sight returns the position of a blocking node (if that position is not nil, then it could be used as the limit).

(The below code could use some tweaking/adjusting)

https://dev.minetest.net/minetest.line_of_sight
  • Returns true/false, pos
  • Returns the position of the blocking node when false
See also: https://dev.minetest.net/vector
The vector functions provide distance, length, etc between positions -- so you don't need to define a distance function.

Code: Select all

local dir = user:get_look_dir()
local pos = user:get_pos()
local range = 20
local new_pos1 = {
	x = pos.x + (dir.x * range),
	y = pos.y + 1 + (dir.y * range),
	z = pos.z + (dir.z * range),
}

local dist = vector.distance(pos, new_pos1)

if dist < range then
 range = dist -- if the dist is less than the range then limit range
end

local a,b = minetest.line_of_sight(pos, new_pos1, 2)

local is_not_blocked = a -- true when not blocked, false when blocked
local blocked_pos = b -- the position of the blocking node (when is_not_blocked is false), otherwise nil


if not is_not_blocked then -- line of sight is blocked and blocked_pos should not be nil
	if blocked_pos ~= nil then
		dist = vector.distance(pos, blocked_pos)
		-- set the range to be 1 node less than the blocked position
		-- again this value might need to be tweaked:
		-- ie dist  - (scale) ; scale could 0.25 or -0.25, or, 1.5 or -1.5, etc
		-- (as needed to move back 1 block)
		range = dist - 1
	else
		-- throw an error, as this wasn't expected
		-- if line_of_sight returns false, the line of sight is blocked and
		-- the blocked position should not be nil
	end
}

for i = 0, range do
               -- NOTE: using an integer scalar might not correspond to exactly one node
               -- it might need to be something like x + (dir.x * 0.25 * i) or similar
               -- the scalar value: 0.25 will need to be adjusted (increased / decreased) to make it
               -- correspond to exactly 1 node
               local new_pos2 = {
                  x = pos.x + (dir.x * i),
                  y = pos.y + 1 + (dir.y * i),
                  z = pos.z + (dir.z * i),
               }
               if minetest.get_node(new_pos2).name == "air"  then
                   minetest.set_node(new_pos2, {name = "blockbeam:block"})
               end
            end
end
Last edited by neoh4x0r on Fri Aug 09, 2019 17:34, edited 7 times in total.

User avatar
Extex
Member
Posts: 244
Joined: Wed Mar 14, 2018 23:14
GitHub: Extex101
In-game: Extex

Re: Block projection problems

by Extex » Post

----removed----
Creator of jelys_pizzaria and motorbike, and player of persistent kingdoms. RIP

Post Reply

Who is online

Users browsing this forum: No registered users and 2 guests