You've already forked ComfyFactorio
							
							
				mirror of
				https://github.com/ComfyFactory/ComfyFactorio.git
				synced 2025-10-30 23:47:41 +02:00 
			
		
		
		
	mtn v3 - fix of broken core feature
This commit is contained in:
		| @@ -18,6 +18,7 @@ local Task = require 'utils.task' | ||||
| local Token = require 'utils.token' | ||||
| local MapFunctions = require 'tools.map_functions' | ||||
| local SpamProtection = require 'utils.spam_protection' | ||||
| local AI = require 'utils.ai' | ||||
|  | ||||
| local format_number = require 'util'.format_number | ||||
|  | ||||
| @@ -33,6 +34,13 @@ local sin = math.sin | ||||
| local cos = math.cos | ||||
| local ceil = math.ceil | ||||
|  | ||||
| local clear_items_upon_surface_entry = { | ||||
|     ['small-electric-pole'] = true, | ||||
|     ['medium-electric-pole'] = true, | ||||
|     ['big-electric-pole'] = true, | ||||
|     ['substation'] = true | ||||
| } | ||||
|  | ||||
| local shopkeeper = '[color=blue]Shopkeeper:[/color]\n' | ||||
|  | ||||
| local space = { | ||||
| @@ -1450,10 +1458,18 @@ local function spawn_biter() | ||||
|  | ||||
|     local position = loco_surface.find_non_colliding_position('market', center_position, 128, 0.5) | ||||
|     local biters = { | ||||
|         'character', | ||||
|         'small-biter', | ||||
|         'medium-biter', | ||||
|         'big-biter', | ||||
|         'behemoth-biter', | ||||
|         'character', | ||||
|         'small-spitter', | ||||
|         'medium-spitter', | ||||
|         'big-spitter', | ||||
|         'behemoth-spitter' | ||||
|         'behemoth-spitter', | ||||
|         'compilatron', | ||||
|         'character' | ||||
|     } | ||||
|  | ||||
|     local size_of = #biters | ||||
| @@ -1461,9 +1477,21 @@ local function spawn_biter() | ||||
|     if not position then | ||||
|         return | ||||
|     end | ||||
|     this.locomotive_biter = loco_surface.create_entity({name = biters[random(1, size_of)], position = position, force = 'player', create_build_effect_smoke = false}) | ||||
|     this.locomotive_biter.ai_settings.allow_destroy_when_commands_fail = false | ||||
|     this.locomotive_biter.ai_settings.allow_try_return_to_spawner = false | ||||
|  | ||||
|     local chosen_ent = biters[random(1, size_of)] | ||||
|  | ||||
|     if chosen_ent == 'character' then | ||||
|         local data = { | ||||
|             force = 'player', | ||||
|             surface = loco_surface.index, | ||||
|             command = 1, | ||||
|             tick = 60, | ||||
|             repeat_function = true | ||||
|         } | ||||
|         AI.add_job_to_task(data) | ||||
|     end | ||||
|  | ||||
|     this.locomotive_biter = loco_surface.create_entity({name = chosen_ent, position = position, force = 'player', create_build_effect_smoke = false}) | ||||
|  | ||||
|     rendering.draw_text { | ||||
|         text = ({'locomotive.shoo'}), | ||||
| @@ -1476,6 +1504,11 @@ local function spawn_biter() | ||||
|         alignment = 'center', | ||||
|         scale_with_zoom = false | ||||
|     } | ||||
|  | ||||
|     if not chosen_ent == 'character' then | ||||
|         this.locomotive_biter.ai_settings.allow_destroy_when_commands_fail = false | ||||
|         this.locomotive_biter.ai_settings.allow_try_return_to_spawner = false | ||||
|     end | ||||
| end | ||||
|  | ||||
| local function create_market(data, rebuild) | ||||
| @@ -1852,7 +1885,12 @@ local function shoo(event) | ||||
|                 } | ||||
|             ) | ||||
|             if locomotive_biter and locomotive_biter.valid then | ||||
|                 locomotive_biter.die() | ||||
|                 local explosion = { | ||||
|                     name = 'massive-explosion', | ||||
|                     position = locomotive_biter.position | ||||
|                 } | ||||
|                 surface.create_entity(explosion) | ||||
|                 locomotive_biter.destroy() | ||||
|                 WPT.set().locomotive_biter = nil | ||||
|             end | ||||
|             return | ||||
| @@ -1879,6 +1917,15 @@ local function on_player_changed_surface(event) | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     local item = player.cursor_stack | ||||
|     if item and item.valid_for_read then | ||||
|         local name = item.name | ||||
|         if clear_items_upon_surface_entry[name] then | ||||
|             player.cursor_stack.clear() | ||||
|         end | ||||
|     end | ||||
|  | ||||
|  | ||||
|     if player.surface.name == 'nauvis' then | ||||
|         local pos = surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(surface), 3, 0, 5) | ||||
|         if pos then | ||||
|   | ||||
| @@ -6,12 +6,12 @@ local Session = require 'utils.datastore.session_data' | ||||
| local Event = require 'utils.event' | ||||
| local Server = require 'utils.server' | ||||
| local MapFuntions = require 'tools.map_functions' | ||||
| local CommonFunctions = require 'maps.planet_prison.mod.common' | ||||
| local CommonFunctions = require 'utils.common' | ||||
| local LayersFunctions = require 'maps.planet_prison.mod.layers' | ||||
| local AIFunctions = require 'maps.planet_prison.mod.ai' | ||||
| local AIFunctions = require 'utils.ai' | ||||
| local Blueprints = require 'maps.planet_prison.mod.bp' | ||||
| local AfkFunctions = require 'maps.planet_prison.mod.afk' | ||||
| local Timers = require 'maps.planet_prison.mod.timers' | ||||
| local Timers = require 'utils.timers' | ||||
| local ClaimsFunctions = require 'maps.planet_prison.mod.claims' | ||||
| local MapConfig = require 'maps.planet_prison.config' | ||||
| local Token = require 'utils.token' | ||||
|   | ||||
| @@ -1,210 +0,0 @@ | ||||
| local CommonFunctions = require 'maps.planet_prison.mod.common' | ||||
|  | ||||
| local Public = {} | ||||
| local remove = table.remove | ||||
|  | ||||
| Public.command = { | ||||
|     --[[ | ||||
|       @param args nil | ||||
|    --]] | ||||
|     noop = 0, | ||||
|     --[[ | ||||
|       @param args nil | ||||
|    --]] | ||||
|     seek_and_destroy_player = 1, | ||||
|     --[[ | ||||
|       @param args = { | ||||
|           agents, // All movable agents | ||||
|           positions, // Table of positions to attack | ||||
|       } | ||||
|    --]] | ||||
|     attack_objects = 2 | ||||
| } | ||||
|  | ||||
| local function _get_direction(src, dest) | ||||
|     local src_x = CommonFunctions.get_axis(src, 'x') | ||||
|     local src_y = CommonFunctions.get_axis(src, 'y') | ||||
|     local dest_x = CommonFunctions.get_axis(dest, 'x') | ||||
|     local dest_y = CommonFunctions.get_axis(dest, 'y') | ||||
|  | ||||
|     local step = { | ||||
|         x = nil, | ||||
|         y = nil | ||||
|     } | ||||
|  | ||||
|     local precision = CommonFunctions.rand_range(1, 10) | ||||
|     if dest_x - precision > src_x then | ||||
|         step.x = 1 | ||||
|     elseif dest_x < src_x - precision then | ||||
|         step.x = -1 | ||||
|     else | ||||
|         step.x = 0 | ||||
|     end | ||||
|  | ||||
|     if dest_y - precision > src_y then | ||||
|         step.y = 1 | ||||
|     elseif dest_y < src_y - precision then | ||||
|         step.y = -1 | ||||
|     else | ||||
|         step.y = 0 | ||||
|     end | ||||
|  | ||||
|     return CommonFunctions.direction_lookup[step.x][step.y] | ||||
| end | ||||
|  | ||||
| local function _move_to(ent, trgt, min_distance) | ||||
|     local state = { | ||||
|         walking = false | ||||
|     } | ||||
|  | ||||
|     local distance = CommonFunctions.get_distance(trgt.position, ent.position) | ||||
|     if min_distance < distance then | ||||
|         local dir = _get_direction(ent.position, trgt.position) | ||||
|         if dir then | ||||
|             state = { | ||||
|                 walking = true, | ||||
|                 direction = dir | ||||
|             } | ||||
|         end | ||||
|     end | ||||
|  | ||||
|     ent.walking_state = state | ||||
|     return state.walking | ||||
| end | ||||
|  | ||||
| local function refill_ammo(ent) | ||||
|     if not ent or not ent.valid then | ||||
|         return | ||||
|     end | ||||
|     local weapon = ent.get_inventory(defines.inventory.character_guns)[ent.selected_gun_index] | ||||
|     if weapon and weapon.valid_for_read then | ||||
|         local selected_ammo = ent.get_inventory(defines.inventory.character_ammo)[ent.selected_gun_index] | ||||
|         if selected_ammo then | ||||
|             if not selected_ammo.valid_for_read then | ||||
|                 if weapon.name == 'shotgun' then | ||||
|                     ent.insert({name = 'shotgun-shell', count = 20}) | ||||
|                 end | ||||
|                 if weapon.name == 'pistol' then | ||||
|                     ent.insert({name = 'firearm-magazine', count = 20}) | ||||
|                 end | ||||
|             end | ||||
|         end | ||||
|     end | ||||
| end | ||||
|  | ||||
| local function _shoot_at(ent, trgt) | ||||
|     ent.shooting_state = { | ||||
|         state = defines.shooting.shooting_enemies, | ||||
|         position = trgt.position | ||||
|     } | ||||
| end | ||||
|  | ||||
| local function _shoot_stop(ent) | ||||
|     ent.shooting_state = { | ||||
|         state = defines.shooting.not_shooting, | ||||
|         position = {0, 0} | ||||
|     } | ||||
| end | ||||
|  | ||||
| local function _do_job_seek_and_destroy_player(surf) | ||||
|     for _, player in pairs(game.players) do | ||||
|         if player and player.valid and player.character then | ||||
|             local search_info = { | ||||
|                 name = 'character', | ||||
|                 position = player.character.position, | ||||
|                 radius = 20, | ||||
|                 force = 'enemy' | ||||
|             } | ||||
|  | ||||
|             local ents = surf.find_entities_filtered(search_info) | ||||
|             if ents and #ents > 0 then | ||||
|                 for _, e in pairs(ents) do | ||||
|                     refill_ammo(e) | ||||
|                     if not _move_to(e, player.character, CommonFunctions.rand_range(5, 10)) then | ||||
|                         _shoot_at(e, player.character) | ||||
|                     else | ||||
|                         _shoot_stop(e) | ||||
|                     end | ||||
|                 end | ||||
|             end | ||||
|         end | ||||
|     end | ||||
| end | ||||
|  | ||||
| local function _do_job_attack_objects(surf, args) | ||||
|     local agents = args.agents | ||||
|     if #agents == 0 then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     local objects = args.objects | ||||
|     local target, closest, agent, query | ||||
|     for i = #agents, 1, -1 do | ||||
|         agent = agents[i] | ||||
|         if not agent.valid then | ||||
|             remove(agents, i) | ||||
|             goto continue | ||||
|         end | ||||
|  | ||||
|         if game.tick % i ~= 0 then | ||||
|             goto continue | ||||
|         end | ||||
|  | ||||
|         query = { | ||||
|             position = agent.position, | ||||
|             radius = 15, | ||||
|             type = { | ||||
|                 'projectile', | ||||
|                 'beam' | ||||
|             }, | ||||
|             force = { | ||||
|                 'enemy', | ||||
|                 'player', | ||||
|                 'neutral' | ||||
|             }, | ||||
|             invert = true | ||||
|         } | ||||
|         closest = surf.find_entities_filtered(query) | ||||
|         if #closest ~= 0 then | ||||
|             target = CommonFunctions.get_closest_neighbour(agent.position, closest) | ||||
|         else | ||||
|             if #objects == 0 then | ||||
|                 _shoot_stop(agent) | ||||
|                 goto continue | ||||
|             end | ||||
|  | ||||
|             target = CommonFunctions.get_closest_neighbour(agent.position, objects) | ||||
|         end | ||||
|  | ||||
|         if target == nil or not target.valid then | ||||
|             goto continue | ||||
|         end | ||||
|  | ||||
|         if not _move_to(agent, target, CommonFunctions.rand_range(5, 15)) then | ||||
|             _shoot_at(agent, target) | ||||
|         else | ||||
|             _shoot_stop(agent) | ||||
|         end | ||||
|  | ||||
|         ::continue:: | ||||
|     end | ||||
| end | ||||
|  | ||||
| --[[ | ||||
| do_job - Perform non-stateful operation on all enemy "character" entities. | ||||
| @param surf - LuaSurface, on which everything is happening. | ||||
| @param command - Command to perform on all non-player controllable characters. | ||||
| --]] | ||||
| Public.do_job = function(surf, command, args) | ||||
|     if args == nil then | ||||
|         args = {} | ||||
|     end | ||||
|  | ||||
|     if command == Public.command.seek_and_destroy_player then | ||||
|         _do_job_seek_and_destroy_player(surf) | ||||
|     elseif command == Public.command.attack_objects then | ||||
|         _do_job_attack_objects(surf, args) | ||||
|     end | ||||
| end | ||||
|  | ||||
| return Public | ||||
							
								
								
									
										346
									
								
								utils/ai.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										346
									
								
								utils/ai.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,346 @@ | ||||
| local Event = require 'utils.event' | ||||
| local CommonFunctions = require 'utils.common' | ||||
| local Token = require 'utils.token' | ||||
| local Task = require 'utils.task' | ||||
| local Global = require 'utils.global' | ||||
|  | ||||
| local this = { | ||||
|     timers = {} | ||||
| } | ||||
|  | ||||
| Global.register( | ||||
|     this, | ||||
|     function(tbl) | ||||
|         this = tbl | ||||
|     end | ||||
| ) | ||||
|  | ||||
| local Public = {} | ||||
| local remove = table.remove | ||||
|  | ||||
| Public.command = { | ||||
|     --[[ | ||||
|       @param args nil | ||||
|    --]] | ||||
|     noop = 0, | ||||
|     --[[ | ||||
|       @param args nil | ||||
|    --]] | ||||
|     seek_and_destroy_player = 1, | ||||
|     --[[ | ||||
|       @param args = { | ||||
|           agents, // All movable agents | ||||
|           positions, // Table of positions to attack | ||||
|       } | ||||
|    --]] | ||||
|     attack_objects = 2 | ||||
| } | ||||
|  | ||||
| local function _get_direction(src, dest) | ||||
|     local src_x = CommonFunctions.get_axis(src, 'x') | ||||
|     local src_y = CommonFunctions.get_axis(src, 'y') | ||||
|     local dest_x = CommonFunctions.get_axis(dest, 'x') | ||||
|     local dest_y = CommonFunctions.get_axis(dest, 'y') | ||||
|  | ||||
|     local step = { | ||||
|         x = nil, | ||||
|         y = nil | ||||
|     } | ||||
|  | ||||
|     local precision = CommonFunctions.rand_range(1, 10) | ||||
|     if dest_x - precision > src_x then | ||||
|         step.x = 1 | ||||
|     elseif dest_x < src_x - precision then | ||||
|         step.x = -1 | ||||
|     else | ||||
|         step.x = 0 | ||||
|     end | ||||
|  | ||||
|     if dest_y - precision > src_y then | ||||
|         step.y = 1 | ||||
|     elseif dest_y < src_y - precision then | ||||
|         step.y = -1 | ||||
|     else | ||||
|         step.y = 0 | ||||
|     end | ||||
|  | ||||
|     return CommonFunctions.direction_lookup[step.x][step.y] | ||||
| end | ||||
|  | ||||
| local function _move_to(ent, trgt, min_distance) | ||||
|     local state = { | ||||
|         walking = false | ||||
|     } | ||||
|  | ||||
|     local distance = CommonFunctions.get_distance(trgt.position, ent.position) | ||||
|     if min_distance < distance then | ||||
|         local dir = _get_direction(ent.position, trgt.position) | ||||
|         if dir then | ||||
|             state = { | ||||
|                 walking = true, | ||||
|                 direction = dir | ||||
|             } | ||||
|         end | ||||
|     end | ||||
|  | ||||
|     ent.walking_state = state | ||||
|     return state.walking | ||||
| end | ||||
|  | ||||
| local function refill_ammo(ent) | ||||
|     if not ent or not ent.valid then | ||||
|         return | ||||
|     end | ||||
|     local weapon = ent.get_inventory(defines.inventory.character_guns)[ent.selected_gun_index] | ||||
|     if weapon and weapon.valid_for_read then | ||||
|         local selected_ammo = ent.get_inventory(defines.inventory.character_ammo)[ent.selected_gun_index] | ||||
|         if selected_ammo then | ||||
|             if not selected_ammo.valid_for_read then | ||||
|                 if weapon.name == 'shotgun' then | ||||
|                     ent.insert({name = 'shotgun-shell', count = 5}) | ||||
|                 end | ||||
|                 if weapon.name == 'pistol' then | ||||
|                     ent.insert({name = 'firearm-magazine', count = 5}) | ||||
|                 end | ||||
|             end | ||||
|         end | ||||
|     end | ||||
| end | ||||
|  | ||||
| local function _shoot_at(ent, trgt) | ||||
|     ent.shooting_state = { | ||||
|         state = defines.shooting.shooting_selected, | ||||
|         position = trgt.position | ||||
|     } | ||||
| end | ||||
|  | ||||
| local function _shoot_stop(ent) | ||||
|     ent.shooting_state = { | ||||
|         state = defines.shooting.not_shooting, | ||||
|         position = {0, 0} | ||||
|     } | ||||
| end | ||||
|  | ||||
| local function set_noise_hostile_hook(ent) | ||||
|     if not ent or not ent.valid then | ||||
|         return | ||||
|     end | ||||
|     local weapon = ent.get_inventory(defines.inventory.character_guns)[ent.selected_gun_index] | ||||
|     if weapon and weapon.valid_for_read then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     if CommonFunctions.rand_range(1, 5) == 1 then | ||||
|         ent.insert({name = 'shotgun', count = 1}) | ||||
|         ent.insert({name = 'shotgun-shell', count = 5}) | ||||
|     end | ||||
| end | ||||
|  | ||||
| local function _do_job_seek_and_destroy_player(data) | ||||
|     local surf = data.surface | ||||
|     local force = data.force | ||||
|     local players = game.connected_players | ||||
|  | ||||
|     if type(surf) == 'number' then | ||||
|         surf = game.surfaces[surf] | ||||
|         if not surf or not surf.valid then | ||||
|             this.timers[game.tick] = nil | ||||
|             return | ||||
|         end | ||||
|     end | ||||
|  | ||||
|     for _, player in pairs(players) do | ||||
|         if player and player.valid and player.character then | ||||
|             local position = data.position or player.character.position | ||||
|             local search_info = { | ||||
|                 name = 'character', | ||||
|                 position = position, | ||||
|                 radius = 30, | ||||
|                 force = force or 'enemy' | ||||
|             } | ||||
|  | ||||
|             local ents = surf.find_entities_filtered(search_info) | ||||
|             if ents and #ents > 0 then | ||||
|                 for _, e in pairs(ents) do | ||||
|                     if e and e.valid then | ||||
|                         if e.player == nil then | ||||
|                             set_noise_hostile_hook(e) | ||||
|                             refill_ammo(e) | ||||
|                             if not _move_to(e, player.character, CommonFunctions.rand_range(5, 10)) then | ||||
|                                 _shoot_at(e, player.character) | ||||
|                             else | ||||
|                                 _shoot_stop(e) | ||||
|                             end | ||||
|                         end | ||||
|                     else | ||||
|                         if data.repeat_function then | ||||
|                             this.timers[data.new] = nil | ||||
|                         end | ||||
|                     end | ||||
|                 end | ||||
|             else | ||||
|                 if data.repeat_function then | ||||
|                     this.timers[data.new] = nil | ||||
|                 end | ||||
|             end | ||||
|         end | ||||
|     end | ||||
| end | ||||
|  | ||||
| local function _do_job_attack_objects(data) | ||||
|     local surf = data.surface | ||||
|     local force = data.force | ||||
|     local position = data.position | ||||
|  | ||||
|     if type(surf) == 'number' then | ||||
|         surf = game.surfaces[surf] | ||||
|         if not surf or not surf.valid then | ||||
|             if data.repeat_function then | ||||
|                 this.timers[data.new] = nil | ||||
|             end | ||||
|             return | ||||
|         end | ||||
|     end | ||||
|  | ||||
|     local search_info = { | ||||
|         name = 'character', | ||||
|         position = position, | ||||
|         radius = 30, | ||||
|         force = force or 'enemy' | ||||
|     } | ||||
|  | ||||
|     local ents = surf.find_entities_filtered(search_info) | ||||
|     if ents and #ents > 0 then | ||||
|         local target, closest, agent, query | ||||
|         for i = #ents, 1, -1 do | ||||
|             agent = ents[i] | ||||
|             if not agent.valid then | ||||
|                 remove(ents, i) | ||||
|                 goto continue | ||||
|             end | ||||
|  | ||||
|             if game.tick % i ~= 0 then | ||||
|                 goto continue | ||||
|             end | ||||
|  | ||||
|             query = { | ||||
|                 position = agent.position, | ||||
|                 radius = 15, | ||||
|                 type = { | ||||
|                     'projectile', | ||||
|                     'beam' | ||||
|                 }, | ||||
|                 force = { | ||||
|                     'enemy', | ||||
|                     'player', | ||||
|                     'neutral' | ||||
|                 }, | ||||
|                 invert = true | ||||
|             } | ||||
|             closest = surf.find_entities_filtered(query) | ||||
|             if #closest ~= 0 then | ||||
|                 target = CommonFunctions.get_closest_neighbour(agent.position, closest) | ||||
|             else | ||||
|                 goto continue | ||||
|             end | ||||
|  | ||||
|             if target == nil or not target.valid then | ||||
|                 goto continue | ||||
|             end | ||||
|  | ||||
|             if not _move_to(agent, target, CommonFunctions.rand_range(5, 15)) then | ||||
|                 _shoot_at(agent, target) | ||||
|             else | ||||
|                 _shoot_stop(agent) | ||||
|             end | ||||
|  | ||||
|             ::continue:: | ||||
|         end | ||||
|     else | ||||
|         if data.repeat_function then | ||||
|             this.timers[data.new] = nil | ||||
|         end | ||||
|     end | ||||
| end | ||||
|  | ||||
| local do_job_token | ||||
|  | ||||
| do_job_token = | ||||
|     Token.register( | ||||
|     function(data) | ||||
|         local surf = data.surface | ||||
|         local command = data.command | ||||
|  | ||||
|         if type(surf) == 'number' then | ||||
|             surf = game.surfaces[surf] | ||||
|             if not surf or not surf.valid then | ||||
|                 this.timers[game.tick] = nil | ||||
|                 return | ||||
|             end | ||||
|         end | ||||
|  | ||||
|         if command == Public.command.seek_and_destroy_player then | ||||
|             _do_job_seek_and_destroy_player(data) | ||||
|         elseif command == Public.command.attack_objects then | ||||
|             _do_job_attack_objects(data) | ||||
|         end | ||||
|     end | ||||
| ) | ||||
|  | ||||
| function Public.add_job_to_task(data) | ||||
|     if not type(data) == 'table' then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     if not data.tick then | ||||
|         return | ||||
|     end | ||||
|  | ||||
|     if not this.timers[game.tick + data.tick] then | ||||
|         this.timers[game.tick + data.tick] = data | ||||
|     end | ||||
| end | ||||
|  | ||||
| --[[ | ||||
| do_job - Perform non-stateful operation on all chosen force "character" entities. | ||||
| @param surf - LuaSurface, on which everything is happening. | ||||
| @param command - Command to perform on all non-player controllable characters. | ||||
| --]] | ||||
| Public.do_job = function(surf, command, args, force) | ||||
|     if args == nil then | ||||
|         args = {} | ||||
|     end | ||||
|  | ||||
|     if command == Public.command.seek_and_destroy_player then | ||||
|         _do_job_seek_and_destroy_player(surf, force) | ||||
|     elseif command == Public.command.attack_objects then | ||||
|         _do_job_attack_objects(surf, args) | ||||
|     end | ||||
| end | ||||
|  | ||||
| Event.add( | ||||
|     defines.events.on_tick, | ||||
|     function() | ||||
|         local tick = game.tick | ||||
|  | ||||
|         if not this.timers[tick] then | ||||
|             return | ||||
|         end | ||||
|         local data = this.timers[tick] | ||||
|         if not data then | ||||
|             return | ||||
|         end | ||||
|  | ||||
|         if data.repeat_function then | ||||
|             this.timers[tick + data.tick] = data | ||||
|             this.timers[tick + data.tick].previous = tick | ||||
|             data.new = tick + data.tick | ||||
|         end | ||||
|  | ||||
|         Task.set_timeout_in_ticks(data.tick, do_job_token, data) | ||||
|  | ||||
|         this.timers[tick] = nil | ||||
|     end | ||||
| ) | ||||
|  | ||||
| return Public | ||||
| @@ -542,10 +542,12 @@ Public.get_closest_neighbour = function(position, objects) | ||||
|     local object, dist | ||||
|     for i = #objects, 1, -1 do | ||||
|         object = objects[i] | ||||
|         dist = Public.get_distance(position, object) | ||||
|         if dist < min_dist then | ||||
|             closest = object | ||||
|             min_dist = dist | ||||
|         if object and not object.player then | ||||
|             dist = Public.get_distance(position, object) | ||||
|             if dist < min_dist then | ||||
|                 closest = object | ||||
|                 min_dist = dist | ||||
|             end | ||||
|         end | ||||
|     end | ||||
| 
 | ||||
		Reference in New Issue
	
	Block a user