diff --git a/lib_planes/entities.lua b/lib_planes/entities.lua index 092f40f..29ebef6 100644 --- a/lib_planes/entities.lua +++ b/lib_planes/entities.lua @@ -73,6 +73,8 @@ function airutils.on_activate(self, staticdata, dtime_s) self.inv = inv end + airutils.seats_create(self) + self._passengers = {} if not self._vehicle_custom_data then self._vehicle_custom_data = {} end --initialize when it does not exists airutils.setText(self, self.infotext) @@ -263,7 +265,7 @@ function airutils.logic(self) if longit_speed > (self._min_speed) then local percentage = math.abs(((longit_speed * 100)/(self._min_speed + 5))/100) if percentage > 1.5 then percentage = 1.5 end - self._angle_of_attack = self._wing_angle_of_attack - ((self._elevator_angle / 10)*percentage) + self._angle_of_attack = self._wing_angle_of_attack - ((self._elevator_angle / self._elevator_response_attenuation)*percentage) --set the plane on level if airutils.adjust_attack_angle_by_speed then @@ -295,7 +297,7 @@ function airutils.logic(self) -- new yaw if math.abs(self._rudder_angle)>1.5 then - local turn_rate = math.rad(14) + local turn_rate = math.rad(self._yaw_turn_rate) local yaw_turn = self.dtime * math.rad(self._rudder_angle) * turn_rate * airutils.sign(longit_speed) * math.abs(longit_speed/2) newyaw = yaw + yaw_turn @@ -521,8 +523,9 @@ local function damage_vehicle(self, toolcaps, ttime, damage) end function airutils.on_punch(self, puncher, ttime, toolcaps, dir, damage) + local name = puncher:get_player_name() if self.hp_max <= 0 then - airutils.destroy(self, true) + airutils.destroy(self, name) end airutils.setText(self, self.infotext) @@ -539,7 +542,6 @@ function airutils.on_punch(self, puncher, ttime, toolcaps, dir, damage) local is_admin = false is_admin = minetest.check_player_privs(puncher, {server=true}) - local name = puncher:get_player_name() if self.owner and self.owner ~= name and self.owner ~= "" then if is_admin == false then return end end @@ -615,7 +617,7 @@ function airutils.on_punch(self, puncher, ttime, toolcaps, dir, damage) end if self.hp_max <= 0 then - airutils.destroy(self) + airutils.destroy(self, name) end else if self._custom_punch_when_attached then self._custom_punch_when_attached(self, puncher) end @@ -623,6 +625,7 @@ function airutils.on_punch(self, puncher, ttime, toolcaps, dir, damage) end function airutils.on_rightclick(self, clicker) + local message = "" if not clicker or not clicker:is_player() then return end @@ -633,86 +636,117 @@ function airutils.on_rightclick(self, clicker) self.owner = name end - local passenger_name = nil - if self._passenger then - passenger_name = self._passenger + local copilot_name = nil + if self.co_pilot and self._have_copilot then + copilot_name = self.co_pilot end - local touching_ground, liquid_below = airutils.check_node_below(self.object, 1.3) + local touching_ground, liquid_below = airutils.check_node_below(self.object, 2.5) local is_on_ground = self.isinliquid or touching_ground or liquid_below local is_under_water = airutils.check_is_under_water(self.object) - --minetest.chat_send_all('name '.. dump(name) .. ' - pilot: ' .. dump(self.driver_name) .. ' - pax: ' .. dump(passenger_name)) + --minetest.chat_send_all('name '.. dump(name) .. ' - pilot: ' .. dump(self.driver_name) .. ' - pax: ' .. dump(copilot_name)) --========================= - -- detach pilot + -- form to pilot --========================= + local is_attached = false + local seat = clicker:get_attach() + --TODO crar funcao legacy aqui + if seat then + local plane = seat:get_attach() + if plane == self.object then is_attached = true end + end if name == self.driver_name then - if not self._custom_pilot_formspec then - airutils.pilot_formspec(name) + if is_attached then + local itmstck=clicker:get_wielded_item() + local item_name = "" + if itmstck then item_name = itmstck:get_name() end + --adf program function + if (item_name == "compassgps:cgpsmap_marked") then + local meta = minetest.deserialize(itmstck:get_metadata()) + if meta then + self._adf_destiny = {x=meta["x"], z=meta["z"]} + end + else + --formspec of the plane + if not self._custom_pilot_formspec then + airutils.pilot_formspec(name) + else + self._custom_pilot_formspec(name) + end + end else - self._custom_pilot_formspec(name) + self.driver_name = nil --error, so clean it end --========================= - -- detach passenger + -- detach copilot --========================= - elseif name == passenger_name then - if is_on_ground or clicker:get_player_control().sneak then - airutils.dettach_pax(self, clicker) - else - minetest.chat_send_player(name, "Hold sneak and right-click to disembark while flying") - end + elseif name == copilot_name then + airutils.pax_formspec(name) --========================= -- attach pilot --========================= elseif not self.driver_name then if self.owner == name or minetest.check_player_privs(clicker, {protection_bypass=true}) then + if clicker:get_player_control().aux1 == true then --lets see the inventory + airutils.show_vehicle_trunk_formspec(self, clicker, self._trunk_slots) + else + --[[if airutils.restricted == "true" and not minetest.check_player_privs(clicker, {flight_licence=true}) then + minetest.show_formspec(name, "airutils:flightlicence", + "size[4,2]" .. + "label[0.0,0.0;Sorry ...]".. + "label[0.0,0.7;You need a flight licence to fly it.]" .. + "label[0.0,1.0;You must obtain it from server admin.]" .. + "button_exit[1.5,1.9;0.9,0.1;e;Exit]") + return + end]]-- - local itmstck=clicker:get_wielded_item() - local item_name = "" - if itmstck then item_name = itmstck:get_name() end + if is_under_water then return end - if itmstck then - if airutils.set_param_paint(self, clicker, itmstck, 2) == false then - - if clicker:get_player_control().aux1 == true then --lets see the inventory - airutils.show_vehicle_trunk_formspec(self, clicker, self._trunk_slots) - else - if is_under_water then return end - --remove pax to prevent bug - if self._passenger then - local pax_obj = minetest.get_player_by_name(self._passenger) - airutils.dettach_pax(self, pax_obj) - end - - --attach player - if clicker:get_player_control().sneak == true then - -- flight instructor mode - self._instruction_mode = true - airutils.attach(self, clicker, true) - else - -- no driver => clicker is new driver - self._instruction_mode = false - airutils.attach(self, clicker) - end - self._elevator_angle = 0 - self._rudder_angle = 0 - self._command_is_given = false + --remove the passengers first + local max_seats = table.getn(self._seats) + for i = max_seats,1,-1 + do + if self._passengers[i] then + local passenger = minetest.get_player_by_name(self._passengers[i]) + if passenger then airutils.dettach_pax(self, passenger) end end + end - end + --attach player + -- no driver => clicker is new driver + airutils.attach(self, clicker) + self._command_is_given = false end else - minetest.chat_send_player(name, core.colorize('#ff0000', " >>> You aren't the owner of this machine.")) + airutils.dettach_pax(self, clicker) + minetest.chat_send_player(name, core.colorize('#ff0000', " >>> You aren't the owner of this "..self.infotext..".")) end --========================= -- attach passenger --========================= - elseif self.driver_name and not self._passenger then - airutils.attach_pax(self, clicker) - + --TODO - _autoflymode + elseif self.driver_name ~= nil or self._autoflymode == true then + local player = minetest.get_player_by_name(self.driver_name) + if player then + is_attached = airutils.check_passenger_is_attached(self, name) + + if is_attached then + --remove pax + airutils.pax_formspec(name) + else + --attach normal passenger + airutils.attach_pax(self, clicker) + end + + else + minetest.chat_send_player(clicker:get_player_name(), message) + end else - minetest.chat_send_player(name, core.colorize('#ff0000', " >>> Can't enter airplane.")) + minetest.chat_send_player(clicker:get_player_name(), message) end + end + diff --git a/lib_planes/forms.lua b/lib_planes/forms.lua index 7949365..e1132b4 100644 --- a/lib_planes/forms.lua +++ b/lib_planes/forms.lua @@ -38,7 +38,71 @@ function airutils.pilot_formspec(name) minetest.show_formspec(name, "lib_planes:pilot_main", basic_form) end +function airutils.pax_formspec(name) + local basic_form = table.concat({ + "formspec_version[3]", + "size[6,5]", + }, "") + + basic_form = basic_form.."button[1,1.0;4,1;new_seat;Change Seat]" + basic_form = basic_form.."button[1,2.5;4,1;go_out;Go Offboard]" + + minetest.show_formspec(name, "lib_planes:passenger_main", basic_form) +end + +function airutils.go_out_confirmation_formspec(name) + local basic_form = table.concat({ + "formspec_version[3]", + "size[7,2.2]", + }, "") + + basic_form = basic_form.."label[0.5,0.5;Do you really want to go offboard now?]" + basic_form = basic_form.."button[1.3,1.0;2,0.8;no;No]" + basic_form = basic_form.."button[3.6,1.0;2,0.8;yes;Yes]" + + minetest.show_formspec(name, "lib_planes:go_out_confirmation_form", basic_form) +end + minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname == "lib_planes:go_out_confirmation_form" then + local name = player:get_player_name() + local plane_obj = airutils.getPlaneFromPlayer(player) + if plane_obj == nil then + minetest.close_formspec(name, "lib_planes:go_out_confirmation_form") + return + end + local ent = plane_obj:get_luaentity() + if ent then + if fields.yes then + airutils.dettach_pax(ent, player) + end + end + minetest.close_formspec(name, "lib_planes:go_out_confirmation_form") + end + if formname == "lib_planes:passenger_main" then + local name = player:get_player_name() + local plane_obj = airutils.getPlaneFromPlayer(player) + if plane_obj == nil then + minetest.close_formspec(name, "lib_planes:passenger_main") + return + end + local ent = plane_obj:get_luaentity() + if ent then + if fields.new_seat then + airutils.dettach_pax(ent, player) + airutils.attach_pax(ent, player) + end + if fields.go_out then + local touching_ground, liquid_below = airutils.check_node_below(plane_obj, 2.5) + if ent.isinliquid or touching_ground then --isn't flying? + airutils.dettach_pax(ent, player) + else + airutils.go_out_confirmation_formspec(name) + end + end + end + minetest.close_formspec(name, "lib_planes:passenger_main") + end if formname == "lib_planes:pilot_main" then local name = player:get_player_name() local plane_obj = airutils.getPlaneFromPlayer(player) diff --git a/lib_planes/utilities.lua b/lib_planes/utilities.lua index a314564..d893b8a 100644 --- a/lib_planes/utilities.lua +++ b/lib_planes/utilities.lua @@ -33,6 +33,7 @@ function airutils.get_gauge_angle(value, initial_angle) return angle end +-- attach player function airutils.attach(self, player, instructor_mode) instructor_mode = instructor_mode or false local name = player:get_player_name() @@ -40,9 +41,9 @@ function airutils.attach(self, player, instructor_mode) -- attach the driver local eye_y = 0 - if instructor_mode == true then - eye_y = -2.5 - player:set_attach(self.passenger_seat_base, "", {x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0}) + if instructor_mode == true and self._have_copilot then + eye_y = -4 + player:set_attach(self.co_pilot_seat_base, "", {x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0}) else eye_y = -4 player:set_attach(self.pilot_seat_base, "", {x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0}) @@ -92,7 +93,8 @@ function airutils.check_passenger_is_attached(self, name) local is_attached = false if self._passenger == name then is_attached = true end if is_attached == false then - for i = self._max_occupants,1,-1 + local max_occupants = table.getn(self._seats) + for i = max_occupants,1,-1 do if self._passengers[i] == name then is_attached = true @@ -114,8 +116,8 @@ function airutils.attach_pax(self, player, is_copilot) end if is_copilot == true then - if self._passenger == nil then - self._passenger = name + if self.co_pilot == nil then + self.co_pilot = name -- attach the driver player:set_attach(self.co_pilot_seat_base, "", {x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0}) @@ -133,8 +135,11 @@ function airutils.attach_pax(self, player, is_copilot) end else --randomize the seat + local max_seats = table.getn(self._seats) + local crew = 1 + if self._have_copilot then crew = crew + 1 end t = {} -- new array - for i=1, self._max_occupants - 2 do --(the first 2 are the pilot and the copilot + for i=1, max_seats - crew do --(the first are for the crew t[i] = i end @@ -146,7 +151,7 @@ function airutils.attach_pax(self, player, is_copilot) --for i = 1,10,1 do for k,v in ipairs(t) do - i = t[k] + i = t[k] + crew --jump the crew seats if self._passengers[i] == nil then --minetest.chat_send_all(self.driver_name) self._passengers[i] = name @@ -180,7 +185,8 @@ function airutils.dettach_pax(self, player) if self._passenger == name then self._passenger = nil else - for i = (self._max_occupants - 2),1,-1 --the first 2 are the pilot and copilot + local max_seats = table.getn(self._seats) + for i = max_seats,1,-1 do if self._passengers[i] == name then self._passengers[i] = nil @@ -203,26 +209,35 @@ function airutils.checkAttach(self, player) if player then local player_attach = player:get_attach() if player_attach then - if player_attach == self.pilot_seat_base or player_attach == self.passenger_seat_base then - return true + local max_seats = table.getn(self._seats) + for i = max_seats,1,-1 + do + if player_attach == self._passengers_base[i] then + return true + end end end end return false end -function airutils.destroy(self, effects) - effects = effects or false +function airutils.destroy(self, by_name) + by_name = by_name or "" + local with_fire = self._enable_fire_explosion + if by_name == self.owner then with_fire = false end + if self.sound_handle then minetest.sound_stop(self.sound_handle) self.sound_handle = nil end - if self._passenger then - -- detach the passenger - local passenger = minetest.get_player_by_name(self._passenger) - if passenger then - airutils.dettach_pax(self, passenger) + --remove the passengers first + local max_seats = table.getn(self._seats) + for i = max_seats,2,-1 + do + if self._passengers[i] then + local passenger = minetest.get_player_by_name(self._passengers[i]) + if passenger then airutils.dettach_pax(self, passenger) end end end @@ -233,8 +248,9 @@ function airutils.destroy(self, effects) end local pos = self.object:get_pos() - if effects then airutils.add_destruction_effects(pos, 5) end + airutils.add_destruction_effects(pos, 5, with_fire) + airutils.seats_destroy(self) if self._destroy_parts_method then self._destroy_parts_method(self) end @@ -263,7 +279,7 @@ end function airutils.testImpact(self, velocity, position) if self.hp_max < 0 then --if acumulated damage is greater than 50, adieu - airutils.destroy(self, true) + airutils.destroy(self) end local impact_speed = 2 local p = position --self.object:get_pos() @@ -327,7 +343,7 @@ function airutils.testImpact(self, velocity, position) airutils.setText(self, self.infotext) end if self.hp_max < 0 then --if acumulated damage is greater than 50, adieu - airutils.destroy(self, true) + airutils.destroy(self) end end end @@ -363,7 +379,7 @@ function airutils.testImpact(self, velocity, position) --minetest.chat_send_all('damage: '.. damage .. ' - hp: ' .. self.hp_max) if self.hp_max < 0 then --adieu - airutils.destroy(self, self._enable_explosion) + airutils.destroy(self) end local player = minetest.get_player_by_name(player_name) @@ -570,7 +586,9 @@ function airutils.pid_controller(current_value, setpoint, last_error, d_time, kp return output, last_error end -function airutils.add_destruction_effects(pos, radius) +function airutils.add_destruction_effects(pos, radius, w_fire) + w_fire = w_fire + if w_fire == nil then w_fire = true end local node = airutils.nodeatpos(pos) local is_liquid = false if (node.drawtype == 'liquid' or node.drawtype == 'flowingliquid') then is_liquid = true end @@ -582,7 +600,7 @@ function airutils.add_destruction_effects(pos, radius) fade = 0.0, pitch = 1.0, }, true) - if is_liquid == false then + if is_liquid == false and w_fire == true then minetest.add_particle({ pos = pos, velocity = vector.new(), @@ -661,3 +679,30 @@ function airutils.camera_reposition(player, pitch, roll) return new_eye_offset end +function airutils.seats_create(self) + if self.object then + local pos = self.object:get_pos() + self._passengers_base = {} + local max_seats = table.getn(self._seats) + for i=1, max_seats do + self._passengers_base[i] = minetest.add_entity(pos,'airutils:seat_base') + if not self._seats_rot then + self._passengers_base[i]:set_attach(self.object,'',self._seats[i],{x=0,y=0,z=0}) + else + self._passengers_base[i]:set_attach(self.object,'',self._seats[i],{x=0,y=self._seats_rot[i],z=0}) + end + end + + self.pilot_seat_base = self._passengers_base[1] --sets pilot seat reference + if self._have_copilot and self.pilot_seat_base[2] then + self.co_pilot_seat_base = self.pilot_seat_base[2] --sets copilot seat reference + end + end +end + +function airutils.seats_destroy(self) + local max_seats = table.getn(self._passengers_base) + for i=1, max_seats do + if self._passengers_base[i] then self._passengers_base[i]:remove() end + end +end diff --git a/textures/airutils_blue.png b/textures/airutils_blue.png new file mode 100755 index 0000000..7071936 Binary files /dev/null and b/textures/airutils_blue.png differ diff --git a/textures/airutils_green.png b/textures/airutils_green.png new file mode 100755 index 0000000..de6d716 Binary files /dev/null and b/textures/airutils_green.png differ