]> git.lizzy.rs Git - Crafter.git/blob - mods/minecart/init.lua
Fix furnace particles
[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         local obj = minetest.add_item(self.object:getpos(), "minecart:minecart")
88         obj:get_luaentity().collection_timer = 2
89         self.object:remove()
90 end
91
92
93
94
95
96
97 --repel from players on track "push"
98 function minecart:push(self)
99         local pos = self.object:getpos()
100         for _,object in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
101                 if object:is_player() and object:get_player_name() ~= self.rider then
102                         local player_pos = object:getpos()
103                         pos.y = 0
104                         player_pos.y = 0
105                         
106                         local vel = vector.subtract(pos, player_pos)
107                         vel = vector.normalize(vel)
108                         local distance = vector.distance(pos,player_pos)
109                         
110                         distance = (1-distance)*10
111                         
112                         vel = vector.multiply(vel,distance)
113                         
114                         --only push if it's faster than current speed
115                         if distance > self.speed then
116                                 self.object:setvelocity(vel)
117                                 self.speed = distance
118                         end             
119                 end
120         end
121 end
122
123 function minecart:ride_rail(self)
124         local pos = vector.floor(vector.add(self.object:getpos(),0.5))
125         local speed = self.speed
126         if self.speed > 10 then
127                 self.speed = 10
128         end
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                         for y = -1,1 do
211                                 if is_rail(pos.x,pos.y+y,pos.z+1) then
212                                         dir.z = speed
213                                         dir.x = 0
214                                         --recenter on the rail
215                                         self.object:moveto(pos)
216                                 elseif is_rail(pos.x,pos.y+y,pos.z-1) then
217                                         dir.z = -speed
218                                         dir.x = 0
219                                         --recenter on the rail
220                                         self.object:moveto(pos)
221                                 end
222                         end
223                 elseif z > x then
224                         for y = -1,1 do
225                                 if is_rail(pos.x+1,pos.y+y,pos.z) then
226                                         dir.x = speed
227                                         dir.z = 0
228                                         --recenter on the rail
229                                         self.object:moveto(pos)
230                                 elseif is_rail(pos.x-1,pos.y+y,pos.z) then
231                                         dir.x = -speed
232                                         dir.z = 0
233                                         --recenter on the rail
234                                         self.object:moveto(pos)
235                                 end
236                         end
237                 end
238                 
239         end
240         --apply
241         --if not vector.equals(dir,vector.new(0,0,0)) then
242         self.object:setvelocity(dir)
243         --end
244         self.oldpos=self.object:getpos()
245         
246         --make the cart move up and down on hills
247         self.object:set_properties({mesh="minecart.obj"})
248         if vel.y <0  then
249                 self.object:set_properties({mesh="minecart_down.obj"})
250         elseif vel.y > 0 then
251                 self.object:set_properties({mesh="minecart_up.obj"})
252         end
253         
254         --slow it down
255         if self.speed > 0 then
256                 self.speed = self.speed - 0.01
257         end
258         if self.speed < 0 then
259                 self.speed = 0
260         end
261         
262 end
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 minetest.register_craftitem("minecart:minecart", {
273         description = "Minecart",
274         inventory_image = "minecartitem.png",
275         wield_image = "minecartitem.png",
276         on_place = function(itemstack, placer, pointed_thing)
277                 if not pointed_thing.type == "node" then
278                         return
279                 end
280                 
281                 if minetest.get_item_group(minetest.get_node(pointed_thing.under).name, "rail")>0 then
282                         minetest.add_entity(pointed_thing.under, "minecart:minecart")
283                 else
284                         return
285                 end
286
287                 itemstack:take_item()
288
289                 return itemstack
290         end,
291 })
292
293 minetest.register_craft({
294         output = "minecart:minecart",
295         recipe = {
296                 {"main:iron", "", "main:iron"},
297                 {"main:iron", "main:iron", "main:iron"},
298         },
299 })