350 lines
8.1 KiB
Lua
350 lines
8.1 KiB
Lua
|
|
--
|
|
-- Helper functions
|
|
--
|
|
|
|
local function get_sign(i)
|
|
if i == 0 then
|
|
return 0
|
|
else
|
|
return i/math.abs(i)
|
|
end
|
|
end
|
|
|
|
--
|
|
-- Heli entity
|
|
--
|
|
|
|
local heli = {
|
|
physical = true,
|
|
collisionbox = {-1,-0.6,-1, 1,0.3,1},
|
|
|
|
collide_with_objects = true,
|
|
weight = 5,
|
|
|
|
visual = "mesh",
|
|
mesh = "root.x",
|
|
--Player
|
|
pilot = nil,
|
|
|
|
--Heli mesh
|
|
model = nil,
|
|
|
|
--In progress
|
|
motor = nil,
|
|
|
|
--Rotation
|
|
yaw=0,
|
|
|
|
--Speeds
|
|
vx=0,
|
|
vy=0,
|
|
vz=0,
|
|
|
|
-- Current yaw speed -1 to 1
|
|
yawspeed = 0,
|
|
|
|
-- Current 'thrust' setting, -1 to 1
|
|
thrust = 0,
|
|
sidethrust = 0
|
|
|
|
}
|
|
local heliModel = {
|
|
visual = "mesh",
|
|
mesh = "heli.x",
|
|
textures = {"blades.png","blades.png","heli.png","Glass.png"},
|
|
}
|
|
local motor = {
|
|
physical = true,
|
|
collisionbox = {-2,0.5,-1, 1,1,1},
|
|
visual = "mesh",
|
|
mesh = "motor.x",
|
|
textures = {"motor.png"},
|
|
}
|
|
|
|
function heli:on_rightclick(clicker)
|
|
if not clicker or not clicker:is_player() then
|
|
return
|
|
end
|
|
if self.pilot and clicker == self.pilot then
|
|
self.pilot = nil
|
|
clicker:set_detach()
|
|
self.model:set_animation({x=0,y=1},0, 0)
|
|
elseif not self.pilot then
|
|
self.model:set_animation({x=0,y=10},10, 0)
|
|
self.pilot = clicker
|
|
clicker:set_attach(self.object, "", {x=0,y=0,z=-10}, {x=0,y=0,z=0})
|
|
clicker:set_look_yaw(self.object:getyaw() - math.pi / 2)
|
|
end
|
|
end
|
|
|
|
function heliModel:on_activate(staticdata, dtime_s)
|
|
self.object:set_armor_groups({immortal=1})
|
|
local is_attached = false
|
|
for _,object in ipairs(minetest.env:get_objects_inside_radius(self.object:getpos(), 2)) do
|
|
if object and object:get_luaentity() and object:get_luaentity().name=="helicopter:heli" then
|
|
if object:get_luaentity().model == nil then
|
|
object:get_luaentity().model = self
|
|
end
|
|
if object:get_luaentity().model == self then
|
|
is_attached = true
|
|
end
|
|
end
|
|
end
|
|
if is_attached == false then
|
|
self.object:remove()
|
|
end
|
|
|
|
end
|
|
|
|
function heli:on_activate(staticdata, dtime_s)
|
|
self.object:set_armor_groups({immortal=1})
|
|
if not self.model then
|
|
self.model = minetest.env:add_entity(self.object:getpos(), "helicopter:heliModel")
|
|
self.model:set_attach(self.object, "Root", {x=0,y=0,z=2}, {x=-90,y=0,z=0})
|
|
end
|
|
end
|
|
|
|
function heli:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
|
|
if self.pilot then return end
|
|
if puncher and puncher:is_player() then
|
|
if self.model ~= nil then
|
|
self.model:remove()
|
|
end
|
|
self.object:remove()
|
|
puncher:get_inventory():add_item("main", "helicopter:heli")
|
|
end
|
|
end
|
|
function heliModel:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
|
|
self.object:remove()
|
|
end
|
|
function heli:on_step(dtime)
|
|
--Prevent shaking heli while sitting in it
|
|
|
|
if self.pilot then
|
|
|
|
local ctrl = self.pilot:get_player_control()
|
|
|
|
if ctrl.up then
|
|
self.thrust = self.thrust + 0.25 * dtime
|
|
if self.thrust > 1 then
|
|
self.thrust = 1
|
|
end
|
|
end
|
|
if ctrl.down then
|
|
self.thrust = self.thrust - 0.25 * dtime
|
|
if self.thrust < -1 then
|
|
self.thrust = -1
|
|
end
|
|
end
|
|
if not ctrl.up and not ctrl.down then
|
|
local s = get_sign(self.thrust)
|
|
self.thrust = self.thrust - self.thrust * dtime
|
|
if math.abs(self.thrust) < 0.1 or get_sign(self.thrust) ~= s then
|
|
self.thrust = 0
|
|
end
|
|
end
|
|
if ctrl.aux1 then
|
|
if ctrl.right then
|
|
self.sidethrust = self.sidethrust + 0.25 * dtime
|
|
if self.sidethrust > 1 then
|
|
self.sidethrust = 1
|
|
end
|
|
end
|
|
if ctrl.down then
|
|
self.sidethrust = self.sidethrust - 0.25 * dtime
|
|
if self.sidethrust < -1 then
|
|
self.sidethrust = -1
|
|
end
|
|
end
|
|
else
|
|
if ctrl.left then
|
|
self.yawspeed = self.yawspeed - 0.25 * dtime
|
|
if self.yawspeed < -1 then
|
|
self.yawspeed = -1
|
|
end
|
|
end
|
|
if ctrl.right then
|
|
self.yawspeed = self.yawspeed + 0.25 * dtime
|
|
if self.yawspeed > 1 then
|
|
self.yawspeed = 1
|
|
end
|
|
end
|
|
end
|
|
if self.yawspeed ~= 0 and not ctrl.left and not ctrl.right then
|
|
local s = get_sign(self.yawspeed)
|
|
self.yawspeed = self.yawspeed - self.yawspeed * dtime
|
|
if math.abs(self.yawspeed) < 0.1 or get_sign(self.yawspeed) ~= s then
|
|
self.yawspeed = 0
|
|
end
|
|
end
|
|
if not ctrl.aux1 or (not ctrl.left and not ctrl.right) then
|
|
local s = get_sign(self.sidethrust)
|
|
self.sidethrust = self.sidethrust - self.sidethrust * dtime
|
|
if math.abs(self.sidethrust) < 0.1 or get_sign(self.sidethrust) ~= s then
|
|
self.sidethrust = 0
|
|
end
|
|
end
|
|
|
|
if ctrl.jump then
|
|
self.vy = self.vy + 10 * dtime
|
|
end
|
|
if ctrl.sneak then
|
|
self.vy = self.vy - 10 * dtime
|
|
end
|
|
|
|
local c = math.pi * 2
|
|
|
|
local yawdelta = math.pi / 8 * self.yawspeed * dtime
|
|
self.yaw = self.yaw - yawdelta
|
|
while self.yaw > c do self.yaw = self.yaw - c end
|
|
while self.yaw < 0 do self.yaw = self.yaw + c end
|
|
self.vx = self.vx + math.cos(self.yaw) * self.thrust * 10 * dtime
|
|
self.vz = self.vz + math.sin(self.yaw) * self.thrust * 10 * dtime
|
|
self.vx = self.vx - math.sin(math.pi + self.yaw) * self.sidethrust * 10 * dtime
|
|
self.vz = self.vz - math.cos(self.yaw) * self.sidethrust * 10 * dtime
|
|
|
|
if yawdelta ~= 0 then
|
|
local curyaw = self.pilot:get_look_yaw()
|
|
if curyaw then
|
|
-- Correct for api insanity
|
|
curyaw = curyaw - math.pi / 2
|
|
curyaw = curyaw - yawdelta
|
|
while curyaw > c do curyaw = curyaw - c end
|
|
while curyaw < 0 do curyaw = curyaw + c end
|
|
self.pilot:set_look_yaw(curyaw)
|
|
end
|
|
end
|
|
|
|
if self.vy ~= 0 then
|
|
vdelta = get_sign(self.vy) * (self.vy * self.vy * dtime * 0.8)
|
|
if vdelta > math.abs(self.vy) then
|
|
vdelta = math.abs(self.vy)
|
|
end
|
|
local s = get_sign(self.vy)
|
|
self.vy = self.vy - vdelta
|
|
if s ~= get_sign(self.vy) then
|
|
self.vy = 0
|
|
end
|
|
if math.abs(self.vy) < 0.3 then
|
|
self.vy = 0
|
|
end
|
|
end
|
|
|
|
else
|
|
self.vy = -9.81
|
|
end
|
|
|
|
-- Drag and speed limit. Convert to speed and unit vector for the
|
|
-- duration of these calculations, and go back to a velocity vector
|
|
-- afterwards.
|
|
local speed = math.sqrt(self.vx * self.vx + self.vz * self.vz)
|
|
if speed ~= 0 then
|
|
local ux = self.vx / speed
|
|
local uz = self.vz / speed
|
|
local sdelta = (speed * speed * dtime * 0.3)
|
|
if sdelta > speed then
|
|
sdelta = speed
|
|
end
|
|
speed = speed - sdelta
|
|
if speed < 0.5 then
|
|
speed = 0
|
|
end
|
|
self.vx = ux * speed
|
|
self.vz = uz * speed
|
|
end
|
|
|
|
--Model rotation
|
|
local attachpos
|
|
if self.pilot then
|
|
local pilotpos = self.pilot:getpos()
|
|
if pilotpos then
|
|
attachpos = {
|
|
x=-(pilotpos.x-self.object:getpos().x)*dtime,
|
|
y=-(pilotpos.y-self.object:getpos().y)*dtime,
|
|
z=-(pilotpos.z-self.object:getpos().z)*dtime
|
|
}
|
|
end
|
|
end
|
|
--if not attachpos then
|
|
attachpos = {x=0, y=0, z=0}
|
|
--end
|
|
self.model:set_attach(self.object,"Root", attachpos,
|
|
{x=-90, y=0, z=self.yaw*57})
|
|
|
|
self.object:setvelocity({x=self.vx, y=self.vy, z=self.vz})
|
|
|
|
end
|
|
|
|
--
|
|
--Registration
|
|
--
|
|
|
|
minetest.register_entity("helicopter:heli", heli)
|
|
minetest.register_entity("helicopter:heliModel", heliModel)
|
|
minetest.register_entity("helicopter:motor", motor)
|
|
|
|
--
|
|
--Craft items
|
|
--
|
|
|
|
--Blades
|
|
minetest.register_craftitem("helicopter:blades",{
|
|
description = "Helicopter Blades",
|
|
inventory_image = "blades_inv.png",
|
|
wield_image = "blades_inv.png",
|
|
})
|
|
--Cabin
|
|
minetest.register_craftitem("helicopter:cabin",{
|
|
description = "Helicopter Cabin",
|
|
inventory_image = "cabin_inv.png",
|
|
wield_image = "cabin_inv.png",
|
|
})
|
|
--Heli
|
|
minetest.register_craftitem("helicopter:heli", {
|
|
description = "Helicopter",
|
|
inventory_image = "heli_inv.png",
|
|
wield_image = "heli_inv.png",
|
|
wield_scale = {x=1, y=1, z=1},
|
|
liquids_pointable = false,
|
|
|
|
on_place = function(itemstack, placer, pointed_thing)
|
|
if pointed_thing.type ~= "node" then
|
|
return
|
|
end
|
|
pointed_thing.under.y = pointed_thing.under.y+1
|
|
minetest.env:add_entity(pointed_thing.under, "helicopter:heli")
|
|
itemstack:take_item()
|
|
return itemstack
|
|
end,
|
|
})
|
|
|
|
--
|
|
--Craft
|
|
--
|
|
|
|
minetest.register_craft({
|
|
output = 'helicopter:blades',
|
|
recipe = {
|
|
{'', 'default:steel_ingot', ''},
|
|
{'default:steel_ingot', 'group:stick', 'default:steel_ingot'},
|
|
{'', 'default:steel_ingot', ''},
|
|
}
|
|
})
|
|
minetest.register_craft({
|
|
output = 'helicopter:cabin',
|
|
recipe = {
|
|
{'', 'group:wood', ''},
|
|
{'group:wood', 'default:mese_crystal','default:glass'},
|
|
{'group:wood','group:wood','group:wood'},
|
|
}
|
|
})
|
|
minetest.register_craft({
|
|
output = 'helicopter:heli',
|
|
recipe = {
|
|
{'', 'helicopter:blades', ''},
|
|
{'helicopter:blades', 'helicopter:cabin',''},
|
|
}
|
|
})
|
|
|