-- 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)