1
0
mirror of https://github.com/Refactorio/RedMew.git synced 2024-12-16 10:19:27 +02:00
RedMew/map_gen/shared/hail_hydra.lua
BlueRock (on discord) e2b6f6096d
Update hail_hydra.lua
Fixes an infrequent bug in hail_hydra that has existed a long time.    Currently Factorio does not allow enemy entitities of type 'turret' to target entities of type 'car' (includes cars and tanks).  Doing so logs an error.  If this changes in the future then the condition cause.type ~= "car" below can be removed.
2020-08-09 20:58:59 -04:00

214 lines
6.3 KiB
Lua

-- Cut off a limb, and two more shall take its place!
local Event = require 'utils.event'
local CreateParticles = require 'features.create_particles'
local Token = require 'utils.token'
local Global = require 'utils.global'
local table = require 'utils.table'
local random = math.random
local floor = math.floor
local ceil = math.ceil
local pairs = pairs
local type = type
local clear_table = table.clear_table
local compound = defines.command.compound
local logical_or = defines.compound_command.logical_or
local attack = defines.command.attack
local attack_area = defines.command.attack_area
local hail_hydra_conf = global.config.hail_hydra
local spawn_table = {}
for k, v in pairs(global.config.hail_hydra.hydras) do
spawn_table[k] = v
end
local function formula(evo)
evo = evo * 100
local value = (0.00003 * evo ^ 3 + 0.004 * evo ^ 2 + 0.3 * evo) * 0.01
return value <= 1 and value or 1
end
local primitives = {
evolution_scale = (hail_hydra_conf.evolution_scale ~= nil) and hail_hydra_conf.evolution_scale or 1,
online_player_scale_enabled = hail_hydra_conf.online_player_scale_enabled,
online_player_scale = hail_hydra_conf.online_player_scale,
enabled = nil
}
Global.register(
{
primitives = primitives,
spawn_table = spawn_table
},
function(tbl)
primitives = tbl.primitives
spawn_table = tbl.spawn_table
end
)
local Public = {}
local function backwards_compatibility(amount)
return {min = amount, max = amount + primitives.evolution_scale}
end
local function create_attack_command(position, target)
local command = {type = attack_area, destination = position, radius = 10}
if target then
command = {
type = compound,
structure_type = logical_or,
commands = {
{type = attack, target = target},
command
}
}
end
return command
end
local on_died =
Token.register(
function(event)
local entity = event.entity
local name = entity.name
local hydra = spawn_table[name]
if not hydra then
return
end
local position = entity.position
local force = entity.force
local num_online_players = #game.connected_players
local player_scale = 0
if primitives.online_player_scale_enabled then
player_scale = (num_online_players - primitives.online_player_scale) * 0.01
end
local evolution_scaled = formula(force.evolution_factor)
local evolution_factor = evolution_scaled + evolution_scaled * player_scale
local cause = event.cause
local surface = entity.surface
local create_entity = surface.create_entity
local create_particle = surface.create_particle
local find_non_colliding_position = surface.find_non_colliding_position
local command = create_attack_command(position, cause)
for hydra_spawn, amount in pairs(hydra) do
if (type(amount) == 'number') then
amount = backwards_compatibility(amount)
end
local trigger = amount.trigger
if trigger == nil or trigger < force.evolution_factor then
if amount.locked then
evolution_factor = evolution_scaled
end
local min = amount.min
local max = amount.max
max = (max ~= nil and max >= min) and max or min
if max ~= min then
amount = (max - min) * (evolution_factor / formula(1)) + min
else
amount = min
end
else
amount = 0
end
amount = (amount > 0) and amount or 0
local extra_chance = amount % 1
if extra_chance > 0 then
if random() <= extra_chance then
amount = ceil(amount)
else
amount = floor(amount)
end
end
local particle_count
if amount > 4 then
particle_count = 60
else
particle_count = amount * 15
end
CreateParticles.blood_explosion(create_particle, particle_count, position)
for _ = amount, 1, -1 do
position = find_non_colliding_position(hydra_spawn, position, 2, 0.4) or position
local spawned = create_entity({name = hydra_spawn, force = force, position = position})
if spawned and spawned.type == 'unit' then
spawned.set_command(command)
elseif spawned and cause and cause.valid and cause.force and cause.type ~= "car" then
spawned.shooting_target = cause
end
end
end
end
)
local function register_event()
if not primitives.enabled then
Event.add_removable(defines.events.on_entity_died, on_died)
primitives.enabled = true
end
end
--- Enables hail_hydra
function Public.enable_hail_hydra()
register_event()
end
--- Disables hail_hydra
function Public.disable_hail_hydra()
if primitives.enabled then
Event.remove_removable(defines.events.on_entity_died, on_died)
primitives.enabled = nil
end
end
--- Sets the evolution scale
-- @param scale <number>
function Public.set_evolution_scale(scale)
primitives.evolution_scale = scale
end
--- Sets the online player scale
-- @param scale <number>
function Public.set_evolution_scale(scale)
primitives.online_player_scale = scale
end
--- Toggles the online player scale feature
-- @param enable <boolean>
function Public.set_evolution_scale(enabled)
primitives.online_player_scale_enabled = enabled
end
--- Sets the hydra spawning table
-- @param hydras <table> see config.lua's hail_hydra section for example
function Public.set_hydras(hydras)
clear_table(spawn_table)
for k, v in pairs(hydras) do
spawn_table[k] = v
end
end
--- Adds to/overwrites parts of the hydra spawning table
-- @param hydras <table> see config.lua's hail_hydra section for example
function Public.add_hydras(hydras)
for k, v in pairs(hydras) do
spawn_table[k] = v
end
end
if global.config.hail_hydra.enabled then
register_event()
end
return Public