forked from Mirrorlandia_minetest/portalgun
355 lines
13 KiB
Lua
355 lines
13 KiB
Lua
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:tureta",
|
|
{
|
|
description = "Tureta",
|
|
tiles = {"portalgun_sentry_turret.png"},
|
|
drawtype = "mesh",
|
|
mesh = "turret1.obj",
|
|
--spawn turretgun and set to air
|
|
on_place = function(itemstack, placer, pointed_thing)
|
|
local pos = pointed_thing.above
|
|
local obj = minetest.add_entity(pos, "portalgun:turretgun")
|
|
--rotate turret to face player
|
|
local dir = placer:get_look_dir()
|
|
local yaw = math.atan(dir.z, dir.x) + math.pi / 2
|
|
if dir.x < 0 then
|
|
yaw = yaw + math.pi
|
|
end
|
|
yaw = yaw + math.pi
|
|
local deg = math.deg(yaw)
|
|
deg = math.fmod(deg, 360)
|
|
deg = math.floor(deg / 90) * 90
|
|
deg = deg + 90
|
|
deg = math.fmod(deg, 360)
|
|
obj:set_yaw(math.rad(deg))
|
|
--set turret to air
|
|
minetest.set_node(pos, {name = "air"})
|
|
end
|
|
}
|
|
)
|
|
minetest.register_craftitem(
|
|
"portalgun:turret_rotator",
|
|
{
|
|
description = "Turret rotator",
|
|
inventory_image = "portalgun_turret_rotator.png",
|
|
stack_max = 1,
|
|
on_use = function(itemstack, user, pointed_thing)
|
|
--if pointing at a entity
|
|
if pointed_thing.type == "object" then
|
|
local obj = pointed_thing.ref
|
|
--if entity is a turret
|
|
if obj:get_luaentity().name == "portalgun:turretgun" then
|
|
--get object yaw
|
|
local yaw = obj:get_yaw()
|
|
local deg = math.deg(yaw)
|
|
deg = math.fmod(deg, 360)
|
|
deg = math.floor(deg / 90) * 90
|
|
deg = deg + 90
|
|
deg = math.fmod(deg, 360)
|
|
--set object yaw
|
|
obj:set_yaw(math.rad(deg))
|
|
end
|
|
end
|
|
end,
|
|
}
|
|
)
|
|
minetest.register_entity(
|
|
"portalgun:turretgun2",
|
|
{
|
|
description = "Sentry turret",
|
|
textures = {"portalgun_sentry_turret.png"},
|
|
visual = "mesh",
|
|
hp_max = 100,
|
|
physical = true,
|
|
collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
|
|
weight = 5,
|
|
is_visible = true,
|
|
visual_size = {x = 6, y = 6},
|
|
make_footstep_sound = true,
|
|
_tmr = 0,
|
|
_stop = 1,
|
|
automatic_rotate = 0,
|
|
mesh = "turret2.obj",
|
|
on_step = function(self, elapsed, moveresult)
|
|
self._tmr = self._tmr + elapsed
|
|
self.object:set_yaw(math.rad(math.fmod((math.floor(math.fmod(math.deg(self.object:get_yaw()), 360) / 90) * 90), 360)))
|
|
--get yaw and convert it into param2
|
|
local p = self.object:getyaw()
|
|
--convert yaw from rad to degrees
|
|
local yaw = math.deg(p)
|
|
yaw = math.floor(yaw / 90)
|
|
--if param2 is less than 0, set it to 3
|
|
if yaw < 0 then
|
|
yaw = 3
|
|
end
|
|
p = yaw
|
|
--add -y force
|
|
local force = {x = 0, y = -10, z = 0}
|
|
self.object:setvelocity(force)
|
|
if self._tmr < 0.2 then
|
|
return
|
|
else
|
|
self._tmr = 0
|
|
end
|
|
local pos = self.object:getpos()
|
|
local pos1 = {x = pos.x, y = pos.y + 0.5, z = pos.z}
|
|
local d
|
|
--swap 1 and 3 in p
|
|
if p == 1 then
|
|
p = 3
|
|
elseif p == 3 then
|
|
p = 1
|
|
end
|
|
for i, ob in pairs(minetest.get_objects_inside_radius(pos, 10)) do
|
|
if portalgun_visiable(pos1, ob) and (ob:is_player()) 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.sound_play("portalgun_bullet1", {pos = pos, gain = 1, max_hear_distance = 15})
|
|
else
|
|
local obj = minetest.add_entity(pos1, "portalgun:turretgun")
|
|
obj:setyaw(self.object:getyaw())
|
|
self.object:remove()
|
|
end
|
|
return true
|
|
end
|
|
}
|
|
)
|
|
|
|
minetest.register_node("portalgun:turretgun_spawner",
|
|
{
|
|
--this node spawns a turret on top of the block if there is no turret nearby
|
|
description = "Turret spawner",
|
|
--separate tile for top others same
|
|
tiles = {"portalgun_turret_spawner_top.png", "portalgun_turret_spawner_side.png"},
|
|
groups = {cracky = 3},
|
|
sounds = stone_sounds,
|
|
drawtype = "allfaces",
|
|
paramtype = "light",
|
|
paramtype2 = "facedir",
|
|
drop = "",
|
|
on_construct = function(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_string("pos", minetest.pos_to_string(pos))
|
|
meta:set_int("yaw", 0)
|
|
meta:set_string("infotext", "Turret spawner (" .. meta:get_int("yaw") .. ")")
|
|
minetest.get_node_timer(pos):start(1.0)
|
|
end,
|
|
on_punch = function(pos, node, puncher, pointed_thing)
|
|
local haspriv, missingpriv = minetest.check_player_privs(puncher:get_player_name(), {server = true})
|
|
--if puncher has privilege server add 90 degrees to yaw
|
|
if haspriv then
|
|
local meta = minetest.get_meta(pos)
|
|
local tmppos = minetest.string_to_pos(meta:get_string("pos"))
|
|
if tmppos ~= pos then
|
|
minetest.crash("hehe")
|
|
end
|
|
local yaw = meta:get_int("yaw")
|
|
yaw = yaw + 90
|
|
yaw = yaw % 360
|
|
meta:set_int("yaw", yaw)
|
|
meta:set_string("infotext", "Turret spawner (" .. meta:get_int("yaw") .. ")")
|
|
end
|
|
end,
|
|
on_timer = function (pos, elapsed)
|
|
local meta = minetest.get_meta(pos)
|
|
local pos = meta:get_string("pos")
|
|
local pos1 = minetest.string_to_pos(pos)
|
|
local pos2 = {x = pos1.x, y = pos1.y + 1, z = pos1.z}
|
|
local objs = minetest.get_objects_inside_radius(pos2, 1)
|
|
local found = 0
|
|
for i, obj in pairs(objs) do
|
|
if obj:get_luaentity().name == "portalgun:turretgun" then
|
|
found = found + 1
|
|
end
|
|
end
|
|
if found == 0 then
|
|
local obj = minetest.add_entity(pos2, "portalgun:turretgun")
|
|
obj:setyaw(math.rad(meta:get_int("yaw")))
|
|
end
|
|
minetest.get_node_timer(pos1):start(10)
|
|
end
|
|
})
|
|
|
|
minetest.register_entity(
|
|
"portalgun:turretgun",
|
|
{
|
|
description = "Sentry turret",
|
|
textures = {"portalgun_sentry_turret.png"},
|
|
visual = "mesh",
|
|
hp_max = 100,
|
|
physical = true,
|
|
collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
|
|
weight = 5,
|
|
is_visible = true,
|
|
make_footstep_sound = true,
|
|
automatic_rotate = 0,
|
|
_tmr = 0,
|
|
_stop = 1,
|
|
visual_size = {x = 6, y = 6},
|
|
mesh = "turret1.obj",
|
|
on_step = function(self, elapsed, moveresult)
|
|
self.object:set_yaw(math.rad(math.fmod((math.floor(math.fmod(math.deg(self.object:get_yaw()), 360) / 90) * 90), 360)))
|
|
--get yaw and convert it into param2
|
|
local p = self.object:getyaw()
|
|
--convert yaw from rad to degrees
|
|
local yaw = math.deg(p)
|
|
yaw = math.floor(yaw / 90)
|
|
--if param2 is less than 0, set it to 3
|
|
if yaw < 0 then
|
|
yaw = 3
|
|
end
|
|
p = yaw
|
|
local pos = self.object:get_pos()
|
|
local pos1 = {x = pos.x, y = pos.y + 0.5, z = pos.z}
|
|
local force = {x = 0, y = -10, z = 0}
|
|
self.object:setvelocity(force)
|
|
self._tmr = self._tmr + elapsed
|
|
if self._tmr < 0.2 then
|
|
return
|
|
else
|
|
self._tmr = 0
|
|
end
|
|
--swap 1 and 3 in p
|
|
if p == 1 then
|
|
p = 3
|
|
elseif p == 3 then
|
|
p = 1
|
|
end
|
|
|
|
local d
|
|
for i, ob in pairs(minetest.get_objects_inside_radius(pos1, 10)) do
|
|
if portalgun_visiable(pos1, ob) and (ob:is_player()) 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
|
|
local obj = minetest.add_entity(pos1, "portalgun:turretgun2")
|
|
--set yaw to same as this object
|
|
obj:setyaw(self.object:getyaw())
|
|
self.object:remove()
|
|
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
|
|
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() > 3 then
|
|
ob:set_hp(ob:get_hp() - 3)
|
|
elseif ob:get_hp() == 0 then
|
|
else
|
|
ob:set_hp(0)
|
|
end
|
|
self.object:remove()
|
|
return
|
|
end
|
|
end
|
|
end,
|
|
timer = 0,
|
|
timer2 = 0
|
|
}
|
|
)
|