Improve parachute spawn space checks
This commit is contained in:
parent
b6f3ef6b97
commit
71b26f060c
@ -22,6 +22,55 @@ local function air_physics(v)
|
|||||||
return ((m * g + 0.5 * cw * rho * A * v * v) / m)
|
return ((m * g + 0.5 * cw * rho * A * v * v) / m)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Checks if pos is suitable for a parachute to spawn in
|
||||||
|
-- for player
|
||||||
|
local check_parachute_spawnable = function(pos, player)
|
||||||
|
-- We do 5 raycasts, which are all vertical.
|
||||||
|
-- 4 raycasts for the 4 vertical edges of the
|
||||||
|
-- (soon-to-exist) parachute collisionbox and
|
||||||
|
-- 1 raycast for the center.
|
||||||
|
-- The position is only treated as OK
|
||||||
|
-- when all raycasts find nothing except the player.
|
||||||
|
|
||||||
|
-- Tiny number added to the coordinates to make
|
||||||
|
-- the checked area slightly bigger than the expected
|
||||||
|
-- collision box to make sure the collisionbox
|
||||||
|
-- definitely won't overlap with nodes or objects when
|
||||||
|
-- spawned.
|
||||||
|
local tiny = 0.01
|
||||||
|
local side = CBOX_SIDE + tiny
|
||||||
|
local offsets = {
|
||||||
|
-- for testing the middle
|
||||||
|
{ 0, 0 },
|
||||||
|
-- for testing the 4 edges of the collisionbox
|
||||||
|
{ -side, -side },
|
||||||
|
{ -side, side },
|
||||||
|
{ side, -side },
|
||||||
|
{ side, side },
|
||||||
|
}
|
||||||
|
local y_extend = 1 -- Check a little bit below the potential collisionbox as well
|
||||||
|
-- so the parachute isn't spawned when standing on the ground
|
||||||
|
-- Finally check the rays
|
||||||
|
for i=1, #offsets do
|
||||||
|
local off_start = vector.new(offsets[i][1], CBOX_BOTTOM - y_extend - tiny, offsets[i][2])
|
||||||
|
local off_end = vector.new(offsets[i][1], CBOX_TOP + tiny, offsets[i][2])
|
||||||
|
local ray_start = vector.add(pos, off_start)
|
||||||
|
local ray_end = vector.add(pos, off_end)
|
||||||
|
local ray = minetest.raycast(ray_start, ray_end, true, true)
|
||||||
|
while true do
|
||||||
|
local thing = ray:next()
|
||||||
|
if not thing then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
-- Any collision counts, EXCEPT with the parachuting player
|
||||||
|
if not (thing.type == "object" and thing.ref == player) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
-- Tries to spawn a parachute entity and attaches it to player.
|
-- Tries to spawn a parachute entity and attaches it to player.
|
||||||
-- Will fail if player is already attached to something
|
-- Will fail if player is already attached to something
|
||||||
-- or if player is too close to the ground.
|
-- or if player is too close to the ground.
|
||||||
@ -40,13 +89,18 @@ local function open_parachute_for_player(player, play_sound, load_area)
|
|||||||
|
|
||||||
local pos = player:get_pos()
|
local pos = player:get_pos()
|
||||||
|
|
||||||
local on = minetest.get_node({x = pos.x, y = pos.y - 1, z = pos.z})
|
|
||||||
|
|
||||||
if rp_player.player_attached[name] then
|
if rp_player.player_attached[name] then
|
||||||
return false, "already_attached"
|
return false, "already_attached"
|
||||||
end
|
end
|
||||||
|
|
||||||
if on.name == "air" or on.name == "ignore" then
|
local spawnable = check_parachute_spawnable(pos, player)
|
||||||
|
|
||||||
|
|
||||||
|
local in_node = minetest.get_node(pos)
|
||||||
|
if in_node.name == "ignore" then
|
||||||
|
return false, "on_ground"
|
||||||
|
end
|
||||||
|
if spawnable then
|
||||||
-- Spawn parachute
|
-- Spawn parachute
|
||||||
local ppos = vector.new(pos.x, pos.y + CBOX_BOTTOM, pos.z)
|
local ppos = vector.new(pos.x, pos.y + CBOX_BOTTOM, pos.z)
|
||||||
|
|
||||||
@ -62,16 +116,12 @@ local function open_parachute_for_player(player, play_sound, load_area)
|
|||||||
minetest.sound_play({name="parachute_open", pos=ppos}, {gain=0.5}, true)
|
minetest.sound_play({name="parachute_open", pos=ppos}, {gain=0.5}, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
if on.name ~= "ignore" then
|
obj:set_velocity(
|
||||||
obj:set_velocity(
|
{
|
||||||
{
|
x = 0,
|
||||||
x = 0,
|
y = math.min(0, player:get_velocity().y),
|
||||||
y = math.min(0, player:get_velocity().y),
|
z = 0
|
||||||
z = 0
|
})
|
||||||
})
|
|
||||||
else
|
|
||||||
obj:set_velocity(vector.zero())
|
|
||||||
end
|
|
||||||
|
|
||||||
player:set_attach(obj, "", {x = 0, y = -8, z = 0}, {x = 0, y = 0, z = 0}, true)
|
player:set_attach(obj, "", {x = 0, y = -8, z = 0}, {x = 0, y = 0, z = 0}, true)
|
||||||
|
|
||||||
@ -80,9 +130,6 @@ local function open_parachute_for_player(player, play_sound, load_area)
|
|||||||
local lua = obj:get_luaentity()
|
local lua = obj:get_luaentity()
|
||||||
lua.attached = name
|
lua.attached = name
|
||||||
|
|
||||||
local in_node = minetest.get_node(pos)
|
|
||||||
lua.ignore_mode = in_node.name == "ignore"
|
|
||||||
|
|
||||||
rp_player.player_attached[name] = true
|
rp_player.player_attached[name] = true
|
||||||
|
|
||||||
local meta = player:get_meta()
|
local meta = player:get_meta()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user