]> git.lizzy.rs Git - Crafter.git/blob - mods/minecart/init.lua
Complete minecart logic - for now
[Crafter.git] / mods / minecart / init.lua
1 --[[
2
3 Basic idealogy
4
5 goal - > go to goal - > check all this and repeat
6
7
8 minecart does check axis dir then -1 1 on opposite axis (x and z)
9
10 minecart checks in front and above 
11
12 minecart checks in front and below
13
14 if in front above start moving up
15
16 if in front below start moving down
17
18 minecart checks if rail in front then if not check sides and if none then stop
19
20 if a rail in front of minecart then when past center of node center, turn towards the available rail and then recenter self onto rail on the new axis
21
22
23 keep it simple stupid
24
25 make cart make noise
26
27 ]]--
28 local path = minetest.get_modpath("minecart")
29 dofile(path.."/rail.lua")
30
31
32
33 local function is_rail(x,y,z)
34         return(minetest.get_node_group(minetest.get_node(vector.new(x,y,z)).name,"rail")>0)
35 end
36
37 local minecart = {
38         initial_properties = {
39                 physical = false, -- otherwise going uphill breaks
40                 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},
41                 visual = "mesh",
42                 mesh = "minecart.obj",
43                 visual_size = {x=1, y=1},
44                 textures = {"minecart.png"},
45                 automatic_face_movement_dir = 90.0,
46         },
47
48         rider = nil,
49         punched = false,
50         
51 }
52
53 function minecart:on_rightclick(clicker)
54         if not clicker or not clicker:is_player() then
55                 return
56         end
57         local player_name = clicker:get_player_name()
58         if self.rider and player_name == self.rider then
59                 self.rider = nil
60                 carts:manage_attachment(clicker, nil)
61         elseif not self.rider then
62                 self.rider = player_name
63                 carts:manage_attachment(clicker, self.object)
64
65                 -- player_api does not update the animation
66                 -- when the player is attached, reset to default animation
67                 
68                 --player_api.set_animation(clicker, "stand")
69         end
70 end
71
72 function minecart:on_activate(staticdata, dtime_s)
73         self.object:set_armor_groups({immortal=1})
74         if string.sub(staticdata, 1, string.len("return")) ~= "return" then
75                 return
76         end
77         local data = minetest.deserialize(staticdata)
78         if type(data) ~= "table" then
79                 return
80         end
81         self.railtype = data.railtype
82         if data.old_dir then
83                 self.old_dir = data.old_dir
84         end
85 end
86
87 function minecart:get_staticdata()
88         return minetest.serialize({
89         })
90 end
91 function minecart:on_punch(puncher, time_from_last_punch, tool_capabilities, dir, damage)
92         self.object:remove()
93 end
94
95
96
97
98
99
100 --repel from players on track "push"
101 function minecart:push(self)
102         local pos = self.object:getpos()
103         for _,object in ipairs(minetest.get_objects_inside_radius(pos, 2)) do
104                 if object:is_player() then
105                         local player_pos = object:getpos()
106                         pos.y = 0
107                         player_pos.y = 0
108                         
109                         local vel = vector.subtract(pos, player_pos)
110                         vel = vector.normalize(vel)
111                         local distance = vector.distance(pos,player_pos)
112                         
113                         distance = (2-distance)*3
114                         
115                         vel = vector.multiply(vel,distance)
116                         
117                         self.object:setvelocity(vel)
118                         
119                 end
120         end
121 end
122
123 function minecart:ride_rail(self)
124
125         --floor position!!!!
126         
127         local pos = vector.floor(vector.add(self.object:getpos(),0.5))
128         local speed = 10 --change to the cart speed soon
129         
130         local vel = self.object:getvelocity()
131         local x = math.abs(vel.x)
132         local z = math.abs(vel.z)
133         local xdir
134         local zdir
135         local dir = {x=0,y=0,z=0}
136         
137         --check direction
138         --x axis
139         if x > z then
140                 if vel.x>0 then xdir=1 elseif vel.x<0 then xdir=-1 end
141                 
142                 --print(minetest.get_node(vector.new(pos.x,pos.y,pos.z)).name)
143                 
144                 --go up
145                 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
146                         print("up")
147                         dir.y = speed
148                         dir.x = xdir*speed
149
150                 --go down
151                 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
152                         print("down")
153                         dir.y = -speed
154                         dir.x = xdir*speed
155                 
156                 --go flat
157                 elseif is_rail(pos.x,pos.y,pos.z) then --currently on rail
158                         print("flat")
159                         --print("forward inside")
160                         --correct y position
161                         if dir.y == 0 and self.object:getpos().y ~= pos.y then
162                                 --print("correcting y")
163                                 local posser = self.object:getpos()
164                                 self.object:moveto(vector.new(posser.x,pos.y,posser.z))
165                         end
166                         dir.x = xdir*speed
167                 end
168         --z axis
169         elseif z > x then
170                 if vel.z>0 then zdir=1 elseif vel.z<0 then zdir=-1 end
171                 
172                 --print(minetest.get_node(vector.new(pos.x,pos.y,pos.z)).name)
173                 
174                 --go up
175                 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
176                         --print("up")
177                         dir.y = speed
178                         dir.z = zdir*speed
179                 
180                 --go down
181                 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
182                         --print("down")
183                         dir.y = -speed
184                         dir.z = zdir*speed
185                 
186                 
187                 --go flat
188                 elseif is_rail(pos.x,pos.y,pos.z) then --currently on rail
189                         --print("flat")
190                         --print("forward inside")
191                         --correct y position
192                         if dir.y == 0 and self.object:getpos().y ~= pos.y then
193                                 --print("correcting y")
194                                 local posser = self.object:getpos()
195                                 self.object:moveto(vector.new(posser.x,pos.y,posser.z))
196                         end
197                         dir.z = zdir*speed
198                 end
199         end
200         --turn
201         local turnx = 0
202         local turnz = 0
203         
204         if vel.x>0 then turnx=1 elseif vel.x<0 then turnx=-1 end
205         if vel.z>0 then turnz=1 elseif vel.z<0 then turnz=-1 end
206         
207
208         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
209                 if x > z then
210                         if is_rail(pos.x,pos.y,pos.z+1) then
211                                 dir.z = speed
212                                 dir.x = 0
213                                 --recenter on the rail
214                                 self.object:moveto(pos)
215                         elseif is_rail(pos.x,pos.y,pos.z-1) then
216                                 dir.z = -speed
217                                 dir.x = 0
218                                 --recenter on the rail
219                                 self.object:moveto(pos)
220                         end
221                 elseif z > x then
222                         if is_rail(pos.x+1,pos.y,pos.z) then
223                                 dir.x = speed
224                                 dir.z = 0
225                                 --recenter on the rail
226                                 self.object:moveto(pos)
227                         elseif is_rail(pos.x-1,pos.y,pos.z) then
228                                 dir.x = -speed
229                                 dir.z = 0
230                                 --recenter on the rail
231                                 self.object:moveto(pos)
232                         end
233                 end
234                 
235         end
236         --apply
237         --if not vector.equals(dir,vector.new(0,0,0)) then
238         self.object:setvelocity(dir)
239         --end
240         self.oldpos=self.object:getpos()
241         
242         
243         self.object:set_properties({mesh="minecart.obj"})
244         if vel.y <0  then
245                 self.object:set_properties({mesh="minecart_down.obj"})
246         elseif vel.y > 0 then
247                 self.object:set_properties({mesh="minecart_up.obj"})
248         end
249         return(self.object:set_animation(anim, 1, 0))
250 end
251
252
253
254 function minecart:on_step(dtime)
255         minecart:push(self)
256         minecart:ride_rail(self)
257 end
258
259 minetest.register_entity("minecart:minecart", minecart)
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280 minetest.register_craftitem("minecart:minecart", {
281         description = "Minecart",
282         inventory_image = "minecartitem.png",
283         wield_image = "minecartitem.png",
284         on_place = function(itemstack, placer, pointed_thing)
285                 if not pointed_thing.type == "node" then
286                         return
287                 end
288                 
289                 if minetest.get_item_group(minetest.get_node(pointed_thing.under).name, "rail")>0 then
290                         minetest.add_entity(pointed_thing.under, "minecart:minecart")
291                 else
292                         return
293                 end
294
295                 itemstack:take_item()
296
297                 return itemstack
298         end,
299 })
300
301 minetest.register_craft({
302         output = "minecart:minecart",
303         recipe = {
304                 {"main:iron", "", "main:iron"},
305                 {"main:iron", "main:iron", "main:iron"},
306         },
307 })