diff --git a/.luacheckrc b/.luacheckrc new file mode 100755 index 0000000..f4d08e0 --- /dev/null +++ b/.luacheckrc @@ -0,0 +1,25 @@ +unused_args = false +allow_defined_top = true + +globals = { + "minetest", + "mobkit", + "core", + "player_api", + "player_monoids", + "math.sign", +} + +read_globals = { + string = {fields = {"split"}}, + table = {fields = {"copy", "getn"}}, + + -- Builtin + "vector", "ItemStack", + "dump", "DIR_DELIM", "VoxelArea", "Settings", + + -- MTG + "default", "sfinv", "creative", +} + +ignore = {"611"} diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 index 5974cc4..3aa4429 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Alexsandro Percy +Copyright (c) 2023 APercy - Alexsandro Percy Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md old mode 100644 new mode 100755 index b71caae..e2c387a --- a/README.md +++ b/README.md @@ -1,2 +1,113 @@ -# ap_airship -An Airship for Minetest +Minetest 5.4 mod: Steampunk Blimp +======================================== + +This mod implements a fantasy steampunk blimp for minetest. +The mod was made for fun, but tries to provide an immersion on it's operation. +It can carry 5 people. + +To fly it, it is necessary to provide some items, such as fuel to be burned and +water for the boiler. The fuel can be coal, coal block and wood. To supply it, +be on board and punch the necessary items on the airship. There is another way to +load water to the boiler: if it is landed on water, it can load it through the +menu. But the current pressure will be lost. + +Activate the furnace in the first option of the menu. Take control by activating +the option "Take the Control". + +The information panel will be on the left and bottom of the screen. Wait for the +boiler to reach the proper pressure for operation (green) before operating the power lever. +To go up, press Jump (space). Note that it takes some pressure from the boiler. To go down, +hold sneak (shift). + +Forward increases the propeller power, Backward reduces. +There is a power mode. When the lever reaches the up limit, hold E +and forward to increase the acceleration. But note that the boiler will lose pressure. +The blimp inventory can be accessed by Aux (E) + rightclick. + +Shared owners: +This vehicle was made to be shared with a team. So the owner can set more users to +operate it. Inside the blimp, just use the command /blimp_share + +- To go reverse, hold aux (E key) and backward together. +- To remove someone from the sharing, /blimp_remove +- To list the owners, /blimp_list +- To lock the blimp access, so only the owners can enter: /blimp_lock true +- To let anyone enter, /blimp_lock false + +All shared owners can access the blimp inventory + +Painting: +As the planes, punch a dye against the hull, so the primary color will change +- To change the secondary color, punch a dye, but holding Aux (E) key. +It is possible to set a logo on your blimp, so enter inside it and type the command /blimp_logo +Only the original owner can do the paintings + +Shortcuts: + +punch with dye to paint +forward and backward while in drive position: controls the power lever +left and right while in drive position: controls the direction +jump and sneak: controls the up and down movement + +- right click to enter and access menu +- E + right click while inside: acess inventory +- E + backward while in drive position: the machine does backward +- E + foward while in drive position: extra power + +Tip: +Drive it gently. +The captain can leave the drive position to walk too +If a player goes timeout or logoff in flight, the blimp will "rescue" him if no other player +enter the blimp, so is a good idea wait the friend at a secure place far from anyone who +wants to enter the blimp. + +Know issues: +The walk movement inside the ship is affected by server lag, because the lack of +an interpolation method on attach function. + +Rubber-band bug is from minetest nature, just close and reopen minetest to solve. +Or try to live the Michael Jackson's way of life and learn the Moonwalk properly XD +Some old versions of minetest can have an strange issue, the camera is set to +the map center. So if it happens, just type /blimp_eject to be free again. + + +License of source code: +MIT (see file LICENSE) + +License of media (textures and sounds): +--------------------------------------- +collision.ogg by APercy, CC0 + +Blimp model and textures by APercy. CC BY-SA 3.0 + +Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) +Copyright (C) 2022 Alexsandro Percy (APercy) + +You are free to: +Share — copy and redistribute the material in any medium or format. +Adapt — remix, transform, and build upon the material for any purpose, even commercially. +The licensor cannot revoke these freedoms as long as you follow the license terms. + +Under the following terms: + +Attribution — You must give appropriate credit, provide a link to the license, and +indicate if changes were made. You may do so in any reasonable manner, but not in any way +that suggests the licensor endorses you or your use. + +ShareAlike — If you remix, transform, or build upon the material, you must distribute +your contributions under the same license as the original. + +No additional restrictions — You may not apply legal terms or technological measures that +legally restrict others from doing anything the license permits. + +Notices: + +You do not have to comply with the license for elements of the material in the public +domain or where your use is permitted by an applicable exception or limitation. +No warranties are given. The license may not give you all of the permissions necessary +for your intended use. For example, other rights such as publicity, privacy, or moral +rights may limit how you use the material. + +For more details: +http://creativecommons.org/licenses/by-sa/3.0/ + diff --git a/control.lua b/control.lua new file mode 100755 index 0000000..664f630 --- /dev/null +++ b/control.lua @@ -0,0 +1,170 @@ +--global constants + +ap_airship.vector_up = vector.new(0, 1, 0) + +function ap_airship.check_node_below(obj) + local pos_below = obj:get_pos() + pos_below.y = pos_below.y - 0.1 + local node_below = minetest.get_node(pos_below).name + local nodedef = minetest.registered_nodes[node_below] + local touching_ground = not nodedef or -- unknown nodes are solid + nodedef.walkable or false + local liquid_below = not touching_ground and nodedef.liquidtype ~= "none" + return touching_ground, liquid_below +end + +function ap_airship.powerAdjust(self,dtime,factor,dir,max_power) + local max = max_power or 100 + local add_factor = factor/2 + add_factor = add_factor * (dtime/ap_airship.ideal_step) --adjusting the command speed by dtime + local power_index = self._power_lever + + if dir == 1 then + if self._power_lever < max then + self._power_lever = self._power_lever + add_factor + end + if self._power_lever > max then + self._power_lever = max + end + end + if dir == -1 then + self._power_lever = self._power_lever - add_factor + if self._power_lever < -15 then self._power_lever = -15 end + end +end + +function ap_airship.control(self, dtime, hull_direction, longit_speed, accel) + if self._last_time_command == nil then self._last_time_command = 0 end + self._last_time_command = self._last_time_command + 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 retval_accel = accel; + + -- player control + local ctrl = nil + if player and self._at_control == true then + ctrl = player:get_player_control() + local max_speed_anchor = 0.2 + + if self.anchored == false then + local factor = 1 + if ctrl.up then + local can_acc = true + if self._power_lever >= 82 then can_acc = false end + if ctrl.aux1 then can_acc = true end + if can_acc then + ap_airship.powerAdjust(self, dtime, factor, 1) + end + elseif ctrl.down then + ap_airship.powerAdjust(self, dtime, factor, -1) + else + --self.object:set_animation_frame_speed(ap_airship.iddle_rotation) + end + else + --anchor away, so stop! + self._power_lever = 0 + end + if not ctrl.aux1 and self._power_lever < 0 then self._power_lever = 0 end + + --control lift + self._is_going_up = false + local work_speed = math.abs(longit_speed) + if ap_airship.max_speed < work_speed then work_speed = ap_airship.max_speed end --limit the range + local normal_lift = 0.15 + local extra_lift = 0.15 + local abs_baloon_buoyancy = normal_lift + ((work_speed*extra_lift)/ap_airship.max_speed) + if ctrl.jump then + --if self._boiler_pressure > 0 then + self._baloon_buoyancy = abs_baloon_buoyancy + --end + self._is_going_up = true + elseif ctrl.sneak then + self._baloon_buoyancy = -1*abs_baloon_buoyancy + end + --end lift + + --check if is near the ground, so revert the flight mode + local noded = automobiles_lib.nodeatpos(airutils.pos_shift(self.object:get_pos(),{y=-4})) + if (noded and noded.drawtype ~= 'airlike') then + --avoid liquids + if noded.drawtype == 'liquid' then + --self._baloon_buoyancy = abs_baloon_buoyancy*2 + end + end + + + -- rudder + local rudder_limit = 30 + local speed = 10 + if ctrl.right then + self._rudder_angle = math.max(self._rudder_angle-speed*dtime,-rudder_limit) + elseif ctrl.left then + self._rudder_angle = math.min(self._rudder_angle+speed*dtime,rudder_limit) + end + end + + + --engine acceleration calc + local engineacc = (self._power_lever * ap_airship.max_engine_acc) / 100; + + --do not exceed + if longit_speed > ap_airship.max_speed then + engineacc = engineacc - (longit_speed-ap_airship.max_speed) + end + + if engineacc ~= nil then + retval_accel=vector.add(accel,vector.multiply(hull_direction,engineacc)) + end + --minetest.chat_send_all('paddle: '.. paddleacc) + + + if longit_speed > 0 then + if ctrl then + if ctrl.right or ctrl.left then + else + ap_airship.rudder_auto_correction(self, longit_speed, dtime) + end + else + ap_airship.rudder_auto_correction(self, longit_speed, dtime) + end + end + + ap_airship.buoyancy_auto_correction(self, self.dtime) + + return retval_accel +end + +function ap_airship.rudder_auto_correction(self, longit_speed, dtime) + local factor = 1 + if self._rudder_angle > 0 then factor = -1 end + local correction = (ap_airship.rudder_limit*(longit_speed/2000)) * factor * (dtime/ap_airship.ideal_step) + local before_correction = self._rudder_angle + local new_rudder_angle = self._rudder_angle + correction + if math.sign(before_correction) ~= math.sign(new_rudder_angle) then + self._rudder_angle = 0 + else + self._rudder_angle = new_rudder_angle + end +end + +function ap_airship.buoyancy_auto_correction(self, dtime) + local factor = 1 + --minetest.chat_send_player(self.driver_name, "antes: " .. self._baloon_buoyancy) + if self._baloon_buoyancy > 0 then factor = -1 end + local time_correction = (dtime/ap_airship.ideal_step) + local intensity = 0.001 + local correction = (intensity*factor) * time_correction + --minetest.chat_send_player(self.driver_name, correction) + local before_correction = self._baloon_buoyancy + local new_baloon_buoyancy = self._baloon_buoyancy + correction + if math.sign(before_correction) ~= math.sign(new_baloon_buoyancy) then + self._baloon_buoyancy = 0 + else + self._baloon_buoyancy = new_baloon_buoyancy + end + --minetest.chat_send_player(self.driver_name, "depois: " .. self._baloon_buoyancy) +end + diff --git a/custom_physics.lua b/custom_physics.lua new file mode 100755 index 0000000..0e6d867 --- /dev/null +++ b/custom_physics.lua @@ -0,0 +1,86 @@ +local min = math.min +local abs = math.abs + +function ap_airship.physics(self) + local friction = 0.996 + local vel=self.object:get_velocity() + -- dumb friction + if self.isonground and not self.isinliquid then + --minetest.chat_send_all("with friction") + vel = {x=vel.x*friction, + y=vel.y, + z=vel.z*friction} + self.object:set_velocity(vel) + end + + -- bounciness + if self.springiness and self.springiness > 0 then + local vnew = vector.new(vel) + + if not self.collided then -- ugly workaround for inconsistent collisions + for _,k in ipairs({'y','z','x'}) do + if vel[k]==0 and abs(self.lastvelocity[k])> 0.1 then + vnew[k]=-self.lastvelocity[k]*self.springiness + end + end + end + + if not vector.equals(vel,vnew) then + self.collided = true + else + if self.collided then + vnew = vector.new(self.lastvelocity) + end + self.collided = false + end + --minetest.chat_send_all("vnew") + self.object:set_velocity(vnew) + end + --[[else + self.object:set_pos(self.object:get_pos()) + if not self.isonground then + --minetest.chat_send_all("test") + self.object:set_velocity(vel) + end + end]]-- + + --buoyancy + local surface = nil + local surfnodename = nil + local spos = airutils.get_stand_pos(self) + spos.y = spos.y+0.01 + -- get surface height + local snodepos = airutils.get_node_pos(spos) + local surfnode = airutils.nodeatpos(spos) + while surfnode and (surfnode.drawtype == 'liquid' or surfnode.drawtype == 'flowingliquid') do + surfnodename = surfnode.name + surface = snodepos.y +0.5 + if surface > spos.y+self.height then break end + snodepos.y = snodepos.y+1 + surfnode = airutils.nodeatpos(snodepos) + end + + local new_velocity = nil + + local accell = {x=0, y=0, z=0} + self.water_drag = 0.1 + self.object:move_to(self.object:get_pos()) + local time_correction = (self.dtime/ap_airship.ideal_step) + local y_accel = self._baloon_buoyancy*time_correction + --minetest.chat_send_all(y_accel) + local max_y_acell = 0.3 + if y_accel > max_y_acell then y_accel = max_y_acell end + if y_accel < (-1*max_y_acell) then y_accel = -1*max_y_acell end + + + self.isinliquid = false + if self._baloon_buoyancy == 0 then + local velocity = vector.new(vel) + velocity.y = velocity.y - (velocity.y/100) + self.object:set_velocity(velocity) + end + --minetest.chat_send_all("_baloon_buoyancy: "..self._baloon_buoyancy.." - dtime: "..self.dtime.." - ideal: "..ap_airship.ideal_step) + airutils.set_acceleration(self.object,{x=0,y=y_accel,z=0}) + + +end diff --git a/engine_management.lua b/engine_management.lua new file mode 100644 index 0000000..0c719ce --- /dev/null +++ b/engine_management.lua @@ -0,0 +1,50 @@ +ap_airship.PRESSURE_CONSUMPTION = 500 + +local adjust_variable = 500 +local lost_power = (1/ap_airship.FUEL_CONSUMPTION)*adjust_variable +local gained_pressure = (2/ap_airship.FUEL_CONSUMPTION)*adjust_variable + +ap_airship.boiler_min = 1 +ap_airship.boiler_max = 310 + +function ap_airship.start_engine(self) + -- sound + --minetest.chat_send_all(dump(self.sound_handle_engine)) + if self.sound_handle_engine == nil and self._engine_running == true then + self.object:set_animation_frame_speed(ap_airship.iddle_rotation) + if self.object then + self.sound_handle_engine = minetest.sound_play({name = "ap_airship_engine"},--"default_item_smoke"}, + {object = self.object, gain = 3.0, + pitch = 0.4, + max_hear_distance = 120, + loop = true,}) + end + end +end + +local function engines_step(self, accel) + ap_airship.start_engine(self) + ap_airship.engine_set_sound_and_animation(self) +end + +local function furnace_step(self, accel) + if self._energy > 0 and self._engine_running then + local consumed_power = (1/ap_airship.FUEL_CONSUMPTION) + --self._energy = self._energy - consumed_power; --removes energy + end +end + +function ap_airship.engine_step(self, accel) + furnace_step(self, accel) + engines_step(self, accel) + + if self.driver_name then + local player = minetest.get_player_by_name(self.driver_name) + + local pressure = 0 + local coal = self._energy + --minetest.chat_send_all(self._power_lever) + ap_airship.update_hud(player, coal, 180, -pressure, self._power_lever) + end +end + diff --git a/entities.lua b/entities.lua new file mode 100755 index 0000000..7596073 --- /dev/null +++ b/entities.lua @@ -0,0 +1,679 @@ +-- +-- constants +-- +local LONGIT_DRAG_FACTOR = 0.13*0.13 +local LATER_DRAG_FACTOR = 2.0 + +local function right_click_function(self, clicker) + local message = "" + if not clicker or not clicker:is_player() then + return + end + + local name = clicker:get_player_name() + + 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('passengers: '.. dump(self._passengers)) + --========================= + -- form to pilot + --========================= + local is_attached = false + local seat = clicker:get_attach() + if seat then + local plane = seat:get_attach() + if plane == self.object then is_attached = true end + end + + --check error after being shot for any other mod + if is_attached == false then + for i = ap_airship.max_seats,1,-1 + do + if self._passengers[i] == name then + self._passengers[i] = nil --clear the wrong information + break + end + end + end + + --shows pilot formspec + if name ~= self.driver_name then + local pass_is_attached = ap_airship.check_passenger_is_attached(self, name) + + if pass_is_attached then + local can_bypass = minetest.check_player_privs(clicker, {protection_bypass=true}) + if clicker:get_player_control().aux1 == true then --lets see the inventory + local is_shared = false + if name == self.owner or can_bypass then is_shared = true end + for k, v in pairs(self._shared_owners) do + if v == name then + is_shared = trueright_click_function + break + end + end + if is_shared then + airutils.show_vehicle_trunk_formspec(self, clicker, ap_airship.trunk_slots) + end + else + ap_airship.pax_formspec(name) + end + else + --first lets clean the boat slots + --note that when it happens, the "rescue" function will lost the historic + for i = ap_airship.max_seats,1,-1 + do + if self._passengers[i] ~= nil then + local old_player = minetest.get_player_by_name(self._passengers[i]) + if not old_player then self._passengers[i] = nil end + end + end + --attach normal passenger + --if self._door_closed == false then + ap_airship.attach_pax(self, clicker) + --end + end + end + +end + +local function right_click_controls(self, clicker) + local message = "" + if not clicker or not clicker:is_player() then + return + end + + local name = clicker:get_player_name() + local ship_self = nil + + local is_attached = false + local seat = clicker:get_attach() + if seat then + ship_attach = seat:get_attach() + if ship_attach then + ship_self = ship_attach:get_luaentity() + is_attached = true + end + end + + + if is_attached then + --minetest.chat_send_all('passengers: '.. dump(ship_self._passengers)) + --========================= + -- form to pilot + --========================= + if ship_self.owner == "" then + ship_self.owner = name + end + + if ship_self.driver_name ~= nil and ship_self.driver_name ~= "" then + --shows pilot formspec + if name == ship_self.driver_name then + ap_airship.pilot_formspec(name) + return + end + --lets take the control by force + if name == ship_self.owner or can_bypass then + --require the pilot position now + ap_airship.owner_formspec(name) + return + end + else + --check if is on owner list + local is_shared = false + if name == ship_self.owner or can_bypass then is_shared = true end + for k, v in pairs(ship_self._shared_owners) do + if v == name then + is_shared = true + break + end + end + --normal user + if is_shared == false then + ap_airship.pax_formspec(name) + else + --owners + ap_airship.pilot_formspec(name) + end + end + end +end + +local function right_click_cabin(self, clicker) + local message = "" + if not clicker or not clicker:is_player() then + return + end + + local name = clicker:get_player_name() + local ship_self = nil + + local is_attached = false + local seat = clicker:get_attach() + if seat then + ship_attach = seat:get_attach() + if ship_attach then + ship_self = ship_attach:get_luaentity() + is_attached = true + end + end + + + if is_attached then + --shows pilot formspec + if name == ship_self.driver_name then + return + else + ap_airship.pax_formspec(name) + end + end +end + + +-- +-- entity +-- + +minetest.register_entity('ap_airship:control_interactor',{ + initial_properties = { + physical = true, + collide_with_objects=true, + collisionbox = {-0.5, 0, -0.5, 0.5, 0.5, 0.5}, + visual = "mesh", + mesh = "ap_airship_stand_base.b3d", + textures = {"ap_airship_alpha.png",}, + }, + dist_moved = 0, + + on_activate = function(self,std) + self.sdata = minetest.deserialize(std) or {} + if self.sdata.remove then self.object:remove() end + end, + + get_staticdata=function(self) + self.sdata.remove=true + return minetest.serialize(self.sdata) + end, + + on_punch = function(self, puncher, ttime, toolcaps, dir, damage) + --minetest.chat_send_all("punch") + if not puncher or not puncher:is_player() then + return + end + end, + + on_rightclick = right_click_controls, + +}) + +minetest.register_entity('ap_airship:cabin_interactor',{ + initial_properties = { + physical = true, + collide_with_objects=true, + collisionbox = {-0.5, 0, -0.5, 0.5, 5, 0.5}, + visual = "mesh", + mesh = "ap_airship_stand_base.b3d", + textures = {"ap_airship_alpha.png",}, + }, + dist_moved = 0, + + on_activate = function(self,std) + self.sdata = minetest.deserialize(std) or {} + if self.sdata.remove then self.object:remove() end + end, + + get_staticdata=function(self) + self.sdata.remove=true + return minetest.serialize(self.sdata) + end, + + on_punch = function(self, puncher, ttime, toolcaps, dir, damage) + --minetest.chat_send_all("punch") + if not puncher or not puncher:is_player() then + return + end + end, + + on_rightclick = right_click_cabin, + +}) + +-- +-- seat pivot +-- +minetest.register_entity('ap_airship:stand_base',{ + initial_properties = { + physical = true, + collide_with_objects=true, + collisionbox = {-2, -2, -2, 2, 0, 2}, + pointable=false, + visual = "mesh", + mesh = "ap_airship_stand_base.b3d", + textures = {"ap_airship_alpha.png",}, + }, + dist_moved = 0, + + on_activate = function(self,std) + self.sdata = minetest.deserialize(std) or {} + if self.sdata.remove then self.object:remove() end + end, + + get_staticdata=function(self) + self.sdata.remove=true + return minetest.serialize(self.sdata) + end, +}) + +minetest.register_entity("ap_airship:airship", { + initial_properties = { + physical = true, + collide_with_objects = true, --true, + collisionbox = {-10, -3.5, -10, 10, 15, 10}, --{-1,0,-1, 1,0.3,1}, + --selectionbox = {-0.6,0.6,-0.6, 0.6,1,0.6}, + visual = "mesh", + backface_culling = false, + mesh = "ap_airship_mesh.b3d", + textures = ap_airship.textures_copy(), + }, + textures = {}, + driver_name = nil, + sound_handle = nil, + static_save = true, + infotext = "A nice airship", + lastvelocity = vector.new(), + hp = 50, + color = "blue", + color2 = "white", + logo = "ap_airship_alpha_logo.png", + timeout = 0; + buoyancy = 0.15, + max_hp = 50, + anchored = false, + physics = ap_airship.physics, + hull_integrity = nil, + owner = "", + _shared_owners = {}, + _engine_running = false, + _power_lever = 0, + _last_applied_power = 0, + _at_control = false, + _rudder_angle = 0, + _baloon_buoyancy = 0, + _show_hud = true, + _energy = 1.0,--0.001, + _boiler_pressure = 1.0, --min 155 max 310 + _is_going_up = false, --to tell the boiler to lose pressure + _passengers = {}, --passengers list + _passengers_base = {}, --obj id + _passengers_base_pos = ap_airship.copy_vector({}), + _passengers_locked = false, + _disconnection_check_time = 0, + _inv = nil, + _inv_id = "", + item = "ap_airship:airship", + + get_staticdata = function(self) -- unloaded/unloads ... is now saved + return minetest.serialize({ + stored_baloon_buoyancy = self._baloon_buoyancy, + stored_energy = self._energy, + stored_owner = self.owner, + stored_shared_owners = self._shared_owners, + stored_hp = self.hp, + stored_color = self.color, + stored_color2 = self.color2, + stored_logo = self.logo, + stored_anchor = self.anchored, + stored_hull_integrity = self.hull_integrity, + stored_item = self.item, + stored_inv_id = self._inv_id, + stored_passengers = self._passengers, --passengers list + stored_passengers_locked = self._passengers_locked, + }) + end, + + on_deactivate = function(self) + airutils.save_inventory(self) + if self.sound_handle then minetest.sound_stop(self.sound_handle) end + if self.sound_handle_engine then minetest.sound_stop(self.sound_handle_engine) end + end, + + on_activate = function(self, staticdata, dtime_s) + --minetest.chat_send_all('passengers: '.. dump(self._passengers)) + if staticdata ~= "" and staticdata ~= nil then + local data = minetest.deserialize(staticdata) or {} + + self._baloon_buoyancy = data.stored_baloon_buoyancy or 0 + self._energy = data.stored_energy or 0 + self.owner = data.stored_owner or "" + self._shared_owners = data.stored_shared_owners or {} + self.hp = data.stored_hp or 50 + self.color = data.stored_color or "blue" + self.color2 = data.stored_color2 or "white" + self.logo = data.stored_logo or "ap_airship_alpha_logo.png" + self.anchored = data.stored_anchor or false + self.buoyancy = data.stored_buoyancy or 0.15 + self.hull_integrity = data.stored_hull_integrity + self.item = data.stored_item + self._inv_id = data.stored_inv_id + self._passengers = data.stored_passengers or ap_airship.copy_vector({[1]=nil, [2]=nil, [3]=nil, [4]=nil, [5]=nil,}) + self._passengers_locked = data.stored_passengers_locked + --minetest.debug("loaded: ", self._energy) + local properties = self.object:get_properties() + properties.infotext = data.stored_owner .. " nice airship" + self.object:set_properties(properties) + end + + local colstr = ap_airship.colors[self.color] + if not colstr then + colstr = "blue" + self.color = colstr + end + ap_airship.paint(self, self.color) + ap_airship.paint2(self, self.color2) + local pos = self.object:get_pos() + + self._passengers_base = ap_airship.copy_vector({[1]=nil, [2]=nil, [3]=nil, [4]=nil, [5]=nil,}) + self._passengers_base_pos = ap_airship.copy_vector({[1]=nil, [2]=nil, [3]=nil, [4]=nil, [5]=nil,}) + self._passengers_base_pos = { + [1]=ap_airship.copy_vector(ap_airship.passenger_pos[1]), + [2]=ap_airship.copy_vector(ap_airship.passenger_pos[2]), + [3]=ap_airship.copy_vector(ap_airship.passenger_pos[3]), + [4]=ap_airship.copy_vector(ap_airship.passenger_pos[4]), + [5]=ap_airship.copy_vector(ap_airship.passenger_pos[5]),} --curr pos + --self._passengers = {[1]=nil, [2]=nil, [3]=nil, [4]=nil, [5]=nil,} --passenger names + + self._passengers_base[1]=minetest.add_entity(pos,'ap_airship:stand_base') + self._passengers_base[1]:set_attach(self.object,'',self._passengers_base_pos[1],{x=0,y=0,z=0}) + + self._passengers_base[2]=minetest.add_entity(pos,'ap_airship:stand_base') + self._passengers_base[2]:set_attach(self.object,'',self._passengers_base_pos[2],{x=0,y=0,z=0}) + + self._passengers_base[3]=minetest.add_entity(pos,'ap_airship:stand_base') + self._passengers_base[3]:set_attach(self.object,'',self._passengers_base_pos[3],{x=0,y=0,z=0}) + + self._passengers_base[4]=minetest.add_entity(pos,'ap_airship:stand_base') + self._passengers_base[4]:set_attach(self.object,'',self._passengers_base_pos[4],{x=0,y=0,z=0}) + + self._passengers_base[5]=minetest.add_entity(pos,'ap_airship:stand_base') + self._passengers_base[5]:set_attach(self.object,'',self._passengers_base_pos[5],{x=0,y=0,z=0}) + + self._control_interactor=minetest.add_entity(pos,'ap_airship:control_interactor') + self._control_interactor:set_attach(self.object,'',{x=0,y=-28,z=175},{x=0,y=0,z=0}) + self._cabin_interactor=minetest.add_entity(pos,'ap_airship:cabin_interactor') + self._cabin_interactor:set_attach(self.object,'',{x=-6,y=-28,z=115},{x=0,y=0,z=0}) + + --animation load - stoped + self.object:set_animation({x = 1, y = 47}, 0, 0, true) + + self.object:set_bone_position("low_rudder_a", {x=0,y=0,z=-40}, {x=-5.35,y=0,z=0}) + + self.object:set_armor_groups({immortal=1}) + + airutils.actfunc(self, staticdata, dtime_s) + + self.object:set_armor_groups({immortal=1}) + + local inv = minetest.get_inventory({type = "detached", name = self._inv_id}) + -- if the game was closed the inventories have to be made anew, instead of just reattached + if not inv then + airutils.create_inventory(self, ap_airship.trunk_slots) + else + self.inv = inv + end + + ap_airship.engine_step(self, 0) + end, + + on_step = function(self,dtime,colinfo) + self.dtime = math.min(dtime,0.2) + self.colinfo = colinfo + self.height = airutils.get_box_height(self) + + -- physics comes first + local vel = self.object:get_velocity() + + if colinfo then + self.isonground = colinfo.touching_ground + else + if self.lastvelocity.y==0 and vel.y==0 then + self.isonground = true + else + self.isonground = false + end + end + + self:physics() + + if self.logic then + self:logic() + end + + self.lastvelocity = self.object:get_velocity() + self.time_total=self.time_total+self.dtime + end, + logic = function(self) + + 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 newpitch = pitch + local roll = rotation.z + + local hull_direction = minetest.yaw_to_dir(yaw) + local nhdir = {x=hull_direction.z,y=0,z=-hull_direction.x} -- lateral unit vector + local velocity = self.object:get_velocity() + + local longit_speed = ap_airship.dot(velocity,hull_direction) + self._longit_speed = longit_speed --for anchor verify + local longit_drag = vector.multiply(hull_direction,longit_speed* + longit_speed*LONGIT_DRAG_FACTOR*-1*ap_airship.sign(longit_speed)) + local later_speed = ap_airship.dot(velocity,nhdir) + local later_drag = vector.multiply(nhdir,later_speed*later_speed* + LATER_DRAG_FACTOR*-1*ap_airship.sign(later_speed)) + local accel = vector.add(longit_drag,later_drag) + + local vel = self.object:get_velocity() + local curr_pos = self.object:get_pos() + self._last_pos = curr_pos + self.object:move_to(curr_pos) + + --minetest.chat_send_all(self._energy) + --local node_bellow = airutils.nodeatpos(airutils.pos_shift(curr_pos,{y=-2.8})) + --[[local is_flying = true + if node_bellow and node_bellow.drawtype ~= 'airlike' then is_flying = false end]]-- + + local is_attached = false + local player = nil + if self.driver_name then + player = minetest.get_player_by_name(self.driver_name) + + if player then + is_attached = ap_airship.checkAttach(self, player) + end + end + + if self.owner == "" then return end + --[[if longit_speed == 0 and is_flying == false and is_attached == false and self._engine_running == false then + self.object:move_to(curr_pos) + --self.object:set_acceleration({x=0,y=airutils.gravity,z=0}) + return + end]]-- + + --detect collision + ap_airship.testDamage(self, vel, curr_pos) + + accel = ap_airship.control(self, self.dtime, hull_direction, longit_speed, accel) or vel + + --get disconnected players + ap_airship.rescueConnectionFailedPassengers(self) + + local turn_rate = math.rad(9) + newyaw = yaw + self.dtime*(1 - 1 / (math.abs(longit_speed) + 1)) * + self._rudder_angle / 30 * turn_rate * ap_airship.sign(longit_speed) + + ap_airship.engine_step(self, accel) + + --roll adjust + --------------------------------- + local sdir = minetest.yaw_to_dir(newyaw) + local snormal = {x=sdir.z,y=0,z=-sdir.x} -- rightside, dot is negative + local prsr = ap_airship.dot(snormal,nhdir) + local rollfactor = -15 + local newroll = 0 + if self._last_roll ~= nil then newroll = self._last_roll end + --oscilation when stoped + if longit_speed == 0 then + local time_correction = (self.dtime/ap_airship.ideal_step) + --stoped + if self._roll_state == nil then + self._roll_state = math.floor(math.random(-1,1)) + if self._roll_state == 0 then self._roll_state = 1 end + self._last_roll = newroll + end + if math.deg(newroll) >= 1 and self._roll_state == 1 then + self._roll_state = -1 + end + if math.deg(newroll) <= -1 and self._roll_state == -1 then + self._roll_state = 1 + end + local roll_factor = (self._roll_state * 0.005) * time_correction + self._last_roll = self._last_roll + math.rad(roll_factor) + else + --in movement + self._roll_state = nil + newroll = (prsr*math.rad(rollfactor))*later_speed + self._last_roll = newroll + end + --minetest.chat_send_all('newroll: '.. newroll) + --------------------------------- + -- end roll + local wind = airutils.get_wind(curr_pos, 0.3) + local wind_yaw = minetest.dir_to_yaw(wind) + --minetest.chat_send_all("x: "..wind.x.. " - z: "..wind.z.." - yaw: "..math.deg(wind_yaw).. " - orig: "..wind_yaw) + + if self.anchored == false then + accel = vector.add(accel, wind) + else + accel = vector.new() + end + accel.y = accel_y + + newpitch = velocity.y * math.rad(1.5) * (longit_speed/3) + self.object:set_acceleration(accel) + self.object:set_rotation({x=newpitch,y=newyaw,z=newroll}) + + local N_angle = math.deg(newyaw) + local S_angle = N_angle + 180 + + self.object:set_bone_position("elevator", {x=0,y=60.5919,z=-284.79}, {x=0,y=newpitch,z=0}) + self.object:set_bone_position("rudder", {x=0,y=60.5919,z=-284.79}, {x=0,y=self._rudder_angle-180,z=0}) + self.object:set_bone_position("timao", {x=0,y=-22.562,z=176.018}, {x=0,y=0,z=self._rudder_angle*8}) + self.object:set_bone_position("compass_axis", {x=0,y=-21.8,z=178.757}, {x=0, y=S_angle, z=0}) + + --saves last velocy for collision detection (abrupt stop) + self._last_vel = self.object:get_velocity() + self._last_accell = accel + + ap_airship.move_persons(self) + end, + + on_punch = function(self, puncher, ttime, toolcaps, dir, damage) + if not puncher or not puncher:is_player() then + return + end + 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 + if self.owner == nil then + self.owner = name + 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 + return + end + + local is_attached = ap_airship.checkAttach(self, puncher) + + local itmstck=puncher:get_wielded_item() + local item_name = "" + if itmstck then item_name = itmstck:get_name() end + + if is_attached == true then + --refuel + ap_airship.load_fuel(self, puncher) + end + + -- deal with painting or destroying + if itmstck then + local _,indx = item_name:find('dye:') + if indx then + + --lets paint!!!! + local color = item_name:sub(indx+1) + local colstr = ap_airship.colors[color] + --minetest.chat_send_all(color ..' '.. dump(colstr)) + if colstr and (name == self.owner or minetest.check_player_privs(puncher, {protection_bypass=true})) then + local ctrl = puncher:get_player_control() + if ctrl.aux1 then + ap_airship.paint2(self, colstr) + else + ap_airship.paint(self, colstr) + end + itmstck:set_count(itmstck:get_count()-1) + puncher:set_wielded_item(itmstck) + end + -- end painting + end + end + + if is_attached == false then + local i = 0 + local has_passengers = false + for i = ap_airship.max_seats,1,-1 + do + if self._passengers[i] ~= nil then + has_passengers = true + break + end + end + + + if not has_passengers and toolcaps and toolcaps.damage_groups and + toolcaps.groupcaps and toolcaps.groupcaps.choppy then + + local is_empty = true --[[false + local inventory = airutils.get_inventory(self) + if inventory then + if inventory:is_empty("main") then is_empty = true end + end]]-- + + --airutils.make_sound(self,'hit') + if is_empty == true then + self.hp = self.hp - 10 + minetest.sound_play("ap_airship_collision", { + object = self.object, + max_hear_distance = 5, + gain = 1.0, + fade = 0.0, + pitch = 1.0, + }) + end + end + + if self.hp <= 0 then + ap_airship.destroy(self, false) + end + + end + + end, + + on_rightclick = right_click_function, +}) diff --git a/forms.lua b/forms.lua new file mode 100755 index 0000000..995e60c --- /dev/null +++ b/forms.lua @@ -0,0 +1,467 @@ + +-------------- +-- Manual -- +-------------- + +function ap_airship.getPlaneFromPlayer(player) + local seat = player:get_attach() + if seat then + local plane = seat:get_attach() + return plane + end + return nil +end + +function ap_airship.pilot_formspec(name) + local basic_form = table.concat({ + "formspec_version[5]", + "size[6,9]", + }, "") + + local player = minetest.get_player_by_name(name) + local plane_obj = ap_airship.getPlaneFromPlayer(player) + if plane_obj == nil then + return + end + local ent = plane_obj:get_luaentity() + + local take_control = "false" + if ent._at_control then take_control = "true" end + local anchor = "false" + if ent.anchored == true then anchor = "true" end + + basic_form = basic_form.."button[1,1.0;4,1;turn_on;Start/Stop the fire]" + basic_form = basic_form.."button[1,3.0;4,1;inventory;Open inventory]" + basic_form = basic_form.."button[1,4.0;4,1;manual;Show Manual Menu]" + + basic_form = basic_form.."checkbox[1,5.6;take_control;Take the Control;"..take_control.."]" + basic_form = basic_form.."checkbox[1,6.2;anchor;Anchor away;"..anchor.."]" + + basic_form = basic_form.."label[1,7.0;Disembark:]" + basic_form = basic_form.."button[1,7.2;2,1;disembark_l;<< Left]" + basic_form = basic_form.."button[3,7.2;2,1;disembark_r;Right >>]" + + minetest.show_formspec(name, "ap_airship:pilot_main", basic_form) +end + +function ap_airship.pax_formspec(name) + local basic_form = table.concat({ + "formspec_version[3]", + "size[6,3]", + }, "") + + basic_form = basic_form.."label[1,1.0;Disembark:]" + basic_form = basic_form.."button[1,1.2;2,1;disembark_l;<< Left]" + basic_form = basic_form.."button[3,1.2;2,1;disembark_r;Right >>]" + + minetest.show_formspec(name, "ap_airship:passenger_main", basic_form) +end + +function ap_airship.logo_formspec(name) + local basic_form = table.concat({ + "formspec_version[3]", + "size[6,4]", + }, "") + + local logos = {"airship_clover.png","airship_liz.png","airship_shotting_star.png","airship_skull.png", "airship_jack.png",} + local logolist = "" + for k, v in pairs(logos) do + logolist = logolist .. v .. "," + end + + basic_form = basic_form.."label[1,1.0;Select a logo:]" + basic_form = basic_form.."dropdown[1,1.2;4,0.6;logo;"..logolist..";0;false]" + basic_form = basic_form.."button[1,2.2;4,0.8;set_logo;Set Airship Logo]" + + minetest.show_formspec(name, "ap_airship:logo_main", basic_form) +end + +function ap_airship.owner_formspec(name) + local basic_form = table.concat({ + "formspec_version[3]", + "size[6,4.2]", + }, "") + + basic_form = basic_form.."button[1,1.0;4,1;take;Take the Control Now]" + basic_form = basic_form.."label[1,2.2;Disembark:]" + basic_form = basic_form.."button[1,2.4;2,1;disembark_l;<< Left]" + basic_form = basic_form.."button[3,2.4;2,1;disembark_r;Right >>]" + + minetest.show_formspec(name, "ap_airship:owner_main", basic_form) +end + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname == "ap_airship:owner_main" then + local name = player:get_player_name() + local plane_obj = ap_airship.getPlaneFromPlayer(player) + if plane_obj == nil then + minetest.close_formspec(name, "ap_airship:owner_main") + return + end + local ent = plane_obj:get_luaentity() + if ent then + if fields.disembark_l then + ap_airship.dettach_pax(ent, player, "l") + end + if fields.disembark_r then + ap_airship.dettach_pax(ent, player, "r") + end + if fields.take then + ent._at_control = true + for i = 5,1,-1 + do + if ent._passengers[i] == name then + ent._passengers_base_pos[i] = vector.new(ap_airship.pilot_base_pos) + ent._passengers_base[i]:set_attach(ent.object,'',ap_airship.pilot_base_pos,{x=0,y=0,z=0}) + player:set_attach(ent._passengers_base[i], "", {x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0}) + end + if ent._passengers[i] == ent.driver_name then + ent._passengers_base_pos[i] = vector.new(ap_airship.passenger_pos[i]) + ent._passengers_base[i]:set_attach(ent.object,'',ent._passengers_base_pos[i],{x=0,y=0,z=0}) + end + end + ent.driver_name = name + end + end + minetest.close_formspec(name, "ap_airship:owner_main") + end + if formname == "ap_airship:passenger_main" then + local name = player:get_player_name() + local plane_obj = ap_airship.getPlaneFromPlayer(player) + if plane_obj == nil then + minetest.close_formspec(name, "ap_airship:passenger_main") + return + end + local ent = plane_obj:get_luaentity() + if ent then + if fields.disembark_l then + ap_airship.dettach_pax(ent, player, "l") + end + if fields.disembark_r then + ap_airship.dettach_pax(ent, player, "r") + end + end + minetest.close_formspec(name, "ap_airship:passenger_main") + end + if formname == "ap_airship:logo_main" then + local name = player:get_player_name() + local plane_obj = ap_airship.getPlaneFromPlayer(player) + if plane_obj == nil then + minetest.close_formspec(name, "ap_airship:logo_main") + return + end + local ent = plane_obj:get_luaentity() + if ent then + if fields.logo or fields.set_logo then + ap_airship.set_logo(ent, fields.logo) + end + end + minetest.close_formspec(name, "ap_airship:logo_main") + end + if formname == "ap_airship:pilot_main" then + local name = player:get_player_name() + local plane_obj = ap_airship.getPlaneFromPlayer(player) + if plane_obj == nil then + minetest.close_formspec(name, "ap_airship:pilot_main") + return + end + local ent = plane_obj:get_luaentity() + if ent then + if fields.turn_on then + ap_airship.start_furnace(ent) + end + if fields.inventory then + airutils.show_vehicle_trunk_formspec(ent, player, ap_airship.trunk_slots) + end + if fields.manual then + ap_airship.manual_formspec(name) + end + if fields.take_control then + if fields.take_control == "true" then + if ent.driver_name == nil or ent.driver_name == "" then + ent._at_control = true + for i = 5,1,-1 + do + if ent._passengers[i] == name then + ent._passengers_base_pos[i] = vector.new(ap_airship.pilot_base_pos) + ent._passengers_base[i]:set_attach(ent.object,'',ap_airship.pilot_base_pos,{x=0,y=0,z=0}) + player:set_attach(ent._passengers_base[i], "", {x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0}) + ent.driver_name = name + --minetest.chat_send_all(">>"..ent.driver_name) + break + end + end + else + minetest.chat_send_player(name,core.colorize('#ff0000', " >>> Impossible. Someone is at the airship control now.")) + end + else + ent.driver_name = nil + ent._at_control = false + ap_airship.remove_hud(player) + end + end + if fields.disembark_l then + --========================= + -- dettach player + --========================= + -- eject passenger if the plane is on ground + ent.driver_name = nil + ent._at_control = false + + ap_airship.dettach_pax(ent, player, "l") + + end + if fields.disembark_r then + --========================= + -- dettach player + --========================= + -- eject passenger if the plane is on ground + ent.driver_name = nil + ent._at_control = false + + ap_airship.dettach_pax(ent, player, "r") + + end + if fields.bring then + + end + if fields.anchor then + if fields.anchor == "true" then + local max_speed_anchor = 0.6 + if ent._longit_speed then + if math.abs(ent._longit_speed) < max_speed_anchor then + + ent.anchored = true + ent.object:set_acceleration(vector.new()) + ent.object:set_velocity(vector.new()) + if name then + minetest.chat_send_player(name,core.colorize('#00ff00', " >>> Anchor away!")) + end + --ent.buoyancy = 0.1 + else + if name then + minetest.chat_send_player(name,core.colorize('#ff0000', " >>> Too fast to set anchor!")) + end + end + end + else + ent.anchored = false + if name then + minetest.chat_send_player(name,core.colorize('#00ff00', " >>> Weigh anchor!")) + end + end + --ent._rudder_angle = 0 + end + end + minetest.close_formspec(name, "ap_airship:pilot_main") + end +end) + + +minetest.register_chatcommand("airship_share", { + params = "name", + description = "Share ownewrship with your friends", + privs = {interact = true}, + func = function(name, param) + local player = minetest.get_player_by_name(name) + local target_player = minetest.get_player_by_name(param) + local attached_to = player:get_attach() + + if attached_to ~= nil and target_player ~= nil then + local seat = attached_to:get_attach() + if seat ~= nil then + local entity = seat:get_luaentity() + if entity then + if entity.name == "ap_airship:airship" then + if entity.owner == name then + local exists = false + for k, v in pairs(entity._shared_owners) do + if v == param then + exists = true + break + end + end + if exists == false then + table.insert(entity._shared_owners, param) + minetest.chat_send_player(name,core.colorize('#00ff00', " >>> airship shared")) + --minetest.chat_send_all(dump(entity._shared_owners)) + else + minetest.chat_send_player(name,core.colorize('#ff0000', " >>> this user is already registered for airship share")) + end + else + minetest.chat_send_player(name,core.colorize('#ff0000', " >>> only the owner can share this airship")) + end + else + minetest.chat_send_player(name,core.colorize('#ff0000', " >>> you are not inside a airship to perform this command")) + end + end + end + else + minetest.chat_send_player(name,core.colorize('#ff0000', " >>> you are not inside a airship to perform this command")) + end + end +}) + +minetest.register_chatcommand("airship_remove", { + params = "name", + description = "Removes ownewrship from someone", + privs = {interact = true}, + func = function(name, param) + local player = minetest.get_player_by_name(name) + local attached_to = player:get_attach() + + if attached_to ~= nil then + local seat = attached_to:get_attach() + if seat ~= nil then + local entity = seat:get_luaentity() + if entity then + if entity.name == "ap_airship:airship" then + if entity.owner == name then + for k, v in pairs(entity._shared_owners) do + if v == param then + table.remove(entity._shared_owners,k) + break + end + end + minetest.chat_send_player(name,core.colorize('#00ff00', " >>> user removed")) + --minetest.chat_send_all(dump(entity._shared_owners)) + else + minetest.chat_send_player(name,core.colorize('#ff0000', " >>> only the owner can do this action")) + end + else + minetest.chat_send_player(name,core.colorize('#ff0000', " >>> you are not inside a airship to perform this command")) + end + end + end + else + minetest.chat_send_player(name,core.colorize('#ff0000', " >>> you are not inside a airship to perform this command")) + end + end +}) + +minetest.register_chatcommand("airship_list", { + params = "", + description = "Lists the airship shared owners", + privs = {interact = true}, + func = function(name, param) + local player = minetest.get_player_by_name(name) + local attached_to = player:get_attach() + + if attached_to ~= nil then + local seat = attached_to:get_attach() + if seat ~= nil then + local entity = seat:get_luaentity() + if entity then + if entity.name == "ap_airship:airship" then + minetest.chat_send_player(name,core.colorize('#ffff00', " >>> Current owners are:")) + minetest.chat_send_player(name,core.colorize('#0000ff', entity.owner)) + for k, v in pairs(entity._shared_owners) do + minetest.chat_send_player(name,core.colorize('#00ff00', v)) + end + --minetest.chat_send_all(dump(entity._shared_owners)) + else + minetest.chat_send_player(name,core.colorize('#ff0000', " >>> you are not inside a airship to perform this command")) + end + end + end + else + minetest.chat_send_player(name,core.colorize('#ff0000', " >>> you are not inside a airship to perform this command")) + end + end +}) + +minetest.register_chatcommand("airship_lock", { + params = "true/false", + description = "Blocks boarding of non-owners. true to lock, false to unlock", + privs = {interact = true}, + func = function(name, param) + local player = minetest.get_player_by_name(name) + local attached_to = player:get_attach() + + if attached_to ~= nil then + local seat = attached_to:get_attach() + if seat ~= nil then + local entity = seat:get_luaentity() + if entity then + if entity.name == "ap_airship:airship" then + if param == "true" then + entity._passengers_locked = true + minetest.chat_send_player(name,core.colorize('#ffff00', " >>> Non owners cannot enter now.")) + elseif param == "false" then + entity._passengers_locked = false + minetest.chat_send_player(name,core.colorize('#00ff00', " >>> Non owners are free to enter now.")) + end + else + minetest.chat_send_player(name,core.colorize('#ff0000', " >>> you are not inside a airship to perform this command")) + end + end + end + else + minetest.chat_send_player(name,core.colorize('#ff0000', " >>> you are not inside a airship to perform this command")) + end + end +}) + +minetest.register_chatcommand("airship_logo", { + params = "", + description = "Changes airship logo", + privs = {interact = true}, + func = function(name, param) + local player = minetest.get_player_by_name(name) + local attached_to = player:get_attach() + + if attached_to ~= nil then + local seat = attached_to:get_attach() + if seat ~= nil then + local entity = seat:get_luaentity() + if entity then + if entity.name == "ap_airship:airship" then + if entity.owner == name then + ap_airship.logo_formspec(name) + --minetest.chat_send_all(dump(entity._shared_owners)) + else + minetest.chat_send_player(name,core.colorize('#ff0000', " >>> only the owner can do this action")) + end + else + minetest.chat_send_player(name,core.colorize('#ff0000', " >>> you are not inside a airship to perform this command")) + end + end + end + else + minetest.chat_send_player(name,core.colorize('#ff0000', " >>> you are not inside a airship to perform this command")) + end + end +}) + +minetest.register_chatcommand("airship_eject", { + params = "", + description = "Ejects from the airship - useful for clients before 5.3", + privs = {interact = true}, + func = function(name, param) + local colorstring = core.colorize('#ff0000', " >>> you are not inside a airship") + local player = minetest.get_player_by_name(name) + local attached_to = player:get_attach() + + if attached_to ~= nil then + local seat = attached_to:get_attach() + if seat ~= nil then + local entity = seat:get_luaentity() + if entity then + if entity.name == "ap_airship:airship" then + for i = 5,1,-1 + do + if entity._passengers[i] == name then + ap_airship.dettach_pax(entity, player, "l") + break + end + end + else + minetest.chat_send_player(name,colorstring) + end + end + end + else + minetest.chat_send_player(name,colorstring) + end + end +}) diff --git a/fuel_management.lua b/fuel_management.lua new file mode 100755 index 0000000..f788c31 --- /dev/null +++ b/fuel_management.lua @@ -0,0 +1,58 @@ +-- +-- fuel +-- +ap_airship.MAX_FUEL = minetest.settings:get("ap_airship_max_fuel") or 99 +ap_airship.FUEL_CONSUMPTION = minetest.settings:get("ap_airship_fuel_consumption") or 6000 + +function ap_airship.contains(table, val) + for k,v in pairs(table) do + if k == val then + return v + end + end + return false +end + +function ap_airship.load_fuel(self, player) + local inv = player:get_inventory() + + local itmstck=player:get_wielded_item() + local item_name = "" + if itmstck then item_name = itmstck:get_name() end + + local grp_wood = minetest.get_item_group(item_name, "wood") + local grp_tree = minetest.get_item_group(item_name, "tree") + if grp_wood == 1 or grp_tree == 1 then + local stack = ItemStack(item_name .. " 1") + + if self._energy < ap_airship.MAX_FUEL then + inv:remove_item("main", stack) + local amount = 1 + if grp_tree == 1 then amount = 4 end + self._energy = self._energy + amount + if self._energy > ap_airship.MAX_FUEL then self._energy = ap_airship.MAX_FUEL end + end + return true + end + + --minetest.chat_send_all("fuel: ".. dump(item_name)) + local fuel = ap_airship.contains(ap_airship.fuel, item_name) + if fuel then + local stack = ItemStack(item_name .. " 1") + + if self._energy < ap_airship.MAX_FUEL then + inv:remove_item("main", stack) + self._energy = self._energy + fuel.amount + if self._energy > ap_airship.MAX_FUEL then self._energy = ap_airship.MAX_FUEL end + --minetest.chat_send_all(self.energy) + + --local energy_indicator_angle = ap_airship.get_pointer_angle(self._energy, ap_airship.MAX_FUEL) + end + + return true + end + + return false +end + + diff --git a/hud.lua b/hud.lua new file mode 100755 index 0000000..356d2d2 --- /dev/null +++ b/hud.lua @@ -0,0 +1,269 @@ +ap_airship.hud_list = {} + +function ap_airship.get_pointer_angle(value, maxvalue) + local angle = value/maxvalue * 180 + --angle = angle - 90 + --angle = angle * -1 + return angle +end + +function ap_airship.animate_gauge(player, ids, prefix, x, y, angle) + local angle_in_rad = math.rad(angle + 180) + local dim = 10 + local pos_x = math.sin(angle_in_rad) * dim + local pos_y = math.cos(angle_in_rad) * dim + player:hud_change(ids[prefix .. "2"], "offset", {x = pos_x + x, y = pos_y + y}) + dim = 20 + pos_x = math.sin(angle_in_rad) * dim + pos_y = math.cos(angle_in_rad) * dim + player:hud_change(ids[prefix .. "3"], "offset", {x = pos_x + x, y = pos_y + y}) + dim = 30 + pos_x = math.sin(angle_in_rad) * dim + pos_y = math.cos(angle_in_rad) * dim + player:hud_change(ids[prefix .. "4"], "offset", {x = pos_x + x, y = pos_y + y}) + dim = 40 + pos_x = math.sin(angle_in_rad) * dim + pos_y = math.cos(angle_in_rad) * dim + player:hud_change(ids[prefix .. "5"], "offset", {x = pos_x + x, y = pos_y + y}) + dim = 50 + pos_x = math.sin(angle_in_rad) * dim + pos_y = math.cos(angle_in_rad) * dim + player:hud_change(ids[prefix .. "6"], "offset", {x = pos_x + x, y = pos_y + y}) + dim = 60 + pos_x = math.sin(angle_in_rad) * dim + pos_y = math.cos(angle_in_rad) * dim + player:hud_change(ids[prefix .. "7"], "offset", {x = pos_x + x, y = pos_y + y}) +end + +function ap_airship.update_hud(player, coal, water, pressure, power_lever) + if player == nil then return end + local player_name = player:get_player_name() + + local screen_pos_y = -100 + local screen_pos_x = 10 + + local water_gauge_x = screen_pos_x + 374 + local water_gauge_y = screen_pos_y + local press_gauge_x = screen_pos_x + 85 + local press_gauge_y = water_gauge_y + local coal_1_x = screen_pos_x + 182 + local coal_1_y = screen_pos_y + local coal_2_x = coal_1_x + 60 + local coal_2_y = screen_pos_y + local throttle_x = screen_pos_x + 395 + local throttle_y = screen_pos_y + 45 + + local ids = ap_airship.hud_list[player_name] + if ids then + player:hud_change(ids["throttle"], "offset", {x = throttle_x, y = throttle_y - power_lever}) + + --[[local coal_value = coal + if coal_value > 99 then coal_value = 99 end + if coal_value < 0 then coal_value = 0 end + player:hud_change(ids["coal_1"], "text", "ap_airship_"..(math.floor(coal_value/10))..".png") + player:hud_change(ids["coal_2"], "text", "ap_airship_"..(math.floor(coal_value%10))..".png")]]-- + + --[[ap_airship.animate_gauge(player, ids, "water_pt_", water_gauge_x, water_gauge_y, water) + ap_airship.animate_gauge(player, ids, "press_pt_", press_gauge_x, press_gauge_y, pressure)]]-- + else + ids = {} + + ids["title"] = player:hud_add({ + hud_elem_type = "text", + position = {x = 0, y = 1}, + offset = {x = screen_pos_x + 240, y = screen_pos_y - 100}, + text = "Airship engine state", + alignment = 0, + scale = { x = 100, y = 30}, + number = 0xFFFFFF, + }) + + ids["bg"] = player:hud_add({ + hud_elem_type = "image", + position = {x = 0, y = 1}, + offset = {x = screen_pos_x, y = screen_pos_y}, + text = "ap_airship_hud_panel.png", + scale = { x = 0.5, y = 0.5}, + alignment = { x = 1, y = 0 }, + }) + + ids["throttle"] = player:hud_add({ + hud_elem_type = "image", + position = {x = 0, y = 1}, + offset = {x = throttle_x, y = throttle_y}, + text = "ap_airship_throttle.png", + scale = { x = 0.5, y = 0.5}, + alignment = { x = 1, y = 0 }, + }) + + --[[ids["coal_1"] = player:hud_add({ + hud_elem_type = "image", + position = {x = 0, y = 1}, + offset = {x = coal_1_x, y = coal_1_y}, + text = "ap_airship_0.png", + scale = { x = 0.5, y = 0.5}, + alignment = { x = 1, y = 0 }, + }) + + ids["coal_2"] = player:hud_add({ + hud_elem_type = "image", + position = {x = 0, y = 1}, + offset = {x = coal_2_x, y = coal_2_y}, + text = "ap_airship_0.png", + scale = { x = 0.5, y = 0.5}, + alignment = { x = 1, y = 0 }, + })]]-- + + --[[ids["water_pt_1"] = player:hud_add({ + hud_elem_type = "image", + position = {x = 0, y = 1}, + offset = {x = water_gauge_x, y = water_gauge_y}, + text = "ap_airship_ind_box.png", + scale = { x = 6, y = 6}, + alignment = { x = 1, y = 0 }, + }) + + ids["water_pt_2"] = player:hud_add({ + hud_elem_type = "image", + position = {x = 0, y = 1}, + offset = {x = water_gauge_x, y = water_gauge_y}, + text = "ap_airship_ind_box.png", + scale = { x = 6, y = 6}, + alignment = { x = 1, y = 0 }, + }) + ids["water_pt_3"] = player:hud_add({ + hud_elem_type = "image", + position = {x = 0, y = 1}, + offset = {x = water_gauge_x, y = water_gauge_y}, + text = "ap_airship_ind_box.png", + scale = { x = 6, y = 6}, + alignment = { x = 1, y = 0 }, + }) + ids["water_pt_4"] = player:hud_add({ + hud_elem_type = "image", + position = {x = 0, y = 1}, + offset = {x = water_gauge_x, y = water_gauge_y}, + text = "ap_airship_ind_box.png", + scale = { x = 6, y = 6}, + alignment = { x = 1, y = 0 }, + }) + ids["water_pt_5"] = player:hud_add({ + hud_elem_type = "image", + position = {x = 0, y = 1}, + offset = {x = water_gauge_x, y = water_gauge_y}, + text = "ap_airship_ind_box.png", + scale = { x = 6, y = 6}, + alignment = { x = 1, y = 0 }, + }) + ids["water_pt_6"] = player:hud_add({ + hud_elem_type = "image", + position = {x = 0, y = 1}, + offset = {x = water_gauge_x, y = water_gauge_y}, + text = "ap_airship_ind_box.png", + scale = { x = 6, y = 6}, + alignment = { x = 1, y = 0 }, + }) + ids["water_pt_7"] = player:hud_add({ + hud_elem_type = "image", + position = {x = 0, y = 1}, + offset = {x = water_gauge_x, y = water_gauge_y}, + text = "ap_airship_ind_box.png", + scale = { x = 6, y = 6}, + alignment = { x = 1, y = 0 }, + }) + + ids["press_pt_1"] = player:hud_add({ + hud_elem_type = "image", + position = {x = 0, y = 1}, + offset = {x = press_gauge_x, y = press_gauge_y}, + text = "ap_airship_ind_box.png", + scale = { x = 6, y = 6}, + alignment = { x = 1, y = 0 }, + }) + ids["press_pt_2"] = player:hud_add({ + hud_elem_type = "image", + position = {x = 0, y = 1}, + offset = {x = press_gauge_x, y = press_gauge_y}, + text = "ap_airship_ind_box.png", + scale = { x = 6, y = 6}, + alignment = { x = 1, y = 0 }, + }) + ids["press_pt_3"] = player:hud_add({ + hud_elem_type = "image", + position = {x = 0, y = 1}, + offset = {x = press_gauge_x, y = press_gauge_y}, + text = "ap_airship_ind_box.png", + scale = { x = 6, y = 6}, + alignment = { x = 1, y = 0 }, + }) + ids["press_pt_4"] = player:hud_add({ + hud_elem_type = "image", + position = {x = 0, y = 1}, + offset = {x = press_gauge_x, y = press_gauge_y}, + text = "ap_airship_ind_box.png", + scale = { x = 6, y = 6}, + alignment = { x = 1, y = 0 }, + }) + ids["press_pt_5"] = player:hud_add({ + hud_elem_type = "image", + position = {x = 0, y = 1}, + offset = {x = press_gauge_x, y = press_gauge_y}, + text = "ap_airship_ind_box.png", + scale = { x = 6, y = 6}, + alignment = { x = 1, y = 0 }, + }) + ids["press_pt_6"] = player:hud_add({ + hud_elem_type = "image", + position = {x = 0, y = 1}, + offset = {x = press_gauge_x, y = press_gauge_y}, + text = "ap_airship_ind_box.png", + scale = { x = 6, y = 6}, + alignment = { x = 1, y = 0 }, + }) + ids["press_pt_7"] = player:hud_add({ + hud_elem_type = "image", + position = {x = 0, y = 1}, + offset = {x = press_gauge_x, y = press_gauge_y}, + text = "ap_airship_ind_box.png", + scale = { x = 6, y = 6}, + alignment = { x = 1, y = 0 }, + })]]-- + + ap_airship.hud_list[player_name] = ids + end +end + + +function ap_airship.remove_hud(player) + if player then + local player_name = player:get_player_name() + --minetest.chat_send_all(player_name) + local ids = ap_airship.hud_list[player_name] + if ids then + --player:hud_remove(ids["altitude"]) + --player:hud_remove(ids["time"]) + player:hud_remove(ids["title"]) + player:hud_remove(ids["bg"]) + player:hud_remove(ids["throttle"]) + --[[ + player:hud_remove(ids["coal_1"]) + player:hud_remove(ids["coal_2"]) + player:hud_remove(ids["water_pt_7"]) + player:hud_remove(ids["water_pt_6"]) + player:hud_remove(ids["water_pt_5"]) + player:hud_remove(ids["water_pt_4"]) + player:hud_remove(ids["water_pt_3"]) + player:hud_remove(ids["water_pt_2"]) + player:hud_remove(ids["water_pt_1"]) + player:hud_remove(ids["press_pt_7"]) + player:hud_remove(ids["press_pt_6"]) + player:hud_remove(ids["press_pt_5"]) + player:hud_remove(ids["press_pt_4"]) + player:hud_remove(ids["press_pt_3"]) + player:hud_remove(ids["press_pt_2"]) + player:hud_remove(ids["press_pt_1"])]]-- + end + ap_airship.hud_list[player_name] = nil + end + +end diff --git a/init.lua b/init.lua new file mode 100755 index 0000000..1c8c772 --- /dev/null +++ b/init.lua @@ -0,0 +1,228 @@ +ap_airship={} +ap_airship.gravity = tonumber(minetest.settings:get("movement_gravity")) or 9.8 +ap_airship.trunk_slots = 50 +ap_airship.fuel = {['biofuel:biofuel'] = {amount=1},['biofuel:bottle_fuel'] = {amount=1}, + ['biofuel:phial_fuel'] = {amount=0.25}, ['biofuel:fuel_can'] = {amount=10}} +ap_airship.ideal_step = 0.02 +ap_airship.rudder_limit = 30 +ap_airship.iddle_rotation = 50 +ap_airship.max_engine_acc = 1.5 +ap_airship.max_speed = 8 +ap_airship.max_seats = 2 +ap_airship.pilot_base_pos = {x=0.0,y=-29,z=170} +ap_airship.passenger_pos = { + [1] = {x=0.0,y=0,z=60}, + [2] = {x=-11,y=0,z=20}, + [3] = {x=11,y=0,z=20}, + [4] = {x=-11,y=0,z=80}, + [5] = {x=11,y=0,z=80}, + } + +ap_airship.canvas_texture = "wool_white.png^[colorize:#f4e7c1:128" +ap_airship.grey_texture = "ap_airship_base.png^[colorize:#535c5c:128" +ap_airship.white_texture = "ap_airship_base.png^[colorize:#a3acac:128" +ap_airship.metal_texture = "ap_airship_metal.png" +ap_airship.black_texture = "ap_airship_base.png^[colorize:#030303:200" +ap_airship.rotor_texture = "ap_airship_helice.png" +ap_airship.textures = { + ap_airship.grey_texture, --"ap_airship_painting.png", --balao + ap_airship.metal_texture, --ponteira nariz + ap_airship.black_texture, -- corpo da bussola + ap_airship.metal_texture, -- indicador bussola + ap_airship.grey_texture, --"ap_airship_painting.png", --empenagem + ap_airship.metal_texture, --timao + ap_airship.black_texture, --timao + "ap_airship_compass.png", --bussola + "ap_airship_sup_eng.png", --suporte motores + "ap_airship_helice.png", --helice + ap_airship.black_texture, --eixo helice + ap_airship.grey_texture, --interior cabine + "default_ladder_steel.png", --escada + ap_airship.white_texture, --interior cabine 2 + "ap_airship_glass_2.png", --vidros do deck superior + ap_airship.grey_texture, -- "ap_airship_painting.png", --motor + ap_airship.grey_texture, --"ap_airship_painting.png", --cabine + "ap_airship_glass.png", --janelas + ap_airship.black_texture, --piso + "ap_airship_alpha_logo.png", --logo + ap_airship.metal_texture, + } + +ap_airship.colors ={ + black='black', + blue='blue', + brown='brown', + cyan='cyan', + dark_green='dark_green', + dark_grey='dark_grey', + green='green', + grey='grey', + magenta='magenta', + orange='orange', + pink='pink', + red='red', + violet='violet', + white='white', + yellow='yellow', +} + +dofile(minetest.get_modpath("ap_airship") .. DIR_DELIM .. "utilities.lua") +dofile(minetest.get_modpath("ap_airship") .. DIR_DELIM .. "control.lua") +dofile(minetest.get_modpath("ap_airship") .. DIR_DELIM .. "fuel_management.lua") +dofile(minetest.get_modpath("ap_airship") .. DIR_DELIM .. "engine_management.lua") +dofile(minetest.get_modpath("ap_airship") .. DIR_DELIM .. "custom_physics.lua") +dofile(minetest.get_modpath("ap_airship") .. DIR_DELIM .. "hud.lua") +dofile(minetest.get_modpath("ap_airship") .. DIR_DELIM .. "entities.lua") +dofile(minetest.get_modpath("ap_airship") .. DIR_DELIM .. "forms.lua") +dofile(minetest.get_modpath("ap_airship") .. DIR_DELIM .. "manual.lua") +dofile(minetest.get_modpath("ap_airship") .. DIR_DELIM .. "walk_map.lua") + +-- +-- helpers and co. +-- + +function ap_airship.get_hipotenuse_value(point1, point2) + return math.sqrt((point1.x - point2.x) ^ 2 + (point1.y - point2.y) ^ 2 + (point1.z - point2.z) ^ 2) +end + +function ap_airship.dot(v1,v2) + return v1.x*v2.x+v1.y*v2.y+v1.z*v2.z +end + +function ap_airship.sign(n) + return n>=0 and 1 or -1 +end + +function ap_airship.minmax(v,m) + return math.min(math.abs(v),m)*ap_airship.sign(v) +end + +----------- +-- items +----------- + +-- airship +minetest.register_craftitem("ap_airship:airship", { + description = "Airship", + inventory_image = "ap_airship_icon.png", + liquids_pointable = true, + + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" then + return + end + + local pointed_pos = pointed_thing.under + --local node_below = minetest.get_node(pointed_pos).name + --local nodedef = minetest.registered_nodes[node_below] + + pointed_pos.y=pointed_pos.y+4 + local airship = minetest.add_entity(pointed_pos, "ap_airship:airship") + if airship and placer then + local ent = airship:get_luaentity() + ent._passengers = ap_airship.copy_vector({[1]=nil, [2]=nil, [3]=nil, [4]=nil, [5]=nil,}) + --minetest.chat_send_all('passengers: '.. dump(ent._passengers)) + local owner = placer:get_player_name() + ent.owner = owner + airship:set_yaw(placer:get_look_horizontal()) + itemstack:take_item() + airutils.create_inventory(ent, ap_airship.trunk_slots, owner) + + local properties = ent.object:get_properties() + properties.infotext = owner .. " nice airship" + airship:set_properties(properties) + --ap_airship.attach_pax(ent, placer) + end + + return itemstack + end, +}) + + +-- +-- crafting +-- + +if not minetest.settings:get_bool('ap_airship.disable_craftitems') then + --[[minetest.register_craft({ + output = "ap_airship:cylinder_part", + recipe = { + {"default:stick", "wool:white", "default:stick"}, + {"wool:white", "group:wood", "wool:white"}, + {"default:stick", "wool:white", "default:stick"}, + } + }) + + minetest.register_craft({ + output = "ap_airship:cylinder", + recipe = { + {"ap_airship:cylinder_part", "ap_airship:cylinder_part", "ap_airship:cylinder_part"}, + } + }) + + minetest.register_craft({ + output = "ap_airship:rotor", + recipe = { + {"wool:white", "default:stick", ""}, + {"wool:white", "default:stick", "default:steelblock"}, + {"wool:white", "default:stick", ""}, + } + }) + + minetest.register_craft({ + output = "ap_airship:boiler", + recipe = { + {"default:steel_ingot","default:steel_ingot"}, + {"default:steelblock","default:steel_ingot",}, + {"default:steelblock","default:steel_ingot"}, + } + }) + + minetest.register_craft({ + output = "ap_airship:boat", + recipe = { + {"group:wood", "group:wood", "ap_airship:rotor"}, + {"group:wood", "ap_airship:boiler", "group:wood"}, + {"group:wood", "group:wood", "ap_airship:rotor"}, + } + }) + + minetest.register_craft({ + output = "ap_airship:airship", + recipe = { + {"ap_airship:cylinder",}, + {"ap_airship:boat",}, + } + })]]-- + + -- cylinder section + --[[minetest.register_craftitem("ap_airship:cylinder_part",{ + description = "ap_airship cylinder section", + inventory_image = "ap_airship_cylinder_part.png", + }) + + -- cylinder + minetest.register_craftitem("ap_airship:cylinder",{ + description = "ap_airship cylinder", + inventory_image = "ap_airship_cylinder.png", + }) + + -- boiler + minetest.register_craftitem("ap_airship:boiler",{ + description = "ap_airship boiler", + inventory_image = "ap_airship_boiler.png", + }) + + -- boiler + minetest.register_craftitem("ap_airship:rotor",{ + description = "ap_airship rotor", + inventory_image = "ap_airship_rotor.png", + }) + + -- fuselage + minetest.register_craftitem("ap_airship:boat",{ + description = "ap_airship fuselage", + inventory_image = "ap_airship_boat.png", + })]]-- +end + diff --git a/manual.lua b/manual.lua new file mode 100755 index 0000000..071fb57 --- /dev/null +++ b/manual.lua @@ -0,0 +1,91 @@ +-------------- +-- Manual -- +-------------- + +function ap_airship.manual_formspec(name) + local basic_form = table.concat({ + "formspec_version[3]", + "size[6,6]" + }, "") + + basic_form = basic_form.."button[1,1.0;4,1;short;Shortcuts]" + basic_form = basic_form.."button[1,2.5;4,1;fuel;Refueling]" + basic_form = basic_form.."button[1,4.0;4,1;share;Sharing]" + + minetest.show_formspec(name, "ap_airship:manual_main", basic_form) +end + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname == "ap_airship:manual_main" then + local formspec_color = "#44444466" + if fields.short then + local text = { + "Shortcuts \n\n", + "* Right click: enter in / acess the internal menu \n", + "* Punch with dye to paint the primary color\n", + "* Punch a dye, but holding Aux (E) key to change the secondary color.\n", + "* To change the airship logo, call the command \""..core.colorize('#ffff00', "/airship_logo").."\".\n", + "* Forward or backward while in drive position: controls the power lever \n", + "* Left or right while in drive position: controls the direction \n", + "* Jump and sneak: controls the up and down movement \n", + "* Aux (E) + right click while inside: acess inventory \n", + "* Aux (E) + backward while in drive position: the machine does backward \n", + "* Aux (E) + foward while in drive position: extra power \n" + } + local shortcut_form = table.concat({ + "formspec_version[3]", + "size[16,10]", + "no_prepend[]", + "bgcolor["..formspec_color..";false]", + "label[1.0,2.0;", table.concat(text, ""), "]", + }, "") + minetest.show_formspec(player:get_player_name(), "ap_airship:manual_shortcut", shortcut_form) + end + if fields.fuel then + local text = { + "Fuel \n\n", + "To fly it, it is necessary to provide some items, such as fuel to be burned and \n", + "water for the boiler. The fuel can be coal, coal block or wood. To supply it, \n", + "be on board and punch the necessary items on the airship.\n", + "There is another way to load water to the boiler: if it is landed on water, it can load \n", + "it through the menu. But the current pressure will be lost. \n" + } + local fuel_form = table.concat({ + "formspec_version[3]", + "size[16,10]", + "no_prepend[]", + "bgcolor["..formspec_color..";false]", + "label[1.0,2.0;", table.concat(text, ""), "]", + }, "") + minetest.show_formspec(player:get_player_name(), "ap_airship:fuel", fuel_form) + end + if fields.share then + local text = { + "Sharing \n\n", + "This vehicle was made to be shared with a team. So the owner can set more users to \n", + "operate it. Inside the airship, just use the command \""..core.colorize('#ffff00', "/airship_share ").."\" \n", + "To remove someone from the sharing, \""..core.colorize('#ffff00', "/airship_remove ").."\" \n", + "To list the owners, \""..core.colorize('#ffff00', "/airship_list").."\" \n", + "Is possible to lock the airship access, so only the owners can enter: \""..core.colorize('#ffff00', "/airship_lock true").."\" \n", + "To let anyone enter, \""..core.colorize('#ffff00', "/airship_lock false").."\" \n", + "All shared owners can access the airship inventory" + } + local tips_form = table.concat({ + "formspec_version[3]", + "size[16,10]", + "no_prepend[]", + "bgcolor["..formspec_color..";false]", + "label[1,2;", table.concat(text, ""), "]", + }, "") + minetest.show_formspec(player:get_player_name(), "ap_airship:share", tips_form) + end + end +end) + +minetest.register_chatcommand("airship_manual", { + params = "", + description = "Airship manual", + func = function(name, param) + ap_airship.manual_formspec(name) + end +}) diff --git a/mod.conf b/mod.conf new file mode 100755 index 0000000..29321af --- /dev/null +++ b/mod.conf @@ -0,0 +1,6 @@ +name = ap_airship +depends = default,player_api,wool,airutils +optional_depends = climate_api +author = APercy +description = Adds an airship to minetest game +title = Airship diff --git a/models/ap_airship_light.b3d b/models/ap_airship_light.b3d new file mode 100755 index 0000000..2302148 Binary files /dev/null and b/models/ap_airship_light.b3d differ diff --git a/models/ap_airship_mesh.b3d b/models/ap_airship_mesh.b3d new file mode 100755 index 0000000..3f7383a Binary files /dev/null and b/models/ap_airship_mesh.b3d differ diff --git a/models/ap_airship_stand_base.b3d b/models/ap_airship_stand_base.b3d new file mode 100755 index 0000000..ccf1db3 Binary files /dev/null and b/models/ap_airship_stand_base.b3d differ diff --git a/sounds/ap_airship_collision.ogg b/sounds/ap_airship_collision.ogg new file mode 100755 index 0000000..b15fbb1 Binary files /dev/null and b/sounds/ap_airship_collision.ogg differ diff --git a/sounds/ap_airship_engine.ogg b/sounds/ap_airship_engine.ogg new file mode 100644 index 0000000..ef429c2 Binary files /dev/null and b/sounds/ap_airship_engine.ogg differ diff --git a/textures/ap_airship_alpha.png b/textures/ap_airship_alpha.png new file mode 100755 index 0000000..b09a735 Binary files /dev/null and b/textures/ap_airship_alpha.png differ diff --git a/textures/ap_airship_alpha_logo.png b/textures/ap_airship_alpha_logo.png new file mode 100755 index 0000000..b09a735 Binary files /dev/null and b/textures/ap_airship_alpha_logo.png differ diff --git a/textures/ap_airship_base.png b/textures/ap_airship_base.png new file mode 100644 index 0000000..0c02eaf Binary files /dev/null and b/textures/ap_airship_base.png differ diff --git a/textures/ap_airship_compass.png b/textures/ap_airship_compass.png new file mode 100644 index 0000000..22d95cd Binary files /dev/null and b/textures/ap_airship_compass.png differ diff --git a/textures/ap_airship_cylinder.png b/textures/ap_airship_cylinder.png new file mode 100755 index 0000000..a22fb7a Binary files /dev/null and b/textures/ap_airship_cylinder.png differ diff --git a/textures/ap_airship_cylinder_part.png b/textures/ap_airship_cylinder_part.png new file mode 100755 index 0000000..77763b7 Binary files /dev/null and b/textures/ap_airship_cylinder_part.png differ diff --git a/textures/ap_airship_glass.png b/textures/ap_airship_glass.png new file mode 100755 index 0000000..fdb0578 Binary files /dev/null and b/textures/ap_airship_glass.png differ diff --git a/textures/ap_airship_glass_2.png b/textures/ap_airship_glass_2.png new file mode 100755 index 0000000..6e31b6b Binary files /dev/null and b/textures/ap_airship_glass_2.png differ diff --git a/textures/ap_airship_helice.png b/textures/ap_airship_helice.png new file mode 100755 index 0000000..500fd16 Binary files /dev/null and b/textures/ap_airship_helice.png differ diff --git a/textures/ap_airship_hud_panel.png b/textures/ap_airship_hud_panel.png new file mode 100755 index 0000000..9215979 Binary files /dev/null and b/textures/ap_airship_hud_panel.png differ diff --git a/textures/ap_airship_hud_panel.xcf b/textures/ap_airship_hud_panel.xcf new file mode 100644 index 0000000..be433c5 Binary files /dev/null and b/textures/ap_airship_hud_panel.xcf differ diff --git a/textures/ap_airship_icon.png b/textures/ap_airship_icon.png new file mode 100755 index 0000000..7410bd1 Binary files /dev/null and b/textures/ap_airship_icon.png differ diff --git a/textures/ap_airship_ind_box.png b/textures/ap_airship_ind_box.png new file mode 100755 index 0000000..581208b Binary files /dev/null and b/textures/ap_airship_ind_box.png differ diff --git a/textures/ap_airship_metal.png b/textures/ap_airship_metal.png new file mode 100644 index 0000000..a779fe9 Binary files /dev/null and b/textures/ap_airship_metal.png differ diff --git a/textures/ap_airship_painting.png b/textures/ap_airship_painting.png new file mode 100644 index 0000000..0c02eaf Binary files /dev/null and b/textures/ap_airship_painting.png differ diff --git a/textures/ap_airship_rotor.png b/textures/ap_airship_rotor.png new file mode 100755 index 0000000..558c025 Binary files /dev/null and b/textures/ap_airship_rotor.png differ diff --git a/textures/ap_airship_sup_eng.png b/textures/ap_airship_sup_eng.png new file mode 100755 index 0000000..c657597 Binary files /dev/null and b/textures/ap_airship_sup_eng.png differ diff --git a/textures/ap_airship_throttle.png b/textures/ap_airship_throttle.png new file mode 100644 index 0000000..b40c33d Binary files /dev/null and b/textures/ap_airship_throttle.png differ diff --git a/textures/blimp_clover.png b/textures/blimp_clover.png new file mode 100644 index 0000000..68035ad Binary files /dev/null and b/textures/blimp_clover.png differ diff --git a/textures/blimp_jack.png b/textures/blimp_jack.png new file mode 100644 index 0000000..d79c045 Binary files /dev/null and b/textures/blimp_jack.png differ diff --git a/textures/blimp_liz.png b/textures/blimp_liz.png new file mode 100755 index 0000000..52658d7 Binary files /dev/null and b/textures/blimp_liz.png differ diff --git a/textures/blimp_shotting_star.png b/textures/blimp_shotting_star.png new file mode 100755 index 0000000..084baf0 Binary files /dev/null and b/textures/blimp_shotting_star.png differ diff --git a/textures/blimp_skull.png b/textures/blimp_skull.png new file mode 100755 index 0000000..8f71f1c Binary files /dev/null and b/textures/blimp_skull.png differ diff --git a/utilities.lua b/utilities.lua new file mode 100755 index 0000000..f43533f --- /dev/null +++ b/utilities.lua @@ -0,0 +1,419 @@ +function ap_airship.testDamage(self, velocity, position) + if self._last_accell == nil then return end + local p = position --self.object:get_pos() + local collision = false + local low_node_pos = -2.5 + if self._last_vel == nil then return end + --lets calculate the vertical speed, to avoid the bug on colliding on floor with hard lag + if math.abs(velocity.y - self._last_vel.y) > 2 then + local noded = airutils.nodeatpos(airutils.pos_shift(p,{y=low_node_pos})) + if (noded and noded.drawtype ~= 'airlike') then + collision = true + else + self.object:set_velocity(self._last_vel) + --self.object:set_acceleration(self._last_accell) + self.object:set_velocity(vector.add(velocity, vector.multiply(self._last_accell, self.dtime/8))) + end + end + local impact = math.abs(ap_airship.get_hipotenuse_value(velocity, self._last_vel)) + if impact > 2 then + if self.colinfo then + collision = self.colinfo.collides + --minetest.chat_send_all(impact) + end + end + + if collision then + --self.object:set_velocity({x=0,y=0,z=0}) + local damage = impact -- / 2 + minetest.sound_play("ap_airship_collision", { + --to_player = self.driver_name, + object = self.object, + max_hear_distance = 15, + gain = 1.0, + fade = 0.0, + pitch = 1.0, + }, true) + if damage > 5 then + self._power_lever = 0 + end + + if self.driver_name then + local player_name = self.driver_name + + local player = minetest.get_player_by_name(player_name) + if player then + if player:get_hp() > 0 then + player:set_hp(player:get_hp()-(damage/2)) + end + end + if self._passenger ~= nil then + local passenger = minetest.get_player_by_name(self._passenger) + if passenger then + if passenger:get_hp() > 0 then + passenger:set_hp(passenger:get_hp()-(damage/2)) + end + end + end + end + + end +end + +local function do_attach(self, player, slot) + if slot == 0 then return end + if self._passengers[slot] == nil then + local name = player:get_player_name() + --minetest.chat_send_all(self.driver_name) + self._passengers[slot] = name + player:set_attach(self._passengers_base[slot], "", {x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0}) + player_api.player_attached[name] = true + end +end + +function ap_airship.check_passenger_is_attached(self, name) + local is_attached = false + if is_attached == false then + for i = 5,1,-1 + do + if self._passengers[i] == name then + is_attached = true + break + end + end + end + return is_attached +end + +--this method checks each 1 second for a disconected player who comes back +function ap_airship.rescueConnectionFailedPassengers(self) + self._disconnection_check_time = self._disconnection_check_time + self.dtime + if self._disconnection_check_time > 1 then + --minetest.chat_send_all(dump(self._passengers)) + self._disconnection_check_time = 0 + for i = 5,1,-1 + do + if self._passengers[i] then + local player = minetest.get_player_by_name(self._passengers[i]) + if player then --we have a player! + if player_api.player_attached[self._passengers[i]] == nil then --but isn't attached? + --minetest.chat_send_all("okay") + if player:get_hp() > 0 then + self._passengers[i] = nil --clear the slot first + do_attach(self, player, i) --attach + else + --ap_airship.dettachPlayer(self, player) + end + end + end + end + end + end +end + +-- attach passenger +function ap_airship.attach_pax(self, player, slot) + slot = slot or 0 + + --verify if is locked to non-owners + if self._passengers_locked == true then + local name = player:get_player_name() + local can_bypass = minetest.check_player_privs(player, {protection_bypass=true}) + local is_shared = false + if name == self.owner or can_bypass then is_shared = true end + for k, v in pairs(self._shared_owners) do + if v == name then + is_shared = true + break + end + end + if is_shared == false then + minetest.chat_send_player(name,core.colorize('#ff0000', " >>> This airship is currently locked for non-owners")) + return + end + end + + + if slot > 0 then + do_attach(self, player, slot) + return + end + --minetest.chat_send_all(dump(self._passengers)) + + --now yes, lets attach the player + --randomize the seat + local t = {1,2,3,4,5} + for i = 1, #t*2 do + local a = math.random(#t) + local b = math.random(#t) + t[a],t[b] = t[b],t[a] + end + + --minetest.chat_send_all(dump(t)) + + local i=0 + for k,v in ipairs(t) do + i = t[k] + if self._passengers[i] == nil then + do_attach(self, player, i) + break + end + end +end + +function ap_airship.dettach_pax(self, player, side) + side = side or "r" + if player then + local name = player:get_player_name() --self._passenger + ap_airship.remove_hud(player) + + -- passenger clicked the object => driver gets off the vehicle + for i = 5,1,-1 + do + if self._passengers[i] == name then + self._passengers[i] = nil + self._passengers_base_pos[i] = ap_airship.copy_vector(ap_airship.passenger_pos[i]) + --break + end + end + + -- detach the player + player:set_detach() + player_api.player_attached[name] = nil + player_api.set_animation(player, "stand") + + -- move player down + minetest.after(0.1, function(pos) + local rotation = self.object:get_rotation() + local direction = rotation.y + + if side == "l" then + direction = direction - math.rad(180) + end + + local move = 5 + pos.x = pos.x + move * math.cos(direction) + pos.z = pos.z + move * math.sin(direction) + if self.isinliquid then + pos.y = pos.y + 1 + else + pos.y = pos.y - 2.5 + end + player:set_pos(pos) + end, player:get_pos()) + end +end + +function ap_airship.textures_copy() + local tablecopy = {} + for k, v in pairs(ap_airship.textures) do + tablecopy[k] = v + end + return tablecopy +end + +local function paint(self) + local l_textures = ap_airship.textures_copy() + for _, texture in ipairs(l_textures) do + local indx = texture:find('wool_blue.png') + if indx then + l_textures[_] = "wool_".. self.color..".png" + end + indx = texture:find('wool_yellow.png') + if indx then + l_textures[_] = "wool_".. self.color2..".png" + end + indx = texture:find('ap_airship_alpha_logo.png') + if indx then + l_textures[_] = self.logo + end + end + self.object:set_properties({textures=l_textures}) +end + +function ap_airship.set_logo(self, texture_name) + if texture_name == "" or texture_name == nil then + self.logo = "ap_airship_alpha_logo.png" + elseif texture_name then + self.logo = texture_name + end + paint(self) +end + +--painting +function ap_airship.paint(self, colstr) + if colstr then + self.color = colstr + paint(self) + end +end +function ap_airship.paint2(self, colstr) + if colstr then + self.color2 = colstr + paint(self) + end +end + +-- destroy the boat +function ap_airship.destroy(self, overload) + if self.sound_handle then + minetest.sound_stop(self.sound_handle) + self.sound_handle = nil + end + + local pos = self.object:get_pos() + if self._passengers_base[1] then self._passengers_base[1]:remove() end + if self._passengers_base[2] then self._passengers_base[2]:remove() end + if self._passengers_base[3] then self._passengers_base[3]:remove() end + if self._passengers_base[4] then self._passengers_base[4]:remove() end + if self._passengers_base[5] then self._passengers_base[5]:remove() end + + airutils.destroy_inventory(self) + self.object:remove() + + pos.y=pos.y+2 + --[[for i=1,7 do + minetest.add_item({x=pos.x+math.random()-0.5,y=pos.y,z=pos.z+math.random()-0.5},'default:steel_ingot') + end + + for i=1,7 do + minetest.add_item({x=pos.x+math.random()-0.5,y=pos.y,z=pos.z+math.random()-0.5},'default:mese_crystal') + end]]-- + + --minetest.add_item({x=pos.x+math.random()-0.5,y=pos.y,z=pos.z+math.random()-0.5},'ap_airship:boat') + --minetest.add_item({x=pos.x+math.random()-0.5,y=pos.y,z=pos.z+math.random()-0.5},'default:diamond') + + --[[local total_biofuel = math.floor(self._energy) - 1 + for i=0,total_biofuel do + minetest.add_item({x=pos.x+math.random()-0.5,y=pos.y,z=pos.z+math.random()-0.5},'biofuel:biofuel') + end]]-- + if overload then + local stack = ItemStack(self.item) + local item_def = stack:get_definition() + + if item_def.overload_drop then + for _,item in pairs(item_def.overload_drop) do + minetest.add_item({x=pos.x+math.random()-0.5,y=pos.y,z=pos.z+math.random()-0.5},item) + end + return + end + end + local stack = ItemStack(self.item) + local item_def = stack:get_definition() + if self.hull_integrity then + local boat_wear = math.floor(65535*(1-(self.hull_integrity/item_def.hull_integrity))) + stack:set_wear(boat_wear) + end + minetest.add_item({x=pos.x+math.random()-0.5,y=pos.y,z=pos.z+math.random()-0.5}, stack) +end + +--returns 0 for old, 1 for new +function ap_airship.detect_player_api(player) + local player_proterties = player:get_properties() + local mesh = "character.b3d" + if player_proterties.mesh == mesh then + local models = player_api.registered_models + local character = models[mesh] + if character then + if character.animations.sit.eye_height then + return 1 + else + return 0 + end + end + end + + return 0 +end + +function ap_airship.checkAttach(self, player) + local retVal = false + if player then + local player_attach = player:get_attach() + if player_attach then + for i = 5,1,-1 + do + if player_attach == self._passengers_base[i] then + retVal = true + break + end + end + end + end + return retVal +end + +function ap_airship.engineSoundPlay(self) + --sound + if self.sound_handle then minetest.sound_stop(self.sound_handle) end + if self.sound_handle_engine then minetest.sound_stop(self.sound_handle_engine) end + if self.object then + self.sound_handle = minetest.sound_play({name = "default_furnace_active"}, + {object = self.object, gain = 0.2, + max_hear_distance = 5, + loop = true,}) + + self.sound_handle_engine = minetest.sound_play({name = "ap_airship_engine"},--"default_item_smoke"}, + {object = self.object, gain = 3.0, + pitch = 0.4+((math.abs(self._power_lever)/100)/2), + max_hear_distance = 32, + loop = true,}) + end +end + +function ap_airship.engine_set_sound_and_animation(self) + if self._last_applied_power ~= self._power_lever then + --minetest.chat_send_all('test2') + self._last_applied_power = self._power_lever + self.object:set_animation_frame_speed(ap_airship.iddle_rotation + (self._power_lever*100)) + if self._last_sound_update == nil then self._last_sound_update = self._power_lever end + if math.abs(self._last_sound_update - self._power_lever) > 5 then + self._last_sound_update = self._power_lever + ap_airship.engineSoundPlay(self) + end + end + if self._engine_running == false then + self._power_lever = 0 + self.object:set_animation_frame_speed(0) + if self.sound_handle then + minetest.sound_stop(self.sound_handle) + self.sound_handle = nil + --self.object:set_animation_frame_speed(0) + end + if self.sound_handle_engine then + minetest.sound_stop(self.sound_handle_engine) + self.sound_handle_engine = nil + end + end +end + + +function ap_airship.start_furnace(self) + if self._engine_running then + self._engine_running = false + -- sound and animation + if self.sound_handle then + minetest.sound_stop(self.sound_handle) + self.sound_handle = nil + end + elseif self._engine_running == false and self._energy > 0 then + self._engine_running = true + -- sound + if self.sound_handle then minetest.sound_stop(self.sound_handle) end + if self.object then + self.sound_handle = minetest.sound_play({name = "default_furnace_active"}, + {object = self.object, gain = 0.2, + max_hear_distance = 5, + loop = true,}) + end + end +end + +function ap_airship.copy_vector(original_vector) + local tablecopy = {} + for k, v in pairs(original_vector) do + tablecopy[k] = v + end + return tablecopy +end + diff --git a/walk_map.lua b/walk_map.lua new file mode 100644 index 0000000..a6c946a --- /dev/null +++ b/walk_map.lua @@ -0,0 +1,205 @@ +function ap_airship.clamp(value, min, max) + local retVal = value + if value < min then retVal = min end + if value > max then retVal = max end + --minetest.chat_send_all(value .. " - " ..retVal) + return retVal +end + +function ap_airship.reclamp(value, min, max) + local retVal = value + local mid = (max-min)/2 + if value > min and value <= (min+mid) then retVal = min end + if value < max and value > (max-mid) then retVal = max end + --minetest.chat_send_all(value .. " - return: " ..retVal .. " - mid: " .. mid) + return retVal +end + +function ap_airship.cabin_map(pos, dpos) + local orig_pos = ap_airship.copy_vector(pos) + local position = ap_airship.copy_vector(dpos) + local new_pos = ap_airship.copy_vector(dpos) + + --limit to the cabin + new_pos.z = ap_airship.clamp(new_pos.z, 112, 164) + new_pos.y = -29 + new_pos.x = ap_airship.clamp(new_pos.x, -8.42, 8.42) + + --minetest.chat_send_all("x: "..new_pos.x.." - z: "..new_pos.z) + return new_pos +end + +local function is_cabin_zone(pos) + local cabin_zone = false + if pos.z > -20 and pos.z <= 200 and pos.x > -8 and pos.x < 8 then cabin_zone = true end + return cabin_zone +end + +local function is_ladder_zone(pos) + local ladder_zone = false + if pos.z <= 120 and pos.z >= 109 and pos.x > -9 and pos.x < -2 then ladder_zone = true end + return ladder_zone +end + +function ap_airship.passengers_deck_map(pos, dpos) + local orig_pos = ap_airship.copy_vector(pos) + local position = ap_airship.copy_vector(dpos) + local new_pos = ap_airship.copy_vector(dpos) + local ladder_zone = is_ladder_zone(pos) + + if ladder_zone then + --limiting ladder space + new_pos.z = ap_airship.clamp(new_pos.z, 3, 118) + new_pos.x = ap_airship.clamp(new_pos.x, -8.42, -2) + else + --limiting upper deck + new_pos.z = ap_airship.clamp(new_pos.z, 3, 109) + new_pos.x = ap_airship.clamp(new_pos.x, -43, 43) + end + new_pos.y = 0 + + --minetest.chat_send_all("x: "..new_pos.x.." - z: "..new_pos.z) + return new_pos +end + +function ap_airship.ladder_map(pos, dpos) + local orig_pos = steampunk_blimp.copy_vector(pos) + local position = steampunk_blimp.copy_vector(dpos) + local new_pos = steampunk_blimp.copy_vector(dpos) + new_pos.z = steampunk_blimp.clamp(new_pos.z, 112, 118) + new_pos.x = steampunk_blimp.clamp(new_pos.x, -8.42, -2) + + return new_pos +end + +function ap_airship.navigate_deck(pos, dpos, player) + local pos_d = dpos + local ladder_zone = is_ladder_zone(pos) + + local upper_deck_y = 0 + local lower_deck_y = -29 + local cabin_zone = is_cabin_zone(pos) + if player then + if pos.y == upper_deck_y then + pos_d = ap_airship.passengers_deck_map(pos, dpos) + elseif pos.y <= lower_deck_y + 5 then + if ladder_zone == false then + pos_d = ap_airship.cabin_map(pos, dpos) + end + elseif pos.y > lower_deck_y and pos.y < 10 then + pos_d = ap_airship.ladder_map(pos, dpos) + end + + local ctrl = player:get_player_control() + if ctrl.jump or ctrl.sneak then --ladder + if ladder_zone then + --minetest.chat_send_all(dump(pos)) + if ctrl.jump then + pos_d.y = pos_d.y + 0.9 + if pos_d.y > upper_deck_y then pos_d.y = upper_deck_y end + end + if ctrl.sneak then + pos_d.y = pos_d.y - 0.9 + if pos_d.y < lower_deck_y then pos_d.y = lower_deck_y end + end + end + end + end + + return pos_d +end + +--note: index variable just for the walk +--this function was improved by Auri Collings on steampunk_blimp +local function get_result_pos(self, player, index) + local pos = nil + if player then + local ctrl = player:get_player_control() + + local direction = player:get_look_horizontal() + local rotation = self.object:get_rotation() + direction = direction - rotation.y + + pos = vector.new() + + local y_rot = -math.deg(direction) + pos.y = y_rot --okay, this is strange to keep here, but as I dont use it anyway... + + + if ctrl.up or ctrl.down or ctrl.left or ctrl.right then + player_api.set_animation(player, "walk", 30) + + local speed = 0.4 + + dir = vector.new(ctrl.up and -1 or ctrl.down and 1 or 0, 0, ctrl.left and 1 or ctrl.right and -1 or 0) + dir = vector.normalize(dir) + dir = vector.rotate(dir, {x = 0, y = -direction, z = 0}) + + local time_correction = (self.dtime/ap_airship.ideal_step) + local move = speed * time_correction + + pos.x = move * dir.x + pos.z = move * dir.z + + --lets fake walk sound + if self._passengers_base_pos[index].dist_moved == nil then self._passengers_base_pos[index].dist_moved = 0 end + self._passengers_base_pos[index].dist_moved = self._passengers_base_pos[index].dist_moved + move; + if math.abs(self._passengers_base_pos[index].dist_moved) > 5 then + self._passengers_base_pos[index].dist_moved = 0 + minetest.sound_play({name = "default_wood_footstep"}, + {object = self._passengers_base_pos[index].object, gain = 0.1, + max_hear_distance = 5, + ephemeral = true,}) + end + else + player_api.set_animation(player, "stand") + end + end + return pos +end + + +function ap_airship.move_persons(self) + --self._passenger = nil + if self.object == nil then return end + for i = 5,1,-1 + do + local player = nil + if self._passengers[i] then player = minetest.get_player_by_name(self._passengers[i]) end + + if self.driver_name and self._passengers[i] == self.driver_name then + --clean driver if it's nil + if player == nil then + self._passengers[i] = nil + self.driver_name = nil + end + else + if self._passengers[i] ~= nil then + --minetest.chat_send_all("pass: "..dump(self._passengers[i])) + --the rest of the passengers + if player then + local result_pos = get_result_pos(self, player, i) + local y_rot = 0 + if result_pos then + y_rot = result_pos.y -- the only field that returns a rotation + local new_pos = ap_airship.copy_vector(self._passengers_base_pos[i]) + new_pos.x = new_pos.x - result_pos.z + new_pos.z = new_pos.z - result_pos.x + --minetest.chat_send_all(dump(new_pos)) + --local pos_d = ap_airship.boat_lower_deck_map(self._passengers_base_pos[i], new_pos) + local pos_d = ap_airship.navigate_deck(self._passengers_base_pos[i], new_pos, player) + --minetest.chat_send_all(dump(height)) + self._passengers_base_pos[i] = ap_airship.copy_vector(pos_d) + self._passengers_base[i]:set_attach(self.object,'',self._passengers_base_pos[i],{x=0,y=0,z=0}) + end + --minetest.chat_send_all(dump(self._passengers_base_pos[i])) + player:set_attach(self._passengers_base[i], "", {x = 0, y = 0, z = 0}, {x = 0, y = y_rot, z = 0}) + else + --self._passengers[i] = nil + end + end + end + end +end + +