diff --git a/init.lua b/init.lua index 731a4a2..9b6aa0e 100644 --- a/init.lua +++ b/init.lua @@ -32,6 +32,36 @@ local node_fall_hurt = core.settings:get_bool("node_fall_hurt") ~= false local delay = 0.1 -- used to simulate lag local gravity = core.settings:get("movement_gravity") or 9.81 +local builtin_shared = ... +local SCALE = 0.667 + +local facedir_to_euler = { + {y = 0, x = 0, z = 0}, + {y = -math.pi/2, x = 0, z = 0}, + {y = math.pi, x = 0, z = 0}, + {y = math.pi/2, x = 0, z = 0}, + {y = math.pi/2, x = -math.pi/2, z = math.pi/2}, + {y = math.pi/2, x = math.pi, z = math.pi/2}, + {y = math.pi/2, x = math.pi/2, z = math.pi/2}, + {y = math.pi/2, x = 0, z = math.pi/2}, + {y = -math.pi/2, x = math.pi/2, z = math.pi/2}, + {y = -math.pi/2, x = 0, z = math.pi/2}, + {y = -math.pi/2, x = -math.pi/2, z = math.pi/2}, + {y = -math.pi/2, x = math.pi, z = math.pi/2}, + {y = 0, x = 0, z = math.pi/2}, + {y = 0, x = -math.pi/2, z = math.pi/2}, + {y = 0, x = math.pi, z = math.pi/2}, + {y = 0, x = math.pi/2, z = math.pi/2}, + {y = math.pi, x = math.pi, z = math.pi/2}, + {y = math.pi, x = math.pi/2, z = math.pi/2}, + {y = math.pi, x = 0, z = math.pi/2}, + {y = math.pi, x = -math.pi/2, z = math.pi/2}, + {y = math.pi, x = math.pi, z = 0}, + {y = -math.pi/2, x = math.pi, z = 0}, + {y = 0, x = math.pi, z = 0}, + {y = math.pi/2, x = math.pi, z = 0} +} + local function fall_hurt_check(self, pos) if self.hurt_toggle then @@ -72,7 +102,7 @@ core.register_entity(":__builtin:falling_node", { initial_properties = { visual = "wielditem", - visual_size = {x = 0.667, y = 0.667}, + visual_size = {x = SCALE, y = SCALE, z = SCALE}, textures = {}, physical = true, is_visible = false, @@ -115,125 +145,215 @@ core.register_entity(":__builtin:falling_node", { self.meta = meta - if def.drawtype == "airlike" then + -- Cache whether we're supposed to float on water + self.floats = core.get_item_group(node.name, "float") ~= 0 - self.object:set_properties({ - is_visible = false, - }) - - elseif def.drawtype == "torchlike" or def.drawtype == "signlike" then + -- Set entity visuals + if def.drawtype == "torchlike" or def.drawtype == "signlike" then local textures if def.tiles and def.tiles[1] then - if def.drawtype == "torchlike" then - textures = { - "(" .. def.tiles[1] .. ")^[transformFX", def.tiles[1]} - else - textures = { def.tiles[1] } + local tile = def.tiles[1] + + if type(tile) == "table" then + tile = tile.name end + + if def.drawtype == "torchlike" then + textures = { "("..tile..")^[transformFX", tile } + else + textures = { tile, "("..tile..")^[transformFX" } + end + end + + local vsize + + if def.visual_scale then + + local s = def.visual_scale + + vsize = {x = s, y = s, z = s} end self.object:set_properties({ is_visible = true, visual = "upright_sprite", - visual_size = {x = 1, y = 1}, + visual_size = vsize, textures = textures, - glow = def.light_source, + glow = def.light_source }) - else + + elseif def.drawtype == "mesh" then + local itemstring = node.name if core.is_colored_paramtype(def.paramtype2) then - itemstring = core.itemstring_with_palette( - itemstring, node.param2) + itemstring = core.itemstring_with_palette(itemstring, node.param2) + end + + local s = (def.visual_scale or 1) * SCALE * 0.5 + local vsize = vector.new(s, s, s) + + self.object:set_properties({ + is_visible = true, + wield_item = itemstring, + visual_size = vsize, + glow = def.light_source + }) + + elseif def.drawtype ~= "airlike" then + + local itemstring = node.name + + if core.is_colored_paramtype(def.paramtype2) then + itemstring = core.itemstring_with_palette(itemstring, node.param2) + end + + -- FIXME: solution needed for paramtype2 == "leveled" + local vsize + + if def.visual_scale then + + local s = def.visual_scale * SCALE + + vsize = {x = s, y = s, z = s} end self.object:set_properties({ is_visible = true, wield_item = itemstring, - glow = def.light_source, + visual_size = vsize, + glow = def.light_source }) end + -- Set collision box (certain nodeboxes only for now) + local nb_types = {fixed=true, leveled=true, connected=true} + + if def.drawtype == "nodebox" and def.node_box and + + nb_types[def.node_box.type] and def.node_box.fixed then + + local box = table.copy(def.node_box.fixed) + + if type(box[1]) == "table" then + box = #box == 1 and box[1] or nil -- We can only use a single box + end + + if box then + + if def.paramtype2 == "leveled" and (self.node.level or 0) > 0 then + box[5] = -0.5 + self.node.level / 64 + end + + self.object:set_properties({ + collisionbox = box + }) + end + end + -- Rotate entity if def.drawtype == "torchlike" then - self.object:set_yaw(math.pi * 0.25) + self.object:set_yaw(math.pi*0.25) - elseif (node.param2 ~= 0 and (def.wield_image == "" - or def.wield_image == nil)) - or def.drawtype == "signlike" then + elseif ((node.param2 ~= 0 or def.drawtype == "nodebox" or def.drawtype == "mesh") + and (def.wield_image == "" or def.wield_image == nil)) + or def.drawtype == "signlike" + or def.drawtype == "mesh" + or def.drawtype == "normal" + or def.drawtype == "nodebox" then - if (def.paramtype2 == "facedir" - or def.paramtype2 == "colorfacedir") then + if (def.paramtype2 == "facedir" or def.paramtype2 == "colorfacedir") then - local fdir = (node.param2 or 1) % 32 - local face = fdir % 4 - local axis = fdir - face - local pitch, yaw, roll + local fdir = node.param2 % 32 - if axis == 4 then - pitch = (4 - face) * (math.pi / 2) - math.pi / 2 - yaw = math.pi / 2 - roll = math.pi / 2 + -- Get rotation from a precalculated lookup table + local euler = facedir_to_euler[fdir + 1] - elseif axis == 8 then - pitch = (4 - face) * (math.pi / 2) - math.pi * 1.5 - yaw = math.pi * 1.5 - roll = math.pi / 2 - - elseif axis == 12 then - pitch = (4 - face) * (math.pi / 2) - yaw = 0 - roll = math.pi / 2 - - elseif axis == 16 then - pitch = (4 - face) * (math.pi / 2) + math.pi - yaw = math.pi - roll = math.pi / 2 - - elseif axis == 20 then - pitch = math.pi - yaw = face * (math.pi / 2) + math.pi - roll = 0 - else - pitch = 0 - yaw = (4 - face) * (math.pi / 2) - roll = 0 + if euler then + self.object:set_rotation(euler) end - self.object:set_rotation({x = pitch, y = yaw, z = roll}) - elseif (def.paramtype2 == "wallmounted" - or def.paramtype2 == "colorwallmounted") then + or def.paramtype2 == "colorwallmounted" or def.drawtype == "signlike") then + + local rot = node.param2 % 8 + + if (def.drawtype == "signlike" + and def.paramtype2 ~= "wallmounted" + and def.paramtype2 ~= "colorwallmounted") then + + -- Change rotation to "floor" by default for non-wallmounted paramtype2 + rot = 1 + end - local rot = (node.param2 or 1) % 8 local pitch, yaw, roll = 0, 0, 0 - if rot == 1 then - pitch, yaw = -math.pi, -math.pi - elseif rot == 2 then - pitch, yaw = math.pi / 2, math.pi / 2 - elseif rot == 3 then - pitch, yaw = math.pi / 2, math.pi * 1.5 - elseif rot == 4 then - pitch, yaw = math.pi / 2, math.pi - elseif rot == 5 then - pitch, yaw = math.pi / 2, 0 + if def.drawtype == "nodebox" or def.drawtype == "mesh" then + + if rot == 0 then + pitch, yaw = math.pi/2, 0 + elseif rot == 1 then + pitch, yaw = -math.pi/2, math.pi + elseif rot == 2 then + pitch, yaw = 0, math.pi/2 + elseif rot == 3 then + pitch, yaw = 0, -math.pi/2 + elseif rot == 4 then + pitch, yaw = 0, math.pi + end + else + if rot == 1 then + pitch, yaw = math.pi, math.pi + elseif rot == 2 then + pitch, yaw = math.pi/2, math.pi/2 + elseif rot == 3 then + pitch, yaw = math.pi/2, -math.pi/2 + elseif rot == 4 then + pitch, yaw = math.pi/2, math.pi + elseif rot == 5 then + pitch, yaw = math.pi/2, 0 + end end if def.drawtype == "signlike" then - pitch = pitch - math.pi / 2 + pitch = pitch - math.pi/2 + + if rot == 0 then + yaw = yaw + math.pi/2 + elseif rot == 1 then + yaw = yaw - math.pi/2 + end + + elseif def.drawtype == "mesh" + or def.drawtype == "normal" or def.drawtype == "nodebox" then if rot >= 0 and rot <= 1 then - roll = roll - math.pi / 2 + roll = roll + math.pi + else + yaw = yaw + math.pi end end - self.object:set_rotation({x = pitch, y = yaw, z = roll}) + self.object:set_rotation({x=pitch, y=yaw, z=roll}) + + elseif (def.drawtype == "mesh" and def.paramtype2 == "degrotate") then + + local p2 = (node.param2 - (def.place_param2 or 0)) % 240 + local yaw = (p2 / 240) * (math.pi * 2) + + self.object:set_yaw(yaw) + + elseif (def.drawtype == "mesh" and def.paramtype2 == "colordegrotate") then + + local p2 = (node.param2 % 32 - (def.place_param2 or 0) % 32) % 24 + local yaw = (p2 / 24) * (math.pi * 2) + + self.object:set_yaw(yaw) end end end, @@ -382,7 +502,7 @@ core.register_entity(":__builtin:falling_node", { or (cdef and cdef.liquidtype ~= "none") -- or core.get_item_group(cnode.name, "attached_node") ~= 0 then --- only drop attacked nodes if area not protected (torch, rails etc.) +-- only drop attached nodes if area not protected (torch, rails etc.) or (core.get_item_group(cnode.name, "attached_node") ~= 0 and not minetest.is_protected(npos, "")) then