mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-01-04 00:15:45 +02:00
724 lines
30 KiB
Lua
724 lines
30 KiB
Lua
local Event = require 'utils.event'
|
|
local ScenarioTable = require 'maps.scrap_towny_ffa.table'
|
|
|
|
local Public = {}
|
|
local math_floor = math.floor
|
|
local math_log10 = math.log10
|
|
|
|
local biters = {
|
|
[1] = 'small-biter',
|
|
[2] = 'medium-biter',
|
|
[3] = 'big-biter',
|
|
[4] = 'behemoth-biter'
|
|
}
|
|
|
|
local spitters = {
|
|
[1] = 'small-spitter',
|
|
[2] = 'medium-spitter',
|
|
[3] = 'big-spitter',
|
|
[4] = 'behemoth-spitter'
|
|
}
|
|
|
|
local worms = {
|
|
[1] = 'small-worm-turret',
|
|
[2] = 'medium-worm-turret',
|
|
[3] = 'big-worm-turret',
|
|
[4] = 'behemoth-worm-turret'
|
|
}
|
|
|
|
-- evolution max distance in tiles
|
|
local max_evolution_distance = 1024
|
|
local max_pollution_behemoth = 256
|
|
local max_pollution_big = 64
|
|
local max_pollution_medium = 16
|
|
-- max_factor < 1.0 means technology sum of weights will be greater than 1.0
|
|
local max_factor = 0.8
|
|
|
|
-- technology weights (biter, spitter, worm)
|
|
local technology_weights = {
|
|
['advanced-electronics'] = {biter = 1, spitter = 1, worm = 1},
|
|
['advanced-electronics-2'] = {biter = 1, spitter = 1, worm = 1},
|
|
['advanced-material-processing'] = {biter = 1, spitter = 1, worm = 1},
|
|
['advanced-material-processing-2'] = {biter = 1, spitter = 1, worm = 1},
|
|
['advanced-oil-processing'] = {biter = 1, spitter = 1, worm = 1},
|
|
['artillery'] = {biter = 1, spitter = 1, worm = 1},
|
|
['artillery-shell-range-1'] = {biter = 1, spitter = 1, worm = 1},
|
|
['artillery-shell-speed-1'] = {biter = 1, spitter = 1, worm = 1},
|
|
['atomic-bomb'] = {biter = 1, spitter = 1, worm = 1},
|
|
['automated-rail-transportation'] = {biter = 1, spitter = 1, worm = 1},
|
|
['automation'] = {biter = 1, spitter = 1, worm = 1},
|
|
['automation-2'] = {biter = 1, spitter = 1, worm = 1},
|
|
['automation-3'] = {biter = 1, spitter = 1, worm = 1},
|
|
['automobilism'] = {biter = 1, spitter = 1, worm = 1},
|
|
['battery'] = {biter = 1, spitter = 1, worm = 1},
|
|
['battery-equipment'] = {biter = 1, spitter = 1, worm = 1},
|
|
['battery-mk2-equipment'] = {biter = 1, spitter = 1, worm = 1},
|
|
['belt-immunity-equipment'] = {biter = 1, spitter = 1, worm = 1},
|
|
['braking-force-1'] = {biter = 1, spitter = 1, worm = 1},
|
|
['braking-force-2'] = {biter = 1, spitter = 1, worm = 1},
|
|
['braking-force-3'] = {biter = 1, spitter = 1, worm = 1},
|
|
['braking-force-4'] = {biter = 1, spitter = 1, worm = 1},
|
|
['braking-force-5'] = {biter = 1, spitter = 1, worm = 1},
|
|
['braking-force-6'] = {biter = 1, spitter = 1, worm = 1},
|
|
['braking-force-7'] = {biter = 1, spitter = 1, worm = 1},
|
|
['chemical-science-pack'] = {biter = 125, spitter = 125, worm = 125},
|
|
['circuit-network'] = {biter = 1, spitter = 1, worm = 1},
|
|
['cliff-explosives'] = {biter = 1, spitter = 1, worm = 1},
|
|
['coal-liquefaction'] = {biter = 1, spitter = 1, worm = 1},
|
|
['concrete'] = {biter = 1, spitter = 1, worm = 1},
|
|
['construction-robotics'] = {biter = 1, spitter = 1, worm = 1},
|
|
['defender'] = {biter = 1, spitter = 1, worm = 1},
|
|
['destroyer'] = {biter = 1, spitter = 1, worm = 1},
|
|
['discharge-defense-equipment'] = {biter = 5, spitter = 5, worm = 5},
|
|
['distractor'] = {biter = 1, spitter = 1, worm = 1},
|
|
['effect-transmission'] = {biter = 1, spitter = 1, worm = 1},
|
|
['effectivity-module'] = {biter = 1, spitter = 1, worm = 1},
|
|
['effectivity-module-2'] = {biter = 1, spitter = 1, worm = 1},
|
|
['effectivity-module-3'] = {biter = 1, spitter = 1, worm = 1},
|
|
['electric-energy-accumulators'] = {biter = 1, spitter = 1, worm = 1},
|
|
['electric-energy-distribution-1'] = {biter = 1, spitter = 1, worm = 1},
|
|
['electric-energy-distribution-2'] = {biter = 1, spitter = 1, worm = 1},
|
|
['electric-engine'] = {biter = 1, spitter = 1, worm = 1},
|
|
['electronics'] = {biter = 1, spitter = 1, worm = 1},
|
|
['energy-shield-equipment'] = {biter = 5, spitter = 5, worm = 5},
|
|
['energy-shield-mk2-equipment'] = {biter = 5, spitter = 5, worm = 5},
|
|
['energy-weapons-damage-1'] = {biter = 5, spitter = 5, worm = 5},
|
|
['energy-weapons-damage-2'] = {biter = 5, spitter = 5, worm = 5},
|
|
['energy-weapons-damage-3'] = {biter = 5, spitter = 5, worm = 5},
|
|
['energy-weapons-damage-4'] = {biter = 5, spitter = 5, worm = 5},
|
|
['energy-weapons-damage-5'] = {biter = 5, spitter = 5, worm = 5},
|
|
['energy-weapons-damage-6'] = {biter = 5, spitter = 5, worm = 5},
|
|
['energy-weapons-damage-7'] = {biter = 5, spitter = 5, worm = 5},
|
|
['engine'] = {biter = 1, spitter = 1, worm = 1},
|
|
['exoskeleton-equipment'] = {biter = 5, spitter = 5, worm = 5},
|
|
['explosive-rocketry'] = {biter = 1, spitter = 1, worm = 1},
|
|
['explosives'] = {biter = 5, spitter = 5, worm = 5},
|
|
['fast-inserter'] = {biter = 1, spitter = 1, worm = 1},
|
|
['flamethrower'] = {biter = 5, spitter = 5, worm = 5},
|
|
['flammables'] = {biter = 1, spitter = 1, worm = 1},
|
|
['fluid-handling'] = {biter = 1, spitter = 1, worm = 1},
|
|
['fluid-wagon'] = {biter = 1, spitter = 1, worm = 1},
|
|
['follower-robot-count-1'] = {biter = 1, spitter = 1, worm = 1},
|
|
['follower-robot-count-2'] = {biter = 1, spitter = 1, worm = 1},
|
|
['follower-robot-count-3'] = {biter = 1, spitter = 1, worm = 1},
|
|
['follower-robot-count-4'] = {biter = 1, spitter = 1, worm = 1},
|
|
['follower-robot-count-5'] = {biter = 1, spitter = 1, worm = 1},
|
|
['follower-robot-count-6'] = {biter = 1, spitter = 1, worm = 1},
|
|
['follower-robot-count-7'] = {biter = 1, spitter = 1, worm = 1},
|
|
['fusion-reactor-equipment'] = {biter = 1, spitter = 1, worm = 1},
|
|
['gate'] = {biter = 1, spitter = 1, worm = 1},
|
|
['gun-turret'] = {biter = 1, spitter = 1, worm = 1},
|
|
['heavy-armor'] = {biter = 5, spitter = 5, worm = 5},
|
|
['inserter-capacity-bonus-1'] = {biter = 1, spitter = 1, worm = 1},
|
|
['inserter-capacity-bonus-3'] = {biter = 1, spitter = 1, worm = 1},
|
|
['inserter-capacity-bonus-4'] = {biter = 1, spitter = 1, worm = 1},
|
|
['inserter-capacity-bonus-5'] = {biter = 1, spitter = 1, worm = 1},
|
|
['inserter-capacity-bonus-6'] = {biter = 1, spitter = 1, worm = 1},
|
|
['inserter-capacity-bonus-7'] = {biter = 1, spitter = 1, worm = 1},
|
|
['kovarex-enrichment-process'] = {biter = 1, spitter = 1, worm = 1},
|
|
['land-mine'] = {biter = 5, spitter = 5, worm = 5},
|
|
['landfill'] = {biter = 1, spitter = 1, worm = 1},
|
|
['laser'] = {biter = 5, spitter = 5, worm = 5},
|
|
['laser-shooting-speed-1'] = {biter = 5, spitter = 5, worm = 5},
|
|
['laser-shooting-speed-2'] = {biter = 5, spitter = 5, worm = 5},
|
|
['laser-shooting-speed-3'] = {biter = 5, spitter = 5, worm = 5},
|
|
['laser-shooting-speed-4'] = {biter = 5, spitter = 5, worm = 5},
|
|
['laser-shooting-speed-5'] = {biter = 5, spitter = 5, worm = 5},
|
|
['laser-shooting-speed-6'] = {biter = 5, spitter = 5, worm = 5},
|
|
['laser-shooting-speed-7'] = {biter = 5, spitter = 5, worm = 5},
|
|
['laser-turret'] = {biter = 5, spitter = 5, worm = 5},
|
|
['logistic-robotics'] = {biter = 1, spitter = 1, worm = 1},
|
|
['logistic-science-pack'] = {biter = 25, spitter = 25, worm = 25},
|
|
['logistic-system'] = {biter = 1, spitter = 1, worm = 1},
|
|
['logistics'] = {biter = 1, spitter = 1, worm = 1},
|
|
['logistics-2'] = {biter = 1, spitter = 1, worm = 1},
|
|
['logistics-3'] = {biter = 1, spitter = 1, worm = 1},
|
|
['low-density-structure'] = {biter = 1, spitter = 1, worm = 1},
|
|
['lubricant'] = {biter = 1, spitter = 1, worm = 1},
|
|
['military'] = {biter = 5, spitter = 5, worm = 5},
|
|
['military-2'] = {biter = 5, spitter = 5, worm = 5},
|
|
['military-3'] = {biter = 5, spitter = 5, worm = 51},
|
|
['military-4'] = {biter = 5, spitter = 5, worm = 5},
|
|
['military-science-pack'] = {biter = 50, spitter = 50, worm = 50},
|
|
['mining-productivity-1'] = {biter = 1, spitter = 1, worm = 1},
|
|
['mining-productivity-2'] = {biter = 1, spitter = 1, worm = 1},
|
|
['mining-productivity-3'] = {biter = 1, spitter = 1, worm = 1},
|
|
['mining-productivity-4'] = {biter = 1, spitter = 1, worm = 1},
|
|
['modular-armor'] = {biter = 1, spitter = 1, worm = 1},
|
|
['modules'] = {biter = 1, spitter = 1, worm = 1},
|
|
['night-vision-equipment'] = {biter = 1, spitter = 1, worm = 1},
|
|
['nuclear-fuel-reprocessing'] = {biter = 1, spitter = 1, worm = 1},
|
|
['nuclear-power'] = {biter = 1, spitter = 1, worm = 1},
|
|
['oil-processing'] = {biter = 1, spitter = 1, worm = 1},
|
|
['optics'] = {biter = 1, spitter = 1, worm = 1},
|
|
['personal-laser-defense-equipment'] = {biter = 5, spitter = 5, worm = 5},
|
|
['personal-roboport-equipment'] = {biter = 1, spitter = 1, worm = 1},
|
|
['personal-roboport-mk2-equipment'] = {biter = 1, spitter = 1, worm = 1},
|
|
['physical-projectile-damage-1'] = {biter = 5, spitter = 5, worm = 5},
|
|
['physical-projectile-damage-2'] = {biter = 5, spitter = 5, worm = 5},
|
|
['physical-projectile-damage-3'] = {biter = 5, spitter = 5, worm = 5},
|
|
['physical-projectile-damage-4'] = {biter = 5, spitter = 5, worm = 5},
|
|
['physical-projectile-damage-5'] = {biter = 5, spitter = 5, worm = 5},
|
|
['physical-projectile-damage-6'] = {biter = 5, spitter = 5, worm = 5},
|
|
['physical-projectile-damage-7'] = {biter = 5, spitter = 5, worm = 5},
|
|
['plastics'] = {biter = 1, spitter = 1, worm = 1},
|
|
['power-armor'] = {biter = 5, spitter = 5, worm = 5},
|
|
['power-armor-mk2'] = {biter = 5, spitter = 5, worm = 5},
|
|
['production-science-pack'] = {biter = 250, spitter = 250, worm = 250},
|
|
['productivity-module'] = {biter = 1, spitter = 1, worm = 1},
|
|
['productivity-module-2'] = {biter = 1, spitter = 1, worm = 1},
|
|
['productivity-module-3'] = {biter = 1, spitter = 1, worm = 1},
|
|
['rail-signals'] = {biter = 1, spitter = 1, worm = 1},
|
|
['railway'] = {biter = 1, spitter = 1, worm = 1},
|
|
['refined-flammables-1'] = {biter = 5, spitter = 5, worm = 5},
|
|
['refined-flammables-2'] = {biter = 5, spitter = 5, worm = 51},
|
|
['refined-flammables-3'] = {biter = 5, spitter = 5, worm = 5},
|
|
['refined-flammables-4'] = {biter = 5, spitter = 5, worm = 5},
|
|
['refined-flammables-5'] = {biter = 5, spitter = 5, worm = 5},
|
|
['refined-flammables-6'] = {biter = 5, spitter = 5, worm = 5},
|
|
['refined-flammables-7'] = {biter = 5, spitter = 5, worm = 51},
|
|
['research-speed-1'] = {biter = 1, spitter = 1, worm = 1},
|
|
['research-speed-2'] = {biter = 1, spitter = 1, worm = 1},
|
|
['research-speed-3'] = {biter = 1, spitter = 1, worm = 1},
|
|
['research-speed-4'] = {biter = 1, spitter = 1, worm = 1},
|
|
['research-speed-5'] = {biter = 1, spitter = 1, worm = 1},
|
|
['research-speed-6'] = {biter = 1, spitter = 1, worm = 1},
|
|
['robotics'] = {biter = 1, spitter = 1, worm = 1},
|
|
['rocket-control-unit'] = {biter = 1, spitter = 1, worm = 1},
|
|
['rocket-fuel'] = {biter = 1, spitter = 1, worm = 1},
|
|
['rocket-silo'] = {biter = 1, spitter = 1, worm = 1},
|
|
['rocketry'] = {biter = 1, spitter = 1, worm = 1},
|
|
['solar-energy'] = {biter = 1, spitter = 1, worm = 1},
|
|
['solar-panel-equipment'] = {biter = 1, spitter = 1, worm = 1},
|
|
['space-science-pack'] = {biter = 1000, spitter = 1000, worm = 1000},
|
|
['speed-module'] = {biter = 1, spitter = 1, worm = 1},
|
|
['speed-module-2'] = {biter = 1, spitter = 1, worm = 1},
|
|
['speed-module-3'] = {biter = 1, spitter = 1, worm = 1},
|
|
['spidertron'] = {biter = 1, spitter = 1, worm = 1},
|
|
['stack-inserter'] = {biter = 1, spitter = 1, worm = 1},
|
|
['steel-axe'] = {biter = 1, spitter = 1, worm = 1},
|
|
['steel-processing'] = {biter = 1, spitter = 1, worm = 1},
|
|
['stone-wall'] = {biter = 1, spitter = 1, worm = 1},
|
|
['stronger-explosives-1'] = {biter = 5, spitter = 5, worm = 5},
|
|
['stronger-explosives-2'] = {biter = 5, spitter = 5, worm = 5},
|
|
['stronger-explosives-3'] = {biter = 5, spitter = 5, worm = 5},
|
|
['stronger-explosives-4'] = {biter = 5, spitter = 5, worm = 5},
|
|
['stronger-explosives-5'] = {biter = 5, spitter = 5, worm = 5},
|
|
['stronger-explosives-6'] = {biter = 5, spitter = 5, worm = 5},
|
|
['stronger-explosives-7'] = {biter = 5, spitter = 5, worm = 51},
|
|
['sulfur-processing'] = {biter = 1, spitter = 1, worm = 1},
|
|
['tank'] = {biter = 1, spitter = 1, worm = 1},
|
|
['toolbelt'] = {biter = 1, spitter = 1, worm = 1},
|
|
['uranium-ammo'] = {biter = 1, spitter = 1, worm = 1},
|
|
['uranium-processing'] = {biter = 1, spitter = 1, worm = 1},
|
|
['utility-science-pack'] = {biter = 500, spitter = 500, worm = 500},
|
|
['weapon-shooting-speed-1'] = {biter = 5, spitter = 5, worm = 5},
|
|
['weapon-shooting-speed-2'] = {biter = 5, spitter = 5, worm = 5},
|
|
['weapon-shooting-speed-3'] = {biter = 5, spitter = 5, worm = 5},
|
|
['weapon-shooting-speed-4'] = {biter = 5, spitter = 5, worm = 5},
|
|
['weapon-shooting-speed-5'] = {biter = 5, spitter = 5, worm = 5},
|
|
['weapon-shooting-speed-6'] = {biter = 5, spitter = 5, worm = 5},
|
|
['worker-robots-speed-1'] = {biter = 1, spitter = 1, worm = 1},
|
|
['worker-robots-speed-2'] = {biter = 1, spitter = 1, worm = 1},
|
|
['worker-robots-speed-3'] = {biter = 1, spitter = 1, worm = 1},
|
|
['worker-robots-speed-4'] = {biter = 1, spitter = 1, worm = 1},
|
|
['worker-robots-speed-5'] = {biter = 1, spitter = 1, worm = 1},
|
|
['worker-robots-speed-6'] = {biter = 1, spitter = 1, worm = 1},
|
|
['worker-robots-storage-1'] = {biter = 1, spitter = 1, worm = 1},
|
|
['worker-robots-storage-2'] = {biter = 1, spitter = 1, worm = 1},
|
|
['worker-robots-storage-3'] = {biter = 1, spitter = 1, worm = 1}
|
|
}
|
|
|
|
local max_biter_weight = 0
|
|
local max_spitter_weight = 0
|
|
local max_worm_weight = 0
|
|
for _, weight in pairs(technology_weights) do
|
|
max_biter_weight = max_biter_weight + weight.biter
|
|
max_spitter_weight = max_spitter_weight + weight.spitter
|
|
max_worm_weight = max_worm_weight + weight.worm
|
|
end
|
|
max_biter_weight = max_biter_weight * max_factor
|
|
max_spitter_weight = max_spitter_weight * max_factor
|
|
max_worm_weight = max_worm_weight * max_factor
|
|
|
|
local function get_unit_size(evolution)
|
|
-- returns a value 1-4 that represents the unit size
|
|
|
|
-- basically evo values of: 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%
|
|
-- -----------------------------------------------------------------------------------
|
|
-- small unit chances are 100% 60% 40% 30% 20% 15% 7.5% 0% 0% 0% 0%
|
|
-- medium unit chances are 0% 40% 40% 30% 20% 15% 7.5% 12.5% 25% 0% 0%
|
|
-- big unit chances are 0% 0% 20% 40% 60% 60% 75% 75% 50% 50% 0%
|
|
-- behemoth unit chances are 0% 0% 0% 0% 0% 10% 10% 12.5% 25% 50% 100%
|
|
-- and curve accordingly in between evo values
|
|
|
|
-- magic stuff happens here
|
|
-- 0%
|
|
if (evolution < 0.1) then
|
|
return 1
|
|
end
|
|
-- 10%
|
|
if (evolution >= 0.1 and evolution < 0.2) then
|
|
local r = math.random()
|
|
if r < 0.6 then
|
|
return 1
|
|
end
|
|
return 2
|
|
end
|
|
-- 20%
|
|
if (evolution >= 0.2 and evolution < 0.3) then
|
|
local r = math.random()
|
|
if r < 0.8 then
|
|
if r < 0.4 then
|
|
return 1
|
|
else
|
|
return 2
|
|
end
|
|
end
|
|
return 3
|
|
end
|
|
-- 30%
|
|
if (evolution >= 0.3 and evolution < 0.4) then
|
|
local r = math.random()
|
|
if r < 0.6 then
|
|
if r < 0.3 then
|
|
return 1
|
|
else
|
|
return 2
|
|
end
|
|
end
|
|
return 3
|
|
end
|
|
-- 40%
|
|
if (evolution >= 0.4 and evolution < 0.5) then
|
|
local r = math.random()
|
|
if r < 0.4 then
|
|
if r < 0.2 then
|
|
return 1
|
|
else
|
|
return 2
|
|
end
|
|
end
|
|
return 3
|
|
end
|
|
-- 50%
|
|
if (evolution >= 0.5 and evolution < 0.6) then
|
|
local r = math.random()
|
|
if r < 0.9 then
|
|
if r < 0.3 then
|
|
if r < 0.15 then
|
|
return 1
|
|
else
|
|
return 2
|
|
end
|
|
end
|
|
return 3
|
|
end
|
|
return 4
|
|
end
|
|
-- 60%
|
|
if (evolution >= 0.60 and evolution < 0.70) then
|
|
local r = math.random()
|
|
if r < 0.9 then
|
|
if r < 0.15 then
|
|
if r < 0.075 then
|
|
return 1
|
|
else
|
|
return 2
|
|
end
|
|
end
|
|
return 3
|
|
end
|
|
return 4
|
|
end
|
|
-- 70%
|
|
if (evolution >= 0.70 and evolution < 0.80) then
|
|
local r = math.random()
|
|
if r < 0.985 then
|
|
if r < 0.125 then
|
|
return 2
|
|
else
|
|
return 3
|
|
end
|
|
end
|
|
return 4
|
|
end
|
|
-- 80%
|
|
if (evolution >= 0.80 and evolution < 0.90) then
|
|
local r = math.random()
|
|
if r < 0.75 then
|
|
if r < 0.25 then
|
|
return 2
|
|
else
|
|
return 3
|
|
end
|
|
end
|
|
return 4
|
|
end
|
|
-- 90%
|
|
if (evolution >= 0.90 and evolution < 1) then
|
|
local r = math.random()
|
|
if r < 0.5 then
|
|
return 3
|
|
end
|
|
return 4
|
|
end
|
|
-- 100%
|
|
if (evolution >= 1.0) then
|
|
return 4
|
|
end
|
|
end
|
|
|
|
local function distance_squared(pos1, pos2)
|
|
-- calculate the distance squared
|
|
local dx = pos1.x - pos2.x
|
|
local dy = pos1.y - pos2.y
|
|
local d2 = dx * dx + dy * dy
|
|
return d2
|
|
end
|
|
|
|
-- calculate the relative evolution based on evolution factor (0.0-1.0) and distance factor (0.0-1.0)
|
|
local function calculate_relative_evolution(evolution_factor, distance_factor)
|
|
-- distance factor will be from 0.0 to 1.0 but drop off dramatically towards zero
|
|
local log_distance_factor = math_log10(distance_factor * 10 + 1)
|
|
local evo = log_distance_factor * evolution_factor
|
|
if evo < 0.0 then
|
|
evo = 0.0
|
|
end
|
|
if evo > 1.0 then
|
|
evo = 1.0
|
|
end
|
|
return evo
|
|
end
|
|
|
|
local function get_relative_biter_evolution(position)
|
|
local this = ScenarioTable.get_table()
|
|
local relative_evolution = 0.0
|
|
local max_d2 = max_evolution_distance * max_evolution_distance
|
|
-- for all of the teams
|
|
local teams = this.town_centers
|
|
for _, town_center in pairs(teams) do
|
|
local market = town_center.market
|
|
if market == nil or not market.valid then
|
|
return relative_evolution
|
|
end
|
|
-- calculate the distance squared
|
|
local d2 = distance_squared(position, market.position)
|
|
if d2 < max_d2 then
|
|
-- get the distance factor (0.0-1.0)
|
|
local distance_factor = 1.0 - d2 / max_d2
|
|
-- get the evolution factor (0.0-1.0)
|
|
if not town_center.evolution then
|
|
town_center.evolution = {}
|
|
end
|
|
if town_center.evolution.biters == nil then
|
|
town_center.evolution.biters = 0.0
|
|
end
|
|
local evo = calculate_relative_evolution(town_center.evolution.biters, distance_factor)
|
|
-- get the highest of the relative evolutions of each town
|
|
relative_evolution = math.max(relative_evolution, evo)
|
|
end
|
|
end
|
|
return relative_evolution
|
|
end
|
|
|
|
local function get_relative_spitter_evolution(position)
|
|
local this = ScenarioTable.get_table()
|
|
local relative_evolution = 0.0
|
|
local max_d2 = max_evolution_distance * max_evolution_distance
|
|
-- for all of the teams
|
|
local teams = this.town_centers
|
|
for _, town_center in pairs(teams) do
|
|
local market = town_center.market
|
|
if market == nil or not market.valid then
|
|
return relative_evolution
|
|
end
|
|
-- calculate the distance squared
|
|
local d2 = distance_squared(position, market.position)
|
|
if d2 < max_d2 then
|
|
-- get the distance factor (0.0-1.0)
|
|
local distance_factor = 1.0 - d2 / max_d2
|
|
-- get the evolution factor (0.0-1.0)
|
|
if not town_center.evolution then
|
|
town_center.evolution = {}
|
|
end
|
|
if town_center.evolution.spitters == nil then
|
|
town_center.evolution.spitters = 0.0
|
|
end
|
|
local evo = calculate_relative_evolution(town_center.evolution.spitters, distance_factor)
|
|
-- get the highest of the relative evolutions of each town
|
|
relative_evolution = math.max(relative_evolution, evo)
|
|
end
|
|
end
|
|
return relative_evolution
|
|
end
|
|
|
|
local function get_relative_worm_evolution(position)
|
|
local this = ScenarioTable.get_table()
|
|
local relative_evolution = 0.0
|
|
local max_d2 = max_evolution_distance * max_evolution_distance
|
|
-- for all of the teams
|
|
local teams = this.town_centers
|
|
for _, town_center in pairs(teams) do
|
|
local market = town_center.market
|
|
if market == nil or not market.valid then
|
|
return relative_evolution
|
|
end
|
|
-- calculate the distance squared
|
|
local d2 = distance_squared(position, market.position)
|
|
if d2 < max_d2 then
|
|
-- get the distance factor (0.0-1.0)
|
|
local distance_factor = 1.0 - d2 / max_d2
|
|
-- get the evolution factor (0.0-1.0)
|
|
if not town_center.evolution then
|
|
town_center.evolution = {}
|
|
end
|
|
if town_center.evolution.worms == nil then
|
|
town_center.evolution.worms = 0.0
|
|
end
|
|
local evo = calculate_relative_evolution(town_center.evolution.worms, distance_factor)
|
|
-- get the highest of the relative evolutions of each town
|
|
relative_evolution = math.max(relative_evolution, evo)
|
|
end
|
|
end
|
|
return relative_evolution
|
|
end
|
|
|
|
function Public.get_highest_evolution()
|
|
local this = ScenarioTable.get_table()
|
|
local max_evo = 0
|
|
for _, town_center in pairs(this.town_centers) do
|
|
if town_center.evolution.worms > max_evo then
|
|
max_evo = town_center.evolution.worms
|
|
end
|
|
end
|
|
return max_evo
|
|
end
|
|
|
|
function Public.get_evolution(position)
|
|
return get_relative_biter_evolution(position)
|
|
end
|
|
|
|
function Public.get_biter_evolution(entity)
|
|
return get_relative_biter_evolution(entity.position)
|
|
end
|
|
|
|
function Public.get_spitter_evolution(entity)
|
|
return get_relative_spitter_evolution(entity.position)
|
|
end
|
|
|
|
function Public.get_worm_evolution(entity)
|
|
return get_relative_worm_evolution(entity.position)
|
|
end
|
|
|
|
local function get_nearby_location(position, surface, radius, entity_name)
|
|
return surface.find_non_colliding_position(entity_name, position, radius, 0.5, false)
|
|
end
|
|
|
|
local function set_biter_type(entity)
|
|
-- checks nearby evolution levels for bases and returns an appropriately leveled type
|
|
local position = entity.position
|
|
local evo = get_relative_biter_evolution(position)
|
|
local unit_size = get_unit_size(evo)
|
|
local entity_name = biters[unit_size]
|
|
if entity.name == entity_name then
|
|
return
|
|
end
|
|
local surface = entity.surface
|
|
local pollution = surface.get_pollution(position)
|
|
local behemoth = math_floor(pollution / max_pollution_behemoth)
|
|
local big = math_floor((pollution - (behemoth * max_pollution_behemoth)) / max_pollution_big)
|
|
local medium = math_floor((pollution - (behemoth * max_pollution_behemoth) - (big * max_pollution_big)) / max_pollution_medium)
|
|
local small = pollution - (behemoth * max_pollution_behemoth) - (big * max_pollution_big) - (medium * max_pollution_medium) + 1
|
|
|
|
if entity.valid then
|
|
for _ = 1, behemoth do
|
|
local e = surface.create_entity({name = biters[4], position = get_nearby_location(position, surface, 5, biters[4])})
|
|
e.copy_settings(entity)
|
|
e.ai_settings.allow_try_return_to_spawner = true
|
|
end
|
|
for _ = 1, big do
|
|
local e = surface.create_entity({name = biters[3], position = get_nearby_location(position, surface, 5, biters[3])})
|
|
e.copy_settings(entity)
|
|
e.ai_settings.allow_try_return_to_spawner = true
|
|
end
|
|
for _ = 1, medium do
|
|
local e = surface.create_entity({name = biters[2], position = get_nearby_location(position, surface, 5, biters[2])})
|
|
e.copy_settings(entity)
|
|
e.ai_settings.allow_try_return_to_spawner = true
|
|
end
|
|
for _ = 1, small do
|
|
local e = surface.create_entity({name = biters[1], position = get_nearby_location(position, surface, 5, biters[1])})
|
|
e.copy_settings(entity)
|
|
e.ai_settings.allow_try_return_to_spawner = true
|
|
end
|
|
local e = surface.create_entity({name = entity_name, position = get_nearby_location(position, surface, 5, entity_name)})
|
|
e.copy_settings(entity)
|
|
e.ai_settings.allow_try_return_to_spawner = true
|
|
entity.destroy()
|
|
--log("spawned " .. entity_name)
|
|
end
|
|
end
|
|
|
|
local function set_spitter_type(entity)
|
|
-- checks nearby evolution levels for bases and returns an appropriately leveled type
|
|
local position = entity.position
|
|
local evo = get_relative_spitter_evolution(position)
|
|
local unit_size = get_unit_size(evo)
|
|
local entity_name = spitters[unit_size]
|
|
if entity.name == entity_name then
|
|
return
|
|
end
|
|
local surface = entity.surface
|
|
local pollution = surface.get_pollution(position)
|
|
local behemoth = math_floor(pollution / max_pollution_behemoth)
|
|
local big = math_floor((pollution - (behemoth * max_pollution_behemoth)) / max_pollution_big)
|
|
local medium = math_floor((pollution - (behemoth * max_pollution_behemoth) - (big * max_pollution_big)) / max_pollution_medium)
|
|
local small = pollution - (behemoth * max_pollution_behemoth) - (big * max_pollution_big) - (medium * max_pollution_medium) + 1
|
|
|
|
if entity.valid then
|
|
for _ = 1, behemoth do
|
|
local e = surface.create_entity({name = spitters[4], position = get_nearby_location(position, surface, 5, spitters[4])})
|
|
e.copy_settings(entity)
|
|
e.ai_settings.allow_try_return_to_spawner = true
|
|
end
|
|
for _ = 1, big do
|
|
local e = surface.create_entity({name = spitters[3], position = get_nearby_location(position, surface, 5, spitters[3])})
|
|
e.copy_settings(entity)
|
|
e.ai_settings.allow_try_return_to_spawner = true
|
|
end
|
|
for _ = 1, medium do
|
|
local e = surface.create_entity({name = spitters[2], position = get_nearby_location(position, surface, 5, spitters[2])})
|
|
e.copy_settings(entity)
|
|
e.ai_settings.allow_try_return_to_spawner = true
|
|
end
|
|
for _ = 1, small do
|
|
local e = surface.create_entity({name = spitters[1], position = get_nearby_location(position, surface, 5, spitters[1])})
|
|
e.copy_settings(entity)
|
|
e.ai_settings.allow_try_return_to_spawner = true
|
|
end
|
|
local e = surface.create_entity({name = entity_name, position = get_nearby_location(position, surface, 5, entity_name)})
|
|
e.copy_settings(entity)
|
|
e.ai_settings.allow_try_return_to_spawner = true
|
|
entity.destroy()
|
|
--log("spawned " .. entity_name)
|
|
end
|
|
end
|
|
|
|
local function set_worm_type(entity)
|
|
-- checks nearby evolution levels for bases and returns an appropriately leveled type
|
|
local position = entity.position
|
|
local evo = get_relative_worm_evolution(position)
|
|
local unit_size = get_unit_size(evo)
|
|
local entity_name = worms[unit_size]
|
|
if entity.name == entity_name then
|
|
return
|
|
end
|
|
local surface = entity.surface
|
|
if entity.valid then
|
|
entity.destroy()
|
|
surface.create_entity({name = entity_name, position = position})
|
|
--log("spawned " .. entity_name)
|
|
end
|
|
end
|
|
|
|
local function is_biter(entity)
|
|
if entity == nil or not entity.valid then
|
|
return false
|
|
end
|
|
if entity.name == 'small-biter' or entity.name == 'medium-biter' or entity.name == 'big-biter' or entity.name == 'behemoth-biter' then
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function is_spitter(entity)
|
|
if entity == nil or not entity.valid then
|
|
return false
|
|
end
|
|
if entity.name == 'small-spitter' or entity.name == 'medium-spitter' or entity.name == 'big-spitter' or entity.name == 'behemoth-spitter' then
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function is_worm(entity)
|
|
if entity == nil or not entity.valid then
|
|
return false
|
|
end
|
|
if entity.name == 'small-worm-turret' or entity.name == 'medium-worm-turret' or entity.name == 'big-worm-turret' or entity.name == 'behemoth-worm-turret' then
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
-- update evolution based on research completed (weighted)
|
|
-- sets the evolution to a value from 0.0 to 1.0 based on research progress
|
|
local function update_evolution(force_name, technology)
|
|
if technology == nil then
|
|
return
|
|
end
|
|
local this = ScenarioTable.get_table()
|
|
local town_center = this.town_centers[force_name]
|
|
-- town_center is a reference to a global table
|
|
if not town_center then
|
|
return
|
|
end
|
|
-- initialize if not already
|
|
local evo = town_center.evolution
|
|
-- get the weights for this technology
|
|
local weight = technology_weights[technology]
|
|
if weight == nil then
|
|
log('no technology_weights for ' .. technology)
|
|
return
|
|
end
|
|
local biter_weight = weight.biter
|
|
local spitter_weight = weight.spitter
|
|
local worm_weight = weight.worm
|
|
-- update the evolution values (0.0 to 1.0)
|
|
-- max weights might be less than 1.0, to allow for evo > 1.0
|
|
local b = (biter_weight / max_biter_weight)
|
|
local s = (spitter_weight / max_spitter_weight)
|
|
local w = (worm_weight / max_worm_weight)
|
|
b = b + evo.biters
|
|
s = s + evo.spitters
|
|
w = w + evo.worms
|
|
evo.biters = b
|
|
evo.spitters = s
|
|
evo.worms = w
|
|
end
|
|
|
|
local function on_research_finished(event)
|
|
local research = event.research
|
|
local force = research.force
|
|
local technology = research.name
|
|
update_evolution(force.name, technology)
|
|
end
|
|
|
|
local function on_entity_spawned(event)
|
|
local entity = event.entity
|
|
-- check the unit type and handle appropriately
|
|
if is_biter(entity) then
|
|
set_biter_type(entity)
|
|
end
|
|
if is_spitter(entity) then
|
|
set_spitter_type(entity)
|
|
end
|
|
if is_worm(entity) then
|
|
set_worm_type(entity)
|
|
end
|
|
end
|
|
|
|
local function on_biter_base_built(event)
|
|
local entity = event.entity
|
|
if is_worm(entity) then
|
|
set_worm_type(entity)
|
|
end
|
|
end
|
|
|
|
Event.add(defines.events.on_research_finished, on_research_finished)
|
|
Event.add(defines.events.on_entity_spawned, on_entity_spawned)
|
|
Event.add(defines.events.on_biter_base_built, on_biter_base_built)
|
|
|
|
return Public
|