]> git.lizzy.rs Git - Crafter.git/commitdiff
Add in prototype 2 of minecart
authoroilboi <47129783+oilboi@users.noreply.github.com>
Wed, 19 Feb 2020 18:21:50 +0000 (13:21 -0500)
committeroilboi <47129783+oilboi@users.noreply.github.com>
Wed, 19 Feb 2020 18:21:50 +0000 (13:21 -0500)
mods/minecart/init.lua
mods/minecart/oldcode.txt
mods/minecart/rail.lua
todo.txt

index 87258cc666b9515e6d27a1e04730b6386784f3c6..ffd2d981e5c2d097c2535c48ff8003726b1b1b7c 100644 (file)
---[[
-
-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",
index 3f4975a817404ea0d5a92964d60f92cc6d511224..6b47de41354090b7b652df57f5101e6acf86f3d3 100644 (file)
-       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,
index 8e94f9bee57e494575bbd0647957cc25be63a009..cc794c654c149096b7f9d6353b48877ff03246f1 100644 (file)
@@ -1,10 +1,16 @@
 minetest.register_node("minecart:rail",{
        description = "Rail",
        wield_image = "rail.png",
+       tiles = {
+               "stone.png", "stone.png",
+               "stone.png", "stone.png"
+       },
+       --[[
        tiles = {
                "rail.png", "railcurve.png",
                "railt.png", "railcross.png"
        },
+       ]]--
        drawtype = "raillike",
        paramtype = "light",
        sunlight_propagates = true,
index df93d812fdd943bb6658420516b9437b28735141..3edd280d83c7e9c488d8341bea971ee29763095c 100644 (file)
--- a/todo.txt
+++ b/todo.txt
@@ -22,7 +22,9 @@
 --fix tools causing crash on pigs with no fleshy definition
 --ladders - only placeable on walls
 --eating animation - particles? - entity?
-boats
+--boats
+--make entities push against players
+rewrite minecart
 redstone - make nodes drop multiple items individually
 crafting bench
 fishing
@@ -40,3 +42,34 @@ add a function to set a velocity goal to entities and then implement it with all
 
 open bugs:
 fix torches not deleting particles when mounted node dug <- meta glitch?
+
+possible applications:
+
+causes object to magnetize towards player or other objects and stop after an inner radius
+use for better item magnet?
+
+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 = (1-distance)*10
+       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, -1)
+       --object:add_player_velocity(acceleration)
+end