first commit
25
README.md
|
@ -1 +1,24 @@
|
|||
# nautilus
|
||||
Minetest 5.2 mod: Nautilus
|
||||
========================================
|
||||
|
||||
This is the "Nautilus", a grandchild mod from "Sailing Kit".
|
||||
It's water dynamics comes from Sailing Kit (by TheTermos). So it depends on mobkit. And It dependes on the biofuel mod for fuel making.
|
||||
It starts anchored, so press aux key (special key - maybe E in your keyboard) to remove anchor. With keyboard you can move the nautilus. When you press sneak, it it dives, when you press jump, it emerges. And you can set anchor again by pressing E, but it only works when the Nautilus is near completely stopped (when the anchor is sucessfull, you receive a message on chat).
|
||||
|
||||
It can be painted using dye of any color you want, you must punch the seat with the dye.
|
||||
|
||||
|
||||
Biofuel mod can be found here: https://github.com/APercy/minetest_biofuel
|
||||
|
||||
-----------------------
|
||||
It uses some code from Sailing Kit (by TheTermos)
|
||||
|
||||
License of source code:
|
||||
MIT (see file LICENSE)
|
||||
|
||||
License of media (textures and sounds):
|
||||
---------------------------------------
|
||||
collision.ogg by APercy. See License file
|
||||
|
||||
Submarine model by APercy. See License file
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
mobkit
|
||||
default
|
||||
biofuel
|
|
@ -0,0 +1,505 @@
|
|||
--
|
||||
-- constants
|
||||
--
|
||||
local LONGIT_DRAG_FACTOR = 0.13*0.13
|
||||
local LATER_DRAG_FACTOR = 2.0
|
||||
|
||||
nautilus={}
|
||||
nautilus.gravity = tonumber(minetest.settings:get("movement_gravity")) or 9.8
|
||||
|
||||
nautilus.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',
|
||||
}
|
||||
|
||||
dofile(minetest.get_modpath("nautilus") .. DIR_DELIM .. "nautilus_control.lua")
|
||||
dofile(minetest.get_modpath("nautilus") .. DIR_DELIM .. "nautilus_fuel_management.lua")
|
||||
dofile(minetest.get_modpath("nautilus") .. DIR_DELIM .. "nautilus_custom_physics.lua")
|
||||
|
||||
|
||||
--
|
||||
-- helpers and co.
|
||||
--
|
||||
|
||||
local creative_exists = minetest.global_exists("creative")
|
||||
|
||||
function nautilus.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 nautilus.dot(v1,v2)
|
||||
return v1.x*v2.x+v1.y*v2.y+v1.z*v2.z
|
||||
end
|
||||
|
||||
function nautilus.sign(n)
|
||||
return n>=0 and 1 or -1
|
||||
end
|
||||
|
||||
function nautilus.minmax(v,m)
|
||||
return math.min(math.abs(v),m)*nautilus.sign(v)
|
||||
end
|
||||
|
||||
--painting
|
||||
function nautilus.paint(self, colstr)
|
||||
if colstr then
|
||||
self.color = colstr
|
||||
local l_textures = self.initial_properties.textures
|
||||
for _, texture in ipairs(l_textures) do
|
||||
local i,indx = texture:find('nautilus_painting.png')
|
||||
if indx then
|
||||
l_textures[_] = "nautilus_painting.png^[multiply:".. colstr
|
||||
end
|
||||
end
|
||||
self.object:set_properties({textures=l_textures})
|
||||
end
|
||||
end
|
||||
|
||||
-- destroy the boat
|
||||
function nautilus.destroy(self)
|
||||
if self.sound_handle then
|
||||
minetest.sound_stop(self.sound_handle)
|
||||
self.sound_handle = nil
|
||||
end
|
||||
|
||||
if self.driver_name then
|
||||
-- detach the driver first (puncher must be driver)
|
||||
puncher:set_detach()
|
||||
puncher:set_eye_offset({x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0})
|
||||
player_api.player_attached[name] = nil
|
||||
-- player should stand again
|
||||
player_api.set_animation(puncher, "stand")
|
||||
self.driver_name = nil
|
||||
end
|
||||
|
||||
local pos = self.object:get_pos()
|
||||
if self.pointer then self.pointer: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},'nautilus: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
|
||||
end
|
||||
|
||||
-- attach player
|
||||
function nautilus.attach(self, player)
|
||||
local name = player:get_player_name()
|
||||
self.driver_name = name
|
||||
player:set_breath(10)
|
||||
|
||||
-- temporary------
|
||||
self.hp = 50 -- why? cause I can desist from destroy
|
||||
------------------
|
||||
|
||||
-- attach the driver
|
||||
player:set_attach(self.object, "", {x = 0, y = -7, z = -2}, {x = 0, y = 0, z = 0})
|
||||
player:set_eye_offset({x = 0, y = -12, z = 0}, {x = 0, y = -12, z = -5})
|
||||
player_api.player_attached[name] = true
|
||||
-- make the driver sit
|
||||
minetest.after(0.2, function()
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if player then
|
||||
player_api.set_animation(player, "sit")
|
||||
end
|
||||
end)
|
||||
-- disable gravity
|
||||
self.object:set_acceleration(vector.new())
|
||||
end
|
||||
|
||||
--
|
||||
-- entity
|
||||
--
|
||||
|
||||
minetest.register_entity("nautilus:boat", {
|
||||
initial_properties = {
|
||||
physical = true,
|
||||
collisionbox = {-1, -1, -1, 1, 1, 1}, --{-1,0,-1, 1,0.3,1},
|
||||
selectionbox = {-0.6,0.6,-0.6, 0.6,1,0.6},
|
||||
visual = "mesh",
|
||||
mesh = "nautilus.b3d",
|
||||
textures = {"nautilus_black.png", "nautilus_painting.png", "nautilus_glass.png", "nautilus_metal.png", "nautilus_metal.png", "nautilus_orange.png", "nautilus_painting.png", "nautilus_red.png", "nautilus_painting.png", "nautilus_helice.png", "nautilus_interior.png", "nautilus_panel.png"},
|
||||
},
|
||||
textures = {},
|
||||
driver_name = nil,
|
||||
sound_handle = nil,
|
||||
energy = 0.001,
|
||||
owner = "",
|
||||
static_save = true,
|
||||
infotext = "A nice submarine",
|
||||
lastvelocity = vector.new(),
|
||||
hp = 50,
|
||||
color = "#ffe400",
|
||||
rudder_angle = 0,
|
||||
timeout = 0;
|
||||
buoyancy = 0.98,
|
||||
max_hp = 50,
|
||||
engine_running = false,
|
||||
anchored = false,
|
||||
physics = nautilus.physics,
|
||||
--water_drag = 0,
|
||||
|
||||
get_staticdata = function(self) -- unloaded/unloads ... is now saved
|
||||
return minetest.serialize({
|
||||
stored_energy = self.energy,
|
||||
stored_owner = self.owner,
|
||||
stored_hp = self.hp,
|
||||
stored_color = self.color,
|
||||
stored_anchor = self.anchored,
|
||||
stored_buoyancy = self.buoyancy,
|
||||
stored_driver_name = self.driver_name,
|
||||
})
|
||||
end,
|
||||
|
||||
on_activate = function(self, staticdata, dtime_s)
|
||||
if staticdata ~= "" and staticdata ~= nil then
|
||||
local data = minetest.deserialize(staticdata) or {}
|
||||
self.energy = data.stored_energy
|
||||
self.owner = data.stored_owner
|
||||
self.hp = data.stored_hp
|
||||
self.color = data.stored_color
|
||||
self.anchored = data.stored_anchor
|
||||
self.buoyancy = data.stored_buoyancy
|
||||
self.driver_name = data.stored_driver_name
|
||||
--minetest.debug("loaded: ", self.energy)
|
||||
end
|
||||
|
||||
nautilus.paint(self, self.color)
|
||||
local pos = self.object:get_pos()
|
||||
|
||||
--animation load - stoped
|
||||
self.object:set_animation({x = 1, y = 5}, 0, 0, true);
|
||||
|
||||
local pointer=minetest.add_entity(pos,'nautilus:pointer')
|
||||
local energy_indicator_angle = nautilus.get_pointer_angle(self.energy)
|
||||
pointer:set_attach(self.object,'',{x=0,y=-8.45,z=5.31},{x=0,y=0,z=energy_indicator_angle})
|
||||
self.pointer = pointer
|
||||
|
||||
self.object:set_armor_groups({immortal=1})
|
||||
|
||||
mobkit.actfunc(self, staticdata, dtime_s)
|
||||
|
||||
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 newroll=roll
|
||||
|
||||
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 = nautilus.dot(velocity,hull_direction)
|
||||
local longit_drag = vector.multiply(hull_direction,longit_speed*longit_speed*LONGIT_DRAG_FACTOR*-1*nautilus.sign(longit_speed))
|
||||
local later_speed = nautilus.dot(velocity,nhdir)
|
||||
local later_drag = vector.multiply(nhdir,later_speed*later_speed*LATER_DRAG_FACTOR*-1*nautilus.sign(later_speed))
|
||||
local accel = vector.add(longit_drag,later_drag)
|
||||
|
||||
local vel = self.object:get_velocity()
|
||||
|
||||
local is_attached = false
|
||||
if self.owner then
|
||||
local player = minetest.get_player_by_name(self.owner)
|
||||
|
||||
if player then
|
||||
local player_attach = player:get_attach()
|
||||
if player_attach then
|
||||
if player_attach == self.object then is_attached = true end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if is_attached then
|
||||
local impact = nautilus.get_hipotenuse_value(vel, self.last_vel)
|
||||
if impact > 1 then
|
||||
--self.damage = self.damage + impact --sum the impact value directly to damage meter
|
||||
local curr_pos = self.object:get_pos()
|
||||
minetest.sound_play("collision", {
|
||||
to_player = self.driver_name,
|
||||
--pos = curr_pos,
|
||||
--max_hear_distance = 5,
|
||||
gain = 1.0,
|
||||
fade = 0.0,
|
||||
pitch = 1.0,
|
||||
})
|
||||
--[[if self.damage > 100 then --if acumulated damage is greater than 100, adieu
|
||||
nautilus.destroy(self)
|
||||
end]]--
|
||||
end
|
||||
local player = minetest.get_player_by_name(self.owner)
|
||||
player:set_breath(10)
|
||||
--control
|
||||
accel = nautilus.nautilus_control(self, dtime, hull_direction, longit_speed, accel) or vel
|
||||
else
|
||||
-- for some engine error the player can be detached from the submarine, so lets set him attached again
|
||||
local can_stop = true
|
||||
--[[if self.owner and self.driver_name and touching_ground == false then
|
||||
-- attach the driver again
|
||||
local player = minetest.get_player_by_name(self.owner)
|
||||
if player then
|
||||
nautilus.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
|
||||
|
||||
if math.abs(self.rudder_angle)>5 then
|
||||
local turn_rate = math.rad(24)
|
||||
newyaw = yaw + self.dtime*(1 - 1 / (math.abs(longit_speed) + 1)) * self.rudder_angle / 30 * turn_rate * nautilus.sign(longit_speed)
|
||||
end
|
||||
|
||||
-- calculate energy consumption --
|
||||
----------------------------------
|
||||
if self.energy > 0 then
|
||||
local zero_reference = vector.new()
|
||||
local acceleration = nautilus.get_hipotenuse_value(accel, zero_reference)
|
||||
local consumed_power = acceleration/6000
|
||||
self.energy = self.energy - consumed_power;
|
||||
|
||||
local energy_indicator_angle = nautilus.get_pointer_angle(self.energy)
|
||||
if self.pointer:get_luaentity() then
|
||||
self.pointer:set_attach(self.object,'',{x=0,y=-8.45,z=5.31},{x=0,y=0,z=energy_indicator_angle})
|
||||
else
|
||||
--in case it have lost the entity by some conflict
|
||||
self.pointer=minetest.add_entity({x=0,y=-8.45,z=5.31},'nautilus:pointer')
|
||||
self.pointer:set_attach(self.object,'',{x=0,y=-8.45,z=5.31},{x=0,y=0,z=energy_indicator_angle})
|
||||
end
|
||||
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 = nautilus.dot(snormal,nhdir)
|
||||
local rollfactor = -10
|
||||
newroll = (prsr*math.rad(rollfactor))*later_speed
|
||||
--minetest.chat_send_all('newroll: '.. newroll)
|
||||
---------------------------------
|
||||
-- end roll
|
||||
|
||||
--local bob = nautilus.minmax(nautilus.dot(accel,hull_direction),0.8) -- vertical bobbing
|
||||
|
||||
if self.isinliquid then
|
||||
accel.y = accel_y -- + bob
|
||||
newpitch = velocity.y * math.rad(6)
|
||||
self.object:set_acceleration(accel)
|
||||
end
|
||||
|
||||
if newyaw~=yaw or newpitch~=pitch or newroll~=roll then self.object:set_rotation({x=newpitch,y=newyaw,z=newroll}) end
|
||||
|
||||
--saves last velocy for collision detection (abrupt stop)
|
||||
self.last_vel = self.object:get_velocity()
|
||||
end,
|
||||
|
||||
on_punch = function(self, puncher, ttime, toolcaps, dir, damage)
|
||||
if not puncher or not puncher:is_player() then
|
||||
return
|
||||
end
|
||||
local name = puncher:get_player_name()
|
||||
if self.owner and self.owner ~= name and self.owner ~= "" then return 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 touching_ground, liquid_below = nautilus.check_node_below(self.object)
|
||||
|
||||
local is_attached = false
|
||||
if puncher:get_attach() == self.object then
|
||||
is_attached = true
|
||||
end
|
||||
|
||||
local itmstck=puncher:get_wielded_item()
|
||||
local item_name = ""
|
||||
if itmstck then item_name = itmstck:get_name() end
|
||||
|
||||
if is_attached == true and item_name == "biofuel:biofuel" then
|
||||
--refuel
|
||||
nautilus_load_fuel(self, puncher:get_player_name())
|
||||
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 = nautilus.colors[color]
|
||||
--minetest.chat_send_all(color ..' '.. dump(colstr))
|
||||
if colstr then
|
||||
nautilus.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 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
|
||||
nautilus.destroy(self)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end,
|
||||
|
||||
on_rightclick = function(self, clicker)
|
||||
if not clicker or not clicker:is_player() then
|
||||
return
|
||||
end
|
||||
|
||||
local name = clicker:get_player_name()
|
||||
if self.owner and self.owner ~= name and self.owner ~= "" then return end
|
||||
if self.owner == "" then
|
||||
self.owner = name
|
||||
end
|
||||
|
||||
if name == self.driver_name then
|
||||
self.engine_running = false
|
||||
|
||||
-- driver clicked the object => driver gets off the vehicle
|
||||
self.driver_name = nil
|
||||
clicker:set_breath(10)
|
||||
-- sound and animation
|
||||
if self.sound_handle then
|
||||
minetest.sound_stop(self.sound_handle)
|
||||
self.sound_handle = nil
|
||||
end
|
||||
|
||||
--self.engine:set_animation_frame_speed(0)
|
||||
|
||||
-- detach the player
|
||||
clicker:set_detach()
|
||||
player_api.player_attached[name] = nil
|
||||
clicker:set_eye_offset({x=0,y=0,z=0},{x=0,y=0,z=0})
|
||||
player_api.set_animation(clicker, "stand")
|
||||
self.driver = nil
|
||||
self.object:set_acceleration(vector.multiply(nautilus.vector_up, -nautilus.gravity))
|
||||
|
||||
elseif not self.driver_name then
|
||||
-- no driver => clicker is new driver
|
||||
nautilus.attach(self, clicker)
|
||||
self.engine_running = true
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
--
|
||||
-- items
|
||||
--
|
||||
|
||||
-- boat
|
||||
minetest.register_craftitem("nautilus:boat", {
|
||||
description = "Nautilus",
|
||||
inventory_image = "nautilus_inv.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
|
||||
pointed_pos.y=pointed_pos.y+0.2
|
||||
local boat = minetest.add_entity(pointed_pos, "nautilus:boat")
|
||||
if boat and placer then
|
||||
local ent = boat:get_luaentity()
|
||||
local owner = placer:get_player_name()
|
||||
ent.owner = owner
|
||||
boat:set_yaw(placer:get_look_horizontal())
|
||||
itemstack:take_item()
|
||||
end
|
||||
end
|
||||
|
||||
return itemstack
|
||||
end,
|
||||
})
|
||||
|
||||
--
|
||||
-- crafting
|
||||
--
|
||||
|
||||
if minetest.get_modpath("default") then
|
||||
minetest.register_craft({
|
||||
output = "nautilus:boat",
|
||||
recipe = {
|
||||
{"", ""},
|
||||
{"nautilus:hull", "nautilus:engine"},
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
name = nautilus
|
||||
depends = mobkit,default,biofuel
|
||||
author = APercy
|
||||
description = Adds a craftable submarine
|
||||
title = Nautilus
|
|
@ -0,0 +1,109 @@
|
|||
--global constants
|
||||
|
||||
nautilus.nautilus_last_time_command = 0
|
||||
nautilus.vector_up = vector.new(0, 1, 0)
|
||||
|
||||
function nautilus.get_pointer_angle(energy)
|
||||
local angle = energy * 18
|
||||
angle = angle - 90
|
||||
angle = angle * -1
|
||||
return angle
|
||||
end
|
||||
|
||||
function nautilus.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 nautilus.nautilus_control(self, dtime, hull_direction, longit_speed, accel)
|
||||
nautilus.nautilus_last_time_command = nautilus.nautilus_last_time_command + dtime
|
||||
if nautilus.nautilus_last_time_command > 1 then nautilus.nautilus_last_time_command = 1 end
|
||||
local player = minetest.get_player_by_name(self.driver_name)
|
||||
local retval_accel = accel;
|
||||
|
||||
-- player control
|
||||
if player then
|
||||
local ctrl = player:get_player_control()
|
||||
local max_speed_anchor = 0.2
|
||||
if ctrl.aux1 and nautilus.nautilus_last_time_command > 0.3 and longit_speed < max_speed_anchor and longit_speed > -max_speed_anchor then
|
||||
nautilus.nautilus_last_time_command = 0
|
||||
if self.anchored == false then
|
||||
self.anchored = true
|
||||
self.object:set_velocity(vector.new())
|
||||
minetest.chat_send_player(self.driver_name, 'anchors away!')
|
||||
self.buoyancy = 0.98
|
||||
else
|
||||
self.anchored = false
|
||||
minetest.chat_send_player(self.driver_name, 'weigh anchor!')
|
||||
end
|
||||
end
|
||||
|
||||
if self.anchored == false and self.engine_running == true then
|
||||
local paddleacc
|
||||
if longit_speed < 3.0 and ctrl.up then
|
||||
paddleacc = 0.5
|
||||
elseif longit_speed > -1.0 and ctrl.down then
|
||||
paddleacc = -0.5
|
||||
end
|
||||
|
||||
if ctrl.up then
|
||||
self.object:set_animation_frame_speed(40)
|
||||
elseif ctrl.down then
|
||||
self.object:set_animation_frame_speed(-40)
|
||||
else
|
||||
self.object:set_animation_frame_speed(0)
|
||||
end
|
||||
|
||||
if paddleacc then
|
||||
retval_accel=vector.add(accel,vector.multiply(hull_direction,paddleacc))
|
||||
end
|
||||
--minetest.chat_send_all('paddle: '.. paddleacc)
|
||||
end
|
||||
|
||||
if ctrl.jump then
|
||||
self.buoyancy = 0.97
|
||||
elseif ctrl.sneak then
|
||||
self.buoyancy = 1.03
|
||||
else
|
||||
--check if its liquid above
|
||||
local pos_up = self.object:get_pos()
|
||||
pos_up.y = pos_up.y + 2
|
||||
local node_up = minetest.get_node(pos_up).name
|
||||
local nodedef = minetest.registered_nodes[node_up]
|
||||
local liquid_up = nodedef.liquidtype ~= "none"
|
||||
if not liquid_up then
|
||||
--if in surface
|
||||
self.buoyancy = 0.98
|
||||
else
|
||||
--if submerged
|
||||
self.buoyancy = 1
|
||||
end
|
||||
end
|
||||
|
||||
-- rudder
|
||||
local rudder_limit = 30
|
||||
if ctrl.right then
|
||||
self.rudder_angle = math.max(self.rudder_angle-60*dtime,-rudder_limit)
|
||||
elseif ctrl.left then
|
||||
self.rudder_angle = math.min(self.rudder_angle+60*dtime,rudder_limit)
|
||||
end
|
||||
|
||||
--center steering
|
||||
if longit_speed > 0 then
|
||||
local factor = 1
|
||||
if self.rudder_angle > 0 then factor = -1 end
|
||||
local correction = (rudder_limit*(longit_speed/200)) * factor
|
||||
self.rudder_angle = self.rudder_angle + correction
|
||||
end
|
||||
end
|
||||
return retval_accel
|
||||
end
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
local min = math.min
|
||||
local abs = math.abs
|
||||
|
||||
function nautilus.physics(self)
|
||||
local vel=self.object:get_velocity()
|
||||
-- dumb friction
|
||||
if self.isonground and not self.isinliquid then
|
||||
self.object:set_velocity({x= vel.x> 0.2 and vel.x*mobkit.friction or 0,
|
||||
y=vel.y,
|
||||
z=vel.z > 0.2 and vel.z*mobkit.friction or 0})
|
||||
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
|
||||
|
||||
self.object:set_velocity(vnew)
|
||||
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
|
||||
self.isinliquid = surfnodename
|
||||
if surface then -- standing in liquid
|
||||
-- self.isinliquid = true
|
||||
local submergence = min(surface-spos.y,self.height)/self.height
|
||||
-- local balance = self.buoyancy*self.height
|
||||
local buoyacc = mobkit.gravity*(self.buoyancy-submergence)
|
||||
mobkit.set_acceleration(self.object,
|
||||
{x=-vel.x*self.water_drag,y=buoyacc-vel.y*abs(vel.y)*0.4,z=-vel.z*self.water_drag})
|
||||
else
|
||||
-- self.isinliquid = false
|
||||
self.object:set_acceleration({x=0,y=mobkit.gravity,z=0})
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,47 @@
|
|||
--
|
||||
-- fuel
|
||||
--
|
||||
minetest.register_entity('nautilus:pointer',{
|
||||
initial_properties = {
|
||||
physical = false,
|
||||
collide_with_objects=false,
|
||||
pointable=false,
|
||||
visual = "mesh",
|
||||
mesh = "pointer.b3d",
|
||||
textures = {"nautilus_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 nautilus_load_fuel(self, player_name)
|
||||
if self.energy < 9.5 then
|
||||
local player = minetest.get_player_by_name(player_name)
|
||||
local inv = player:get_inventory()
|
||||
local inventory_fuel = "biofuel:biofuel"
|
||||
|
||||
if inv:contains_item("main", inventory_fuel) then
|
||||
local stack = ItemStack(inventory_fuel .. " 1")
|
||||
local taken = inv:remove_item("main", stack)
|
||||
|
||||
self.energy = self.energy + 1
|
||||
if self.energy > 10 then self.energy = 10 end
|
||||
|
||||
local energy_indicator_angle = nautilus.get_pointer_angle(self.energy)
|
||||
self.pointer:set_attach(self.object,'',{x=0,y=-8.45,z=5.31},{x=0,y=0,z=energy_indicator_angle})
|
||||
end
|
||||
else
|
||||
print("Full tank.")
|
||||
end
|
||||
end
|
||||
|
After Width: | Height: | Size: 92 KiB |
After Width: | Height: | Size: 382 B |
After Width: | Height: | Size: 8.5 KiB |
After Width: | Height: | Size: 984 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 2.3 KiB |