1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-01-10 00:43:27 +02:00
ComfyFactorio/maps/biter_hatchery/main.lua

447 lines
16 KiB
Lua
Raw Normal View History

2020-01-19 11:31:16 +02:00
require "modules.no_turrets"
2020-09-02 05:18:26 +02:00
require 'modules.no_acid_puddles'
2019-11-04 20:57:02 +02:00
local Tabs = require 'comfy_panel.main'
2020-05-03 15:41:58 +02:00
local Map_score = require "comfy_panel.map_score"
2019-11-03 18:46:18 +02:00
local unit_raffle = require "maps.biter_hatchery.raffle_tables"
2019-11-03 19:57:36 +02:00
local Terrain = require "maps.biter_hatchery.terrain"
2019-11-04 02:24:09 +02:00
local Gui = require "maps.biter_hatchery.gui"
2019-11-04 15:55:58 +02:00
require "maps.biter_hatchery.share_chat"
2019-11-04 13:48:08 +02:00
local Team = require "maps.biter_hatchery.team"
2020-09-02 07:52:19 +02:00
local Unit_health_booster = require "modules.biter_health_booster"
2019-11-03 19:57:36 +02:00
local Reset = require "functions.soft_reset"
2019-11-03 20:34:36 +02:00
local Map = require "modules.map_info"
2019-11-03 18:46:18 +02:00
local math_random = math.random
2019-11-03 19:57:36 +02:00
local Public = {}
2019-11-06 13:36:31 +02:00
local map_gen_settings = {
["seed"] = 1,
["water"] = 1,
["starting_area"] = 1,
["cliff_settings"] = {cliff_elevation_interval = 0, cliff_elevation_0 = 0},
["default_enable_all_autoplace_controls"] = false,
["autoplace_settings"] = {
["entity"] = {treat_missing_as_default = false},
["tile"] = {treat_missing_as_default = false},
["decorative"] = {treat_missing_as_default = false},
},
}
2020-01-19 11:31:16 +02:00
local m = 2
local health_boost_food_values = {
["automation-science-pack"] = 0.000001 * m,
2019-11-20 20:26:34 +02:00
["logistic-science-pack"] = 0.000003 * m,
["military-science-pack"] = 0.00000822 * m,
["chemical-science-pack"] = 0.00002271 * m,
["production-science-pack"] = 0.00009786 * m,
["utility-science-pack"] = 0.00010634 * m,
["space-science-pack"] = 0.00041828 * m,
}
2020-09-02 07:52:19 +02:00
local worm_turret_spawn_radius = 25
local worm_turret_vectors = {}
worm_turret_vectors.west = {}
for x = 0, worm_turret_spawn_radius, 1 do
for y = worm_turret_spawn_radius * -1, worm_turret_spawn_radius, 1 do
2019-11-04 15:55:58 +02:00
local d = math.sqrt(x ^ 2 + y ^ 2)
if d <= worm_turret_spawn_radius and d > 3 then table.insert(worm_turret_vectors.west, {x, y}) end
end
end
worm_turret_vectors.east = {}
for x = worm_turret_spawn_radius * -1, 0, 1 do
for y = worm_turret_spawn_radius * -1, worm_turret_spawn_radius, 1 do
2019-11-04 15:55:58 +02:00
local d = math.sqrt(x ^ 2 + y ^ 2)
if d <= worm_turret_spawn_radius and d > 3 then table.insert(worm_turret_vectors.east, {x, y}) end
end
end
2019-11-03 19:57:36 +02:00
function Public.reset_map()
2019-11-06 13:36:31 +02:00
Terrain.create_mirror_surface()
2019-11-03 19:57:36 +02:00
if not global.active_surface_index then
2019-11-03 21:29:19 +02:00
global.active_surface_index = game.create_surface("biter_hatchery", map_gen_settings).index
2019-11-03 19:57:36 +02:00
else
2019-11-04 13:48:08 +02:00
global.active_surface_index = Reset.soft_reset_map(game.surfaces[global.active_surface_index], map_gen_settings, Team.starting_items).index
2019-11-03 19:57:36 +02:00
end
2019-11-03 21:29:19 +02:00
local surface = game.surfaces[global.active_surface_index]
2019-11-06 13:36:31 +02:00
2019-11-06 14:02:26 +02:00
surface.request_to_generate_chunks({0,0}, 8)
2019-11-03 21:29:19 +02:00
surface.force_generate_chunk_requests()
2019-11-06 14:02:26 +02:00
game.forces.spectator.set_spawn_position({0, -128}, surface)
game.forces.west.set_spawn_position({-210, 0}, surface)
game.forces.east.set_spawn_position({210, 0}, surface)
2019-11-03 21:09:51 +02:00
2019-11-04 13:48:08 +02:00
Team.set_force_attributes()
Team.assign_random_force_to_active_players()
2019-11-03 21:29:19 +02:00
for _, player in pairs(game.connected_players) do
2019-11-04 13:48:08 +02:00
Team.teleport_player_to_active_surface(player)
end
for _, player in pairs(game.forces.spectator.connected_players) do
player.character.destroy()
Team.set_player_to_spectator(player)
end
for _, player in pairs(game.forces.spectator.players) do
2019-11-04 13:48:08 +02:00
Gui.rejoin_question(player)
2019-11-03 21:29:19 +02:00
end
2019-11-03 19:57:36 +02:00
end
2019-11-03 18:46:18 +02:00
local function spawn_worm_turret(surface, force_name, food_item)
local r_max = surface.count_entities_filtered({type = "turret", force = force_name}) + 1
2020-09-02 07:52:19 +02:00
if r_max > 256 then return end
if math_random(1, r_max) ~= 1 then return end
local vectors = worm_turret_vectors[force_name]
local vector = vectors[math_random(1, #vectors)]
local worm = "small-worm-turret"
2019-11-04 15:55:58 +02:00
local position = {x = global.map_forces[force_name].hatchery.position.x, y = global.map_forces[force_name].hatchery.position.y}
position.x = position.x + vector[1]
position.y = position.y + vector[2]
position = surface.find_non_colliding_position("biter-spawner", position, 16, 1)
if not position then return end
surface.create_entity({name = worm, position = position, force = force_name})
surface.create_entity({name = "blood-explosion-huge", position = position})
2020-09-02 07:52:19 +02:00
surface.create_decoratives{check_collision = false, decoratives = {{name = "enemy-decal", position = position, amount = 1}}}
end
2019-11-03 18:46:18 +02:00
local function spawn_units(belt, food_item, removed_item_count)
local count_per_flask = unit_raffle[food_item][2]
2019-11-03 18:46:18 +02:00
local raffle = unit_raffle[food_item][1]
local team = global.map_forces[belt.force.name]
team.unit_health_boost = team.unit_health_boost + (health_boost_food_values[food_item] * removed_item_count)
for _ = 1, removed_item_count, 1 do
for _ = 1, count_per_flask, 1 do
local name = raffle[math_random(1, #raffle)]
local unit = belt.surface.create_entity({name = name, position = belt.position, force = belt.force})
unit.ai_settings.allow_destroy_when_commands_fail = false
unit.ai_settings.allow_try_return_to_spawner = false
Unit_health_booster.add_unit(unit, team.unit_health_boost)
2019-11-11 14:06:02 +02:00
team.units[unit.unit_number] = unit
team.unit_count = team.unit_count + 1
end
2019-11-03 18:46:18 +02:00
end
if math_random(1, 8) == 1 then spawn_worm_turret(belt.surface, belt.force.name, food_item) end
2019-11-03 18:46:18 +02:00
end
local function get_belts(spawner)
local belts = spawner.surface.find_entities_filtered({
type = "transport-belt",
area = {{spawner.position.x - 5, spawner.position.y - 3},{spawner.position.x + 4, spawner.position.y + 3}},
force = spawner.force,
})
return belts
end
2019-11-04 04:36:47 +02:00
local nom_msg = {"munch", "munch", "yum", "nom"}
2019-11-03 21:48:17 +02:00
local function feed_floaty_text(entity)
2019-11-04 17:43:26 +02:00
entity.surface.create_entity({name = "flying-text", position = entity.position, text = nom_msg[math_random(1, 4)], color = {math_random(50, 100), 0, 255}})
2019-11-03 21:48:17 +02:00
local position = {x = entity.position.x - 0.75, y = entity.position.y - 1}
local b = 1.35
for a = 1, math_random(0, 2), 1 do
local p = {(position.x + 0.4) + (b * -1 + math_random(0, b * 20) * 0.1), position.y + (b * -1 + math_random(0, b * 20) * 0.1)}
entity.surface.create_entity({name = "flying-text", position = p, text = "", color = {math_random(150, 255), 0, 255}})
end
end
2019-11-03 18:46:18 +02:00
local function eat_food_from_belt(belt)
for i = 1, 2, 1 do
local line = belt.get_transport_line(i)
for food_item, raffle in pairs(unit_raffle) do
if global.map_forces[belt.force.name].unit_count > global.map_forces[belt.force.name].max_unit_count then return end
2019-11-04 15:55:58 +02:00
local removed_item_count = line.remove_item({name = food_item, count = 8})
2019-11-03 18:46:18 +02:00
if removed_item_count > 0 then
2019-11-03 21:48:17 +02:00
feed_floaty_text(belt)
2019-11-03 18:46:18 +02:00
spawn_units(belt, food_item, removed_item_count)
end
end
end
end
local function nom()
2019-11-03 19:57:36 +02:00
local surface = game.surfaces[global.active_surface_index]
2019-11-03 18:46:18 +02:00
for key, force in pairs(global.map_forces) do
2019-11-06 13:36:31 +02:00
if not force.hatchery then return end
force.hatchery.health = force.hatchery.health + 1
2019-11-03 18:46:18 +02:00
local belts = get_belts(force.hatchery)
for _, belt in pairs(belts) do
eat_food_from_belt(belt)
end
end
for _, player in pairs(game.connected_players) do Gui.update_health_boost_buttons(player) end
2019-11-03 18:46:18 +02:00
end
2019-11-11 14:06:02 +02:00
local function get_units(force_name)
local units = {}
2019-11-24 01:09:45 +02:00
local count = 1
2019-11-11 14:06:02 +02:00
for _, unit in pairs(global.map_forces[force_name].units) do
if not unit.unit_group then
2019-11-24 01:09:45 +02:00
if math_random(1, 3) ~= 1 then
units[count] = unit
count = count + 1
end
2019-11-11 14:06:02 +02:00
end
end
return units
end
local function alert_bubble(force_name, entity)
if force_name == "west" then force_name = "east" else force_name = "west" end
for _, player in pairs(game.forces[force_name].connected_players) do
player.add_custom_alert(entity, {type = "item", name = "tank"}, "Incoming enemy units!", true)
end
end
2019-11-03 19:57:36 +02:00
local function send_unit_groups()
local surface = game.surfaces[global.active_surface_index]
2019-11-11 14:06:02 +02:00
for key, force in pairs(global.map_forces) do
local units = get_units(key)
2019-11-03 19:57:36 +02:00
if #units > 0 then
2019-11-11 14:06:02 +02:00
alert_bubble(key, units[1])
2019-11-04 15:55:58 +02:00
local vectors = worm_turret_vectors[key]
local vector = vectors[math_random(1, #vectors)]
local position = {x = force.hatchery.position.x + vector[1], y = force.hatchery.position.y + vector[2]}
local unit_group = surface.create_unit_group({position = position, force = key})
2019-11-03 19:57:36 +02:00
for _, unit in pairs(units) do unit_group.add_member(unit) end
2019-11-04 17:43:26 +02:00
if not force.target then return end
if not force.target.valid then return end
2019-11-03 19:57:36 +02:00
unit_group.set_command({
type = defines.command.compound,
structure_type = defines.compound_command.return_last,
commands = {
{
type = defines.command.attack_area,
destination = {x = force.target.position.x, y = force.target.position.y},
2019-11-04 17:43:26 +02:00
radius = 6,
distraction = defines.distraction.by_anything
2019-11-03 19:57:36 +02:00
},
{
type = defines.command.attack,
target = force.target,
distraction = defines.distraction.by_enemy,
},
}
})
2019-11-24 01:09:45 +02:00
unit_group.start_moving()
2019-11-03 19:57:36 +02:00
end
end
end
2019-11-03 20:34:36 +02:00
local border_teleport = {
2019-11-06 14:02:26 +02:00
["east"] = 1,
["west"] = -1,
2019-11-03 20:34:36 +02:00
}
local function on_player_changed_position(event)
local player = game.players[event.player_index]
2019-11-04 02:46:23 +02:00
if not player.character then return end
if not player.character.valid then return end
2019-11-06 14:02:26 +02:00
if player.position.x > -4 and player.position.x < 4 then
2019-11-04 13:48:08 +02:00
if not border_teleport[player.force.name] then return end
2019-11-03 20:34:36 +02:00
if player.character.driving then player.character.driving = false end
player.teleport({player.position.x + border_teleport[player.force.name], player.position.y}, game.surfaces[global.active_surface_index])
end
end
2019-11-03 19:57:36 +02:00
local function on_entity_died(event)
local entity = event.entity
if not entity.valid then return end
if global.game_reset_tick then return end
if entity.type == "unit" then
local team = global.map_forces[entity.force.name]
team.unit_count = team.unit_count - 1
2019-11-11 14:06:02 +02:00
team.units[entity.unit_number] = nil
return
end
if entity.type ~= "unit-spawner" then return end
2019-11-03 21:29:19 +02:00
if entity.force.name == "east" then
2019-11-03 19:57:36 +02:00
game.print("East lost their Hatchery.", {100, 100, 100})
2019-11-11 14:14:29 +02:00
game.forces.east.play_sound{path="utility/game_lost", volume_modifier=0.85}
game.print(">>>> WEST TEAM HAS WON THE GAME!!! <<<<", {250, 120, 0})
game.forces.west.play_sound{path="utility/game_won", volume_modifier=0.85}
for _, player in pairs(game.forces.west.connected_players) do
2019-11-06 14:54:34 +02:00
if global.map_forces.east.player_count > 0 then
2019-11-06 13:36:31 +02:00
Map_score.set_score(player, Map_score.get_score(player) + 1)
2019-11-06 14:54:34 +02:00
end
end
2019-11-03 19:57:36 +02:00
else
game.print("West lost their Hatchery.", {100, 100, 100})
2019-11-11 14:14:29 +02:00
game.forces.west.play_sound{path="utility/game_lost", volume_modifier=0.85}
game.print(">>>> EAST TEAM HAS WON THE GAME!!! <<<<", {250, 120, 0})
game.forces.east.play_sound{path="utility/game_won", volume_modifier=0.85}
for _, player in pairs(game.forces.east.connected_players) do
2019-11-06 14:54:34 +02:00
if global.map_forces.west.player_count > 0 then
2019-11-06 13:36:31 +02:00
Map_score.set_score(player, Map_score.get_score(player) + 1)
2019-11-06 14:54:34 +02:00
end
end
2019-11-03 19:57:36 +02:00
end
2019-11-11 14:14:29 +02:00
2020-09-02 05:18:26 +02:00
game.print("Map will restart in 2 minutes.", {150, 150, 150})
2019-11-04 03:21:57 +02:00
2019-11-11 14:14:29 +02:00
game.forces.spectator.play_sound{path="utility/game_won", volume_modifier=0.85}
2020-09-02 05:18:26 +02:00
global.game_reset_tick = game.tick + 7200
2019-11-06 13:36:31 +02:00
game.delete_surface("mirror_terrain")
2019-11-03 19:57:36 +02:00
for _, player in pairs(game.connected_players) do
2019-11-03 21:29:19 +02:00
for _, child in pairs(player.gui.left.children) do child.destroy() end
2019-11-04 20:57:02 +02:00
Tabs.comfy_panel_call_tab(player, "Map Scores")
2019-11-03 21:29:19 +02:00
end
2019-11-03 19:57:36 +02:00
end
2019-11-03 18:46:18 +02:00
local function on_player_joined_game(event)
local player = game.players[event.player_index]
2019-11-03 19:57:36 +02:00
local surface = game.surfaces[global.active_surface_index]
Gui.unit_health_buttons(player)
Gui.spectate_button(player)
Gui.update_health_boost_buttons(player)
2019-11-04 02:24:09 +02:00
2019-11-04 13:48:08 +02:00
if player.surface.index ~= global.active_surface_index then
if player.force.name == "spectator" then
Team.set_player_to_spectator(player)
Team.teleport_player_to_active_surface(player)
return
end
2019-11-04 13:48:08 +02:00
Team.assign_force_to_player(player)
Team.teleport_player_to_active_surface(player)
Team.put_player_into_random_team(player)
2019-11-03 19:57:36 +02:00
end
2019-11-03 18:46:18 +02:00
end
2019-11-04 04:53:23 +02:00
local function tick()
local game_tick = game.tick
if game_tick % 240 == 0 then
2019-11-06 14:02:26 +02:00
local surface = game.surfaces[global.active_surface_index]
local west = game.forces.west
local east = game.forces.east
local area = {{-320, -161}, {319, 160}}
west.chart(surface, area)
east.chart(surface, area)
local r = 64
for _, player in pairs(west.connected_players) do east.chart(surface, {{player.position.x - r, player.position.y - r}, {player.position.x + r, player.position.y + r}}) end
for _, player in pairs(east.connected_players) do west.chart(surface, {{player.position.x - r, player.position.y - r}, {player.position.x + r, player.position.y + r}}) end
end
2019-11-26 02:31:00 +02:00
if game_tick % 1200 == 0 then send_unit_groups() end
2019-11-03 19:57:36 +02:00
if global.game_reset_tick then
2019-11-04 04:53:23 +02:00
if global.game_reset_tick < game_tick then
2019-11-03 19:57:36 +02:00
global.game_reset_tick = nil
Public.reset_map()
2019-11-06 13:36:31 +02:00
end
2019-11-03 19:57:36 +02:00
return
2019-11-04 13:48:08 +02:00
end
nom()
2019-11-03 18:46:18 +02:00
end
2019-11-03 21:09:51 +02:00
--Construction Robot Restriction
local robot_build_restriction = {
["east"] = function(x)
if x < 0 then return true end
end,
["west"] = function(x)
if x > 0 then return true end
end
}
local function on_robot_built_entity(event)
if not robot_build_restriction[event.robot.force.name] then return end
if not robot_build_restriction[event.robot.force.name](event.created_entity.position.x) then return end
local inventory = event.robot.get_inventory(defines.inventory.robot_cargo)
inventory.insert({name = event.created_entity.name, count = 1})
event.robot.surface.create_entity({name = "explosion", position = event.created_entity.position})
game.print("Team " .. event.robot.force.name .. "'s construction drone had an accident.", {r = 200, g = 50, b = 100})
event.created_entity.destroy()
end
2019-11-03 21:48:17 +02:00
local function on_entity_damaged(event)
local entity = event.entity
if not entity.valid then return end
if entity.type ~= "unit-spawner" then return end
local cause = event.cause
if cause then
if cause.valid then
2019-11-06 13:36:31 +02:00
if cause.type == "unit" then
2020-09-02 07:52:19 +02:00
if math_random(1, 16) == 1 then return end
2019-11-06 13:36:31 +02:00
end
2019-11-03 21:48:17 +02:00
end
end
entity.health = entity.health + event.final_damage_amount
end
2020-09-02 05:18:26 +02:00
local function on_player_used_spider_remote(event)
local vehicle = event.vehicle
local position = event.position
local success = event.success
if not success then return end
if vehicle.force.name == "west" then
if position.x < -3 then return end
else
if position.x > 3 then return end
end
vehicle.autopilot_destination = nil
end
2019-11-03 18:46:18 +02:00
local function on_init()
2020-09-02 07:52:19 +02:00
--Disable Nauvis
local surface = game.surfaces[1]
local map_gen_settings = surface.map_gen_settings
map_gen_settings.height = 3
map_gen_settings.width = 3
surface.map_gen_settings = map_gen_settings
for chunk in surface.get_chunks() do
surface.delete_chunk({chunk.x, chunk.y})
end
game.permissions.get_group("Default").set_allows_action(defines.input_action.open_blueprint_library_gui, false)
game.permissions.get_group("Default").set_allows_action(defines.input_action.import_blueprint_string, false)
2019-11-04 01:20:52 +02:00
game.difficulty_settings.technology_price_multiplier = 0.5
2019-11-03 19:57:36 +02:00
game.map_settings.enemy_evolution.destroy_factor = 0
game.map_settings.enemy_evolution.pollution_factor = 0
game.map_settings.enemy_evolution.time_factor = 0
game.map_settings.enemy_expansion.enabled = false
game.map_settings.pollution.enabled = false
2019-11-03 18:46:18 +02:00
global.map_forces = {
["west"] = {},
["east"] = {},
}
2019-11-03 20:34:36 +02:00
local T = Map.Pop_info()
T.main_caption = "Biter Hatchery"
2020-01-19 11:31:16 +02:00
T.sub_caption = "*nibble nibble nom nom*"
2019-11-03 20:34:36 +02:00
T.text = table.concat({
"Defeat the enemy teams nest.\n",
"Feed your hatchery science flasks to breed biters!\n",
2019-11-04 03:21:57 +02:00
"They will soon after swarm to the opposing teams nest!\n",
2019-11-03 20:34:36 +02:00
"\n",
"Lay transport belts to your hatchery and they will happily nom the science juice off the conveyor.\n",
2019-11-03 20:34:36 +02:00
"Higher tier flasks will breed stronger biters!\n",
"\n",
2020-01-19 11:31:16 +02:00
"Player turrets are disabled.\n",
"Feeding may spawn friendly worm turrets.\n",
2019-11-03 21:09:51 +02:00
"The center river may not be crossed.\n",
"Construction robots may not build over the river.\n",
2019-11-03 20:34:36 +02:00
})
T.main_caption_color = {r = 150, g = 0, b = 255}
T.sub_caption_color = {r = 0, g = 250, b = 150}
2019-11-04 13:48:08 +02:00
Team.create_forces()
2019-11-03 19:57:36 +02:00
Public.reset_map()
2019-11-03 18:46:18 +02:00
end
local event = require 'utils.event'
event.on_init(on_init)
event.on_nth_tick(30, tick)
2020-09-02 05:18:26 +02:00
event.add(defines.events.on_player_used_spider_remote, on_player_used_spider_remote)
2019-11-03 21:09:51 +02:00
event.add(defines.events.on_robot_built_entity, on_robot_built_entity)
2019-11-03 19:57:36 +02:00
event.add(defines.events.on_entity_died, on_entity_died)
2019-11-03 20:34:36 +02:00
event.add(defines.events.on_player_joined_game, on_player_joined_game)
2019-11-03 21:48:17 +02:00
event.add(defines.events.on_player_changed_position, on_player_changed_position)
event.add(defines.events.on_entity_damaged, on_entity_damaged)