Guest User

Untitled

a guest
Jul 27th, 2019
213
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.01 KB | None | 0 0
  1. -- Advanced Vehicles by Andrey01
  2.  
  3. adv_vehicles = {}
  4. global_nodenames_list = {}
  5.  
  6. -- Creates a list with all registered nodes.
  7. local i = 0
  8. for node_name, def in pairs(minetest.registered_nodes) do
  9. i = i+1
  10. global_nodenames_list[i] = node_name
  11. end
  12.  
  13. -- DEPRECATED Rounds 'num' to the tenth and return the rounded number.
  14. local function round_num(num)
  15. local int, frac = math.modf(num)
  16. local to_str = tostring(num)
  17. local to_str_frac = tostring(frac)
  18. local dot_ind = string.find(to_str_frac, '.')
  19. local tenth_rank = string.sub(to_str_frac, dot_ind+2, dot_ind+2)
  20. local new_frac = string.gsub(to_str_frac, tenth_rank, "0")
  21. local new_frac_to_int = tonumber(new_frac)
  22. local new_frac2 = string.gsub(to_str, tenth_rank, tostring(tonumber(tenth_rank)+1))
  23. local rounded_num = (new_frac_to_int < 0.05 and num-new_frac) or (new_frac_to_int >= 0.05 and tonumber(string.sub(new_frac2, 1, dot_ind+2)))
  24. return rounded_num
  25. end
  26.  
  27. local is_car_driven = nil
  28. -- The method calculates new position for any car seat (for example, after a car turning)
  29. adv_vehicles.rotate_point_around_other_point = function (circle_centre_pos, rotating_point_pos, fixed_point_yaw, current_point_yaw)
  30. local turn_angle = current_point_yaw-fixed_point_yaw
  31. local new_pos = {x=rotating_point_pos.x, y=circle_centre_pos.y, z=rotating_point_pos.z}
  32. new_pos.x = circle_centre_pos.x + (rotating_point_pos.x-circle_centre_pos.x) * math.cos(turn_angle) - (rotating_point_pos.z-circle_centre_pos.z) * math.sin(turn_angle)
  33. new_pos.z = circle_centre_pos.z + (rotating_point_pos.z-circle_centre_pos.z) * math.cos(turn_angle) + (rotating_point_pos.x-circle_centre_pos.x) * math.sin(turn_angle)
  34. return new_pos
  35. end
  36.  
  37. -- The method attaches a player to the car
  38. adv_vehicles.attach_player_to_veh = function(player, vehicle, seated, model, animation)
  39. if vehicle.seats_list[seated].busy_by then
  40. minetest.chat_send_player(player:get_player_name(), "This seat is busy by" .. vehicle.seats_list[seated].busy_by .. "!")
  41. return
  42. end
  43.  
  44. vehicle.seats_list[seated].busy_by = player:get_player_name()
  45. local veh_rot = vehicle.object:get_rotation()
  46. local new_seat_pos = adv_vehicles.rotate_point_around_other_point({x=0, y=0, z=0}, vehicle.seats_list[seated].pos, vehicle.fixed_veh_rotate_angle, veh_rot.y)
  47. new_seat_pos.y = 9
  48. vehicle.seats_list[seated].pos = new_seat_pos
  49. local meta = player:get_meta()
  50. meta:set_string("is_sit", minetest.serialize({veh_name, seated}))
  51. local new_player_rot = {x=math.deg(veh_rot.x), y=veh_rot.y+180, z=math.deg(veh_rot.z)}
  52. local p=vehicle.object:get_pos()
  53. --player:set_pos({x=p.x+vehicle.seats_list[seated].pos.x, y=p.y, z=p.z+vehicle.seats_list[seated].pos.z})
  54. local eye_offset_fi, eye_offset_th = player:get_eye_offset()
  55. if vehicle.seats_list[seated].eye_offset then
  56. local eye_off = vehicle.seats_list[seated].eye_offset
  57. player:set_eye_offset({x=eye_offset_fi.x+eye_off.x, y=eye_offset_fi.y+(eye_off.y or 0), z=eye_offset_fi.z+eye_off.z}, eye_offset_th)
  58. end
  59. player:set_attach(vehicle.object, "", new_seat_pos, new_player_rot)
  60.  
  61. --[[if not vehicle.seats_list[seated].eye_offset then
  62. player:set_eye_offset({x=vehicle.seats_list[seated].pos.x, y=0, z=vehicle.seats_list[seated].pos.z}, eye_offset)
  63. else
  64. player:set_eye_offset({z=vehicle.seats_list[seated].eye_offset.x, y=0, z=vehicle.seats_list[seated].eye_offset.z}, eye_offset)
  65. end]]
  66.  
  67. --player:set_eye_offset({x=-4.0, y=-3.0, z=3.0}, eye_offset)
  68.  
  69.  
  70. if model then
  71. player:set_properties({mesh=model})
  72. end
  73. if animation then
  74. player:set_animation({x=animation.x, y=animation.y})
  75. end
  76. end
  77.  
  78. -- The method detaches a player from the car
  79. adv_vehicles.detach_player_from_veh = function (player, vehicle, seated, model, animation)
  80. if not vehicle.seats_list[seated].busy_by then
  81. return
  82. end
  83. local meta = player:get_meta()
  84. meta:set_string("is_sit", "")
  85. vehicle.seats_list[seated].busy_by = nil
  86. player:set_detach()
  87. player:set_eye_offset({x=0, y=0, z=0}, {x=0, y=0, z=0})
  88. if model then
  89. player:set_properties({mesh=model})
  90. end
  91. if animation then
  92. player:set_animation({x=animation.x, y=animation.y})
  93. end
  94. end
  95.  
  96. -- Moves a point around the centre dependently on the rotation angle and returns derived new position of that point.
  97. -- *old_yaw is a fixed_veh_rotation_angle is saved in an entity.
  98. -- *old_acc_vect_pos is an acceleration vector position is also saved in the entity.
  99. adv_vehicles.pave_vector = function (vehicle, old_acc_vect_pos, old_yaw)
  100. local yaw = vehicle.object:get_yaw()
  101. if yaw == old_yaw then
  102. return vehicle.acc_vector_pos, yaw
  103. end
  104. local new_acc_vect_pos = adv_vehicles.rotate_point_around_other_point({x=0, y=0, z=0}, old_acc_vect_pos, old_yaw, yaw)
  105. return new_acc_vect_pos, yaw
  106. end
  107.  
  108. -- WARNING! This method doesn`t work properly currently.
  109. adv_vehicles.rotate_collisionbox = function (vehicle, yaw)
  110. if yaw % 90 ~= 0 then
  111. return
  112. end
  113. local veh_cbox = vehicle.object:get_properties().collisionbox
  114. local cur_cbox_dir = vehicle.collisionbox_yaw.along_axis
  115. local axle_num
  116. local new_axle_num = 1
  117. local axises_table = {"z", "x", "-z", "-x"}
  118. for num, axis in pairs(axises_table) do
  119. if axis == cur_cbox_dir then
  120. axle_num = num
  121. break
  122. end
  123. end
  124. local times = yaw / 90
  125. for i = 1, math.abs(times)+1 do
  126. if times < 0 then
  127. if axises_table[1] == cur_cbox_dir then
  128. new_axle_num = axises_table[#axises_table]
  129. else
  130. new_axle_num = new_axle_num - 1
  131. end
  132. else
  133. if axises_table[#axises_table] == cur_cbox_dir then
  134. new_axle_num = axises_table[1]
  135. else
  136. new_axle_num = new_axle_num + 1
  137. end
  138. end
  139. end
  140.  
  141. local new_cbox_dir = axises_table[new_axle_num]
  142. local cboxes = {
  143. ["z"] = {veh_cbox[1], veh_cbox[2], veh_cbox[3], veh_cbox[4], veh_cbox[5], veh_cbox[6]},
  144. ["x"] = {veh_cbox[3], veh_cbox[2], veh_cbox[1], veh_cbox[6], veh_cbox[5], veh_cbox[4]},
  145. ["-z"] = {veh_cbox[1]*-1, veh_cbox[2], veh_cbox[3]*-1, veh_cbox[4]*-1, veh_cbox[5], veh_cbox[6]*-1},
  146. ["-x"] = {veh_cbox[3]*-1, veh_cbox[2], veh_cbox[1]*-1, veh_cbox[6]*-1, veh_cbox[5], veh_cbox[4]*-1}
  147. }
  148. local new_cbox = cboxes[new_cbox_dir]
  149. vehicle.object:set_properties({collisionbox=new_cbox})
  150. local old_cbox_yaw = vehicle.collisionbox_yaw.val
  151. vehicle.collisionbox_yaw = {val=old_cbox_yaw+yaw, along_axis=new_cbox_dir}
  152. end
  153.  
  154. local is_fallen
  155. -- Bounces a car only due to the falling.
  156. adv_vehicles.collide = function (vehicle)
  157. local vel = vehicle.object:get_velocity()
  158. local fixed_vel = vehicle.veh_vel
  159. local seats_list = vehicle.seats_list
  160. local hp = vehicle.object:get_hp()
  161. if vel.y == 0 and fixed_vel ~= 0 then
  162. if not is_fallen then
  163. is_fallen = true
  164. local acc = vehicle.object:get_acceleration()
  165. vehicle.object:set_acceleration({x=acc.x, y=fixed_vel*-5, z=acc.z})
  166. vehicle.object:set_hp(hp-math.abs(math.ceil(fixed_vel)), {type="fall"})
  167. for seated, data in pairs(seats_list) do
  168. if seated.busy_by then
  169. local player = minetest.get_player_by_name(seated.busy_by)
  170. local player_hp = player:get_hp()
  171. player:set_hp(player_hp-math.abs(math.ceil(fixed_vel)), {type="fall"})
  172. end
  173. end
  174. end
  175. else
  176. is_fallen = nil
  177. end
  178. end
  179.  
  180. -- Called in each 0.1 second in the globalstep, decelerates the vehicle speed.
  181. -- *vector_l is a vector length
  182. adv_vehicles.vehicle_braking = function (vehicle, vector_l)
  183. local obj = vehicle.object
  184. local vel = obj:get_velocity()
  185. local vel_l = vector.length(vel)
  186. local acc_x = -(vel.x*vector_l/vel_l)
  187. local acc_z = -(vel.z*vector_l/vel_l)
  188. local acc_y = obj:get_acceleration().y
  189. obj:set_acceleration({x=acc_x, y=acc_y, z=acc_z})
  190.  
  191. local new_acc = obj:get_acceleration()
  192. local new_vel = obj:get_velocity()
  193. local new_vel_l = vector.length(new_vel)
  194. minetest.debug(vector.length(new_vel))
  195. if new_vel_l < 0.03 and not is_car_driven then
  196. obj:set_velocity({x=0, y=new_vel.y, z=0})
  197. obj:set_acceleration({x=0, y=new_acc.y, z=0})
  198. end
  199. end
  200.  
  201. -- Implements vehicle controls (turning, moving forward/backwards).
  202. adv_vehicles.vehicle_handle = function (vehicle, controls, yaw)
  203. local vel_l = vector.length(vehicle.object:get_velocity())
  204. local new_yaw=math.deg(yaw)
  205. if controls.right and vel_l ~= 0 then
  206. vehicle.object:set_yaw(yaw-math.rad(1))
  207. new_yaw = math.deg(vehicle.object:get_yaw())
  208. local fixed_cbox_yaw = vehicle.collisionbox_yaw.val
  209. if new_yaw-fixed_cbox_yaw <= -90 then
  210. --minetest.debug("1")
  211. adv_vehicles.rotate_collisionbox(vehicle, -90)
  212. end
  213. end
  214. if controls.left and vel_l ~= 0 then
  215. vehicle.object:set_yaw(yaw+math.rad(1))
  216. new_yaw = math.deg(vehicle.object:get_yaw())
  217. local fixed_cbox_yaw = vehicle.collisionbox_yaw.val
  218. if new_yaw+fixed_cbox_yaw >= 90 then
  219. --minetest.debug("2")
  220. adv_vehicles.rotate_collisionbox(vehicle, 90)
  221. end
  222. end
  223.  
  224. local acc = vehicle.object:get_acceleration()
  225. if controls.up then
  226. is_car_driven=true
  227. vehicle.object:set_acceleration({x=vehicle.acc_vector_pos.x, y=acc.y, z=vehicle.acc_vector_pos.z})
  228. else
  229. is_car_driven=nil
  230. end
  231.  
  232. if controls.down then
  233. is_car_driven=true
  234. vehicle.object:set_acceleration({x=vehicle.acc_vector_pos.x*-1, y=acc.y, z=vehicle.acc_vector_pos.z*-1})
  235. else
  236. is_car_driven=nil
  237. end
  238. return math.rad(new_yaw)
  239. end
  240.  
  241.  
  242. --[[adv_cars.nearby_nodes_are = function (car)
  243. local vel = car.object:get_velocity()
  244. local pos = car.object:get_pos()
  245. local meta = minetest.deserialize(minetest.get_meta():get_string("is_sit"))
  246. local z_face = minetest.registered_entities[meta.car_name].collisionbox[6]
  247. if (vel.x and vel.y and vel.z) ~= 0 then
  248.  
  249. local nearby_nodes = minetest.find_node_near(pos, z_face, global_nodenames_list)]]
  250.  
  251. -- Registers a vehicle to the world and creates a spawner item for it with a crafting recipe.
  252. adv_vehicles.register_vehicle = function (vehname, veh_properties, veh_item)
  253. minetest.register_entity("adv_vehicles:"..vehname, {
  254. visual = "mesh",
  255. physical = true,
  256. mass = veh_properties.mass or 2000,
  257. acc_vector_length = veh_properties.acc_vector_length,
  258. max_vel = veh_properties.max_vel or 120,
  259. collide_with_objects = true,
  260. collisionbox = veh_properties.cbox,
  261. mesh = veh_properties.model,
  262. textures = veh_properties.textures,
  263. visual_size = veh_properties.visual_size or {x=1, y=1, z=1},
  264. use_texture_alpha = true,
  265. on_activate = function (self, staticdata, dtime_s)
  266. -- Fixed vehicle rotation angle (in rads). Necessary for calculating a point position.
  267. self.fixed_veh_rotate_angle = math.rad(0)
  268. self.collisionbox_yaw = {val=0, along_axis="z"}
  269. -- Entitysting of an object.
  270. self.entity_name = "adv_vehicles:"..vehname
  271. -- List of a vehicle seats. Fields: 'driver'/'passenger', both keep 'busy_by' (playername) and 'pos' (of the seat) inside.
  272. self.seats_list = {}
  273. for seated, data in pairs(veh_properties.seats) do
  274. self.seats_list[seated] = data
  275. self.seats_list[seated].pos.y = 0
  276. end
  277. self.veh_vel = 0
  278.  
  279. local acc = self.object:get_acceleration()
  280. local gravity_strength = veh_properties.mass * -9.8
  281. self.object:set_acceleration({x=acc.x, y=gravity_strength, z=acc.z})
  282. local acc2 = self.object:get_acceleration()
  283. -- Original acceleration vector position (along to -z dir).
  284. self.acc_vector_pos = {x=0, y=acc2.y, z=veh_properties.acc_vector_length*-1}
  285. yaw = self.object:get_yaw()
  286. --Called in each 0.1 second.
  287. minetest.register_globalstep(function(dtime)
  288. local entity = self.object:get_luaentity()
  289. if entity then
  290. local obj = entity.object
  291. local vel = obj:get_velocity()
  292. if vel.y ~= 0 then
  293. entity.veh_vel = vel.y
  294. end
  295. local acc = obj:get_acceleration()
  296. if acc.y > 0 then
  297. obj:set_acceleration({x=acc.x, y=gravity_strength, z=acc.z})
  298. end
  299. adv_vehicles.collide(entity)
  300.  
  301. -- Further it will get new position for the acceleration vector dependently on fixed rotation angle and fix new rotation angles.
  302. entity.acc_vector_pos, entity.fixed_veh_rotate_angle = adv_vehicles.pave_vector(entity, entity.acc_vector_pos, entity.fixed_veh_rotate_angle)
  303. for seat, d in pairs(entity.seats_list) do
  304. if d.busy_by then
  305. local player = minetest.get_player_by_name(d.busy_by)
  306. local is_sit = minetest.deserialize(player:get_meta():get_string("is_sit"))
  307. if is_sit[2] == "driver" then
  308. yaw = entity.on_handle(entity, player:get_player_control(), yaw)
  309. end
  310. end
  311. end
  312.  
  313. -- If a length of the velocity vector exceeds a 'max_vel' value, sets to zero the acceleration vector.
  314. local vel_length = vector.length(vel)
  315. if vel_length >= veh_properties.max_vel then
  316. obj:set_acceleration({x=0, y=gravity_strength, z=0})
  317. end
  318. if not is_car_driven and vel_length ~= 0 then
  319. adv_vehicles.vehicle_braking(entity, 8)
  320. end
  321. end
  322.  
  323. end)
  324. end,
  325. on_handle = adv_vehicles.vehicle_handle,
  326. on_death = function (self, killer)
  327. for seated, data in pairs(self.seats_list) do
  328. if self.seats_list[seated].busy_by and minetest.get_player_by_name(self.seats_list[seated].busy_by) then
  329. local player = minetest.get_player_by_name(self.seats_list[seated].busy_by)
  330. adv_vehicles.detach_player_from_veh(player, self, seated, "character.b3d") end
  331. end
  332. end,
  333. --[[on_attach_child = function (self, child)
  334. local meta = minetest.deserialize(child:get_meta():get_string("is_sit"))
  335. minetest.debug(dump(meta))
  336. if meta.passenger then minetest.debug(child:get_player_name()) return end
  337. minetest.register_globalstep(function(dtime)
  338. local entity = self.object:get_luaentity()
  339. if entity then
  340. if entity.seats_list.driver.busy_by then
  341. local yaw = entity.object:get_yaw()
  342. local new_yaw = self.on_handle(entity, child:get_player_control(), yaw)
  343. yaw = new_yaw
  344. end
  345.  
  346. end
  347. end)
  348. end, ]]
  349. on_rightclick = function (self, clicker)
  350. local seats_list = self.seats_list
  351. for seated, data in pairs(seats_list) do
  352. if data.busy_by == nil then
  353. if seated == "driver" then
  354. adv_vehicles.attach_player_to_veh(clicker, self, seated, "driver.b3d")
  355. self.is_veh_stopping=nil
  356. else adv_vehicles.attach_player_to_veh(clicker, self, seated, nil, {x=81, y=81}) end
  357. break
  358. elseif data.busy_by == clicker:get_player_name() then
  359. if seated == "driver" then
  360. adv_vehicles.detach_player_from_veh(clicker, self, seated, "character.b3d")
  361. self.is_veh_stopping=true
  362. else adv_vehicles.detach_player_from_veh(clicker, self, seated, nil, {x=1, y=80}) end
  363. break
  364. end
  365. end
  366. end
  367. })
  368.  
  369. if veh_item then
  370. minetest.register_craftitem("adv_vehicles:"..vehname, {
  371. description = veh_item.description,
  372. inventory_image = veh_item.inv_image,
  373. on_place = function (itemstack, placer, pointed_thing)
  374. if pointed_thing.type == "node" then
  375. local object = minetest.add_entity(pointed_thing.above, "adv_vehicles:"..vehname)
  376. local yaw = math.deg(placer:get_look_horizontal())
  377. object:set_yaw(math.rad(yaw+180))
  378. end
  379. end
  380. })
  381.  
  382. minetest.register_craft({
  383. output = "adv_vehicles:"..vehname,
  384. recipe = veh_item.craft_recipe
  385. })
  386. end
  387. end
  388.  
  389. --[[minetest.register_on_joinplayer(function (player)
  390. local meta = player:get_meta()
  391. local attach = player:get_attach()
  392. if attach then
  393. local parent = attach[1]
  394. local entity = parent:get_luaentity()
  395. if entity then
  396. local seat_num = meta:get_string("is_sit").seat_num
  397. entity.seats_list[seat_num] = nil
  398. adv_cars.attach_player_to_car(player, parent, seat_num, "driver.b3d")
  399. end
  400. end
  401. end)]]
  402.  
  403. minetest.register_on_dieplayer(function (player)
  404. local meta = player:get_meta()
  405. if meta:get_string("is_sit") ~= (nil or "") then
  406. local attach = player:get_attach()
  407. local player_meta = minetest.deserialize(meta:get_string("is_sit"))
  408. local seated = player_meta.seated
  409. adv_vehicles.detach_player_from_veh(player, attach[1], seated, "character.b3d")
  410. end
  411. end)
Advertisement
Add Comment
Please, Sign In to add comment