mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-01-08 00:39:30 +02:00
b6aec3bd07
Ideally, you could keep the health modifier in the pool structure so you dont need to calculate the inverse every time again, but since the 3rd spot meant stuff for bosses and it was used in other places, i didn't want to mess with it.
134 lines
4.2 KiB
Lua
134 lines
4.2 KiB
Lua
-- Biters and Spitters gain additional health / resistance -- mewmew
|
|
-- Use global.biter_health_boost or global.biter_health_boost_forces to modify their health.
|
|
-- 1 = vanilla health, 2 = 200% vanilla health
|
|
-- do not use values below 1
|
|
local math_floor = math.floor
|
|
local math_round = math.round
|
|
local Public = {}
|
|
|
|
local function clean_table()
|
|
--Perform a table cleanup every 1000 boosts
|
|
global.biter_health_boost_count = global.biter_health_boost_count + 1
|
|
if global.biter_health_boost_count % 1000 ~= 0 then return end
|
|
|
|
local units_to_delete = {}
|
|
|
|
--Mark all health boost entries for deletion
|
|
for key, health in pairs(global.biter_health_boost_units) do
|
|
units_to_delete[key] = true
|
|
end
|
|
|
|
--Remove valid health boost entries from deletion
|
|
for _, surface in pairs(game.surfaces) do
|
|
for _, unit in pairs(surface.find_entities_filtered({type = "unit"})) do
|
|
units_to_delete[unit.unit_number] = nil
|
|
end
|
|
end
|
|
|
|
--Remove abandoned health boost entries
|
|
for key, _ in pairs(units_to_delete) do
|
|
global.biter_health_boost_units[key] = nil
|
|
end
|
|
end
|
|
|
|
local function create_boss_healthbar(entity, size)
|
|
return rendering.draw_sprite({
|
|
sprite="virtual-signal/signal-white",
|
|
tint={0, 200, 0},
|
|
x_scale=size * 15, y_scale=size, render_layer="light-effect",
|
|
target=entity, target_offset={0, -2.5}, surface=entity.surface,
|
|
})
|
|
end
|
|
|
|
local function set_boss_healthbar(health, max_health, healthbar_id)
|
|
local m = health / max_health
|
|
local x_scale = rendering.get_y_scale(healthbar_id) * 15
|
|
rendering.set_x_scale(healthbar_id, x_scale * m)
|
|
rendering.set_color(healthbar_id, {math_floor(255 - 255 * m), math_floor(200 * m), 0})
|
|
end
|
|
|
|
function Public.add_unit(unit, health_multiplier)
|
|
if not health_multiplier then health_multiplier = global.biter_health_boost end
|
|
global.biter_health_boost_units[unit.unit_number] = {
|
|
math_floor(unit.prototype.max_health * health_multiplier),
|
|
math_round(1 / health_multiplier, 5),
|
|
}
|
|
clean_table()
|
|
end
|
|
|
|
function Public.add_boss_unit(unit, health_multiplier, health_bar_size)
|
|
if not health_multiplier then health_multiplier = global.biter_health_boost end
|
|
if not health_bar_size then health_bar_size = 0.5 end
|
|
local health = math_floor(unit.prototype.max_health * health_multiplier)
|
|
global.biter_health_boost_units[unit.unit_number] = {
|
|
health,
|
|
math_round(1 / health_multiplier, 5),
|
|
{max_health = health, healthbar_id = create_boss_healthbar(unit, health_bar_size), last_update = game.tick},
|
|
}
|
|
clean_table()
|
|
end
|
|
|
|
local function on_entity_damaged(event)
|
|
local biter = event.entity
|
|
if not (biter and biter.valid) then return end
|
|
if biter.type ~= "unit" then return end
|
|
if event.final_damage_amount == 0 then return end
|
|
|
|
local biter_health_boost_units = global.biter_health_boost_units
|
|
|
|
local unit_number = biter.unit_number
|
|
|
|
--Create new health pool
|
|
local health_pool = biter_health_boost_units[unit_number]
|
|
if not health_pool then
|
|
if global.biter_health_boost_forces[biter.force.index] then
|
|
Public.add_unit(biter, global.biter_health_boost_forces[biter.force.index])
|
|
else
|
|
Public.add_unit(biter, global.biter_health_boost)
|
|
end
|
|
health_pool = biter_health_boost_units[unit_number]
|
|
end
|
|
|
|
--Process boss unit health bars
|
|
local boss = health_pool[3]
|
|
if boss then
|
|
if boss.last_update + 10 < game.tick then
|
|
set_boss_healthbar(health_pool[1], boss.max_health, boss.healthbar_id)
|
|
boss.last_update = game.tick
|
|
end
|
|
end
|
|
|
|
--Calculate current actual health, accounting for regeneration
|
|
local current_health = biter.health * (1 / health_pool[2])
|
|
|
|
--Reduce health pool
|
|
health_pool[1] = current_health - event.final_damage_amount
|
|
|
|
--Set entity health relative to health pool
|
|
biter.health = health_pool[1] * health_pool[2]
|
|
|
|
--Proceed to kill entity if health is 0
|
|
if biter.health > 0 then return end
|
|
|
|
if event.cause then
|
|
if event.cause.valid then
|
|
event.entity.die(event.cause.force, event.cause)
|
|
return
|
|
end
|
|
end
|
|
biter.die(biter.force)
|
|
end
|
|
|
|
local function on_init()
|
|
global.biter_health_boost = 1
|
|
global.biter_health_boost_forces = {}
|
|
global.biter_health_boost_units = {}
|
|
global.biter_health_boost_count = 0
|
|
end
|
|
|
|
local event = require 'utils.event'
|
|
event.on_init(on_init)
|
|
event.add(defines.events.on_entity_damaged, on_entity_damaged)
|
|
|
|
return Public
|