1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-12-28 00:13:51 +02:00
Files
ComfyFactorio/modules/wave_defense/table.lua
Gerkiz 38ec1a9a72 Mass refactor
This PR changes generated events by util modules to bypass the need to require each file to utilize them.

Added new module that tracks undo of a player.

The config module for GUI has been refactored to add functions/events from the caller instead of having one massive blob inside of the file.

The debug module now prints each attribute of an object instead of plain <userdata>.
2025-10-19 21:20:03 +02:00

548 lines
15 KiB
Lua

local Global = require 'utils.global'
local Core = require 'utils.core'
local Gui = require 'utils.gui'
local Event = require 'utils.event'
local Server = require 'utils.server'
local this =
{
pause_waves_custom_callback = nil,
threat_event_custom_callback = nil
}
local Public = {}
local insert = table.insert
Global.register(
this,
function (tbl)
this = tbl
end
)
Public.group_size_modifier_raffle = {}
local group_size_chances =
{
{ 4, 0.4 },
{ 5, 0.5 },
{ 6, 0.6 },
{ 7, 0.7 },
{ 8, 0.8 },
{ 9, 0.9 },
{ 10, 1 },
{ 9, 1.1 },
{ 8, 1.2 },
{ 7, 1.3 },
{ 6, 1.4 },
{ 5, 1.5 },
{ 4, 1.6 },
{ 3, 1.7 },
{ 2, 1.8 }
}
for _, v in pairs(group_size_chances) do
for _ = 1, v[1], 1 do
insert(Public.group_size_modifier_raffle, v[2])
end
end
Public.group_size_modifier_raffle_size = #Public.group_size_modifier_raffle
function Public.reset_wave_defense()
this.boss_wave = false
this.boss_wave_warning = false
this.boost_spawner_sizes_wave_is_above = 1000
this.boost_units_when_wave_is_above = 200
this.boost_bosses_when_wave_is_above = 50
this.side_target_count = 0
this.active_biter_count = 0
this.active_biter_threat = 0
this.average_unit_group_size = 16
this.biter_raffle = {}
this.boss_raffle = {}
this.debug = false
this.inverted = false
this.debug_health = false
this.disable_spawn_near_target = true
this.log_wave_to_discord = true
this.paused = false
this.pause_without_votes = true
this.pause_wave_in_ticks = 18000 -- 5 minutes
this.next_pause_interval = game.tick + 216000 -- 1 hour
this.game_lost = false
this.get_random_close_spawner_attempts = 5
this.group_size = 2
this.last_wave = game.tick
this.final_battle = false
this.max_active_biters = 1280
this.max_active_unit_groups = 32
this.max_biter_age = 3600 * 60
this.nest_building_density = 48
this.next_wave = game.tick + 3600 * 20
this.enable_grace_time =
{
enabled = true,
set = nil
}
this.side_targets = {}
this.simple_entity_shredding_cost_modifier = 0.009
this.spawn_position = { x = 0, y = 64 }
this.spitter_raffle = {}
this.surface_index = 1
this.target = nil
this.threat = 0
this.threat_gain_multiplier = 2
this.threat_log = {}
this.threat_log_index = 0
this.tick_to_spawn_unit_groups = 200 -- this defines how often we spawn a unit group
this.unit_groups_size = 0
this.index = 0
this.random_group = nil
this.unit_group_command_delay = 3600 * 20
this.unit_group_command_step_length = 15
this.search_side_targets = { 'simple-entity', 'tree', 'car', 'spider-vehicle', 'character' }
this.wave_interval = 3600
this.wave_enforced = false
this.wave_number = 0
this.worm_building_chance = 3
this.worm_building_density = 16
this.worm_raffle = {}
this.alert_boss_wave = false
this.remove_entities = false
this.pause_waves =
{
index = 0
}
this.enable_random_spawn_positions = false
this.enable_side_target = false
this.enable_threat_log = true
this.disable_threat_below_zero = false
this.check_collapse_position = true
this.resolve_pathing = true
this.increase_damage_per_wave = false
this.increase_boss_health_per_wave = true
this.increase_average_unit_group_size = false
this.increase_max_active_unit_groups = false
this.increase_health_per_wave = false
this.fill_tiles_so_biter_can_path = true
this.modified_unit_health =
{
current_value = 1.2,
limit_value = 150,
health_increase_per_boss_wave = 0.5 -- wave % 25 == 0 at wave 2k boost is at 41.2
}
this.modified_boss_unit_health =
{
current_value = 2,
limit_value = 500,
health_increase_per_boss_wave = 4 -- wave % 25 == 0 at wave 2k boost is at 322
}
this.generated_units =
{
active_biters = {},
unit_groups = {},
unit_group_last_command = {},
unit_group_pos =
{
index = 0,
positions = {}
},
nests = {}
}
this.threat_values =
{
['biter-spawner'] = 128,
['spitter-spawner'] = 128,
['behemoth-biter'] = 64,
['behemoth-spitter'] = 64,
['big-biter'] = 16,
['big-spitter'] = 16,
['medium-biter'] = 4,
['medium-spitter'] = 4,
['small-biter'] = 1,
['small-spitter'] = 1,
['small-worm-turret'] = 16,
['medium-worm-turret'] = 32,
['big-worm-turret'] = 64,
['behemoth-worm-turret'] = 128
}
this.unit_settings =
{
scale_units_by_health =
{
['small-biter'] = 1,
['medium-biter'] = 0.75,
['big-biter'] = 0.5,
['behemoth-biter'] = 0.25,
['small-spitter'] = 1,
['medium-spitter'] = 0.75,
['big-spitter'] = 0.5,
['behemoth-spitter'] = 0.25
},
scale_worms_by_health =
{
['land-mine'] = 0.5, -- not active as of now
['gun-turret'] = 0.5, -- not active as of now
['flamethrower-turret'] = 0.4, -- not active as of now
['artillery-turret'] = 0.25, -- not active as of now
['small-worm-turret'] = 0.8,
['medium-worm-turret'] = 0.6,
['big-worm-turret'] = 0.3,
['behemoth-worm-turret'] = 0.3
}
}
this.valid_enemy_forces =
{
['enemy'] = true,
['aggressors'] = true,
['aggressors_frenzy'] = true
}
end
function Public.debug_print(msg)
if not this.debug then
return
end
Server.output_script_data('WaveDefense: ' .. msg)
end
function Public.debug_print_health(msg)
if not this.debug then
return
end
Server.output_script_data('[HEALTHBOOSTER]: ' .. msg)
end
--- This gets values from our table
-- @param key <string>
function Public.get(key)
if key then
return this[key]
else
return this
end
end
--- This sets values to our table
-- use with caution.
-- @param key <string>
-- @param value <string/boolean/int>
function Public.set(key, value)
if key and (value or value == false or value == 'nil') then
if value == 'nil' then
this[key] = nil
else
this[key] = value
end
return this[key]
elseif key then
return this[key]
else
return this
end
end
--- Legacy, to be removed
Public.get_table = Public.get
--- This gets the status of the current wave
-- @param <null>
function Public.get_wave()
return this.wave_number
end
--- This gets the status of disable_threat_below_zero
-- @param <null>
function Public.get_disable_threat_below_zero()
return this.disable_threat_below_zero
end
--- This sets if we should disable threat below zero
-- @param <boolean>
function Public.set_disable_threat_below_zero(boolean)
if (boolean or boolean == false) then
this.disable_threat_below_zero = boolean
end
return this.disable_threat_below_zero
end
--- This gets the status of alert_boss_wave
-- @param <null>
function Public.get_alert_boss_wave()
return this.get_alert_boss_wave
end
--- This sets if we should alert the players
-- when we spawn a boss wave
-- @param <boolean>
function Public.alert_boss_wave(boolean)
if (boolean or boolean == false) then
this.alert_boss_wave = boolean
end
return this.alert_boss_wave
end
--- This sets the spawning position of where
-- we will spawn the entities.
-- @param <tbl>
function Public.set_spawn_position(tbl)
if type(tbl) == 'table' then
this.spawn_position = tbl
else
error('Tbl must be of type table.', 2)
end
return this.spawn_position
end
--- This sets if we should remove colliding entities
-- when we spawn entities.
-- @param <boolean>
function Public.remove_entities(boolean)
if (boolean or boolean == false) then
this.remove_entities = boolean
end
return this.remove_entities
end
--- This sets if the threat gui should be present for the players
-- Warning - this creates a lot of entries in the global table
-- and makes save/load heavy.
-- @param <boolean>
function Public.enable_threat_log(boolean)
if (boolean or boolean == false) then
this.enable_threat_log = boolean
end
return this.enable_threat_log
end
--- This sets if random spawn positions should be enabled.
-- @param <boolean>
function Public.enable_random_spawn_positions(boolean)
if (boolean or boolean == false) then
this.enable_random_spawn_positions = boolean
end
return this.enable_random_spawn_positions
end
--- This sets if we should spawn the unit near collapse
-- That is, if collapse module is enabled
-- @param <boolean>
function Public.check_collapse_position(boolean)
if (boolean or boolean == false) then
this.check_collapse_position = boolean
end
return this.check_collapse_position
end
--- This sets if the units/bosses should try to pick side-targets.
-- @param <boolean>
function Public.enable_side_target(boolean)
if (boolean or boolean == false) then
this.enable_side_target = boolean
end
return this.enable_side_target
end
--- This sets if the units health should increase.
-- @param <boolean>
function Public.increase_health_per_wave(boolean)
if (boolean or boolean == false) then
this.increase_health_per_wave = boolean
end
return this.increase_health_per_wave
end
--- This sets if the average unit group size should increase.
-- @param <boolean>
function Public.increase_average_unit_group_size(boolean)
if (boolean or boolean == false) then
this.increase_average_unit_group_size = boolean
end
return this.increase_average_unit_group_size
end
--- This sets if the max unit groups should increase.
-- @param <boolean>
function Public.increase_max_active_unit_groups(boolean)
if (boolean or boolean == false) then
this.increase_max_active_unit_groups = boolean
end
return this.increase_max_active_unit_groups
end
--- This sets if the bosses health should increase.
-- @param <boolean>
function Public.increase_boss_health_per_wave(boolean)
if (boolean or boolean == false) then
this.increase_boss_health_per_wave = boolean
end
return this.increase_boss_health_per_wave
end
--- This checks if units are stuck, if they are - act.
-- @param <boolean>
function Public.resolve_pathing(boolean)
if (boolean or boolean == false) then
this.resolve_pathing = boolean
end
return this.resolve_pathing
end
--- Enables non-placeable tiles to be switched to placable-tiles.
-- @param <boolean>
function Public.fill_tiles_so_biter_can_path(boolean)
if (boolean or boolean == false) then
this.fill_tiles_so_biter_can_path = boolean
end
return this.fill_tiles_so_biter_can_path
end
--- Sets the wave defense units damage increase.
-- @param <boolean>
function Public.increase_damage_per_wave(boolean)
if (boolean or boolean == false) then
this.increase_damage_per_wave = boolean
end
return this.increase_damage_per_wave
end
--- Sets the wave defense units health at start current.
-- @param <int>
function Public.set_normal_unit_current_health(int)
this.modified_unit_health.current_value = int or 1.2
end
--- Sets the wave defense boss health increment.
-- @param <int>
function Public.set_boss_unit_current_health(int)
this.modified_boss_unit_health.current_value = int or 2
end
--- Sets the wave defense units health at start current.
-- @param <int>
function Public.set_unit_health_increment_per_wave(int)
this.modified_unit_health.health_increase_per_boss_wave = int or 0.5
end
--- Sets the wave defense boss health increment.
-- @param <int>
function Public.set_boss_health_increment_per_wave(int)
this.modified_boss_unit_health.health_increase_per_boss_wave = int or 4
end
--- Sets when we should spawn a unit_group.
-- @param <int> in ticks
function Public.set_tick_to_spawn_unit_groups(int)
this.tick_to_spawn_unit_groups = int or 200
end
--- Sets the pause length in ticks.
-- @param <int> in ticks
function Public.set_pause_wave_in_ticks(int)
this.pause_wave_in_ticks = int or 18000
end
--- Sets the main target.
-- @param <target_type> userdata
function Public.set_main_target(target)
this.target = target
end
--- Pauses the wave defense module
-- @param null
function Public.pause(boolean)
this.paused = boolean or false
end
--- Completely disables wave defense module
-- @param null
function Public.disable_spawning_biters(boolean)
this.game_lost = boolean or false
end
---Removes the player wave defense gui
function Public.nuke_wave_gui()
if Gui.get_mod_gui_top_frame() then
Core.iter_players(
function (player)
local g = Gui.get_button_flow(player)['wave_defense']
if g and g.valid then
g.destroy()
end
end
)
else
Core.iter_players(
function (player)
if player.gui.top.wave_defense and player.gui.top.wave_defense.valid then
player.gui.top.wave_defense.destroy()
end
end
)
end
end
--- Sets a custom callback
function Public.set_pause_waves_custom_callback(callback)
this.pause_waves_custom_callback = callback or nil
end
--- Gets a custom callback
function Public.get_pause_waves_custom_callback()
return this.pause_waves_custom_callback or nil
end
--- Sets a custom callback
function Public.set_threat_event_custom_callback(callback)
this.threat_event_custom_callback = callback or nil
end
--- Gets a custom callback
function Public.get_threat_event_custom_callback()
return this.threat_event_custom_callback or nil
end
--- Toggle debug - when you need to troubleshoot.
-- @param <null>
function Public.toggle_debug()
if this.debug then
this.debug = false
else
this.debug = true
end
return this.debug
end
--- Toggle debug - when you need to troubleshoot.
-- @param <null>
function Public.toggle_debug_health()
if this.debug_health then
this.debug_health = false
else
this.debug_health = true
end
return this.debug_health
end
--- Toggle grace time, for when you want to waves to start instantly
-- @param <boolean>
function Public.enable_grace_time(boolean)
this.enable_grace_time.enabled = boolean or false
end
--- Toggles a reverse search function
-- @param <boolean>
function Public.enable_inverted(boolean)
this.inverted = boolean or false
end
-- Event.on_nth_tick(30, Public.debug_module)
Event.on_init(
function ()
Public.reset_wave_defense()
end
)
return Public