diff --git a/init.lua b/init.lua index 1bbbc47..266f119 100644 --- a/init.lua +++ b/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 = "", + 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 = "", + 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 +}) + diff --git a/lib_copter/control.lua b/lib_copter/control.lua new file mode 100755 index 0000000..05f58f1 --- /dev/null +++ b/lib_copter/control.lua @@ -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 + + diff --git a/lib_copter/entities.lua b/lib_copter/entities.lua new file mode 100644 index 0000000..3d8f223 --- /dev/null +++ b/lib_copter/entities.lua @@ -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 diff --git a/lib_copter/init.lua b/lib_copter/init.lua new file mode 100755 index 0000000..8e59198 --- /dev/null +++ b/lib_copter/init.lua @@ -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") + + + + diff --git a/lib_planes/control.lua b/lib_planes/control.lua index a264615..ba6d39f 100755 --- a/lib_planes/control.lua +++ b/lib_planes/control.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 diff --git a/lib_planes/custom_physics.lua b/lib_planes/custom_physics.lua index f1f1eea..a4de38a 100755 --- a/lib_planes/custom_physics.lua +++ b/lib_planes/custom_physics.lua @@ -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 diff --git a/lib_planes/entities.lua b/lib_planes/entities.lua index 3febef1..f4884b9 100644 --- a/lib_planes/entities.lua +++ b/lib_planes/entities.lua @@ -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 diff --git a/lib_planes/utilities.lua b/lib_planes/utilities.lua index 18c423b..2a5c75d 100644 --- a/lib_planes/utilities.lua +++ b/lib_planes/utilities.lua @@ -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,