mirror of
https://github.com/APercy/airutils.git
synced 2025-03-15 08:01:22 +00:00
initial lib_copter
This commit is contained in:
parent
30c7525103
commit
e12f018879
8 changed files with 660 additions and 72 deletions
124
init.lua
124
init.lua
|
@ -55,6 +55,7 @@ dofile(minetest.get_modpath("airutils") .. DIR_DELIM .. "inventory_management.lu
|
|||
dofile(minetest.get_modpath("airutils") .. DIR_DELIM .. "light.lua")
|
||||
dofile(minetest.get_modpath("airutils") .. DIR_DELIM .. "physics_lib.lua")
|
||||
dofile(minetest.get_modpath("airutils") .. DIR_DELIM .. "lib_planes" .. DIR_DELIM .. "init.lua")
|
||||
dofile(minetest.get_modpath("airutils") .. DIR_DELIM .. "lib_copter" .. DIR_DELIM .. "init.lua")
|
||||
dofile(minetest.get_modpath("airutils") .. DIR_DELIM .. "texture_management.lua")
|
||||
|
||||
local is_biofuel_installed = false
|
||||
|
@ -228,6 +229,7 @@ end
|
|||
function airutils.get_ground_effect_lift(self, curr_pos, lift, wingspan)
|
||||
local half_wingspan = wingspan/2
|
||||
local lower_collision = self.initial_properties.collisionbox[2]
|
||||
if not self._ground_effect_ammount_percent then self._ground_effect_ammount_percent = 0.5 end
|
||||
local initial_pos = {x=curr_pos.x, y=curr_pos.y + lower_collision, z=curr_pos.z} --lets make my own table to avoid interferences
|
||||
|
||||
if self._extra_lift == nil then self._extra_lift = 0 end
|
||||
|
@ -254,7 +256,7 @@ function airutils.get_ground_effect_lift(self, curr_pos, lift, wingspan)
|
|||
end
|
||||
|
||||
local lift_factor = ((effect_factor) * 1) / (half_wingspan) --agora isso é um percentual
|
||||
local max_extra_lift_percent = 0.5 * lift --e aqui o maximo extra de sustentação
|
||||
local max_extra_lift_percent = self._ground_effect_ammount_percent * lift --e aqui o maximo extra de sustentação
|
||||
local extra_lift = max_extra_lift_percent * lift_factor
|
||||
self._extra_lift = extra_lift
|
||||
end
|
||||
|
@ -271,18 +273,23 @@ end
|
|||
-- lift: lift factor (very simplified)
|
||||
-- max_height: the max ceilling for the airplane
|
||||
-- wingspan: for ground effect calculation
|
||||
function airutils.getLiftAccel(self, velocity, accel, longit_speed, roll, curr_pos, lift, max_height, wingspan)
|
||||
--add wind to the lift calcs
|
||||
local wind = airutils.get_wind(curr_pos, 5)
|
||||
local accel_wind = vector.subtract(accel, wind) --why? because I need to fake more speed when against the wind to gain lift
|
||||
local vel_wind = vector.multiply(accel_wind, self.dtime)
|
||||
local new_velocity = vector.add(velocity, vel_wind)
|
||||
function airutils.getLiftAccel(self, velocity, accel, longit_speed, roll, curr_pos, in_lift, max_height, wingspan)
|
||||
local new_velocity = vector.new(velocity)
|
||||
if not self._min_collective then --ignore if it is an helicopter
|
||||
--add wind to the lift calcs
|
||||
local wind = airutils.get_wind(curr_pos, 5)
|
||||
local accel_wind = vector.subtract(accel, wind) --why? because I need to fake more speed when against the wind to gain lift
|
||||
local vel_wind = vector.multiply(accel_wind, self.dtime)
|
||||
new_velocity = vector.add(new_velocity, vel_wind)
|
||||
end
|
||||
|
||||
if longit_speed == nil then longit_speed = 0 end
|
||||
wingspan = wingspan or 10
|
||||
local ground_effect_extra_lift = airutils.get_ground_effect_lift(self, curr_pos, lift, wingspan)
|
||||
--minetest.chat_send_all('lift: '.. lift ..' - extra lift: '.. ground_effect_extra_lift)
|
||||
lift = lift + ground_effect_extra_lift
|
||||
local lift = in_lift
|
||||
if not airutils.ground_effect_is_disabled then
|
||||
local ground_effect_extra_lift = airutils.get_ground_effect_lift(self, curr_pos, in_lift, wingspan)
|
||||
lift = lift + ground_effect_extra_lift
|
||||
end
|
||||
|
||||
--lift calculations
|
||||
-----------------------------------------------------------
|
||||
|
@ -295,43 +302,45 @@ function airutils.getLiftAccel(self, velocity, accel, longit_speed, roll, curr_p
|
|||
if self._min_speed then min_speed = self._min_speed end
|
||||
min_speed = min_speed / 2
|
||||
|
||||
--if longit_speed > min_speed then
|
||||
local striped_velocity = {x=velocity.x, y=velocity.y, z=velocity.z}
|
||||
local cut_velocity = (min_speed * 1)/longit_speed
|
||||
striped_velocity.x = striped_velocity.x - (striped_velocity.x * cut_velocity)
|
||||
striped_velocity.z = striped_velocity.z - (striped_velocity.z * cut_velocity)
|
||||
local striped_velocity = vector.new(velocity)
|
||||
local cut_velocity = (min_speed * 1)/longit_speed
|
||||
striped_velocity.x = striped_velocity.x - (striped_velocity.x * cut_velocity)
|
||||
striped_velocity.z = striped_velocity.z - (striped_velocity.z * cut_velocity)
|
||||
|
||||
local angle_of_attack = math.rad(self._angle_of_attack + wing_config)
|
||||
--local acc = 0.8
|
||||
local daoa = math.deg(angle_of_attack)
|
||||
--minetest.chat_send_all(dump(daoa))
|
||||
local angle_of_attack = math.rad(self._angle_of_attack + wing_config)
|
||||
--local acc = 0.8
|
||||
local daoa = math.deg(angle_of_attack)
|
||||
--minetest.chat_send_all(dump(daoa))
|
||||
|
||||
--to decrease the lift coefficient at hight altitudes
|
||||
local curr_percent_height = (100 - ((curr_pos.y * 100) / max_height))/100
|
||||
--to decrease the lift coefficient at hight altitudes
|
||||
local curr_percent_height = (100 - ((curr_pos.y * 100) / max_height))/100
|
||||
|
||||
local rotation=self.object:get_rotation()
|
||||
local vrot = airutils.dir_to_rot(velocity,rotation)
|
||||
local rotation=self.object:get_rotation()
|
||||
local vrot = airutils.dir_to_rot(velocity,rotation)
|
||||
|
||||
local hpitch,hyaw = pitchroll2pitchyaw(angle_of_attack,roll)
|
||||
local hpitch,hyaw = pitchroll2pitchyaw(angle_of_attack,roll)
|
||||
|
||||
local hrot = {x=vrot.x+hpitch,y=vrot.y-hyaw,z=roll}
|
||||
local hdir = airutils.rot_to_dir(hrot) --(hrot)
|
||||
local cross = vector.cross(velocity,hdir)
|
||||
local lift_dir = vector.normalize(vector.cross(cross,hdir))
|
||||
local hrot = {x=vrot.x+hpitch,y=vrot.y-hyaw,z=roll}
|
||||
local hdir = airutils.rot_to_dir(hrot) --(hrot)
|
||||
local cross = vector.cross(velocity,hdir)
|
||||
local lift_dir = vector.normalize(vector.cross(cross,hdir))
|
||||
|
||||
local lift_coefficient = (0.24*math.abs(daoa)*(1/(0.025*daoa+3))^4*math.sign(daoa))
|
||||
local lift_val = math.abs((lift*(vector.length(striped_velocity)^2)*lift_coefficient)*curr_percent_height)
|
||||
if lift_val < 1 then lift_val = 1 end -- hipotetical aerodinamic wing will have no "lift" for down
|
||||
--minetest.chat_send_all('lift: '.. lift_val)
|
||||
local lift_coefficient = (0.24*math.abs(daoa)*(1/(0.025*daoa+3))^4*math.sign(daoa))
|
||||
local lift_val = math.abs((lift*(vector.length(striped_velocity)^2)*lift_coefficient)*curr_percent_height)
|
||||
if lift_val < 1 then lift_val = 1 end -- hipotetical aerodinamic wing will have no "lift" for down
|
||||
|
||||
local lift_acc = vector.multiply(lift_dir,lift_val)
|
||||
--lift_acc=vector.add(vector.multiply(minetest.yaw_to_dir(rotation.y),acc),lift_acc)
|
||||
if airutils.show_lift then
|
||||
--yes, I limited it to singleplayer only, it is just for dev purposes
|
||||
minetest.chat_send_player("singleplayer",core.colorize('#ffff00', " >>> lift: "..lift_val))
|
||||
end
|
||||
|
||||
retval = vector.add(retval,lift_acc)
|
||||
--end
|
||||
local lift_acc = vector.multiply(lift_dir,lift_val)
|
||||
--lift_acc=vector.add(vector.multiply(minetest.yaw_to_dir(rotation.y),acc),lift_acc)
|
||||
|
||||
retval = vector.add(retval,lift_acc)
|
||||
-----------------------------------------------------------
|
||||
-- end lift
|
||||
|
||||
|
||||
return retval
|
||||
end
|
||||
|
||||
|
@ -546,3 +555,44 @@ minetest.register_chatcommand("eject_from_plane", {
|
|||
end
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("ground_effect", {
|
||||
params = "<on/off>",
|
||||
description = "Enables/disables the ground effect (for debug purposes)",
|
||||
privs = {interact=true},
|
||||
func = function(name, param)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if minetest.check_player_privs(name, {server=true}) then
|
||||
if param == "on" or param == "" then
|
||||
airutils.ground_effect_is_disabled = nil
|
||||
minetest.chat_send_player(name,core.colorize('#00ff00', " >>> Ground effect was turned on."))
|
||||
elseif param == "off" then
|
||||
airutils.ground_effect_is_disabled = true
|
||||
minetest.chat_send_player(name,core.colorize('#0000ff', " >>> Ground effect was turned off."))
|
||||
end
|
||||
else
|
||||
minetest.chat_send_player(name,core.colorize('#ff0000', " >>> You need 'server' priv to run this command."))
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("show_lift", {
|
||||
params = "<on/off>",
|
||||
description = "Enables/disables the lift printing (for debug purposes)",
|
||||
privs = {interact=true},
|
||||
func = function(name, param)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if minetest.check_player_privs(name, {server=true}) then
|
||||
if param == "on" or param == "" then
|
||||
airutils.show_lift = true
|
||||
minetest.chat_send_player(name,core.colorize('#0000ff', " >>> Lift printing turned on."))
|
||||
elseif param == "off" then
|
||||
airutils.show_lift = nil
|
||||
minetest.chat_send_player(name,core.colorize('#00ff00', " >>> Lift printing turned off."))
|
||||
end
|
||||
else
|
||||
minetest.chat_send_player(name,core.colorize('#ff0000', " >>> You need 'server' priv to run this command."))
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
|
|
199
lib_copter/control.lua
Executable file
199
lib_copter/control.lua
Executable file
|
@ -0,0 +1,199 @@
|
|||
--[[airutils.rudder_limit = 30
|
||||
airutils.elevator_limit = 40]]--
|
||||
|
||||
dofile(minetest.get_modpath("airutils") .. DIR_DELIM .. "lib_planes" .. DIR_DELIM .. "utilities.lua")
|
||||
|
||||
local function floating_auto_correction(self, dtime)
|
||||
local factor = 1
|
||||
--minetest.chat_send_player(self.driver_name, "antes: " .. self._air_float)
|
||||
if self._wing_configuration > self._stable_collective then factor = -1 end
|
||||
local time_correction = (dtime/airutils.ideal_step)
|
||||
if time_correction < 1 then time_correction = 1 end
|
||||
local intensity = 0.01
|
||||
local correction = (intensity*factor) * time_correction
|
||||
|
||||
local new_wing_configuration = self._wing_configuration + correction
|
||||
|
||||
self._wing_configuration = new_wing_configuration
|
||||
|
||||
--minetest.chat_send_all(dump(self._wing_configuration))
|
||||
end
|
||||
|
||||
local function set_pitch_by_mouse(self, player)
|
||||
local vehicle_rot = self.object:get_rotation()
|
||||
local rot_x = player:get_look_vertical()-vehicle_rot.x
|
||||
self._elevator_angle = -(rot_x * self._elevator_limit)*(self._pitch_intensity*10)
|
||||
if self._elevator_angle > self._elevator_limit then self._elevator_angle = self._elevator_limit end
|
||||
if self._elevator_angle < -self._elevator_limit then self._elevator_angle = -self._elevator_limit end
|
||||
end
|
||||
|
||||
function set_pitch(self, dir, dtime)
|
||||
local pitch_factor = self._pitch_intensity or 0.6
|
||||
local multiplier = pitch_factor*(dtime/airutils.ideal_step)
|
||||
if dir == -1 then
|
||||
--minetest.chat_send_all("cabrando")
|
||||
if self._elevator_angle > 0 then pitch_factor = pitch_factor * 2 end
|
||||
self._elevator_angle = math.max(self._elevator_angle-multiplier,-self._elevator_limit)
|
||||
elseif dir == 1 then
|
||||
--minetest.chat_send_all("picando")
|
||||
if self._angle_of_attack < 0 then pitch_factor = 1 end --lets reduce the command power to avoid accidents
|
||||
self._elevator_angle = math.min(self._elevator_angle+multiplier,self._elevator_limit)
|
||||
end
|
||||
end
|
||||
|
||||
local function set_yaw_by_mouse(self, dir)
|
||||
local rotation = self.object:get_rotation()
|
||||
local rot_y = math.deg(rotation.y)
|
||||
|
||||
local total = math.abs(math.floor(rot_y/360))
|
||||
|
||||
if rot_y < 0 then rot_y = rot_y + (360*total) end
|
||||
if rot_y > 360 then rot_y = rot_y - (360*total) end
|
||||
if rot_y >= 270 and dir <= 90 then dir = dir + 360 end
|
||||
if rot_y <= 90 and dir >= 270 then dir = dir - 360 end
|
||||
|
||||
local intensity = self._yaw_intensity / 10
|
||||
local command = (rot_y - dir) * intensity
|
||||
if command < -90 then command = -90
|
||||
elseif command > 90 then command = 90 end
|
||||
--minetest.chat_send_all("rotation y: "..rot_y.." - dir: "..dir.." - command: "..command)
|
||||
|
||||
self._rudder_angle = (-command * self._rudder_limit)/90
|
||||
end
|
||||
|
||||
local function set_yaw(self, dir, dtime)
|
||||
local yaw_factor = self._yaw_intensity or 25
|
||||
if dir == 1 then
|
||||
self._rudder_angle = math.max(self._rudder_angle-(yaw_factor*dtime),-self._rudder_limit)
|
||||
elseif dir == -1 then
|
||||
self._rudder_angle = math.min(self._rudder_angle+(yaw_factor*dtime),self._rudder_limit)
|
||||
end
|
||||
end
|
||||
|
||||
function airutils.heli_control(self, dtime, hull_direction, longit_speed, longit_drag, nhdir,
|
||||
later_speed, later_drag, accel, player, is_flying)
|
||||
--if self.driver_name == nil then return end
|
||||
local retval_accel = accel
|
||||
|
||||
local stop = false
|
||||
local ctrl = nil
|
||||
|
||||
local time_correction = (dtime/airutils.ideal_step)
|
||||
if time_correction < 1 then time_correction = 1 end
|
||||
self._vehicle_acc = self._vehicle_acc or 0
|
||||
|
||||
-- player control
|
||||
if player then
|
||||
ctrl = player:get_player_control()
|
||||
|
||||
if self._last_time_command > 0.5 then
|
||||
self._last_time_command = 0.5
|
||||
end
|
||||
|
||||
self._acceleration = 0
|
||||
self._lat_acceleration = 0
|
||||
local acc = 0
|
||||
if self._engine_running then
|
||||
--engine acceleration calc
|
||||
|
||||
local factor = 1
|
||||
|
||||
--control lift
|
||||
local collective_up_max = 1.2
|
||||
local min_angle = self._min_collective
|
||||
local collective_up = collective_up_max -- / 10
|
||||
if ctrl.jump then
|
||||
self._wing_configuration = self._wing_configuration + collective_up
|
||||
--end
|
||||
self._is_going_up = true
|
||||
elseif ctrl.sneak then
|
||||
self._wing_configuration = self._wing_configuration - collective_up
|
||||
--end
|
||||
else
|
||||
self._wing_configuration = self._stable_collective
|
||||
end
|
||||
if self._wing_configuration < min_angle then self._wing_configuration = min_angle end
|
||||
local up_limit = (self._wing_angle_of_attack+collective_up_max)
|
||||
if self._wing_configuration > up_limit then self._wing_configuration = up_limit end
|
||||
--end lift
|
||||
else
|
||||
self._wing_configuration = self._stable_collective or 1
|
||||
end
|
||||
|
||||
if is_flying or self.wheels then
|
||||
local acc_fraction = (self._max_engine_acc / 10)*time_correction
|
||||
if ctrl.up then
|
||||
if longit_speed < self._max_speed then self._acceleration = self._acceleration + acc_fraction end
|
||||
elseif ctrl.down then
|
||||
if longit_speed > -1.0 then self._acceleration = self._acceleration + (-acc_fraction) end
|
||||
else
|
||||
acc = 0
|
||||
end
|
||||
self._acceleration = math.min(self._acceleration,self._max_engine_acc)
|
||||
|
||||
if is_flying then --why double check? because I dont want lateral movement when landed
|
||||
if ctrl.right then
|
||||
if later_speed < self._max_speed then self._lat_acceleration = self._lat_acceleration + acc_fraction end
|
||||
elseif ctrl.left then
|
||||
if later_speed > -self._max_speed then self._lat_acceleration = self._lat_acceleration + (-acc_fraction) end
|
||||
end
|
||||
--set_yaw(self, yaw_cmd, dtime)
|
||||
end
|
||||
else
|
||||
self._acceleration = 0
|
||||
self._lat_acceleration = 0
|
||||
self.object:set_velocity({x=0,y=self.object:get_velocity().y,z=0})
|
||||
end
|
||||
|
||||
self._vehicle_acc = math.min(self._acceleration, self._max_engine_acc)
|
||||
self._lat_acc = math.min(self._lat_acceleration, self._max_engine_acc)
|
||||
|
||||
local hull_acc = vector.multiply(hull_direction,self._vehicle_acc)
|
||||
local lat_hull_acc = vector.multiply(nhdir,self._lat_acc)
|
||||
--colocar aceleração lateral aqui
|
||||
retval_accel=vector.add(retval_accel,hull_acc)
|
||||
retval_accel=vector.add(retval_accel,lat_hull_acc)
|
||||
|
||||
--pitch
|
||||
local pitch_cmd = 0
|
||||
if self._yaw_by_mouse == true then
|
||||
set_pitch_by_mouse(self, player)
|
||||
else
|
||||
if ctrl.up then pitch_cmd = 1 elseif ctrl.down then pitch_cmd = -1 end
|
||||
set_pitch(self, pitch_cmd, dtime)
|
||||
end
|
||||
|
||||
-- yaw
|
||||
local rot_y = math.deg(player:get_look_horizontal())
|
||||
set_yaw_by_mouse(self, rot_y)
|
||||
|
||||
|
||||
--I'm desperate, center all!
|
||||
if ctrl.right and ctrl.left then
|
||||
self._wing_configuration = self._stable_collective
|
||||
--self._elevator_angle = 0
|
||||
--self._rudder_angle = 0
|
||||
end
|
||||
|
||||
if ctrl.up and ctrl.down and self._last_time_command > 0.5 then
|
||||
self._last_time_command = 0
|
||||
local name = player:get_player_name()
|
||||
if self._yaw_by_mouse == true then
|
||||
minetest.chat_send_player(name, core.colorize('#0000ff', " >>> Mouse control disabled."))
|
||||
self._yaw_by_mouse = false
|
||||
else
|
||||
minetest.chat_send_player(name, core.colorize('#0000ff', " >>> Mouse control enabled."))
|
||||
self._yaw_by_mouse = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if is_flying then
|
||||
--floating_auto_correction(self, self.dtime)
|
||||
end
|
||||
--minetest.chat_send_all(dump(self._wing_configuration))
|
||||
|
||||
return retval_accel, stop
|
||||
end
|
||||
|
||||
|
327
lib_copter/entities.lua
Normal file
327
lib_copter/entities.lua
Normal file
|
@ -0,0 +1,327 @@
|
|||
dofile(minetest.get_modpath("airutils") .. DIR_DELIM .. "lib_planes" .. DIR_DELIM .. "global_definitions.lua")
|
||||
|
||||
local function ground_pitch(self, longit_speed, curr_pitch)
|
||||
local newpitch = curr_pitch
|
||||
if self._last_longit_speed == nil then self._last_longit_speed = 0 end
|
||||
|
||||
-- Estado atual do sistema
|
||||
if self._current_value == nil then self._current_value = 0 end -- Valor atual do sistema
|
||||
if self._last_error == nil then self._last_error = 0 end -- Último erro registrado
|
||||
|
||||
-- adjust pitch at ground
|
||||
if math.abs(longit_speed) < self._tail_lift_max_speed then
|
||||
local speed_range = self._tail_lift_max_speed - self._tail_lift_min_speed
|
||||
local percentage = 1-((math.abs(longit_speed) - self._tail_lift_min_speed)/speed_range)
|
||||
if percentage > 1 then percentage = 1 end
|
||||
if percentage < 0 then percentage = 0 end
|
||||
local angle = self._tail_angle * percentage
|
||||
local rad_angle = math.rad(angle)
|
||||
|
||||
if newpitch < rad_angle then newpitch = rad_angle end --ja aproveita o pitch atual se ja estiver cerrto
|
||||
--[[self._current_value = curr_pitch
|
||||
local kp = (longit_speed - self._tail_lift_min_speed)/10
|
||||
local output, last_error = airutils.pid_controller(self._current_value, rad_angle, self._last_error, self.dtime, kp)
|
||||
self._last_error = last_error
|
||||
newpitch = output]]--
|
||||
|
||||
if newpitch > math.rad(self._tail_angle) then newpitch = math.rad(self._tail_angle) end --não queremos arrastar o cauda no chão
|
||||
end
|
||||
|
||||
return newpitch
|
||||
end
|
||||
|
||||
function airutils.logic_heli(self)
|
||||
local velocity = self.object:get_velocity()
|
||||
local curr_pos = self.object:get_pos()
|
||||
self._curr_pos = curr_pos --shared
|
||||
self._last_accel = self.object:get_acceleration()
|
||||
|
||||
self._last_time_command = self._last_time_command + self.dtime
|
||||
|
||||
if self._last_time_command > 1 then self._last_time_command = 1 end
|
||||
|
||||
local player = nil
|
||||
if self.driver_name then player = minetest.get_player_by_name(self.driver_name) end
|
||||
local co_pilot = nil
|
||||
if self.co_pilot and self._have_copilot then co_pilot = minetest.get_player_by_name(self.co_pilot) end
|
||||
|
||||
--test collision
|
||||
airutils.testImpact(self, velocity, curr_pos)
|
||||
|
||||
local ctrl = nil
|
||||
if player then
|
||||
ctrl = player:get_player_control()
|
||||
---------------------
|
||||
-- change the driver
|
||||
---------------------
|
||||
if co_pilot and self._have_copilot and self._last_time_command >= 1 then
|
||||
if self._command_is_given == true then
|
||||
if ctrl.sneak or ctrl.jump or ctrl.up or ctrl.down or ctrl.right or ctrl.left then
|
||||
self._last_time_command = 0
|
||||
--take the control
|
||||
airutils.transfer_control(self, false)
|
||||
end
|
||||
else
|
||||
if ctrl.sneak == true and ctrl.jump == true then
|
||||
self._last_time_command = 0
|
||||
--trasnfer the control to student
|
||||
airutils.transfer_control(self, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if not self.object:get_acceleration() then return end
|
||||
local accel_y = self.object:get_acceleration().y
|
||||
local rotation = self.object:get_rotation()
|
||||
local yaw = rotation.y
|
||||
local newyaw=yaw
|
||||
local pitch = rotation.x
|
||||
local roll = rotation.z
|
||||
|
||||
local hull_direction = airutils.rot_to_dir(rotation) --minetest.yaw_to_dir(yaw)
|
||||
local nhdir = {x=hull_direction.z,y=0,z=-hull_direction.x} -- lateral unit vector
|
||||
|
||||
local longit_speed = vector.dot(velocity,hull_direction)
|
||||
self._longit_speed = longit_speed
|
||||
|
||||
local longit_drag = vector.multiply(hull_direction,longit_speed*
|
||||
longit_speed*self._longit_drag_factor*-1*airutils.sign(longit_speed))
|
||||
local later_speed = airutils.dot(velocity,nhdir)
|
||||
--minetest.chat_send_all('later_speed: '.. later_speed)
|
||||
local later_drag = vector.multiply(nhdir,later_speed*later_speed*
|
||||
self._later_drag_factor*-1*airutils.sign(later_speed))
|
||||
local accel = vector.add(longit_drag,later_drag)
|
||||
local stop = false
|
||||
|
||||
local node_bellow = airutils.nodeatpos(airutils.pos_shift(curr_pos,{y=-1.3}))
|
||||
local is_flying = true
|
||||
if self.colinfo then
|
||||
is_flying = (not self.colinfo.touching_ground) and (self.isinliquid == false)
|
||||
end
|
||||
--if is_flying then minetest.chat_send_all('is flying') end
|
||||
|
||||
local is_attached = airutils.checkAttach(self, player)
|
||||
if self._indicated_speed == nil then self._indicated_speed = 0 end
|
||||
|
||||
if not is_attached then
|
||||
-- for some engine error the player can be detached from the machine, so lets set him attached again
|
||||
airutils.checkattachBug(self)
|
||||
end
|
||||
|
||||
if self._custom_step_additional_function then
|
||||
self._custom_step_additional_function(self)
|
||||
end
|
||||
|
||||
--landing light
|
||||
if self._have_landing_lights then
|
||||
airutils.landing_lights_operate(self)
|
||||
end
|
||||
|
||||
--smoke and fire
|
||||
if self._engine_running then
|
||||
local curr_health_percent = (self.hp_max * 100)/self._max_plane_hp
|
||||
if curr_health_percent < 20 then
|
||||
airutils.add_smoke_trail(self, 2)
|
||||
elseif curr_health_percent < 50 then
|
||||
airutils.add_smoke_trail(self, 1)
|
||||
end
|
||||
else
|
||||
if self._smoke_spawner and not self._smoke_semaphore then
|
||||
self._smoke_semaphore = 1 --to set it only one time
|
||||
minetest.after(5, function()
|
||||
if self._smoke_spawner then
|
||||
minetest.delete_particlespawner(self._smoke_spawner)
|
||||
self._smoke_spawner = nil
|
||||
self._smoke_semaphore = nil
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
if (math.abs(velocity.x) < 0.1 and math.abs(velocity.z) < 0.1) and is_flying == false and is_attached == false and self._engine_running == false then
|
||||
if self._ground_friction then
|
||||
if not self.isinliquid then self.object:set_velocity({x=0,y=airutils.gravity*self.dtime,z=0}) end
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
--adjust climb indicator
|
||||
local y_velocity = 0
|
||||
if self._engine_running or is_flying then y_velocity = velocity.y end
|
||||
local climb_rate = y_velocity
|
||||
if climb_rate > 5 then climb_rate = 5 end
|
||||
if climb_rate < -5 then
|
||||
climb_rate = -5
|
||||
end
|
||||
|
||||
-- pitch and roll
|
||||
local newroll = 0
|
||||
local newpitch = 0
|
||||
if ctrl and is_flying then
|
||||
local command_angle = math.rad(8)
|
||||
if ctrl.up then newpitch = -command_angle end
|
||||
if ctrl.down then newpitch = command_angle end
|
||||
if ctrl.left then newroll = -command_angle end
|
||||
if ctrl.right then newroll = command_angle end
|
||||
end
|
||||
|
||||
-- new yaw
|
||||
if math.abs(self._rudder_angle)>1.5 then
|
||||
local turn_rate = math.rad(self._yaw_turn_rate)
|
||||
local yaw_turn = self.dtime * math.rad(self._rudder_angle) * turn_rate * 4
|
||||
newyaw = yaw + yaw_turn
|
||||
end
|
||||
|
||||
---------------------------------
|
||||
-- end roll
|
||||
|
||||
local pilot = player
|
||||
if self._have_copilot then
|
||||
if self._command_is_given and co_pilot then
|
||||
pilot = co_pilot
|
||||
else
|
||||
self._command_is_given = false
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------
|
||||
--accell calculation block
|
||||
------------------------------------------------------
|
||||
if is_attached or co_pilot then
|
||||
accel, stop = airutils.heli_control(self, self.dtime, hull_direction,
|
||||
longit_speed, longit_drag, nhdir, later_speed, later_drag, accel, pilot, is_flying)
|
||||
end
|
||||
--end accell
|
||||
|
||||
--get disconnected players
|
||||
airutils.rescueConnectionFailedPassengers(self)
|
||||
|
||||
if accel == nil then accel = {x=0,y=0,z=0} end
|
||||
|
||||
--lift calculation
|
||||
accel.y = accel_y
|
||||
|
||||
--lets apply some bob in water
|
||||
if self.isinliquid then
|
||||
local bob = airutils.minmax(airutils.dot(accel,hull_direction),0.02) -- vertical bobbing
|
||||
if bob < 0 then bob = 0 end
|
||||
accel.y = accel.y + bob
|
||||
local max_pitch = 6
|
||||
local ref_speed = longit_speed * 20
|
||||
if ref_speed < 0 then ref_speed = 0 end
|
||||
local h_vel_compensation = ((ref_speed * 100)/max_pitch)/100
|
||||
if h_vel_compensation < 0 then h_vel_compensation = 0 end
|
||||
if h_vel_compensation > max_pitch then h_vel_compensation = max_pitch end
|
||||
--minetest.chat_send_all(h_vel_compensation)
|
||||
newpitch = newpitch + (velocity.y * math.rad(max_pitch - h_vel_compensation))
|
||||
end
|
||||
|
||||
local ceiling = 5000
|
||||
local blade_speed = self._rotor_speed or 15
|
||||
local limit = 10
|
||||
if self._engine_running == false then blade_speed = self._rotor_idle_speed or 12 end
|
||||
local new_accel = airutils.getLiftAccel(self, {x=0, y=velocity.y, z=blade_speed}, {x=0, y=accel.y, z=blade_speed/self.dtime}, blade_speed, roll, curr_pos, self._lift, ceiling, self._wing_span)
|
||||
local y_accell = new_accel.y
|
||||
new_accel = vector.new(accel)
|
||||
new_accel.y = y_accell
|
||||
if new_accel.y > limit then new_accel.y = limit end --it isn't a rocket :/
|
||||
|
||||
--wind effects
|
||||
if airutils.wind and is_flying == true then
|
||||
local wind = airutils.get_wind(curr_pos, 0.1)
|
||||
new_accel = vector.add(new_accel, wind)
|
||||
end
|
||||
|
||||
if stop ~= true then --maybe == nil
|
||||
self._last_accell = new_accel
|
||||
self.object:move_to(curr_pos)
|
||||
--airutils.set_acceleration(self.object, new_accel)
|
||||
local limit = self._climb_speed
|
||||
--if new_accel.y > limit then new_accel.y = limit end --it isn't a rocket :/
|
||||
|
||||
else
|
||||
if stop == true then
|
||||
self._last_accell = vector.new() --self.object:get_acceleration()
|
||||
self.object:set_acceleration({x=0,y=0,z=0})
|
||||
self.object:set_velocity({x=0,y=0,z=0})
|
||||
end
|
||||
end
|
||||
|
||||
if self.wheels then
|
||||
if is_flying == false then --isn't flying?
|
||||
--animate wheels
|
||||
local min_speed_animation = 0.1
|
||||
if math.abs(velocity.x) > min_speed_animation or math.abs(velocity.z) > min_speed_animation then
|
||||
self.wheels:set_animation_frame_speed(longit_speed * 10)
|
||||
else
|
||||
self.wheels:set_animation_frame_speed(0)
|
||||
end
|
||||
else
|
||||
--stop wheels
|
||||
self.wheels:set_animation_frame_speed(0)
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------
|
||||
-- end accell
|
||||
------------------------------------------------------
|
||||
|
||||
------------------------------------------------------
|
||||
-- sound and animation
|
||||
------------------------------------------------------
|
||||
airutils.engine_set_sound_and_animation(self)
|
||||
|
||||
------------------------------------------------------
|
||||
|
||||
--self.object:get_luaentity() --hack way to fix jitter on climb
|
||||
|
||||
--GAUGES
|
||||
--minetest.chat_send_all('rate '.. climb_rate)
|
||||
local climb_angle = airutils.get_gauge_angle(climb_rate)
|
||||
self._climb_rate = climb_rate
|
||||
|
||||
local indicated_speed = longit_speed * 0.9
|
||||
if indicated_speed < 0 then indicated_speed = 0 end
|
||||
self._indicated_speed = indicated_speed
|
||||
local speed_angle = airutils.get_gauge_angle(indicated_speed, -45)
|
||||
|
||||
--adjust power indicator
|
||||
local power_indicator_angle = airutils.get_gauge_angle(self._power_lever/10) + 90
|
||||
local fuel_in_percent = (self._energy * 1)/self._max_fuel
|
||||
local energy_indicator_angle = (180*fuel_in_percent)-180 --(airutils.get_gauge_angle((self._max_fuel - self._energy)*2)) - 90
|
||||
|
||||
if is_attached then
|
||||
if self._show_hud then
|
||||
airutils.update_hud(player, climb_angle, speed_angle, power_indicator_angle, energy_indicator_angle)
|
||||
else
|
||||
airutils.remove_hud(player)
|
||||
end
|
||||
end
|
||||
|
||||
if is_flying == false then
|
||||
newyaw = yaw
|
||||
end
|
||||
|
||||
if player and self._use_camera_relocation then
|
||||
--minetest.chat_send_all(dump(newroll))
|
||||
local new_eye_offset = airutils.camera_reposition(player, newpitch, newroll)
|
||||
player:set_eye_offset(new_eye_offset, {x = 0, y = 1, z = -30})
|
||||
end
|
||||
|
||||
--apply rotations
|
||||
self.object:set_rotation({x=newpitch,y=newyaw,z=newroll})
|
||||
--end
|
||||
|
||||
-- calculate energy consumption --
|
||||
airutils.consumptionCalc(self, accel)
|
||||
|
||||
--saves last velocity for collision detection (abrupt stop)
|
||||
self._last_accel = new_accel
|
||||
self._last_vel = self.object:get_velocity()
|
||||
self._last_longit_speed = longit_speed
|
||||
self._yaw = newyaw
|
||||
self._roll = newroll
|
||||
self._pitch = newpitch
|
||||
end
|
8
lib_copter/init.lua
Executable file
8
lib_copter/init.lua
Executable file
|
@ -0,0 +1,8 @@
|
|||
|
||||
|
||||
dofile(minetest.get_modpath("airutils") .. DIR_DELIM .. "lib_copter" .. DIR_DELIM .. "control.lua")
|
||||
dofile(minetest.get_modpath("airutils") .. DIR_DELIM .. "lib_copter" .. DIR_DELIM .. "entities.lua")
|
||||
|
||||
|
||||
|
||||
|
|
@ -89,7 +89,7 @@ function airutils.control(self, dtime, hull_direction, longit_speed, longit_drag
|
|||
end
|
||||
end
|
||||
--do not exceed
|
||||
local max_speed = 6
|
||||
local max_speed = self._max_speed
|
||||
if longit_speed > max_speed then
|
||||
engineacc = engineacc - (longit_speed-max_speed)
|
||||
if engineacc < 0 then engineacc = 0 end
|
||||
|
|
|
@ -24,9 +24,9 @@ function airutils.physics(self)
|
|||
if surface then -- standing in liquid
|
||||
self.isinliquid = true
|
||||
end
|
||||
local last_accel = nil
|
||||
local last_accel = new
|
||||
if self._last_accel then
|
||||
last_accel = airutils.properties_copy(self._last_accel)
|
||||
last_accel = vector.new(self._last_accel)
|
||||
end
|
||||
|
||||
if self.isinliquid then
|
||||
|
|
|
@ -7,20 +7,20 @@ end
|
|||
function airutils.get_staticdata(self) -- unloaded/unloads ... is now saved
|
||||
return minetest.serialize({
|
||||
--stored_sound_handle = self.sound_handle,
|
||||
stored_energy = self._energy,
|
||||
stored_owner = self.owner,
|
||||
stored_hp = self.hp_max,
|
||||
stored_color = self._color,
|
||||
stored_color_2 = self._color_2,
|
||||
stored_power_lever = self._power_lever,
|
||||
stored_driver_name = self.driver_name,
|
||||
stored_last_accell = self._last_accell,
|
||||
stored_inv_id = self._inv_id,
|
||||
stored_flap = self._flap,
|
||||
stored_passengers = self._passengers,
|
||||
stored_adf_destiny = self._adf_destiny,
|
||||
stored_skin = self._skin,
|
||||
stored_vehicle_custom_data = self._vehicle_custom_data
|
||||
stored_energy = self._energy or 0,
|
||||
stored_owner = self.owner or "",
|
||||
stored_hp = self.hp_max or 10,
|
||||
stored_color = self._color or "#FFFFFF",
|
||||
stored_color_2 = self._color_2 or "#FFFFFF",
|
||||
stored_power_lever = self._power_lever or 0,
|
||||
stored_driver_name = self.driver_name or nil,
|
||||
stored_last_accell = self._last_accell or vector.new(),
|
||||
stored_inv_id = self._inv_id or nil,
|
||||
stored_flap = self._flap or false,
|
||||
stored_passengers = self._passengers or {},
|
||||
stored_adf_destiny = self._adf_destiny or vector.new(),
|
||||
stored_skin = self._skin or "",
|
||||
stored_vehicle_custom_data = self._vehicle_custom_data or nil
|
||||
})
|
||||
end
|
||||
|
||||
|
@ -39,20 +39,20 @@ function airutils.on_activate(self, staticdata, dtime_s)
|
|||
|
||||
if staticdata ~= "" and staticdata ~= nil then
|
||||
local data = minetest.deserialize(staticdata) or {}
|
||||
self._energy = data.stored_energy
|
||||
self.owner = data.stored_owner
|
||||
self.hp_max = data.stored_hp
|
||||
self._color = data.stored_color
|
||||
self._energy = data.stored_energy or 0
|
||||
self.owner = data.stored_owner or ""
|
||||
self.hp_max = data.stored_hp or 10
|
||||
self._color = data.stored_color or "#FFFFFF"
|
||||
self._color_2 = data.stored_color_2 or data.stored_color --if it has no color 2, now it have!
|
||||
self._power_lever = data.stored_power_lever
|
||||
self.driver_name = data.stored_driver_name
|
||||
self._last_accell = data.stored_last_accell
|
||||
self._inv_id = data.stored_inv_id
|
||||
if self._wing_angle_extra_flaps then self._flap = data.stored_flap end
|
||||
self._power_lever = data.stored_power_lever or 0
|
||||
self.driver_name = data.stored_driver_name or nil
|
||||
self._last_accell = data.stored_last_accell or vector.new()
|
||||
self._inv_id = data.stored_inv_id or nil
|
||||
if self._wing_angle_extra_flaps then self._flap = data.stored_flap or false end
|
||||
self._passengers = data.stored_passengers or {}
|
||||
self._adf_destiny = data.stored_adf_destiny or vector.new()
|
||||
self._skin = data.stored_skin
|
||||
local custom_data = data.stored_vehicle_custom_data
|
||||
self._skin = data.stored_skin or ""
|
||||
local custom_data = data.stored_vehicle_custom_data or nil
|
||||
if custom_data then
|
||||
self._vehicle_custom_data = custom_data
|
||||
else
|
||||
|
@ -64,6 +64,7 @@ function airutils.on_activate(self, staticdata, dtime_s)
|
|||
self._last_applied_power = -1 --signal to start
|
||||
end
|
||||
end
|
||||
|
||||
self._climb_rate = 0
|
||||
self._yaw = 0
|
||||
self._roll = 0
|
||||
|
@ -93,7 +94,10 @@ function airutils.on_activate(self, staticdata, dtime_s)
|
|||
self.wheels:set_animation({x = 1, y = self._anim_frames}, 0, 0, true)
|
||||
end
|
||||
|
||||
local inv = minetest.get_inventory({type = "detached", name = self._inv_id})
|
||||
local inv = nil
|
||||
if self._inv_id then
|
||||
inv = minetest.get_inventory({type = "detached", name = self._inv_id})
|
||||
end
|
||||
-- if the game was closed the inventories have to be made anew, instead of just reattached
|
||||
if not inv then
|
||||
airutils.create_inventory(self, self._trunk_slots)
|
||||
|
@ -107,7 +111,7 @@ function airutils.on_activate(self, staticdata, dtime_s)
|
|||
|
||||
if self._flap then airutils.flap_on(self) end
|
||||
|
||||
airutils.setText(self, self._vehicle_name)
|
||||
if self._vehicle_name then airutils.setText(self, self._vehicle_name) end
|
||||
end
|
||||
|
||||
function airutils.on_step(self,dtime,colinfo)
|
||||
|
@ -660,7 +664,7 @@ function airutils.on_punch(self, puncher, ttime, toolcaps, dir, damage)
|
|||
airutils.destroy(self, name)
|
||||
return
|
||||
end
|
||||
airutils.setText(self, self._vehicle_name)
|
||||
if self._vehicle_name then airutils.setText(self, self._vehicle_name) end
|
||||
|
||||
if (string.find(puncher:get_wielded_item():get_name(), "rayweapon") or
|
||||
toolcaps.damage_groups.vehicle) then
|
||||
|
@ -669,12 +673,12 @@ function airutils.on_punch(self, puncher, ttime, toolcaps, dir, damage)
|
|||
|
||||
local is_admin = false
|
||||
is_admin = minetest.check_player_privs(puncher, {server=true})
|
||||
if self.owner and self.owner ~= name and self.owner ~= "" then
|
||||
if is_admin == false then return end
|
||||
end
|
||||
if self.owner == nil then
|
||||
self.owner = name
|
||||
end
|
||||
if self.owner and self.owner ~= name and self.owner ~= "" then
|
||||
if is_admin == false then return end
|
||||
end
|
||||
|
||||
if self.driver_name and self.driver_name ~= name then
|
||||
-- do not allow other players to remove the object while there is a driver
|
||||
|
|
|
@ -411,7 +411,7 @@ function airutils.testImpact(self, velocity, position)
|
|||
self._last_touch = 0
|
||||
if not self._ground_friction then self._ground_friction = 0.99 end
|
||||
|
||||
if self._ground_friction > 0.97 then
|
||||
if self._ground_friction > 0.97 and self.wheels then
|
||||
minetest.sound_play("airutils_touch", {
|
||||
--to_player = self.driver_name,
|
||||
object = self.object,
|
||||
|
|
Loading…
Add table
Reference in a new issue