1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-01-10 00:43:27 +02:00
ComfyFactorio/maps/biter_battles_v2/mirror_terrain.lua
MewMew 913d42d6d8 Update
added tooltip for current biter health and damage bonus
moved science gui button, to prevent cut off threat values for spectators
reverted to old biter health boost method
spawners and worms gain health boost too
reduced trees in spawn area 
increased tree generation randomness overall
bigger biter area, less worms
border to biter lands tweaked
biter area starts at ~y512
side area worm turrets start to appear at the same distance as the biter area starts
chunks that are discovered north are mirrored to south as well
biters will try to attack from different angles
removed some console spam
2020-04-13 06:31:39 +02:00

297 lines
10 KiB
Lua

-- Mirrored Terrain for Biter Battles -- by MewMew and Serennie
local Public = {}
local direction_translation = {
[0] = 4,
[1] = 5,
[2] = 6,
[3] = 7,
[4] = 0,
[5] = 1,
[6] = 2,
[7] = 3
}
local cliff_orientation_translation = {
["east-to-none"] = "west-to-none",
["east-to-north"] = "west-to-south",
["east-to-south"] = "west-to-north",
["east-to-west"] = "west-to-east",
["north-to-east"] = "south-to-west",
["north-to-none"] = "south-to-none",
["north-to-south"] = "south-to-north",
["north-to-west"] = "south-to-east",
["south-to-east"] = "north-to-west",
["south-to-none"] = "north-to-none",
["south-to-north"] = "north-to-south",
["south-to-west"] = "north-to-east",
["west-to-east"] = "east-to-west",
["west-to-none"] = "east-to-none",
["west-to-north"] = "east-to-south",
["west-to-south"] = "east-to-north",
["none-to-east"] = "none-to-west",
["none-to-north"] = "none-to-south",
["none-to-south"] = "none-to-north",
["none-to-west"] = "none-to-east"
}
local entity_copy_functions = {
["tree"] = function(surface, entity, mirror_position)
if not surface.can_place_entity({name = entity.name, position = mirror_position}) then return end
entity.clone({position = mirror_position, surface = surface, force = "neutral"})
end,
["simple-entity"] = function(surface, entity, mirror_position)
local mirror_entity = {name = entity.name, position = mirror_position, direction = direction_translation[entity.direction]}
if not surface.can_place_entity(mirror_entity) then return end
local mirror_entity = surface.create_entity(mirror_entity)
mirror_entity.graphics_variation = entity.graphics_variation
end,
["cliff"] = function(surface, entity, mirror_position)
local mirror_entity = {name = entity.name, position = mirror_position, cliff_orientation = cliff_orientation_translation[entity.cliff_orientation]}
if not surface.can_place_entity(mirror_entity) then return end
surface.create_entity(mirror_entity)
return
end,
["resource"] = function(surface, entity, mirror_position)
surface.create_entity({name = entity.name, position = mirror_position, amount = entity.amount})
end,
["corpse"] = function(surface, entity, mirror_position)
if game.tick > 900 then return end
surface.create_entity({name = entity.name, position = mirror_position})
end,
["unit-spawner"] = function(surface, entity, mirror_position)
local mirror_entity = {name = entity.name, position = mirror_position, direction = direction_translation[entity.direction], force = "south_biters"}
if not surface.can_place_entity(mirror_entity) then return end
table.insert(global.unit_spawners.south_biters, surface.create_entity(mirror_entity))
end,
["turret"] = function(surface, entity, mirror_position)
local mirror_entity = {name = entity.name, position = mirror_position, direction = direction_translation[entity.direction], force = "south_biters"}
if not surface.can_place_entity(mirror_entity) then return end
surface.create_entity(mirror_entity)
end,
["rocket-silo"] = function(surface, entity, mirror_position)
if game.tick > 900 then return end
if surface.count_entities_filtered({name = "rocket-silo", area = {{mirror_position.x - 8, mirror_position.y - 8},{mirror_position.x + 8, mirror_position.y + 8}}}) > 0 then return end
global.rocket_silo["south"] = surface.create_entity({name = entity.name, position = mirror_position, direction = direction_translation[entity.direction], force = "south"})
global.rocket_silo["south"].minable = false
end,
["ammo-turret"] = function(surface, entity, mirror_position)
if game.tick > 900 then return end
if not surface.can_place_entity({name = entity.name, position = mirror_position, force = "south"}) then return end
entity.clone({position = mirror_position, surface = surface, force="south"})
end,
["wall"] = function(surface, entity, mirror_position)
if game.tick > 900 then return end
entity.clone({position = mirror_position, surface = surface, force="south"})
end,
["container"] = function(surface, entity, mirror_position)
if game.tick > 900 then return end
entity.clone({position = mirror_position, surface = surface, force="south"})
end,
["fish"] = function(surface, entity, mirror_position)
local mirror_entity = {name = entity.name, position = mirror_position, direction = direction_translation[entity.direction]}
if not surface.can_place_entity(mirror_entity) then return end
local e = surface.create_entity(mirror_entity)
end,
}
local function process_entity(surface, entity)
if not entity.valid then return end
if not entity_copy_functions[entity.type] then return end
local mirror_position = {x = entity.position.x * -1, y = entity.position.y * -1}
entity_copy_functions[entity.type](surface, entity, mirror_position)
end
local function mirror_tiles(surface, source_area)
mirrored = {}
local i = 0
for x = source_area.left_top.x, source_area.left_top.x+31 do
for y = source_area.left_top.y, source_area.left_top.y+31 do
local tile = surface.get_tile(x, y)
mirrored[i] = {name = tile.name, position = {-x, -y - 1}}
i = i + 1
end
end
surface.set_tiles(mirrored, true)
end
local function clear_chunk(surface, area)
surface.destroy_decoratives{area=area}
if area.left_top.y > 32 or area.left_top.x > 32 or area.left_top.x < -32 then
for _, e in pairs(surface.find_entities_filtered({area = area})) do
if e.valid then
e.destroy()
end
end
else
for _, e in pairs(surface.find_entities_filtered({area = area})) do
if e.valid then
if e.name ~= "character" then
e.destroy()
end
end
end
end
end
local function mirror_chunk(surface, chunk)
--local x = chunk.x * -32 + 32
--local y = chunk.y * -32 + 32
--clear_chunk(surface, {left_top = {x = x, y = y}, right_bottom = {x = x + 32, y = y + 32}})
local chunk_area = {left_top = {x = chunk.x * 32, y = chunk.y * 32}, right_bottom = {x = chunk.x * 32 + 32, y = chunk.y * 32 + 32}}
if not surface.is_chunk_generated(chunk) then
surface.request_to_generate_chunks({x = chunk_area.left_top.x - 16, y = chunk_area.left_top.y - 16}, 1)
surface.force_generate_chunk_requests()
end
for _, tile in pairs(surface.find_tiles_filtered({area = chunk_area})) do
surface.set_tiles({{name = tile.name, position = {x = tile.position.x * -1, y = (tile.position.y * -1) - 1}}}, true)
end
for _, entity in pairs(surface.find_entities_filtered({area = chunk_area})) do
process_entity(surface, entity)
end
for _, decorative in pairs(surface.find_decoratives_filtered{area=chunk_area}) do
surface.create_decoratives{
check_collision=false,
decoratives={{name = decorative.decorative.name, position = {x = decorative.position.x * -1, y = (decorative.position.y * -1) - 1}, amount = decorative.amount}}
}
end
end
local function is_chunk_already_mirrored(chunk)
local index = chunk[1] .. "_" .. chunk[2]
if not global.chunks_mirrored[index] then global.chunks_mirrored[index] = true return false end
return true
end
local function add_work(work)
if not global.ctp then global.ctp = { continue = 1, last = 0 } end
local idx = global.ctp.last + 1
global.ctp[idx] = work
global.ctp.last = idx
end
function Public.add_chunks(event)
local surface = event.surface
if surface.name ~= "biter_battles" then return end
if event.area.left_top.y < 0 then
if game.tick == 0 then return end
local x = event.area.left_top.x / 32
local y = event.area.left_top.y / 32
if is_chunk_already_mirrored({x, y}) then return end
add_work({x = x, y = y, state = 1})
return
end
surface.destroy_decoratives{ area = event.area }
-- Destroy biters here before they get active and attack other biters;
-- prevents threat decrease
for _, e in pairs(surface.find_entities_filtered{ area = event.area, force = "enemy" }) do
if e.valid then e.destroy() end
end
local x = (((event.area.left_top.x + 16) * -1) - 16) / 32
local y = (((event.area.left_top.y + 16) * -1) - 16) / 32
if is_chunk_already_mirrored({x, y}) then return end
add_work({x = x, y = y, state = 1})
end
function Public.ticking_work()
if not global.ctp then return end
local work = global.mws or 512 -- define the number of work per tick here (for copies, creations, deletions)
-- 136.5333 is the number of work needed to finish 4*(32*32) operations over 30 ticks (spreading a chunk copy over 30 ticks)
local w = 0
local i = global.ctp.continue
local c = global.ctp[i]
if not c then return end
local state = c.state
local d = c.data
local area = {
left_top = {x = c.x * 32, y = c.y * 32},
right_bottom = {x = c.x * 32 + 32, y = c.y * 32 + 32}
}
local inverted_area = {
left_top = { -area.right_bottom.x, -area.right_bottom.y },
right_bottom = { -area.left_top.x, -area.left_top.y }
}
local surface = game.surfaces["biter_battles"]
if not surface.is_chunk_generated(c) then
--game.print("Chunk not generated yet, requesting..")
surface.request_to_generate_chunks({x = area.left_top.x + 16, y = area.left_top.y + 16}, 0)
-- requeue
add_work(c)
global.ctp.continue = i+1
global.ctp[i] = nil
return
end
local tasks = {
[1] = {
name = "Clearing entities",
list = function () return surface.find_entities_filtered({area = inverted_area, name = "character", invert = true}) end,
action = function (e) e.destroy() end
},
[2] = {},
[3] = {
name = "Entity copy",
list = function () return surface.find_entities_filtered({area = area}) end,
action = function (entity) process_entity(surface, entity) end
},
[4] = {
name = "Decorative copy",
list = function () return surface.find_decoratives_filtered{area = area} end,
action = function (decorative)
surface.create_decoratives{
check_collision = false,
decoratives = {{
name = decorative.decorative.name,
position = {x = decorative.position.x * -1, y = (decorative.position.y * -1) - 1},
amount = decorative.amount
}}
}
end
}
}
if c.state == 2 then
mirror_tiles(surface, area)
c.state = c.state + 1
c.data = nil
else
local task = tasks[c.state]
-- game.print(task.name)
d = d or task.list()
local last_idx = nil
for k, v in pairs(d) do
task.action(v)
d[k] = nil
last_idx = k
w = w + 1
if w > work then break end
end
local next_idx, _ = next(d, last_idx)
if next_idx == nil then
c.state = c.state + 1
c.data = nil
else
c.data = d
end
end
if c.state == 5 then
-- game.print("Finished processing chunk "..c.x..","..c.y)
global.ctp.continue = i+1
global.ctp[i] = nil
else
global.ctp.continue = i
end
end
return Public