mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 20:21:32 -06:00
Factorio: prevent players from getting stuck from Teleport Traps (#4537)
This commit is contained in:
@@ -49,6 +49,73 @@ function fire_entity_at_entities(entity_name, entities, speed)
|
||||
end
|
||||
end
|
||||
|
||||
local teleport_requests = {}
|
||||
local teleport_attempts = {}
|
||||
local max_attempts = 100
|
||||
|
||||
function attempt_teleport_player(player, attempt)
|
||||
-- global attempt storage as metadata can't be stored
|
||||
if attempt == nil then
|
||||
attempt = teleport_attempts[player.index]
|
||||
else
|
||||
teleport_attempts[player.index] = attempt
|
||||
end
|
||||
|
||||
if attempt > max_attempts then
|
||||
player.print("Teleport failed: No valid position found after " .. max_attempts .. " attempts!")
|
||||
teleport_attempts[player.index] = 0
|
||||
return
|
||||
end
|
||||
|
||||
local surface = player.character.surface
|
||||
local prototype_name = player.character.prototype.name
|
||||
local original_position = player.character.position
|
||||
local candidate_position = random_offset_position(original_position, 1024)
|
||||
|
||||
local non_colliding_position = surface.find_non_colliding_position(
|
||||
prototype_name, candidate_position, 0, 1
|
||||
)
|
||||
|
||||
if non_colliding_position then
|
||||
-- Request pathfinding asynchronously
|
||||
local path_id = surface.request_path{
|
||||
bounding_box = player.character.prototype.collision_box,
|
||||
collision_mask = { layers = { ["player"] = true } },
|
||||
start = original_position,
|
||||
goal = non_colliding_position,
|
||||
force = player.force.name,
|
||||
radius = 1,
|
||||
pathfind_flags = {cache = true, low_priority = true, allow_paths_through_own_entities = true},
|
||||
}
|
||||
|
||||
-- Store the request with the player index as the key
|
||||
teleport_requests[player.index] = path_id
|
||||
else
|
||||
attempt_teleport_player(player, attempt + 1)
|
||||
end
|
||||
end
|
||||
|
||||
function handle_teleport_attempt(event)
|
||||
for player_index, path_id in pairs(teleport_requests) do
|
||||
-- Check if the event matches the stored path_id
|
||||
if path_id == event.id then
|
||||
local player = game.players[player_index]
|
||||
|
||||
if event.path then
|
||||
if player.character then
|
||||
player.character.teleport(event.path[#event.path].position) -- Teleport to the last point in the path
|
||||
-- Clear the attempts for this player
|
||||
teleport_attempts[player_index] = 0
|
||||
return
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
attempt_teleport_player(player, nil)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
function spill_character_inventory(character)
|
||||
if not (character and character.valid) then
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user