91 lines
3.4 KiB
Lua
91 lines
3.4 KiB
Lua
-- Periodically check the player position if it is in the valid range.
|
||
-- For example, if the player "fell out" of the level.
|
||
--
|
||
-- If the player is out of range, then:
|
||
-- * In the menu ship: Teleport back to ship spawn
|
||
-- * In a level: Fail level, teleport back to ship and taunt player
|
||
-- * Any other game state: Do nothing
|
||
--
|
||
-- Additionally, it is checked whether the player head is stuck
|
||
-- in a solid node.
|
||
--
|
||
-- Having the fly or noclip privs bypasses all resets.
|
||
|
||
local S = minetest.get_translator("lzr_fallout")
|
||
|
||
local CRUSH_TIMER = 3
|
||
local FALLOUT_TIMER = 2
|
||
local SHIP_FALLOUT_Y = lzr_globals.MENU_SHIP_POS.y + lzr_globals.MENU_SHIP_FALLOUT_Y_OFFSET
|
||
|
||
local timer = 0
|
||
local crush_timer = 0
|
||
minetest.register_globalstep(function(dtime)
|
||
timer = timer + dtime
|
||
if timer < FALLOUT_TIMER then
|
||
return
|
||
end
|
||
timer = 0
|
||
local players = minetest.get_connected_players()
|
||
local state = lzr_gamestate.get_state()
|
||
for p=1, #players do
|
||
local player = players[p]
|
||
local privs = minetest.get_player_privs(player:get_player_name())
|
||
if not (privs["fly"] or privs["noclip"]) then
|
||
local pos = player:get_pos()
|
||
if state == lzr_gamestate.MENU then
|
||
if pos.y < SHIP_FALLOUT_Y then
|
||
local spawn = vector.add(lzr_globals.MENU_SHIP_POS, lzr_globals.MENU_SHIP_PLAYER_SPAWN_OFFSET)
|
||
player:set_pos(spawn)
|
||
end
|
||
crush_timer = 0
|
||
elseif state == lzr_gamestate.LEVEL then
|
||
-- Below allowed minimum Y
|
||
if pos.y < lzr_globals.LEVEL_FALLOUT_Y then
|
||
lzr_messages.show_message(player, S("You are sleeping with the fishes!"), 6.0, 0xFF0000)
|
||
lzr_levels.leave_level()
|
||
crush_timer = 0
|
||
return
|
||
else
|
||
-- Outside of level bounds in other directions
|
||
local minpos = lzr_globals.LEVEL_POS
|
||
local maxpos = vector.add(lzr_globals.LEVEL_POS, lzr_levels.get_level_size())
|
||
if pos.x < minpos.x -0.5 or pos.x > maxpos.x + 0.5 or pos.z < minpos.z -0.5 or pos.z > maxpos.z + 0.5 or pos.y > maxpos.y + 0.5 then
|
||
lzr_messages.show_message(player, S("Where yer thinks yar goin’, landlubber?"), 6.0, 0xFF0000)
|
||
lzr_levels.leave_level()
|
||
crush_timer = 0
|
||
return
|
||
else
|
||
-- Player head got stuck in solid node for a few seconds
|
||
local node2 = minetest.get_node(vector.offset(pos, 0, 1, 0))
|
||
local def2 = minetest.registered_nodes[node2.name]
|
||
if def2 and def2.walkable and minetest.get_item_group(node2.name, "slab") == 0 and minetest.get_item_group(node2.name, "stair") == 0 and minetest.get_item_group(node2.name, "takable") == 0 then
|
||
-- Stuck in solid skull: No further delay
|
||
if minetest.get_item_group(node2.name, "skull") ~= 0 then
|
||
lzr_messages.show_message(player, S("You were skull-crushed!"), 6.0, 0xFF0000)
|
||
lzr_levels.leave_level()
|
||
crush_timer = 0
|
||
return
|
||
end
|
||
-- Stuck in other solid node: After a short time
|
||
-- Only full-size nodes count
|
||
if (not def2.collision_box and not def2.node_box) or (def2.collision_box and def2.collision_box.type == "regular") or (not def2.collision_box and def2.node_box and def2.node_box.type == "regular") then
|
||
crush_timer = crush_timer + FALLOUT_TIMER + dtime
|
||
if crush_timer > CRUSH_TIMER then
|
||
lzr_messages.show_message(player, S("You were between a rock and a hard place."), 6.0, 0xFF0000)
|
||
lzr_levels.leave_level()
|
||
crush_timer = 0
|
||
return
|
||
end
|
||
end
|
||
else
|
||
crush_timer = 0
|
||
end
|
||
end
|
||
end
|
||
else
|
||
crush_timer = 0
|
||
end
|
||
end
|
||
end
|
||
end)
|