mirror of
https://github.com/veden/Rampant.git
synced 2025-03-11 14:49:32 +02:00
working unitclass generation
This commit is contained in:
parent
347c057dc2
commit
c709c47011
363
BuildSwarm.lua
363
BuildSwarm.lua
@ -1,3 +1,4 @@
|
||||
local swarmUtils = {}
|
||||
-- imports
|
||||
|
||||
local biterUtils = require("prototypes/enemies/BiterUtils")
|
||||
@ -5,21 +6,22 @@ local mathUtils = require("libs/MathUtils")
|
||||
|
||||
-- imported functions
|
||||
|
||||
local gaussianRandomRange = mathUtils.gaussianRandomRange
|
||||
local gaussianRandomRangeRG = mathUtils.gaussianRandomRangeRG
|
||||
|
||||
local mRandom = math.random
|
||||
local mMin = math.min
|
||||
local mMax = math.max
|
||||
local mMin = math.min
|
||||
|
||||
local mFloor = math.floor
|
||||
|
||||
local deepcopy = util.table.deepcopy
|
||||
|
||||
local xorRandom = mathUtils.xorRandom(settings.startup["rampant-enemySeed"].value)
|
||||
|
||||
local makeBiter = biterUtils.makeBiter
|
||||
local makeSpitter = biterUtils.makeSpitter
|
||||
local makeWorm = biterUtils.makeWorm
|
||||
local makeUnitSpawner = biterUtils.makeUnitSpawner
|
||||
|
||||
local createSuicideAttack = biterUtils.createSuicideAttack
|
||||
|
||||
-- module code
|
||||
|
||||
local function unitSetToProbabilityTable(points, upgradeTable, unitSet)
|
||||
@ -29,17 +31,19 @@ local function unitSetToProbabilityTable(points, upgradeTable, unitSet)
|
||||
dividers[i] = 1
|
||||
end
|
||||
|
||||
while (points > 0) do
|
||||
local upgrade = upgradeTable[mRandom(#upgradeTable)]
|
||||
if upgradeTable then
|
||||
while (points > 0) do
|
||||
local upgrade = upgradeTable[mFloor(xorRandom() * #upgradeTable)+1]
|
||||
|
||||
local cost = upgrade.cost
|
||||
local index = upgrade.index
|
||||
local cost = upgrade.cost
|
||||
local index = upgrade.index
|
||||
|
||||
dividers[index] = dividers[index] + upgrade.adjustment
|
||||
|
||||
points = points - cost
|
||||
dividers[index] = dividers[index] + upgrade.adjustment
|
||||
|
||||
points = points - cost
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local total = 0
|
||||
for i=1,#dividers do
|
||||
total = total + dividers[i]
|
||||
@ -51,8 +55,8 @@ local function unitSetToProbabilityTable(points, upgradeTable, unitSet)
|
||||
dividers[i] = runningTotal
|
||||
end
|
||||
|
||||
local stepUnit = 1 / #unitSet[1]
|
||||
|
||||
local stepUnit = 1 / (#unitSet[1] + 1)
|
||||
|
||||
local probabilityTable = {}
|
||||
|
||||
for i=1,#unitSet do
|
||||
@ -111,9 +115,94 @@ local function unitSetToProbabilityTable(points, upgradeTable, unitSet)
|
||||
return result
|
||||
end
|
||||
|
||||
local function upgradeEntity(points, entity, upgradeTable)
|
||||
local remainingPoints = points
|
||||
if upgradeTable then
|
||||
while (remainingPoints > 0) do
|
||||
local upgrade = upgradeTable[mFloor(xorRandom() * #upgradeTable)+1]
|
||||
|
||||
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
|
||||
entity.attributes[bonus.name] = (entity.attributes[bonus.name] or 0) + bonus.adjustment
|
||||
end
|
||||
end
|
||||
if (bonus.type == "resistance") then
|
||||
local field = bonus.resistance.name
|
||||
if not entity.resistances[field] then
|
||||
entity.resistances[field] = {}
|
||||
end
|
||||
if bonus.resistance.decrease then
|
||||
entity.resistances[field].decrease = (entity.resistances[field].decrease or 0) + bonus.resistance.decrease
|
||||
end
|
||||
if bonus.resistance.percentage then
|
||||
entity.resistances[field].percentage = (entity.resistances[field].percentage or 0) + bonus.resistance.percentage
|
||||
end
|
||||
end
|
||||
if (bonus.type == "attack") then
|
||||
local attack = bonus.attack
|
||||
entity.attack[attack.name] = (entity.attack[attack.name] or 0) + attack.adjustment
|
||||
if attack.mapping then
|
||||
entity.attributes[attack.name] = attack.mapping[entity.attributes[attack.name] or "default"]
|
||||
else
|
||||
entity.attributes[attack.name] = (entity.attributes[attack.name] or 0) + attack.adjustment
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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 }
|
||||
|
||||
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 }
|
||||
|
||||
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
|
||||
|
||||
local function buildUnits(startingPoints, template, attackGenerator, upgradeTable, variations, tiers)
|
||||
local unitSet = {}
|
||||
|
||||
|
||||
for t=1, tiers do
|
||||
local result = {}
|
||||
|
||||
@ -122,58 +211,9 @@ local function buildUnits(startingPoints, template, attackGenerator, upgradeTabl
|
||||
for i=1,variations do
|
||||
local unit = deepcopy(template)
|
||||
unit.name = unit.name .. "-v" .. i .. "-t" .. t
|
||||
local remainingPoints = allottedPoints
|
||||
while (remainingPoints > 0) do
|
||||
local upgrade = upgradeTable[mRandom(#upgradeTable)]
|
||||
|
||||
local cost = upgrade.cost
|
||||
if upgrade.attribute then
|
||||
local attribute = upgrade.attribute
|
||||
unit.attributes[attribute.name] = unit.attributes[attribute.name] + attribute.adjustment
|
||||
end
|
||||
if upgrade.resistance then
|
||||
local field = upgrade.resistance.name
|
||||
if not unit.resistances[field] then
|
||||
unit.resistances[field] = {}
|
||||
end
|
||||
if upgrade.resistance.decrease then
|
||||
unit.resistances[field].decrease = (unit.resistances[field].decrease or 0) + upgrade.resistance.decrease
|
||||
end
|
||||
if upgrade.resistance.percentage then
|
||||
unit.resistances[field].percentage = (unit.resistances[field].percentage or 0) + upgrade.resistance.percentage
|
||||
end
|
||||
end
|
||||
if upgrade.attack then
|
||||
local attack = upgrade.attack
|
||||
unit.attack[attack.name] = (unit.attack[attack.name] or 0) + attack.adjustment
|
||||
end
|
||||
|
||||
remainingPoints = remainingPoints - cost
|
||||
end
|
||||
|
||||
local scale = gaussianRandomRange(unit.scale, unit.scale * 0.12, unit.scale * 0.60, unit.scale * 1.40) + (0.05 * t)
|
||||
local tint1 = {
|
||||
gaussianRandomRange(unit.tint1.r, unit.tint1.r * 0.06 + (0.005 * t), unit.tint1.r * 0.85 - (0.005 * t), unit.tint1.r * 1.15),
|
||||
gaussianRandomRange(unit.tint1.g, unit.tint1.g * 0.06 + (0.005 * t), unit.tint1.g * 0.85 - (0.005 * t), unit.tint1.g * 1.15),
|
||||
gaussianRandomRange(unit.tint1.b, unit.tint1.b * 0.06 + (0.005 * t), unit.tint1.b * 0.85 - (0.005 * t), unit.tint1.b * 1.15),
|
||||
gaussianRandomRange(unit.tint1.a, unit.tint1.a * 0.06 + (0.005 * t), unit.tint1.a * 0.85 - (0.005 * t), unit.tint1.a * 1.15)
|
||||
}
|
||||
local tint2 = {
|
||||
gaussianRandomRange(unit.tint2.r, unit.tint2.r * 0.06 + (0.005 * t), unit.tint2.r * 0.85 - (0.005 * t), unit.tint2.r * 1.15),
|
||||
gaussianRandomRange(unit.tint2.g, unit.tint2.g * 0.06 + (0.005 * t), unit.tint2.g * 0.85 - (0.005 * t), unit.tint2.g * 1.15),
|
||||
gaussianRandomRange(unit.tint2.b, unit.tint2.b * 0.06 + (0.005 * t), unit.tint2.b * 0.85 - (0.005 * t), unit.tint2.b * 1.15),
|
||||
gaussianRandomRange(unit.tint2.a, unit.tint2.a * 0.06 + (0.005 * t), unit.tint2.a * 0.85 - (0.005 * t), unit.tint2.a * 1.15)
|
||||
}
|
||||
generateApperance(unit, t)
|
||||
upgradeEntity(allottedPoints, unit, upgradeTable)
|
||||
|
||||
unit.attributes.scale = scale
|
||||
unit.attributes.tint1 = tint1
|
||||
unit.attributes.tint2 = tint2
|
||||
|
||||
unit.attack.scale = scale
|
||||
unit.attack.tint1 = tint1
|
||||
unit.attack.tint2 = tint2
|
||||
|
||||
|
||||
local entity
|
||||
if (unit.type == "spitter") then
|
||||
entity = makeSpitter(unit.name,
|
||||
@ -205,42 +245,8 @@ local function buildUnitSpawner(startingPoints, template, upgradeTable, unitTabl
|
||||
for i=1,variations do
|
||||
local unitSpawner = deepcopy(template)
|
||||
unitSpawner.name = unitSpawner.name .. "-v" .. i .. "-t" .. t
|
||||
local remainingPoints = allottedPoints
|
||||
while (remainingPoints > 0) do
|
||||
local upgrade = upgradeTable[mRandom(#upgradeTable)]
|
||||
|
||||
local cost = upgrade.cost
|
||||
if upgrade.attribute then
|
||||
local attribute = upgrade.attribute
|
||||
unitSpawner.attributes[attribute.name] = unitSpawner.attributes[attribute.name] + attribute.adjustment
|
||||
end
|
||||
if upgrade.resistance then
|
||||
local field = upgrade.resistance.name
|
||||
if not unitSpawner.resistances[field] then
|
||||
unitSpawner.resistances[field] = {}
|
||||
unitSpawner.resistances[field].type = field
|
||||
end
|
||||
if upgrade.resistance.decrease then
|
||||
unitSpawner.resistances[field].decrease = (unitSpawner.resistances[field].decrease or 0) + upgrade.resistance.decrease
|
||||
end
|
||||
if upgrade.resistance.percentage then
|
||||
unitSpawner.resistances[field].percentage = (unitSpawner.resistances[field].percentage or 0) + upgrade.resistance.percentage
|
||||
end
|
||||
end
|
||||
|
||||
remainingPoints = remainingPoints - cost
|
||||
end
|
||||
|
||||
local scale = gaussianRandomRange(unitSpawner.scale, unitSpawner.scale * 0.12, unitSpawner.scale * 0.60, unitSpawner.scale * 1.40) + (0.05 * t)
|
||||
local tint = {
|
||||
gaussianRandomRange(unitSpawner.tint1.r, unitSpawner.tint1.r * 0.06 + (0.005 * t), unitSpawner.tint1.r * 0.85 - (0.005 * t), unitSpawner.tint1.r * 1.15),
|
||||
gaussianRandomRange(unitSpawner.tint1.g, unitSpawner.tint1.g * 0.06 + (0.005 * t), unitSpawner.tint1.g * 0.85 - (0.005 * t), unitSpawner.tint1.g * 1.15),
|
||||
gaussianRandomRange(unitSpawner.tint1.b, unitSpawner.tint1.b * 0.06 + (0.005 * t), unitSpawner.tint1.b * 0.85 - (0.005 * t), unitSpawner.tint1.b * 1.15),
|
||||
gaussianRandomRange(unitSpawner.tint1.a, unitSpawner.tint1.a * 0.06 + (0.005 * t), unitSpawner.tint1.a * 0.85 - (0.005 * t), unitSpawner.tint1.a * 1.15)
|
||||
}
|
||||
|
||||
unitSpawner.attributes.scale = scale
|
||||
unitSpawner.attributes.tint = tint
|
||||
generateApperance(unitSpawner, t)
|
||||
upgradeEntity(allottedPoints, unitSpawner, upgradeTable)
|
||||
|
||||
data:extend({
|
||||
makeUnitSpawner(unitSpawner.name,
|
||||
@ -253,61 +259,16 @@ local function buildUnitSpawner(startingPoints, template, upgradeTable, unitTabl
|
||||
|
||||
end
|
||||
|
||||
local function buildWorm(startingPoints, template, attackGenerator, upgradeTable, variations, tiers)
|
||||
function swarmUtils.buildWorm(startingPoints, template, attackGenerator, upgradeTable, variations, tiers)
|
||||
for t=1, tiers do
|
||||
local allottedPoints = startingPoints * t
|
||||
|
||||
for i=1,variations do
|
||||
local worm = deepcopy(template)
|
||||
worm.name = worm.name .. "-v" .. i .. "-t" .. t
|
||||
local remainingPoints = allottedPoints
|
||||
while (remainingPoints > 0) do
|
||||
local upgrade = upgradeTable[mRandom(#upgradeTable)]
|
||||
|
||||
local cost = upgrade.cost
|
||||
if upgrade.attribute then
|
||||
local attribute = upgrade.attribute
|
||||
worm.attributes[attribute.name] = worm.attributes[attribute.name] + attribute.adjustment
|
||||
end
|
||||
if upgrade.resistance then
|
||||
local field = upgrade.resistance.name
|
||||
if not worm.resistances[field] then
|
||||
worm.resistances[field] = {}
|
||||
worm.resistances[field].type = field
|
||||
end
|
||||
if upgrade.resistance.decrease then
|
||||
worm.resistances[field].decrease = (worm.resistances[field].decrease or 0) + upgrade.resistance.decrease
|
||||
end
|
||||
if upgrade.resistance.percentage then
|
||||
worm.resistances[field].percentage = (worm.resistances[field].percentage or 0) + upgrade.resistance.percentage
|
||||
end
|
||||
end
|
||||
|
||||
remainingPoints = remainingPoints - cost
|
||||
end
|
||||
|
||||
local scale = gaussianRandomRange(worm.scale, worm.scale * 0.12, worm.scale * 0.60, worm.scale * 1.40) + (0.05 * t)
|
||||
local tint1 = {
|
||||
gaussianRandomRange(worm.tint1.r, worm.tint1.r * 0.06 + (0.005 * t), worm.tint1.r * 0.85 - (0.005 * t), worm.tint1.r * 1.15),
|
||||
gaussianRandomRange(worm.tint1.g, worm.tint1.g * 0.06 + (0.005 * t), worm.tint1.g * 0.85 - (0.005 * t), worm.tint1.g * 1.15),
|
||||
gaussianRandomRange(worm.tint1.b, worm.tint1.b * 0.06 + (0.005 * t), worm.tint1.b * 0.85 - (0.005 * t), worm.tint1.b * 1.15),
|
||||
gaussianRandomRange(worm.tint1.a, worm.tint1.a * 0.06 + (0.005 * t), worm.tint1.a * 0.85 - (0.005 * t), worm.tint1.a * 1.15)
|
||||
}
|
||||
local tint2 = {
|
||||
gaussianRandomRange(worm.tint2.r, worm.tint2.r * 0.06 + (0.005 * t), worm.tint2.r * 0.85 - (0.005 * t), worm.tint2.r * 1.15),
|
||||
gaussianRandomRange(worm.tint2.g, worm.tint2.g * 0.06 + (0.005 * t), worm.tint2.g * 0.85 - (0.005 * t), worm.tint2.g * 1.15),
|
||||
gaussianRandomRange(worm.tint2.b, worm.tint2.b * 0.06 + (0.005 * t), worm.tint2.b * 0.85 - (0.005 * t), worm.tint2.b * 1.15),
|
||||
gaussianRandomRange(worm.tint2.a, worm.tint2.a * 0.06 + (0.005 * t), worm.tint2.a * 0.85 - (0.005 * t), worm.tint2.a * 1.15)
|
||||
}
|
||||
|
||||
worm.attributes.scale = scale
|
||||
worm.attributes.tint1 = tint1
|
||||
worm.attributes.tint2 = tint2
|
||||
|
||||
worm.attack.scale = scale
|
||||
worm.attack.tint1 = tint1
|
||||
worm.attack.tint2 = tint2
|
||||
|
||||
generateApperance(worm, t)
|
||||
upgradeEntity(allottedPoints, worm, upgradeTable)
|
||||
|
||||
data:extend({
|
||||
makeWorm(worm.name,
|
||||
worm.attributes,
|
||||
@ -318,12 +279,10 @@ local function buildWorm(startingPoints, template, attackGenerator, upgradeTable
|
||||
end
|
||||
end
|
||||
|
||||
local function createUnitClass(points, templates, upgradeTable, attackGenerator, variations, tiers)
|
||||
function swarmUtils.createUnitClass(points, templates, upgradeTable, attackGenerator, variations, tiers)
|
||||
buildUnitSpawner(points.unitSpawner,
|
||||
templates.unitSpawner,
|
||||
upgradeTable.unitSpawner,
|
||||
variations.unitSpawner,
|
||||
tiers.unitSpawner,
|
||||
unitSetToProbabilityTable(points.probabilityTable,
|
||||
upgradeTable.probabilityTable,
|
||||
buildUnits(points.unit,
|
||||
@ -332,98 +291,8 @@ local function createUnitClass(points, templates, upgradeTable, attackGenerator,
|
||||
upgradeTable.unit,
|
||||
variations.unit,
|
||||
tiers.unit)),
|
||||
variations.unitSpawner,
|
||||
tiers.unitSpawner)
|
||||
end
|
||||
|
||||
createUnitClass({
|
||||
unit = 10,
|
||||
unitSpawner = 5,
|
||||
probabilityTable = 5
|
||||
},
|
||||
{
|
||||
unit = {
|
||||
name = "rampant-suicide-biter",
|
||||
attributes = {
|
||||
health = 30,
|
||||
movement = 0.21,
|
||||
distancePerFrame = 0.1,
|
||||
healing = 0.01,
|
||||
explosion = "blood-explosion-small",
|
||||
},
|
||||
attack = {
|
||||
area = 3.5,
|
||||
damage = 20,
|
||||
explosion = "explosion",
|
||||
scorchmark = "small-scorchmark",
|
||||
explosionCount = 2,
|
||||
explosionDistance = 2,
|
||||
},
|
||||
resistances = {
|
||||
explosion = {
|
||||
decrease = 0,
|
||||
percentage = -50
|
||||
},
|
||||
laser = {
|
||||
decrease = 1,
|
||||
percentage = 0
|
||||
},
|
||||
fire = {
|
||||
decrease = 0,
|
||||
percentage = -60
|
||||
}
|
||||
},
|
||||
type = "biter",
|
||||
scale = 0.55,
|
||||
tint1 = {r=0.6, g=0.0, b=0.70, a=0.8},
|
||||
tint2 = {r=0.7, g=0.0, b=0.72, a=0.4}
|
||||
},
|
||||
unitSpawner = {
|
||||
|
||||
scale = 0.55,
|
||||
tint1 = {},
|
||||
tint2 = {}
|
||||
}
|
||||
},
|
||||
{
|
||||
unit = {
|
||||
{
|
||||
cost = 1,
|
||||
attribute = {
|
||||
name = "health",
|
||||
adjustment = 50
|
||||
}
|
||||
}
|
||||
},
|
||||
unitSpawner = {
|
||||
{
|
||||
cost = 1,
|
||||
attribute = {
|
||||
name = "health",
|
||||
adjustment = 50
|
||||
}
|
||||
}
|
||||
},
|
||||
probabilityTable = {
|
||||
{
|
||||
cost = 1,
|
||||
index = 1,
|
||||
adjustment = 1
|
||||
}
|
||||
}
|
||||
},
|
||||
createSuicideAttack,
|
||||
{
|
||||
unit = 5,
|
||||
unitSpawner = 5
|
||||
},
|
||||
{
|
||||
unit = 7,
|
||||
unitSpawner = 7
|
||||
}
|
||||
)
|
||||
|
||||
local function dog(a)
|
||||
a[1] = 2
|
||||
end
|
||||
|
||||
dog()
|
||||
return swarmUtils
|
||||
|
188
UnitClasses.lua
Executable file
188
UnitClasses.lua
Executable file
@ -0,0 +1,188 @@
|
||||
-- imports
|
||||
|
||||
local biterUtils = require("prototypes/enemies/BiterUtils")
|
||||
local swarmUtils = require("Swarmutils")
|
||||
|
||||
-- imported functions
|
||||
|
||||
|
||||
|
||||
local createUnitClass = swarmUtils.createUnitClass
|
||||
|
||||
local createSuicideAttack = biterUtils.createSuicideAttack
|
||||
|
||||
|
||||
-- module code
|
||||
|
||||
createUnitClass(
|
||||
{
|
||||
unit = 10,
|
||||
unitSpawner = 5,
|
||||
probabilityTable = 5
|
||||
},
|
||||
{
|
||||
unit = {
|
||||
name = "rampant-suicide-biter",
|
||||
|
||||
attributes = {
|
||||
health = 30,
|
||||
movement = 0.21,
|
||||
distancePerFrame = 0.1,
|
||||
healing = 0.01,
|
||||
explosion = "blood-explosion-small",
|
||||
},
|
||||
|
||||
attack = {
|
||||
area = 3.5,
|
||||
damage = 20,
|
||||
explosion = "explosion",
|
||||
scorchmark = "small-scorchmark",
|
||||
explosionCount = 2,
|
||||
explosionDistance = 2,
|
||||
},
|
||||
|
||||
resistances = {
|
||||
explosion = {
|
||||
decrease = 0,
|
||||
percentage = -50
|
||||
},
|
||||
laser = {
|
||||
decrease = 1,
|
||||
percentage = 0
|
||||
},
|
||||
fire = {
|
||||
decrease = 0,
|
||||
percentage = -60
|
||||
}
|
||||
},
|
||||
|
||||
type = "biter",
|
||||
scale = 0.55,
|
||||
tint1 = {r=0.6, g=0.0, b=0.70, a=0.8},
|
||||
tint2 = {r=0.7, g=0.0, b=0.72, a=0.4}
|
||||
},
|
||||
|
||||
unitSpawner = {
|
||||
name = "rampant-suicide-nest",
|
||||
attributes = {
|
||||
health = 30,
|
||||
healing = 0.01,
|
||||
unitsOwned = 7,
|
||||
unitsToSpawn = 5,
|
||||
spawingCooldownStart = 360,
|
||||
spawingCooldownStop = 150,
|
||||
|
||||
},
|
||||
resistances = {
|
||||
explosion = {
|
||||
decrease = 0,
|
||||
percentage = -50
|
||||
},
|
||||
laser = {
|
||||
decrease = 1,
|
||||
percentage = 0
|
||||
},
|
||||
fire = {
|
||||
decrease = 0,
|
||||
percentage = -60
|
||||
}
|
||||
},
|
||||
scale = 0.95,
|
||||
tint = {r=0.7, g=0.0, b=0.72, a=0.4}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
unit = {
|
||||
{
|
||||
cost = 1,
|
||||
bonus = {
|
||||
{
|
||||
type = "attribute",
|
||||
name = "health",
|
||||
adjustment = 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
unitSpawner = {
|
||||
{
|
||||
cost = 1,
|
||||
bonus = {
|
||||
{
|
||||
type = "attribute",
|
||||
name = "health",
|
||||
adjustment = 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
probabilityTable = {
|
||||
{
|
||||
cost = 1,
|
||||
index = 1,
|
||||
adjustment = 1
|
||||
},
|
||||
{
|
||||
cost = 1,
|
||||
index = 2,
|
||||
adjustment = 1
|
||||
},
|
||||
{
|
||||
cost = 1,
|
||||
index = 3,
|
||||
adjustment = 1
|
||||
},
|
||||
{
|
||||
cost = 1,
|
||||
index = 4,
|
||||
adjustment = 1
|
||||
},
|
||||
{
|
||||
cost = 1,
|
||||
index = 5,
|
||||
adjustment = 1
|
||||
},
|
||||
{
|
||||
cost = 1,
|
||||
index = 6,
|
||||
adjustment = 1.5
|
||||
},
|
||||
{
|
||||
cost = 1,
|
||||
index = 7,
|
||||
adjustment = 2
|
||||
},
|
||||
{
|
||||
cost = 1,
|
||||
index = 8,
|
||||
adjustment = 2
|
||||
},
|
||||
{
|
||||
cost = 1,
|
||||
index = 9,
|
||||
adjustment = 1.5
|
||||
},
|
||||
{
|
||||
cost = 1,
|
||||
index = 10,
|
||||
adjustment = 1
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
createSuicideAttack,
|
||||
|
||||
{
|
||||
unit = 5,
|
||||
unitSpawner = 5
|
||||
},
|
||||
|
||||
{
|
||||
unit = 10,
|
||||
unitSpawner = 7
|
||||
}
|
||||
)
|
||||
|
10
data.lua
10
data.lua
@ -8,10 +8,10 @@ require("prototypes/tile/fillableDirt")
|
||||
|
||||
|
||||
|
||||
-- if settings.startup["rampant-newEnemies"].value then
|
||||
if settings.startup["rampant-newEnemies"].value then
|
||||
require("BuildSwarm")
|
||||
-- end
|
||||
end
|
||||
|
||||
require("prototypes/enemies/UnitSuicideBiters")
|
||||
require("prototypes/enemies/UnitFireSpitters")
|
||||
require("prototypes/enemies/UnitTendril")
|
||||
-- require("prototypes/enemies/UnitSuicideBiters")
|
||||
-- require("prototypes/enemies/UnitFireSpitters")
|
||||
-- require("prototypes/enemies/UnitTendril")
|
||||
|
@ -16,9 +16,8 @@ local mMax = math.max
|
||||
local mSqrt = math.sqrt
|
||||
local mLog10 = math.log10
|
||||
|
||||
local mFloor = math.floor
|
||||
|
||||
local mRandom = math.random
|
||||
local mFloor = math.floor
|
||||
|
||||
-- module code
|
||||
|
||||
@ -33,37 +32,98 @@ function mathUtils.randomTickEvent(tick, low, high)
|
||||
return tick + nextTick
|
||||
end
|
||||
|
||||
function mathUtils.xorRandom(state)
|
||||
local xor = bit32.bxor
|
||||
local lshift = bit32.lshift
|
||||
local rshift = bit32.rshift
|
||||
|
||||
state = state + 21594771
|
||||
|
||||
return function()
|
||||
state = xor(state, lshift(state, 13))
|
||||
state = xor(state, rshift(state, 17))
|
||||
state = xor(state, lshift(state, 5))
|
||||
state = state % 2147483647
|
||||
return state * 4.65661287525e-10
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
Used for gaussian random numbers
|
||||
--]]
|
||||
local function marsagliaPolarMethod(rg)
|
||||
function mathUtils.gaussianRandom(mean, std_dev)
|
||||
-- marsagliaPolarMethod
|
||||
local iid1
|
||||
local iid2
|
||||
local q
|
||||
repeat
|
||||
if rg then
|
||||
iid1 = 2 * rg() + -1
|
||||
iid2 = 2 * rg() + -1
|
||||
else
|
||||
iid1 = 2 * mRandom() + -1
|
||||
iid2 = 2 * mRandom() + -1
|
||||
end
|
||||
iid1 = 2 * mRandom() + -1
|
||||
iid2 = 2 * mRandom() + -1
|
||||
q = (iid1 * iid1) + (iid2 * iid2)
|
||||
until (q ~= 0) and (q < 1)
|
||||
local s = mSqrt((-2 * mLog10(q)) / q)
|
||||
return iid1 * s
|
||||
local v = iid1 * s
|
||||
|
||||
return mean + (v * std_dev)
|
||||
end
|
||||
|
||||
function mathUtils.gaussianRandom(mean, std_dev, rg)
|
||||
return mean + (marsagliaPolarMethod(rg) * std_dev)
|
||||
end
|
||||
|
||||
function mathUtils.gaussianRandomRange(mean, std_dev, min, max, rg)
|
||||
local q
|
||||
function mathUtils.gaussianRandomRange(mean, std_dev, min, max)
|
||||
if (min == max) then
|
||||
return min
|
||||
end
|
||||
local r
|
||||
repeat
|
||||
q = mathUtils.gaussianRandom(mean, std_dev, rg)
|
||||
until (q >= min) and (q <= max)
|
||||
return q
|
||||
local iid1
|
||||
local iid2
|
||||
local q
|
||||
repeat
|
||||
iid1 = 2 * mRandom() + -1
|
||||
iid2 = 2 * mRandom() + -1
|
||||
q = (iid1 * iid1) + (iid2 * iid2)
|
||||
until (q ~= 0) and (q < 1)
|
||||
local s = mSqrt((-2 * mLog10(q)) / q)
|
||||
local v = iid1 * s
|
||||
|
||||
r = mean + (v * std_dev)
|
||||
until (r >= min) and (r <= max)
|
||||
return r
|
||||
end
|
||||
|
||||
function mathUtils.gaussianRandomRG(mean, std_dev, rg)
|
||||
-- marsagliaPolarMethod
|
||||
local iid1
|
||||
local iid2
|
||||
local q
|
||||
repeat
|
||||
iid1 = 2 * rg() + -1
|
||||
iid2 = 2 * rg() + -1
|
||||
q = (iid1 * iid1) + (iid2 * iid2)
|
||||
until (q ~= 0) and (q < 1)
|
||||
local s = mSqrt((-2 * mLog10(q)) / q)
|
||||
local v = iid1 * s
|
||||
|
||||
return mean + (v * std_dev)
|
||||
end
|
||||
|
||||
function mathUtils.gaussianRandomRangeRG(mean, std_dev, min, max, rg)
|
||||
local r
|
||||
if (min == max) then
|
||||
return min
|
||||
end
|
||||
repeat
|
||||
local iid1
|
||||
local iid2
|
||||
local q
|
||||
repeat
|
||||
iid1 = 2 * rg() + -1
|
||||
iid2 = 2 * rg() + -1
|
||||
q = (iid1 * iid1) + (iid2 * iid2)
|
||||
until (q ~= 0) and (q < 1)
|
||||
local s = mSqrt((-2 * mLog10(q)) / q)
|
||||
local v = iid1 * s
|
||||
r = mean + (v * std_dev)
|
||||
until (r >= min) and (r <= max)
|
||||
return r
|
||||
end
|
||||
|
||||
function mathUtils.euclideanDistanceNamed(p1, p2)
|
||||
|
@ -1,6 +1,12 @@
|
||||
local biterFunctions = {}
|
||||
|
||||
function biterFunctions.makeBiter(name, biterAttributes, biterAttack, biterResistances)
|
||||
local resistances = {}
|
||||
for k,v in pairs(biterResistances) do
|
||||
v.type = k
|
||||
resistances[#resistances+1] = v
|
||||
end
|
||||
|
||||
return {
|
||||
type = "unit",
|
||||
name = name,
|
||||
@ -11,7 +17,7 @@ function biterFunctions.makeBiter(name, biterAttributes, biterAttack, biterResis
|
||||
order = "b-b-a",
|
||||
subgroup="enemies",
|
||||
healing_per_tick = biterAttributes.healing,
|
||||
resistances = biterResistances,
|
||||
resistances = resistances,
|
||||
collision_box = {{-0.4 * biterAttributes.scale, -0.4 * biterAttributes.scale},
|
||||
{0.4 * biterAttributes.scale, 0.4 * biterAttributes.scale}},
|
||||
selection_box = {{-0.7 * biterAttributes.scale, -1.5 * biterAttributes.scale},
|
||||
@ -33,6 +39,12 @@ function biterFunctions.makeBiter(name, biterAttributes, biterAttack, biterResis
|
||||
end
|
||||
|
||||
function biterFunctions.makeSpitter(name, biterAttributes, biterAttack, biterResistances)
|
||||
local resistances = {}
|
||||
for k,v in pairs(biterResistances) do
|
||||
v.type = k
|
||||
resistances[#resistances+1] = v
|
||||
end
|
||||
|
||||
return {
|
||||
type = "unit",
|
||||
name = name,
|
||||
@ -43,7 +55,7 @@ function biterFunctions.makeSpitter(name, biterAttributes, biterAttack, biterRes
|
||||
order = "b-b-a",
|
||||
subgroup="enemies",
|
||||
healing_per_tick = biterAttributes.healing,
|
||||
resistances = biterResistances,
|
||||
resistances = resistances,
|
||||
collision_box = {{-0.4 * biterAttributes.scale, -0.4 * biterAttributes.scale},
|
||||
{0.4 * biterAttributes.scale, 0.4 * biterAttributes.scale}},
|
||||
selection_box = {{-0.7 * biterAttributes.scale, -1.5 * biterAttributes.scale},
|
||||
@ -65,62 +77,69 @@ function biterFunctions.makeSpitter(name, biterAttributes, biterAttack, biterRes
|
||||
end
|
||||
|
||||
function biterFunctions.makeUnitSpawner(name, biterAttributes, biterResistances, unitSet)
|
||||
local resistances = {}
|
||||
for k,v in pairs(biterResistances) do
|
||||
v.type = k
|
||||
resistances[#resistances+1] = v
|
||||
end
|
||||
|
||||
local o = {
|
||||
type = "unit-spawner",
|
||||
name = name,
|
||||
icon = "__base__/graphics/icons/biter-spawner.png",
|
||||
icon_size = 32,
|
||||
flags = {"placeable-player", "placeable-enemy", "not-repairable"},
|
||||
max_health = biterAttributes.health,
|
||||
order="b-b-g",
|
||||
subgroup="enemies",
|
||||
resistances = biterResistances,
|
||||
working_sound = {
|
||||
sound =
|
||||
{
|
||||
{
|
||||
filename = "__base__/sound/creatures/spawner.ogg",
|
||||
volume = 1.0
|
||||
}
|
||||
},
|
||||
apparent_volume = 2
|
||||
},
|
||||
dying_sound =
|
||||
{
|
||||
{
|
||||
filename = "__base__/sound/creatures/spawner-death-1.ogg",
|
||||
volume = 1.0
|
||||
},
|
||||
{
|
||||
filename = "__base__/sound/creatures/spawner-death-2.ogg",
|
||||
volume = 1.0
|
||||
}
|
||||
},
|
||||
healing_per_tick = biterAttributes.healing or 0.02,
|
||||
collision_box = {{-3.2 * biterAttributes.scale, -2.2 * biterAttributes.scale}, {2.2 * biterAttributes.scale, 2.2 * biterAttributes.scale}},
|
||||
selection_box = {{-3.5 * biterAttributes.scale, -2.5 * biterAttributes.scale}, {2.5 * biterAttributes.scale, 2.5 * biterAttributes.scale}},
|
||||
-- in ticks per 1 pu
|
||||
pollution_absorbtion_absolute = biterAttributes.pollutionAbsorbtionAbs or 20,
|
||||
pollution_absorbtion_proportional = biterAttributes.pollutionAbsorbtionPro or 0.01,
|
||||
corpse = "biter-spawner-corpse",
|
||||
dying_explosion = "blood-explosion-huge",
|
||||
max_count_of_owned_units = biterAttributes.unitsOwned or 7,
|
||||
max_friends_around_to_spawn = biterAttributes.unitsToSpawn or 5,
|
||||
animations =
|
||||
{
|
||||
spawner_idle_animation(0, biterAttributes.tint),
|
||||
spawner_idle_animation(1, biterAttributes.tint),
|
||||
spawner_idle_animation(2, biterAttributes.tint),
|
||||
spawner_idle_animation(3, biterAttributes.tint)
|
||||
},
|
||||
result_units = unitSet,
|
||||
-- With zero evolution the spawn rate is 6 seconds, with max evolution it is 2.5 seconds
|
||||
spawning_cooldown = biterAttributes.spawningCooldown or {360, 150},
|
||||
spawning_radius = biterAttributes.spawningRadius or 10,
|
||||
spawning_spacing = biterAttributes.spawningSpacing or 3,
|
||||
max_spawn_shift = 0,
|
||||
max_richness_for_spawn_shift = 100,
|
||||
call_for_help_radius = 50
|
||||
type = "unit-spawner",
|
||||
name = name,
|
||||
icon = "__base__/graphics/icons/biter-spawner.png",
|
||||
icon_size = 32,
|
||||
flags = {"placeable-player", "placeable-enemy", "not-repairable"},
|
||||
max_health = biterAttributes.health,
|
||||
order="b-b-g",
|
||||
subgroup="enemies",
|
||||
resistances = resistances,
|
||||
working_sound = {
|
||||
sound =
|
||||
{
|
||||
{
|
||||
filename = "__base__/sound/creatures/spawner.ogg",
|
||||
volume = 1.0
|
||||
}
|
||||
},
|
||||
apparent_volume = 2
|
||||
},
|
||||
dying_sound =
|
||||
{
|
||||
{
|
||||
filename = "__base__/sound/creatures/spawner-death-1.ogg",
|
||||
volume = 1.0
|
||||
},
|
||||
{
|
||||
filename = "__base__/sound/creatures/spawner-death-2.ogg",
|
||||
volume = 1.0
|
||||
}
|
||||
},
|
||||
healing_per_tick = biterAttributes.healing or 0.02,
|
||||
collision_box = {{-3.2 * biterAttributes.scale, -2.2 * biterAttributes.scale}, {2.2 * biterAttributes.scale, 2.2 * biterAttributes.scale}},
|
||||
selection_box = {{-3.5 * biterAttributes.scale, -2.5 * biterAttributes.scale}, {2.5 * biterAttributes.scale, 2.5 * biterAttributes.scale}},
|
||||
-- in ticks per 1 pu
|
||||
pollution_absorbtion_absolute = biterAttributes.pollutionAbsorbtionAbs or 20,
|
||||
pollution_absorbtion_proportional = biterAttributes.pollutionAbsorbtionPro or 0.01,
|
||||
corpse = "biter-spawner-corpse",
|
||||
dying_explosion = "blood-explosion-huge",
|
||||
max_count_of_owned_units = biterAttributes.unitsOwned or 7,
|
||||
max_friends_around_to_spawn = biterAttributes.unitsToSpawn or 5,
|
||||
animations =
|
||||
{
|
||||
spawner_idle_animation(0, biterAttributes.tint),
|
||||
spawner_idle_animation(1, biterAttributes.tint),
|
||||
spawner_idle_animation(2, biterAttributes.tint),
|
||||
spawner_idle_animation(3, biterAttributes.tint)
|
||||
},
|
||||
result_units = unitSet,
|
||||
-- With zero evolution the spawn rate is 6 seconds, with max evolution it is 2.5 seconds
|
||||
spawning_cooldown = biterAttributes.spawningCooldown or {360, 150},
|
||||
spawning_radius = biterAttributes.spawningRadius or 10,
|
||||
spawning_spacing = biterAttributes.spawningSpacing or 3,
|
||||
max_spawn_shift = 0,
|
||||
max_richness_for_spawn_shift = 100,
|
||||
build_base_evolution_requirement = biterAttributes.evolutionRequirement or 0.0,
|
||||
call_for_help_radius = 50
|
||||
}
|
||||
if biterAttributes.autoplace then
|
||||
o["autoplace"] = enemy_spawner_autoplace(biterAttributes.autoplace)
|
||||
@ -128,6 +147,57 @@ function biterFunctions.makeUnitSpawner(name, biterAttributes, biterResistances,
|
||||
return o
|
||||
end
|
||||
|
||||
function biterFunctions.makeWorm(name, attributes, attack, wormResistances)
|
||||
local resistances = {}
|
||||
for k,v in pairs(wormResistances) do
|
||||
v.type = k
|
||||
resistances[#resistances+1] = v
|
||||
end
|
||||
|
||||
local o = {
|
||||
type = "turret",
|
||||
name = name,
|
||||
icon = "__base__/graphics/icons/medium-worm.png",
|
||||
icon_size = 32,
|
||||
flags = attributes.flags or {"placeable-player", "placeable-enemy", "not-repairable", "breaths-air"},
|
||||
order="b-b-e",
|
||||
subgroup="enemies",
|
||||
max_health = attributes.health,
|
||||
resistances = resistances,
|
||||
healing_per_tick = attributes.healing or 0.01,
|
||||
collision_box = {{-1.1 * attributes.scale, -1.0 * attributes.scale}, {1.1 * attributes.scale, 1.0 * attributes.scale}},
|
||||
selection_box = {{-1.1 * attributes.scale, -1.0 * attributes.scale}, {1.1 * attributes.scale, 1.0 * attributes.scale}},
|
||||
shooting_cursor_size = attributes.cursorSize or 3,
|
||||
rotation_speed = attributes.rotationSpeed or 1,
|
||||
corpse = "medium-worm-corpse",
|
||||
dying_explosion = "blood-explosion-big",
|
||||
dying_sound = make_worm_dying_sounds(0.9),
|
||||
folded_speed = attributes.foldedSpeed or 0.01,
|
||||
folded_animation = worm_folded_animation(attributes.scale, attributes.tint),
|
||||
preparing_speed = attributes.preparingSpeed or 0.025,
|
||||
preparing_animation = worm_preparing_animation(attributes.scale, attributes.tint, "forward"),
|
||||
prepared_speed = attributes.preparedSpeed or 0.015,
|
||||
prepared_animation = worm_prepared_animation(attributes.scale, attributes.tint),
|
||||
starting_attack_speed = attributes.attackSpeed or 0.03,
|
||||
starting_attack_animation = worm_attack_animation(attributes.scale, attributes.tint, "forward"),
|
||||
starting_attack_sound = make_worm_roars(0.8),
|
||||
ending_attack_speed = attributes.endingAttackSpeed or 0.03,
|
||||
ending_attack_animation = worm_attack_animation(attributes.scale, attributes.tint, "backward"),
|
||||
folding_speed = attributes.foldingSpeed or 0.015,
|
||||
folding_animation = worm_preparing_animation(attributes.scale, attributes.tint, "backward"),
|
||||
prepare_range = attributes.prepareRange or 30,
|
||||
attack_parameters = attack,
|
||||
build_base_evolution_requirement = attributes.evolutionRequirement or 0.0,
|
||||
call_for_help_radius = 40
|
||||
}
|
||||
|
||||
if attributes.autoplace then
|
||||
o["autoplace"] = enemy_worm_autoplace(attributes.autoplace)
|
||||
end
|
||||
return o
|
||||
|
||||
end
|
||||
|
||||
function biterFunctions.createSuicideAttack(attributes)
|
||||
return { type = "projectile",
|
||||
range = 0.5,
|
||||
|
22
settings.lua
22
settings.lua
@ -212,7 +212,29 @@ data:extend({
|
||||
default_value = true,
|
||||
order = "k[modifier]-a[unit]",
|
||||
per_user = false
|
||||
},
|
||||
|
||||
{
|
||||
type = "int-setting",
|
||||
name = "rampant-enemySeed",
|
||||
description = "rampant-enemySeed",
|
||||
setting_type = "startup",
|
||||
minimum_value = 0,
|
||||
default_value = 0,
|
||||
order = "l[modifer]-a[seed]",
|
||||
per_user = false
|
||||
},
|
||||
|
||||
{
|
||||
type = "bool-setting",
|
||||
name = "rampant-newEnemies",
|
||||
description = "rampant-newEnemies",
|
||||
setting_type = "startup",
|
||||
default_value = true,
|
||||
order = "l[modifier]-b[unit]",
|
||||
per_user = false
|
||||
}
|
||||
|
||||
|
||||
-- {
|
||||
-- type = "bool-setting",
|
||||
|
Loading…
x
Reference in New Issue
Block a user