helicopter/init.lua
2014-03-09 11:59:30 +00:00

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',''},
}
})