automobiles_pck/automobiles_lib/init.lua

452 lines
14 KiB
Lua
Executable File

-- Minetest 5.4.1 : automobiles
automobiles_lib = {}
automobiles_lib.fuel = {['biofuel:biofuel'] = 1,['biofuel:bottle_fuel'] = 1,
['biofuel:phial_fuel'] = 0.25, ['biofuel:fuel_can'] = 10}
automobiles_lib.gravity = 9.8
automobiles_lib.is_creative = minetest.settings:get_bool("creative_mode", false)
--cars colors
automobiles_lib.colors ={
black='#2b2b2b',
blue='#0063b0',
brown='#8c5922',
cyan='#07B6BC',
dark_green='#567a42',
dark_grey='#6d6d6d',
green='#4ee34c',
grey='#9f9f9f',
magenta='#ff0098',
orange='#ff8b0e',
pink='#ff62c6',
red='#dc1818',
violet='#a437ff',
white='#FFFFFF',
yellow='#ffe400',
}
--
-- helpers and co.
--
function automobiles_lib.get_hipotenuse_value(point1, point2)
return math.sqrt((point1.x - point2.x) ^ 2 + (point1.y - point2.y) ^ 2 + (point1.z - point2.z) ^ 2)
end
function automobiles_lib.dot(v1,v2)
return (v1.x*v2.x)+(v1.y*v2.y)+(v1.z*v2.z)
end
function automobiles_lib.sign(n)
return n>=0 and 1 or -1
end
function automobiles_lib.minmax(v,m)
return math.min(math.abs(v),m)*minekart.sign(v)
end
--returns 0 for old, 1 for new
function automobiles_lib.detect_player_api(player)
local player_proterties = player:get_properties()
local mesh = "character.b3d"
if player_proterties.mesh == mesh or player_proterties.mesh == "max.b3d" then
local models = player_api.registered_models
local character = models[mesh]
if character then
if character.animations.sit.eye_height then
return 1
else
return 0
end
end
end
return 0
end
-- attach player
function automobiles_lib.attach_driver(self, player)
local name = player:get_player_name()
self.driver_name = name
-- attach the driver
player:set_attach(self.driver_seat, "", {x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0})
local eye_y = -4
if automobiles_lib.detect_player_api(player) == 1 then
eye_y = 2.5
end
player:set_eye_offset({x = 0, y = eye_y, z = 0}, {x = 0, y = eye_y, z = -30})
player_api.player_attached[name] = true
-- make the driver sit
minetest.after(0.2, function()
player = minetest.get_player_by_name(name)
if player then
--player:set_properties({physical=false})
player_api.set_animation(player, "sit")
--apply_physics_override(player, {speed=0,gravity=0,jump=0})
end
end)
end
function automobiles_lib.dettach_driver(self, player)
local name = self.driver_name
--self._engine_running = false
-- driver clicked the object => driver gets off the vehicle
self.driver_name = nil
if self._engine_running then
self._engine_running = false
end
-- sound and animation
if self.sound_handle then
minetest.sound_stop(self.sound_handle)
self.sound_handle = nil
end
-- detach the player
if player then
--automobiles_lib.remove_hud(player)
--player:set_properties({physical=true})
player:set_detach()
player_api.player_attached[name] = nil
player:set_eye_offset({x=0,y=0,z=0},{x=0,y=0,z=0})
player_api.set_animation(player, "stand")
end
self.driver = nil
end
-- attach passenger
function automobiles_lib.attach_pax(self, player, onside)
local onside = onside or false
local name = player:get_player_name()
if onside == true then
if self._passenger == nil then
self._passenger = name
-- attach the driver
player:set_attach(self.passenger_seat, "", {x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0})
local eye_y = -4
if automobiles_lib.detect_player_api(player) == 1 then
eye_y = 2.5
end
player:set_eye_offset({x = 0, y = eye_y, z = 0}, {x = 0, y = eye_y, z = -30})
player_api.player_attached[name] = true
-- make the driver sit
minetest.after(0.2, function()
player = minetest.get_player_by_name(name)
if player then
--player:set_properties({physical=false})
player_api.set_animation(player, "sit")
--apply_physics_override(player, {speed=0,gravity=0,jump=0})
end
end)
end
else
--randomize the seat
--[[local t = {1,2,3,4,5,6,7,8,9,10}
for i = 1, #t*2 do
local a = math.random(#t)
local b = math.random(#t)
t[a],t[b] = t[b],t[a]
end
--for i = 1,10,1 do
for k,v in ipairs(t) do
i = t[k]
if self._passengers[i] == nil then
--minetest.chat_send_all(self.driver_name)
self._passengers[i] = name
player:set_attach(self._passengers_base[i], "", {x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0})
if i > 2 then
player:set_eye_offset({x = 0, y = -4, z = 2}, {x = 0, y = 3, z = -30})
else
player:set_eye_offset({x = 0, y = -4, z = 0}, {x = 0, y = 3, z = -30})
end
player_api.player_attached[name] = true
-- make the driver sit
minetest.after(0.2, function()
player = minetest.get_player_by_name(name)
if player then
player_api.set_animation(player, "sit")
--apply_physics_override(player, {speed=0,gravity=0,jump=0})
end
end)
break
end
end]]--
end
end
function automobiles_lib.dettach_pax(self, player)
local name = player:get_player_name() --self._passenger
-- passenger clicked the object => driver gets off the vehicle
if self._passenger == name then
self._passenger = nil
else
--[[for i = 10,1,-1
do
if self._passengers[i] == name then
self._passengers[i] = nil
break
end
end]]--
end
-- detach the player
if player then
--player:set_properties({physical=true})
player:set_detach()
player_api.player_attached[name] = nil
player_api.set_animation(player, "stand")
player:set_eye_offset({x=0,y=0,z=0},{x=0,y=0,z=0})
--remove_physics_override(player, {speed=1,gravity=1,jump=1})
end
end
function automobiles_lib.get_gauge_angle(value, initial_angle)
initial_angle = initial_angle or 90
local angle = value * 18
angle = angle - initial_angle
angle = angle * -1
return angle
end
function automobiles_lib.setText(self, vehicle_name)
local properties = self.object:get_properties()
local formatted = ""
if self.hp_max then
formatted = " Current hp: " .. string.format(
"%.2f", self.hp_max
)
end
if properties then
properties.infotext = "Nice ".. vehicle_name .." of " .. self.owner .. "." .. formatted
self.object:set_properties(properties)
end
end
function automobiles_lib.get_xz_from_hipotenuse(orig_x, orig_z, yaw, distance)
--cara, o minetest é bizarro, ele considera o eixo no sentido ANTI-HORÁRIO... Então pra equação funcionar, subtrair o angulo de 360 antes
yaw = math.rad(360) - yaw
local z = (math.cos(yaw)*distance) + orig_z
local x = (math.sin(yaw)*distance) + orig_x
return x, z
end
function automobiles_lib.remove_light(self)
if self._light_old_pos then
--force the remotion of the last light
minetest.add_node(self._light_old_pos, {name="air"})
self._light_old_pos = nil
end
end
function automobiles_lib.swap_node(self, pos)
local target_pos = pos
local have_air = false
local node = nil
local count = 0
while have_air == false and count <= 3 do
node = minetest.get_node(target_pos)
if node.name == "air" then
have_air = true
break
end
count = count + 1
target_pos.y = target_pos.y + 1
end
if have_air then
minetest.set_node(target_pos, {name='automobiles_lib:light'})
automobiles_lib.remove_light(self)
self._light_old_pos = target_pos
--remove after one second
--[[minetest.after(1,function(target_pos)
local node = minetest.get_node_or_nil(target_pos)
if node and node.name == "automobiles_lib:light" then
minetest.swap_node(target_pos, {name="air"})
end
end, target_pos)]]--
return true
end
return false
end
function automobiles_lib.put_light(self)
local pos = self.object:get_pos()
pos.y = pos.y + 1
local yaw = self.object:get_yaw()
local lx, lz = automobiles_lib.get_xz_from_hipotenuse(pos.x, pos.z, yaw, 10)
local light_pos = {x=lx, y=pos.y, z=lz}
local cast = minetest.raycast(pos, light_pos, false, false)
local thing = cast:next()
local was_set = false
while thing do
if thing.type == "node" then
local ipos = thing.intersection_point
if ipos then
was_set = automobiles_lib.swap_node(self, ipos)
end
end
thing = cast:next()
end
if was_set == false then
local n = minetest.get_node_or_nil(light_pos)
if n and n.name == 'air' then
automobiles_lib.swap_node(self, light_pos)
end
end
--[[local n = minetest.get_node_or_nil(light_pos)
--minetest.chat_send_player(name, n.name)
if n and n.name == 'air' then
minetest.set_node(pos, {name='automobiles_lib:light'})
--local timer = minetest.get_node_timer(pos)
--timer:set(10, 0)
minetest.after(0.3,function(pos)
local node = minetest.get_node_or_nil(pos)
if node and node.name == "automobiles_lib:light" then
minetest.swap_node(pos, {name="air"})
end
end, pos)
end]]--
end
minetest.register_node("automobiles_lib:light", {
drawtype = "glasslike",
tile_images = {"automobiles_light.png"},
inventory_image = minetest.inventorycube("automobiles_light.png"),
paramtype = "light",
walkable = false,
is_ground_content = true,
light_propagates = true,
sunlight_propagates = true,
light_source = 14,
selection_box = {
type = "fixed",
fixed = {0, 0, 0, 0, 0, 0},
},
})
function automobiles_lib.set_paint(self, puncher, itmstck)
local item_name = ""
if itmstck then item_name = itmstck:get_name() end
if item_name == "automobiles_lib:painter" or item_name == "bike:painter" then
--painting with bike painter
local meta = itmstck:get_meta()
local colstr = meta:get_string("paint_color")
automobiles_lib.paint(self, colstr)
return true
else
--painting with dyes
local split = string.split(item_name, ":")
local color, indx, _
if split[1] then _,indx = split[1]:find('dye') end
if indx then
for clr,_ in pairs(automobiles_lib.colors) do
local _,x = split[2]:find(clr)
if x then color = clr end
end
--lets paint!!!!
--local color = item_name:sub(indx+1)
local colstr = automobiles_lib.colors[color]
--minetest.chat_send_all(color ..' '.. dump(colstr))
if colstr then
automobiles_lib.paint(self, colstr)
itmstck:set_count(itmstck:get_count()-1)
puncher:set_wielded_item(itmstck)
return true
end
-- end painting
end
end
return false
end
--painting
function automobiles_lib.paint(self, colstr)
if colstr then
self._color = colstr
local l_textures = self.initial_properties.textures
for _, texture in ipairs(l_textures) do
local indx = texture:find('automobiles_painting.png')
if indx then
l_textures[_] = "automobiles_painting.png^[multiply:".. colstr
end
end
self.object:set_properties({textures=l_textures})
end
end
dofile(minetest.get_modpath("automobiles_lib") .. DIR_DELIM .. "custom_physics.lua")
dofile(minetest.get_modpath("automobiles_lib") .. DIR_DELIM .. "control.lua")
dofile(minetest.get_modpath("automobiles_lib") .. DIR_DELIM .. "fuel_management.lua")
dofile(minetest.get_modpath("automobiles_lib") .. DIR_DELIM .. "ground_detection.lua")
dofile(minetest.get_modpath("automobiles_lib") .. DIR_DELIM .. "painter.lua")
dofile(minetest.get_modpath("automobiles_lib") .. DIR_DELIM .. "inventory_management.lua")
-- engine
minetest.register_craftitem("automobiles_lib:engine",{
description = "Car engine",
inventory_image = "automobiles_engine.png",
})
-- engine
minetest.register_craftitem("automobiles_lib:wheel",{
description = "Car wheel",
inventory_image = "automobiles_wheel_icon.png",
})
if minetest.get_modpath("default") then
minetest.register_craft({
output = "automobiles_lib:engine",
recipe = {
{"default:steel_ingot","default:steel_ingot","default:steel_ingot"},
{"default:steelblock","default:mese_block", "default:steelblock"},
}
})
minetest.register_craft({
output = "automobiles_lib:wheel",
recipe = {
{"default:tin_ingot", "default:steel_ingot", "default:tin_ingot"},
{"default:steel_ingot","default:steelblock", "default:steel_ingot"},
{"default:tin_ingot", "default:steel_ingot", "default:tin_ingot"},
}
})
end
minetest.register_entity('automobiles_lib:wheel',{
initial_properties = {
physical = false,
collide_with_objects=false,
pointable=false,
visual = "mesh",
mesh = "automobiles_wheel.b3d",
backface_culling = false,
textures = {"automobiles_black.png", "automobiles_metal.png"},
},
on_activate = function(self,std)
self.sdata = minetest.deserialize(std) or {}
if self.sdata.remove then self.object:remove() end
end,
get_staticdata=function(self)
self.sdata.remove=true
return minetest.serialize(self.sdata)
end,
})