local Task = require 'utils.schedule' local Game = require 'utils.game' local Event = require 'utils.event' local Token = require 'utils.token' local Utils = require 'utils.core' global.walking = {} global.walking_storage = {} --- Returns a player from walkabout after the timeout. -- If the player is no longer logged in, store their info -- in the global table walking_storage local custom_commands_return_player = Token.register( function(args) local player = args.player if not player.valid then return end local index = player.index -- If walking is false it means they got cleaned by clean_on_join if global.walking[index] == false then return end -- If the player is no longer connected, store that information. if player.connected then global.walking[index] = false local walkabout_character = player.character if walkabout_character and walkabout_character.valid then walkabout_character.destroy() end local character = args.character if character ~= nil and character.valid then player.character = character else player.create_character() player.teleport(args.position) end player.force = args.force game.print(args.player.name .. ' came back from his walkabout.') else local data = {index = index, character = args.character, force = args.force, position = args.position} table.insert(global.walking_storage, data) end end ) --- Sends a player on a walkabout: -- They are teleported far away, placed on a neutral force, and are given a new character. -- They are turned after the timeout by custom_commands_return_player local function walkabout(cmd) if game.player and not game.player.admin then Utils.cant_run(cmd.name) return end local params = {} if cmd.parameter == nil then Game.player_print('Walkabout failed, check /help walkabout.') return end for param in string.gmatch(cmd.parameter, '%S+') do table.insert(params, param) end local player_name = params[1] local duration = 60 if #params > 2 then Game.player_print('Walkabout failed, check /help walkabout.') return elseif #params == 2 and tonumber(params[2]) == nil then Game.player_print(params[2] .. ' is not a number.') return elseif #params == 2 and tonumber(params[2]) then duration = tonumber(params[2]) end if duration < 15 then duration = 15 end local player = game.players[player_name] if not player or not player.character or global.walking[player.index] then Game.player_print(player_name .. ' could not go on a walkabout.') return end local chunks = {} for chunk in player.surface.get_chunks() do table.insert(chunks, chunk) end local surface = player.surface local chunk = surface.get_random_chunk() local pos = {x = chunk.x * 32, y = chunk.y * 32} local non_colliding_pos = surface.find_non_colliding_position('player', pos, 100, 1) local character = player.character if character and character.valid then character.walking_state = {walking = false} end if non_colliding_pos then game.print(player_name .. ' went on a walkabout, to find himself.') Task.set_timeout( duration, custom_commands_return_player, { player = player, force = player.force, position = {x = player.position.x, y = player.position.y}, character = character } ) player.character = nil player.create_character() player.teleport(non_colliding_pos) player.force = 'neutral' global.walking[player.index] = true else Game.player_print('Walkabout failed: could not find non colliding position') end end --- Cleans the walkabout status off players who disconnected during walkabout. -- Restores their original force, character, and position. local function clean_on_join(event) local player = Game.get_player_by_index(event.player_index) local index = player.index if global.walking[index] then global.walking[index] = false local walking_storage = global.walking_storage for _, s in pairs(walking_storage) do if s.index == index then local walkabout_character = player.character if walkabout_character and walkabout_character.valid then walkabout_character.destroy() end local character = s.character if character ~= nil and character.valid then player.character = character else player.create_character() player.teleport(s.position) end player.force = s.force end end end end Event.add(defines.events.on_player_joined_game, clean_on_join) commands.add_command('walkabout', ' - Send someone on a walk. (Admins only)', walkabout)