1069 lines
24 KiB
Lua
1069 lines
24 KiB
Lua
local utils = ...
|
|
local S = utils.S
|
|
|
|
|
|
|
|
local cannon_force = 20
|
|
local min_pitch = -20
|
|
local max_pitch = 70
|
|
local min_rotation = -60
|
|
local max_rotation = 60
|
|
|
|
|
|
|
|
local function get_cannon_barrel (pos)
|
|
local barrel_pos = { x = pos.x, y = pos.y + 0.65, z = pos.z }
|
|
local objects = minetest.get_objects_inside_radius (barrel_pos, 0.1)
|
|
|
|
for i = 1, #objects do
|
|
if not objects[i]:is_player () then
|
|
if objects[i].get_luaentity and objects[i]:get_luaentity () and
|
|
objects[i]:get_luaentity ().name and
|
|
objects[i]:get_luaentity ().name == "lwcomponents:cannon_barrel" then
|
|
|
|
return objects[i]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
local function get_barrel_pos (pos)
|
|
local barrel = get_cannon_barrel (pos)
|
|
|
|
if barrel then
|
|
return barrel:get_pos ()
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
|
|
|
|
local function get_barrel_angle (pos)
|
|
local node = minetest.get_node_or_nil (pos)
|
|
local barrel = get_cannon_barrel (pos)
|
|
|
|
if barrel and node then
|
|
local cur = barrel:get_rotation ()
|
|
local node_rot = vector.dir_to_rotation (minetest.facedir_to_dir (node.param2))
|
|
local rot = (cur.y - node_rot.y) * 180 / math.pi
|
|
|
|
if (node.param2 % 2) == 0 then
|
|
rot = -rot
|
|
end
|
|
|
|
return {
|
|
x = cur.x * -180 / math.pi,
|
|
y = rot,
|
|
z = 0
|
|
}
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
|
|
|
|
local function set_barrel_rotation (pos, angle)
|
|
local node = minetest.get_node_or_nil (pos)
|
|
local barrel = get_cannon_barrel (pos)
|
|
|
|
angle = tonumber (angle)
|
|
|
|
if angle and barrel and node then
|
|
local cur = barrel:get_rotation ()
|
|
local node_rot = vector.dir_to_rotation (minetest.facedir_to_dir (node.param2))
|
|
|
|
angle = math.max (math.min (angle, max_rotation), min_rotation)
|
|
|
|
if (node.param2 % 2) == 0 then
|
|
angle = -angle
|
|
end
|
|
|
|
cur.y = node_rot.y + (angle * math.pi / 180)
|
|
cur.z = 0
|
|
|
|
barrel:set_rotation (cur)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
local function set_barrel_pitch (pos, pitch)
|
|
local node = minetest.get_node_or_nil (pos)
|
|
local barrel = get_cannon_barrel (pos)
|
|
|
|
pitch = tonumber (pitch)
|
|
|
|
if pitch and barrel and node then
|
|
local cur = barrel:get_rotation ()
|
|
|
|
cur.x = (math.max (math.min (pitch, max_pitch), min_pitch) / -180 * math.pi)
|
|
cur.z = 0
|
|
|
|
barrel:set_rotation (cur)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
local function start_flash (pos)
|
|
local blank_pos = { x = pos.x, y = pos.y + 1, z = pos.z }
|
|
local blank = minetest.get_node_or_nil (blank_pos)
|
|
local node_timer = minetest.get_node_timer (pos)
|
|
|
|
if node_timer and blank and blank.name == "lwcomponents:cannon_blank" then
|
|
node_timer:stop ()
|
|
minetest.set_node (blank_pos, { name = "lwcomponents:cannon_blank_fire" })
|
|
node_timer:start (0.5)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
local function cancel_flash (pos)
|
|
local blank_pos = { x = pos.x, y = pos.y + 1, z = pos.z }
|
|
local blank = minetest.get_node_or_nil (blank_pos)
|
|
|
|
if blank and blank.name == "lwcomponents:cannon_blank_fire" then
|
|
minetest.set_node (blank_pos, { name = "lwcomponents:cannon_blank" })
|
|
end
|
|
end
|
|
|
|
|
|
|
|
local function set_barrel_angle_delayed (pos, pitch, rotation)
|
|
pitch = pitch and tonumber (pitch)
|
|
rotation = rotation and tonumber (rotation)
|
|
local node = minetest.get_node_or_nil (pos)
|
|
|
|
if node and pitch or rotation then
|
|
local angle = get_barrel_angle (pos)
|
|
local node_timer = minetest.get_node_timer (pos)
|
|
local meta = minetest.get_meta (pos)
|
|
local was_set = false
|
|
|
|
if angle and node_timer and meta then
|
|
cancel_flash (pos)
|
|
|
|
if pitch then
|
|
pitch = math.floor (math.max (math.min (pitch, max_pitch), min_pitch) - angle.x)
|
|
|
|
if pitch ~= 0 then
|
|
meta:set_int ("barrel_pitch", pitch)
|
|
was_set = true
|
|
end
|
|
end
|
|
|
|
if rotation then
|
|
if (node.param2 % 2) == 1 then
|
|
rotation = -rotation
|
|
end
|
|
|
|
rotation = math.floor (math.max (math.min (rotation, max_rotation), min_rotation) - angle.y)
|
|
|
|
if rotation ~= 0 then
|
|
meta:set_int ("barrel_rotate", rotation)
|
|
was_set = true
|
|
end
|
|
end
|
|
|
|
if was_set then
|
|
node_timer:stop ()
|
|
node_timer:start (0.1)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
local function aim_barrel_delayed (pos, aimpos)
|
|
local x = tonumber (aimpos.x) or 0
|
|
local y = tonumber (aimpos.y) or 0
|
|
local z = tonumber (aimpos.z) or 0
|
|
|
|
if z < 1 then
|
|
return
|
|
end
|
|
|
|
local angle = vector.dir_to_rotation (aimpos)
|
|
|
|
local rot = math.floor (math.deg (-angle.y) + 0.5)
|
|
local pitch = math.floor (math.deg (angle.x) + 0.5)
|
|
|
|
set_barrel_angle_delayed (pos, pitch, rot)
|
|
end
|
|
|
|
|
|
|
|
local function fire_cannon (pos)
|
|
local meta = minetest.get_meta (pos)
|
|
|
|
if meta then
|
|
if meta:get_int ("barrel_pitch") ~= 0 or
|
|
meta:get_int ("barrel_rotate") ~= 0 then
|
|
|
|
return false
|
|
end
|
|
|
|
local inv = meta:get_inventory ()
|
|
|
|
if inv then
|
|
local stack = inv:get_stack ("main", 1)
|
|
|
|
if not stack:is_empty () and stack:get_count () > 0 then
|
|
local name = stack:get_name ()
|
|
local item = ItemStack (stack)
|
|
|
|
if item then
|
|
item:set_count (1)
|
|
|
|
local barrel = get_cannon_barrel (pos)
|
|
|
|
if barrel then
|
|
local ammo_pos = barrel:get_pos ()
|
|
local ammo_angle = barrel:get_rotation (pos)
|
|
|
|
if ammo_pos and ammo_angle then
|
|
local dir = vector.rotate ({ x = 0, y = 0, z = -1 }, ammo_angle)
|
|
local owner = meta:get_string ("owner")
|
|
local obj, cancel = nil, false
|
|
local spawn_pos = { x = ammo_pos.x + dir.x,
|
|
y = ammo_pos.y + dir.y,
|
|
z = ammo_pos.z + dir.z }
|
|
|
|
if utils.settings.spawn_mobs then
|
|
obj, cancel = utils.spawn_registered (name,
|
|
spawn_pos,
|
|
item,
|
|
owner,
|
|
pos,
|
|
dir,
|
|
cannon_force)
|
|
|
|
if obj == nil and cancel then
|
|
return false
|
|
end
|
|
end
|
|
|
|
if not obj then
|
|
obj = minetest.add_item (spawn_pos, item)
|
|
|
|
if obj then
|
|
local vel = vector.multiply (dir, cannon_force)
|
|
|
|
obj:set_velocity (vel)
|
|
end
|
|
end
|
|
|
|
if obj then
|
|
stack:set_count (stack:get_count () - 1)
|
|
inv:set_stack ("main", 1, stack)
|
|
|
|
start_flash (pos)
|
|
|
|
minetest.sound_play ("lwcannon",
|
|
{
|
|
pos = pos,
|
|
gain = 1.0,
|
|
max_hear_distance = 20
|
|
},
|
|
true)
|
|
|
|
--send_fired_message (pos, slot, name)
|
|
|
|
return true, name
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
local function process_controller_input (pos, input)
|
|
local node = minetest.get_node_or_nil (pos)
|
|
local meta = minetest.get_meta (pos)
|
|
|
|
if meta and node then
|
|
local owner = meta:get_string ("owner")
|
|
|
|
if owner:len () < 1 or owner == input.name then
|
|
local pitch = input.pitch * -180 / math.pi
|
|
local node_rot = vector.dir_to_rotation (minetest.facedir_to_dir ((node.param2 + 2) % 4))
|
|
local rot = (input.yaw - node_rot.y) * 180 / math.pi
|
|
local sensitivity = (meta:get_string ("sensitive") == "true" and 3) or 1
|
|
|
|
while rot > 180 do
|
|
rot = rot - 360
|
|
end
|
|
|
|
while rot < -180 do
|
|
rot = rot + 360
|
|
end
|
|
|
|
if (node.param2 % 2) == 0 then
|
|
rot = -rot
|
|
end
|
|
|
|
set_barrel_pitch (pos, pitch * sensitivity)
|
|
set_barrel_rotation (pos, rot * sensitivity)
|
|
|
|
if input.dig then
|
|
fire_cannon (pos)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
local function get_formspec (pos)
|
|
local meta = minetest.get_meta (pos)
|
|
local sensitive = (meta and meta:get_string ("sensitive")) or "false"
|
|
|
|
return
|
|
"formspec_version[3]\n"..
|
|
"size[11.75,10.75;true]\n"..
|
|
"field[1.0,1.0;4.0,0.8;channel;Channel;${channel}]\n"..
|
|
"button[5.5,1.0;2.0,0.8;setchannel;Set]\n"..
|
|
"button[8.5,1.0;2.0,0.8;hide;Hide]\n"..
|
|
"field[1.0,2.6;4.0,0.8;controller;Controller;${controller}]\n"..
|
|
"button[5.5,2.6;2.0,0.8;setcontroller;Set]\n"..
|
|
"checkbox[1.3,3.8;sensitive;Sensitive;"..sensitive.."]\n"..
|
|
"list[context;main;9.0,2.75;1,1;]\n"..
|
|
"list[current_player;main;1.0,5.0;8,4;]\n"..
|
|
"listring[]"
|
|
end
|
|
|
|
|
|
|
|
local function can_place (pos, player)
|
|
local above = { x = pos.x, y = pos.y + 1, z = pos.z }
|
|
|
|
return utils.can_place (pos) and utils.can_place (above) and
|
|
not utils.is_protected (pos, player) and
|
|
not utils.is_protected (above, player)
|
|
end
|
|
|
|
|
|
|
|
local function on_construct (pos)
|
|
local barrel_pos = { x = pos.x, y = pos.y + 0.65, z = pos.z }
|
|
local blank_pos = { x = pos.x, y = pos.y + 1, z = pos.z }
|
|
local staticdata =
|
|
{
|
|
base_pos = { x = pos.x, y = pos.y, z = pos.z },
|
|
blank_pos = blank_pos,
|
|
}
|
|
|
|
local barrel = minetest.add_entity (barrel_pos,
|
|
"lwcomponents:cannon_barrel",
|
|
minetest.serialize (staticdata))
|
|
|
|
if barrel then
|
|
set_barrel_rotation (pos, 0)
|
|
set_barrel_pitch (pos, 0)
|
|
barrel:set_armor_groups ({ immortal = 1 })
|
|
end
|
|
|
|
minetest.set_node (blank_pos, { name = "lwcomponents:cannon_blank" })
|
|
end
|
|
|
|
|
|
|
|
local function on_destruct (pos)
|
|
local blank_pos = { x = pos.x, y = pos.y + 1, z = pos.z }
|
|
local blank = minetest.get_node_or_nil (blank_pos)
|
|
local barrel = get_cannon_barrel (pos)
|
|
|
|
if barrel then
|
|
barrel:remove ()
|
|
end
|
|
|
|
if blank and (blank.name == "lwcomponents:cannon_blank" or
|
|
blank.name == "lwcomponents:cannon_blank_fire") then
|
|
minetest.remove_node (blank_pos)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
local function after_place_node (pos, placer, itemstack, pointed_thing)
|
|
local meta = minetest.get_meta (pos)
|
|
|
|
meta:set_string ("sensitive", "true")
|
|
meta:set_string ("inventory", "{ main = { } }")
|
|
|
|
local inv = meta:get_inventory ()
|
|
|
|
inv:set_size ("main", 1)
|
|
inv:set_width ("main", 1)
|
|
|
|
meta:set_string ("formspec", get_formspec (pos))
|
|
|
|
-- If return true no item is taken from itemstack
|
|
return false
|
|
end
|
|
|
|
|
|
|
|
local function after_place_node_locked (pos, placer, itemstack, pointed_thing)
|
|
after_place_node (pos, placer, itemstack, pointed_thing)
|
|
|
|
if placer and placer:is_player () then
|
|
local meta = minetest.get_meta (pos)
|
|
|
|
meta:set_string ("owner", placer:get_player_name ())
|
|
meta:set_string ("infotext", "Cannon (owned by "..placer:get_player_name ()..")")
|
|
end
|
|
|
|
-- If return true no item is taken from itemstack
|
|
return false
|
|
end
|
|
|
|
|
|
|
|
local function on_place (itemstack, placer, pointed_thing)
|
|
if pointed_thing and pointed_thing.type == "node" and placer and placer:is_player () then
|
|
local param2 = 0
|
|
local pos = pointed_thing.under
|
|
|
|
local on_rightclick = utils.get_on_rightclick (pos, placer)
|
|
if on_rightclick then
|
|
return on_rightclick (pos, minetest.get_node (pos), placer, itemstack, pointed_thing)
|
|
end
|
|
|
|
if not can_place (pos, placer) then
|
|
pos = pointed_thing.above
|
|
|
|
if not can_place (pos, placer) then
|
|
return itemstack
|
|
end
|
|
end
|
|
|
|
if placer and placer:is_player () then
|
|
param2 = (minetest.dir_to_facedir (placer:get_look_dir (), false) + 2) % 4
|
|
end
|
|
|
|
minetest.set_node (pos, { name = "lwcomponents:cannon", param1 = 0, param2 = param2 })
|
|
after_place_node (pos, placer, itemstack, pointed_thing)
|
|
|
|
if not utils.is_creative (player) then
|
|
itemstack:set_count (itemstack:get_count () - 1)
|
|
end
|
|
end
|
|
|
|
return itemstack
|
|
end
|
|
|
|
|
|
|
|
local function on_place_locked (itemstack, placer, pointed_thing)
|
|
if pointed_thing and pointed_thing.type == "node" and placer and placer:is_player () then
|
|
local param2 = 0
|
|
local pos = pointed_thing.under
|
|
|
|
local on_rightclick = utils.get_on_rightclick (pos, placer)
|
|
if on_rightclick then
|
|
return on_rightclick (pos, minetest.get_node (pos), placer, itemstack, pointed_thing)
|
|
end
|
|
|
|
if not can_place (pos, placer) then
|
|
pos = pointed_thing.above
|
|
|
|
if not can_place (pos, placer) then
|
|
return itemstack
|
|
end
|
|
end
|
|
|
|
if placer and placer:is_player () then
|
|
param2 = (minetest.dir_to_facedir (placer:get_look_dir (), false) + 2) % 4
|
|
end
|
|
|
|
minetest.set_node (pos, { name = "lwcomponents:cannon_locked", param1 = 0, param2 = param2 })
|
|
after_place_node_locked (pos, placer, itemstack, pointed_thing)
|
|
|
|
if not utils.is_creative (player) then
|
|
itemstack:set_count (itemstack:get_count () - 1)
|
|
end
|
|
end
|
|
|
|
return itemstack
|
|
end
|
|
|
|
|
|
|
|
local function can_dig (pos, player)
|
|
if not utils.can_interact_with_node (pos, player) then
|
|
return false
|
|
end
|
|
|
|
local meta = minetest.get_meta (pos)
|
|
|
|
if meta then
|
|
local inv = meta:get_inventory ()
|
|
|
|
if inv then
|
|
if not inv:is_empty ("main") then
|
|
return false
|
|
end
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
|
|
|
|
local function on_receive_fields (pos, formname, fields, sender)
|
|
if not utils.can_interact_with_node (pos, sender) then
|
|
return
|
|
end
|
|
|
|
if fields.setchannel then
|
|
local meta = minetest.get_meta (pos)
|
|
|
|
if meta then
|
|
meta:set_string ("channel", fields.channel)
|
|
end
|
|
end
|
|
|
|
if fields.setcontroller then
|
|
local meta = minetest.get_meta (pos)
|
|
|
|
if meta then
|
|
meta:set_string ("controller", fields.controller)
|
|
end
|
|
end
|
|
|
|
if fields.hide then
|
|
local meta = minetest.get_meta (pos)
|
|
|
|
if meta then
|
|
meta:set_string ("formspec", "")
|
|
end
|
|
end
|
|
|
|
if fields.sensitive ~= nil then
|
|
local meta = minetest.get_meta (pos)
|
|
|
|
if meta then
|
|
meta:set_string ("sensitive", fields.sensitive)
|
|
meta:set_string ("formspec", get_formspec (pos))
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
local function on_blast (pos, intensity)
|
|
local meta = minetest.get_meta (pos)
|
|
|
|
if meta then
|
|
if intensity >= 1.0 then
|
|
local inv = meta:get_inventory ()
|
|
|
|
if inv then
|
|
local slots = inv:get_size ("main")
|
|
|
|
for slot = 1, slots do
|
|
local stack = inv:get_stack ("main", slot)
|
|
|
|
if stack and not stack:is_empty () then
|
|
if math.floor (math.random (0, 5)) == 3 then
|
|
utils.item_drop (stack, nil, pos)
|
|
else
|
|
utils.on_destroy (stack)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
on_destruct (pos)
|
|
minetest.remove_node (pos)
|
|
|
|
else -- intensity < 1.0
|
|
local inv = meta:get_inventory ()
|
|
|
|
if inv then
|
|
local slots = inv:get_size ("main")
|
|
|
|
for slot = 1, slots do
|
|
local stack = inv:get_stack ("main", slot)
|
|
|
|
if stack and not stack:is_empty () then
|
|
utils.item_drop (stack, nil, pos)
|
|
end
|
|
end
|
|
end
|
|
|
|
local node = minetest.get_node_or_nil (pos)
|
|
if node then
|
|
local items = minetest.get_node_drops (node, nil)
|
|
|
|
if items and #items > 0 then
|
|
local stack = ItemStack (items[1])
|
|
|
|
if stack then
|
|
preserve_metadata (pos, node, meta, { stack })
|
|
utils.item_drop (stack, nil, pos)
|
|
on_destruct (pos)
|
|
minetest.remove_node (pos)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
local function on_rightclick (pos, node, clicker, itemstack, pointed_thing)
|
|
if not utils.can_interact_with_node (pos, clicker) then
|
|
if clicker and clicker:is_player () then
|
|
local owner = "<unknown>"
|
|
local meta = minetest.get_meta (pos)
|
|
|
|
if meta then
|
|
owner = meta:get_string ("owner")
|
|
end
|
|
|
|
local spec =
|
|
"formspec_version[3]"..
|
|
"size[8.0,4.0,false]"..
|
|
"label[1.0,1.0;Owned by "..minetest.formspec_escape (owner).."]"..
|
|
"button_exit[3.0,2.0;2.0,1.0;close;Close]"
|
|
|
|
minetest.show_formspec (clicker:get_player_name (),
|
|
"lwcomponents:component_privately_owned",
|
|
spec)
|
|
end
|
|
|
|
else
|
|
local meta = minetest.get_meta (pos)
|
|
|
|
if meta then
|
|
local formspec = meta:get_string ("formspec")
|
|
|
|
if formspec == "" then
|
|
local hit = minetest.pointed_thing_to_face_pos (clicker, pointed_thing)
|
|
hit.x = hit.x - pos.x
|
|
hit.y = hit.y - pos.y
|
|
hit.z = hit.z - pos.z
|
|
|
|
local hx = hit.x
|
|
local hy = hit.y
|
|
local hz = hit.z
|
|
local inc = (clicker:get_player_control ().aux1 and 1) or 10
|
|
|
|
if node.param2 == 1 then
|
|
hx = hit.z
|
|
hz = hit.x
|
|
elseif node.param2 == 2 then
|
|
hx = -hit.x
|
|
hz = -hit.z
|
|
elseif node.param2 == 3 then
|
|
hx = -hit.z
|
|
hz = -hit.x
|
|
end
|
|
|
|
if hz == 0.5 and hy >= -0.5 and hy <= 0.2 then
|
|
local angle = get_barrel_angle (pos)
|
|
|
|
if angle then
|
|
if hx >= -0.5 and hx <= -0.25 and hy >= -0.25 and hy <= -0.0625 then
|
|
-- left
|
|
set_barrel_rotation (pos, angle.y + inc)
|
|
elseif hx >= 0.25 and hx <= 0.5 and hy >= -0.25 and hy <= -0.0625 then
|
|
-- right
|
|
set_barrel_rotation (pos, angle.y - inc)
|
|
elseif hx >= -0.125 and hx <= 0.125 and hy >= 0.0 and hy <= 0.1875 then
|
|
-- up
|
|
set_barrel_pitch (pos, angle.x + inc)
|
|
elseif hx >= -0.125 and hx <= 0.125 and hy >= -0.5 and hy <= -0.3125 then
|
|
-- down
|
|
set_barrel_pitch (pos, angle.x - inc)
|
|
elseif hx >= -0.125 and hx <= 0.125 and hy >= -0.25 and hy <= -0.0625 then
|
|
-- fire
|
|
fire_cannon (pos)
|
|
end
|
|
end
|
|
else
|
|
meta:set_string ("formspec", get_formspec (pos))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return itemstack
|
|
end
|
|
|
|
|
|
|
|
local function on_timer (pos, elapsed)
|
|
local meta = minetest.get_meta (pos)
|
|
|
|
if meta then
|
|
local barrel_pitch = meta:get_int ("barrel_pitch")
|
|
local barrel_rotate = meta:get_int ("barrel_rotate")
|
|
|
|
if barrel_pitch ~= 0 or barrel_rotate ~= 0 then
|
|
local angle = get_barrel_angle (pos)
|
|
|
|
if angle then
|
|
if barrel_pitch < -10 then
|
|
angle.x = angle.x - 10
|
|
barrel_pitch = barrel_pitch + 10
|
|
elseif barrel_pitch > 10 then
|
|
angle.x = angle.x + 10
|
|
barrel_pitch = barrel_pitch - 10
|
|
else
|
|
angle.x = angle.x + barrel_pitch
|
|
barrel_pitch = 0
|
|
end
|
|
|
|
if barrel_rotate < -10 then
|
|
angle.y = angle.y - 10
|
|
barrel_rotate = barrel_rotate + 10
|
|
elseif barrel_rotate > 10 then
|
|
angle.y = angle.y + 10
|
|
barrel_rotate = barrel_rotate - 10
|
|
else
|
|
angle.y = angle.y + barrel_rotate
|
|
barrel_rotate = 0
|
|
end
|
|
|
|
set_barrel_pitch (pos, angle.x)
|
|
set_barrel_rotation (pos, angle.y)
|
|
|
|
meta:set_int ("barrel_pitch", barrel_pitch)
|
|
meta:set_int ("barrel_rotate", barrel_rotate)
|
|
end
|
|
|
|
return barrel_pitch ~= 0 or barrel_rotate ~= 0
|
|
end
|
|
end
|
|
|
|
cancel_flash (pos)
|
|
|
|
return false
|
|
end
|
|
|
|
|
|
|
|
local function digilines_support ()
|
|
if utils.digilines_supported then
|
|
return
|
|
{
|
|
effector =
|
|
{
|
|
action = function (pos, node, channel, msg)
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
if meta then
|
|
local this_channel = meta:get_string ("channel")
|
|
|
|
if this_channel ~= "" then
|
|
if type (msg) == "string" then
|
|
local m = { }
|
|
for w in string.gmatch(msg, "[^%s]+") do
|
|
m[#m + 1] = w
|
|
end
|
|
|
|
if this_channel == channel then
|
|
if m[1] == "pitch" then
|
|
set_barrel_angle_delayed (pos, m[2], nil)
|
|
|
|
elseif m[1] == "rotation" then
|
|
set_barrel_angle_delayed (pos, nil, m[2])
|
|
|
|
elseif m[1] == "fire" then
|
|
fire_cannon (pos)
|
|
|
|
end
|
|
end
|
|
|
|
elseif type (msg) == "table" then
|
|
local controller = meta:get_string ("controller")
|
|
|
|
if controller:len () > 0 and controller == channel and
|
|
msg.pitch and msg.yaw and msg.name and msg.look_vector then
|
|
|
|
process_controller_input (pos, msg)
|
|
|
|
elseif type (msg.action) == "string" and msg.action == "aim" and
|
|
type (msg.aim) == "table" then
|
|
|
|
aim_barrel_delayed (pos, msg.aim)
|
|
|
|
end
|
|
|
|
end
|
|
end
|
|
end
|
|
end,
|
|
}
|
|
}
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
|
|
|
|
local function mesecon_support ()
|
|
if utils.mesecon_supported then
|
|
return
|
|
{
|
|
effector =
|
|
{
|
|
rules = utils.mesecon_flat_rules,
|
|
|
|
action_on = function (pos, node)
|
|
fire_cannon (pos)
|
|
end
|
|
}
|
|
}
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
|
|
|
|
minetest.register_node("lwcomponents:cannon_blank", {
|
|
description = S("Cannon blank"),
|
|
drawtype = "airlike",
|
|
light_source = 0,
|
|
sunlight_propagates = true,
|
|
walkable = false,
|
|
pointable = false,
|
|
diggable = false,
|
|
climbable = false,
|
|
buildable_to = false,
|
|
floodable = false,
|
|
is_ground_content = false,
|
|
drop = "",
|
|
groups = { not_in_creative_inventory = 1 },
|
|
paramtype = "light",
|
|
-- unaffected by explosions
|
|
on_blast = function() end,
|
|
})
|
|
|
|
|
|
|
|
minetest.register_node("lwcomponents:cannon_blank_fire", {
|
|
description = S("Cannon blank"),
|
|
drawtype = "airlike",
|
|
light_source = 7,
|
|
sunlight_propagates = true,
|
|
walkable = false,
|
|
pointable = false,
|
|
diggable = false,
|
|
climbable = false,
|
|
buildable_to = false,
|
|
floodable = false,
|
|
is_ground_content = false,
|
|
drop = "",
|
|
groups = { not_in_creative_inventory = 1 },
|
|
paramtype = "light",
|
|
-- unaffected by explosions
|
|
on_blast = function() end,
|
|
})
|
|
|
|
|
|
|
|
minetest.register_node("lwcomponents:cannon", {
|
|
description = S("Cannon"),
|
|
tiles = {
|
|
"lwcannon_top.png",
|
|
"lwcannon_bottom.png",
|
|
"lwcannon.png",
|
|
"lwcannon.png",
|
|
"lwcannon_face.png",
|
|
"lwcannon.png"
|
|
},
|
|
drawtype = "nodebox",
|
|
node_box = {
|
|
type = "fixed",
|
|
fixed = {
|
|
{ -0.09, 0, -0.09, 0.09, 0.5, 0.09 },
|
|
{ -0.5, -0.25, -0.5, 0.5, 0.125, 0.5 },
|
|
{ -0.4375, -0.1875, -0.4375, 0.4375, 0.1875, 0.5 },
|
|
{ -0.5, -0.5, 0.3125, 0.5, 0.125, 0.5 },
|
|
{ -0.5, -0.5, -0.5, -0.3125, 0.125, -0.3125 },
|
|
{ 0.3125, -0.5, -0.5, 0.5, 0.125, -0.3125 },
|
|
}
|
|
},
|
|
collision_box = {
|
|
type = "fixed",
|
|
fixed = {
|
|
{ -0.5, -0.5, -0.5, 0.5, 0.85, 0.5 }
|
|
}
|
|
},
|
|
selection_box = {
|
|
type = "fixed",
|
|
fixed = {
|
|
{ -0.5, -0.5, -0.5, 0.5, 0.1875, 0.5 }
|
|
}
|
|
},
|
|
wield_image = "lwcannon_item.png",
|
|
inventory_image = "lwcannon_item.png",
|
|
is_ground_content = false,
|
|
groups = { cracky = 3 },
|
|
sounds = default.node_sound_stone_defaults (),
|
|
paramtype = "light",
|
|
paramtype2 = "facedir",
|
|
param2 = 0,
|
|
floodable = false,
|
|
drop = "lwcomponents:cannon",
|
|
_digistuff_channelcopier_fieldname = "channel",
|
|
|
|
mesecons = mesecon_support (),
|
|
digiline = digilines_support (),
|
|
|
|
on_construct = on_construct,
|
|
on_destruct = on_destruct,
|
|
on_place = on_place,
|
|
on_receive_fields = on_receive_fields,
|
|
can_dig = can_dig,
|
|
after_place_node = after_place_node,
|
|
on_blast = on_blast,
|
|
on_rightclick = on_rightclick,
|
|
on_timer = on_timer,
|
|
})
|
|
|
|
|
|
|
|
minetest.register_node("lwcomponents:cannon_locked", {
|
|
description = S("Cannon (locked)"),
|
|
tiles = {
|
|
"lwcannon_top.png",
|
|
"lwcannon_bottom.png",
|
|
"lwcannon.png",
|
|
"lwcannon.png",
|
|
"lwcannon_face.png",
|
|
"lwcannon.png"
|
|
},
|
|
drawtype = "nodebox",
|
|
node_box = {
|
|
type = "fixed",
|
|
fixed = {
|
|
{ -0.09, 0, -0.09, 0.09, 0.5, 0.09 },
|
|
{ -0.5, -0.25, -0.5, 0.5, 0.125, 0.5 },
|
|
{ -0.4375, -0.1875, -0.4375, 0.4375, 0.1875, 0.5 },
|
|
{ -0.5, -0.5, 0.3125, 0.5, 0.125, 0.5 },
|
|
{ -0.5, -0.5, -0.5, -0.3125, 0.125, -0.3125 },
|
|
{ 0.3125, -0.5, -0.5, 0.5, 0.125, -0.3125 },
|
|
}
|
|
},
|
|
collision_box = {
|
|
type = "fixed",
|
|
fixed = {
|
|
{ -0.5, -0.5, -0.5, 0.5, 0.85, 0.5 }
|
|
}
|
|
},
|
|
selection_box = {
|
|
type = "fixed",
|
|
fixed = {
|
|
{ -0.5, -0.5, -0.5, 0.5, 0.1875, 0.5 }
|
|
}
|
|
},
|
|
wield_image = "lwcannon_item.png",
|
|
inventory_image = "lwcannon_item.png",
|
|
is_ground_content = false,
|
|
groups = { cracky = 3 },
|
|
sounds = default.node_sound_stone_defaults (),
|
|
paramtype = "light",
|
|
paramtype2 = "facedir",
|
|
param2 = 0,
|
|
floodable = false,
|
|
drop = "lwcomponents:cannon_locked",
|
|
_digistuff_channelcopier_fieldname = "channel",
|
|
|
|
mesecons = mesecon_support (),
|
|
digiline = digilines_support (),
|
|
|
|
on_construct = on_construct,
|
|
on_destruct = on_destruct,
|
|
on_place = on_place_locked,
|
|
on_receive_fields = on_receive_fields,
|
|
can_dig = can_dig,
|
|
after_place_node = after_place_node_locked,
|
|
on_blast = on_blast,
|
|
on_rightclick = on_rightclick,
|
|
on_timer = on_timer,
|
|
})
|
|
|
|
|
|
|
|
minetest.register_entity ("lwcomponents:cannon_barrel", {
|
|
initial_properties = {
|
|
physical = false,
|
|
collide_with_objects = false,
|
|
collisionbox = { -0.5, -0.35, -0.5, 0.5, 0.35, 0.5 },
|
|
selectionbox = { -0.5, -0.35, -0.5, 0.5, 0.35, 0.5 },
|
|
pointable = false,
|
|
visual = "mesh",
|
|
visual_size = { x = 1, y = 1, z = 1 },
|
|
mesh = "lwcomponents_cannon_barrel.obj",
|
|
textures = { "lwcomponents_cannon_barrel.png" },
|
|
use_texture_alpha = false,
|
|
is_visible = true,
|
|
makes_footstep_sound = false,
|
|
automatic_rotate = 0,
|
|
backface_culling = true,
|
|
damage_texture_modifier = "",
|
|
glow = 0,
|
|
static_save = true,
|
|
shaded = true,
|
|
show_on_minimap = false,
|
|
},
|
|
|
|
on_activate = function (self, staticdata, dtime_s)
|
|
self.staticdata = staticdata
|
|
end,
|
|
|
|
get_staticdata = function (self)
|
|
return self.staticdata
|
|
end,
|
|
|
|
on_step = function (self, dtime, moveresult)
|
|
end,
|
|
|
|
on_punch = function (self, puncher, time_from_last_punch, tool_capabilities, dir)
|
|
return true
|
|
end,
|
|
|
|
on_blast = function (self, damage)
|
|
return false, false, nil
|
|
end,
|
|
})
|
|
|
|
|
|
|
|
utils.hopper_add_container({
|
|
{"top", "lwcomponents:cannon", "main"}, -- take items from above into hopper below
|
|
{"bottom", "lwcomponents:cannon", "main"}, -- insert items below from hopper above
|
|
{"side", "lwcomponents:cannon", "main"}, -- insert items from hopper at side
|
|
})
|
|
|
|
|
|
|
|
utils.hopper_add_container({
|
|
{"top", "lwcomponents:cannon_locked", "main"}, -- take items from above into hopper below
|
|
{"bottom", "lwcomponents:cannon_locked", "main"}, -- insert items below from hopper above
|
|
{"side", "lwcomponents:cannon_locked", "main"}, -- insert items from hopper at side
|
|
})
|
|
|
|
|
|
|
|
--
|