2018-01-14 02:12:09 +02:00
|
|
|
local swarmUtils = {}
|
2018-01-13 04:55:20 +02:00
|
|
|
-- imports
|
|
|
|
|
|
|
|
local biterUtils = require("prototypes/enemies/BiterUtils")
|
|
|
|
local mathUtils = require("libs/MathUtils")
|
|
|
|
|
|
|
|
-- imported functions
|
|
|
|
|
2018-01-14 02:12:09 +02:00
|
|
|
local gaussianRandomRangeRG = mathUtils.gaussianRandomRangeRG
|
2018-01-13 04:55:20 +02:00
|
|
|
|
|
|
|
local mMax = math.max
|
2018-01-14 02:12:09 +02:00
|
|
|
local mMin = math.min
|
|
|
|
|
|
|
|
local mFloor = math.floor
|
2018-01-13 04:55:20 +02:00
|
|
|
|
|
|
|
local deepcopy = util.table.deepcopy
|
|
|
|
|
2018-01-14 02:12:09 +02:00
|
|
|
local xorRandom = mathUtils.xorRandom(settings.startup["rampant-enemySeed"].value)
|
|
|
|
|
2018-01-13 04:55:20 +02:00
|
|
|
local makeBiter = biterUtils.makeBiter
|
|
|
|
local makeSpitter = biterUtils.makeSpitter
|
|
|
|
local makeWorm = biterUtils.makeWorm
|
|
|
|
local makeUnitSpawner = biterUtils.makeUnitSpawner
|
|
|
|
|
|
|
|
-- module code
|
|
|
|
|
|
|
|
local function unitSetToProbabilityTable(points, upgradeTable, unitSet)
|
|
|
|
local dividers = {}
|
|
|
|
|
|
|
|
for i=1,#unitSet do
|
|
|
|
dividers[i] = 1
|
|
|
|
end
|
|
|
|
|
2018-01-14 02:12:09 +02:00
|
|
|
if upgradeTable then
|
|
|
|
while (points > 0) do
|
|
|
|
local upgrade = upgradeTable[mFloor(xorRandom() * #upgradeTable)+1]
|
2018-01-13 04:55:20 +02:00
|
|
|
|
2018-01-14 02:12:09 +02:00
|
|
|
local cost = upgrade.cost
|
|
|
|
local index = upgrade.index
|
2018-01-13 04:55:20 +02:00
|
|
|
|
2018-01-14 02:12:09 +02:00
|
|
|
dividers[index] = dividers[index] + upgrade.adjustment
|
|
|
|
|
|
|
|
points = points - cost
|
|
|
|
end
|
2018-01-13 04:55:20 +02:00
|
|
|
end
|
2018-01-14 02:12:09 +02:00
|
|
|
|
2018-01-13 04:55:20 +02:00
|
|
|
local total = 0
|
|
|
|
for i=1,#dividers do
|
|
|
|
total = total + dividers[i]
|
|
|
|
end
|
|
|
|
|
|
|
|
local runningTotal = 0
|
|
|
|
for i=1,#dividers do
|
|
|
|
runningTotal = runningTotal + (dividers[i] / total)
|
|
|
|
dividers[i] = runningTotal
|
|
|
|
end
|
|
|
|
|
2018-01-14 02:12:09 +02:00
|
|
|
local stepUnit = 1 / (#unitSet[1] + 1)
|
|
|
|
|
2018-01-13 04:55:20 +02:00
|
|
|
local probabilityTable = {}
|
|
|
|
|
|
|
|
for i=1,#unitSet do
|
|
|
|
local result
|
|
|
|
if (i == 1) then
|
|
|
|
result = {
|
|
|
|
{
|
|
|
|
0,
|
|
|
|
stepUnit
|
|
|
|
},
|
|
|
|
{
|
|
|
|
dividers[i],
|
|
|
|
0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
elseif (i == #unitSet) then
|
|
|
|
result = {
|
|
|
|
{
|
|
|
|
dividers[i-2],
|
|
|
|
0
|
|
|
|
},
|
|
|
|
{
|
|
|
|
1,
|
|
|
|
stepUnit
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
result = {
|
|
|
|
{
|
|
|
|
((i - 2) > 0 and dividers[i-2]) or 0,
|
|
|
|
0
|
|
|
|
},
|
|
|
|
{
|
|
|
|
dividers[i-1],
|
|
|
|
stepUnit
|
|
|
|
},
|
|
|
|
{
|
|
|
|
dividers[i],
|
|
|
|
0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
probabilityTable[i] = result
|
|
|
|
end
|
|
|
|
|
|
|
|
local result = {}
|
|
|
|
|
|
|
|
for i=1, #probabilityTable do
|
|
|
|
local probability = probabilityTable[i]
|
|
|
|
for x=1, #unitSet[i] do
|
|
|
|
result[#result+1] = {unitSet[i][x], probability}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return result
|
|
|
|
end
|
|
|
|
|
2018-01-16 09:21:12 +02:00
|
|
|
local function upgradeEntity(points, entity, upgradeTable, tierMultipler)
|
2018-01-14 02:12:09 +02:00
|
|
|
local remainingPoints = points
|
|
|
|
if upgradeTable then
|
|
|
|
while (remainingPoints > 0) do
|
|
|
|
local upgrade = upgradeTable[mFloor(xorRandom() * #upgradeTable)+1]
|
2018-01-13 04:55:20 +02:00
|
|
|
|
2018-01-14 02:12:09 +02:00
|
|
|
local cost = upgrade.cost
|
|
|
|
for i=1, #upgrade.bonus do
|
|
|
|
local bonus = upgrade.bonus[i]
|
|
|
|
|
|
|
|
if (bonus.type == "attribute") then
|
|
|
|
if bonus.mapping then
|
|
|
|
entity.attributes[bonus.name] = bonus.mapping[entity.attributes[bonus.name] or "default"]
|
|
|
|
else
|
2018-01-16 09:21:12 +02:00
|
|
|
local adj = bonus.adjustment * tierMultipler
|
|
|
|
if adj < 0 then
|
|
|
|
adj = -adj
|
|
|
|
adj = -gaussianRandomRangeRG(adj, adj * 0.2, adj * 0.75, adj * 1.25, xorRandom)
|
|
|
|
else
|
|
|
|
adj = gaussianRandomRangeRG(adj, adj * 0.2, adj * 0.75, adj * 1.25, xorRandom)
|
|
|
|
end
|
|
|
|
entity.attributes[bonus.name] = (entity.attributes[bonus.name] or 0) + adj
|
2018-01-14 02:12:09 +02:00
|
|
|
end
|
2018-01-13 04:55:20 +02:00
|
|
|
end
|
2018-01-14 02:12:09 +02:00
|
|
|
if (bonus.type == "resistance") then
|
2018-01-16 09:21:12 +02:00
|
|
|
local field = bonus.name
|
2018-01-14 02:12:09 +02:00
|
|
|
if not entity.resistances[field] then
|
|
|
|
entity.resistances[field] = {}
|
2018-01-13 04:55:20 +02:00
|
|
|
end
|
2018-01-16 09:21:12 +02:00
|
|
|
if bonus.decrease then
|
|
|
|
entity.resistances[field].decrease = (entity.resistances[field].decrease or 0) + bonus.decrease
|
2018-01-13 04:55:20 +02:00
|
|
|
end
|
2018-01-16 09:21:12 +02:00
|
|
|
if bonus.percent then
|
|
|
|
entity.resistances[field].percent = mMin((entity.resistances[field].percent or 0) + bonus.percent, 100)
|
2018-01-13 04:55:20 +02:00
|
|
|
end
|
|
|
|
end
|
2018-01-14 02:12:09 +02:00
|
|
|
if (bonus.type == "attack") then
|
2018-01-16 09:21:12 +02:00
|
|
|
if bonus.mapping then
|
|
|
|
entity.attack[bonus.name] = bonus.mapping[entity.attack[bonus.name] or "default"]
|
2018-01-14 02:12:09 +02:00
|
|
|
else
|
2018-01-16 09:21:12 +02:00
|
|
|
local adj = bonus.adjustment * tierMultipler
|
|
|
|
if adj < 0 then
|
|
|
|
adj = -adj
|
|
|
|
adj = -gaussianRandomRangeRG(adj, adj * 0.2, adj * 0.75, adj * 1.25, xorRandom)
|
|
|
|
else
|
|
|
|
adj = gaussianRandomRangeRG(adj, adj * 0.2, adj * 0.75, adj * 1.25, xorRandom)
|
|
|
|
end
|
|
|
|
entity.attack[bonus.name] = (entity.attack[bonus.name] or 0) + adj
|
2018-01-14 02:12:09 +02:00
|
|
|
end
|
2018-01-13 04:55:20 +02:00
|
|
|
end
|
|
|
|
end
|
2018-01-14 02:12:09 +02:00
|
|
|
|
|
|
|
remainingPoints = remainingPoints - cost
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local function generateApperance(unit, tier)
|
|
|
|
local scale = gaussianRandomRangeRG(unit.scale, unit.scale * 0.12, unit.scale * 0.60, unit.scale * 1.40, xorRandom) + (0.05 * tier)
|
2018-01-13 04:55:20 +02:00
|
|
|
|
2018-01-14 02:12:09 +02:00
|
|
|
local r,g,b,a
|
|
|
|
|
|
|
|
if unit.tint then
|
|
|
|
r = gaussianRandomRangeRG(unit.tint.r, unit.tint.r * 0.10 + (0.005 * tier), mMax(unit.tint.r * 0.85 - (0.005 * tier), 0), mMin(unit.tint.r * 1.15, 1), xorRandom)
|
|
|
|
g = gaussianRandomRangeRG(unit.tint.g, unit.tint.g * 0.10 + (0.005 * tier), mMax(unit.tint.g * 0.85 - (0.005 * tier), 0), mMin(unit.tint.g * 1.15, 1), xorRandom)
|
|
|
|
b = gaussianRandomRangeRG(unit.tint.b, unit.tint.b * 0.10 + (0.005 * tier), mMax(unit.tint.b * 0.85 - (0.005 * tier), 0), mMin(unit.tint.b * 1.15, 1), xorRandom)
|
|
|
|
a = gaussianRandomRangeRG(unit.tint.a, unit.tint.a * 0.10 + (0.005 * tier), mMax(unit.tint.a * 0.85 - (0.005 * tier), 0), mMin(unit.tint.a * 1.15, 1), xorRandom)
|
2018-01-13 04:55:20 +02:00
|
|
|
|
2018-01-14 02:12:09 +02:00
|
|
|
local tint = { r=r, g=g, b=b, a=a }
|
|
|
|
|
|
|
|
unit.attributes.scale = scale
|
|
|
|
unit.attributes.tint = tint
|
|
|
|
else
|
|
|
|
r = gaussianRandomRangeRG(unit.tint1.r, unit.tint1.r * 0.10 + (0.005 * tier), mMax(unit.tint1.r * 0.85 - (0.005 * tier), 0), mMin(unit.tint1.r * 1.15, 1), xorRandom)
|
|
|
|
g = gaussianRandomRangeRG(unit.tint1.g, unit.tint1.g * 0.10 + (0.005 * tier), mMax(unit.tint1.g * 0.85 - (0.005 * tier), 0), mMin(unit.tint1.g * 1.15, 1), xorRandom)
|
|
|
|
b = gaussianRandomRangeRG(unit.tint1.b, unit.tint1.b * 0.10 + (0.005 * tier), mMax(unit.tint1.b * 0.85 - (0.005 * tier), 0), mMin(unit.tint1.b * 1.15, 1), xorRandom)
|
|
|
|
a = gaussianRandomRangeRG(unit.tint1.a, unit.tint1.a * 0.10 + (0.005 * tier), mMax(unit.tint1.a * 0.85 - (0.005 * tier), 0), mMin(unit.tint1.a * 1.15, 1), xorRandom)
|
|
|
|
|
|
|
|
local tint1 = { r=r, g=g, b=b, a=a }
|
2018-01-13 04:55:20 +02:00
|
|
|
|
2018-01-14 02:12:09 +02:00
|
|
|
r = gaussianRandomRangeRG(unit.tint2.r, unit.tint2.r * 0.10 + (0.005 * tier), mMax(unit.tint2.r * 0.85 - (0.005 * tier), 0), mMin(unit.tint2.r * 1.15, 1), xorRandom)
|
|
|
|
g = gaussianRandomRangeRG(unit.tint2.g, unit.tint2.g * 0.10 + (0.005 * tier), mMax(unit.tint2.g * 0.85 - (0.005 * tier), 0), mMin(unit.tint2.g * 1.15, 1), xorRandom)
|
|
|
|
b = gaussianRandomRangeRG(unit.tint2.b, unit.tint2.b * 0.10 + (0.005 * tier), mMax(unit.tint2.b * 0.85 - (0.005 * tier), 0), mMin(unit.tint2.b * 1.15, 1), xorRandom)
|
|
|
|
a = gaussianRandomRangeRG(unit.tint2.a, unit.tint2.a * 0.10 + (0.005 * tier), mMax(unit.tint2.a * 0.85 - (0.005 * tier), 0), mMin(unit.tint2.a * 1.15, 1), xorRandom)
|
|
|
|
|
|
|
|
local tint2 = { r=r, g=g, b=b, a=a }
|
2018-01-13 04:55:20 +02:00
|
|
|
|
2018-01-14 02:12:09 +02:00
|
|
|
unit.attributes.scale = scale
|
|
|
|
unit.attributes.tint1 = tint1
|
|
|
|
unit.attributes.tint2 = tint2
|
|
|
|
|
|
|
|
unit.attack.scale = scale
|
|
|
|
unit.attack.tint1 = tint1
|
|
|
|
unit.attack.tint2 = tint2
|
|
|
|
end
|
|
|
|
end
|
2018-01-13 04:55:20 +02:00
|
|
|
|
2018-01-14 02:12:09 +02:00
|
|
|
local function buildUnits(startingPoints, template, attackGenerator, upgradeTable, variations, tiers)
|
|
|
|
local unitSet = {}
|
|
|
|
|
|
|
|
for t=1, tiers do
|
|
|
|
local result = {}
|
|
|
|
|
|
|
|
for i=1,variations do
|
|
|
|
local unit = deepcopy(template)
|
2018-01-16 09:21:12 +02:00
|
|
|
unit.name = unit.name .. "-v" .. i .. "-t" .. t .. "-rampant"
|
2018-01-14 02:12:09 +02:00
|
|
|
generateApperance(unit, t)
|
2018-01-16 09:21:12 +02:00
|
|
|
upgradeEntity(startingPoints, unit, upgradeTable, tiers)
|
2018-01-14 02:12:09 +02:00
|
|
|
|
2018-01-13 04:55:20 +02:00
|
|
|
local entity
|
|
|
|
if (unit.type == "spitter") then
|
|
|
|
entity = makeSpitter(unit.name,
|
|
|
|
unit.attributes,
|
|
|
|
attackGenerator(unit.attack),
|
|
|
|
unit.resistances)
|
|
|
|
elseif (unit.type == "biter") then
|
|
|
|
entity = makeBiter(unit.name,
|
|
|
|
unit.attributes,
|
|
|
|
attackGenerator(unit.attack),
|
|
|
|
unit.resistances)
|
|
|
|
end
|
|
|
|
|
|
|
|
result[i] = entity.name
|
|
|
|
|
|
|
|
data:extend({entity})
|
|
|
|
end
|
|
|
|
|
|
|
|
unitSet[t] = result
|
|
|
|
end
|
|
|
|
|
|
|
|
return unitSet
|
|
|
|
end
|
|
|
|
|
2018-01-15 01:10:56 +02:00
|
|
|
function swarmUtils.buildUnitSpawner(points, templates, upgradeTable, attackGenerator, variations, tiers)
|
|
|
|
local unitSet = buildUnits(points.unit,
|
|
|
|
templates.unit,
|
|
|
|
attackGenerator,
|
|
|
|
upgradeTable.unit,
|
|
|
|
variations.unit,
|
|
|
|
tiers.unit)
|
|
|
|
|
2018-01-16 09:21:12 +02:00
|
|
|
for t=1, tiers.unitSpawner do
|
2018-01-15 01:10:56 +02:00
|
|
|
local allottedPoints = points.unitSpawner * t
|
2018-01-13 04:55:20 +02:00
|
|
|
|
2018-01-15 01:10:56 +02:00
|
|
|
for i=1,variations.unitSpawner do
|
|
|
|
local unitSpawner = deepcopy(templates.unitSpawner)
|
2018-01-16 09:21:12 +02:00
|
|
|
unitSpawner.name = unitSpawner.name .. "-v" .. i .. "-t" .. t .. "-rampant"
|
2018-01-15 01:10:56 +02:00
|
|
|
local unitTable = unitSetToProbabilityTable(points.probabilityTable,
|
|
|
|
upgradeTable.probabilityTable,
|
|
|
|
unitSet)
|
2018-01-14 02:12:09 +02:00
|
|
|
generateApperance(unitSpawner, t)
|
2018-01-16 09:21:12 +02:00
|
|
|
upgradeEntity(allottedPoints, unitSpawner, upgradeTable.unitSpawner, t / tiers)
|
2018-01-13 04:55:20 +02:00
|
|
|
|
|
|
|
data:extend({
|
|
|
|
makeUnitSpawner(unitSpawner.name,
|
|
|
|
unitSpawner.attributes,
|
|
|
|
unitSpawner.resistances,
|
|
|
|
unitTable)
|
|
|
|
})
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
2018-01-14 02:12:09 +02:00
|
|
|
function swarmUtils.buildWorm(startingPoints, template, attackGenerator, upgradeTable, variations, tiers)
|
2018-01-13 04:55:20 +02:00
|
|
|
for t=1, tiers do
|
|
|
|
local allottedPoints = startingPoints * t
|
|
|
|
|
|
|
|
for i=1,variations do
|
|
|
|
local worm = deepcopy(template)
|
2018-01-16 09:21:12 +02:00
|
|
|
worm.name = worm.name .. "-v" .. i .. "-t" .. t .. "-rampant"
|
2018-01-14 02:12:09 +02:00
|
|
|
generateApperance(worm, t)
|
2018-01-16 09:21:12 +02:00
|
|
|
upgradeEntity(allottedPoints, worm, upgradeTable, t / tiers)
|
2018-01-14 02:12:09 +02:00
|
|
|
|
2018-01-13 04:55:20 +02:00
|
|
|
data:extend({
|
|
|
|
makeWorm(worm.name,
|
|
|
|
worm.attributes,
|
|
|
|
attackGenerator(worm.attack),
|
|
|
|
worm.resistances)
|
|
|
|
})
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-01-14 02:12:09 +02:00
|
|
|
return swarmUtils
|