]> git.lizzy.rs Git - Crafter.git/blob - mods/boat/init.lua
Make boats fall faster
[Crafter.git] / mods / boat / init.lua
1 --minetest.get_node_level(pos)
2 minetest.register_entity("boat:boat", {
3         initial_properties = {
4                 hp_max = 1,
5                 physical = true,
6                 collide_with_objects = false,
7                 collisionbox = {-0.4, 0, -0.4, 0.4, 0.5, 0.4},
8                 visual = "mesh",
9                 mesh = "boat.x",
10                 textures = {"boat.png"},
11                 visual_size = {x=1,y=1,z=1},
12                 is_visible = true,
13                 automatic_face_movement_dir = -90.0,
14                 automatic_face_movement_max_rotation_per_sec = 600,
15         },
16         
17         rider = nil,
18         boat = true,
19
20         get_staticdata = function(self)
21                 return minetest.serialize({
22                         --itemstring = self.itemstring,
23                 })
24         end,
25
26         on_activate = function(self, staticdata, dtime_s)
27                 if string.sub(staticdata, 1, string.len("return")) == "return" then
28                         local data = minetest.deserialize(staticdata)
29                         if data and type(data) == "table" then
30                                 --self.itemstring = data.itemstring
31                         end
32                 else
33                         --self.itemstring = staticdata
34                 end
35                 self.object:set_armor_groups({immortal = 1})
36                 self.object:set_velocity({x = 0, y = 0, z = 0})
37                 self.object:set_acceleration({x = 0, y = 0, z = 0})
38         end,
39         on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
40                 local pos = self.object:get_pos()
41                 minetest.add_item(pos, "boat:boat")
42                 self.object:remove()
43         end,
44         
45         
46         on_rightclick = function(self,clicker)
47                 if not clicker or not clicker:is_player() then
48                         return
49                 end
50                 local player_name = clicker:get_player_name()
51                 
52                 if self.rider and player_name == self.rider then
53                         clicker:set_detach()
54                         local pos = self.object:get_pos()
55                         pos.y = pos.y + 1
56                         clicker:move_to(pos)
57                         clicker:add_player_velocity(vector.new(0,11,0))
58                         self.rider = nil
59                         
60                         player_is_attached(clicker,false)
61                         force_update_animation(clicker)
62
63                 elseif not self.rider then
64                         self.rider = player_name
65                         clicker:set_attach(self.object, "", {x=0, y=2, z=0}, {x=0, y=0, z=0})
66                         
67                         set_player_animation(clicker,"sit",0)
68                         player_is_attached(clicker,true)
69                 end
70         end,
71         --check if the boat is stuck on land
72         check_if_on_land = function(self)
73                 local pos = self.object:get_pos()
74                 pos.y = pos.y - 0.37
75                 local bottom_node = minetest.get_node(pos).name
76                 if (bottom_node == "main:water" or bottom_node == "main:waterflow" or bottom_node == "air") then
77                         self.on_land = false
78                 else
79                         self.on_land = true
80                 end
81         
82         end,
83         
84         --players drive the baot
85         drive = function(self)
86                 if self.rider and not self.on_land == true then
87                         local rider = minetest.get_player_by_name(self.rider)
88                         local move = rider:get_player_control().up
89                         self.moving = nil
90                         if move then
91                                 local currentvel = self.object:get_velocity()
92                                 local goal = rider:get_look_dir()
93                                 goal = vector.multiply(goal,20)
94                                 local acceleration = vector.new(goal.x-currentvel.x,0,goal.z-currentvel.z)
95                                 acceleration = vector.multiply(acceleration, 0.01)
96                                 self.object:add_velocity(acceleration)
97                                 self.moving = true
98                         end
99                 else
100                         self.moving = nil
101                 end
102         end,
103         
104         --players push boat
105         push = function(self)
106                 local pos = self.object:get_pos()
107                 for _,object in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
108                         if object:is_player() and object:get_player_name() ~= self.rider then
109                                 local player_pos = object:get_pos()
110                                 pos.y = 0
111                                 player_pos.y = 0
112                                 
113                                 local currentvel = self.object:get_velocity()
114                                 local vel = vector.subtract(pos, player_pos)
115                                 vel = vector.normalize(vel)
116                                 local distance = vector.distance(pos,player_pos)
117                                 distance = (1-distance)*10
118                                 vel = vector.multiply(vel,distance)
119                                 local acceleration = vector.new(vel.x-currentvel.x,0,vel.z-currentvel.z)
120                                 self.object:add_velocity(acceleration)
121                                 acceleration = vector.multiply(acceleration, -1)
122                                 object:add_player_velocity(acceleration)
123                         end
124                 end
125         end,
126         
127         --makes the boat float
128         float = function(self)
129                 local pos = self.object:get_pos()
130                 local node = minetest.get_node(pos).name
131                 self.swimming = false
132                 
133                 --flow normally if floating else don't
134                 if node == "main:water" or node =="main:waterflow" then
135                         self.object:set_acceleration(vector.new(0,0,0))
136                         self.swimming = true
137                         local vel = self.object:get_velocity()
138                         local goal = 9
139                         local acceleration = vector.new(0,goal-vel.y,0)
140                         acceleration = vector.multiply(acceleration, 0.01)
141                         self.object:add_velocity(acceleration)
142                         --self.object:set_acceleration(vector.new(0,0,0))
143                 else
144                         self.object:set_acceleration(vector.new(0,-10,0))
145                 end
146         end,
147         
148         --makes boats flow
149         flow = function(self)
150                 local pos = self.object:get_pos()
151                 pos.y = pos.y - 0.4
152                 local node = minetest.get_node(pos).name
153                 local node_above = minetest.get_node(vector.new(pos.x,pos.y+1,pos.z)).name
154                 local goalx = 0
155                 local goalz = 0
156                 --print(node_above)
157                 if (node == "main:waterflow" or node == "main:water" ) and not self.moving == true and (node_above ~= "main:water" and node_above ~= "main:waterflow") then
158                         local currentvel = self.object:get_velocity()
159                         local level = minetest.get_node_level(pos)
160                         local pos = self.object:get_pos()
161                         for x = -1,1 do
162                                 for y = -1,0 do
163                                         for z = -1,1 do
164                                                 if (x == 0 and z ~= 0) or (z == 0 and x ~=0) then
165                                                         local nodename = minetest.get_node(vector.new(pos.x+x,pos.y+y,pos.z+z)).name
166                                                         local level2 = minetest.get_node_level(vector.new(pos.x+x,pos.y+y,pos.z+z))
167                                                         if (level2 < level and nodename == "main:waterflow") or (nodename == "main:water" and level2 == 7)  then
168                                                                 goalx = x*7
169                                                                 goalz = z*7
170                                                                 --break
171                                                         end
172                                                 end
173                                         end
174                                 end
175                         end
176                         --only add velocity if there is one
177                         --else this stops the boat
178                         if goalx ~= 0 or goalz ~= 0 then
179                                 local acceleration = vector.new(goalx-currentvel.x,0,goalz-currentvel.z)
180                                 acceleration = vector.multiply(acceleration, 0.01)
181                                 self.object:add_velocity(acceleration)
182                         end
183                 end
184         end,
185         
186         
187         --slows the boat down
188         slowdown = function(self)
189                 if not self.moving == true then
190                         local vel = self.object:get_velocity()
191                         local acceleration = vector.new(-vel.x,0,-vel.z)
192                         local deceleration = vector.multiply(acceleration, 0.01)
193                         self.object:add_velocity(deceleration)
194                 end
195         end,
196
197         lag_correction = function(self,dtime)
198                 local pos = self.object:get_pos()
199                 local velocity = self.object:get_velocity()
200                 if self.lag_check then
201                         local chugent = math.ceil(minetest.get_us_time()/1000 - self.lag_check)
202
203                         --print("lag = "..chugent.." ms")
204                         if chugent > 70 and  self.old_pos and self.old_velocity then
205                                 self.object:move_to(self.old_pos)
206                                 self.object:set_velocity(self.old_velocity)
207                         end
208                 end
209                 self.old_pos = pos
210                 self.old_velocity = vel
211                 self.lag_check = minetest.get_us_time()/1000
212         end,
213
214         on_step = function(self, dtime)
215                 self.check_if_on_land(self)
216                 self.push(self)
217                 self.drive(self)
218                 self.float(self)
219                 self.flow(self)
220                 self.slowdown(self)
221                 self.lag_correction(self,dtime)
222         end,
223 })
224
225 minetest.register_craftitem("boat:boat", {
226         description = "Boat",
227         inventory_image = "boatitem.png",
228         wield_image = "boatitem.png",
229         liquids_pointable = true,
230         on_place = function(itemstack, placer, pointed_thing)
231                 if not pointed_thing.type == "node" then
232                         return
233                 end
234                 
235                 local sneak = placer:get_player_control().sneak
236                 local noddef = minetest.registered_nodes[minetest.get_node(pointed_thing.under).name]
237                 if not sneak and noddef.on_rightclick then
238                         minetest.item_place(itemstack, placer, pointed_thing)
239                         return
240                 end
241                 
242                 if minetest.get_item_group(minetest.get_node(pointed_thing.under).name, "water")>0 then
243                         minetest.add_entity(pointed_thing.under, "boat:boat")
244                 else
245                         return
246                 end
247
248                 itemstack:take_item()
249
250                 return itemstack
251         end,
252 })
253
254 minetest.register_craft({
255         output = "boat:boat",
256         recipe = {
257                 {"main:wood", "", "main:wood"},
258                 {"main:wood", "main:wood", "main:wood"},
259         },
260 })
261
262 ----------------------------------
263
264
265
266 minetest.register_entity("boat:iron_boat", {
267         initial_properties = {
268                 hp_max = 1,
269                 physical = true,
270                 collide_with_objects = false,
271                 collisionbox = {-0.4, 0, -0.4, 0.4, 0.5, 0.4},
272                 visual = "mesh",
273                 mesh = "boat.x",
274                 textures = {"iron_boat.png"},
275                 visual_size = {x=1,y=1,z=1},
276                 is_visible = true,
277                 automatic_face_movement_dir = -90.0,
278                 automatic_face_movement_max_rotation_per_sec = 600,
279         },
280         
281         rider = nil,
282         iron_boat = true,
283
284         get_staticdata = function(self)
285                 return minetest.serialize({
286                         --itemstring = self.itemstring,
287                 })
288         end,
289
290         on_activate = function(self, staticdata, dtime_s)
291                 if string.sub(staticdata, 1, string.len("return")) == "return" then
292                         local data = minetest.deserialize(staticdata)
293                         if data and type(data) == "table" then
294                                 --self.itemstring = data.itemstring
295                         end
296                 else
297                         --self.itemstring = staticdata
298                 end
299                 self.object:set_armor_groups({immortal = 1})
300                 self.object:set_velocity({x = 0, y = 0, z = 0})
301                 self.object:set_acceleration({x = 0, y = 0, z = 0})
302         end,
303         on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
304                 local pos = self.object:get_pos()
305                 minetest.add_item(pos, "boat:iron_boat")
306                 self.object:remove()
307         end,
308         
309         
310         on_rightclick = function(self,clicker)
311                 if not clicker or not clicker:is_player() then
312                         return
313                 end
314                 local player_name = clicker:get_player_name()
315                 
316                 if self.rider and player_name == self.rider then
317                         clicker:set_detach()
318                         local pos = self.object:get_pos()
319                         pos.y = pos.y + 1
320                         clicker:move_to(pos)
321                         clicker:add_player_velocity(vector.new(0,11,0))
322                         self.rider = nil
323                         
324                         player_is_attached(clicker,false)
325                         force_update_animation(clicker)
326
327                 elseif not self.rider then
328                         self.rider = player_name
329                         clicker:set_attach(self.object, "", {x=0, y=2, z=0}, {x=0, y=0, z=0})
330                         
331                         set_player_animation(clicker,"sit",0)
332                         player_is_attached(clicker,true)
333                 end
334         end,
335         --check if the boat is stuck on land
336         check_if_on_land = function(self)
337                 local pos = self.object:get_pos()
338                 pos.y = pos.y - 0.37
339                 local bottom_node = minetest.get_node(pos).name
340                 if (bottom_node == "nether:lava" or bottom_node == "nether:lavaflow" or bottom_node == "air") then
341                         self.on_land = false
342                 else
343                         self.on_land = true
344                 end
345         
346         end,
347         
348         --players drive the baot
349         drive = function(self)
350                 if self.rider and not self.on_land == true then
351                         local rider = minetest.get_player_by_name(self.rider)
352                         local move = rider:get_player_control().up
353                         self.moving = nil
354                         if move then
355                                 local currentvel = self.object:get_velocity()
356                                 local goal = rider:get_look_dir()
357                                 goal = vector.multiply(goal,20)
358                                 local acceleration = vector.new(goal.x-currentvel.x,0,goal.z-currentvel.z)
359                                 acceleration = vector.multiply(acceleration, 0.01)
360                                 self.object:add_velocity(acceleration)
361                                 self.moving = true
362                         end
363                 else
364                         self.moving = nil
365                 end
366         end,
367         
368         --players push boat
369         push = function(self)
370                 local pos = self.object:get_pos()
371                 for _,object in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
372                         if object:is_player() and object:get_player_name() ~= self.rider then
373                                 local player_pos = object:get_pos()
374                                 pos.y = 0
375                                 player_pos.y = 0
376                                 
377                                 local currentvel = self.object:get_velocity()
378                                 local vel = vector.subtract(pos, player_pos)
379                                 vel = vector.normalize(vel)
380                                 local distance = vector.distance(pos,player_pos)
381                                 distance = (1-distance)*10
382                                 vel = vector.multiply(vel,distance)
383                                 local acceleration = vector.new(vel.x-currentvel.x,0,vel.z-currentvel.z)
384                                 self.object:add_velocity(acceleration)
385                                 acceleration = vector.multiply(acceleration, -1)
386                                 object:add_player_velocity(acceleration)
387                         end
388                 end
389         end,
390         
391         --makes the boat float
392         float = function(self)
393                 local pos = self.object:get_pos()
394                 local node = minetest.get_node(pos).name
395                 self.swimming = false
396                 
397                 --flow normally if floating else don't
398                 if node == "nether:lava" or node =="nether:lavaflow" then
399                         self.swimming = true
400                         local vel = self.object:get_velocity()
401                         local goal = 9
402                         local acceleration = vector.new(0,goal-vel.y,0)
403                         acceleration = vector.multiply(acceleration, 0.01)
404                         self.object:add_velocity(acceleration)
405                         --self.object:set_acceleration(vector.new(0,0,0))
406                 else
407                         local vel = self.object:get_velocity()
408                         local goal = -9.81
409                         local acceleration = vector.new(0,goal-vel.y,0)
410                         acceleration = vector.multiply(acceleration, 0.01)
411                         self.object:add_velocity(acceleration)
412                         --self.object:set_acceleration(vector.new(0,0,0))
413                 end
414         end,
415         
416         --makes boats flow
417         flow = function(self)
418                 local pos = self.object:get_pos()
419                 pos.y = pos.y - 0.4
420                 local node = minetest.get_node(pos).name
421                 local node_above = minetest.get_node(vector.new(pos.x,pos.y+1,pos.z)).name
422                 local goalx = 0
423                 local goalz = 0
424                 --print(node_above)
425                 if (node == "nether:lavaflow" or node == "nether:lava" ) and not self.moving == true and (node_above ~= "nether:lava" and node_above ~= "nether:lavaflow") then
426                         local currentvel = self.object:get_velocity()
427                         local level = minetest.get_node_level(pos)
428                         local pos = self.object:get_pos()
429                         for x = -1,1 do
430                                 for y = -1,0 do
431                                         for z = -1,1 do
432                                                 if (x == 0 and z ~= 0) or (z == 0 and x ~=0) then
433                                                         local nodename = minetest.get_node(vector.new(pos.x+x,pos.y+y,pos.z+z)).name
434                                                         local level2 = minetest.get_node_level(vector.new(pos.x+x,pos.y+y,pos.z+z))
435                                                         if (level2 < level and nodename == "main:lavaflow") or (nodename == "main:lava" and level2 == 7)  then
436                                                                 goalx = x*7
437                                                                 goalz = z*7
438                                                                 --break
439                                                         end
440                                                 end
441                                         end
442                                 end
443                         end
444                         --only add velocity if there is one
445                         --else this stops the boat
446                         if goalx ~= 0 or goalz ~= 0 then
447                                 local acceleration = vector.new(goalx-currentvel.x,0,goalz-currentvel.z)
448                                 acceleration = vector.multiply(acceleration, 0.01)
449                                 self.object:add_velocity(acceleration)
450                         end
451                 end
452         end,
453         
454         
455         --slows the boat down
456         slowdown = function(self)
457                 if not self.moving == true then
458                         local vel = self.object:get_velocity()
459                         local acceleration = vector.new(-vel.x,0,-vel.z)
460                         local deceleration = vector.multiply(acceleration, 0.01)
461                         self.object:add_velocity(deceleration)
462                 end
463         end,
464
465         lag_correction = function(self,dtime)
466                 local pos = self.object:get_pos()
467                 local velocity = self.object:get_velocity()
468                 if self.lag_check then
469                         local chugent = math.ceil(minetest.get_us_time()/1000- self.lag_check)
470
471                         --print("lag = "..chugent.." ms")
472                         if chugent > 70 and  self.old_pos and self.old_velocity then
473                                 self.object:move_to(self.old_pos)
474                                 self.object:set_velocity(self.old_velocity)
475                         end
476                 end
477                 self.old_pos = pos
478                 self.old_velocity = vel
479                 self.lag_check = minetest.get_us_time()/1000
480         end,
481
482         on_step = function(self, dtime)
483                 self.check_if_on_land(self)
484                 self.push(self)
485                 self.drive(self)
486                 self.float(self)
487                 self.flow(self)
488                 self.slowdown(self)
489                 self.lag_correction(self,dtime)
490         end,
491 })
492
493 minetest.register_craftitem("boat:iron_boat", {
494         description = "Iron Boat",
495         inventory_image = "iron_boatitem.png",
496         wield_image = "iron_boatitem.png",
497         liquids_pointable = true,
498         on_place = function(itemstack, placer, pointed_thing)
499                 if not pointed_thing.type == "node" then
500                         return
501                 end
502                 
503                 local sneak = placer:get_player_control().sneak
504                 local noddef = minetest.registered_nodes[minetest.get_node(pointed_thing.under).name]
505                 if not sneak and noddef.on_rightclick then
506                         minetest.item_place(itemstack, placer, pointed_thing)
507                         return
508                 end
509                 
510                 if pointed_thing.above.y < -10000 and pointed_thing.above.y > -20000 then
511                         minetest.add_entity(pointed_thing.under, "boat:iron_boat")
512                 else
513                         return
514                 end
515
516                 itemstack:take_item()
517
518                 return itemstack
519         end,
520 })
521
522 minetest.register_craft({
523         output = "boat:iron_boat",
524         recipe = {
525                 {"main:iron", "main:coal", "main:iron"},
526                 {"main:iron", "main:iron", "main:iron"},
527         },
528 })