portalgun/scripts/turrets.lua

258 lines
9.6 KiB
Lua
Raw Normal View History

2022-07-12 10:20:50 +02:00
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_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
}
)