This commit is contained in:
Alexsandro Percy 2023-02-27 19:54:38 -03:00
parent 4759793d08
commit 146aca5195
43 changed files with 2867 additions and 3 deletions

25
.luacheckrc Executable file
View file

@ -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"}

2
LICENSE Normal file → Executable file
View file

@ -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

115
README.md Normal file → Executable file
View file

@ -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 <name>
- To go reverse, hold aux (E key) and backward together.
- To remove someone from the sharing, /blimp_remove <name>
- 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) <alexsandro.percy@gmail.com>
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/

170
control.lua Executable file
View file

@ -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

86
custom_physics.lua Executable file
View file

@ -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

50
engine_management.lua Normal file
View file

@ -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

679
entities.lua Executable file
View file

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

467
forms.lua Executable file
View file

@ -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
})

58
fuel_management.lua Executable file
View file

@ -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

269
hud.lua Executable file
View file

@ -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

228
init.lua Executable file
View file

@ -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

91
manual.lua Executable file
View file

@ -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 <name>").."\" \n",
"To remove someone from the sharing, \""..core.colorize('#ffff00', "/airship_remove <name>").."\" \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
})

6
mod.conf Executable file
View file

@ -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

BIN
models/ap_airship_light.b3d Executable file

Binary file not shown.

BIN
models/ap_airship_mesh.b3d Executable file

Binary file not shown.

BIN
models/ap_airship_stand_base.b3d Executable file

Binary file not shown.

BIN
sounds/ap_airship_collision.ogg Executable file

Binary file not shown.

Binary file not shown.

BIN
textures/ap_airship_alpha.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

BIN
textures/ap_airship_cylinder.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
textures/ap_airship_glass.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
textures/ap_airship_glass_2.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
textures/ap_airship_helice.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
textures/ap_airship_hud_panel.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

BIN
textures/ap_airship_icon.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

BIN
textures/ap_airship_ind_box.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

BIN
textures/ap_airship_rotor.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

BIN
textures/ap_airship_sup_eng.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
textures/blimp_clover.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
textures/blimp_jack.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
textures/blimp_liz.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
textures/blimp_shotting_star.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
textures/blimp_skull.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

419
utilities.lua Executable file
View file

@ -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

205
walk_map.lua Normal file
View file

@ -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