Merge pull request #499 from Coethium/mff.carts
All in one cart/rail patch
34
mods/carts/README.txt
Executable file → Normal file
@ -1,17 +1,20 @@
|
||||
Minetest 0.4 mod: carts
|
||||
=======================
|
||||
by PilzAdam
|
||||
This version is modified by Kilarin (Donald Hines), all changes CC-0
|
||||
modifications include:
|
||||
New Controls:LEFT or RIGHT to switch track at junction
|
||||
DOWN for hand break
|
||||
JUMP lock the users view to the view of the cart
|
||||
SNEAK unlock the users view from the cart
|
||||
Touring Rails: Try to maintain a speed of 4.5
|
||||
Chat notification of controls when cart is placed
|
||||
Track rail count in debug.txt
|
||||
punch by driver patch from spillz
|
||||
get_voxel when hit ignore patch by minermoder27
|
||||
Minetest mod: carts for MFF
|
||||
===========================
|
||||
|
||||
Based on boost_cart and modified to fully *replace* carts (@Coethium)
|
||||
- desactivate mesecons
|
||||
- power_rail: accelerate, max_speed set in init.lua
|
||||
- brake_rail: deccelerate, min_speed set in init.lua (so the cart doesn't stop and runs at very low speed)
|
||||
- default:rail / rail_cooper : no friction, keep the current speed
|
||||
- no collision (avoid the "walled_in" bug)
|
||||
|
||||
|
||||
|
||||
Boost_cart
|
||||
==========
|
||||
|
||||
Based on (and fully compatible with) the mod "carts" by PilzAdam
|
||||
Target: Run smoothly and do not use too much CPU
|
||||
|
||||
License of source code:
|
||||
-----------------------
|
||||
@ -31,6 +34,3 @@ kddekadenz:
|
||||
Zeg9:
|
||||
cart.x
|
||||
cart.png
|
||||
|
||||
rarkenin:
|
||||
cart_rail_*.png
|
||||
|
2
mods/carts/depends.txt
Executable file → Normal file
@ -1 +1,3 @@
|
||||
default
|
||||
mesecons?
|
||||
moreores?
|
58
mods/carts/detector.lua
Normal file
@ -0,0 +1,58 @@
|
||||
local mesecons_rules = mesecon.rules.flat
|
||||
|
||||
function carts:turnoff_detector_rail(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
if minetest.get_item_group(node.name, "detector_rail") == 1 then
|
||||
if node.name == "carts:detectorrail_on" then --has not been dug
|
||||
minetest.swap_node(pos, {name = "carts:detectorrail", param2=node.param2})
|
||||
end
|
||||
mesecon.receptor_off(pos, mesecons_rules)
|
||||
end
|
||||
end
|
||||
|
||||
function carts:signal_detector_rail(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
if minetest.get_item_group(node.name, "detector_rail") ~= 1 then
|
||||
return
|
||||
end
|
||||
|
||||
if node.name == "carts:detectorrail" then
|
||||
minetest.swap_node(pos, {name = "carts:detectorrail_on", param2=node.param2})
|
||||
end
|
||||
mesecon.receptor_on(pos, mesecons_rules)
|
||||
minetest.after(0.5, carts.turnoff_detector_rail, carts, pos)
|
||||
end
|
||||
|
||||
carts:register_rail("carts:detectorrail", {
|
||||
description = "Detector rail",
|
||||
tiles = {
|
||||
"carts_rail_dtc.png", "carts_rail_curved_dtc.png",
|
||||
"carts_rail_t_junction_dtc.png", "carts_rail_crossing_dtc.png"
|
||||
},
|
||||
groups = carts:get_rail_groups({detector_rail = 1}),
|
||||
|
||||
mesecons = {receptor = {state = "off", rules = mesecons_rules}},
|
||||
})
|
||||
|
||||
carts:register_rail("carts:detectorrail_on", {
|
||||
description = "Detector rail ON (you hacker you)",
|
||||
tiles = {
|
||||
"carts_rail_dtc_on.png", "carts_rail_curved_dtc_on.png",
|
||||
"carts_rail_t_junction_dtc_on.png", "carts_rail_crossing_dtc_on.png"
|
||||
},
|
||||
groups = carts:get_rail_groups({
|
||||
detector_rail = 1, not_in_creative_inventory = 1
|
||||
}),
|
||||
drop = "carts:detectorrail",
|
||||
|
||||
mesecons = {receptor = {state = "on", rules = mesecons_rules}},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "carts:detectorrail 6",
|
||||
recipe = {
|
||||
{"default:steel_ingot", "mesecons:wire_00000000_off", "default:steel_ingot"},
|
||||
{"default:steel_ingot", "group:stick", "default:steel_ingot"},
|
||||
{"default:steel_ingot", "mesecons:wire_00000000_off", "default:steel_ingot"},
|
||||
},
|
||||
})
|
265
mods/carts/functions.lua
Executable file → Normal file
@ -1,11 +1,4 @@
|
||||
|
||||
--
|
||||
-- Helper functions
|
||||
--
|
||||
|
||||
cart_func = {}
|
||||
|
||||
function cart_func:get_sign(z)
|
||||
function carts:get_sign(z)
|
||||
if z == 0 then
|
||||
return 0
|
||||
else
|
||||
@ -13,77 +6,221 @@ function cart_func:get_sign(z)
|
||||
end
|
||||
end
|
||||
|
||||
-- Returns the velocity as a unit vector
|
||||
-- The smaller part of the vector will be turned to 0
|
||||
function cart_func:velocity_to_dir(v)
|
||||
function carts:manage_attachment(player, status, obj)
|
||||
if not player then
|
||||
return
|
||||
end
|
||||
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
|
||||
player:set_attach(obj, "", {x=0, y=6, 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})
|
||||
end
|
||||
end
|
||||
|
||||
function carts:velocity_to_dir(v)
|
||||
if math.abs(v.x) > math.abs(v.z) then
|
||||
return {x=cart_func:get_sign(v.x), y=cart_func:get_sign(v.y), z=0}
|
||||
return {x=carts:get_sign(v.x), y=carts:get_sign(v.y), z=0}
|
||||
else
|
||||
return {x=0, y=cart_func:get_sign(v.y), z=cart_func:get_sign(v.z)}
|
||||
return {x=0, y=carts:get_sign(v.y), z=carts:get_sign(v.z)}
|
||||
end
|
||||
end
|
||||
|
||||
function cart_func:is_rail(p)
|
||||
local nn = minetest.get_node(p).name
|
||||
--print("*!* is_rail p x=",p.x," y=",p.y," z=",p.z," nn=",nn," group rail=", minetest.get_item_group(nn, "rail"))
|
||||
if nn == "ignore" then
|
||||
nn=cart_func:get_content_voxel(p)
|
||||
print("carts: is_rail hit ignore, trying again with get_content: now nn=",nn," group rail=", minetest.get_item_group(nn, "rail"),"p x=",p.x," y=",p.y," z=",p.z)
|
||||
function carts:is_rail(pos, railtype)
|
||||
local node = minetest.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
|
||||
return minetest.get_item_group(nn, "rail") ~= 0
|
||||
end
|
||||
|
||||
function cart_func:check_rail_in_direction(pos, dir)
|
||||
local p = cart_func.v3:add(pos, dir)
|
||||
if cart_func:is_rail(p) then
|
||||
return true
|
||||
else
|
||||
if minetest.get_item_group(node, "rail") == 0 then
|
||||
return false
|
||||
end
|
||||
end -- cart:check_rail_in_direction
|
||||
|
||||
|
||||
function cart_func:is_int(z)
|
||||
z = math.abs(z)
|
||||
return math.abs(math.floor(z+0.5)-z) <= 0.1
|
||||
if not railtype then
|
||||
return true
|
||||
end
|
||||
return minetest.get_item_group(node, "connect_to_raillike") == railtype
|
||||
end
|
||||
|
||||
cart_func.v3 = {}
|
||||
function carts:check_front_up_down(pos, dir_, check_up, railtype)
|
||||
local dir = vector.new(dir_)
|
||||
local cur = nil
|
||||
|
||||
function cart_func.v3:add(v1, v2)
|
||||
return {x=v1.x+v2.x, y=v1.y+v2.y, z=v1.z+v2.z}
|
||||
-- Front
|
||||
dir.y = 0
|
||||
cur = vector.add(pos, dir)
|
||||
if carts:is_rail(cur, railtype) then
|
||||
return dir
|
||||
end
|
||||
-- Up
|
||||
if check_up then
|
||||
dir.y = 1
|
||||
cur = vector.add(pos, dir)
|
||||
if carts:is_rail(cur, railtype) then
|
||||
return dir
|
||||
end
|
||||
end
|
||||
-- Down
|
||||
dir.y = -1
|
||||
cur = vector.add(pos, dir)
|
||||
if carts:is_rail(cur, railtype) then
|
||||
return dir
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function cart_func.v3:copy(v)
|
||||
return {x=v.x, y=v.y, z=v.z}
|
||||
function carts: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
|
||||
|
||||
function cart_func.v3:round(v)
|
||||
return {
|
||||
x = math.floor(v.x+0.5),
|
||||
y = math.floor(v.y+0.5),
|
||||
z = math.floor(v.z+0.5),
|
||||
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 = carts: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 = carts:check_front_up_down(pos, right, false, railtype)
|
||||
if cur then
|
||||
return cur, 2
|
||||
end
|
||||
right_check = true
|
||||
end
|
||||
end
|
||||
|
||||
-- Normal
|
||||
cur = carts:check_front_up_down(pos, dir, true, railtype)
|
||||
if cur then
|
||||
return cur
|
||||
end
|
||||
|
||||
-- Left, if not already checked
|
||||
if left_check then
|
||||
cur = carts: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 = carts:check_front_up_down(pos, right, false, railtype)
|
||||
if cur then
|
||||
return cur
|
||||
end
|
||||
end
|
||||
|
||||
-- Backwards
|
||||
if not old_switch then
|
||||
cur = carts: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 carts:pathfinder(pos_, expected_pos, old_dir, ctrl, pf_switch, railtype)
|
||||
local pos = vector.round(pos_)
|
||||
local pf_pos = vector.round(expected_pos)
|
||||
local pf_dir = vector.new(old_dir)
|
||||
|
||||
for i = 1, 3 do
|
||||
if vector.equals(pf_pos, pos) then
|
||||
-- Success! Cart moved on correctly
|
||||
return true
|
||||
end
|
||||
|
||||
pf_dir, pf_switch = carts:get_rail_direction(pf_pos, pf_dir, ctrl, pf_switch, railtype)
|
||||
if vector.equals(pf_dir, {x=0, y=0, z=0}) then
|
||||
-- No way forwards
|
||||
return false
|
||||
end
|
||||
|
||||
pf_pos = vector.add(pf_pos, pf_dir)
|
||||
end
|
||||
-- Cart not found
|
||||
return false
|
||||
end
|
||||
|
||||
function carts: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 carts:register_rail(name, def)
|
||||
local def_default = {
|
||||
drawtype = "raillike",
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = true,
|
||||
walkable = false,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
|
||||
}
|
||||
end
|
||||
|
||||
function cart_func.v3:equal(v1, v2)
|
||||
return v1.x == v2.x and v1.y == v2.y and v1.z == v2.z
|
||||
end
|
||||
|
||||
|
||||
function cart_func:get_content_voxel(pos)
|
||||
local t1 = os.clock()
|
||||
local vm = minetest.get_voxel_manip()
|
||||
local pos1, pos2 = vm:read_from_map(vector.add(pos, {x=-1,y=-1,z=-1}),vector.add(pos, {x=1,y=1,z=1}))
|
||||
local a = VoxelArea:new{
|
||||
MinEdge=pos1,
|
||||
MaxEdge=pos2,
|
||||
}
|
||||
|
||||
local data = vm:get_data()
|
||||
local vi = a:indexp(pos)
|
||||
local railid = data[vi]
|
||||
local real_name = minetest.get_name_from_content_id(railid)
|
||||
print(string.format("voxel-ing rail: elapsed time: %.2fms", (os.clock() - t1) * 1000))
|
||||
return real_name
|
||||
for k, v in pairs(def_default) 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 carts: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 type(additional_groups) == "table" then
|
||||
for k, v in pairs(additional_groups) do
|
||||
groups[k] = v
|
||||
end
|
||||
end
|
||||
return groups
|
||||
end
|
||||
|
829
mods/carts/init.lua
Executable file → Normal file
@ -1,594 +1,400 @@
|
||||
dofile(minetest.get_modpath("carts").."/functions.lua")
|
||||
dofile(minetest.get_modpath("carts").."/rails.lua")
|
||||
|
||||
local cart = {
|
||||
physical = true, -- Set to false to not make carts collide with other entities such as carts or the player.
|
||||
carts = {}
|
||||
carts.modpath = minetest.get_modpath("carts")
|
||||
|
||||
-- Maximal speed of the cart in m/s
|
||||
carts.speed_max = minetest.setting_get("movement_speed_walk")*3
|
||||
-- Minimal speed of the cart on brake rail
|
||||
carts.brake_speed_min = minetest.setting_get("movement_speed_walk")/2
|
||||
-- Set to nil to disable punching the cart from inside (min = -1)
|
||||
carts.punch_speed_min = 7
|
||||
-- 1 disable mesecons / 0 enable mesecons
|
||||
carts.mesecon_disabled = 1
|
||||
|
||||
|
||||
if not carts.modpath then
|
||||
error("\nWrong mod directory name! Please change it to 'carts'.\n" ..
|
||||
"See also: http://dev.minetest.net/Installing_Mods")
|
||||
end
|
||||
|
||||
function vector.floor(v)
|
||||
return {
|
||||
x = math.floor(v.x),
|
||||
y = math.floor(v.y),
|
||||
z = math.floor(v.z)
|
||||
}
|
||||
end
|
||||
|
||||
dofile(carts.modpath.."/functions.lua")
|
||||
dofile(carts.modpath.."/rails.lua")
|
||||
|
||||
if not carts.mesecon_disabled and mesecon then
|
||||
dofile(carts.modpath.."/detector.lua")
|
||||
end
|
||||
|
||||
-- Support for non-default games
|
||||
if not default.player_attached then
|
||||
default.player_attached = {}
|
||||
end
|
||||
|
||||
carts.cart = {
|
||||
physical = false,
|
||||
collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
|
||||
visual = "mesh",
|
||||
mesh = "cart.x",
|
||||
visual_size = {x=1, y=1},
|
||||
textures = {"cart.png"}, -- Set to "invisible.png" to make the cart invisible, which is sometimes useful for videos and custom maps.
|
||||
textures = {"cart.png"},
|
||||
|
||||
driver = nil,
|
||||
velocity = {x=0, y=0, z=0},
|
||||
punched = false, -- used to re-send velocity and position
|
||||
velocity = {x=0, y=0, z=0}, -- only used on punch
|
||||
old_dir = {x=1, y=0, z=0}, -- random value to start the cart on punch
|
||||
old_pos = nil,
|
||||
old_velocity = nil,
|
||||
pre_stop_dir = nil,
|
||||
MAX_V = minetest.setting_get("movement_speed_walk")*2.5, -- Limit of the velocity (speed). default: 3 times the walk speed
|
||||
TARGET_TOUR_V = 6, -- Target touring velocity, currently unused.
|
||||
railcount = 0,
|
||||
ignorekeypos = nil,
|
||||
lockyaw = false, -- Set to true to lock camera by default. If set to false, player has to press the "jump" key to lock camera.
|
||||
yawtarget = nil,
|
||||
YAW_STEP = math.pi/64 -- Larger YAW_STEP makes for slower camera turning.
|
||||
old_switch = 0,
|
||||
railtype = nil,
|
||||
attached_items = {}
|
||||
}
|
||||
|
||||
function cart:on_rightclick(clicker)
|
||||
function carts.cart:on_rightclick(clicker)
|
||||
if not clicker or not clicker:is_player() then
|
||||
return
|
||||
end
|
||||
if self.driver and clicker == self.driver then
|
||||
local player_name = clicker:get_player_name()
|
||||
if self.driver and player_name == self.driver then
|
||||
self.driver = nil
|
||||
clicker:set_detach()
|
||||
carts:manage_attachment(clicker, false)
|
||||
elseif not self.driver then
|
||||
self.driver = clicker
|
||||
clicker:set_attach(self.object, "", {x=0,y=5,z=0}, {x=0,y=0,z=0})
|
||||
self.driver = player_name
|
||||
carts:manage_attachment(clicker, true, self.object)
|
||||
end
|
||||
end
|
||||
|
||||
function cart:on_activate(staticdata, dtime_s)
|
||||
function carts.cart:on_activate(staticdata, dtime_s)
|
||||
self.object:set_armor_groups({immortal=1})
|
||||
if staticdata then
|
||||
local tmp = minetest.deserialize(staticdata)
|
||||
if tmp then
|
||||
self.velocity = tmp.velocity
|
||||
if string.sub(staticdata, 1, string.len("return")) ~= "return" then
|
||||
return
|
||||
end
|
||||
if tmp and tmp.pre_stop_dir then
|
||||
self.pre_stop_dir = tmp.pre_stop_dir
|
||||
local data = minetest.deserialize(staticdata)
|
||||
if not data or type(data) ~= "table" then
|
||||
return
|
||||
end
|
||||
self.railtype = data.railtype
|
||||
if data.old_dir then
|
||||
self.old_dir = data.old_dir
|
||||
end
|
||||
self.old_pos = self.object:getpos()
|
||||
self.old_velocity = self.velocity
|
||||
end
|
||||
|
||||
function cart:get_staticdata()
|
||||
function carts.cart:get_staticdata()
|
||||
return minetest.serialize({
|
||||
velocity = self.velocity,
|
||||
pre_stop_dir = self.pre_stop_dir,
|
||||
railtype = self.railtype,
|
||||
old_dir = self.old_dir
|
||||
})
|
||||
end
|
||||
|
||||
-- Remove the cart if holding a tool or accelerate it
|
||||
function cart:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
|
||||
function carts.cart:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
|
||||
local pos = self.object:getpos()
|
||||
if not self.railtype then
|
||||
local bar = vector.floor(vector.add(pos, 0.1))
|
||||
local node = minetest.get_node(bar).name
|
||||
self.railtype = minetest.get_item_group(node, "connect_to_raillike")
|
||||
end
|
||||
|
||||
if not puncher or not puncher:is_player() then
|
||||
local cart_dir = carts:get_rail_direction(pos, self.old_dir, nil, nil, self.railtype)
|
||||
if vector.equals(cart_dir, {x=0, y=0, z=0}) then
|
||||
return
|
||||
end
|
||||
self.velocity = vector.multiply(cart_dir, 3)
|
||||
self.old_pos = nil
|
||||
self.punched = true
|
||||
return
|
||||
end
|
||||
|
||||
if puncher:get_player_control().sneak then
|
||||
minetest.log("action", "carts:cart removed at " .. pos_to_string(vector.round(self.object:getpos())) .. ", " .. self.railcount .. " rails travelled.")
|
||||
self.object:remove()
|
||||
local inv = puncher:get_inventory()
|
||||
if minetest.setting_getbool("creative_mode") then
|
||||
if not inv:contains_item("main", "carts:cart") then
|
||||
inv:add_item("main", "carts:cart")
|
||||
end
|
||||
else
|
||||
inv:add_item("main", "carts:cart")
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if puncher == self.driver and (math.abs(self.velocity.x)>1 or math.abs(self.velocity.z)>1) then
|
||||
return
|
||||
end
|
||||
|
||||
local d = cart_func:velocity_to_dir(direction)
|
||||
if d.x==0 and d.z==0 then
|
||||
local fd = minetest.dir_to_facedir(puncher:get_look_dir())
|
||||
if fd == 0 then
|
||||
d.x = 1
|
||||
elseif fd == 1 then
|
||||
d.z = -1
|
||||
elseif fd == 2 then
|
||||
d.x = -1
|
||||
elseif fd == 3 then
|
||||
d.z = 1
|
||||
end
|
||||
end
|
||||
|
||||
local s = self.velocity
|
||||
if time_from_last_punch > tool_capabilities.full_punch_interval then
|
||||
time_from_last_punch = tool_capabilities.full_punch_interval
|
||||
end
|
||||
local f = 4*(time_from_last_punch/tool_capabilities.full_punch_interval)
|
||||
local v = {x=s.x+d.x*f, y=s.y, z=s.z+d.z*f}
|
||||
if math.abs(v.x) < 6 and math.abs(v.z) < 6 then
|
||||
self.velocity = v
|
||||
else
|
||||
if math.abs(self.velocity.x) < 6 and math.abs(v.x) >= 6 then
|
||||
self.velocity.x = 6*cart_func:get_sign(self.velocity.x)
|
||||
end
|
||||
if math.abs(self.velocity.z) < 6 and math.abs(v.z) >= 6 then
|
||||
self.velocity.z = 6*cart_func:get_sign(self.velocity.z)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Returns the direction as a unit vector
|
||||
function cart:get_rail_direction(pos, dir)
|
||||
--minetest.log("action", "get_rail_direction top pos="..pos_to_string(pos).." dir="..pos_to_string(dir))
|
||||
local fwd=cart_func.v3:copy(dir)
|
||||
fwd.y=0
|
||||
local up=cart_func.v3:copy(dir)
|
||||
up.y=1
|
||||
local down=cart_func.v3:copy(dir)
|
||||
down.y=-1
|
||||
-- figure out 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 --left is opposite sign from z
|
||||
right.x=dir.z --right is same sign as z
|
||||
elseif dir.x ~= 0 and dir.z == 0 then
|
||||
left.z=dir.x --left is same sign as x
|
||||
right.z=-dir.x --right is opposite sign from x
|
||||
end --left and right
|
||||
local leftdown=cart_func.v3:copy(left)
|
||||
leftdown.y=-1
|
||||
local rightdown=cart_func.v3:copy(right)
|
||||
rightdown.y=-1
|
||||
--minetest.log("action", " fwd="..pos_to_string(fwd))
|
||||
--minetest.log("action", " down="..pos_to_string(down))
|
||||
--minetest.log("action", " up="..pos_to_string(up))
|
||||
--minetest.log("action", " left="..pos_to_string(left))
|
||||
--minetest.log("action", " leftdown="..pos_to_string(leftdown))
|
||||
--minetest.log("action", " right="..pos_to_string(right))
|
||||
--minetest.log("action", " rightdown="..pos_to_string(rightdown))
|
||||
|
||||
local ignorekeys=false
|
||||
--ignorekeypos stores a position where we changed direction because the
|
||||
--player was pressing left or right keys. once we have changed direction,
|
||||
--we want to ignore those keys until you have changed to a different rail
|
||||
--(otherwise you end up reversing)
|
||||
--I use the ignorekeys boolean to make the key logic more readable
|
||||
if self.ignorekeypos then --ignorekeypos was set
|
||||
if cart_func.v3:equal(self.ignorekeypos,pos) then
|
||||
ignorekeys=true --if still at same position, ignore left and right keys
|
||||
else
|
||||
self.ignorekeypos=nil --if ignorekeypos was set but pos does not match anymore, clear it
|
||||
end
|
||||
end
|
||||
|
||||
local ctrl=nil
|
||||
if self.driver and not ignorekeys then
|
||||
ctrl = self.driver:get_player_control()
|
||||
end
|
||||
|
||||
if ctrl and ctrl.left then --left key pressed, check left first
|
||||
if cart_func:check_rail_in_direction(pos,left) then
|
||||
self.ignorekeypos=cart_func.v3:copy(pos) --ignore keys until pos changes
|
||||
return left
|
||||
elseif cart_func:check_rail_in_direction(pos,leftdown) then
|
||||
self.ignorekeypos=cart_func.v3:copy(pos)
|
||||
return leftdown
|
||||
end
|
||||
elseif ctrl and ctrl.right then --right key pressed, check right first
|
||||
if cart_func:check_rail_in_direction(pos,right) then
|
||||
self.ignorekeypos=cart_func.v3:copy(pos)
|
||||
return right
|
||||
elseif cart_func:check_rail_in_direction(pos,rightdown) then
|
||||
self.ignorekeypos=cart_func.v3:copy(pos)
|
||||
return rightdown
|
||||
end
|
||||
end --ctrl.left ctrl.right
|
||||
|
||||
--now for normal checks
|
||||
if cart_func:check_rail_in_direction(pos,fwd) then
|
||||
return fwd
|
||||
elseif cart_func:check_rail_in_direction(pos,down) then
|
||||
return down
|
||||
elseif cart_func:check_rail_in_direction(pos,up) then
|
||||
return up
|
||||
elseif (not ctrl or not ctrl.left) --only check left if we didnt above
|
||||
and cart_func:check_rail_in_direction(pos,left) then
|
||||
return left
|
||||
elseif (not ctrl or not ctrl.left)
|
||||
and cart_func:check_rail_in_direction(pos,leftdown) then
|
||||
return leftdown
|
||||
elseif (not ctrl or not ctrl.right) --only check right if we didnt above
|
||||
and cart_func:check_rail_in_direction(pos,right) then
|
||||
return right
|
||||
elseif (not ctrl or not ctrl.right)
|
||||
and cart_func:check_rail_in_direction(pos,rightdown) then
|
||||
return rightdown
|
||||
else
|
||||
return {x=0, y=0, z=0}
|
||||
end --normal rail checks
|
||||
end --get_rail_direction
|
||||
|
||||
function cart:calc_rail_direction(pos, vel)
|
||||
local velocity = cart_func.v3:copy(vel)
|
||||
local p = cart_func.v3:copy(pos)
|
||||
if cart_func:is_int(p.x) and cart_func:is_int(p.z) then
|
||||
|
||||
local dir = cart_func:velocity_to_dir(velocity)
|
||||
local dir_old = cart_func.v3:copy(dir)
|
||||
|
||||
dir = self:get_rail_direction(cart_func.v3:round(p), dir)
|
||||
|
||||
local v = math.max(math.abs(velocity.x), math.abs(velocity.z))
|
||||
velocity = {
|
||||
x = v * dir.x,
|
||||
y = v * dir.y,
|
||||
z = v * dir.z,
|
||||
}
|
||||
|
||||
if cart_func.v3:equal(velocity, {x=0, y=0, z=0}) and not cart_func:is_rail(p) then
|
||||
|
||||
-- First try this HACK
|
||||
-- Move the cart on the rail if above or under it
|
||||
if cart_func:is_rail(cart_func.v3:add(p, {x=0, y=1, z=0})) and vel.y >= 0 then
|
||||
p = cart_func.v3:add(p, {x=0, y=1, z=0})
|
||||
return self:calc_rail_direction(p, vel)
|
||||
end
|
||||
if cart_func:is_rail(cart_func.v3:add(p, {x=0, y=-1, z=0})) and vel.y <= 0 then
|
||||
p = cart_func.v3:add(p, {x=0, y=-1, z=0})
|
||||
return self:calc_rail_direction(p, vel)
|
||||
end
|
||||
-- Now the HACK gets really dirty
|
||||
if cart_func:is_rail(cart_func.v3:add(p, {x=0, y=2, z=0})) and vel.y >= 0 then
|
||||
p = cart_func.v3:add(p, {x=0, y=1, z=0})
|
||||
return self:calc_rail_direction(p, vel)
|
||||
end
|
||||
if cart_func:is_rail(cart_func.v3:add(p, {x=0, y=-2, z=0})) and vel.y <= 0 then
|
||||
p = cart_func.v3:add(p, {x=0, y=-1, z=0})
|
||||
return self:calc_rail_direction(p, vel)
|
||||
end
|
||||
-- NOW the hack gets even dirtier
|
||||
if cart_func:is_rail(cart_func.v3:add(p, {x=0, y=3, z=0})) and vel.y >= 0 then
|
||||
p = cart_func.v3:add(p, {x=0, y=1, z=0})
|
||||
return self:calc_rail_direction(p, vel)
|
||||
end
|
||||
if cart_func:is_rail(cart_func.v3:add(p, {x=0, y=-3, z=0})) and vel.y <= 0 then
|
||||
p = cart_func.v3:add(p, {x=0, y=-1, z=0})
|
||||
return self:calc_rail_direction(p, vel)
|
||||
end
|
||||
if cart_func:is_rail(cart_func.v3:add(p, {x=0, y=4, z=0})) and vel.y >= 0 then
|
||||
p = cart_func.v3:add(p, {x=0, y=1, z=0})
|
||||
return self:calc_rail_direction(p, vel)
|
||||
end
|
||||
if cart_func:is_rail(cart_func.v3:add(p, {x=0, y=-4, z=0})) and vel.y <= 0 then
|
||||
p = cart_func.v3:add(p, {x=0, y=-1, z=0})
|
||||
return self:calc_rail_direction(p, vel)
|
||||
end
|
||||
|
||||
return {x=0, y=0, z=0}, p
|
||||
end
|
||||
|
||||
if not cart_func.v3:equal(dir, dir_old) then
|
||||
return velocity, cart_func.v3:round(p)
|
||||
end
|
||||
|
||||
end
|
||||
return velocity, p
|
||||
end
|
||||
|
||||
-- built in pos_to_string doesn't handle nil.
|
||||
function pos_to_string(pos)
|
||||
if pos==nil then return "(nil)"
|
||||
else return minetest.pos_to_string(pos)
|
||||
end --poss==nil
|
||||
end --pos_to_string
|
||||
|
||||
function cart:on_step(dtime)
|
||||
|
||||
local pos = self.object:getpos()
|
||||
local dir = cart_func:velocity_to_dir(self.velocity)
|
||||
|
||||
-- *!* Debug.
|
||||
-- Pick up cart: Drop all attachments
|
||||
if self.driver then
|
||||
if self.old_pos then
|
||||
local cmp_old=vector.round(self.old_pos)
|
||||
local cmp_new=vector.round(pos)
|
||||
if cmp_old.x~=cmp_new.x or cmp_old.y~=cmp_new.y or cmp_old.z~=cmp_new.z then
|
||||
self.railcount=self.railcount+1
|
||||
-- local a = tonumber(minetest.get_meta(pos):get_string("cart_acceleration"))
|
||||
-- local railtype=""
|
||||
-- if a and a>0 then railtype="power" end
|
||||
-- minetest.chat_send_all("-- cart pos="..pos_to_string(vector.round(pos)).." railcount="..self.railcount.." vel="..pos_to_string(self.velocity).." "..railtype) --*!*debug
|
||||
self.object:setpos(self.old_pos)
|
||||
end
|
||||
local player = minetest.get_player_by_name(self.driver)
|
||||
carts:manage_attachment(player, false)
|
||||
end
|
||||
for _,obj_ in ipairs(self.attached_items) do
|
||||
if obj_ then
|
||||
obj_:set_detach()
|
||||
end
|
||||
end
|
||||
-- *!* Debug.
|
||||
|
||||
local ctrl=nil
|
||||
local leftover = puncher:get_inventory():add_item("main", "carts:cart")
|
||||
if not leftover:is_empty() then
|
||||
minetest.add_item(self.object:getpos(), leftover)
|
||||
end
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
|
||||
local vel = self.object:getvelocity()
|
||||
if puncher:get_player_name() == self.driver then
|
||||
if math.abs(vel.x + vel.z) > carts.punch_speed_min then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local punch_dir = carts:velocity_to_dir(puncher:get_look_dir())
|
||||
punch_dir.y = 0
|
||||
local cart_dir = carts:get_rail_direction(pos, punch_dir, nil, nil, self.railtype)
|
||||
if vector.equals(cart_dir, {x=0, y=0, z=0}) then
|
||||
return
|
||||
end
|
||||
|
||||
local punch_interval = 1
|
||||
if tool_capabilities and tool_capabilities.full_punch_interval then
|
||||
punch_interval = tool_capabilities.full_punch_interval
|
||||
end
|
||||
time_from_last_punch = math.min(time_from_last_punch or punch_interval, punch_interval)
|
||||
local f = 3 * (time_from_last_punch / punch_interval)
|
||||
|
||||
self.velocity = vector.multiply(cart_dir, f)
|
||||
self.old_dir = cart_dir
|
||||
self.old_pos = nil
|
||||
self.punched = true
|
||||
end
|
||||
|
||||
function carts.cart:on_step(dtime)
|
||||
local vel = self.object:getvelocity()
|
||||
local update = {}
|
||||
if self.punched then
|
||||
vel = vector.add(vel, self.velocity)
|
||||
self.object:setvelocity(vel)
|
||||
self.old_dir.y = 0
|
||||
elseif vector.equals(vel, {x=0, y=0, z=0}) then
|
||||
return
|
||||
end
|
||||
|
||||
-- dir: New moving direction of the cart
|
||||
-- last_switch: Currently pressed L/R key, used to ignore the key on the next rail node
|
||||
local dir, last_switch
|
||||
local pos = self.object:getpos()
|
||||
local is_slow = ((vel.x ~= 0 and math.abs(vel.x) <= carts.brake_speed_min) or
|
||||
(vel.y ~= 0 and math.abs(vel.y) <= carts.brake_speed_min) or
|
||||
(vel.z ~= 0 and math.abs(vel.z) <= carts.brake_speed_min)) and
|
||||
string.match(minetest.get_node(pos).name, "brake")
|
||||
|
||||
if self.old_pos and not self.punched then
|
||||
local flo_pos = vector.round(pos)
|
||||
local flo_old = vector.round(self.old_pos)
|
||||
if vector.equals(flo_pos, flo_old) and not is_slow then -- Do not check one node multiple times (but check if low speed)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local ctrl, player
|
||||
|
||||
-- Get player controls
|
||||
if self.driver then
|
||||
ctrl = self.driver:get_player_control()
|
||||
if ctrl and ctrl.jump and not self.lockyaw then
|
||||
self.lockyaw=true
|
||||
self.yawtarget=self.object:getyaw()
|
||||
-- minetest.chat_send_player(self.driver:get_player_name(),"Player view locked to cart, sneak to unlock.")
|
||||
elseif ctrl and ctrl.sneak and self.lockyaw then
|
||||
self.lockyaw=false
|
||||
-- minetest.chat_send_player(self.driver:get_player_name(),"Player view unlocked from cart, jump to lock.")
|
||||
end
|
||||
end -- Check lockyaw if self.driver.
|
||||
|
||||
if not cart_func.v3:equal(self.velocity, {x=0,y=0,z=0}) then
|
||||
self.pre_stop_dir = cart_func:velocity_to_dir(self.velocity)
|
||||
end
|
||||
|
||||
-- Stop the cart if the velocity is nearly 0, only if on a flat railway.
|
||||
if dir.y == 0 then
|
||||
if math.abs(self.velocity.x) < 0.1 and math.abs(self.velocity.z) < 0.1 then
|
||||
-- Start the cart if powered from mesecons.
|
||||
local a = 0--tonumber(minetest.get_meta(pos):get_string("cart_acceleration"))
|
||||
if a and a ~= 0 then
|
||||
if self.pre_stop_dir and cart_func.v3:equal(self:get_rail_direction(self.object:getpos(), self.pre_stop_dir), self.pre_stop_dir) then
|
||||
self.velocity = {
|
||||
x = self.pre_stop_dir.x * 0.2,
|
||||
y = self.pre_stop_dir.y * 0.2,
|
||||
z = self.pre_stop_dir.z * 0.2,
|
||||
}
|
||||
self.old_velocity = self.velocity
|
||||
return
|
||||
end
|
||||
for _,y in ipairs({0,-1,1}) do
|
||||
for _,z in ipairs({1,-1}) do
|
||||
if cart_func.v3:equal(self:get_rail_direction(self.object:getpos(), {x=0, y=y, z=z}), {x=0, y=y, z=z}) then
|
||||
self.velocity = {
|
||||
x = 0,
|
||||
y = 0.2*y,
|
||||
z = 0.2*z,
|
||||
}
|
||||
self.old_velocity = self.velocity
|
||||
return
|
||||
end
|
||||
end
|
||||
for _,x in ipairs({1,-1}) do
|
||||
if cart_func.v3:equal(self:get_rail_direction(self.object:getpos(), {x=x, y=y, z=0}), {x=x, y=y, z=0}) then
|
||||
self.velocity = {
|
||||
x = 0.2*x,
|
||||
y = 0.2*y,
|
||||
z = 0,
|
||||
}
|
||||
self.old_velocity = self.velocity
|
||||
return
|
||||
end
|
||||
end
|
||||
player = minetest.get_player_by_name(self.driver)
|
||||
if player then
|
||||
ctrl = player:get_player_control()
|
||||
end
|
||||
end
|
||||
|
||||
self.velocity = {x=0, y=0, z=0}
|
||||
self.object:setvelocity(self.velocity)
|
||||
self.old_velocity = self.velocity
|
||||
self.old_pos = self.object:getpos()
|
||||
return
|
||||
if self.old_pos then
|
||||
-- Detection for "skipping" nodes
|
||||
local expected_pos = vector.add(self.old_pos, self.old_dir)
|
||||
local found_path = carts:pathfinder(
|
||||
pos, expected_pos, self.old_dir, ctrl, self.old_switch, self.railtype
|
||||
)
|
||||
|
||||
if not found_path and not is_slow then
|
||||
-- No rail found: reset back to the expected position
|
||||
pos = expected_pos
|
||||
update.pos = true
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Set the new moving direction
|
||||
--
|
||||
|
||||
-- Recalcualte the rails that are passed since the last server step
|
||||
local old_dir = cart_func:velocity_to_dir(self.old_velocity)
|
||||
if old_dir.x ~= 0 then
|
||||
local sign = cart_func:get_sign(pos.x-self.old_pos.x)
|
||||
while true do
|
||||
if sign ~= cart_func:get_sign(pos.x-self.old_pos.x) or pos.x == self.old_pos.x then
|
||||
break
|
||||
end
|
||||
self.old_pos.x = self.old_pos.x + cart_func:get_sign(pos.x-self.old_pos.x)*0.1
|
||||
self.old_pos.y = self.old_pos.y + cart_func:get_sign(pos.x-self.old_pos.x)*0.1*old_dir.y
|
||||
self.old_velocity, self.old_pos = self:calc_rail_direction(self.old_pos, self.old_velocity)
|
||||
old_dir = cart_func:velocity_to_dir(self.old_velocity)
|
||||
if not cart_func.v3:equal(cart_func:velocity_to_dir(self.old_velocity), dir) then
|
||||
self.velocity = self.old_velocity
|
||||
pos = self.old_pos
|
||||
self.object:setpos(self.old_pos)
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif old_dir.z ~= 0 then
|
||||
local sign = cart_func:get_sign(pos.z-self.old_pos.z)
|
||||
while true do
|
||||
if sign ~= cart_func:get_sign(pos.z-self.old_pos.z) or pos.z == self.old_pos.z then
|
||||
break
|
||||
end
|
||||
self.old_pos.z = self.old_pos.z + cart_func:get_sign(pos.z-self.old_pos.z)*0.1
|
||||
self.old_pos.y = self.old_pos.y + cart_func:get_sign(pos.z-self.old_pos.z)*0.1*old_dir.y
|
||||
self.old_velocity, self.old_pos = self:calc_rail_direction(self.old_pos, self.old_velocity)
|
||||
old_dir = cart_func:velocity_to_dir(self.old_velocity)
|
||||
if not cart_func.v3:equal(cart_func:velocity_to_dir(self.old_velocity), dir) then
|
||||
self.velocity = self.old_velocity
|
||||
pos = self.old_pos
|
||||
self.object:setpos(self.old_pos)
|
||||
break
|
||||
end
|
||||
end
|
||||
local cart_dir = carts:velocity_to_dir(vel)
|
||||
local max_vel = carts.speed_max
|
||||
if not dir then
|
||||
dir, last_switch = carts:get_rail_direction(
|
||||
pos, cart_dir, ctrl, self.old_switch, self.railtype
|
||||
)
|
||||
end
|
||||
|
||||
-- Calculate the new step
|
||||
self.velocity, pos = self:calc_rail_direction(pos, self.velocity)
|
||||
self.object:setpos(pos)
|
||||
dir = cart_func:velocity_to_dir(self.velocity)
|
||||
local new_acc = {x=0, y=0, z=0}
|
||||
local speed_mod = 0
|
||||
if vector.equals(dir, {x=0, y=0, z=0}) then
|
||||
vel = {x=0, y=0, z=0}
|
||||
pos = vector.round(pos)
|
||||
update.pos = true
|
||||
update.vel = true
|
||||
else
|
||||
-- If the direction changed
|
||||
if dir.x ~= 0 and self.old_dir.z ~= 0 then
|
||||
vel.x = dir.x * math.abs(vel.z)
|
||||
vel.z = 0
|
||||
pos.z = math.floor(pos.z + 0.5)
|
||||
update.pos = true
|
||||
end
|
||||
if dir.z ~= 0 and self.old_dir.x ~= 0 then
|
||||
vel.z = dir.z * math.abs(vel.x)
|
||||
vel.x = 0
|
||||
pos.x = math.floor(pos.x + 0.5)
|
||||
update.pos = true
|
||||
end
|
||||
-- Up, down?
|
||||
if dir.y ~= self.old_dir.y then
|
||||
vel.y = dir.y * math.abs(vel.x + vel.z)
|
||||
pos = vector.round(pos)
|
||||
update.pos = true
|
||||
end
|
||||
|
||||
-- Accelerate or decelerate the cart according to the pitch and acceleration of the rail node
|
||||
--[[local a = tonumber(minetest.get_meta(pos):get_string("cart_acceleration"))
|
||||
if not a then
|
||||
a = 0
|
||||
end--]]
|
||||
-- Slow down or speed up in slopes..
|
||||
local acc = dir.y * -1.8
|
||||
|
||||
-- get rail type and set acceleration
|
||||
-- MFF : Some rails have bad acceleration property, reinit them !
|
||||
-- this code would be commented when all rails will be corrected
|
||||
local rail = minetest.get_node(pos)
|
||||
local a = 0
|
||||
if rail.name == "carts:rail_power" then a = 1
|
||||
elseif rail.name == "carts:rail_brake" then a = -1
|
||||
else a = 0
|
||||
if string.match(rail.name, "power")
|
||||
then minetest.get_meta(pos):set_string("cart_acceleration", "1")
|
||||
elseif string.match(rail.name, "brake") then minetest.get_meta(pos):set_string("cart_acceleration", "-1")
|
||||
else minetest.get_meta(pos):set_string("cart_acceleration", "0")
|
||||
end
|
||||
|
||||
-- Change acceleration by rail (power/brake)
|
||||
local speed_mod_string = minetest.get_meta(pos):get_string("cart_acceleration")
|
||||
if speed_mod_string and speed_mod_string ~= ""
|
||||
then speed_mod = tonumber(speed_mod_string)
|
||||
else speed_mod = 0
|
||||
end
|
||||
|
||||
if speed_mod > 0 then speed_mod = 2
|
||||
elseif speed_mod < 0 then speed_mod = -2
|
||||
else speed_mod = 0
|
||||
end
|
||||
--a = a*minetest.setting_get("movement_acceleration_default") -- pour plus tard
|
||||
a = a*0.5
|
||||
--minetest.chat_send_all(a)
|
||||
|
||||
|
||||
-- Check if down arrow is being pressed (handbrake).
|
||||
if self.driver then
|
||||
local ctrl = self.driver:get_player_control()
|
||||
if ctrl and ctrl.down then
|
||||
a=a-0.1 -- Same as uphill.
|
||||
|
||||
end -- If handbrake.
|
||||
end -- If self.driver.
|
||||
|
||||
if self.velocity.y < 0 then
|
||||
self.velocity = {
|
||||
x = self.velocity.x + (a+0.13)*cart_func:get_sign(self.velocity.x),
|
||||
y = self.velocity.y + (a+0.13)*cart_func:get_sign(self.velocity.y),
|
||||
z = self.velocity.z + (a+0.13)*cart_func:get_sign(self.velocity.z),
|
||||
}
|
||||
elseif self.velocity.y > 0 then
|
||||
self.velocity = {
|
||||
x = self.velocity.x + (a-0.1)*cart_func:get_sign(self.velocity.x),
|
||||
y = self.velocity.y + (a-0.1)*cart_func:get_sign(self.velocity.y),
|
||||
z = self.velocity.z + (a-0.1)*cart_func:get_sign(self.velocity.z),
|
||||
}
|
||||
--[[if speed_mod_string == "halt" then --stop rail, not used in MFF
|
||||
vel = {x=0, y=0, z=0}
|
||||
acc = 0
|
||||
pos = vector.round(pos)
|
||||
update.pos = true
|
||||
update.vel = true
|
||||
else--]]if speed_mod and speed_mod ~= 0 then
|
||||
acc = acc + (speed_mod * 10)
|
||||
else
|
||||
self.velocity = {
|
||||
x = self.velocity.x + (a-0.0)*cart_func:get_sign(self.velocity.x), --0.03 (frottements)
|
||||
y = self.velocity.y + (a-0.0)*cart_func:get_sign(self.velocity.y),
|
||||
z = self.velocity.z + (a-0.0)*cart_func:get_sign(self.velocity.z),
|
||||
}
|
||||
|
||||
-- Place the cart exactly on top of the rail
|
||||
if cart_func:is_rail(cart_func.v3:round(pos)) then
|
||||
self.object:setpos({x=pos.x, y=math.floor(pos.y+0.5), z=pos.z})
|
||||
pos = self.object:getpos()
|
||||
--acc = acc - 0.4 --No friction (to be set as an option)
|
||||
-- Handbrake
|
||||
if ctrl and ctrl.down then
|
||||
acc = acc - 1.2
|
||||
end
|
||||
end
|
||||
|
||||
-- Dont switch moving direction
|
||||
-- Only if on flat railway
|
||||
if dir.y == 0 then
|
||||
if cart_func:get_sign(dir.x) ~= cart_func:get_sign(self.velocity.x) then
|
||||
self.velocity.x = 0
|
||||
if self.old_dir.y == 0 and not self.punched then
|
||||
-- Stop the cart swing between two rail parts (handbrake)
|
||||
if vector.equals(vector.multiply(self.old_dir, -1), dir) then
|
||||
vel = {x=0, y=0, z=0}
|
||||
acc = 0
|
||||
if self.old_pos then
|
||||
pos = vector.new(self.old_pos)
|
||||
update.pos = true
|
||||
end
|
||||
if cart_func:get_sign(dir.y) ~= cart_func:get_sign(self.velocity.y) then
|
||||
self.velocity.y = 0
|
||||
end
|
||||
if cart_func:get_sign(dir.z) ~= cart_func:get_sign(self.velocity.z) then
|
||||
self.velocity.z = 0
|
||||
dir = vector.new(self.old_dir)
|
||||
update.vel = true
|
||||
end
|
||||
end
|
||||
|
||||
-- Allow only one moving direction (multiply the other one with 0)
|
||||
dir = cart_func:velocity_to_dir(self.velocity)
|
||||
self.velocity = {
|
||||
x = math.abs(self.velocity.x) * dir.x,
|
||||
y = self.velocity.y,
|
||||
z = math.abs(self.velocity.z) * dir.z,
|
||||
}
|
||||
|
||||
|
||||
-- Move cart exactly on the rail
|
||||
if dir.x ~= 0 and not cart_func:is_int(pos.z) then
|
||||
pos.z = math.floor(0.5+pos.z)
|
||||
self.object:setpos(pos)
|
||||
elseif dir.z ~= 0 and not cart_func:is_int(pos.x) then
|
||||
pos.x = math.floor(0.5+pos.x)
|
||||
self.object:setpos(pos)
|
||||
new_acc = vector.multiply(dir, acc)
|
||||
end
|
||||
|
||||
-- Limit the velocity.
|
||||
if math.abs(self.velocity.x) > self.MAX_V then
|
||||
self.velocity.x = self.MAX_V*cart_func:get_sign(self.velocity.x)
|
||||
end
|
||||
if math.abs(self.velocity.y) > self.MAX_V then
|
||||
self.velocity.y = self.MAX_V*cart_func:get_sign(self.velocity.y)
|
||||
end
|
||||
if math.abs(self.velocity.z) > self.MAX_V then
|
||||
self.velocity.z = self.MAX_V*cart_func:get_sign(self.velocity.z)
|
||||
if not carts.mesecon_disabled and mesecon then
|
||||
carts:signal_detector_rail(vector.round(pos))
|
||||
end
|
||||
|
||||
self.object:setvelocity(self.velocity)
|
||||
--minetest.chat_send_all(self.velocity.x.." "..self.velocity.y.." "..self.velocity.z)
|
||||
|
||||
self.old_pos = self.object:getpos()
|
||||
self.old_velocity = cart_func.v3:copy(self.velocity)
|
||||
|
||||
local oldyaw=self.object:getyaw()
|
||||
if dir.x < 0 then
|
||||
self.object:setyaw(math.pi/2)
|
||||
elseif dir.x > 0 then
|
||||
self.object:setyaw(3*math.pi/2)
|
||||
elseif dir.z < 0 then
|
||||
self.object:setyaw(math.pi)
|
||||
elseif dir.z > 0 then
|
||||
self.object:setyaw(0)
|
||||
-- Limits
|
||||
for _,v in ipairs({"x","y","z"}) do
|
||||
if speed_mod > 0 and math.abs(vel[v]) > max_vel then
|
||||
vel[v] = carts:get_sign(vel[v]) * max_vel
|
||||
new_acc[v] = 0
|
||||
update.vel = true
|
||||
elseif speed_mod < 0 and vel[v] ~= 0 and math.abs(vel[v]) <= carts.brake_speed_min then
|
||||
vel[v] = carts:get_sign(vel[v]) * carts.brake_speed_min
|
||||
new_acc[v] = 0
|
||||
update.vel = true
|
||||
end
|
||||
end
|
||||
|
||||
local newyaw=self.object:getyaw()
|
||||
-- Now if driver and lockyaw, change drivers direction.
|
||||
if self.driver and self.lockyaw then
|
||||
if oldyaw~=newyaw then
|
||||
self.yawtarget=newyaw -- Set new target.
|
||||
-- minetest.log("action", "--Cart yawtarget set "..self.yawtarget)
|
||||
self.object:setacceleration(new_acc)
|
||||
self.old_pos = vector.new(pos)
|
||||
if not vector.equals(dir, {x=0, y=0, z=0}) then
|
||||
self.old_dir = vector.new(dir)
|
||||
end
|
||||
if self.driver:get_look_yaw() == nil then
|
||||
self.old_switch = last_switch
|
||||
|
||||
|
||||
if self.punched then
|
||||
-- Collect dropped items
|
||||
for _,obj_ in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
|
||||
if not obj_:is_player() and
|
||||
obj_:get_luaentity() and
|
||||
not obj_:get_luaentity().physical_state and
|
||||
obj_:get_luaentity().name == "__builtin:item" then
|
||||
|
||||
obj_:set_attach(self.object, "", {x=0, y=0, z=0}, {x=0, y=0, z=0})
|
||||
self.attached_items[#self.attached_items + 1] = obj_
|
||||
end
|
||||
end
|
||||
self.punched = false
|
||||
update.vel = true -- update player animation
|
||||
end
|
||||
|
||||
if not (update.vel or update.pos) then
|
||||
return
|
||||
end
|
||||
local playeryaw=self.driver:get_look_yaw()-1.57
|
||||
if playeryaw<0 then playeryaw=playeryaw+(math.pi*2) end
|
||||
if self.yawtarget and playeryaw ~= self.yawtarget then
|
||||
local diff = self.yawtarget - playeryaw
|
||||
if diff>math.pi then
|
||||
diff=diff-(2*math.pi)
|
||||
elseif diff<(-math.pi) then
|
||||
diff=diff+(2*math.pi)
|
||||
end
|
||||
local yawdir=cart_func:get_sign(diff)
|
||||
local step=self.YAW_STEP
|
||||
if math.abs(diff)<=self.YAW_STEP then
|
||||
step=diff
|
||||
self.yawtarget=nil
|
||||
end
|
||||
local setyaw=playeryaw+(step*yawdir)
|
||||
self.driver:set_look_yaw(setyaw)
|
||||
end -- Move yaw.
|
||||
end -- lockyaw set.
|
||||
|
||||
local yaw = 0
|
||||
if self.old_dir.x < 0 then
|
||||
yaw = 0.5
|
||||
elseif self.old_dir.x > 0 then
|
||||
yaw = 1.5
|
||||
elseif self.old_dir.z < 0 then
|
||||
yaw = 1
|
||||
end
|
||||
self.object:setyaw(yaw * math.pi)
|
||||
|
||||
local anim = {x=0, y=0}
|
||||
if dir.y == -1 then
|
||||
self.object:set_animation({x=1, y=1}, 1, 0)
|
||||
anim = {x=1, y=1}
|
||||
elseif dir.y == 1 then
|
||||
self.object:set_animation({x=2, y=2}, 1, 0)
|
||||
else
|
||||
self.object:set_animation({x=0, y=0}, 1, 0)
|
||||
anim = {x=2, y=2}
|
||||
end
|
||||
self.object:set_animation(anim, 1, 0)
|
||||
|
||||
self.object:setvelocity(vel)
|
||||
if update.pos then
|
||||
self.object:setpos(pos)
|
||||
end
|
||||
update = nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
minetest.register_entity("carts:cart", cart)
|
||||
|
||||
minetest.register_craftitem("carts:cart", {
|
||||
description = "Cart",
|
||||
minetest.register_entity(":carts:cart", carts.cart)
|
||||
minetest.register_craftitem(":carts:cart", {
|
||||
description = "Cart (Sneak+Click to pick up)",
|
||||
inventory_image = minetest.inventorycube("cart_top.png", "cart_side.png", "cart_side.png"),
|
||||
wield_image = "cart_side.png",
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
if not pointed_thing.type == "node" then
|
||||
return
|
||||
end
|
||||
if cart_func:is_rail(pointed_thing.under) then
|
||||
local obj=minetest.add_entity(pointed_thing.under, "carts:cart")
|
||||
minetest.log("action", "carts:cart placed at " .. pos_to_string(vector.round(obj:getpos())) .. ".")
|
||||
-- minetest.chat_send_player(placer:get_player_name(),"Right click to ride, left click to push, sneak + left click to put back in inventory, jump to lock view to cart, sneak to unlock view from cart, move left and right to switch tracks, move backwards to apply handbrake.")
|
||||
if not minetest.setting_getbool("creative_mode") then
|
||||
itemstack:take_item()
|
||||
end
|
||||
return itemstack
|
||||
elseif cart_func:is_rail(pointed_thing.above) then
|
||||
if carts:is_rail(pointed_thing.under) then
|
||||
minetest.add_entity(pointed_thing.under, "carts:cart")
|
||||
elseif carts:is_rail(pointed_thing.above) then
|
||||
minetest.add_entity(pointed_thing.above, "carts:cart")
|
||||
if not minetest.setting_getbool("creative_mode") then
|
||||
else return end
|
||||
|
||||
itemstack:take_item()
|
||||
end
|
||||
return itemstack
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
@ -599,10 +405,3 @@ minetest.register_craft({
|
||||
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
if minetest.setting_getbool("log_mods") then
|
||||
minetest.log("action", "Carbone: [carts] loaded.")
|
||||
end
|
||||
|
||||
|
||||
|
BIN
mods/carts/models/cart.png
Executable file → Normal file
Before Width: | Height: | Size: 210 B After Width: | Height: | Size: 216 B |
0
mods/carts/models/cart.x
Executable file → Normal file
@ -1,7 +1,10 @@
|
||||
minetest.register_node(":default:rail", {
|
||||
description = "Rail",
|
||||
drawtype = "raillike",
|
||||
tiles = {"default_rail.png", "default_rail_curved.png", "default_rail_t_junction.png", "default_rail_crossing.png"},
|
||||
tiles = {
|
||||
"default_rail.png", "default_rail_curved.png",
|
||||
"default_rail_t_junction.png", "default_rail_crossing.png"
|
||||
},
|
||||
inventory_image = "default_rail.png",
|
||||
wield_image = "default_rail.png",
|
||||
paramtype = "light",
|
||||
@ -12,177 +15,25 @@ minetest.register_node(":default:rail", {
|
||||
type = "fixed",
|
||||
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
|
||||
},
|
||||
groups = {bendy = 2, snappy = 1, dig_immediate = 2, rail = 1, connect_to_raillike = 1},
|
||||
--[[mesecons = {
|
||||
effector = {
|
||||
action_off = function(pos, node)
|
||||
minetest.get_meta(pos):set_string("cart_acceleration", "0.5")
|
||||
minetest.get_meta(pos):set_string("cart_touring_velocity", cart:get_staticdata().velocity)
|
||||
end,
|
||||
|
||||
action_on = function(pos, node)
|
||||
minetest.get_meta(pos):set_string("cart_acceleration", "0")
|
||||
end,
|
||||
},
|
||||
},--]]
|
||||
groups = carts:get_rail_groups(),
|
||||
})
|
||||
|
||||
minetest.register_node("carts:rail_copper", {
|
||||
description = "Copper Rail",
|
||||
drawtype = "raillike",
|
||||
tiles = {"carts_rail_copper.png", "carts_rail_copper_curved.png", "carts_rail_copper_t_junction.png", "carts_rail_copper_crossing.png"},
|
||||
inventory_image = "carts_rail_copper.png",
|
||||
wield_image = "carts_rail_copper.png",
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = true,
|
||||
walkable = false,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
|
||||
|
||||
-- Copper rail
|
||||
|
||||
if minetest.get_modpath("moreores") then
|
||||
-- Moreores' copper rail
|
||||
minetest.register_alias("carts:rail_copper", "moreores:copper_rail")
|
||||
else
|
||||
carts:register_rail(":carts:rail_copper", {
|
||||
description = "Copper rail",
|
||||
tiles = {
|
||||
"carts_rail_cp.png", "carts_rail_curved_cp.png",
|
||||
"carts_rail_t_junction_cp.png", "carts_rail_crossing_cp.png"
|
||||
},
|
||||
groups = {bendy = 2, snappy = 1, dig_immediate = 2, rail = 1, connect_to_raillike = 1},
|
||||
groups = carts:get_rail_groups(),
|
||||
})
|
||||
|
||||
minetest.register_node("carts:rail_invisible", {
|
||||
description = "Invisible Rail",
|
||||
stack_max = 10000,
|
||||
range = 12,
|
||||
drawtype = "raillike",
|
||||
tiles = {"invisible.png", "invisible.png", "invisible.png", "invisible.png"},
|
||||
inventory_image = "default_rail.png^default_steel_ingot.png",
|
||||
wield_image = "default_rail.png^default_steel_ingot.png",
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = true,
|
||||
walkable = false,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
|
||||
},
|
||||
drop = "",
|
||||
groups = {unbreakable = 1, rail = 1, connect_to_raillike = 1, not_in_creative_inventory = 1},
|
||||
})
|
||||
|
||||
minetest.register_node("carts:rail_power", {
|
||||
description = "Powered Rail",
|
||||
drawtype = "raillike",
|
||||
tiles = {"carts_rail_pwr.png", "carts_rail_curved_pwr.png", "carts_rail_t_junction_pwr.png", "carts_rail_crossing_pwr.png"},
|
||||
inventory_image = "carts_rail_pwr.png",
|
||||
wield_image = "carts_rail_pwr.png",
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = true,
|
||||
walkable = false,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
|
||||
},
|
||||
groups = {bendy = 2, snappy = 1, dig_immediate = 2, rail = 1, connect_to_raillike = 1},
|
||||
|
||||
after_place_node = function(pos, placer, itemstack)
|
||||
minetest.get_meta(pos):set_string("cart_acceleration", "1")
|
||||
--minetest.get_meta(pos):set_string("cart_touring_velocity", cart:get_staticdata().velocity)
|
||||
end,
|
||||
|
||||
--[[mesecons = {
|
||||
effector = {
|
||||
action_off = function(pos, node)
|
||||
minetest.get_meta(pos):set_string("cart_acceleration", "0.5")
|
||||
end,
|
||||
|
||||
action_on = function(pos, node)
|
||||
minetest.get_meta(pos):set_string("cart_acceleration", "0")
|
||||
end,
|
||||
},
|
||||
},--]]
|
||||
})
|
||||
|
||||
minetest.register_node("carts:rail_power_invisible", {
|
||||
description = "Invisible Powered Rail",
|
||||
stack_max = 10000,
|
||||
range = 12,
|
||||
drawtype = "raillike",
|
||||
tiles = {"invisible.png", "invisible.png", "invisible.png", "invisible.png"},
|
||||
inventory_image = "default_rail.png^default_mese_crystal_fragment.png",
|
||||
wield_image = "default_rail.png^default_mese_crystal_fragment.png",
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = true,
|
||||
walkable = false,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
|
||||
},
|
||||
drop = "",
|
||||
groups = {unbreakable = 1, rail = 1, connect_to_raillike = 1, not_in_creative_inventory = 1},
|
||||
|
||||
after_place_node = function(pos, placer, itemstack)
|
||||
minetest.get_meta(pos):set_string("cart_acceleration", "10")
|
||||
--minetest.get_meta(pos):set_string("cart_touring_velocity", cart:get_staticdata().velocity)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_node("carts:rail_brake", {
|
||||
description = "Brake Rail",
|
||||
drawtype = "raillike",
|
||||
tiles = {"carts_rail_brk.png", "carts_rail_curved_brk.png", "carts_rail_t_junction_brk.png", "carts_rail_crossing_brk.png"},
|
||||
inventory_image = "carts_rail_brk.png",
|
||||
wield_image = "carts_rail_brk.png",
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = true,
|
||||
walkable = false,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
|
||||
},
|
||||
groups = {bendy = 2, snappy = 1, dig_immediate = 2, rail = 1, connect_to_raillike = 1},
|
||||
|
||||
after_place_node = function(pos, placer, itemstack)
|
||||
minetest.get_meta(pos):set_string("cart_acceleration", "-1")
|
||||
--minetest.get_meta(pos):set_string("cart_touring_velocity", cart.TARGET_TOUR_V)
|
||||
end,
|
||||
|
||||
--[[mesecons = {
|
||||
effector = {
|
||||
action_off = function(pos, node)
|
||||
minetest.get_meta(pos):set_string("cart_acceleration", "-0.2")
|
||||
end,
|
||||
|
||||
action_on = function(pos, node)
|
||||
minetest.get_meta(pos):set_string("cart_acceleration", "0")
|
||||
end,
|
||||
},
|
||||
},--]]
|
||||
})
|
||||
|
||||
minetest.register_node("carts:rail_brake_invisible", {
|
||||
description = "Invisible Brake Rail",
|
||||
stack_max = 10000,
|
||||
range = 12,
|
||||
drawtype = "raillike",
|
||||
tiles = {"invisible.png", "invisible.png", "invisible.png", "invisible.png"},
|
||||
inventory_image = "default_rail.png^default_coal_lump.png",
|
||||
wield_image = "default_rail.png^default_coal_lump.png",
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = true,
|
||||
walkable = false,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
|
||||
},
|
||||
drop = "",
|
||||
groups = {bendy = 2, snappy = 1, dig_immediate = 2, rail = 1, connect_to_raillike = 1, not_in_creative_inventory = 1},
|
||||
|
||||
after_place_node = function(pos, placer, itemstack)
|
||||
minetest.get_meta(pos):set_string("cart_acceleration", "-10")
|
||||
--minetest.get_meta(pos):set_string("cart_touring_velocity", cart:get_staticdata().velocity)
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
minetest.register_craft({
|
||||
output = "carts:rail_copper 16",
|
||||
recipe = {
|
||||
@ -191,6 +42,38 @@ minetest.register_craft({
|
||||
{"default:copper_ingot", "group:stick", "default:copper_ingot"},
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
-- Speed up
|
||||
|
||||
-- Rail Power
|
||||
|
||||
carts:register_rail(":carts:rail_power", {
|
||||
description = "Powered rail",
|
||||
tiles = {
|
||||
"carts_rail_pwr.png", "carts_rail_curved_pwr.png",
|
||||
"carts_rail_t_junction_pwr.png", "carts_rail_crossing_pwr.png"
|
||||
},
|
||||
groups = carts:get_rail_groups(),
|
||||
|
||||
after_place_node = function(pos, placer, itemstack)
|
||||
if not mesecon then
|
||||
minetest.get_meta(pos):set_string("cart_acceleration", "1")
|
||||
end
|
||||
end,
|
||||
|
||||
mesecons = {
|
||||
effector = {
|
||||
action_on = function(pos, node)
|
||||
carts:boost_rail(pos, 1)
|
||||
end,
|
||||
|
||||
action_off = function(pos, node)
|
||||
minetest.get_meta(pos):set_string("cart_acceleration", "0")
|
||||
end,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
@ -198,16 +81,80 @@ minetest.register_craft({
|
||||
recipe = {"group:rail", "default:mese_crystal_fragment"},
|
||||
})
|
||||
|
||||
|
||||
-- Rail Brake
|
||||
|
||||
carts:register_rail(":carts:rail_brake", {
|
||||
description = "Brake rail",
|
||||
tiles = {
|
||||
"carts_rail_brk.png", "carts_rail_curved_brk.png",
|
||||
"carts_rail_t_junction_brk.png", "carts_rail_crossing_brk.png"
|
||||
},
|
||||
groups = carts:get_rail_groups(),
|
||||
|
||||
after_place_node = function(pos, placer, itemstack)
|
||||
if not mesecon then
|
||||
minetest.get_meta(pos):set_string("cart_acceleration", "-1")
|
||||
end
|
||||
end,
|
||||
|
||||
mesecons = {
|
||||
effector = {
|
||||
action_on = function(pos, node)
|
||||
minetest.get_meta(pos):set_string("cart_acceleration", "-1")
|
||||
end,
|
||||
|
||||
action_off = function(pos, node)
|
||||
minetest.get_meta(pos):set_string("cart_acceleration", "0")
|
||||
end,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "carts:rail_brake",
|
||||
recipe = {"group:rail", "default:coal_lump"},
|
||||
})
|
||||
|
||||
-- Start stop rail (temporary removed for mff)
|
||||
|
||||
--[[carts:register_rail("carts:startstoprail", {
|
||||
description = "Start-stop rail",
|
||||
tiles = {
|
||||
"carts_rail_ss.png", "carts_rail_curved_ss.png",
|
||||
"carts_rail_t_junction_ss.png", "carts_rail_crossing_ss.png"
|
||||
},
|
||||
groups = carts:get_rail_groups(),
|
||||
|
||||
after_place_node = function(pos, placer, itemstack)
|
||||
if not mesecon then
|
||||
minetest.get_meta(pos):set_string("cart_acceleration", "halt")
|
||||
end
|
||||
end,
|
||||
|
||||
mesecons = {
|
||||
effector = {
|
||||
action_on = function(pos, node)
|
||||
carts:boost_rail(pos, 0.5)
|
||||
end,
|
||||
|
||||
action_off = function(pos, node)
|
||||
minetest.get_meta(pos):set_string("cart_acceleration", "halt")
|
||||
end,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "carts:startstoprail 2",
|
||||
recipe = {"carts:powerrail", "carts:brakerail"},
|
||||
})--]]
|
||||
|
||||
--Alias
|
||||
|
||||
minetest.register_alias("carts:powerrail", "carts:rail_power")
|
||||
minetest.register_alias("carts:power_rail", "carts:rail_power")
|
||||
minetest.register_alias("carts:brakerail", "carts:rail_brake")
|
||||
minetest.register_alias("carts:brake_rail", "carts:rail_power")
|
||||
|
||||
minetest.register_alias("carts:brake_rail", "carts:rail_brake")
|
||||
|
0
mods/carts/textures/cart_bottom.png
Executable file → Normal file
Before Width: | Height: | Size: 114 B After Width: | Height: | Size: 114 B |
BIN
mods/carts/textures/cart_side.png
Executable file → Normal file
Before Width: | Height: | Size: 144 B After Width: | Height: | Size: 147 B |
0
mods/carts/textures/cart_top.png
Executable file → Normal file
Before Width: | Height: | Size: 131 B After Width: | Height: | Size: 131 B |
BIN
mods/carts/textures/carts_rail_brk.png
Executable file → Normal file
Before Width: | Height: | Size: 438 B After Width: | Height: | Size: 577 B |
Before Width: | Height: | Size: 437 B |
Before Width: | Height: | Size: 388 B |
Before Width: | Height: | Size: 374 B |
Before Width: | Height: | Size: 374 B |
BIN
mods/carts/textures/carts_rail_cp.png
Normal file
After Width: | Height: | Size: 522 B |
BIN
mods/carts/textures/carts_rail_crossing_brk.png
Executable file → Normal file
Before Width: | Height: | Size: 387 B After Width: | Height: | Size: 549 B |
BIN
mods/carts/textures/carts_rail_crossing_cp.png
Normal file
After Width: | Height: | Size: 495 B |
BIN
mods/carts/textures/carts_rail_crossing_dtc.png
Normal file
After Width: | Height: | Size: 621 B |
BIN
mods/carts/textures/carts_rail_crossing_dtc_on.png
Normal file
After Width: | Height: | Size: 654 B |
BIN
mods/carts/textures/carts_rail_crossing_pwr.png
Executable file → Normal file
Before Width: | Height: | Size: 398 B After Width: | Height: | Size: 458 B |
BIN
mods/carts/textures/carts_rail_crossing_ss.png
Normal file
After Width: | Height: | Size: 463 B |
Before Width: | Height: | Size: 416 B |
BIN
mods/carts/textures/carts_rail_curved_brk.png
Executable file → Normal file
Before Width: | Height: | Size: 378 B After Width: | Height: | Size: 537 B |
BIN
mods/carts/textures/carts_rail_curved_cp.png
Normal file
After Width: | Height: | Size: 488 B |
BIN
mods/carts/textures/carts_rail_curved_dtc.png
Normal file
After Width: | Height: | Size: 578 B |
BIN
mods/carts/textures/carts_rail_curved_dtc_on.png
Normal file
After Width: | Height: | Size: 575 B |
BIN
mods/carts/textures/carts_rail_curved_pwr.png
Executable file → Normal file
Before Width: | Height: | Size: 387 B After Width: | Height: | Size: 443 B |
BIN
mods/carts/textures/carts_rail_curved_ss.png
Normal file
After Width: | Height: | Size: 450 B |
Before Width: | Height: | Size: 391 B |
BIN
mods/carts/textures/carts_rail_dtc.png
Normal file
After Width: | Height: | Size: 542 B |
BIN
mods/carts/textures/carts_rail_dtc_on.png
Normal file
After Width: | Height: | Size: 559 B |
BIN
mods/carts/textures/carts_rail_pwr.png
Executable file → Normal file
Before Width: | Height: | Size: 442 B After Width: | Height: | Size: 498 B |
BIN
mods/carts/textures/carts_rail_ss.png
Normal file
After Width: | Height: | Size: 514 B |
BIN
mods/carts/textures/carts_rail_t_junction_brk.png
Executable file → Normal file
Before Width: | Height: | Size: 375 B After Width: | Height: | Size: 538 B |
BIN
mods/carts/textures/carts_rail_t_junction_cp.png
Normal file
After Width: | Height: | Size: 496 B |
BIN
mods/carts/textures/carts_rail_t_junction_dtc.png
Normal file
After Width: | Height: | Size: 607 B |
BIN
mods/carts/textures/carts_rail_t_junction_dtc_on.png
Normal file
After Width: | Height: | Size: 621 B |
BIN
mods/carts/textures/carts_rail_t_junction_pwr.png
Executable file → Normal file
Before Width: | Height: | Size: 385 B After Width: | Height: | Size: 539 B |
BIN
mods/carts/textures/carts_rail_t_junction_ss.png
Normal file
After Width: | Height: | Size: 439 B |
Before Width: | Height: | Size: 398 B |
Before Width: | Height: | Size: 453 B |
BIN
mods/carts/textures/default_rail_t_junction.png
Normal file
After Width: | Height: | Size: 476 B |
@ -1,104 +0,0 @@
|
||||
--[[local t = tonumber(minetest.get_meta(pos):get_string("cart_touring_velocity"))
|
||||
if not t then t=0 end
|
||||
t = 0
|
||||
if t>0 then
|
||||
local vx=math.abs(self.velocity.x)
|
||||
local vy=math.abs(self.velocity.y)
|
||||
local vz=math.abs(self.velocity.z)
|
||||
-- make v the largest of the 3 velocities
|
||||
local v=vx
|
||||
if vy>v then v=vy end
|
||||
if vz>v then v=vz end
|
||||
--
|
||||
local diff=0
|
||||
local acelordecl=0
|
||||
if v>t then
|
||||
diff=v-t
|
||||
acelordecl=-1
|
||||
elseif v<t then
|
||||
diff=t-v
|
||||
acelordecl=1
|
||||
end --v>t
|
||||
--minetest.log("action", " on_step t1 v="..v.." t="..t.." diff="..diff.." a="..a.." acelordecl="..acelordecl)
|
||||
--adjust for grav
|
||||
if self.velocity.y<0 then --going downhill so grav will acel by extra 0.13
|
||||
--if we are decel then add an extra 0.13 to how much we need to decel
|
||||
--if we are accel then subtract an extra 0.13 from how much we need to acel
|
||||
diff=diff-(0.13*acelordecl)
|
||||
elseif self.velocity.y>0 then --going uphill grav will decl by extra 0.10
|
||||
--if we are decel then subtract 0.1 from how much we need to decel
|
||||
--if we are acel then add 0.1 to how much we need to acel
|
||||
diff=diff+(0.1*acelordecl)
|
||||
end -- self.velocity.y<0
|
||||
--so now diff is the difference between cart velocity (after this turns grav)
|
||||
--and our target touring velocity
|
||||
--minetest.log("action", "*!* on_step t2 grav v="..v.." diff="..diff.." a="..a)
|
||||
if diff<a then --we dont want to over acel or decel
|
||||
a=diff
|
||||
elseif diff>a*4 then
|
||||
a=a*2 --if big difference, play catchup fast!
|
||||
elseif diff>a*3 then
|
||||
a=a*1.5 --if big difference, play catchup fast!
|
||||
end --diff<a
|
||||
a=a*acelordecl
|
||||
end -- if t>0--]]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
--[[minetest.register_node("carts:rail_tour", {
|
||||
description = "Touring Rail",
|
||||
drawtype = "raillike",
|
||||
tiles = {"carts_rail_tour.png", "carts_rail_curved_tour.png", "carts_rail_t_junction_tour.png", "carts_rail_crossing_tour.png"},
|
||||
inventory_image = "carts_rail_tour.png",
|
||||
wield_image = "carts_rail_tour.png",
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = true,
|
||||
walkable = false,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
|
||||
},
|
||||
groups = {bendy = 2, snappy = 1, dig_immediate = 2, rail = 1, connect_to_raillike = 1},
|
||||
|
||||
after_place_node = function(pos, placer, itemstack)
|
||||
if not mesecon then
|
||||
minetest.get_meta(pos):set_string("cart_acceleration", "0.5")
|
||||
minetest.get_meta(pos):set_string("cart_touring_velocity", cart.TARGET_TOUR_V)
|
||||
end
|
||||
end,
|
||||
|
||||
mesecons = {
|
||||
effector = {
|
||||
action_on = function(pos, node)
|
||||
minetest.get_meta(pos):set_string("cart_acceleration", "0.5")
|
||||
end,
|
||||
|
||||
action_off = function(pos, node)
|
||||
minetest.get_meta(pos):set_string("cart_acceleration", "0")
|
||||
end,
|
||||
},
|
||||
},
|
||||
})
|
||||
--]]
|
||||
--[[minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "carts:rail_tour",
|
||||
recipe = {"group:rail", "default:clay_lump"},
|
||||
})--]]
|
||||
--minetest.register_alias("carts:tourrail", "carts:rail_tour")
|
||||
|
||||
|
||||
|
||||
|
||||
-- temporary
|
||||
--[[minetest.register_abm({
|
||||
nodes = {"group:rail"},
|
||||
func = function(pos)
|
||||
local name = minetest.get_node(pos).name
|
||||
minetest.remove_node(pos)
|
||||
minetest.place_node(pos,{name = name})
|
||||
end
|
||||
})--]]
|