1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-01-22 03:38:48 +02:00

biter_battles_v2 update

This commit is contained in:
MewMew 2019-03-16 07:31:34 +01:00
parent be73a5caac
commit 06687500d0
7 changed files with 247 additions and 89 deletions

View File

@ -1,6 +1,27 @@
local event = require 'utils.event'
local math_random = math.random
local ai = {}
local threat_values = {
["small-spitter"] = 2,
["small-biter"] = 2,
["medium-spitter"] = 4,
["medium-biter"] = 4,
["big-spitter"] = 8,
["big-biter"] = 8,
["behemoth-spitter"] = 16,
["behemoth-biter"] = 16
}
local function shuffle(tbl)
local size = #tbl
for i = size, 1, -1 do
local rand = math_random(size)
tbl[i], tbl[rand] = tbl[rand], tbl[i]
end
return tbl
end
ai.send_near_biter_to_silo = function()
if not global.rocket_silo then return end
game.surfaces["surface"].set_multi_command({
@ -26,4 +47,93 @@ ai.send_near_biter_to_silo = function()
})
end
local function get_random_close_spawner(surface, biter_force_name)
local spawners = surface.find_entities_filtered({type = "unit-spawner", force = biter_force_name})
if not spawners[1] then return false end
spawners = shuffle(spawners)
local spawner = spawners[1]
for i = 2, 4, 1 do
if not spawners[i] then return spawner end
if spawners[i].position.x ^ 2 + spawners[i].position.y ^ 2 < spawner.position.x ^ 2 + spawner.position.y ^ 2 then spawner = spawners[i] end
end
return spawner
end
local function select_units_around_spawner(spawner, force_name, biter_force_name)
local biters = spawner.surface.find_enemy_units(spawner.position, 128, force_name)
if not biters[1] then return false end
local valid_biters = {}
local threat = global.bb_threat[biter_force_name] * 0.5
for _, biter in pairs(biters) do
valid_biters[#valid_biters + 1] = biter
threat = threat - threat_values[biter.name]
if threat < 0 then return valid_biters end
end
end
local function send_group(unit_group, force_name, nearest_player_unit)
unit_group.set_command({
type = defines.command.compound,
structure_type = defines.compound_command.return_last,
commands = {
{
type = defines.command.attack_area,
destination = nearest_player_unit.position,
radius = 32,
distraction=defines.distraction.by_enemy
},
{
type = defines.command.attack,
target = global.rocket_silo[force_name],
distraction = defines.distraction.by_enemy
}
}
})
return true
end
local function create_attack_group(surface, force_name, biter_force_name)
if global.bb_threat[biter_force_name] <= 0 then return false end
local spawner = get_random_close_spawner(surface, biter_force_name)
if not spawner then return false end --game.print("no unit-spawner for " .. biter_force_name)
local nearest_player_unit = surface.find_nearest_enemy({position = spawner.position, max_distance = 2048, force = biter_force_name})
if not nearest_player_unit then nearest_player_unit = global.rocket_silo[force_name] end
local unit_group_position = {x = (spawner.position.x + nearest_player_unit.position.x) * 0.5, y = (spawner.position.y + nearest_player_unit.position.y) * 0.5}
local pos = surface.find_non_colliding_position("rocket-silo", unit_group_position, 96, 1)
if pos then unit_group_position = pos end
local units = select_units_around_spawner(spawner, force_name, biter_force_name)
if not units then return false end
local unit_group = surface.create_unit_group({position = unit_group_position, force = biter_force_name})
for _, unit in pairs(units) do unit_group.add_member(unit) end
send_group(unit_group, force_name, nearest_player_unit)
end
ai.main_attack = function()
local surface = game.surfaces["biter_battles"]
for _, force_name in pairs({"north", "south"}) do
create_attack_group(surface, force_name, force_name .. "_biters")
end
end
--Biter Evasion
local function on_entity_damaged(event)
if not event.entity.valid then return end
if event.entity.type ~= "unit" then return end
if global.bb_evasion[event.entity.force.name] < math_random(1,1000) then return end
event.entity.health = event.entity.health + event.final_damage_amount
end
--Biter Threat Value Substraction
local function on_entity_died(event)
if not event.entity.valid then return end
if threat_values[event.entity.name] then
global.bb_threat[event.entity.force.name] = global.bb_threat[event.entity.force.name] - threat_values[event.entity.name]
return
end
end
event.add(defines.events.on_entity_damaged, on_entity_damaged)
event.add(defines.events.on_entity_died, on_entity_died)
return ai

View File

@ -7,8 +7,8 @@ local math_random = math.random
local function init_surface()
if game.surfaces["biter_battles"] then return end
local map_gen_settings = {}
map_gen_settings.water = "0.5"
map_gen_settings.starting_area = "5"
map_gen_settings.water = "0.6"
map_gen_settings.starting_area = "5"
map_gen_settings.cliff_settings = {cliff_elevation_interval = 12, cliff_elevation_0 = 32}
map_gen_settings.autoplace_controls = {
["coal"] = {frequency = "3", size = "1", richness = "1"},

View File

@ -1,5 +1,3 @@
local event = require 'utils.event'
local food_values = {
["automation-science-pack"] = {value = 0.001, name = "automation science"},
["logistic-science-pack"] = {value = 0.00292, name = "logistic science"},
@ -10,17 +8,6 @@ local food_values = {
["space-science-pack"] = {value = 0.420, name = "space science"},
}
local threat_values = {
["small_biter"] = 1,
["medium_biter"] = 3,
["big_biter"] = 5,
["behemoth_biter"] = 10,
["small_spitter"] = 1,
["medium_spitter"] = 3,
["big_spitter"] = 5,
["behemoth_spitter"] = 10
}
local force_translation = {
["south_biters"] = "south",
["north_biters"] = "north"
@ -43,9 +30,8 @@ local function set_biter_endgame_damage(force_name, biter_force)
end
local function feed_biters(player, food)
--local enemy_force_name = enemy_team_of[player.force.name] ---------------
enemy_force_name = player.force.name
local enemy_force_name = enemy_team_of[player.force.name] ---------------
--enemy_force_name = player.force.name
local biter_force_name = enemy_force_name .. "_biters"
@ -56,7 +42,7 @@ local function feed_biters(player, food)
return
end
--i.remove({name = food, count = flask_amount})
i.remove({name = food, count = flask_amount})
if flask_amount >= 20 then
game.print(player.name .. " fed " .. flask_amount .. " flasks of " .. food_values[food].name .. " juice to team " .. enemy_force_name .. "'s biters!", {r = 0.98, g = 0.66, b = 0.22})
@ -69,53 +55,32 @@ local function feed_biters(player, food)
end
--ADD TOTAL FOOD FEED
--global.bb_total_food[enemy_force_name] = global.bb_total_food[enemy_force_name] + (food_values[food].value * flask_amount)
--global.bb_total_food[biter_force_name] = global.bb_total_food[biter_force_name] + (food_values[food].value * flask_amount)
for a = 1, flask_amount, 1 do
--SET THREAT INCOME
local e = (global.bb_evolution[enemy_force_name] * 100) + 1
local e = (global.bb_evolution[biter_force_name] * 100) + 1
local diminishing_modifier = 1 / (10 ^ (e * 0.03))
global.bb_threat_income[enemy_force_name] = global.bb_threat_income[enemy_force_name] + (food_values[food].value * diminishing_modifier * 10)
global.bb_threat_income[biter_force_name] = global.bb_threat_income[biter_force_name] + (food_values[food].value * diminishing_modifier * 10)
---SET EVOLUTION
local e = (game.forces[biter_force_name].evolution_factor * 100) + 1
local diminishing_modifier = 1 / (10 ^ (e * 0.03))
global.bb_evolution[enemy_force_name] = global.bb_evolution[enemy_force_name] + (food_values[food].value * diminishing_modifier)
if global.bb_evolution[enemy_force_name] < 1 then
game.forces[biter_force_name].evolution_factor = global.bb_evolution[enemy_force_name]
global.bb_evolution[biter_force_name] = global.bb_evolution[biter_force_name] + (food_values[food].value * diminishing_modifier)
if global.bb_evolution[biter_force_name] < 1 then
game.forces[biter_force_name].evolution_factor = global.bb_evolution[biter_force_name]
else
game.forces[biter_force_name].evolution_factor = 1
end
end
--ADD INSTANT THREAT
global.bb_threat[enemy_force_name] = global.bb_threat[enemy_force_name] + (food_values[food].value * 100 * flask_amount)
global.bb_threat[biter_force_name] = global.bb_threat[biter_force_name] + (food_values[food].value * 100 * flask_amount)
set_biter_endgame_damage(enemy_force_name, game.forces[biter_force_name])
set_biter_endgame_damage(biter_force_name, game.forces[biter_force_name])
global.bb_evasion[biter_force_name] = (global.bb_evolution[enemy_force_name] - 1) * 333
global.bb_evasion[biter_force_name] = (global.bb_evolution[biter_force_name] - 1) * 333
if global.bb_evasion[biter_force_name] > 900 then global.bb_evasion[biter_force_name] = 900 end
end
--Biter Evasion
local math_random = math.random
local function on_entity_damaged(event)
if not event.entity.valid then return end
if event.entity.type ~= "unit" then return end
if global.bb_evasion[event.entity.force.name] < math_random(1,1000) then return end
event.entity.health = event.entity.health + event.final_damage_amount
end
--Biter Threat Value Reduction
local function on_entity_died(event)
if not event.entity.valid then return end
if threat_values[event.entity.name] then
global.bb_threat[event.entity.force.name] = global.bb_threat[event.entity.force.name] - threat_values[event.entity.name]
return
end
end
event.add(defines.events.on_entity_damaged, on_entity_damaged)
event.add(defines.events.on_entity_died, on_entity_died)
return feed_biters

View File

@ -1,13 +1,74 @@
local event = require 'utils.event'
local math_random = math.random
local particles = {"coal-particle", "copper-ore-particle", "iron-ore-particle", "stone-particle"}
local gui_values = {
["north"] = {c1 = "Team North", color1 = {r = 0.55, g = 0.55, b = 0.99}},
["south"] = {c1 = "Team South", color1 = {r = 0.99, g = 0.33, b = 0.33}}
}
local function shuffle(tbl)
local size = #tbl
for i = size, 1, -1 do
local rand = math_random(size)
tbl[i], tbl[rand] = tbl[rand], tbl[i]
end
return tbl
end
local function create_victory_gui(player)
local values = gui_values[global.bb_game_won_by_team]
local frame = player.gui.left.add {type = "frame", name = "bb_victory_gui", direction = "vertical", caption = values.c1 .. " team has won!" }
frame.style.font = "heading-1"
frame.style.font_color = values.color1
end
local function destroy_entity(e)
if not e.valid then return end
local names = {"big-artillery-explosion", "big-explosion", "big-explosion", "big-explosion", "fire-flame", "massive-explosion"}
e.surface.create_entity({name = names[math.random(1,#names)], position = e.position})
e.die()
end
local function annihilate_base(center_pos, surface, force_name)
local entities = {}
for _, e in pairs(surface.find_entities_filtered({force = force_name})) do
if e.name ~= "player" then
entities[#entities + 1] = e
end
end
if not entities[2] then return end
entities = shuffle(entities)
for i1 = #entities, 1, -1 do
for i2 = #entities, 1, -1 do
local distance_to_center_1 = (entities[i1].position.x - center_pos.x)^2 + (entities[i1].position.y - center_pos.y)^2
local distance_to_center_2 = (entities[i2].position.x - center_pos.x)^2 + (entities[i2].position.y - center_pos.y)^2
if distance_to_center_1 > distance_to_center_2 then
local k = entities[i1]
entities[i1] = entities[i2]
entities[i2] = k
end
end
end
for i = 1, #entities, 1 do
local t = i * 8
if not global.on_tick_schedule[game.tick + t] then global.on_tick_schedule[game.tick + t] = {} end
local pos = global.rocket_silo[global.bb_game_won_by_team].position
global.on_tick_schedule[game.tick + t][#global.on_tick_schedule[game.tick + t] + 1] = {
func = destroy_entity,
args = {entities[i]}
}
end
end
local function create_fireworks_rocket(surface, position)
local particles = {"coal-particle", "copper-ore-particle", "iron-ore-particle", "stone-particle"}
local particle = particles[math_random(1, #particles)]
local m = math_random(16, 36)
local m2 = m * 0.005
for i = 1, 80, 1 do
for i = 1, 60, 1 do
surface.create_entity({
name = particle,
position = position,
@ -18,21 +79,24 @@ local function create_fireworks_rocket(surface, position)
})
end
if math_random(1,16) ~= 1 then return end
if math_random(1,12) ~= 1 then return end
surface.create_entity({name = "explosion", position = position})
end
local function fireworks(surface)
local radius = 96
for t = 1, 18000, 1 do
if not global.on_tick_schedule[game.tick + t] then global.on_tick_schedule[game.tick + t] = {} end
for x = 1, 3, 1 do
local radius = 52
for t = 1, 10800, 1 do
if t % 3 == 0 then
if not global.on_tick_schedule[game.tick + t] then global.on_tick_schedule[game.tick + t] = {} end
local pos = global.rocket_silo[global.bb_game_won_by_team].position
global.on_tick_schedule[game.tick + t][#global.on_tick_schedule[game.tick + t] + 1] = {
func = create_fireworks_rocket,
args = {surface, {x = radius - math_random(0, radius * 2),y = radius - math_random(0, radius * 2)}}
}
args = {
surface,
{x = (pos.x - radius) + math_random(0, radius * 2),y = (pos.y - radius) + math_random(0, radius * 2)}
}
}
end
t = t + 1
end
end
@ -112,15 +176,15 @@ local function show_mvps(player)
if not global.results_sent_north then
local result = {}
insert(result, 'NORTH: \\n')
insert(result, 'MVP Defender: \\n')
insert(result, mvp.killscore.name .. " with a score of " .. mvp.killscore.score .. "\\n" )
insert(result, '\\n')
insert(result, 'MVP Builder: \\n')
insert(result, mvp.built_entities.name .. " built " .. mvp.built_entities.score .. " things\\n" )
insert(result, '\\n')
insert(result, 'MVP Deaths: \\n')
insert(result, mvp.deaths.name .. " died " .. mvp.deaths.score .. " times" )
table.insert(result, 'NORTH: \\n')
table.insert(result, 'MVP Defender: \\n')
table.insert(result, mvp.killscore.name .. " with a score of " .. mvp.killscore.score .. "\\n" )
table.insert(result, '\\n')
table.insert(result, 'MVP Builder: \\n')
table.insert(result, mvp.built_entities.name .. " built " .. mvp.built_entities.score .. " things\\n" )
table.insert(result, '\\n')
table.insert(result, 'MVP Deaths: \\n')
table.insert(result, mvp.deaths.name .. " died " .. mvp.deaths.score .. " times" )
local message = table.concat(result)
server_commands.to_discord_embed(message)
global.results_sent_north = true
@ -157,15 +221,15 @@ local function show_mvps(player)
if not global.results_sent_south then
local result = {}
insert(result, 'SOUTH: \\n')
insert(result, 'MVP Defender: \\n')
insert(result, mvp.killscore.name .. " with a score of " .. mvp.killscore.score .. "\\n" )
insert(result, '\\n')
insert(result, 'MVP Builder: \\n')
insert(result, mvp.built_entities.name .. " built " .. mvp.built_entities.score .. " things\\n" )
insert(result, '\\n')
insert(result, 'MVP Deaths: \\n')
insert(result, mvp.deaths.name .. " died " .. mvp.deaths.score .. " times" )
table.insert(result, 'SOUTH: \\n')
table.insert(result, 'MVP Defender: \\n')
table.insert(result, mvp.killscore.name .. " with a score of " .. mvp.killscore.score .. "\\n" )
table.insert(result, '\\n')
table.insert(result, 'MVP Builder: \\n')
table.insert(result, mvp.built_entities.name .. " built " .. mvp.built_entities.score .. " things\\n" )
table.insert(result, '\\n')
table.insert(result, 'MVP Deaths: \\n')
table.insert(result, mvp.deaths.name .. " died " .. mvp.deaths.score .. " times" )
local message = table.concat(result)
server_commands.to_discord_embed(message)
global.results_sent_south = true
@ -173,17 +237,26 @@ local function show_mvps(player)
end
end
local enemy_team_of = {
["north"] = "south",
["south"] = "north"
}
local function on_entity_died(event)
if not event.entity.valid then return end
if event.entity.name ~= "rocket-silo" then return end
if event.entity == global.rocket_silo.south or event.entity == global.rocket_silo.north then
if event.entity == global.rocket_silo.south or event.entity == global.rocket_silo.north then
global.bb_game_won_by_team = enemy_team_of[event.entity.force.name]
for _, player in pairs(game.connected_players) do
player.play_sound{path="utility/game_won", volume_modifier=1}
if player.gui.left["bb_main_gui"] then player.gui.left["bb_main_gui"].destroy() end
show_mvps(player)
end
create_victory_gui(player)
show_mvps(player)
if player.character then player.character.destructible = false end
end
fireworks(event.entity.surface)
end
annihilate_base(event.entity.position, event.entity.surface, event.entity.force.name)
end
end
event.add(defines.events.on_entity_died, on_entity_died)

View File

@ -14,10 +14,10 @@ local food_names = {
}
local gui_values = {
[1] = {force = "north", c1 = "Team North", c2 = "JOIN NORTH", n1 = "join_north_button",
["north"] = {force = "north", biter_force = "north_biters", c1 = "Team North", c2 = "JOIN NORTH", n1 = "join_north_button",
t1 = "Evolution of the North side biters. Can go beyond 100% for endgame modifiers.",
t2 = "Threat causes biters to attack. Reduces when biters are slain.", color1 = {r = 0.55, g = 0.55, b = 0.99}, color2 = {r = 0.66, g = 0.66, b = 0.99}},
[2] = {force = "south", c1 = "Team South", c2 = "JOIN SOUTH", n1 = "join_south_button",
["south"] = {force = "south", biter_force = "south_biters", c1 = "Team South", c2 = "JOIN SOUTH", n1 = "join_south_button",
t1 = "Evolution of the South side biters. Can go beyond 100% for endgame modifiers.",
t2 = "Threat causes biters to attack. Reduces when biters are slain.", color1 = {r = 0.99, g = 0.33, b = 0.33}, color2 = {r = 0.99, g = 0.44, b = 0.44}}
}
@ -79,6 +79,7 @@ end
local function create_main_gui(player)
if player.gui.left["bb_main_gui"] then player.gui.left["bb_main_gui"].destroy() end
if global.bb_game_won_by_team then return end
if player.force.name == "player" then create_first_join_gui(player) return end
local frame = player.gui.left.add { type = "frame", name = "bb_main_gui", direction = "vertical" }
@ -124,7 +125,7 @@ local function create_main_gui(player)
local l = t.add { type = "label", caption = "Evo:"}
--l.style.minimal_width = 25
l.tooltip = gui_value.t1
local l = t.add {type = "label", caption = tostring(math.ceil(100 * global.bb_evolution[gui_value.force])) .. "%"}
local l = t.add {type = "label", caption = tostring(math.ceil(100 * global.bb_evolution[gui_value.biter_force])) .. "%"}
l.style.minimal_width = 38
l.style.font_color = gui_value.color2
l.style.font = "default-bold"
@ -133,7 +134,7 @@ local function create_main_gui(player)
local l = t.add { type = "label", caption = "Threat: "}
l.style.minimal_width = 25
l.tooltip = gui_value.t2
local l = t.add { type = "label", caption = math.ceil(global.bb_threat[gui_value.force])}
local l = t.add { type = "label", caption = math.ceil(global.bb_threat[gui_value.biter_force])}
l.style.font_color = gui_value.color2
l.style.font = "default-bold"
l.style.minimal_width = 25

View File

@ -20,8 +20,8 @@ end
local function on_tick(event)
if game.tick % 60 ~= 0 then return end
global.bb_threat["north"] = global.bb_threat["north"] + global.bb_threat_income["north"]
global.bb_threat["south"] = global.bb_threat["south"] + global.bb_threat_income["south"]
global.bb_threat["north_biters"] = global.bb_threat["north_biters"] + global.bb_threat_income["north_biters"]
global.bb_threat["south_biters"] = global.bb_threat["south_biters"] + global.bb_threat_income["south_biters"]
gui()
if game.tick % 300 ~= 0 then return end
if global.spy_fish_timeout["south"] - game.tick > 0 then
@ -33,7 +33,16 @@ local function on_tick(event)
reveal_team("south")
else
global.spy_fish_timeout["north"] = 0
end
end
if game.tick % 3600 ~= 0 then return end
if global.bb_game_won_by_team then
for _, p in pairs(game.connected_players) do
if p.character then p.character.destructible = false end
end
return
end
ai.main_attack()
end
event.add(defines.events.on_tick, on_tick)

View File

@ -77,7 +77,7 @@ local function create_schedule(radius)
end
local function on_player_joined_game(event)
if not global.chunk_gen_coords then create_schedule(6) end
if not global.chunk_gen_coords then create_schedule(20) end
end
event.add(defines.events.on_player_joined_game, on_player_joined_game)