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