--[[ Shooter Turret Gun [shooter_turret] Copyright (C) 2013-2019 stujones11, Stuart Jones This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ]]-- local use_player_api = minetest.get_modpath("player_api") local function get_turret_entity(pos) local entity = nil local objects = minetest.get_objects_inside_radius(pos, 1) for _, obj in ipairs(objects) do local ent = obj:get_luaentity() if ent then if ent.name == "shooter_turret:turret_entity" then -- Remove duplicates if entity then obj:remove() else entity = ent end end end end return entity end minetest.register_entity("shooter_turret:turret_entity", { physical = true, visual = "mesh", mesh = "shooter_turret.b3d", visual_size = {x=1, y=1}, collisionbox = {-0.3, 0.5,-0.3, 0.3,1,0.3}, textures = { "shooter_turret_uv.png", }, timer = 0, user = nil, pitch = 40, yaw = 0, firing = false, on_activate = function(self) self.pos = self.object:get_pos() self.yaw = self.object:get_yaw() if minetest.get_node(self.pos).name ~= "shooter_turret:turret" then self.object:remove() return end self.object:set_animation({x=self.pitch, y=self.pitch}, 0) self.object:set_armor_groups({immortal=1}) -- Remove duplicates get_turret_entity(self.pos) end, on_rightclick = function(self, clicker) if self.user then local player = minetest.get_player_by_name(self.user) if player then player:set_detach() if use_player_api then player_api.player_attached[self.user] = false end end self.user = nil else clicker:set_attach(self.object, "", {x=0,y=-5,z=-8}, {x=0,y=0,z=0}) self.user = clicker:get_player_name() if use_player_api then player_api.player_attached[self.user] = true end end end, on_step = function(self, dtime) if not self.user then return end self.timer = self.timer + dtime if self.timer < 0.2 then return end local player = minetest.get_player_by_name(self.user) if player then local pitch = self.pitch local yaw = self.object:get_yaw() local ctrl = player:get_player_control() local step = 2 if ctrl then if ctrl.sneak then step = 1 if ctrl.jump then if self.firing == false then self:fire() self.firing = true end else self.firing = false end end if ctrl.down then pitch = pitch + 1 * step elseif ctrl.up then pitch = pitch - 1 * step end if ctrl.left then yaw = yaw + 0.025 * step elseif ctrl.right then yaw = yaw - 0.025 * step end if pitch < 0 then pitch = 0 elseif pitch > 90 then pitch = 90 end if self.pitch ~= pitch then self.object:set_animation({x=pitch, y=pitch}, 0) self.pitch = pitch end if self.yaw ~= yaw then self.object:set_yaw(yaw) self.yaw = yaw end end end self.timer = 0 end, fire = function(self) if not self.user then return end local meta = minetest.get_meta(self.pos) local inv = meta:get_inventory() if not inv then return end if not inv:contains_item("main", "shooter_rocket:rocket") then minetest.sound_play("shooter_click", {object=self.object}) return end inv:remove_item("main", "shooter_rocket:rocket") minetest.sound_play("shooter_shotgun", {object=self.object}) local pitch = math.rad(self.pitch - 40) local len = math.cos(pitch) local dir = vector.normalize({ x = len * math.sin(-self.yaw), y = math.sin(pitch), z = len * math.cos(self.yaw), }) local pos = {x=self.pos.x, y=self.pos.y + 0.87, z=self.pos.z} pos = vector.add(pos, vector.multiply(dir, 1.5)) local obj = minetest.add_entity(pos, "shooter_rocket:rocket_entity") if obj then local ent = obj:get_luaentity() if ent then minetest.sound_play("shooter_rocket_fire", {object=obj}) ent.user = self.user obj:set_yaw(self.yaw) obj:set_velocity(vector.multiply(dir, 30)) obj:set_acceleration({x=dir.x * -3, y=-10, z=dir.z * -3}) end end if shooter.config.enable_particle_fx == true then minetest.add_particlespawner({ amount = 10, time = 0.1, minpos = {x=pos.x - 1, y=pos.y - 1, z=pos.z - 1}, maxpos = {x=pos.x + 1, y=pos.y + 1, z=pos.z + 1}, minvel = {x=0, y=0, z=0}, maxvel = {x=0, y=0, z=0}, minacc = {x=-0.5, y=-0.5, z=-0.5}, maxacc = {x=0.5, y=0.5, z=0.5}, minexptime = 0.1, maxexptime = 1, minsize = 8, maxsize = 15, collisiondetection = false, texture = "shooter_smoke.png", }) end end }) minetest.register_node("shooter_turret:turret", { description = "Turret Gun", tiles = {"shooter_turret_base.png"}, inventory_image = "shooter_turret_gun.png", wield_image = "shooter_turret_gun.png", drawtype = "nodebox", paramtype = "light", paramtype2 = "facedir", groups = {snappy=2, choppy=2, oddly_breakable_by_hand=3}, node_box = { type = "fixed", fixed = { {-1/8, 1/8, -1/8, 1/8, 1/2, 1/8}, {-5/16, 0, -5/16, 5/16, 1/8, 5/16}, {-3/8, -1/2, -3/8, -1/4, 0, -1/4}, {1/4, -1/2, 1/4, 3/8, 0, 3/8}, {1/4, -1/2, -3/8, 3/8, 0, -1/4}, {-3/8, -1/2, 1/4, -1/4, 0, 3/8}, }, }, on_construct = function(pos) local meta = minetest.get_meta(pos) meta:set_string("formspec", "size[8,9]".. "list[current_name;main;2,0;4,4;]".. "list[current_player;main;0,5;8,4;]".. "listring[]" ) meta:set_string("infotext", "Turret Gun") local inv = meta:get_inventory() inv:set_size("main", 16) end, after_place_node = function(pos) local node = minetest.get_node({x=pos.x, y=pos.y + 1, z=pos.z}) if node.name == "air" then if not get_turret_entity(pos) then minetest.add_entity(pos, "shooter_turret:turret_entity") end end end, can_dig = function(pos) local meta = minetest.get_meta(pos); local inv = meta:get_inventory() return inv:is_empty("main") end, after_destruct = function(pos) local ent = get_turret_entity(pos) if ent then ent.object:remove() end end, mesecons = { effector = { action_on = function(pos) local ent = get_turret_entity(pos) if ent then if ent.firing == false then ent:fire() ent.firing = true end end end, action_off = function(pos) local ent = get_turret_entity(pos) if ent then ent.firing = false end end, }, }, }) minetest.register_abm({ nodenames = {"shooter_turret:turret"}, interval = 15, chance = 1, action = function(pos) if not get_turret_entity(pos) then minetest.add_entity(pos, "shooter_turret:turret_entity") end end }) if shooter.config.enable_crafting == true then minetest.register_craft({ output = "shooter_turret:turret", recipe = { {"default:bronze_ingot", "default:bronze_ingot", "default:steel_ingot"}, {"", "default:bronze_ingot", "default:steel_ingot"}, {"", "default:diamond", ""}, }, }) end --Backward compatibility minetest.register_alias("shooter:turret", "shooter_turret:turret")