---[[
-
-Basic idealogy
-
-keep it simple stupid
-
-make cart make noise
-
-make player able to push cart
-
-make carts push each other away --repel axis
-
-make chest and furnace cart
-
-
-minetest.dir_to_facedir(dir, is6d) - to get player direction converted and to convert the minecart direction
-
-]]--
local path = minetest.get_modpath("minecart")
dofile(path.."/rail.lua")
-
-local function is_rail(x,y,z)
- return(minetest.get_node_group(minetest.get_node(vector.new(x,y,z)).name,"rail")>0)
+--get if rail
+local function rail(pos)
+ return(minetest.get_node_group(minetest.get_node(pos).name,"rail")>0)
end
-local minecart = {
- initial_properties = {
- physical = false, -- otherwise going uphill breaks
- collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},--{-0.5, -0.4, -0.5, 0.5, 0.25, 0.5},
- visual = "mesh",
- mesh = "minecart.obj",
- visual_size = {x=1, y=1},
- textures = {"minecart.png"},
- automatic_face_movement_dir = 90.0,
- automatic_face_movement_max_rotation_per_sec = 600,
- },
-
- rider = nil,
- punched = false,
- speed = 0,
-
-}
+--check if on rail
+local function on_rail(self,pos)
+ if not rail(pos) and not self.slope then
+ self.axis = nil
+ return(false)
+ else
+ return(true)
+ end
+end
-function minecart:on_rightclick(clicker)
- if not clicker or not clicker:is_player() then
- return
+--set physical state
+local function physical(self,pos)
+ if on_rail(self,pos) then
+ self.object:set_properties({physical = false})
+ self.object:setacceleration(vector.new(0,0,0))
+ elseif not self.slope then
+ self.object:set_properties({physical = true})
+ self.object:setacceleration(vector.new(0,-9.81,0))
end
- local player_name = clicker:get_player_name()
-
- if self.rider and player_name == self.rider then
- self.rider = nil
- --carts:manage_attachment(clicker, nil)
- elseif not self.rider then
- self.rider = player_name
- clicker:set_attach(self.object, "", {x=0, y=-4.5, z=0}, {x=0, y=0, z=0})
- --player:set_eye_offset({x=0, y=-4, z=0},{x=0, y=-4, z=0})
- --carts:manage_attachment(clicker, self.object)
+end
- -- player_api does not update the animation
- -- when the player is attached, reset to default animation
-
- --player_api.set_animation(clicker, "stand")
+--get if node in minecarts direction
+local function node_ahead(self,pos)
+ local vel = self.object:getvelocity()
+ local dir = vector.normalize(vel)
+ return(rail(vector.add(pos,dir)))
+end
+
+--get current axis (prefers x)
+local function axis(pos)
+ if rail(pos) then
+ if rail(vector.new(pos.x-1,pos.y,pos.z)) or rail(vector.new(pos.x+1,pos.y,pos.z)) then return("x") end
+ if rail(vector.new(pos.x,pos.y,pos.z-1)) or rail(vector.new(pos.x,pos.y,pos.z+1)) then return("z") end
end
end
-function minecart:on_activate(staticdata, dtime_s)
- self.object:set_armor_groups({immortal=1})
- if string.sub(staticdata, 1, string.len("return")) ~= "return" then
- return
+--snap object to rail
+local function snap_rail(self,pos)
+ local slopy = self.slope
+ if not slopy then print("the slope is nil") else
+ print("the slope is ".. slopy)
end
- local data = minetest.deserialize(staticdata)
- if type(data) ~= "table" then
+ local railpos = vector.floor(vector.add(pos, 0.5))
+ local vel = self.object:getvelocity()
+ if self.axis == "x" and pos.x ~= railpos.x then
+ self.object:moveto(vector.new(pos.x,railpos.y,railpos.z))
+ self.object:setvelocity(vector.new(vel.x,0,0))
+ print("snapped to x")
return
end
- self.railtype = data.railtype
- if data.old_dir then
- self.old_dir = data.old_dir
+ if self.axis == "z" and pos.z ~= railpos.z then
+ self.object:moveto(vector.new(railpos.x,railpos.y,pos.z))
+ self.object:setvelocity(vector.new(0,0,vel.z))
+ print("snapped to z")
+ return
end
end
-function minecart:get_staticdata()
- return minetest.serialize({
- })
-end
-function minecart:on_punch(puncher, time_from_last_punch, tool_capabilities, dir, damage)
- local obj = minetest.add_item(self.object:getpos(), "minecart:minecart")
- obj:get_luaentity().collection_timer = 2
- self.object:remove()
+--check if entering new position
+local function newnode(self,pos)
+ local pos = vector.floor(vector.add(pos,0.5))
+
+ pos.y = 0
+
+ local equals = false
+
+
+ if self.oldpos then
+ equals = vector.equals(pos,self.oldpos)
+ end
+
+ self.oldpos = pos
+ return(not equals)
end
+--check if past center - used for turning
+local function pastcenter(self,pos)
+
+ local center = vector.floor(vector.add(pos,0.5))
+ center.y = 0
+ local pos2d = vector.new(pos.x,0,pos.z)
+
+ local vel = self.object:getvelocity()
+ local dir = vector.normalize(vel)
+ dir.y = 0
+ local checker = vector.round(vector.normalize(vector.subtract(pos2d,center)))
+ checker.y = 0
+ local past = vector.equals(checker, dir)
+ return(past)
+end
+--check if node ahead
+local function node_forward(self,pos)
+ local vel = self.object:getvelocity()
+ local dir = vector.normalize(vel)
+ return(rail(vector.add(pos,dir)))
+end
-
-
-
---repel from players on track "push"
-function minecart:push(self)
- local pos = self.object:getpos()
- for _,object in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
- if object:is_player() and object:get_player_name() ~= self.rider then
- local player_pos = object:getpos()
- pos.y = 0
- player_pos.y = 0
-
- local vel = vector.subtract(pos, player_pos)
- vel = vector.normalize(vel)
- local distance = vector.distance(pos,player_pos)
-
- distance = (1-distance)*10
-
- vel = vector.multiply(vel,distance)
-
- --only push if it's faster than current speed
- if distance > self.speed then
- self.object:setvelocity(vel)
- self.speed = distance
- end
- end
+--check if node above or below
+local function check_hill(self,pos)
+ local vel = self.object:getvelocity()
+ local dirup = vector.normalize(vel)
+
+ dirup.y = dirup.y + 1
+
+ print(dump(dirup))
+
+ minetest.add_particlespawner({
+ amount = 5,
+ time = 0,
+ minpos = vector.add(pos,dirup),
+ maxpos = vector.add(pos,dirup),
+ minvel = vector.new(0,0,0),
+ maxvel = vector.new(0,0,0),
+ minacc = {x=0, y=0, z=0},
+ maxacc = {x=0, y=0, z=0},
+ minexptime = 5,
+ maxexptime = 5,
+ minsize = 1,
+ maxsize = 1,
+ attached = player,
+ collisiondetection = true,
+ vertical = false,
+ texture = "treecapitator.png"
+ })
+
+ local dirdown = vector.new(0,-0.5,0)
+
+ if rail(vector.add(pos,dirup)) then
+ self.slope = "up"
+ return("up")
+ elseif rail(vector.add(pos,dirdown)) then
+ self.slope = "down"
+ return("down")
+ else
+ self.slope = nil
+ return(nil)
end
end
-function minecart:ride_rail(self)
- local pos = vector.floor(vector.add(self.object:getpos(),0.5))
- local speed = self.speed
- if self.speed > 10 then
- self.speed = 10
- end
+local function gravity(self,pos)
- local vel = self.object:getvelocity()
- local x = math.abs(vel.x)
- local z = math.abs(vel.z)
- local xdir
- local zdir
- local dir = {x=0,y=0,z=0}
-
- --check direction
- --x axis
- if x > z then
- if vel.x>0 then xdir=1 elseif vel.x<0 then xdir=-1 end
-
- --print(minetest.get_node(vector.new(pos.x,pos.y,pos.z)).name)
-
- --go up
- if is_rail(pos.x+xdir,pos.y+1,pos.z) or (not is_rail(pos.x,pos.y,pos.z) and is_rail(pos.x+xdir,pos.y,pos.z)) then
- --print("up")
- dir.y = speed
- dir.x = xdir*speed
+ if self.slope == up then
+ local vel = vector.multiply(self.object:getvelocity(), 0.95)
+ self.object:set_velocity(vel)
+ end
+ if self.slope == up then
+ local vel = vector.multiply(self.object:getvelocity(), 1.05)
+ self.object:set_velocity(vel)
+ end
+
+end
- --go down
- elseif (is_rail(pos.x,pos.y-1,pos.z) or vel.y < 0) and not is_rail(pos.x+xdir,pos.y,pos.z) then
- --print("down")
- dir.y = -speed
- dir.x = xdir*speed
+--make the minecart go up and down hills
+local function navigate_hill(self)
+ if self.slope then
+ local vel = self.object:getvelocity()
+ if self.slope == "up" then
- --go flat
- elseif is_rail(pos.x,pos.y,pos.z) then --currently on rail
- --print("flat")
- --print("forward inside")
- --correct y position
- if dir.y == 0 and self.object:getpos().y ~= pos.y then
- --print("correcting y")
- local posser = self.object:getpos()
- self.object:moveto(vector.new(posser.x,pos.y,posser.z))
+ local yvel = 0
+ if self.axis == "x" then
+ yvel = math.abs(vel.x)*1.1
end
- dir.x = xdir*speed
- end
- --z axis
- elseif z > x then
- if vel.z>0 then zdir=1 elseif vel.z<0 then zdir=-1 end
-
- --print(minetest.get_node(vector.new(pos.x,pos.y,pos.z)).name)
-
- --go up
- if is_rail(pos.x,pos.y+1,pos.z+zdir) or (not is_rail(pos.x,pos.y,pos.z) and is_rail(pos.x,pos.y,pos.z+zdir)) then
- --print("up")
- dir.y = speed
- dir.z = zdir*speed
-
- --go down
- elseif (is_rail(pos.x,pos.y-1,pos.z) or vel.y < 0) and not is_rail(pos.x,pos.y,pos.z+zdir) then
- --print("down")
- dir.y = -speed
- dir.z = zdir*speed
-
+ if self.axis == "z" then
+ yvel = math.abs(vel.z)*1.1
+ end
+ self.object:setvelocity(vector.new(vel.x,yvel,vel.z))
+ elseif self.slope == "down" then
- --go flat
- elseif is_rail(pos.x,pos.y,pos.z) then --currently on rail
- --print("flat")
- --print("forward inside")
- --correct y position
- if dir.y == 0 and self.object:getpos().y ~= pos.y then
- --print("correcting y")
- local posser = self.object:getpos()
- self.object:moveto(vector.new(posser.x,pos.y,posser.z))
+ local yvel = 0
+ if self.axis == "x" then
+ yvel = math.abs(vel.x)*-1
end
- dir.z = zdir*speed
+ if self.axis == "z" then
+ yvel = math.abs(vel.z)*-1
+ end
+
+ self.object:setvelocity(vector.new(vel.x,yvel,vel.z))
end
end
- --turn
- local turnx = 0
- local turnz = 0
-
- if vel.x>0 then turnx=1 elseif vel.x<0 then turnx=-1 end
- if vel.z>0 then turnz=1 elseif vel.z<0 then turnz=-1 end
-
+end
- if turnx and turnz and dir.y == 0 and not vector.equals(dir, vector.new(0,0,0)) and not is_rail(pos.x+turnx,pos.y-1,pos.z+turnz) and not is_rail(pos.x+turnx,pos.y,pos.z+turnz) and not is_rail(pos.x+turnx,pos.y+1,pos.z+turnz) then
- if x > z then
- for y = -1,1 do
- if is_rail(pos.x,pos.y+y,pos.z+1) then
- dir.z = speed
- dir.x = 0
- --recenter on the rail
- self.object:moveto(pos)
- elseif is_rail(pos.x,pos.y+y,pos.z-1) then
- dir.z = -speed
- dir.x = 0
- --recenter on the rail
- self.object:moveto(pos)
- end
- end
- elseif z > x then
- for y = -1,1 do
- if is_rail(pos.x+1,pos.y+y,pos.z) then
- dir.x = speed
- dir.z = 0
- --recenter on the rail
- self.object:moveto(pos)
- elseif is_rail(pos.x-1,pos.y+y,pos.z) then
- dir.x = -speed
- dir.z = 0
- --recenter on the rail
- self.object:moveto(pos)
- end
- end
+--swap axis and speed 90 degrees
+local function turn_check(self,pos)
+ local axis = self.axis
+ local vel = self.object:getvelocity()
+ vel.x = math.abs(vel.x)
+ vel.y = math.abs(vel.y)
+ vel.z = math.abs(vel.z)
+
+ if axis == "x" then
+ if rail(vector.new(pos.x,pos.y,pos.z-1)) then
+ print("-x")
+ self.object:setvelocity(vector.new(0,0,vel.x*-1))
+ self.axis = "z"
+ snap_rail(self,pos)
+ self.turn_timer = 0
+ return
+ elseif rail(vector.new(pos.x,pos.y,pos.z+1)) then
+ print("+x")
+ self.object:setvelocity(vector.new(0,0,vel.x))
+ self.axis = "z"
+ snap_rail(self,pos)
+ self.turn_timer = 0
+ return
end
-
end
- --apply
- --if not vector.equals(dir,vector.new(0,0,0)) then
- self.object:setvelocity(dir)
- --end
- self.oldpos=self.object:getpos()
-
- --make the cart move up and down on hills
- self.object:set_properties({mesh="minecart.obj"})
- if vel.y <0 then
- self.object:set_properties({mesh="minecart_down.obj"})
- elseif vel.y > 0 then
- self.object:set_properties({mesh="minecart_up.obj"})
+ if axis == "z" then
+ if rail(vector.new(pos.x-1,pos.y,pos.z)) then
+ print("-z")
+ self.object:setvelocity(vector.new(vel.z*-1,0,0))
+ self.axis = "x"
+ snap_rail(self,pos)
+ self.turn_timer = 0
+ return
+ elseif rail(vector.new(pos.x+1,pos.y,pos.z)) then
+ print("+z")
+ self.object:setvelocity(vector.new(vel.z,0,0))
+ self.axis = "x"
+ snap_rail(self,pos)
+ self.turn_timer = 0
+ return
+ end
end
+end
+--try to turn
+local function turn(self,pos)
+ if pastcenter(self,pos) then
+ if not node_forward(self,pos) and self.axis then
+ turn_check(self,pos)
+ end
+ end
+end
+
+--the main mechanics of the minecart
+local function minecart_brain(self,dtime)
+ if self.turn_timer < 5 then
+ self.turn_timer = self.turn_timer + dtime
+ end
+ local pos = self.object:getpos()
+ pos.y = pos.y - 0.5
+
- --slow it down
- if self.speed > 0 then
- self.speed = self.speed - 0.01
+ if not self.axis then
+ self.axis = axis(pos)
end
- if self.speed < 0 then
- self.speed = 0
+
+ if newnode(self,pos) then
+ snap_rail(self,pos)
end
+ --check_hill(self,pos)
+ --navigate_hill(self)
+
+
+ turn(self,pos)
+
+ on_rail(self,pos)
+ physical(self,pos)
+ --print(self.axis)
+ --check if falling and then fall at the same speed to go down
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-function minecart:on_step(dtime)
- minecart:push(self)
- minecart:ride_rail(self)
-end
+minetest.register_entity("minecart:minecart", {
+ initial_properties = {
+ physical = true, -- otherwise going uphill breaks
+ collisionbox = {-0.4, -0.5, -0.4, 0.4, 0.45, 0.4},--{-0.5, -0.4, -0.5, 0.5, 0.25, 0.5},
+ visual = "mesh",
+ mesh = "minecart.obj",
+ visual_size = {x=1, y=1},
+ textures = {"minecart.png"},
+ automatic_face_movement_dir = 90.0,
+ automatic_face_movement_max_rotation_per_sec = 600,
+ },
-minetest.register_entity("minecart:minecart", minecart)
+ rider = nil,
+ punched = false,
+ speed = 0,
+ turn_timer = 0,
+ incline = nil,
+ turn_timer = 5,
+ on_rightclick = function(self,clicker)
+ if not clicker or not clicker:is_player() then
+ return
+ end
+ local player_name = clicker:get_player_name()
+
+ if self.rider and player_name == self.rider then
+ self.rider = nil
+ --carts:manage_attachment(clicker, nil)
+ elseif not self.rider then
+ self.rider = player_name
+ clicker:set_attach(self.object, "", {x=0, y=-4.5, z=0}, {x=0, y=0, z=0})
+ --player:set_eye_offset({x=0, y=-4, z=0},{x=0, y=-4, z=0})
+ --carts:manage_attachment(clicker, self.object)
+
+ -- player_api does not update the animation
+ -- when the player is attached, reset to default animation
+
+ --player_api.set_animation(clicker, "stand")
+ end
+ end,
+
+ on_activate = function(self,staticdata, dtime_s)
+ self.object:set_armor_groups({immortal=1})
+ if string.sub(staticdata, 1, string.len("return")) ~= "return" then
+ return
+ end
+ local data = minetest.deserialize(staticdata)
+ if type(data) ~= "table" then
+ return
+ end
+ self.railtype = data.railtype
+ if data.old_dir then
+ self.old_dir = data.old_dir
+ end
+ end,
+
+ get_staticdata = function(self)
+ return minetest.serialize({
+ })
+ end,
+
+ on_punch = function(self,puncher, time_from_last_punch, tool_capabilities, dir, damage)
+ local obj = minetest.add_item(self.object:getpos(), "minecart:minecart")
+ obj:get_luaentity().collection_timer = 2
+ self.object:remove()
+ end,
+
+ --repel from players on track "push"
+ push = function(self)
+ if self.turn_timer > 0.3 then
+ local pos = self.object:getpos()
+ local radius = 1.2
+ for _,object in ipairs(minetest.get_objects_inside_radius(pos, radius)) do
+ if object:is_player() and object:get_player_name() ~= self.rider then
+ local player_pos = object:getpos()
+ pos.y = 0
+ player_pos.y = 0
+
+ local currentvel = self.object:getvelocity()
+ local vel = vector.subtract(pos, player_pos)
+ vel = vector.normalize(vel)
+ local distance = vector.distance(pos,player_pos)
+ distance = (radius-distance)*20
+ vel = vector.multiply(vel,distance)
+ local acceleration = vector.new(vel.x-currentvel.x,0,vel.z-currentvel.z)
+
+
+ if self.axis == "x" then
+ self.object:add_velocity(vector.new(acceleration.x,0,0))
+ elseif self.axis == "z" then
+ self.object:add_velocity(vector.new(0,0,acceleration.z))
+ else
+ self.object:add_velocity(acceleration)
+ end
+
+ acceleration = vector.multiply(acceleration, -0,5)
+ object:add_player_velocity(acceleration)
+ end
+ end
+ end
+ end,
+
+ --slows the minecart down
+ slowdown = function(self)
+ if not self.moving == true then
+ local vel = self.object:getvelocity()
+ local deceleration = vector.multiply(vel, -0.01)
+ self.object:add_velocity(deceleration)
+ end
+ end,
+
+ --mechanics to follow rails
+ ride_rail = function(self,dtime)
+ minecart_brain(self,dtime)
+ end,
+
+ on_step = function(self,dtime)
+ self.push(self)
+ self.slowdown(self)
+ self.ride_rail(self,dtime)
+ end,
+
+})
minetest.register_craftitem("minecart:minecart", {
description = "Minecart",
- local oldvel = self.object:getvelocity()
- local olddir = vector.normalize(oldvel)
- local x = math.abs(oldvel.x)
- local z = math.abs(oldvel.z)
- local pos = self.object:getpos()
- pos.y = pos.y - 0.5
- local pos2 = self.object:getpos()
- local pos3 = self.object:getpos()
- pos3.y = pos3.y + 0.5
-
- local xer
- local zer
- local dir = {x=0,y=0,z=0}
-
- --check direction
- --x axis
- if x > z then
- if olddir.x>0 then xer=1 elseif olddir.x<0 then xer=-1 end
- --check up
- if minetest.get_node_group(minetest.get_node(vector.new(pos.x+xer,pos.y+1,pos.z)).name,"rail")>0 then
- dir.x = xer
- dir.y = 1
- --check down
- elseif minetest.get_node_group(minetest.get_node(vector.new(pos.x+xer,pos.y-1,pos.z)).name,"rail")>0 then
- dir.x = xer
- dir.y = -1
- --check flat
- elseif minetest.get_node_group(minetest.get_node(vector.new(pos.x+xer,pos.y,pos.z)).name,"rail")>0 then
- dir.x = xer
+ --mechanics to follow rails
+ ride_rail = function(self)
+ local pos = vector.floor(vector.add(self.object:getpos(),0.5))
+ local speed = self.speed
+ if self.speed > 10 then
+ self.speed = 10
end
- --z axis
- elseif z > x then
- if olddir.z>0 then zer=1 elseif olddir.z<0 then zer=-1 end
- --check up
- if minetest.get_node_group(minetest.get_node(vector.new(pos.x,pos.y+1,pos.z+zer)).name,"rail")>0 then
- dir.z = zer
- dir.y = 1
- --check down
- elseif minetest.get_node_group(minetest.get_node(vector.new(pos.x,pos.y-1,pos.z+zer)).name,"rail")>0 then
- dir.z = zer
- dir.y = -1
- --check flat
- elseif minetest.get_node_group(minetest.get_node(vector.new(pos.x,pos.y,pos.z+zer)).name,"rail")>0 then
- dir.z = zer
- end
- end
-
- --turn
- if vector.equals(dir,vector.new(0,0,0)) then
+
+ local vel = self.object:getvelocity()
+ local x = math.abs(vel.x)
+ local z = math.abs(vel.z)
+ local xdir
+ local zdir
+ local dir = {x=0,y=0,z=0}
+
+ --check direction
+ --x axis
if x > z then
- if minetest.get_node_group(minetest.get_node(vector.new(pos.x,pos.y,pos.z+1)).name,"rail")>0 then
- dir.z = 1
- --recenter on the rail
- self.object:moveto(vector.new(math.floor(pos2.x+0.5),pos2.y,pos2.z))
- elseif minetest.get_node_group(minetest.get_node(vector.new(pos.x,pos.y,pos.z-1)).name,"rail")>0 then
- dir.z = -1
- --recenter on the rail
- self.object:moveto(vector.new(math.floor(pos2.x+0.5),pos2.y,pos2.z))
+ if vel.x>0 then xdir=1 elseif vel.x<0 then xdir=-1 end
+
+ --print(minetest.get_node(vector.new(pos.x,pos.y,pos.z)).name)
+
+ --go up
+ if is_rail(pos.x+xdir,pos.y+1,pos.z) or (not is_rail(pos.x,pos.y,pos.z) and is_rail(pos.x+xdir,pos.y,pos.z)) then
+ --print("up")
+ dir.y = speed
+ dir.x = xdir*speed
+
+ --go down
+ elseif (is_rail(pos.x,pos.y-1,pos.z) or vel.y < 0) and not is_rail(pos.x+xdir,pos.y,pos.z) then
+ --print("down")
+ dir.y = -speed
+ dir.x = xdir*speed
+
+ --go flat
+ elseif is_rail(pos.x,pos.y,pos.z) then --currently on rail
+ --print("flat")
+ --print("forward inside")
+ --correct y position
+ if dir.y == 0 and self.object:getpos().y ~= pos.y then
+ --print("correcting y")
+ local posser = self.object:getpos()
+ self.object:moveto(vector.new(posser.x,pos.y,posser.z))
+ end
+ dir.x = xdir*speed
end
+ --z axis
elseif z > x then
- print("zzzz")
- if minetest.get_node_group(minetest.get_node(vector.new(pos.x+1,pos.y,pos.z)).name,"rail")>0 then
- dir.x = 1
- --recenter on the rail
- self.object:moveto(vector.new(pos2.x,pos2.y,math.floor(pos2.z+0.5)))
- elseif minetest.get_node_group(minetest.get_node(vector.new(pos.x-1,pos.y,pos.z)).name,"rail")>0 then
- dir.x = -1
- --recenter on the rail
- self.object:moveto(vector.new(pos2.x,pos2.y,math.floor(pos2.z+0.5)))
+ if vel.z>0 then zdir=1 elseif vel.z<0 then zdir=-1 end
+
+ --print(minetest.get_node(vector.new(pos.x,pos.y,pos.z)).name)
+
+ --go up
+ if is_rail(pos.x,pos.y+1,pos.z+zdir) or (not is_rail(pos.x,pos.y,pos.z) and is_rail(pos.x,pos.y,pos.z+zdir)) then
+ --print("up")
+ dir.y = speed
+ dir.z = zdir*speed
+
+ --go down
+ elseif (is_rail(pos.x,pos.y-1,pos.z) or vel.y < 0) and not is_rail(pos.x,pos.y,pos.z+zdir) then
+ --print("down")
+ dir.y = -speed
+ dir.z = zdir*speed
+
+
+ --go flat
+ elseif is_rail(pos.x,pos.y,pos.z) then --currently on rail
+ --print("flat")
+ --print("forward inside")
+ --correct y position
+ if dir.y == 0 and self.object:getpos().y ~= pos.y then
+ --print("correcting y")
+ local posser = self.object:getpos()
+ self.object:moveto(vector.new(posser.x,pos.y,posser.z))
+ end
+ dir.z = zdir*speed
+ end
+ end
+ --turn
+ local turnx = 0
+ local turnz = 0
+
+ if vel.x>0 then turnx=1 elseif vel.x<0 then turnx=-1 end
+ if vel.z>0 then turnz=1 elseif vel.z<0 then turnz=-1 end
+
+
+ if turnx and turnz and dir.y == 0 and not vector.equals(dir, vector.new(0,0,0)) and not is_rail(pos.x+turnx,pos.y-1,pos.z+turnz) and not is_rail(pos.x+turnx,pos.y,pos.z+turnz) and not is_rail(pos.x+turnx,pos.y+1,pos.z+turnz) then
+ if x > z then
+ for y = -1,1 do
+ if is_rail(pos.x,pos.y+y,pos.z+1) then
+ dir.z = speed
+ dir.x = 0
+ --recenter on the rail
+ self.object:moveto(pos)
+ elseif is_rail(pos.x,pos.y+y,pos.z-1) then
+ dir.z = -speed
+ dir.x = 0
+ --recenter on the rail
+ self.object:moveto(pos)
+ end
+ end
+ elseif z > x then
+ for y = -1,1 do
+ if is_rail(pos.x+1,pos.y+y,pos.z) then
+ dir.x = speed
+ dir.z = 0
+ --recenter on the rail
+ self.object:moveto(pos)
+ elseif is_rail(pos.x-1,pos.y+y,pos.z) then
+ dir.x = -speed
+ dir.z = 0
+ --recenter on the rail
+ self.object:moveto(pos)
+ end
+ end
end
+
+ end
+ --apply
+ --if not vector.equals(dir,vector.new(0,0,0)) then
+ self.object:setvelocity(dir)
+ --end
+ self.oldpos=self.object:getpos()
+
+ --make the cart move up and down on hills
+ self.object:set_properties({mesh="minecart.obj"})
+ if vel.y <0 then
+ self.object:set_properties({mesh="minecart_down.obj"})
+ elseif vel.y > 0 then
+ self.object:set_properties({mesh="minecart_up.obj"})
+ end
+
+ --slow it down
+ if self.speed > 0 then
+ self.speed = self.speed - 0.01
+ end
+ if self.speed < 0 then
+ self.speed = 0
end
- end
- --apply
- --if not vector.equals(dir,vector.new(0,0,0)) then
- self.object:setvelocity(dir)
- --end
-
+
+ end,