Noch mehr mods
This commit is contained in:
parent
a063db5d3b
commit
cf017b2ca1
527 changed files with 21113 additions and 181 deletions
209
mods/hot_air_balloons/movement.lua
Normal file
209
mods/hot_air_balloons/movement.lua
Normal file
|
@ -0,0 +1,209 @@
|
|||
--localize global functions
|
||||
local vector_new = vector.new
|
||||
local math_hypot = math.hypot
|
||||
local atan = math.atan
|
||||
local cos = math.cos
|
||||
local sin = math.sin
|
||||
local abs = math.abs
|
||||
local pi = math.pi
|
||||
local min = math.min
|
||||
|
||||
--max speed settings
|
||||
local max_ballooning_vertical_speed = 1
|
||||
local max_ballooning_horizontal_speed = 3
|
||||
|
||||
local function is_water_is_air(pos)
|
||||
local node_name = minetest.get_node(pos).name
|
||||
return minetest.get_item_group(node_name, "water") > 0,
|
||||
node_name == "air"
|
||||
end
|
||||
local function get_vertical_acceleration(self)
|
||||
local heat = self.heat
|
||||
local vel_y = self.object:getvelocity().y
|
||||
local acc_candidate = heat / 1000 - 0.5
|
||||
|
||||
--enforce max speed
|
||||
if vel_y > max_ballooning_vertical_speed
|
||||
and acc_candidate * vel_y > 0
|
||||
then
|
||||
return 0
|
||||
else
|
||||
return acc_candidate
|
||||
end
|
||||
end
|
||||
|
||||
--if balloon is submerged
|
||||
local function float_up(self, vel)
|
||||
self.submerged = true
|
||||
vel.y = 1
|
||||
return vel
|
||||
end
|
||||
|
||||
local function swim(self, vel)
|
||||
--allow controls, allow up
|
||||
local pos = self.object:get_pos()
|
||||
--keep y constant or rising
|
||||
local acc_y = get_vertical_acceleration(self)
|
||||
|
||||
if self.submerged or acc_y < 0
|
||||
then
|
||||
self.submerged = false
|
||||
vel.y = 0
|
||||
return 0, vel
|
||||
else
|
||||
return acc_y, vel
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local tau = pi * 2
|
||||
--returns the radian equivalent of a in the range [0, tau)
|
||||
local function to_radian(a)
|
||||
if a < 0
|
||||
then
|
||||
return to_radian(a + tau)
|
||||
elseif a >= tau
|
||||
then
|
||||
return to_radian(a - tau)
|
||||
else
|
||||
return a
|
||||
end
|
||||
end
|
||||
--decides which is the shortest way to rotate towards where the player is looking
|
||||
local function get_rotate_direction(a, b)
|
||||
return to_radian(a - b) < to_radian(b - a)
|
||||
end
|
||||
|
||||
--rotates the balloon towards where the player is looking
|
||||
local pi_192ths = pi / 192 --radians to turn each step
|
||||
local function rotate(self, player)
|
||||
-- + pi so it finishes rotating when looking towards where the player is looking
|
||||
local player_yaw = player:get_look_horizontal() + pi
|
||||
local self_yaw = self.object:getyaw()
|
||||
|
||||
if get_rotate_direction(player_yaw, self_yaw)
|
||||
then
|
||||
self.object:setyaw(to_radian(self_yaw - pi_192ths))
|
||||
else
|
||||
self.object:setyaw(to_radian(self_yaw + pi_192ths))
|
||||
end
|
||||
end
|
||||
|
||||
--takes wasd and turns it into a 2d vector
|
||||
local pi_halves = pi / 2
|
||||
function get_direction(right, left, up, down)
|
||||
local inline, cross = 0, 0
|
||||
local move = right or left or up or down
|
||||
if left then cross = 1 end
|
||||
if right then cross = cross - 1 end
|
||||
if up then inline = 1 end
|
||||
if down then inline = inline - 1 end
|
||||
local arg
|
||||
if inline < 0
|
||||
then
|
||||
return atan(cross / inline) + pi, move
|
||||
elseif inline > 0
|
||||
then
|
||||
return atan(cross / inline), move
|
||||
else
|
||||
return pi_halves * cross, move
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--[[
|
||||
space to rotate where the player is looking
|
||||
wasd to apply acceleration
|
||||
shift to let out hot air, cooling the balloon
|
||||
]]
|
||||
local function handle_control(self, vel)
|
||||
if not self.pilot
|
||||
then
|
||||
return 0, 0
|
||||
end
|
||||
local player = minetest.get_player_by_name(self.pilot)
|
||||
if not player --player left, balloon should get deleted
|
||||
then
|
||||
return 0, 0
|
||||
end
|
||||
local control = player:get_player_control()
|
||||
if control.sneak --lowering heat quickly
|
||||
then
|
||||
local heat = self.heat - 30
|
||||
if heat < 0
|
||||
then
|
||||
self.heat = 0
|
||||
else
|
||||
self.heat = heat
|
||||
end
|
||||
end
|
||||
|
||||
if control.jump --rotate towards player yaw
|
||||
then
|
||||
rotate(self, player)
|
||||
end
|
||||
|
||||
--taking direction from get_direction
|
||||
--and turning it into radians.
|
||||
--if max speed is reached, only acceleration in the opposite direction is applied.
|
||||
local dir_radians, move = get_direction(control.right, control.left, control.up, control.down)
|
||||
if move and math_hypot(vel.x, vel.z)
|
||||
then
|
||||
dir_radians = dir_radians + player:get_look_horizontal()
|
||||
local x, z = -sin(dir_radians), cos(dir_radians)
|
||||
if math_hypot(vel.x, vel.z) > max_ballooning_horizontal_speed
|
||||
then
|
||||
if x * vel.x > 0
|
||||
then
|
||||
x = 0
|
||||
end
|
||||
if z * vel.z > 0
|
||||
then
|
||||
z = 0
|
||||
end
|
||||
end
|
||||
return x, z
|
||||
end
|
||||
return 0, 0
|
||||
end
|
||||
|
||||
--[[handle movement in different cases
|
||||
movement restrictions:
|
||||
-on ground: only vertical movement
|
||||
-on water: free movement, though vertical only if up
|
||||
-submerged: free movement, vertical goes up automatically
|
||||
-in air: completely free movement
|
||||
]]
|
||||
|
||||
return function(self)
|
||||
local pos_in = self.object:get_pos()
|
||||
local pos_under = vector_new(pos_in.x, pos_in.y - 0.1, pos_in.z)
|
||||
local on_water, in_air = is_water_is_air(pos_under)
|
||||
local acc = vector_new(0, 0, 0)
|
||||
local vel = self.object:getvelocity()
|
||||
|
||||
|
||||
if is_water_is_air(pos_in) --if submerged
|
||||
then
|
||||
vel = float_up(self, vel)
|
||||
acc.x, acc.z = handle_control(self, vel)
|
||||
self.object:setvelocity(vel)
|
||||
elseif on_water --if on water
|
||||
then
|
||||
acc.y, vel = swim(self, vel)
|
||||
self.object:setvelocity(vel)
|
||||
acc.x, acc.z = handle_control(self, vel)
|
||||
elseif in_air
|
||||
then
|
||||
--allow controls and height change
|
||||
acc.y = get_vertical_acceleration(self)
|
||||
acc.x, acc.z = handle_control(self, vel)
|
||||
else --if on ground
|
||||
--only allow height change
|
||||
acc.y = get_vertical_acceleration(self)
|
||||
vel.x = 0
|
||||
vel.z = 0
|
||||
self.object:setvelocity(vel)
|
||||
end
|
||||
self.object:setacceleration(acc)
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue