stone_sounds = {} stone_sounds.footstep = {name = "stone_walk", gain = 1.0} stone_sounds.dug = {name = "stone_break", gain = 1.0} stone_sounds.place = {name = "block_place", gain = 1.0} glass_sounds = {} glass_sounds.footstep = {name = "glass_walk", gain = 1.0} glass_sounds.dug = {name = "glass_break", gain = 1.0} glass_sounds.place = {name = "block_place", gain = 1.0} wood_sounds = {} wood_sounds.footstep = {name = "wood_walk", gain = 1.0} wood_sounds.dug = {name = "wood_break", gain = 1.0} wood_sounds.place = {name = "block_place", gain = 1.0} minetest.register_node( "portalgun:turretgun2", { description = "Sentry turret", groups = {oddly_breakable_by_hand = 1, not_in_creative_inventory = 1}, drop = "portalgun:turretgun", paramtype = "light", paramtype2 = "facedir", sunlight_propagates = true, sounds = stone_sounds, tiles = {"portalgun_sentry_turret.png"}, drawtype = "mesh", mesh = "turret2.obj", selection_box = { type = "fixed", fixed = { {-0.3, -0.5, -0.3, 0.3, 1, 0.3} } }, on_timer = function(pos, elapsed) local p = minetest.get_node(pos).param2 local pos1 = {x = pos.x, y = pos.y + 0.5, z = pos.z} local d for i, ob in pairs(minetest.get_objects_inside_radius(pos, 10)) do if portalgun_visiable(pos1, ob) and (ob:is_player() or (ob:get_luaentity() and (ob:get_luaentity().type or ob:get_luaentity().portalgun == nil))) then local a = ob:get_pos() if a.y < pos.y + 2 and a.y > pos.y - 1 then a = {x = math.floor(a.x), y = math.floor(a.y), z = math.floor(a.z)} if p == 3 and a.x > pos.x and a.z == pos.z then d = {x = 20, y = 0, z = 0} break elseif p == 1 and a.x < pos.x and a.z == pos.z then d = {x = -20, y = 0, z = 0} break elseif p == 2 and a.z > pos.z and a.x == pos.x then d = {x = 0, y = 0, z = 20} break elseif p == 0 and a.z < pos.z and a.x == pos.x then d = {x = 0, y = 0, z = -20} break end end end end local m = minetest.get_meta(pos) if d then m:set_int("stop", 0) minetest.add_entity(pos1, "portalgun:bullet1"):set_velocity(d) minetest.sound_play("portalgun_bullet1", {pos = pos, gain = 1, max_hear_distance = 15}) for i = 2, 5, 1 do minetest.after( i * 0.1, function(pos, d) minetest.add_entity(pos1, "portalgun:bullet1"):set_velocity(d) minetest.sound_play("portalgun_bullet1", {pos = pos, gain = 1, max_hear_distance = 15}) end, pos, d ) end else if m:get_int("stop") == 1 then minetest.set_node(pos, {name = "portalgun:turretgun", param2 = p}) minetest.get_node_timer(pos):start(0.2) else m:set_int("stop", 1) end end return true end } ) minetest.register_entity( "portalgun:turret_held", { hp_max = 1000, physical = true, weight = 5, visual = "mesh", visual_size = {x = 10, y = 10}, mesh = "turret2.obj", textures = {"portalgun_sentry_turret.png"}, is_visible = true, makes_footstep_sound = true, automatic_rotate = 1, portalgun = 2, on_step = function(self, dtime) --if not held and on ground then transform to turret self.object:set_acceleration({x = 0, y = -10, z = 0}) if self.held == false then --check if on ground local pos = self.object:get_pos() pos = {x = math.floor(pos.x), y = math.floor(pos.y) - 1, z = math.floor(pos.z)} local n = minetest.get_node(pos) if n.name == "air" then else --create turret node local p = self.object:get_pos() p = {x = math.floor(p.x), y = math.floor(p.y), z = math.floor(p.z)} --check if the node with pos p is air local n = minetest.get_node(p) if n.name == "air" then local rotation_param2 = self.object:get_rotation().x minetest.set_node(p, {name = "portalgun:turretgun2", param2 = rotation_param2}) minetest.get_node_timer(p):start(0.2) self.object:remove() end end end end, on_detach = function(self, player) --set held variable to false self.held = false end, _held = true, } ) minetest.register_node( "portalgun:turretgun", { description = "Sentry turret", groups = {oddly_breakable_by_hand = 1}, paramtype = "light", paramtype2 = "facedir", sunlight_propagates = true, sounds = stone_sounds, tiles = {"portalgun_sentry_turret.png"}, drawtype = "mesh", mesh = "turret1.obj", selection_box = { type = "fixed", fixed = { {-0.3, -0.5, -0.3, 0.3, 1, 0.3} } }, on_construct = function(pos) minetest.get_node_timer(pos):start(0.2) end, on_timer = function(pos, elapsed) local p = minetest.get_node(pos).param2 local pos1 = {x = pos.x, y = pos.y + 0.5, z = pos.z} local d for i, ob in pairs(minetest.get_objects_inside_radius(pos1, 10)) do if portalgun_visiable(pos1, ob) and (ob:is_player() or (ob:get_luaentity() and (ob:get_luaentity().type or ob:get_luaentity().portalgun == nil))) then local a = ob:get_pos() if a.y < pos.y + 2 and a.y > pos.y - 1 then a = {x = math.floor(a.x), y = math.floor(a.y), z = math.floor(a.z)} if p == 3 and a.x > pos.x and a.z == pos.z then d = {x = 20, y = 0, z = 0} break elseif p == 1 and a.x < pos.x and a.z == pos.z then d = {x = -20, y = 0, z = 0} break elseif p == 2 and a.z > pos.z and a.x == pos.x then d = {x = 0, y = 0, z = 20} break elseif p == 0 and a.z < pos.z and a.x == pos.x then d = {x = 0, y = 0, z = -20} break end end end end if d then minetest.add_entity(pos1, "portalgun:bullet1"):set_velocity(d) minetest.set_node(pos, {name = "portalgun:turretgun2", param2 = p}) minetest.get_node_timer(pos):start(1) minetest.sound_play("portalgun_bullet1", {pos = pos, gain = 1, max_hear_distance = 15}) for i = 2, 5, 1 do minetest.after( i * 0.1, function(pos, d) minetest.add_entity(pos1, "portalgun:bullet1"):set_velocity(d) minetest.sound_play("portalgun_bullet1", {pos = pos, gain = 1, max_hear_distance = 15}) end, pos, d ) end end return true end } ) function portalgun_visiable(pos, ob) if ob == nil or ob:get_pos() == nil or ob:get_pos().y == nil then return false end local ta = ob:get_pos() local v = {x = pos.x - ta.x, y = pos.y - ta.y - 1, z = pos.z - ta.z} v.y = v.y - 1 local amount = (v.x ^ 2 + v.y ^ 2 + v.z ^ 2) ^ 0.5 local d = math.sqrt((pos.x - ta.x) * (pos.x - ta.x) + (pos.y - ta.y) * (pos.y - ta.y) + (pos.z - ta.z) * (pos.z - ta.z)) v.x = (v.x / amount) * -1 v.y = (v.y / amount) * -1 v.z = (v.z / amount) * -1 for i = 1, d, 1 do local node = minetest.registered_nodes[ minetest.get_node({x = pos.x + (v.x * i), y = pos.y + (v.y * i), z = pos.z + (v.z * i)}).name ] if node.walkable then return false end end return true end function portalgun_round(x) if x % 2 ~= 0.5 then return math.floor(x + 0.5) end return x - 0.5 end function portalgun_ra2shoot(pos, ob) local op = ob:get_pos() local m = minetest.get_meta(pos) local x = m:get_int("x") local y = m:get_int("y") local z = m:get_int("z") local ox = portalgun_round(op.x) local oy = portalgun_round(op.y) local oz = portalgun_round(op.z) if x == 1 and ox == pos.x and oz <= pos.z then return true end if x == -1 and ox == pos.x and oz >= pos.z then return true end if z == -1 and oz == pos.z and ox <= pos.x then return true end if z == 1 and oz == pos.z and ox >= pos.x then return true end return false end minetest.register_entity( "portalgun:bullet1", { hp_max = 1, --physical = true, --collisionbox={-0.01,-0.01,-0.01,0.01,0.01,0.01}, pointable = false, visual = "mesh", mesh = "bullet.obj", --yellow color as tiles tiles = {"#color[yellow]"}, initial_sprite_basepos = {x = 0, y = 0}, portalgun = 2, bullet = 1, on_step = function(self, dtime) self.timer = self.timer + dtime self.timer2 = self.timer2 + dtime local pos = self.object:get_pos() local n = minetest.registered_nodes[minetest.get_node(self.object:get_pos()).name] if self.timer > 1 or (n and n.walkable) then self.object:remove() return end for i, ob in pairs(minetest.get_objects_inside_radius(pos, 1.5)) do if ob:is_player() then if ob:get_hp() > 2 then ob:set_hp(ob:get_hp() - 2) else ob:set_hp(0) end self.object:remove() return end end end, timer = 0, timer2 = 0 } )