-- SE sim: tesla_gun
local surface = game.surfaces.nauvis
local logo = surface.find_entities_filtered{name = "se-space-exploration-logo-shattered-15tiles", limit = 1}[1]
game.camera_position = {logo.position.x, logo.position.y+10.50}
game.camera_zoom = 1
game.tick_paused = false
surface.daytime = 0

game.forces.enemy.evolution_factor = 0.75

local character = surface.create_entity{name = "character", position = {-33, 81}, force = "player"}
character.insert{name = "power-armor-mk2"}
character.insert{name = "se-tesla-gun"}
character.insert{name = "se-tesla-ammo", count = 100}

local grid = character.get_inventory(defines.inventory.character_armor)[1].grid
grid.put{name = "exoskeleton-equipment"}
grid.put{name = "exoskeleton-equipment"}
for _ = 1, 10 do
  grid.put{name = "energy-shield-mk2-equipment"}
  grid.put{name = "battery-mk2-equipment"}
  grid.put{name = "battery-mk2-equipment"}
end

for _, equipment in pairs(grid.equipment) do
  if equipment.max_shield > 0 then equipment.shield = equipment.max_shield end
  equipment.energy = equipment.max_energy
end

points =
{
  {-15, -21},
  {15, -9},
  {14, -3},
  {93, 28},
  {93, 36},
  {123, 36},
}

local distance = function(p_1, p_2)
  local dx = (p_1[1] or p_1.x) - (p_2[1] or p_2.x)
  local dy = (p_1[2] or p_1.y) - (p_2[2] or p_2.y)
  return ((dx * dx) + (dy * dy)) ^ 0.5
end

local direction = function(p_1, p_2)

  local d_x = (p_2[1] or p_2.x) - (p_1[1] or p_1.x)
  local d_y = (p_2[2] or p_2.y) - (p_1[2] or p_1.y)
  local angle = math.atan2(d_y, d_x)

  local orientation =  (angle / (2 * math.pi)) - 0.25
  if orientation < 0 then orientation = orientation + 1 end

  local direction = math.floor((orientation * 8) + 0.5)
  if direction == 8 then direction = 0 end
  return direction
end

local get_shoot_target = function(entity)
  local enemies = surface.find_entities_filtered{force = "enemy", type = {"unit-spawner", "turret", "unit"}, position = entity.position, radius = 15}
  local closest = surface.get_closest(entity.position, enemies)
  return closest
end

script.on_nth_tick(1, function()
  if not character.valid then return end
  local k, destination = next(points)
  if not k then return end
  local target = {destination[1], destination[2]}
  if distance(character.position, target) < 1 then
    points[k] = nil
    return
  end

  if game.tick % 17 == 0 then
    local walking_direction = direction(target, character.position)
    character.walking_state = {walking = true, direction = walking_direction}
  end

  if not (shoot_target and shoot_target.valid) or game.tick % 123 == 0 then
    shoot_target = get_shoot_target(character)
  end

  if shoot_target then
    character.shooting_state = {state = defines.shooting.shooting_enemies, position = shoot_target.position}
  else
    character.shooting_state = {state = defines.shooting.not_shooting}
  end

end)
