forked from mtcontrib/boost_cart
c6b9e4b672
Clear driver on leave using the detach callback (0.5.x and later) Fix upright_sprite attachment position Fallback to the regular node sound when metal does not exist Set animation to "stand" on attach
258 lines
5.7 KiB
Lua
258 lines
5.7 KiB
Lua
function boost_cart:get_sign(z)
|
|
if z == 0 then
|
|
return 0
|
|
else
|
|
return z / math.abs(z)
|
|
end
|
|
end
|
|
|
|
function boost_cart:manage_attachment(player, obj)
|
|
if not player then
|
|
return
|
|
end
|
|
local status = obj ~= nil
|
|
local player_name = player:get_player_name()
|
|
if default.player_attached[player_name] == status then
|
|
return
|
|
end
|
|
default.player_attached[player_name] = status
|
|
|
|
if status then
|
|
local y_pos = self.old_player_model and 6 or -4
|
|
if player:get_properties().visual == "upright_sprite" then
|
|
y_pos = -4
|
|
end
|
|
player:set_attach(obj, "", {x=0, y=y_pos, z=0}, {x=0, y=0, z=0})
|
|
player:set_eye_offset({x=0, y=-4, z=0},{x=0, y=-4, z=0})
|
|
else
|
|
player:set_detach()
|
|
player:set_eye_offset({x=0, y=0, z=0},{x=0, y=0, z=0})
|
|
-- HACK in effect! Force updating the attachment rotation
|
|
player:set_properties({})
|
|
end
|
|
end
|
|
|
|
function boost_cart:velocity_to_dir(v)
|
|
if math.abs(v.x) > math.abs(v.z) then
|
|
return {x=self:get_sign(v.x), y=self:get_sign(v.y), z=0}
|
|
else
|
|
return {x=0, y=self:get_sign(v.y), z=self:get_sign(v.z)}
|
|
end
|
|
end
|
|
|
|
local get_node = minetest.get_node
|
|
local get_item_group = minetest.get_item_group
|
|
function boost_cart:is_rail(pos, railtype)
|
|
local node = get_node(pos).name
|
|
if node == "ignore" then
|
|
local vm = minetest.get_voxel_manip()
|
|
local emin, emax = vm:read_from_map(pos, pos)
|
|
local area = VoxelArea:new{
|
|
MinEdge = emin,
|
|
MaxEdge = emax,
|
|
}
|
|
local data = vm:get_data()
|
|
local vi = area:indexp(pos)
|
|
node = minetest.get_name_from_content_id(data[vi])
|
|
end
|
|
if get_item_group(node, "rail") == 0 then
|
|
return false
|
|
end
|
|
if not railtype then
|
|
return true
|
|
end
|
|
return get_item_group(node, "connect_to_raillike") == railtype
|
|
end
|
|
|
|
function boost_cart:check_front_up_down(pos, dir_, check_up, railtype)
|
|
local dir = vector.new(dir_)
|
|
local cur = nil
|
|
|
|
-- Front
|
|
dir.y = 0
|
|
cur = vector.add(pos, dir)
|
|
if self:is_rail(cur, railtype) then
|
|
return dir
|
|
end
|
|
-- Up
|
|
if check_up then
|
|
dir.y = 1
|
|
cur = vector.add(pos, dir)
|
|
if self:is_rail(cur, railtype) then
|
|
return dir
|
|
end
|
|
end
|
|
-- Down
|
|
dir.y = -1
|
|
cur = vector.add(pos, dir)
|
|
if self:is_rail(cur, railtype) then
|
|
return dir
|
|
end
|
|
return nil
|
|
end
|
|
|
|
function boost_cart:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
|
|
local pos = vector.round(pos_)
|
|
local cur = nil
|
|
local left_check, right_check = true, true
|
|
|
|
-- Check left and right
|
|
local left = {x=0, y=0, z=0}
|
|
local right = {x=0, y=0, z=0}
|
|
if dir.z ~= 0 and dir.x == 0 then
|
|
left.x = -dir.z
|
|
right.x = dir.z
|
|
elseif dir.x ~= 0 and dir.z == 0 then
|
|
left.z = dir.x
|
|
right.z = -dir.x
|
|
end
|
|
|
|
if ctrl then
|
|
if old_switch == 1 then
|
|
left_check = false
|
|
elseif old_switch == 2 then
|
|
right_check = false
|
|
end
|
|
if ctrl.left and left_check then
|
|
cur = self:check_front_up_down(pos, left, false, railtype)
|
|
if cur then
|
|
return cur, 1
|
|
end
|
|
left_check = false
|
|
end
|
|
if ctrl.right and right_check then
|
|
cur = self:check_front_up_down(pos, right, false, railtype)
|
|
if cur then
|
|
return cur, 2
|
|
end
|
|
right_check = true
|
|
end
|
|
end
|
|
|
|
-- Normal
|
|
cur = self:check_front_up_down(pos, dir, true, railtype)
|
|
if cur then
|
|
return cur
|
|
end
|
|
|
|
-- Left, if not already checked
|
|
if left_check then
|
|
cur = self:check_front_up_down(pos, left, false, railtype)
|
|
if cur then
|
|
return cur
|
|
end
|
|
end
|
|
|
|
-- Right, if not already checked
|
|
if right_check then
|
|
cur = self:check_front_up_down(pos, right, false, railtype)
|
|
if cur then
|
|
return cur
|
|
end
|
|
end
|
|
|
|
-- Backwards
|
|
if not old_switch then
|
|
cur = self:check_front_up_down(pos, {
|
|
x = -dir.x,
|
|
y = dir.y,
|
|
z = -dir.z
|
|
}, true, railtype)
|
|
if cur then
|
|
return cur
|
|
end
|
|
end
|
|
|
|
return {x=0, y=0, z=0}
|
|
end
|
|
|
|
function boost_cart:pathfinder(pos_, old_pos, old_dir, distance, ctrl,
|
|
pf_switch, railtype)
|
|
|
|
local pos = vector.round(pos_)
|
|
if vector.equals(old_pos, pos) then
|
|
return
|
|
end
|
|
|
|
local pf_pos = vector.round(old_pos)
|
|
local pf_dir = vector.new(old_dir)
|
|
distance = math.min(boost_cart.path_distance_max,
|
|
math.floor(distance + 1))
|
|
|
|
for i = 1, distance do
|
|
pf_dir, pf_switch = self:get_rail_direction(
|
|
pf_pos, pf_dir, ctrl, pf_switch or 0, railtype)
|
|
|
|
if vector.equals(pf_dir, {x=0, y=0, z=0}) then
|
|
-- No way forwards
|
|
return pf_pos, pf_dir
|
|
end
|
|
|
|
pf_pos = vector.add(pf_pos, pf_dir)
|
|
|
|
if vector.equals(pf_pos, pos) then
|
|
-- Success! Cart moved on correctly
|
|
return
|
|
end
|
|
end
|
|
-- Not found. Put cart to predicted position
|
|
return pf_pos, pf_dir
|
|
end
|
|
|
|
function boost_cart:boost_rail(pos, amount)
|
|
minetest.get_meta(pos):set_string("cart_acceleration", tostring(amount))
|
|
for _,obj_ in ipairs(minetest.get_objects_inside_radius(pos, 0.5)) do
|
|
if not obj_:is_player() and
|
|
obj_:get_luaentity() and
|
|
obj_:get_luaentity().name == "carts:cart" then
|
|
obj_:get_luaentity():on_punch()
|
|
end
|
|
end
|
|
end
|
|
|
|
function boost_cart:register_rail(name, def_overwrite)
|
|
local sound_func = default.node_sound_metal_defaults
|
|
or default.node_sound_defaults
|
|
|
|
local def = {
|
|
drawtype = "raillike",
|
|
paramtype = "light",
|
|
sunlight_propagates = true,
|
|
is_ground_content = false,
|
|
walkable = false,
|
|
selection_box = {
|
|
type = "fixed",
|
|
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
|
|
},
|
|
sounds = sound_func()
|
|
}
|
|
for k, v in pairs(def_overwrite) do
|
|
def[k] = v
|
|
end
|
|
if not def.inventory_image then
|
|
def.wield_image = def.tiles[1]
|
|
def.inventory_image = def.tiles[1]
|
|
end
|
|
|
|
minetest.register_node(name, def)
|
|
end
|
|
|
|
function boost_cart:get_rail_groups(additional_groups)
|
|
-- Get the default rail groups and add more when a table is given
|
|
local groups = {
|
|
dig_immediate = 2,
|
|
attached_node = 1,
|
|
rail = 1,
|
|
connect_to_raillike = 1
|
|
}
|
|
if minetest.raillike_group then
|
|
groups.connect_to_raillike = minetest.raillike_group("rail")
|
|
end
|
|
if type(additional_groups) == "table" then
|
|
for k, v in pairs(additional_groups) do
|
|
groups[k] = v
|
|
end
|
|
end
|
|
return groups
|
|
end
|