294 lines
6.8 KiB
Lua
294 lines
6.8 KiB
Lua
local utils = ...
|
|
local S = utils.S
|
|
|
|
|
|
|
|
--[[
|
|
on_step info
|
|
|
|
info.touching_ground = bool
|
|
info.standing_on_object = bool
|
|
info.collides = bool
|
|
|
|
|
|
info.collisions[n].type = "node"
|
|
info.collisions[n].node_pos = vector
|
|
info.collisions[n].old_velocity = vector
|
|
info.collisions[n].now_velocity = vector
|
|
info.collisions[n].axis = "x" | "y" | "z" - axis hit
|
|
|
|
or
|
|
|
|
info.collisions[n].type = "object"
|
|
info.collisions[n].object = userdata
|
|
info.collisions[n].old_velocity = vector
|
|
info.collisions[n].now_velocity = vector
|
|
info.collisions[n].axis = "x" | "y" | "z" - axis hit
|
|
]]
|
|
|
|
|
|
|
|
local function get_adjacent_node (collision_info, spawn_pos)
|
|
if vector.equals (collision_info.node_pos, spawn_pos) then
|
|
return collision_info.node_pos
|
|
end
|
|
|
|
local adj = { x = 0, y = 0, z = 0 }
|
|
|
|
if collision_info.axis == "x" then
|
|
adj.x = (collision_info.old_velocity.x > 0 and -1) or 1
|
|
elseif collision_info.axis == "y" then
|
|
adj.y = (collision_info.old_velocity.y > 0 and -1) or 1
|
|
elseif collision_info.axis == "z" then
|
|
adj.z = (collision_info.old_velocity.z > 0 and -1) or 1
|
|
end
|
|
|
|
local pos = vector.new (collision_info.node_pos)
|
|
local node = utils.get_far_node (pos)
|
|
local def = minetest.registered_nodes[node and node.name or nil]
|
|
|
|
while (node and node.name ~= "air") and (def and not def.buildable_to) do
|
|
local next_pos = vector.add (pos, adj)
|
|
|
|
if vector.equals (next_pos, spawn_pos) then
|
|
return pos
|
|
end
|
|
|
|
pos = next_pos
|
|
node = utils.get_far_node (pos)
|
|
def = minetest.registered_nodes[node and node.name or nil]
|
|
end
|
|
|
|
return pos
|
|
end
|
|
|
|
|
|
|
|
local function register_shell (name, description, texture, inventory_image,
|
|
stack_max, shell_speed, explode_func)
|
|
|
|
minetest.register_entity (name.."_entity", {
|
|
initial_properties = {
|
|
physical = true,
|
|
collide_with_objects = true,
|
|
collisionbox = { -0.25, -0.125, -0.25, 0.25, 0.125, 0.25 },
|
|
pointable = false,
|
|
visual_size = { x = 0.7, y = 0.7, z = 0.7 },
|
|
visual = "mesh",
|
|
mesh = "lwcomponents_shell.obj",
|
|
textures = { texture },
|
|
use_texture_alpha = false,
|
|
is_visible = true,
|
|
makes_footstep_sound = false,
|
|
automatic_face_movement_dir = false,
|
|
automatic_face_movement_max_rotation_per_sec = false,
|
|
automatic_rotate = 0,
|
|
backface_culling = true,
|
|
damage_texture_modifier = "",
|
|
glow = 0,
|
|
static_save = false,
|
|
shaded = true,
|
|
show_on_minimap = false,
|
|
},
|
|
|
|
on_activate = function (self, staticdata, dtime_s)
|
|
if not self.spawn_pos then
|
|
self.spawn_pos = vector.new (self.object:get_pos ())
|
|
end
|
|
|
|
if not self.time_lived then
|
|
self.time_lived = 0
|
|
end
|
|
|
|
if not self.shell_speed then
|
|
self.shell_speed = shell_speed
|
|
end
|
|
|
|
self.staticdata = staticdata
|
|
end,
|
|
|
|
get_staticdata = function (self)
|
|
return self.staticdata
|
|
end,
|
|
|
|
on_step = function (self, dtime, info)
|
|
local explode_pos = nil
|
|
|
|
self.object:set_rotation (vector.dir_to_rotation (self.object:get_velocity ()))
|
|
|
|
if self.time_lived then
|
|
self.time_lived = self.time_lived + dtime
|
|
|
|
if self.time_lived > self.shell_speed then
|
|
self.object:remove ()
|
|
|
|
return
|
|
end
|
|
end
|
|
|
|
if info.collides then
|
|
--For each collision that was found in reverse order
|
|
for i = #info.collisions, 1, -1 do
|
|
local c = info.collisions[i]
|
|
|
|
if c.type == "node" then
|
|
local node = utils.get_far_node (c.node_pos)
|
|
|
|
if node and node.name ~= "air" then
|
|
local def = minetest.registered_nodes[node.name]
|
|
|
|
if def and def.walkable then
|
|
-- adjacent for explosion
|
|
explode_pos = get_adjacent_node (c, self.spawn_pos)
|
|
|
|
--minetest.log ("action", "Shell on node "..node.name.." at "..minetest.pos_to_string (explode_pos)..
|
|
--" node at "..minetest.pos_to_string (c.node_pos))
|
|
|
|
break
|
|
end
|
|
end
|
|
|
|
if not explode_pos then
|
|
self.object:set_velocity (c.old_velocity)
|
|
end
|
|
|
|
elseif c.type == "object" then
|
|
-- explode at this pos
|
|
if c.object:get_armor_groups ().immortal then
|
|
self.object:set_velocity (c.old_velocity)
|
|
else
|
|
explode_pos = vector.new (c.object:get_pos ())
|
|
|
|
--minetest.log ("action", "Shell on entity "..c.object:get_luaentity ().name.." at "..minetest.pos_to_string (explode_pos))
|
|
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if explode_pos then
|
|
self.object:remove ()
|
|
|
|
explode_func (explode_pos)
|
|
end
|
|
end,
|
|
|
|
on_punch = function (self, puncher, time_from_last_punch, tool_capabilities, dir)
|
|
return true
|
|
end,
|
|
})
|
|
|
|
minetest.register_craftitem (name, {
|
|
description = description,
|
|
short_description = description,
|
|
groups = { },
|
|
inventory_image = inventory_image,
|
|
wield_image = inventory_image,
|
|
stack_max = stack_max,
|
|
})
|
|
|
|
|
|
lwcomponents.register_spawner (name,
|
|
function (spawn_pos, itemstack, owner, spawner_pos, spawner_dir, force)
|
|
if not itemstack:is_empty() then
|
|
local def = minetest.registered_entities[name.."_entity"]
|
|
|
|
if def then
|
|
local obj = minetest.add_entity (spawn_pos, name.."_entity")
|
|
|
|
if obj then
|
|
obj:set_armor_groups ({ immortal = 1 })
|
|
obj:set_acceleration ({ x = 0, y = -9.81, z = 0 })
|
|
obj:set_rotation (vector.dir_to_rotation (vector.multiply (spawner_dir, shell_speed)))
|
|
obj:set_velocity (vector.multiply (spawner_dir, shell_speed))
|
|
|
|
local luaent = obj:get_luaentity ()
|
|
|
|
if luaent then
|
|
luaent.spawn_pos = { x = spawn_pos.x, y = spawn_pos.y, z = spawn_pos.z }
|
|
luaent.time_lived = 0
|
|
luaent.shell_speed = shell_speed
|
|
end
|
|
|
|
return obj, false
|
|
end
|
|
end
|
|
end
|
|
|
|
return nil, false
|
|
end)
|
|
end
|
|
|
|
|
|
register_shell ("lwcomponents:cannon_shell",
|
|
S("Shell"),
|
|
"lwcannon_shell.png",
|
|
"lwcannon_shell_item.png",
|
|
99,
|
|
25,
|
|
function (pos)
|
|
utils.boom (pos,
|
|
2, -- node_radius
|
|
70, -- node_chance in 100
|
|
2, -- fire_radius
|
|
5, -- fire_chance in 100
|
|
4, -- entity_radius
|
|
20, -- entity_damage
|
|
false, -- disable_drops
|
|
nil, -- node_filter
|
|
false, -- burn_all
|
|
nil) -- sound
|
|
end)
|
|
|
|
|
|
register_shell ("lwcomponents:cannon_soft_shell",
|
|
S("Soft Shell"),
|
|
"lwcannon_soft_shell.png",
|
|
"lwcannon_soft_shell_item.png",
|
|
99,
|
|
25,
|
|
function (pos)
|
|
utils.boom (pos,
|
|
2, -- node_radius
|
|
50, -- node_chance in 100
|
|
2, -- fire_radius
|
|
5, -- fire_chance in 100
|
|
4, -- entity_radius
|
|
20, -- entity_damage
|
|
false, -- disable_drops
|
|
{
|
|
buildable_to = true,
|
|
buildable_to_undefined = false,
|
|
}, -- node_filter
|
|
false, -- burn_all
|
|
nil) -- sound
|
|
end)
|
|
|
|
|
|
if minetest.global_exists ("fire") then
|
|
register_shell ("lwcomponents:cannon_fire_shell",
|
|
S("Fire Shell"),
|
|
"lwcannon_fire_shell.png",
|
|
"lwcannon_fire_shell_item.png",
|
|
99,
|
|
25,
|
|
function (pos)
|
|
utils.boom (pos,
|
|
2, -- node_radius
|
|
0, -- node_chance in 100
|
|
2, -- fire_radius
|
|
70, -- fire_chance in 100
|
|
4, -- entity_radius
|
|
20, -- entity_damage
|
|
false, -- disable_drops
|
|
nil, -- node_filter
|
|
true, -- burn_all
|
|
nil) -- sound
|
|
end)
|
|
end
|
|
|
|
|
|
|
|
--
|