Aleksei-bird 7c9c708c92 Первый фикс
Пачки некоторых позиций увеличены
2024-03-01 20:54:33 +03:00

831 lines
30 KiB
Lua

-- Copyright (C) 2022 veden
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <https://www.gnu.org/licenses/>.
-- imports
local gui = require("libs/Gui")
--[[
Vanilla factors
time_factor
:: double
The amount evolution naturally progresses by every second. Defaults to 0.000004.
destroy_factor
:: double
The amount evolution progresses for every destroyed spawner. Defaults to 0.002.
pollution_factor
:: double
The amount evolution progresses for every unit of pollution. Defaults to 0.0000009.
Pollution production is the total pollution produced by buildings per tick, not the
pollution spreading on the map, so it is not reduced by trees or other absorbers.
e.g. : 10 boilers produce 300 pollution in one minute, raising the evolution factor
by around 0.027%.
The percentages are applied on the base of (1 - current_evolution_factor)². So
for instance destroying enemy spawners in the beginning of the game results in
increase of evolution factor by 0.002 (0.2%) while doing this when the evolution
factor is 0.5 the increase is only 0.0005 (0.05%).
This also means that the evolution factor approaches 1 asymptotically - generally,
increases past 0.9 or so are very slow and the number never actually reaches 1.0.
--]]
-- constants
local SETTINGS_TO_PERCENT = 1e-7
local SHORT_EVOLUTION_CHECK_DURATION = 5 * 60 * 60
local LONG_EVOLUTION_CHECK_DURATION = 30 * 60 * 60
local LONG_LONG_EVOLUTION_CHECK_DURATION = 60 * 60 * 60
local LOW_VALUE_PLAYER_STRUCTURES = {
"turret",
"ammo-turret",
"electric-turret",
"fluid-turret",
"artillery-turret",
"electric-pole"
}
local MEDIUM_VALUE_PLAYER_STRUCTURES = {
"solar-panel",
"accumulator",
"radar",
"storage-tank",
"container",
"logistic-container",
"lab"
}
local HIGH_VALUE_PLAYER_STRUCTURES = {
"assembling-machine",
"furnace",
"roboport",
"beacon",
"boiler",
"generator",
"mining-drill",
"reactor",
"rocket-silo"
}
-- imported functions
local sFind = string.find
local mMin = math.min
local mMax = math.max
local roundTo = gui.roundTo
local calculateDisplayValue = gui.calculateDisplayValue
-- local references
local world
-- module code
local function linearInterpolation(percent, min, max)
return ((max - min) * percent) + min
end
local function variableInterpolation(percent, min, max, exponent)
return ((max - min) * (percent^exponent)) + min
end
local function onStatsGrabPollution()
local pollutionStats = game.pollution_statistics
local counts = pollutionStats.output_counts
for name,count in pairs(counts) do
local previousCount = world.pollutionConsumed[name]
world.pollutionConsumed[name] = count
local delta
if not previousCount then
delta = count
else
delta = count - previousCount
end
if delta ~= 0 then
world.pollutionDeltas[name] = (world.pollutionDeltas[name] or 0) + delta
end
end
end
local function onStatsGrabTotalPollution()
if world.evolutionPerPollution ~= 0 then
local pollutionStats = game.pollution_statistics
local counts = pollutionStats.input_counts
for name,count in pairs(counts) do
local previousCount = world.pollutionProduced[name]
world.pollutionProduced[name] = count
local delta
if not previousCount then
delta = count
else
delta = count - previousCount
end
if delta ~= 0 then
world.pollutionDeltas["totalPollution"] = (world.pollutionDeltas["totalPollution"] or 0) + delta
end
end
end
end
local function onStatsGrabKill()
local killStats = game.forces.enemy.kill_count_statistics
local counts = killStats.output_counts
for name,count in pairs(counts) do
local previousCount = world.kills[name]
world.kills[name] = count
local delta
if not previousCount then
delta = count
else
delta = count - previousCount
end
if delta ~= 0 then
world.killDeltas[name] = (world.killDeltas[name] or 0) + delta
end
end
counts = killStats.input_counts
for name,count in pairs(counts) do
local previousCount = world.kills[name]
world.kills[name] = count
local delta
if not previousCount then
delta = count
else
delta = count - previousCount
end
if delta ~= 0 then
world.killDeltas[name] = (world.killDeltas[name] or 0) + delta
end
end
end
local function reset()
world.killDeltasIterator = nil
world.pollutionDeltasIterator = nil
world.kills = {}
world.killDeltas = {
["time"] = math.floor(game.tick / 60)
}
world.totalEvolution = 0
world.researchCompleted = 0
world.totalResearch = 0
world.ticksAccrued = 0
world.researchEvolutionMultiplier = 0
world.tickEvolutionMultiplier = 0
world.totalPostiveEvolution = 0
world.totalNegativeEvolution = 0
world.pollutionConsumed = {}
world.pollutionProduced = {}
world.pollutionDeltas = {}
world.stats = {
["tile"] = 0,
["tree"] = 0,
["dyingTree"] = 0,
["absorbed"] = 0,
["spawner"] = 0,
["hive"] = 0,
["unit"] = 0,
["worm"] = 0,
["totalPollution"] = 0,
["time"] = 0,
["evolutionMultiplier"] = 0,
["minimumEvolution"] = 0,
["researchEvolutionCap"] = 0,
["lowPlayer"] = 0,
["mediumPlayer"] = 0,
["highPlayer"] = 0
}
end
local function onModSettingsChange(event)
if event and (string.sub(event.setting, 1, #"rampant-evolution") ~= "rampant-evolution") then
return false
end
world.processingPerTick = settings.global["rampant-evolution--processingPerTick"].value
world.evolutionPerSpawnerAbsorbed = settings.global["rampant-evolution-evolutionPerSpawnerAbsorbed"].value * SETTINGS_TO_PERCENT
world.evolutionPerTreeAbsorbed = settings.global["rampant-evolution-evolutionPerTreeAbsorbed"].value * SETTINGS_TO_PERCENT
world.evolutionPerTreeDied = settings.global["rampant-evolution-evolutionPerTreeDied"].value * SETTINGS_TO_PERCENT
world.evolutionPerTileAbsorbed = settings.global["rampant-evolution-evolutionPerTileAbsorbed"].value * SETTINGS_TO_PERCENT
world.evolutionPerSpawnerKilled = settings.global["rampant-evolution-evolutionPerSpawnerKilled"].value * SETTINGS_TO_PERCENT
world.evolutionPerUnitKilled = settings.global["rampant-evolution-evolutionPerUnitKilled"].value * SETTINGS_TO_PERCENT
world.evolutionPerHiveKilled = settings.global["rampant-evolution-evolutionPerHiveKilled"].value * SETTINGS_TO_PERCENT
world.evolutionPerWormKilled = settings.global["rampant-evolution--evolutionPerWormKilled"].value * SETTINGS_TO_PERCENT
world.evolutionPerTime = settings.global["rampant-evolution--evolutionPerTime"].value * SETTINGS_TO_PERCENT
world.evolutionPerPollution = settings.global["rampant-evolution--evolutionPerPollution"].value * SETTINGS_TO_PERCENT
world.displayEvolutionMsg = settings.global["rampant-evolution--displayEvolutionMsg"].value
world.displayEvolutionMsgInterval = math.ceil(settings.global["rampant-evolution--displayEvolutionMsgInterval"].value * (60 * 60))
world.minimumDevolutionPercentage = settings.global["rampant-evolution--minimumDevolutionPercentage"].value
world.evolutionResolutionLevel = settings.global["rampant-evolution--evolutionResolutionLevel"].value
world.spawnerLookup = {}
world.hiveLookup = {}
world.wormLookup = {}
world.unitLookup = {}
if settings.global["rampant-evolution--recalculateAllEvolution"].value then
reset()
game.forces.enemy.evolution_factor = 0
game.print({"description.rampant-evolution--refreshingEvolution"})
end
for entityName, entityPrototype in pairs(game.entity_prototypes) do
if (entityPrototype.type == "unit-spawner") and sFind(entityName, "-spawner") then
world.spawnerLookup[entityName] = 1
elseif (entityPrototype.type == "unit-spawner") and sFind(entityName, "-hive") then
world.hiveLookup[entityName] = 1
elseif (entityPrototype.type == "turret") and sFind(entityName, "-worm") then
world.wormLookup[entityName] = 1
elseif (entityPrototype.type == "unit") and (sFind(entityName, "biter") or sFind(entityName, "spitter")) then
world.unitLookup[entityName] = 1
end
end
world.enabledResearchEvolutionCap = settings.global["rampant-evolution--researchEvolutionCap"].value
world.researchLookup = {}
world.researchTotals = {}
world.researchCurrent = {}
local sciencePackWeightLookup = {
[1] = settings.global["rampant-evolution--technology-automation-science-multiplier"].value,
[2] = settings.global["rampant-evolution--technology-logistic-science-multiplier"].value,
[3] = settings.global["rampant-evolution--technology-military-science-multiplier"].value,
[4] = settings.global["rampant-evolution--technology-chemical-science-multiplier"].value,
[5] = settings.global["rampant-evolution--technology-production-science-multiplier"].value,
[6] = settings.global["rampant-evolution--technology-utility-science-multiplier"].value,
[7] = settings.global["rampant-evolution--technology-space-science-multiplier"].value
}
local sciencePackOrder = {
"automation-science-pack",
"logistic-science-pack",
"military-science-pack",
"chemical-science-pack",
"production-science-pack",
"utility-science-pack",
"space-science-pack"
}
local sciencePackOrderLookup = {}
for index, science in pairs(sciencePackOrder) do
sciencePackOrderLookup[science] = index
world.researchTotals[index] = 0
world.researchCurrent[index] = 0
end
local totalTechnology = 0
local includeUpgrades = settings.global["rampant-evolution--researchEvolutionCapIncludeUpgrades"].value
for technologyName, technologyPrototype in pairs(game.technology_prototypes) do
local highestOrder = -1
if not technologyPrototype.research_unit_count_formula
and technologyPrototype.enabled
and not technologyPrototype.hidden
and ((not technologyPrototype.upgrade) or (technologyPrototype.upgrade and includeUpgrades))
then
for _, ingredient in pairs(technologyPrototype.research_unit_ingredients) do
if sciencePackOrderLookup[ingredient.name] then
if highestOrder < sciencePackOrderLookup[ingredient.name] then
highestOrder = sciencePackOrderLookup[ingredient.name]
end
end
end
if (highestOrder ~= -1) then
local weight = sciencePackWeightLookup[highestOrder]
totalTechnology = totalTechnology + weight
world.researchTotals[highestOrder] = (world.researchTotals[highestOrder] or 0) + weight
world.researchLookup[technologyName] = {weight, highestOrder}
world.totalResearch = world.totalResearch + 1
end
end
end
for tech, value in pairs(world.researchLookup) do
world.researchLookup[tech][1] = value[1] / totalTechnology
end
for scienceIndex=1,#sciencePackOrder do
world.researchTotals[scienceIndex] = world.researchTotals[scienceIndex] / totalTechnology
end
for technologyName, technology in pairs(game.forces.player.technologies) do
if technology.researched then
local evolutionIncrease = world.researchLookup[technologyName]
if evolutionIncrease then
world.researchCompleted = world.researchCompleted + 1
if world.enabledResearchEvolutionCap then
world.researchCurrent[evolutionIncrease[2]] = world.researchCurrent[evolutionIncrease[2]] + evolutionIncrease[1]
world.stats["researchEvolutionCap"] = world.stats["researchEvolutionCap"] + evolutionIncrease[1]
end
end
end
end
if not world.enabledResearchEvolutionCap then
world.stats["researchEvolutionCap"] = 0.9999999999999
end
world.toggleResearchEvolutionMultiplier = settings.global["rampant-evolution--toggleResearchEvolutionMultiplier"].value
world.startResearchEvolutionMultiplier = settings.global["rampant-evolution--startResearchMultiplier"].value
world.endResearchEvolutionMultiplier = settings.global["rampant-evolution--endResearchMultiplier"].value
world.researchMultiplierExponent = settings.global["rampant-evolution--researchMultiplierExponent"].value
world.toggleTickEvolutionMultiplier = settings.global["rampant-evolution--toggleTickEvolutionMultiplier"].value
world.startTickEvolutionMultiplier = settings.global["rampant-evolution--startTickMultiplier"].value
world.endTickEvolutionMultiplier = settings.global["rampant-evolution--endTickMultiplier"].value
world.tickMultiplierExponent = settings.global["rampant-evolution--tickMultiplierExponent"].value
if world.toggleResearchEvolutionMultiplier then
world.researchEvolutionMultiplier = variableInterpolation(
(world.researchCompleted / world.totalResearch),
world.startResearchEvolutionMultiplier,
world.endResearchEvolutionMultiplier,
world.researchMultiplierExponent
)
world.stats.evolutionMultiplier = world.researchEvolutionMultiplier + world.tickEvolutionMultiplier
end
world.totalTicksAccruable = settings.global["rampant-evolution--totalTickMultiplier"].value * (60 * 60)
world.evolutionPerLowPlayer = settings.global["rampant-evolution--evolutionPerLowPlayer"].value * SETTINGS_TO_PERCENT
world.evolutionPerMediumPlayer = settings.global["rampant-evolution--evolutionPerMediumPlayer"].value * SETTINGS_TO_PERCENT
world.evolutionPerHighPlayer = settings.global["rampant-evolution--evolutionPerHighPlayer"].value * SETTINGS_TO_PERCENT
local structureTypeLookup = {}
for _, structure in pairs(LOW_VALUE_PLAYER_STRUCTURES) do
structureTypeLookup[structure] = {world.evolutionPerLowPlayer, "lowPlayer"}
end
for _, structure in pairs(MEDIUM_VALUE_PLAYER_STRUCTURES) do
structureTypeLookup[structure] = {world.evolutionPerMediumPlayer, "mediumPlayer"}
end
for _, structure in pairs(HIGH_VALUE_PLAYER_STRUCTURES) do
structureTypeLookup[structure] = {world.evolutionPerHighPlayer, "highPlayer"}
end
world.playerStructureLookup = {}
for entityName, entityPrototype in pairs(game.entity_prototypes) do
local structureType = structureTypeLookup[entityPrototype.type]
if structureType then
world.playerStructureLookup[entityName] = structureType
end
end
if settings.global["rampant-evolution--setMapSettingsToZero"].value then
game.map_settings.enemy_evolution.enabled = false
else
game.map_settings.enemy_evolution.enabled = true
end
for playerIndex in pairs(world.playerGuiTick) do
world.playerGuiTick[playerIndex] = nil
end
onStatsGrabPollution()
onStatsGrabKill()
onStatsGrabTotalPollution()
if not settings.global["rampant-evolution--recalculateAllEvolution"].value then
world.killDeltasIterator = nil
world.pollutionDeltasIterator = nil
world.killDeltas = {}
world.pollutionDeltas = {}
end
return true
end
local function onConfigChanged()
if not world.version or world.version < 11 then
world.version = 11
reset()
world.tickModAdded = game.tick
world.playerGuiOpen = {}
world.playerGuiTick = {}
world.lastChangeShortTick = 0
world.lastChangeShortEvolution = 0
world.lastChangeShort = 0
world.lastChangeLongTick = 0
world.lastChangeLongEvolution = 0
world.lastChangeLong = 0
world.lastChangeLongLongTick = 0
world.lastChangeLongLongEvolution = 0
world.lastChangeLongLong = 0
world.playerIterator = nil
onModSettingsChange()
game.print("Rampant Evolution - Version 1.6.4")
end
end
local function calculateEvolution(evo, evolutionModifier, stats, statField, runsRemaining)
if world.toggleTickEvolutionMultiplier
and (statField == "time")
then
world.ticksAccrued = world.ticksAccrued + (60 * runsRemaining)
world.tickEvolutionMultiplier = variableInterpolation(
world.ticksAccrued / world.totalTicksAccruable,
world.startTickEvolutionMultiplier,
world.endTickEvolutionMultiplier,
world.tickMultiplierExponent
)
world.stats.evolutionMultiplier = world.researchEvolutionMultiplier + world.tickEvolutionMultiplier
end
if (evolutionModifier ~= 0) then
local totalEvolution = world.totalEvolution
local totalPostiveEvolution = world.totalPostiveEvolution
local totalNegativeEvolution = world.totalNegativeEvolution
local minimumEvolution = stats.minimumEvolution
local evolutionMultiplier = 1 + stats.evolutionMultiplier
local maximumEvolution = mMin(stats.researchEvolutionCap, 0.9999999999999)
local minimumTotalEvolution = mMax(minimumEvolution / (1 - minimumEvolution), 0)
local maximumTotalEvolution = maximumEvolution / (1 - maximumEvolution)
local process = true
while (runsRemaining > 0) and process do
runsRemaining = runsRemaining - 1
local contribution = (((1 - evo)^2) * evolutionModifier)
local adjustedEvo = totalEvolution + (contribution * evolutionMultiplier)
if adjustedEvo <= minimumTotalEvolution then
contribution = minimumTotalEvolution - totalEvolution
process = false
elseif adjustedEvo >= maximumTotalEvolution then
contribution = maximumTotalEvolution - totalEvolution
process = false
end
if contribution > 0 then
if process then
contribution = contribution * evolutionMultiplier
end
totalPostiveEvolution = totalPostiveEvolution + contribution
else
totalNegativeEvolution = totalNegativeEvolution + contribution
end
totalEvolution = totalEvolution + contribution
evo = totalEvolution / (1+totalEvolution)
stats[statField] = stats[statField] + contribution
end
local newMinimumEvolution = world.minimumDevolutionPercentage * evo
if newMinimumEvolution > minimumEvolution then
stats.minimumEvolution = newMinimumEvolution
end
world.totalNegativeEvolution = totalNegativeEvolution
world.totalPostiveEvolution = totalPostiveEvolution
world.totalEvolution = totalEvolution
end
return evo
end
local function processKill(evo, initialRunsRemaining)
local name = world.killDeltasIterator
local count
if not name then
name,count = next(world.killDeltas, nil)
else
count = world.killDeltas[name]
end
if not name then
return evo
end
world.killDeltasIterator = next(world.killDeltas, name)
local runsRemaining = math.min(initialRunsRemaining, count)
count = count - runsRemaining
if count <= 0 then
world.killDeltas[name] = nil
else
world.killDeltas[name] = count
end
local evolutionModifier = 0
local statField
if name == "time" then
evolutionModifier = world.evolutionPerTime
statField = "time"
elseif world.spawnerLookup[name] then
evolutionModifier = world.evolutionPerSpawnerKilled
statField = "spawner"
elseif world.hiveLookup[name] then
evolutionModifier = world.evolutionPerHiveKilled
statField = "hive"
elseif world.wormLookup[name] then
evolutionModifier = world.evolutionPerWormKilled
statField = "worm"
elseif world.unitLookup[name] then
evolutionModifier = world.evolutionPerUnitKilled
statField = "unit"
elseif world.playerStructureLookup[name] then
local evolutionDeltaPair = world.playerStructureLookup[name]
if evolutionDeltaPair and evolutionDeltaPair[1] ~= 0 then
evolutionModifier = evolutionDeltaPair[1]
statField = evolutionDeltaPair[2]
end
end
return calculateEvolution(
evo,
evolutionModifier,
world.stats,
statField,
runsRemaining
)
end
local function processPollution(evo, initialRunsRemaining)
local name = world.pollutionDeltasIterator
local count
if not name then
name,count = next(world.pollutionDeltas, nil)
else
count = world.pollutionDeltas[name]
end
if not name then
return evo
end
world.pollutionDeltasIterator = next(world.pollutionDeltas, name)
local runsRemaining = math.min(initialRunsRemaining, count)
count = count - runsRemaining
if count <= 0 then
world.pollutionDeltas[name] = nil
else
world.pollutionDeltas[name] = count
end
local evolutionModifier = 0
local statField
if (name == "tile-proxy") then
evolutionModifier = world.evolutionPerTileAbsorbed
statField = "tile"
elseif (name == "tree-proxy") then
evolutionModifier = world.evolutionPerTreeAbsorbed
statField = "tree"
elseif (name == "tree-dying-proxy") then
evolutionModifier = world.evolutionPerTreeDied
statField = "dyingTree"
elseif (name == "totalPollution") then
evolutionModifier = world.evolutionPerPollution
statField = "totalPollution"
elseif world.spawnerLookup[name] then
evolutionModifier = world.evolutionPerSpawnerAbsorbed
statField = "absorbed"
end
return calculateEvolution(
evo,
evolutionModifier,
world.stats,
statField,
runsRemaining
)
end
local function printEvolutionMsg()
local enemy = game.forces.enemy
local stats = world.stats
local enemyEvo = enemy.evolution_factor
game.print({
"description.rampant-evolution--displayEvolutionMsg",
roundTo(enemyEvo*100,0.001),
roundTo(calculateDisplayValue(stats["tile"], world, enemyEvo)*100, 0.001),
roundTo(calculateDisplayValue(stats["tree"], world, enemyEvo)*100, 0.001),
roundTo(calculateDisplayValue(stats["dyingTree"], world, enemyEvo)*100, 0.001),
roundTo(calculateDisplayValue(stats["absorbed"], world, enemyEvo)*100, 0.001),
roundTo(calculateDisplayValue(stats["spawner"], world, enemyEvo)*100, 0.001),
roundTo(calculateDisplayValue(stats["hive"], world, enemyEvo)*100, 0.001),
roundTo(calculateDisplayValue(stats["unit"], world, enemyEvo)*100, 0.001),
roundTo(calculateDisplayValue(stats["worm"], world, enemyEvo)*100, 0.001),
roundTo(calculateDisplayValue(stats["totalPollution"], world, enemyEvo)*100, 0.001),
roundTo(calculateDisplayValue(stats["time"], world, enemyEvo)*100, 0.001),
roundTo(calculateDisplayValue(stats["lowPlayer"], world, enemyEvo)*100, 0.001),
roundTo(calculateDisplayValue(stats["mediumPlayer"], world, enemyEvo)*100, 0.001),
roundTo(calculateDisplayValue(stats["highPlayer"], world, enemyEvo)*100, 0.001),
roundTo(stats["evolutionMultiplier"]*100, 0.001),
roundTo(stats["minimumEvolution"]*100, 0.001),
roundTo(stats["researchEvolutionCap"]*100, 0.001),
roundTo(world.lastChangeShort*100, 0.001),
roundTo(world.lastChangeLong*100, 0.001),
roundTo(world.lastChangeLongLong*100, 0.001)
})
end
local function processing(resolutionLevel, evo)
return processKill(
processPollution(
evo,
resolutionLevel
),
resolutionLevel
)
end
local function onProcessingWrapper(event)
local enemy = game.forces.enemy
local tick = event.tick
local resolutionLevel = world.evolutionResolutionLevel
if resolutionLevel == 0 then
local x = tick / 43200000 -- (60 * 60 * 60 * 200)
resolutionLevel = linearInterpolation(
mMin(x, 1),
20,
4000
)
end
local evo = enemy.evolution_factor
for _ = 1, world.processingPerTick do
evo = processing(resolutionLevel, evo)
end
enemy.evolution_factor = evo
if (tick % 60) == 0 then
world.killDeltas["time"] = (world.killDeltas["time"] or 0) + 1
end
if (tick - world.lastChangeShortTick) >= SHORT_EVOLUTION_CHECK_DURATION then
world.lastChangeShortTick = tick
world.lastChangeShort = evo - world.lastChangeShortEvolution
world.lastChangeShortEvolution = evo
end
if (tick - world.lastChangeLongTick) >= LONG_EVOLUTION_CHECK_DURATION then
world.lastChangeLongTick = tick
world.lastChangeLong = evo - world.lastChangeLongEvolution
world.lastChangeLongEvolution = evo
end
if (tick - world.lastChangeLongLongTick) >= LONG_LONG_EVOLUTION_CHECK_DURATION then
world.lastChangeLongLongTick = tick
world.lastChangeLongLong = evo - world.lastChangeLongLongEvolution
world.lastChangeLongLongEvolution = evo
end
if world.displayEvolutionMsg and ((tick % world.displayEvolutionMsgInterval) == 0) then
printEvolutionMsg()
end
local playerId = world.playerIterator
if not playerId then
world.playerIterator = next(game.connected_players, world.playerIterator)
else
world.playerIterator = next(game.connected_players, playerId)
gui.update(world, playerId, tick)
end
end
local function onInit()
global.world = {}
world = global.world
onConfigChanged()
end
local function onLoad()
world = global.world
end
local function onLuaShortcut(event)
if event.prototype_name == "rampant-evolution--info" then
local playerIndex = event.player_index
local guiPanel = world.playerGuiOpen[playerIndex]
if not guiPanel then
world.playerGuiOpen[playerIndex] = gui.create(game.players[playerIndex], world)
else
gui.close(world, event.player_index)
end
end
end
local function onPlayerRemoved(event)
world.playerIterator = nil
end
local function onResearchCompleted(event)
if not world.researchLookup then
return
end
local research = event.research
local technologyName = research.name
local evolutionIncrease = world.researchLookup[technologyName]
if world.toggleResearchEvolutionMultiplier
and evolutionIncrease
and research.force.name == "player"
then
world.researchCompleted = world.researchCompleted + 1
world.researchEvolutionMultiplier = variableInterpolation(
(world.researchCompleted / world.totalResearch),
world.startResearchEvolutionMultiplier,
world.endResearchEvolutionMultiplier,
world.researchMultiplierExponent
)
world.stats.evolutionMultiplier = world.researchEvolutionMultiplier + world.tickEvolutionMultiplier
if world.enabledResearchEvolutionCap then
world.researchCurrent[evolutionIncrease[2]] = world.researchCurrent[evolutionIncrease[2]] + evolutionIncrease[1]
world.stats["researchEvolutionCap"] = world.stats["researchEvolutionCap"] + evolutionIncrease[1]
end
end
end
local function onResearchUncompleted(event)
if not world.researchLookup then
return
end
local research = event.research
local technologyName = research.name
local evolutionIncrease = world.researchLookup[technologyName]
if world.toggleResearchEvolutionMultiplier
and evolutionIncrease
and research.force.name == "player"
then
world.researchCompleted = world.researchCompleted - 1
world.researchEvolutionMultiplier = variableInterpolation(
(world.researchCompleted / world.totalResearch),
world.startResearchEvolutionMultiplier,
world.endResearchEvolutionMultiplier,
world.researchMultiplierExponent
)
world.stats.evolutionMultiplier = world.researchEvolutionMultiplier + world.tickEvolutionMultiplier
if world.enabledResearchEvolutionCap then
world.researchCurrent[evolutionIncrease[2]] = world.researchCurrent[evolutionIncrease[2]] + evolutionIncrease[1]
world.stats["researchEvolutionCap"] = world.stats["researchEvolutionCap"] - evolutionIncrease[1]
end
end
end
-- hooks
script.on_event(
{
defines.events.on_player_left_game,
defines.events.on_player_kicked,
defines.events.on_player_removed,
defines.events.on_player_banned
},
onPlayerRemoved)
script.on_event(defines.events.on_lua_shortcut, onLuaShortcut)
script.on_nth_tick((2*60*60)+0, onStatsGrabPollution)
script.on_nth_tick((2*60*60)+1, onStatsGrabKill)
script.on_nth_tick((2*60*60)+2, onStatsGrabTotalPollution)
script.on_event(defines.events.on_tick, onProcessingWrapper)
script.on_event(defines.events.on_research_finished, onResearchCompleted)
script.on_event(defines.events.on_research_reversed, onResearchUncompleted)
script.on_init(onInit)
script.on_load(onLoad)
script.on_event(defines.events.on_runtime_mod_setting_changed, onModSettingsChange)
script.on_configuration_changed(onConfigChanged)
-- commands
local function rampantEvolution(event)
printEvolutionMsg()
end
commands.add_command('rampantEvolution', "", rampantEvolution)