mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-01-08 00:39:30 +02:00
419 lines
15 KiB
Lua
419 lines
15 KiB
Lua
require "modules.no_turrets"
|
|
--require "maps.biter_hatchery.flamethrower_nerf"
|
|
local RPG = require "modules.rpg"
|
|
local Tabs = require 'comfy_panel.main'
|
|
local Map_score = require "modules.map_score"
|
|
local Unit_health_booster = require "modules.biter_health_booster"
|
|
local unit_raffle = require "maps.biter_hatchery.raffle_tables"
|
|
local Terrain = require "maps.biter_hatchery.terrain"
|
|
local Gui = require "maps.biter_hatchery.gui"
|
|
require "maps.biter_hatchery.share_chat"
|
|
local Team = require "maps.biter_hatchery.team"
|
|
local Reset = require "functions.soft_reset"
|
|
local Map = require "modules.map_info"
|
|
local math_random = math.random
|
|
local Public = {}
|
|
|
|
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},
|
|
},
|
|
}
|
|
|
|
local m = 2
|
|
local health_boost_food_values = {
|
|
["automation-science-pack"] = 0.000001 * m,
|
|
["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,
|
|
}
|
|
|
|
local worm_turret_spawn_radius = 18
|
|
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
|
|
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
|
|
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
|
|
|
|
function Public.reset_map()
|
|
Terrain.create_mirror_surface()
|
|
|
|
if not global.active_surface_index then
|
|
global.active_surface_index = game.create_surface("biter_hatchery", map_gen_settings).index
|
|
else
|
|
global.active_surface_index = Reset.soft_reset_map(game.surfaces[global.active_surface_index], map_gen_settings, Team.starting_items).index
|
|
end
|
|
|
|
local surface = game.surfaces[global.active_surface_index]
|
|
|
|
surface.request_to_generate_chunks({0,0}, 8)
|
|
surface.force_generate_chunk_requests()
|
|
game.forces.spectator.set_spawn_position({0, -128}, surface)
|
|
game.forces.west.set_spawn_position({-200, 0}, surface)
|
|
game.forces.east.set_spawn_position({200, 0}, surface)
|
|
|
|
RPG.rpg_reset_all_players()
|
|
|
|
Team.set_force_attributes()
|
|
Team.assign_random_force_to_active_players()
|
|
|
|
for _, player in pairs(game.connected_players) do
|
|
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
|
|
Gui.rejoin_question(player)
|
|
end
|
|
end
|
|
|
|
local function spawn_worm_turret(surface, force_name, food_item)
|
|
local r_max = surface.count_entities_filtered({type = "turret", force = force_name}) + 1
|
|
if r_max > 8 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"
|
|
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})
|
|
end
|
|
|
|
local function spawn_units(belt, food_item, removed_item_count)
|
|
local count_per_flask = unit_raffle[food_item][2]
|
|
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)
|
|
team.units[unit.unit_number] = unit
|
|
team.unit_count = team.unit_count + 1
|
|
end
|
|
end
|
|
if math_random(1, 32) == 1 then spawn_worm_turret(belt.surface, belt.force.name, food_item) end
|
|
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
|
|
|
|
local nom_msg = {"munch", "munch", "yum", "nom"}
|
|
|
|
local function feed_floaty_text(entity)
|
|
entity.surface.create_entity({name = "flying-text", position = entity.position, text = nom_msg[math_random(1, 4)], color = {math_random(50, 100), 0, 255}})
|
|
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
|
|
|
|
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
|
|
local removed_item_count = line.remove_item({name = food_item, count = 8})
|
|
if removed_item_count > 0 then
|
|
feed_floaty_text(belt)
|
|
spawn_units(belt, food_item, removed_item_count)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function nom()
|
|
local surface = game.surfaces[global.active_surface_index]
|
|
for key, force in pairs(global.map_forces) do
|
|
if not force.hatchery then return end
|
|
force.hatchery.health = force.hatchery.health + 1
|
|
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
|
|
end
|
|
|
|
local function get_units(force_name)
|
|
local units = {}
|
|
local count = 1
|
|
for _, unit in pairs(global.map_forces[force_name].units) do
|
|
if not unit.unit_group then
|
|
if math_random(1, 3) ~= 1 then
|
|
units[count] = unit
|
|
count = count + 1
|
|
end
|
|
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
|
|
|
|
local function send_unit_groups()
|
|
local surface = game.surfaces[global.active_surface_index]
|
|
for key, force in pairs(global.map_forces) do
|
|
local units = get_units(key)
|
|
if #units > 0 then
|
|
alert_bubble(key, units[1])
|
|
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})
|
|
for _, unit in pairs(units) do unit_group.add_member(unit) end
|
|
if not force.target then return end
|
|
if not force.target.valid then return end
|
|
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},
|
|
radius = 6,
|
|
distraction = defines.distraction.by_anything
|
|
},
|
|
{
|
|
type = defines.command.attack,
|
|
target = force.target,
|
|
distraction = defines.distraction.by_enemy,
|
|
},
|
|
}
|
|
})
|
|
unit_group.start_moving()
|
|
end
|
|
end
|
|
end
|
|
|
|
local border_teleport = {
|
|
["east"] = 1,
|
|
["west"] = -1,
|
|
}
|
|
|
|
local function on_player_changed_position(event)
|
|
local player = game.players[event.player_index]
|
|
if not player.character then return end
|
|
if not player.character.valid then return end
|
|
if player.position.x > -4 and player.position.x < 4 then
|
|
if not border_teleport[player.force.name] then return end
|
|
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
|
|
|
|
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
|
|
team.units[entity.unit_number] = nil
|
|
return
|
|
end
|
|
|
|
if entity.type ~= "unit-spawner" then return end
|
|
|
|
if entity.force.name == "east" then
|
|
game.print("East lost their Hatchery.", {100, 100, 100})
|
|
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
|
|
if global.map_forces.east.player_count > 0 then
|
|
Map_score.set_score(player, Map_score.get_score(player) + 1)
|
|
end
|
|
end
|
|
else
|
|
game.print("West lost their Hatchery.", {100, 100, 100})
|
|
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
|
|
if global.map_forces.west.player_count > 0 then
|
|
Map_score.set_score(player, Map_score.get_score(player) + 1)
|
|
end
|
|
end
|
|
end
|
|
|
|
game.print("Next round starting in 60 seconds..", {150, 150, 150})
|
|
|
|
game.forces.spectator.play_sound{path="utility/game_won", volume_modifier=0.85}
|
|
|
|
global.game_reset_tick = game.tick + 3600
|
|
game.delete_surface("mirror_terrain")
|
|
|
|
for _, player in pairs(game.connected_players) do
|
|
for _, child in pairs(player.gui.left.children) do child.destroy() end
|
|
Tabs.comfy_panel_call_tab(player, "Map Scores")
|
|
end
|
|
end
|
|
|
|
local function on_player_joined_game(event)
|
|
local player = game.players[event.player_index]
|
|
local surface = game.surfaces[global.active_surface_index]
|
|
|
|
Gui.unit_health_buttons(player)
|
|
Gui.spectate_button(player)
|
|
Gui.update_health_boost_buttons(player)
|
|
|
|
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
|
|
Team.assign_force_to_player(player)
|
|
Team.teleport_player_to_active_surface(player)
|
|
Team.put_player_into_random_team(player)
|
|
end
|
|
end
|
|
|
|
local function tick()
|
|
local game_tick = game.tick
|
|
if game_tick % 240 == 0 then
|
|
local surface = game.surfaces[global.active_surface_index]
|
|
--if surface.is_chunk_generated({10, 0}) then
|
|
local area = {{-320, -161}, {319, 160}}
|
|
game.forces.west.chart(surface, area)
|
|
game.forces.east.chart(surface, area)
|
|
--end
|
|
end
|
|
if game_tick % 1200 == 0 then send_unit_groups() end
|
|
if global.game_reset_tick then
|
|
if global.game_reset_tick < game_tick then
|
|
global.game_reset_tick = nil
|
|
Public.reset_map()
|
|
end
|
|
return
|
|
end
|
|
nom()
|
|
end
|
|
|
|
--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
|
|
|
|
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
|
|
if cause.type == "unit" then
|
|
if math_random(1,5) == 1 then return end
|
|
end
|
|
end
|
|
end
|
|
entity.health = entity.health + event.final_damage_amount
|
|
end
|
|
|
|
local function on_init()
|
|
game.difficulty_settings.technology_price_multiplier = 0.5
|
|
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
|
|
global.map_forces = {
|
|
["west"] = {},
|
|
["east"] = {},
|
|
}
|
|
|
|
local T = Map.Pop_info()
|
|
T.main_caption = "Biter Hatchery"
|
|
T.sub_caption = "*nibble nibble nom nom*"
|
|
T.text = table.concat({
|
|
"Defeat the enemy teams nest.\n",
|
|
"Feed your hatchery science flasks to breed biters!\n",
|
|
"They will soon after swarm to the opposing teams nest!\n",
|
|
"\n",
|
|
"Lay transport belts to your hatchery and they will happily nom the juice off the conveyor.\n",
|
|
"Higher tier flasks will breed stronger biters!\n",
|
|
"\n",
|
|
"Player turrets are disabled.\n",
|
|
"Feeding may spawn friendly worm turrets.\n",
|
|
"The center river may not be crossed.\n",
|
|
"Construction robots may not build over the river.\n",
|
|
})
|
|
T.main_caption_color = {r = 150, g = 0, b = 255}
|
|
T.sub_caption_color = {r = 0, g = 250, b = 150}
|
|
|
|
Team.create_forces()
|
|
Public.reset_map()
|
|
end
|
|
|
|
local event = require 'utils.event'
|
|
event.on_init(on_init)
|
|
event.on_nth_tick(60, tick)
|
|
event.add(defines.events.on_robot_built_entity, on_robot_built_entity)
|
|
event.add(defines.events.on_entity_died, on_entity_died)
|
|
event.add(defines.events.on_player_joined_game, on_player_joined_game)
|
|
event.add(defines.events.on_player_changed_position, on_player_changed_position)
|
|
event.add(defines.events.on_entity_damaged, on_entity_damaged) |