1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-02-09 13:37:02 +02:00
2021-03-27 14:47:47 +01:00

211 lines
5.4 KiB
Lua

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