adv_vehicles2/api.lua

627 lines
29 KiB
Lua
Raw Permalink Normal View History

2020-06-25 13:00:39 -07:00
--------------------------------------------------------------------------------------------------
-- Advanced Vehicles II API by Andrey01
--------------------------------------------------------------------------------------------------
--GLOBAL TABLE
2020-06-25 13:00:39 -07:00
vehicles = {}
---------------------------------------------------------------------------
-- Constants
---------------------------------------------------------------------------
vehicles.gravity = -9.8 -- gravity constant
vehicles.air_rfac = 0.3 -- air resistance factor
2020-06-25 13:00:39 -07:00
---------------------------------------------------------------------------
-- Dynamic Tables
---------------------------------------------------------------------------
vehicles.showed_fspecs = {} -- pair: ["playername"] and {self, formname, [invname, invlist]}
vehicles.ngroups_friction_coefs = { -- friction coefficients of some groups of nodes.
2020-06-25 13:00:39 -07:00
["sand"] = 1.5,
["soil"] = 0.6,
["snowy"] = 0.9,
["slippery"] = 0.1,
["default"] = 0.8
}
--------------------------------------------------------------------------
-- API functions
---------------------------------------------------------------------------
vehicles.set_gravity = function(self)
local obj = self.object
local acc = obj:get_acceleration()
local vel = obj:get_velocity()
local m = minetest.registered_entities[self.name].mass
obj:set_acceleration({x=acc.x, y=vehicles.gravity, z=acc.z})
2020-06-25 13:00:39 -07:00
end
--[[ Registers new vehicle (base and wheel)
base_props and wheel_props should contain def props for entity ('obj') and its item ('item')
]]
vehicles.register_vehicle = function(name, base_props, wheel_props)
minetest.register_entity(MOD_NAME .. ":" .. name .. "_base", {
vehicle_type = base_props.obj.vehicle_type,
physical = true,
mass = base_props.obj.mass or 2000, -- in kgs
collide_with_objects = true,
collisionbox = base_props.obj.bounding_box or {-0.5, 0.0, -0.5, 0.5, 1.0, 0.5},
selectionbox = base_props.obj.bounding_box or {-0.5, 0.0, -0.5, 0.5, 1.0, 0.5},
visual = base_props.obj.visual,
visual_size = base_props.obj.visual_size or {x=1, y=1, z=1},
mesh = (base_props.obj.visual == "mesh" and base_props.obj.mesh),
textures = base_props.obj.textures or {""},
use_texture_alpha = base_props.obj.use_texture_alpha,
seats = base_props.obj.seats, -- table fields: {["is_busy"] = playername, [dplayer_obj] = ObjectRef, ["pos"] = position, ["rot"] = rotation, ["getout_coords"] = coords from seat, ["type"] = ("driver" or "passenger"), ["model"] = <name>}
--ctrl_vals = base_props.ctrl_vals, -- table fields: {["move"] = float (acc_len), ["turn"] = float (degs)}
traction_force = base_props.obj.traction_force or 5000, -- in Neutons
trunk_inv = base_props.obj.trunk_inv
wheels = base_props.obj.wheels, -- table fields: {["type"] = ("front" or "rear"), ["pos"] = position, ["rot"] = rotation, ["radius"] = wheel radius}
max_speed = base_props.obj.max_speed or 25000, -- in m/s
compartments_edge = base_props.obj.compartments_edge -- rough edge between the base body and the trunk along local Z-axis (num)
stepheight = base_props.obj.stepheight or 0.5,
on_activate = function(self, staticdata, dtime_s)
self.seats = table.copy(base_props.obj.seats)
local vehpos = self.object:get_pos()
for i, seat in ipairs(self.seats) do
seat.rot = seat.rot or {x=0, y=0, z=0}
seat.radius = seat.radius or 0.5
2020-06-25 13:00:39 -07:00
end
self.wheels = {}
self.move_dir = 0 -- specifies direction of the vehicle movement (1 is forward, -1 is backward)
self.tracf = 0 -- specifies direction of the traction force and contains its value (> 0 is forward, < 0 is backward, =0 is stay)
-- Create detached inventory of the vehicle trunk
if base_props.obj.trunk_inv then
local tr_inv = base_props.obj.trunk_inv
self.trunk_inv = #self.trunk_inv > 0 and self.trunk_inv or {}
minetest.create_detached_inventory(tr_inv.name, {
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
return count
end,
allow_put = function(inv, listname, index, stack, player)
return stack:get_count()
end,
allow_take = function(inv, listname, index, stack, player)
return stack:get_count()
end
})
local inv = minetest.get_inventory({type="detached", name=tr_inv.name})
inv:set_size(tr_inv.listname, tr_inv.listsize.w*tr_inv.listsize.h)
inv:set_list(tr_inv.listname, self.trunk_inv)
end
local vehrot = self.object:get_rotation()
for i, whl in ipairs(base_props.obj.wheels) do
local whl_obj = minetest.add_entity({x=vehpos.x+whl.pos.x, y=vehpos.y+whl.pos.y, z=vehpos.z+whl.pos.z}, MOD_NAME .. ":" .. name .. "_wheel")
whl_obj:set_attach(self.object, "", whl.pos, whl.rot or {0, 0, 0})
self.wheels[i] = {object=whl_obj, type=whl.type, pos=whl.pos, rot=whl.rot or {0, 0, 0}, radius=whl.radius}
end
vehicles.set_gravity(self)
end,
on_step = function(self, dtime)
local drv_name = self.seats[vehicles.get_driver_i(self)].is_busy
if drv_name then
local player = minetest.get_player_by_name(drv_name)
local ctrls = player:get_player_control()
if ctrls.up then
minetest.debug("Going forward...")
self.move_dir = 1
self.tracf = 1
end
if ctrls.down then
minetest.debug("Going backward...")
self.move_dir = -1
self.tracf = -1
end
if not ctrls.up and not ctrls.down then
minetest.debug("Stopping...")
self.tracf = 0
end
end
local v3d_v = self.object:get_velocity()
local v2d_v = {x=v3d_v.x, y=0, z=v3d_v.z}
--minetest.debug("yaw: " .. self.object:get_yaw())
--minetest.debug("velocity: " .. dump(v3d_v))
local v2d_vl = vehicles.v2d_length(v2d_v)
if v2d_vl < 0.4 and v2d_vl > 0 and self.tracf == 0 then
minetest.debug("Stopped!")
self.move_dir = 0
end
local yaw = self.object:get_yaw()
local entity_def = minetest.registered_entities[self.name]
local tdir_v = vehicles.v2d_coords(self.tracf*entity_def.traction_force, yaw)
tdir_v.y = 0
local max_fcoef = vehicles.max_fric_coef(self)
local unit_v2d_v = vector.normalize(v2d_v)
unit_v2d_v = vehicles.check_for_nan(unit_v2d_v)
local sf_fforce = (math.abs(vehicles.gravity)*entity_def.mass)*max_fcoef*(-self.move_dir) -- surface friction force
local sf_fforce_v = vector.multiply(unit_v2d_v, sf_fforce)
sf_fforce_v = vehicles.check_for_nan(sf_fforce_v)
local air_rforce = v2d_vl^2 * vehicles.air_rfac * (-self.move_dir) -- air resistance force
local air_rforce_v = vector.multiply(unit_v2d_v, air_rforce)
air_rforce_v = vehicles.check_for_nan(air_rforce_v)
if self.move_dir == 0 then
minetest.debug("tdir_v: " .. dump(tdir_v))
minetest.debug("sf_fforce_v: " .. dump(sf_fforce_v))
minetest.debug("air_rforce_v: " .. dump(air_rforce_v))
end
--[[if self.tracf_dir ~= 0 then
minetest.debug("self.tracf_dir: " .. self.tracf_dir)
minetest.debug("sf_fforce: " .. sf_fforce)
minetest.debug("air_rforce: " .. air_rforce)
end]]
--[[minetest.debug("tdir_v: " .. dump(tdir_v))
minetest.debug("sf_fforce: " .. sf_fforce)
minetest.debug("sf_fforce_v: " .. dump(sf_fforce_v))
minetest.debug("air_rforce: " .. dump(air_rforce))
minetest.debug("air_rforce_v: " .. dump(air_rforce_v))
minetest.debug("tdir_v+sf_fforce_v: " .. dump(vector.add(tdir_v, sf_fforce_v)))
minetest.debug("(tdir_v+sf_fforce_v)+air_rforce_v: " .. dump(vector.add(vector.add(tdir_v, sf_fforce_v), air_rforce_v)))
minetest.debug("((tdir_v+sf_fforce_v)+air_rforce_v)/edef.mass: " .. dump(vector.divide(vector.add(vector.add(tdir_v, sf_fforce_v), air_rforce_v), edef.mass)))]]
local acc = vector.divide(vector.add(vector.add(tdir_v, sf_fforce_v), air_rforce_v), entity_def.mass)
acc.y = vehicles.gravity
self.object:set_acceleration(acc})
2020-06-25 13:00:39 -07:00
for i, d in ipairs(self.wheels) do
d.object:set_rotation({x=vehicles.calc_angle_vel(vehicles.v2d_length(self.object:get_velocity()), d.radius)*dtime, y=0, z=0})
--minetest.debug("wheels rotation: " .. dump(d.object:get_rotation()))
end
2020-06-25 13:00:39 -07:00
end,
on_death = function(self, killer)
for pn, f in pairs(self.showed_fspecs) do
vehicles.close_compartments_menu(self, pn)
end
for i, sdata in ipairs(self.seats) do
if sdata.is_busy then
vehicles.get_out(self, sdata.dplayer_obj:get_luaentity(), i)
end
end
for i, whl in ipairs(self.wheels) do
whl.object:remove()
end
end,
on_rightclick = function(self, clicker)
local vel = self.object:get_velocity()
if vector.length(vel) ~= 0 then
minetest.chat_send_player(clicker:get_player_name(), "The vehicle needs to be stopped at first!")
return
end
local is_player_sit = vehicles.is_player_sit(clicker)
if is_player_sit then
vehicles.show_cabin_formspec(self, clicker:get_player_name())
else
vehicles.show_compartments_menu(self, clicker:get_player_name())
end
--[[local pos = self.object:get_pos()
local range = minetest.registered_items[""].range
local ray_vec = vector.new(0, 0, range)
ray_vec = vector.rotate(ray_vec, {x=clicker:get_look_vertical(), y=clicker:get_look_horizontal(), z=0})
local ray = minetest.raycast(pos, vehicles.convert_pos_to_absolute(pos, ray_vec), true)
for pointed_thing in ray do
if pointed_thing.ref == self.object then
local compart_edge = minetest.registered_entities[self.name].compartments_edge
vehicles.show_seats_formspec(self, MOD_NAME .. ":vehicle_seats", clicker:get_player_name())]]
end
2020-06-25 13:00:39 -07:00
})
2020-06-25 13:00:39 -07:00
minetest.register_craftitem(MOD_NAME .. ":" .. name .. "_base", {
description = base_props.item.description or "",
inventory_image = base_props.item.inv_image or "",
on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type =="node" and pointed_thing.above.y >= pointed_thing.under.y then
minetest.add_entity(pointed_thing.above, itemstack:get_name())
2020-06-25 13:00:39 -07:00
end
end
2020-06-25 13:00:39 -07:00
})
minetest.register_entity(MOD_NAME .. ":" .. name .. "_wheel", {
visual_size = wheel_props.obj.visual_size or {x=1, y=1, z=1},
pointable = false,
visual = wheel_props.obj.visual,
mesh = (wheel_props.obj.visual == "mesh" and wheel_props.obj.mesh),
textures = wheel_props.obj.textures or {""},
use_texture_alpha = wheel_props.obj.use_texture_alpha
2020-06-25 13:00:39 -07:00
})
minetest.register_craftitem(MOD_NAME .. ":" .. name .. "_wheel", {
description = wheel_props.item.description or "",
inventory_image = wheel_props.item.inventory_image or ""
2020-06-25 13:00:39 -07:00
})
if base_props.obj.player_mdefs then
if base_props.obj.player_mdefs.driver then
player_api.register_model(base_props.obj.player_mdefs.driver.model_name, base_props.obj.player_mdefs.driver.def)
elseif base_props.obj.player_mdefs.passenger then
player_api.register_model(base_props.obj.player_mdefs.passenger.model_name, base_props.obj.player_mdefs.passenger.def)
end
end
end
vehicles.show_compartments_menu = function(self, playername)
local formspec = "formspec_version[3]size[6,7.5]label[2.5,0.5;Open:]button[1,1.5;4,2;seats_cabin;Seats Cabin]"
local trunk = minetest.registered_entities[self.name].trunk_inv
if trunk then
formspec = formspec .. "button[1,4.5;4,2;trunk;Trunk]"
end
vehicles.showed_fspecs[playername] = {self=self, formname=MOD_NAME .. ":compartments_menu"}
minetest.show_formspec(playername, MOD_NAME .. ":compartments_menu", formspec)
end
vehicles.show_cabin_formspec = function(self, playername)
2020-06-25 13:00:39 -07:00
local seats_n = #self.seats
local sbut_size = {x=4, y=1.5}
local pad = 0.5
local visible_cbuts_n = (seats_n <= 4 and seats_n or 4)
local scontainer_size = {x=2*0.3 + sbut_size.x, y=visible_cbuts_n*sbut_size.y + (visible_cbuts_n+1)*0.3}
local wsize_x = pad*2 + scontainer_size.x
local is_player_sit = vehicles.is_player_sit(minetest.get_player_by_name(playername))
local wsize_y = 2 + scontainer_size.y + (is_player_sit and 2.5 or pad) -- + 2.5 units for 'Get Up' button placement
local formspec = "formspec_version[3]size[" .. wsize_x .. ", " .. wsize_y .. "]" ..
"label[" .. pad + 0.2 .. "," .. pad + 0.5 .. ";" .. minetest.formspec_escape("Select a seat to sit down or press to get up:") .. "]" ..
"box[" .. pad .. ",2;" .. scontainer_size.x .. "," .. scontainer_size.y .. ";#000]" ..
"scrollbaroptions[thumbsize=1000]" ..
"scrollbar[" .. scontainer_size.x + pad .. ",2;0.3," .. scontainer_size.y .. ";vertical;vseats_scrollbar;0]" ..
"scroll_container[" .. pad .. ",2;" .. scontainer_size.x .. "," .. scontainer_size.y .. ";vseats_scrollbar;vertical;]"
local butpos_y = 0.3
for i, sdata in ipairs(self.seats) do
local i_busy = sdata.is_busy
formspec = formspec .. (i_busy and "style[seat_" .. i .. ";bgcolor=#FF0000]" or "") .. "button[0.3," .. butpos_y .. ";" .. sbut_size.x .. "," .. sbut_size.y ..
";seat_" .. i .. ";" .. minetest.formspec_escape("#" .. i .. ((i_busy and "\n(busy by " .. playername .. ")") or "")) .. "]"
butpos_y = butpos_y + sbut_size.y + 0.3
end
formspec = formspec .. "scroll_container_end[]" ..
(is_player_sit and "button[" .. wsize_x/2 - sbut_size.x/2 .. "," .. (wsize_y - (2.5/4*3)) .. ";4,1.5;get_up;" .. minetest.formspec_escape("Get up") .. "]" or "")
vehicles.showed_fspecs[playername] = {self=self, formname=MOD_NAME .. ":seats_cabin"}
minetest.show_formspec(playername, MOD_NAME .. ":seats_cabin", formspec)
2020-06-25 13:00:39 -07:00
end
vehicles.show_trunk_formspec = function(self, playername, invname, listname, inv_size)
local pad = 0.5
local slots_sp = 0.3
local wsize_x = pad*2 + slots_sp*(inv_size.w-1) + inv_size.w
local wsize_y = pad*2 + slots_sp*(inv_size.h-1) + inv_size.h + 0.7 + 4 + 3*slots_sp
local formspec = "formspec_version[3]size[" .. wsize_x .. "," .. wsize_y .. "]" ..
"list[detached:" .. listname .. ";" .. pad .. "," .. pad .. ";" .. inv_size.w .. "," .. inv_size.h .. "]" ..
"list[current_player;main;" .. pad .. "," .. (wsize_y - (4+3+slots_sp+pad)) .. ";8,4]"
2020-06-25 13:00:39 -07:00
vehicles.showed_fspecs[playername] = {self=self, formname=MOD_NAME .. ":trunk", invname=invname, listname=listname}
minetest.show_formspec(playername, MOD_NAME .. ":trunk", formspec)
end
vehicles.close_compartments_menu = function(self, playername, cabin_action)
local fd = vehicles.showed_fspecs[playername]
if fd.formname == MOD_NAME .. ":seats_cabin" then
vehicles.close_seats_formspec(self, playername, fd.formname, cabin_action, vehicles.is_player_sit(minetest.get_player_by_name(playername)))
elseif fd.formname == MOD_NAME .. ":trunk" then
vehicles.close_trunk_formspec(self, playername, fd.formname, fd.invname, fd.listname)
2020-06-25 13:00:39 -07:00
end
minetest.close_formspec(playername, MOD_NAME .. ":compartments_menu")
vehicles.showed_fspecs[playername] = nil
end
-- 'seat_id' is optional
-- 'action' is supposed what to do with the player after closing (sit or go out off the vehicle) [optional]
vehicles.close_seats_formspec = function(self, playername, formname, action, seat_id)
local player = minetest.get_player_by_name(playername)
if action == "sit" then
minetest.debug("close_seats_formspec")
local is_busy = self.seats[seat_id].is_busy
if is_busy then return end
vehicles.sit(self, player, seat_id)
elseif action == "get_up" then
minetest.debug(dump(self.seats[seat_id].dplayer_obj))
vehicles.get_out(self, self.seats[seat_id].dplayer_obj:get_luaentity(), seat_id)
local getout_coords = self.seats[seat_id].getout_coords
local yaw = self.object:get_yaw()
local pos = self.object:get_pos()
local player = minetest.get_player_by_name(playername)
local rel_getout_pos = vector.rotate(vector.add(self.seats[seat_id].pos, getout_coords), {x=0, y=self.object:get_yaw(), z=0})
minetest.debug(dump(pos))
minetest.debug(dump(rel_getout_pos))
player:set_pos(vehicles.convert_pos_to_absolute(pos, rel_getout_pos))
local rand_look = {-90, 90}
player:set_look_horizontal(yaw+rand_look[math.random(1, 2)])
2020-06-25 13:00:39 -07:00
end
minetest.close_formspec(playername, formname)
vehicles.showed_fspecs[playername] = nil
end
vehicles.close_trunk_formspec = function(self, playername, formname, inv_name, list_name)
local self = self.object:get_luaentity()
if self then
local inv = minetest.get_inventory(type="detached", name=inv_name)
self.trunk_inv = inv:get_list(list_name)
end
minetest.close_formspec(playername, formname)
vehicles.showed_fspecs[playername] = nil
end
2020-06-25 13:00:39 -07:00
vehicles.sit = function(self, player, seat_id) -- seat_id is an id of a seat table of 'self.seats'
local sel_seat = self.seats[seat_id]
local plname = player:get_player_name()
if type(sel_seat.is_busy) == "string" and sel_seat.is_busy ~= plname then
minetest.chat_send_player(plname, "Seat #" .. seat_id .. " is busy by " .. sel_seat.is_busy .. "!")
return
end
2020-06-25 13:00:39 -07:00
local cur_seat_i = vehicles.is_player_sit(player)
if cur_seat_i then
vehicles.get_out(self, self.seats[cur_seat_i].dplayer_obj:get_luaentity(), cur_seat_i)
end
sel_seat.is_busy = player:get_player_name()
local dummy_player
if sel_seat.type == "driver" then
minetest.debug("adding_dummy_driver...")
dummy_player = minetest.add_entity(vehicles.convert_pos_to_absolute(self.object:get_pos(), sel_seat.pos), MOD_NAME .. ":dummy_driver")
minetest.debug("added_dummy_driver!")
elseif sel_seat.type == "passenger" then
dummy_player = minetest.add_entity(vehicles.convert_pos_to_absolute(self.object:get_pos(), sel_seat.pos), MOD_NAME .. ":dummy_passenger")
end
2020-06-25 13:00:39 -07:00
sel_seat.dplayer_obj = dummy_player
dummy_player:set_attach(self.object, "", sel_seat.pos, {x=0, y=180, z=0})
minetest.debug("attaching_dummy_player...")
player:set_attach(dummy_player, "", {x=0, y=0, z=0}, {x=0, y=0, z=0})
minetest.debug("dummy_player_attached!")
local dplayer_self = dummy_player:get_luaentity()
dplayer_self.attached_player = player
dplayer_self.last_visual_size = player:get_properties().visual_size
player:set_properties({visual_size = vector.new(0, 0, 0)})
player:set_look_horizontal(self.object:get_yaw()+180)
2020-06-25 13:00:39 -07:00
end
vehicles.get_out = function(self, dplayer, seat_id)
if not dplayer.object or not dplayer.attached_player or not self.object:get_luaentity() then
2020-06-25 13:00:39 -07:00
return
end
dplayer.object:set_detach()
dplayer.attached_player:set_detach()
dplayer.attached_player:set_properties({visual_size = dplayer.last_visual_size})
dplayer.object:remove()
self.seats[seat_id].is_busy = nil
self.seats[seat_id].dplayer_obj = nil
2020-06-25 13:00:39 -07:00
end
vehicles.on_formspec_event = function(player, formname, fields)
local plname = player:get_player_name()
local self = vehicles.showed_fspecs[player:get_player_name()].self
if formname == MOD_NAME .. ":context_menu" then
if fields.quit then
vehicles.close_compartments_menu(self, plname)
elseif fields.
if formname ~= MOD_NAME .. ":vehicle_seats" or formname ~= MOD_NAME .. ":vehicle_trunk" then
2020-06-25 13:00:39 -07:00
return
end
local plname = player:get_player_name()
local obj = vehicles.showed_vehicle_fspecs[plname]
2020-06-25 13:00:39 -07:00
local self = obj:get_luaentity()
if self then
for i, sdata in ipairs(self.seats) do
local but_name = "seat_" .. i
if fields[but_name] then
vehicles.close_seats_formspec(self, plname, formname, "sit", i)
return true
end
2020-06-25 13:00:39 -07:00
if fields["get_up"] then
vehicles.close_seats_formspec(self, plname, formname, "get_up", i)
return true
end
2020-06-25 13:00:39 -07:00
end
if fields.quit then
if formname == MOD_NAME .. ":vehicle_seats" then
vehicles.close_seats_formspec(self, plname, formname)
return true
elseif formname == MOD_NAME .. ":vehicle_trunk" then
local edef = minetest.registered_entities[self.name]
vehicles.close_trunk_formspec(self, plname, formname, edef.trunk.name, edef.trunk.listname)
return true
end
end
2020-06-25 13:00:39 -07:00
else -- supposed that vehicle is died while the player is viewing the formspec
if formname == MOD_NAME .. ":vehicle_seats" then
vehicles.close_seats_formspec(self, plname, formname)
elseif formname == MOD_NAME .. ":vehicle_trunk" then
vehicles.close_trunk_formspec(self, plname, formname)
end
2020-06-25 13:00:39 -07:00
end
end
----------------------------------------------------------------------------
-- Helper functions
-----------------------------------------------------------------------------
-- Derives the elements from range 'i1' up to 'i2' of 't' table into new one
-- i1 and i2 can be only positive
-- NOTE: table keys can be not only integral
table.derive_elems = function(t, i1, i2)
local new_t = {}
local elem_c = 0
for k, v in pairs(t) do
elem_c = elem_c + 1
if elem_c > i2 then
return new_t
end
new_t[k] = v
end
return new_t
end
-- Checks whether t[v] is nan and if yes, replaces to zero. Returns changed table
vehicles.check_for_nan = function(t)
for k, v in pairs(t) do
if v ~= v then
t[k] = 0
end
end
return t
end
2020-06-25 13:00:39 -07:00
vehicles.is_player_sit = function(player)
local obj = player:get_attach()
if not obj then return false end
local self = obj:get_attach():get_luaentity()
2020-06-25 13:00:39 -07:00
for i, sdata in pairs(self.seats) do
if sdata.is_busy == player:get_player_name() then
return i
end
end
return false
2020-06-25 13:00:39 -07:00
end
2020-06-25 13:00:39 -07:00
-- Returns index in seats table where driver data is.
vehicles.get_driver_i = function(self)
if not self then return end
for i, sdata in ipairs(self.seats) do
if sdata.type == "driver" then
return i
end
2020-06-25 13:00:39 -07:00
end
return
end
-- Get sign of 'n' value
vehicles.get_sign = function(n)
if n == 0 then
return 0
end
return n/math.abs(n)
end
2020-06-25 13:00:39 -07:00
-- Calculates an angle speed (in rads) of the wheel
vehicles.calc_angle_vel = function(vel_l, radius)
return vel_l
2020-06-25 13:00:39 -07:00
end
-- Calculates new (relative) coords of the acceleration vector
vehicles.v2d_coords = function(a_len, yaw)
local x = -a_len * math.sin(yaw)
local z = a_len * math.cos(yaw)
return {x=x, z=z}
end
vehicles.v2d_length = function(v2d)
return math.sqrt(v2d.x^2 + v2d.z^2)
end
-- Find out max friction coefficient of nodes locating beneath the entity
vehicles.max_fric_coef = function(self)
local max_friction_coef = 0
local vehpos = self.object:get_pos()
for i, whl in ipairs(self.wheels) do
local pos = whl.object:get_pos()
pos = vehicles.convert_pos_to_absolute(vehpos, pos)
local undernode = minetest.get_node({x=pos.x, y=pos.y-whl.radius-0.1, z=pos.z})
local group = vehicles.get_node_groupname(undernode.name)
if max_friction_coef < vehicles.ngroups_friction_coefs[group] then
max_friction_coef = vehicles.ngroups_friction_coefs[group]
2020-06-25 13:00:39 -07:00
end
end
return max_friction_coef
end
-- Calculates a modulo of a friction force of the surface under the vehicle
vehicles.surface_fric_force = function(fric_coef, mass)
return fric_coef*mass*-vehicles.gravity
2020-06-25 13:00:39 -07:00
end
-- Convert the relative pos coords to absolute
vehicles.convert_pos_to_absolute = function(origin, pos)
return {x=origin.x+pos.x, y=origin.y+pos.y, z=origin.z+pos.z}
end
-- Convert the absolute pos coords to relative (relatively to 'origin')
vehicles.convert_pos_to_relative = function(origin, pos)
return {x=pos.x-origin.x, y=pos.y-origin.y, z=pos.z-origin.z}
end
-- Returns a node group that associated with its certain type (e.g. sand/desert sand are "sand" group, snow block/snow with grass are "snowy" group)
vehicles.get_node_groupname = function(name)
local groups = minetest.registered_nodes[name].groups
--minetest.debug("nodename:" .. name)
--minetest.debug("nodegroups:" .. dump(groups))
for group, coef in pairs(vehicles.ngroups_friction_coefs) do
2020-06-25 13:00:39 -07:00
if groups[group] then
return group
end
end
return "default"
end
-- Calculates a modulo of an air resistance force (only along horizontal plane currently)
vehicles.air_resist_force = function(v_l)
return vehicles.air_rfac * math.abs(v_l)^2
2020-06-25 13:00:39 -07:00
end
-----------------------------------------------------------------------------
-- Callback Registrations
-----------------------------------------------------------------------------
minetest.register_on_player_receive_fields(vehicles.on_formspec_event)
minetest.register_on_leaveplayer(function(obj, timed_out)
local is_player_sit = vehicles.is_player_sit(obj:get_luaentity())
if is_player_sit then
local self = obj:get_attach():get_attach():get_luaentity()
vehicles.get_out(self, self.dplayer_obj:get_luaentity(), is_player_sit)
2020-06-25 13:00:39 -07:00
end
end)
2020-06-25 13:00:39 -07:00