first commit

master
Alexsandro Percy 2022-05-18 18:39:50 -03:00
parent fd76675b3a
commit 810b657d8e
27 changed files with 1858 additions and 2 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"}

21
LICENSE Executable file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 APercy - Alexsandro Percy Libanio Motta
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

17
README.md Normal file → Executable file
View File

@ -1,2 +1,15 @@
# steampunk_blimp
A steampunk blimp for minetest
Minetest 5.4 mod: Steampunk Blimp
========================================
License of source code:
MIT (see file LICENSE)
License of media (textures and sounds):
---------------------------------------
collision.ogg by APercy. See License file
Blimp model by APercy. CC-BY-SA

169
control.lua Executable file
View File

@ -0,0 +1,169 @@
--global constants
steampunk_blimp.vector_up = vector.new(0, 1, 0)
function steampunk_blimp.get_pointer_angle(value, maxvalue)
local angle = value/maxvalue * 180
angle = angle - 90
angle = angle * -1
return angle
end
function steampunk_blimp.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 steampunk_blimp.powerAdjust(self,dtime,factor,dir,max_power)
local max = max_power or 100
local add_factor = factor/2
add_factor = add_factor * (dtime/steampunk_blimp.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 steampunk_blimp.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 and self._engine_running == true then
--local paddleacc
--[[if longit_speed < 4.0 and ctrl.up then
paddleacc = 2
elseif longit_speed > -1.0 and ctrl.down then
paddleacc = -0.5
end]]--
local factor = 1
if ctrl.up then
steampunk_blimp.powerAdjust(self, dtime, factor, 1)
--self.object:set_animation_frame_speed(40)
elseif ctrl.down then
steampunk_blimp.powerAdjust(self, dtime, factor, -1)
--self.object:set_animation_frame_speed(-40)
else
--self.object:set_animation_frame_speed(steampunk_blimp.iddle_rotation)
end
end
if ctrl.jump then
self._baloon_buoyancy = 1.02
elseif ctrl.sneak then
self._baloon_buoyancy = -1.02
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 * steampunk_blimp.max_engine_acc) / 100;
--do not exceed
local max_speed = 3
if longit_speed > max_speed then
engineacc = engineacc - (longit_speed-max_speed)
end
if engineacc < 0 then
local is_reversed = false
if ctrl then
if ctrl.aux1 then
is_reversed = true
end
end
if is_reversed == false then
engineacc = 0
self._power_lever = 0
end
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
steampunk_blimp.rudder_auto_correction(self, longit_speed, dtime)
end
else
steampunk_blimp.rudder_auto_correction(self, longit_speed, dtime)
end
end
steampunk_blimp.buoyancy_auto_correction(self, self.dtime)
return retval_accel
end
function steampunk_blimp.rudder_auto_correction(self, longit_speed, dtime)
local factor = 1
if self._rudder_angle > 0 then factor = -1 end
local correction = (steampunk_blimp.rudder_limit*(longit_speed/2000)) * factor * (dtime/steampunk_blimp.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 steampunk_blimp.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/steampunk_blimp.ideal_step)
local intensity = 0.2
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

94
custom_physics.lua Executable file
View File

@ -0,0 +1,94 @@
local min = math.min
local abs = math.abs
function steampunk_blimp.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 = mobkit.get_stand_pos(self)
spos.y = spos.y+0.01
-- get surface height
local snodepos = mobkit.get_node_pos(spos)
local surfnode = mobkit.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 = mobkit.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/steampunk_blimp.ideal_step)
local y_accel = self._baloon_buoyancy*time_correction
if surface then
self.isinliquid = true
local height = self.height
local submergence = min(surface-spos.y,height)/height
-- local balance = self.buoyancy*self.height
local buoyacc = mobkit.gravity*(self.buoyancy-submergence)
--local buoyacc = self._baloon_buoyancy*(self.buoyancy-submergence)
accell = {x=-vel.x*self.water_drag,y=buoyacc-(vel.y*abs(vel.y)*0.4),z=-vel.z*self.water_drag}
--local v_accell = {x=0,y=buoyacc-(vel.y*abs(vel.y)*0.4),z=0}
mobkit.set_acceleration(self.object,accell)
if self._baloon_buoyancy > 0 then
mobkit.set_acceleration(self.object,{x=0,y=y_accel,z=0})
end
else
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: "..steampunk_blimp.ideal_step)
mobkit.set_acceleration(self.object,{x=0,y=y_accel,z=0})
end
end

534
entities.lua Executable file
View File

@ -0,0 +1,534 @@
--
-- constants
--
local LONGIT_DRAG_FACTOR = 0.13*0.13
local LATER_DRAG_FACTOR = 2.0
--
-- entity
--
minetest.register_entity('steampunk_blimp:fire',{
initial_properties = {
physical = false,
collide_with_objects=false,
pointable=false,
glow = 0,
visual = "mesh",
mesh = "steampunk_blimp_light.b3d",
textures = {
"steampunk_blimp_alpha.png",
},
},
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,
})
--
-- seat pivot
--
minetest.register_entity('steampunk_blimp:stand_base',{
initial_properties = {
physical = false,
collide_with_objects=false,
pointable=false,
visual = "mesh",
mesh = "steampunk_blimp_stand_base.b3d",
textures = {"steampunk_blimp_alpha.png",},
},
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("steampunk_blimp:blimp", {
initial_properties = {
physical = true,
collide_with_objects = true, --true,
collisionbox = {-4, -2.5, -4, 4, 10, 4}, --{-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 = "steampunk_blimp.b3d",
textures = {
"steampunk_blimp_black.png", --alimentacao balao
"default_wood.png", --asa
"steampunk_blimp_canvas.png", --asa
"steampunk_blimp_canvas.png", --balao
"wool_white.png", --faixas brancas nariz
"wool_blue.png", --faixas azuis nariz
"steampunk_blimp_metal.png", --pontas do balão
"steampunk_blimp_black.png", --caldeira
"steampunk_blimp_forno.png", --caldeira
"default_junglewood.png", --casco
"steampunk_blimp_canvas.png", --leme
"default_junglewood.png", --leme
"steampunk_blimp_wood.png", --timao
"default_ladder_wood.png", --escada
"default_wood.png", --mureta
"steampunk_blimp_wood.png", --mureta
"steampunk_blimp_black.png", --nacele rotores
"steampunk_blimp_wood.png", --quilha
"default_wood.png", --rotores
"steampunk_blimp_rotor.png", --rotores
"steampunk_blimp_black.png", --suportes rotores
"steampunk_blimp_wood.png", --suporte timao
"steampunk_blimp_rope.png", --cordas
"wool_blue.png", --det azul
"wool_white.png", --det branco
"steampunk_blimp_wood.png", --fixacao cordas
--"steampunk_blimp_metal.png",
--"steampunk_blimp_red.png",
},
},
textures = {},
driver_name = nil,
sound_handle = nil,
static_save = true,
infotext = "A nice blimp",
lastvelocity = vector.new(),
hp = 50,
color = "#000000",
timeout = 0;
buoyancy = 0.15,
max_hp = 50,
anchored = false,
physics = steampunk_blimp.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,
item = "steampunk_blimp:blimp",
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_anchor = self.anchored,
stored_hull_integrity = self.hull_integrity,
stored_item = self.item,
})
end,
on_activate = function(self, staticdata, dtime_s)
if staticdata ~= "" and staticdata ~= nil then
local data = minetest.deserialize(staticdata) or {}
self._baloon_buoyancy = data.stored_baloon_buoyancy
self._energy = data.stored_energy
self.owner = data.stored_owner
self._shared_owners = data.stored_shared_owners
self.hp = data.stored_hp
self.color = data.stored_color
self.anchored = data.stored_anchor
self.buoyancy = data.stored_buoyancy
self.surface_level = data.stored_surface_level
self.hull_integrity = data.stored_hull_integrity
self.item = data.stored_item
--minetest.debug("loaded: ", self._energy)
local properties = self.object:get_properties()
properties.infotext = data.stored_owner .. " nice blimp"
self.object:set_properties(properties)
end
steampunk_blimp.paint(self, self.color)
local pos = self.object:get_pos()
local fire=minetest.add_entity(pos,'steampunk_blimp:fire')
fire:set_attach(self.object,'',{x=0.0,y=0.0,z=0.0},{x=0,y=0,z=0})
self.fire = fire
self._passengers_base = {[1]=nil, [2]=nil, [3]=nil, [4]=nil, [5]=nil} --obj id
self._passengers_base_pos = {
[1]=steampunk_blimp.passenger_pos[1],
[2]=steampunk_blimp.passenger_pos[2],
[3]=steampunk_blimp.passenger_pos[3],
[4]=steampunk_blimp.passenger_pos[4],
[5]=steampunk_blimp.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,'steampunk_blimp: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,'steampunk_blimp: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,'steampunk_blimp: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,'steampunk_blimp: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,'steampunk_blimp:stand_base')
self._passengers_base[5]:set_attach(self.object,'',self._passengers_base_pos[5],{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})
mobkit.actfunc(self, staticdata, dtime_s)
--[[
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, steampunk_blimp.trunk_slots)
else
self.inv = inv
end]]--
end,
on_step = function(self, dtime)
mobkit.stepfunc(self, dtime)
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 = steampunk_blimp.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*steampunk_blimp.sign(longit_speed))
local later_speed = steampunk_blimp.dot(velocity,nhdir)
local later_drag = vector.multiply(nhdir,later_speed*later_speed*
LATER_DRAG_FACTOR*-1*steampunk_blimp.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)
steampunk_blimp.engine_set_sound_and_animation(self)
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 = steampunk_blimp.checkAttach(self, player)
end
end
--fire
if self._engine_running == true then
self.fire:set_properties({textures={"default_furnace_fire_fg.png"},glow=15})
else
self.fire:set_properties({textures={"steampunk_blimp_alpha.png"},glow=0})
end
--detect collision
if self.last_vel ~= nil then
local impact = steampunk_blimp.get_hipotenuse_value(vel, self.last_vel)
if impact > 1 then
minetest.sound_play("steampunk_blimp_collision", {
--to_player = self.driver_name,
pos = curr_pos,
max_hear_distance = 15,
gain = 1.0,
fade = 0.0,
pitch = 1.0,
})
if self.hull_integrity then
self.hull_integrity = self.hull_integrity - impact
if (self.hull_integrity <= 0) then
--minetest.sound_play("steampunk_blimp_hull_break", {
minetest.sound_play("default_break_glass", {
--to_player = self.driver_name,
pos = curr_pos,
max_hear_distance = 15,
gain = 2,
fade = 0.0,
pitch = 1.0,
})
steampunk_blimp.destroy(self, true)
return
end
end
end
end
accel = steampunk_blimp.control(self, dtime, hull_direction, longit_speed, accel) or vel
--[[if is_attached then
--control
else
-- for some engine lag the player can be detached from the blimp, so lets set him attached again
local can_stop = true
if self.owner and self.driver_name then
-- attach the driver again
if player then
steampunk_blimp.attach(self, player)
can_stop = false
end
end
if can_stop then
--detach player
if self.sound_handle ~= nil then
minetest.sound_stop(self.sound_handle)
self.sound_handle = nil
end
end
end]]--
local turn_rate = math.rad(18)
newyaw = yaw + self.dtime*(1 - 1 / (math.abs(longit_speed) + 1)) *
self._rudder_angle / 30 * turn_rate * steampunk_blimp.sign(longit_speed)
-- calculate energy consumption --
----------------------------------
if self._energy > 0 and self._engine_running then
local zero_reference = vector.new()
local acceleration = steampunk_blimp.get_hipotenuse_value(accel, zero_reference)
local consumed_power = acceleration/steampunk_blimp.FUEL_CONSUMPTION
--self._energy = self._energy - consumed_power;
local energy_indicator_angle = steampunk_blimp.get_pointer_angle(self._energy, steampunk_blimp.MAX_FUEL)
end
if self._energy <= 0 then
self._engine_running = false
if self.sound_handle then minetest.sound_stop(self.sound_handle) end
self.object:set_animation_frame_speed(0)
end
----------------------------
-- end energy consumption --
--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 = steampunk_blimp.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/steampunk_blimp.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.abs(math.deg(newroll)) >= 1 then
if self._roll_state == 1 then self._roll_state = -1 elseif self._roll_state == -1 then self._roll_state = 1 end
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
accel.y = accel_y -- + bob
newpitch = velocity.y * math.rad(1.5)
self.object:set_acceleration(accel)
self.object:set_rotation({x=newpitch,y=newyaw,z=newroll})
self.object:set_bone_position("low_rudder", {x=0,y=0,z=0}, {x=0,y=self._rudder_angle,z=0})
self.object:set_bone_position("rudder", {x=0,y=97,z=-148}, {x=0,y=self._rudder_angle,z=0})
self.object:set_bone_position("timao", {x=0,y=27,z=-25}, {x=0,y=0,z=self._rudder_angle*8})
--saves last velocy for collision detection (abrupt stop)
self.last_vel = self.object:get_velocity()
steampunk_blimp.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 = steampunk_blimp.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
steampunk_blimp.load_fuel(self, puncher)
self._engine_running = true
end
if is_attached == false then
-- 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 = steampunk_blimp.colors[color]
--minetest.chat_send_all(color ..' '.. dump(colstr))
if colstr then
steampunk_blimp.paint(self, colstr)
itmstck:set_count(itmstck:get_count()-1)
puncher:set_wielded_item(itmstck)
end
-- end painting
else -- deal damage
if not self.driver_name and toolcaps and toolcaps.damage_groups and
toolcaps.damage_groups.fleshy then
--mobkit.hurt(self,toolcaps.damage_groups.fleshy - 1)
--mobkit.make_sound(self,'hit')
self.hp = self.hp - 10
minetest.sound_play("collision", {
object = self.object,
max_hear_distance = 5,
gain = 1.0,
fade = 0.0,
pitch = 1.0,
})
end
end
end
if self.hp <= 0 then
steampunk_blimp.destroy(self, false)
end
end
end,
on_rightclick = function(self, clicker)
local message = ""
if not clicker or not clicker:is_player() then
return
end
local name = clicker:get_player_name()
if self.owner == "" then
self.owner = name
end
local touching_ground, liquid_below = airutils.check_node_below(self.object, 2.5)
local is_on_ground = self.isinliquid or touching_ground or liquid_below
local is_under_water = airutils.check_is_under_water(self.object)
--minetest.chat_send_all('name '.. dump(name) .. ' - pilot: ' .. dump(self.driver_name) .. ' - pax: ' .. dump(copilot_name))
--=========================
-- 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
if name == self.driver_name then
if is_attached then
steampunk_blimp.pilot_formspec(name)
else
self.driver_name = nil
end
--=========================
-- attach passenger
--=========================
else
is_attached = steampunk_blimp.check_passenger_is_attached(self, name)
if is_attached then
--remove pax
if self.driver_name ~= nil then
if name == self.owner then
--require the pilot position now
steampunk_blimp.owner_formspec(name)
else
steampunk_blimp.pax_formspec(name)
end
else
--check if is on owner list
local is_shared = false
if name == self.owner then is_shared = true end
for k, v in pairs(self._shared_owners) do
if v == name then
is_shared = true
break
end
end
--normal user
if is_shared == false then
steampunk_blimp.pax_formspec(name)
else
--owners
steampunk_blimp.pilot_formspec(name)
end
end
else
--attach normal passenger
--if self._door_closed == false then
steampunk_blimp.attach_pax(self, clicker)
--end
end
end
end,
})

284
forms.lua Executable file
View File

@ -0,0 +1,284 @@
--------------
-- Manual --
--------------
function steampunk_blimp.getPlaneFromPlayer(player)
local seat = player:get_attach()
if seat then
local plane = seat:get_attach()
return plane
end
return nil
end
function steampunk_blimp.pilot_formspec(name)
local basic_form = table.concat({
"formspec_version[5]",
"size[6,8]",
}, "")
local player = minetest.get_player_by_name(name)
local plane_obj = steampunk_blimp.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,2.0;4,1;hud;Show/Hide Gauges]"
basic_form = basic_form.."checkbox[1,4.6;take_control;Take the Control;"..take_control.."]"
basic_form = basic_form.."checkbox[1,5.2;anchor;Anchor away;"..anchor.."]"
basic_form = basic_form.."button[1,6.0;4,1;go_out;Go Offboard]"
minetest.show_formspec(name, "steampunk_blimp:pilot_main", basic_form)
end
function steampunk_blimp.pax_formspec(name)
local basic_form = table.concat({
"formspec_version[3]",
"size[6,3]",
}, "")
basic_form = basic_form.."button[1,1.0;4,1;go_out;Go Offboard]"
minetest.show_formspec(name, "steampunk_blimp:passenger_main", basic_form)
end
function steampunk_blimp.owner_formspec(name)
local basic_form = table.concat({
"formspec_version[3]",
"size[6,4]",
}, "")
basic_form = basic_form.."button[1,1.0;4,1;take;Take the Control Now]"
basic_form = basic_form.."button[1,2.0;4,1;go_out;Go Offboard]"
minetest.show_formspec(name, "steampunk_blimp:owner_main", basic_form)
end
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname == "steampunk_blimp:owner_main" then
local name = player:get_player_name()
local plane_obj = steampunk_blimp.getPlaneFromPlayer(player)
if plane_obj == nil then
minetest.close_formspec(name, "steampunk_blimp:owner_main")
return
end
local ent = plane_obj:get_luaentity()
if ent then
if fields.go_out then
steampunk_blimp.dettach_pax(ent, player)
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(steampunk_blimp.pilot_base_pos)
ent._passengers_base[i]:set_attach(ent.object,'',steampunk_blimp.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(steampunk_blimp.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, "steampunk_blimp:owner_main")
end
if formname == "steampunk_blimp:passenger_main" then
local name = player:get_player_name()
local plane_obj = steampunk_blimp.getPlaneFromPlayer(player)
if plane_obj == nil then
minetest.close_formspec(name, "steampunk_blimp:passenger_main")
return
end
local ent = plane_obj:get_luaentity()
if ent then
if fields.go_out then
steampunk_blimp.dettach_pax(ent, player)
end
end
minetest.close_formspec(name, "steampunk_blimp:passenger_main")
end
if formname == "steampunk_blimp:pilot_main" then
local name = player:get_player_name()
local plane_obj = steampunk_blimp.getPlaneFromPlayer(player)
if plane_obj == nil then
minetest.close_formspec(name, "steampunk_blimp:pilot_main")
return
end
local ent = plane_obj:get_luaentity()
if ent then
if fields.turn_on then
steampunk_blimp.start_furnace(ent)
end
if fields.hud then
if ent._show_hud == true then
ent._show_hud = false
else
ent._show_hud = true
end
end
if fields.take_control then
if fields.take_control == "true" then
if ent.driver_name == nil then
ent._at_control = true
for i = 5,1,-1
do
if ent._passengers[i] == name then
ent._passengers_base_pos[i] = vector.new(steampunk_blimp.pilot_base_pos)
ent._passengers_base[i]:set_attach(ent.object,'',steampunk_blimp.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
end
else
ent.driver_name = nil
ent._at_control = false
end
end
if fields.go_out then
--=========================
-- dettach player
--=========================
-- eject passenger if the plane is on ground
local touching_ground, liquid_below = airutils.check_node_below(plane_obj, 2.5)
--if ent.isinliquid or touching_ground then --isn't flying?
--ok, remove pax
local passenger = nil
for i = 5,1,-1
do
if ent._passengers[i] == name then
passenger = minetest.get_player_by_name(ent._passengers[i])
if passenger then
steampunk_blimp.dettach_pax(ent, passenger)
--minetest.chat_send_all('saiu')
break
end
end
end
--end
end
if fields.bring then
end
if fields.anchor then
if fields.anchor == "true" then
local max_speed_anchor = 0.2
if ent._longit_speed then
if ent._longit_speed < max_speed_anchor and
ent._longit_speed > -max_speed_anchor then
ent.anchored = true
ent.object:set_velocity(vector.new())
minetest.chat_send_player(ent.driver_name,core.colorize('#00ff00', " >>> Anchor away!"))
--ent.buoyancy = 0.1
else
minetest.chat_send_player(ent.driver_name,core.colorize('#ff0000', " >>> Too fast to set anchor!"))
end
end
else
ent.anchored = false
minetest.chat_send_player(ent.driver_name,core.colorize('#00ff00', " >>> Weigh anchor!"))
end
--ent._rudder_angle = 0
end
end
minetest.close_formspec(name, "steampunk_blimp:pilot_main")
end
end)
minetest.register_chatcommand("blimp_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 == "steampunk_blimp:blimp" 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', " >>> blimp shared"))
--minetest.chat_send_all(dump(entity._shared_owners))
else
minetest.chat_send_player(name,core.colorize('#ff0000', " >>> this user is already registered for blimp share"))
end
else
minetest.chat_send_player(name,core.colorize('#ff0000', " >>> only the owner can share this blimp"))
end
else
minetest.chat_send_player(name,core.colorize('#ff0000', " >>> you are not inside a blimp to perform this command"))
end
end
end
else
minetest.chat_send_player(name,core.colorize('#ff0000', " >>> you are not inside a blimp to perform this command"))
end
end
})
minetest.register_chatcommand("blimp_remove", {
params = "name",
description = "Removes ownewrshipfrom 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 == "steampunk_blimp:blimp" 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 blimp to perform this command"))
end
end
end
else
minetest.chat_send_player(name,core.colorize('#ff0000', " >>> you are not inside a blimp to perform this command"))
end
end
})

73
fuel_management.lua Executable file
View File

@ -0,0 +1,73 @@
--
-- fuel
--
steampunk_blimp.GAUGE_FUEL_POSITION = {x=0,y=-8.45,z=5.31}
steampunk_blimp.MAX_FUEL = minetest.settings:get("steampunk_blimp_max_fuel") or 10
steampunk_blimp.FUEL_CONSUMPTION = minetest.settings:get("steampunk_blimp_fuel_consumption") or 6000
minetest.register_entity('steampunk_blimp:pointer',{
initial_properties = {
physical = false,
collide_with_objects=false,
pointable=false,
visual = "mesh",
mesh = "pointer.b3d",
textures = {"steampunk_blimp_interior.png"},
},
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,
})
function steampunk_blimp.contains(table, val)
for k,v in pairs(table) do
if k == val then
return v
end
end
return false
end
function steampunk_blimp.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
--minetest.chat_send_all("fuel: ".. dump(item_name))
local fuel = steampunk_blimp.contains(steampunk_blimp.fuel, item_name)
if fuel then
local stack = ItemStack(item_name .. " 1")
if self.energy < steampunk_blimp.MAX_FUEL then
inv:remove_item("main", stack)
self.energy = self.energy + fuel.amount
if self.energy > steampunk_blimp.MAX_FUEL then self.energy = steampunk_blimp.MAX_FUEL end
--minetest.chat_send_all(self.energy)
if fuel.drop then
local leftover = inv:add_item("main", fuel.drop)
if leftover then
minetest.item_drop(leftover, player, player:get_pos())
end
end
local energy_indicator_angle = steampunk_blimp.get_pointer_angle(self.energy, steampunk_blimp.MAX_FUEL)
end
return true
end
return false
end

113
init.lua Executable file
View File

@ -0,0 +1,113 @@
steampunk_blimp={}
steampunk_blimp.gravity = tonumber(minetest.settings:get("movement_gravity")) or 9.8
steampunk_blimp.fuel = {['default:coal_lump'] = {amount=1},['default:coalblock'] = {amount=10}}
steampunk_blimp.ideal_step = 0.02
steampunk_blimp.rudder_limit = 30
steampunk_blimp.iddle_rotation = 0
steampunk_blimp.max_engine_acc = 3
steampunk_blimp.pilot_base_pos = {x=0.0,y=20.821,z=-30.844}
steampunk_blimp.passenger_pos = {
[1] = {x=0.0,y=0,z=-15},
[2] = {x=-11,y=0,z=-12},
[3] = {x=11,y=0,z=-12},
[4] = {x=-11,y=0,z=14},
[5] = {x=11,y=0,z=14},
}
local steampunk_blimp_attached = {}
steampunk_blimp.colors ={
black='#2b2b2b',
blue='#0063b0',
brown='#8c5922',
cyan='#07B6BC',
dark_green='#567a42',
dark_grey='#6d6d6d',
green='#4ee34c',
grey='#9f9f9f',
magenta='#ff0098',
orange='#ff8b0e',
pink='#ff62c6',
red='#dc1818',
violet='#a437ff',
white='#FFFFFF',
yellow='#ffe400',
}
function steampunk_blimp.clone_node(node_name)
if not (node_name and type(node_name) == 'string') then
return
end
local node = minetest.registered_nodes[node_name]
return table.copy(node)
end
dofile(minetest.get_modpath("steampunk_blimp") .. DIR_DELIM .. "utilities.lua")
dofile(minetest.get_modpath("steampunk_blimp") .. DIR_DELIM .. "control.lua")
dofile(minetest.get_modpath("steampunk_blimp") .. DIR_DELIM .. "fuel_management.lua")
dofile(minetest.get_modpath("steampunk_blimp") .. DIR_DELIM .. "custom_physics.lua")
dofile(minetest.get_modpath("steampunk_blimp") .. DIR_DELIM .. "entities.lua")
dofile(minetest.get_modpath("steampunk_blimp") .. DIR_DELIM .. "forms.lua")
--
-- helpers and co.
--
function steampunk_blimp.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 steampunk_blimp.dot(v1,v2)
return v1.x*v2.x+v1.y*v2.y+v1.z*v2.z
end
function steampunk_blimp.sign(n)
return n>=0 and 1 or -1
end
function steampunk_blimp.minmax(v,m)
return math.min(math.abs(v),m)*steampunk_blimp.sign(v)
end
-----------
-- items
-----------
-- blimp
minetest.register_craftitem("steampunk_blimp:blimp", {
description = "Steampunk Blimp",
inventory_image = "steampunk_blimp_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]
if nodedef.liquidtype ~= "none" then
end
pointed_pos.y=pointed_pos.y+5
local blimp = minetest.add_entity(pointed_pos, "steampunk_blimp:blimp")
if boat and placer then
local ent = blimp:get_luaentity()
local owner = placer:get_player_name()
ent.owner = owner
blimp:set_yaw(placer:get_look_horizontal())
itemstack:take_item()
local properties = ent.object:get_properties()
properties.infotext = owner .. " nice blimp"
ent.object:set_properties(properties)
end
return itemstack
end,
})

5
mod.conf Executable file
View File

@ -0,0 +1,5 @@
name = steampunk_blimp
depends = mobkit,default,player_api,wool
author = APercy
description = Adds a steampunk blimp
title = Steampunk Blimp

BIN
models/steampunk_blimp.b3d Executable file

Binary file not shown.

BIN
models/steampunk_blimp_light.b3d Executable file

Binary file not shown.

Binary file not shown.

BIN
screenshot.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

BIN
textures/steampunk_blimp_fire.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
textures/steampunk_blimp_icon.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
textures/steampunk_blimp_red.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
textures/steampunk_blimp_rope.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

BIN
textures/steampunk_blimp_wood.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

525
utilities.lua Executable file
View File

@ -0,0 +1,525 @@
function steampunk_blimp.check_passenger_is_attached(self, name)
local is_attached = false
if self._passenger == name then is_attached = true end
if is_attached == false then
for i = 5,1,-1
do
if self._passengers[i] == name then
is_attached = true
break
end
end
end
return is_attached
end
-- attach passenger
function steampunk_blimp.attach_pax(self, player)
local name = player:get_player_name()
--randomize the seat
local t = {1,2,3,4}
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
for k,v in ipairs(t) do
i = t[k]
if self._passengers[i] == nil then
--minetest.chat_send_all(self.driver_name)
self._passengers[i] = name
player:set_attach(self._passengers_base[i], "", {x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0})
player_api.player_attached[name] = true
break
end
end
end
function steampunk_blimp.dettach_pax(self, player)
local name = player:get_player_name() --self._passenger
-- passenger clicked the object => driver gets off the vehicle
if self._passenger == name then
self._passenger = nil
else
for i = 5,1,-1
do
if self._passengers[i] == name then
self._passengers[i] = nil
break
end
end
end
-- detach the player
if player then
player:set_detach()
player_api.player_attached[name] = nil
player_api.set_animation(player, "stand")
-- move player down
minetest.after(0.1, function(pos)
pos.y = pos.y - 2.5
player:set_pos(pos)
end, player:get_pos())
end
end
--painting
function steampunk_blimp.paint(self, colstr)
if colstr then
self.color = colstr
local l_textures = self.initial_properties.textures
for _, texture in ipairs(l_textures) do
local indx = texture:find('steampunk_blimp_painting.png')
if indx then
l_textures[_] = "steampunk_blimp_painting.png^[multiply:".. colstr
end
end
self.object:set_properties({textures=l_textures})
end
end
-- destroy the boat
function steampunk_blimp.destroy(self, overload)
if self.sound_handle then
minetest.sound_stop(self.sound_handle)
self.sound_handle = nil
end
if self.driver_name then
local driver = minetest.get_player_by_name(self.driver_name)
-- prevent error when submarine of unlogged driver is destroied by preasure
if driver then
driver:set_detach()
driver:set_eye_offset({x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0})
-- player should stand again
player_api.set_animation(driver, "stand")
end
player_api.player_attached[self.driver_name] = nil
self.driver_name = nil
end
local pos = self.object:get_pos()
if self.fire then self.fire:remove() end
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
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},'steampunk_blimp: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 steampunk_blimp.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
--TODO
--[[function steampunk_blimp.dettachPlayer(self, player)
local name = self.driver_name
airutils.setText(self, "Blimp")
--steampunk_blimp.remove_hud(player)
--self._engine_running = false
-- driver clicked the object => driver gets off the vehicle
self.driver_name = nil
if self._engine_running then
self._engine_running = false
self.object:set_animation_frame_speed(0)
end
-- sound and animation
if self.sound_handle then
minetest.sound_stop(self.sound_handle)
self.sound_handle = nil
end
-- detach the player
player:set_detach()
player_api.player_attached[name] = nil
player:set_eye_offset({x=0,y=0,z=0},{x=0,y=0,z=0})
player_api.set_animation(player, "stand")
self.driver = nil
--remove_physics_override(player, {speed=1,gravity=1,jump=1})
end
]]--
function steampunk_blimp.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 steampunk_blimp.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 steampunk_blimp.reclamp(value, min, max)
local retVal = value
local mid = (max/min)/2
if value > min and value <= mid then retVal = min end
if value < max and value > mid then retVal = max end
--minetest.chat_send_all(value .. " - " ..retVal)
return retVal
end
function steampunk_blimp.engineSoundPlay(self)
--sound
if self.sound_handle then minetest.sound_stop(self.sound_handle) end
if self.sound_handle_pistons then minetest.sound_stop(self.sound_handle_pistons) 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_pistons = minetest.sound_play({name = "default_item_smoke"},
{object = self.object, gain = 4.0,
pitch = 0.5 + ((math.abs(self._power_lever/2)/100)/2),
max_hear_distance = 32,
loop = true,})
end
end
function steampunk_blimp.engine_set_sound_and_animation(self)
if self._engine_running then
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(steampunk_blimp.iddle_rotation + (self._power_lever/2))
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
steampunk_blimp.engineSoundPlay(self)
end
end
else
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_pistons then
minetest.sound_stop(self.sound_handle_pistons)
self.sound_handle_pistons = nil
end
end
end
function steampunk_blimp.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
self.object:set_animation_frame_speed(0)
self._power_lever = 0 --zero power
elseif self._engine_running == false and self._energy > 0 then
self._engine_running = true
-- sound and animation
steampunk_blimp.engineSoundPlay(self)
self.object:set_animation_frame_speed(steampunk_blimp.iddle_rotation)
end
end
function steampunk_blimp.boat_upper_deck_map(pos, dpos)
local orig_pos = vector.new(pos)
local position = vector.new(dpos)
local new_pos = vector.new(dpos)
new_pos.z = steampunk_blimp.clamp(new_pos.z, -47, -16)
if position.z >= -49 and position.z < -32 then --limit 10
new_pos.y = 20.821
new_pos.x = steampunk_blimp.clamp(new_pos.x, -8, 8)
return new_pos
end
if position.z >= -32 and position.z < -14 then --limit 11
new_pos.y = 20.821
new_pos.x = steampunk_blimp.clamp(new_pos.x, -11, 11)
if position.z >= -28 then --timao
if orig_pos.x <= -4 or orig_pos.x >= 4 then
new_pos.x = steampunk_blimp.reclamp(new_pos.x, -4, 4)
else
new_pos.z = steampunk_blimp.reclamp(new_pos.z, -28, -20)
end
end
if position.z > -24 then --escada
if orig_pos.x <= 4 then
new_pos.z = steampunk_blimp.reclamp(new_pos.z, -24, -12)
end
end
return new_pos
end
return new_pos
end
function steampunk_blimp.boat_lower_deck_map(pos, dpos)
local orig_pos = vector.new(pos)
local position = vector.new(dpos)
local new_pos = vector.new(dpos)
new_pos.z = steampunk_blimp.clamp(new_pos.z, -29, 45)
if position.z > -31 and position.z < -14 then --limit 10
new_pos.y = 0
new_pos.x = steampunk_blimp.clamp(new_pos.x, -10, 10)
return new_pos
end
if position.z >= -14 and position.z < -4 then --limit 11
new_pos.y = 0
new_pos.x = steampunk_blimp.clamp(new_pos.x, -12, 12)
if position.z > -9 then
if orig_pos.x <= -6 or orig_pos.x >= 6 then
new_pos.x = steampunk_blimp.reclamp(new_pos.x, -6, 6)
else
new_pos.z = steampunk_blimp.reclamp(new_pos.z, -9, -4)
end
end
return new_pos
end
if position.z >= -4 and position.z <= 4 then --limit 14
new_pos.y = 0
new_pos.x = steampunk_blimp.clamp(position.x, -14, 14)
if orig_pos.x <= -6 or orig_pos.x >= 6 then new_pos.x = steampunk_blimp.reclamp(new_pos.x, -6, 6) end
return new_pos
end
if position.z > 4 and position.z <= 19 then --limit 11
new_pos.y = 0
new_pos.x = steampunk_blimp.clamp(position.x, -12, 12)
if position.z < 14 then
if orig_pos.x <= -6 or orig_pos.x >= 6 then
new_pos.x = steampunk_blimp.reclamp(new_pos.x, -6, 6)
else
new_pos.z = steampunk_blimp.reclamp(new_pos.z, 4, 14)
end
end
return new_pos
end
if position.z > 19 and position.z <= 22 then --limit 10
new_pos.y = 4.4
new_pos.x = steampunk_blimp.clamp(new_pos.x, -10, 10)
return new_pos
end
if position.z > 22 and position.z <= 30 then --limit 7
new_pos.y = 8.5
new_pos.x = steampunk_blimp.clamp(new_pos.x, -7, 7)
return new_pos
end
if position.z > 30 and position.z <= 36 then --limit 5
new_pos.y = 8.5
new_pos.x = steampunk_blimp.clamp(new_pos.x, -5, 5)
return new_pos
end
if position.z > 36 and position.z < 47 then --limit 1
new_pos.y = 8.5
new_pos.x = steampunk_blimp.clamp(new_pos.x, -2, 2)
return new_pos
end
return new_pos
end
function steampunk_blimp.ladder_map(pos, dpos)
local orig_pos = vector.new(pos)
local position = vector.new(dpos)
local new_pos = vector.new(dpos)
new_pos.z = steampunk_blimp.clamp(new_pos.z, -18, -12)
if position.z > -20 and position.z < -10 then --limit 10
new_pos.x = steampunk_blimp.clamp(new_pos.x, 4, 12)
end
return new_pos
end
local function is_ladder_zone(pos)
local ladder_zone = false
if pos.z <= -12 and pos.z >= -18 and pos.x > 4 and pos.x < 12 then ladder_zone = true end
return ladder_zone
end
local function get_result_pos(self, player)
local pos = nil
if player then
local direction = player:get_look_horizontal()
local rotation = self.object:get_rotation()
direction = direction - rotation.y
local y_rot = -math.deg(direction)
local ctrl = player:get_player_control()
pos = vector.new()
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 dir = 0
if ctrl.up then dir = -1 end
if ctrl.down then dir = 1 end
if ctrl.left then
direction = direction - math.rad(90)
dir = 1
end
if ctrl.right then
direction = direction + math.rad(90)
dir = 1
end
local time_correction = (self.dtime/steampunk_blimp.ideal_step)
local move = 0.3 * dir * time_correction
pos.x = move * math.cos(-direction)
pos.z = move * math.sin(-direction)
--[[
sin(theta) = opposite/hypotenuse
cos(theta) = adjacent/hypotenuse
For X "Distance * COS ( Angle )"
For Y "Distance * SIN ( Angle )"
]]--
else
player_api.set_animation(player, "stand")
end
end
return pos
end
function steampunk_blimp.navigate_deck(pos, dpos, player)
local pos_d = dpos
local ladder_zone = is_ladder_zone(pos)
local upper_deck_y = 20.821
if player then
if pos.y == upper_deck_y then
pos_d = steampunk_blimp.boat_upper_deck_map(pos, dpos)
elseif pos.y <= 8.5 and pos.y >= 0 then
if ladder_zone == false then
pos_d = steampunk_blimp.boat_lower_deck_map(pos, dpos)
end
elseif pos.y > 8.5 and pos.y < upper_deck_y then
pos_d = steampunk_blimp.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 < 0 then pos_d.y = 0 end
end
end
end
end
return pos_d
end
function steampunk_blimp.move_persons(self)
--self._passenger = nil
for i = 5,1,-1
do
if self.driver_name and self._passengers[i] == self.driver_name then
local player = minetest.get_player_by_name(self.driver_name)
--the driver
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]))
local player = minetest.get_player_by_name(self._passengers[i])
--the rest of the passengers
if player then
local result_pos = get_result_pos(self, player)
local y_rot = 0
if result_pos then
y_rot = result_pos.y -- the only field that returns a rotation
local new_pos = vector.new(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 = steampunk_blimp.boat_lower_deck_map(self._passengers_base_pos[i], new_pos)
local pos_d = steampunk_blimp.navigate_deck(self._passengers_base_pos[i], new_pos, player)
--minetest.chat_send_all(dump(height))
self._passengers_base_pos[i] = vector.new(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