mirror of
https://github.com/veden/Rampant.git
synced 2026-06-19 22:15:20 +02:00
refactoring files for movement code and tendril stuff
This commit is contained in:
@@ -56,6 +56,9 @@ Configure Options not in game menu:
|
||||
|
||||
# Version History
|
||||
|
||||
0.15.16 -
|
||||
|
||||
|
||||
0.15.15 -
|
||||
- Fixed: Desync when reindexing chunks (https://forums.factorio.com/viewtopic.php?f=94&t=31445&start=180#p287941)
|
||||
- Fixed: Switched from "and" to "or" for player pheromone and base pheromone to form squads
|
||||
|
||||
+10
-10
@@ -8,9 +8,9 @@ local baseProcessor = require("libs/BaseProcessor")
|
||||
local mapProcessor = require("libs/MapProcessor")
|
||||
local constants = require("libs/Constants")
|
||||
local pheromoneUtils = require("libs/PheromoneUtils")
|
||||
local aiDefense = require("libs/AIDefense")
|
||||
local aiAttack = require("libs/AIAttack")
|
||||
local aiBuilding = require("libs/AIBuilding")
|
||||
local squadDefense = require("libs/SquadDefense")
|
||||
local squadAttack = require("libs/SquadAttack")
|
||||
local aiAttackWave = require("libs/AIAttackWave")
|
||||
local aiPlanning = require("libs/AIPlanning")
|
||||
local interop = require("libs/Interop")
|
||||
local tests = require("tests")
|
||||
@@ -44,7 +44,7 @@ local scanMap = mapProcessor.scanMap
|
||||
|
||||
local planning = aiPlanning.planning
|
||||
|
||||
local rallyUnits = aiBuilding.rallyUnits
|
||||
local rallyUnits = aiAttackWave.rallyUnits
|
||||
|
||||
local deathScent = pheromoneUtils.deathScent
|
||||
local victoryScent = pheromoneUtils.victoryScent
|
||||
@@ -53,10 +53,10 @@ local cleanSquads = unitGroupUtils.cleanSquads
|
||||
local regroupSquads = unitGroupUtils.regroupSquads
|
||||
local convertUnitGroupToSquad = unitGroupUtils.convertUnitGroupToSquad
|
||||
|
||||
local squadAttack = aiAttack.squadAttack
|
||||
local squadBeginAttack = aiAttack.squadBeginAttack
|
||||
local squadsAttack = squadAttack.squadsAttack
|
||||
local squadsBeginAttack = squadAttack.squadsBeginAttack
|
||||
|
||||
local retreatUnits = aiDefense.retreatUnits
|
||||
local retreatUnits = squadDefense.retreatUnits
|
||||
|
||||
local addRemovePlayerEntity = entityUtils.addRemovePlayerEntity
|
||||
local unregisterEnemyBaseStructure = baseRegisterUtils.unregisterEnemyBaseStructure
|
||||
@@ -209,8 +209,8 @@ local function onTick(event)
|
||||
processBases(regionMap, surface, natives, tick)
|
||||
end
|
||||
|
||||
squadBeginAttack(natives, players)
|
||||
squadAttack(regionMap, surface, natives)
|
||||
squadsBeginAttack(natives, players)
|
||||
squadsAttack(regionMap, surface, natives)
|
||||
end
|
||||
|
||||
processMap(regionMap, surface, natives, tick)
|
||||
@@ -316,7 +316,7 @@ end
|
||||
local function onSurfaceTileChange(event)
|
||||
-- local player = game.players[event.player_index]
|
||||
-- if (player.surface.index == 1) then
|
||||
-- aiBuilding.fillTunnel(regionMap, player.surface, natives, event.positions)
|
||||
-- aiAttackWave.fillTunnel(regionMap, player.surface, natives, event.positions)
|
||||
-- end
|
||||
end
|
||||
|
||||
|
||||
@@ -8,3 +8,4 @@ require("prototypes/tile/fillableDirt")
|
||||
|
||||
require("prototypes/enemies/UnitSuicideBiters")
|
||||
require("prototypes/enemies/UnitFireSpitters")
|
||||
require("prototypes/enemies/UnitTendril")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
local aiBuilding = {}
|
||||
local aiAttackWave = {}
|
||||
|
||||
-- imports
|
||||
|
||||
@@ -76,7 +76,7 @@ local function validUnitGroupLocation(neighborChunk)
|
||||
return (neighborChunk[PASSABLE] == CHUNK_ALL_DIRECTIONS) and (neighborChunk[NEST_COUNT] == 0)
|
||||
end
|
||||
|
||||
function aiBuilding.rallyUnits(chunk, regionMap, surface, natives, tick)
|
||||
function aiAttackWave.rallyUnits(chunk, regionMap, surface, natives, tick)
|
||||
if (tick - chunk[RALLY_TRIGGERED] > INTERVAL_LOGIC) and (natives.points >= AI_VENGENCE_SQUAD_COST) then
|
||||
chunk[RALLY_TRIGGERED] = tick
|
||||
local cX = chunk.cX
|
||||
@@ -86,7 +86,7 @@ function aiBuilding.rallyUnits(chunk, regionMap, surface, natives, tick)
|
||||
if (x ~= cX) and (y ~= cY) then
|
||||
local rallyChunk = getChunkByIndex(regionMap, x, y)
|
||||
if rallyChunk and (rallyChunk[NEST_COUNT] ~= 0) then
|
||||
aiBuilding.formSquads(regionMap, surface, natives, rallyChunk, AI_VENGENCE_SQUAD_COST)
|
||||
aiAttackWave.formSquads(regionMap, surface, natives, rallyChunk, AI_VENGENCE_SQUAD_COST)
|
||||
if (natives.points < AI_VENGENCE_SQUAD_COST) then
|
||||
return
|
||||
end
|
||||
@@ -97,7 +97,7 @@ function aiBuilding.rallyUnits(chunk, regionMap, surface, natives, tick)
|
||||
end
|
||||
end
|
||||
|
||||
function aiBuilding.formSquads(regionMap, surface, natives, chunk, cost)
|
||||
function aiAttackWave.formSquads(regionMap, surface, natives, chunk, cost)
|
||||
local valid = (cost == AI_VENGENCE_SQUAD_COST) or ((cost == AI_SQUAD_COST) and attackWaveValidCandidate(chunk, natives, surface))
|
||||
|
||||
if valid and (math.random() < natives.formSquadThreshold) then
|
||||
@@ -131,4 +131,4 @@ function aiBuilding.formSquads(regionMap, surface, natives, chunk, cost)
|
||||
end
|
||||
end
|
||||
|
||||
return aiBuilding
|
||||
return aiAttackWave
|
||||
@@ -2,7 +2,7 @@ local baseProcessor = {}
|
||||
|
||||
-- imports
|
||||
|
||||
local baseUtils = require("BaseUtils")
|
||||
local buildUtils = require("BuildUtils")
|
||||
local tendrilUtils = require("TendrilUtils")
|
||||
local constants = require("Constants")
|
||||
|
||||
@@ -14,7 +14,7 @@ local BASE_QUEUE_SIZE = constants.BASE_QUEUE_SIZE
|
||||
|
||||
local mMin = math.min
|
||||
|
||||
local buildOrder = baseUtils.buildOrder
|
||||
local buildOrder = buildUtils.buildOrder
|
||||
local advanceTendrils = tendrilUtils.advanceTendrils
|
||||
|
||||
-- module code
|
||||
@@ -28,7 +28,7 @@ function baseProcessor.processBases(regionMap, surface, natives, tick)
|
||||
local base = bases[index]
|
||||
|
||||
buildOrder(regionMap, natives, base, surface, tick)
|
||||
advanceTendrils(regionMap, base, surface, tick)
|
||||
advanceTendrils(regionMap, base, surface, tick, natives)
|
||||
end
|
||||
|
||||
if (endIndex == #bases) then
|
||||
|
||||
+4
-81
@@ -4,23 +4,17 @@ local baseUtils = {}
|
||||
|
||||
local mapUtils = require("MapUtils")
|
||||
local constants = require("Constants")
|
||||
local mathUtils = require("MathUtils")
|
||||
|
||||
local baseRegisterUtils = require("BaseRegisterUtils")
|
||||
|
||||
local tendrilUtils = require("TendrilUtils")
|
||||
|
||||
local buildUtils = require("BuildUtils")
|
||||
|
||||
-- constants
|
||||
|
||||
local BASE_DISTANCE_THRESHOLD = constants.BASE_DISTANCE_THRESHOLD
|
||||
|
||||
local BASE_ALIGNMENT_NEUTRAL = constants.BASE_ALIGNMENT_NEUTRAL
|
||||
|
||||
local AI_NEST_COST = constants.AI_NEST_COST
|
||||
local AI_WORM_COST = constants.AI_WORM_COST
|
||||
|
||||
local DOUBLE_CHUNK_SIZE = constants.DOUBLE_CHUNK_SIZE
|
||||
|
||||
local MAGIC_MAXIMUM_NUMBER = constants.MAGIC_MAXIMUM_NUMBER
|
||||
local MAGIC_MAXIMUM_BASE_NUMBER = constants.MAGIC_MAXIMUM_BASE_NUMBER
|
||||
|
||||
@@ -28,14 +22,12 @@ local MAGIC_MAXIMUM_BASE_NUMBER = constants.MAGIC_MAXIMUM_BASE_NUMBER
|
||||
|
||||
local euclideanDistancePoints = mapUtils.euclideanDistancePoints
|
||||
|
||||
local gaussianRandomRange = mathUtils.gaussianRandomRange
|
||||
local buildHive = buildUtils.buildHive
|
||||
|
||||
local mFloor = math.floor
|
||||
|
||||
local buildTendril = tendrilUtils.buildTendril
|
||||
|
||||
local registerEnemyBaseStructure = baseRegisterUtils.registerEnemyBaseStructure
|
||||
|
||||
-- module code
|
||||
|
||||
function baseUtils.findNearbyBase(natives, position)
|
||||
@@ -53,75 +45,6 @@ function baseUtils.findNearbyBase(natives, position)
|
||||
return foundBase
|
||||
end
|
||||
|
||||
function baseUtils.buildHive(regionMap, base, surface)
|
||||
local valid = false
|
||||
local position = surface.find_non_colliding_position("biter-spawner-hive", base, DOUBLE_CHUNK_SIZE, 2)
|
||||
if position then
|
||||
local biterSpawner = {name="biter-spawner-hive", position=position}
|
||||
local hive = surface.create_entity(biterSpawner)
|
||||
if (#base.hives == 0) then
|
||||
base.x = hive.position.x
|
||||
base.y = hive.position.y
|
||||
end
|
||||
base.hives[#base.hives+1] = hive
|
||||
registerEnemyBaseStructure(regionMap, hive, base)
|
||||
valid = true
|
||||
end
|
||||
return valid
|
||||
end
|
||||
|
||||
function baseUtils.buildOutpost(natives, base, surface, tick, position)
|
||||
|
||||
end
|
||||
|
||||
function baseUtils.buildOrder(regionMap, natives, base, surface, tick)
|
||||
local foundHive = false
|
||||
for _,_ in pairs(base.hives) do
|
||||
foundHive = true
|
||||
break
|
||||
end
|
||||
if not foundHive or (base.upgradePoints < 10) then
|
||||
return
|
||||
end
|
||||
|
||||
local generator = natives.randomGenerator
|
||||
generator.re_seed(base.pattern)
|
||||
|
||||
for level=0,base.level do
|
||||
local slices = (level * 3)
|
||||
slices = gaussianRandomRange(slices, slices * 0.1, slices * 0.6, slices * 1.4, generator)
|
||||
local slice = (2 * math.pi) / slices
|
||||
local pos = 0
|
||||
local thing
|
||||
local cost
|
||||
local radiusAdjustment
|
||||
if (generator() < 0.3) then
|
||||
thing = "small-worm-turret"
|
||||
cost = AI_WORM_COST
|
||||
radiusAdjustment = -4
|
||||
else
|
||||
thing = "biter-spawner"
|
||||
cost = AI_NEST_COST
|
||||
radiusAdjustment = 0
|
||||
end
|
||||
for _ = 1, slices do
|
||||
if (base.upgradePoints < 10) then
|
||||
return
|
||||
end
|
||||
local radius = 10 * level
|
||||
local distortion = gaussianRandomRange(radius, 10, radius - 7.5 + radiusAdjustment, radius + 7.5 + radiusAdjustment, generator)
|
||||
local nestPosition = {x = base.x + (distortion * math.cos(pos)),
|
||||
y = base.y + (distortion * math.sin(pos))}
|
||||
local biterSpawner = {name=thing, position=nestPosition}
|
||||
if surface.can_place_entity(biterSpawner) then
|
||||
registerEnemyBaseStructure(regionMap, surface.create_entity(biterSpawner), base)
|
||||
base.upgradePoints = base.upgradePoints - cost
|
||||
end
|
||||
pos = pos + slice
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function baseUtils.createBase(regionMap, natives, position, surface, tick)
|
||||
local bases = natives.bases
|
||||
local distance = euclideanDistancePoints(position.x, position.y, 0, 0)
|
||||
@@ -140,7 +63,7 @@ function baseUtils.createBase(regionMap, natives, position, surface, tick)
|
||||
pattern = math.random(MAGIC_MAXIMUM_BASE_NUMBER),
|
||||
level = mFloor(distance / 200)
|
||||
}
|
||||
if not baseUtils.buildHive(regionMap, base, surface) then
|
||||
if not buildHive(regionMap, base, surface) then
|
||||
return nil
|
||||
end
|
||||
buildTendril(regionMap, natives, base, surface, tick)
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
local buildUtils = {}
|
||||
|
||||
-- imports
|
||||
|
||||
local constants = require("Constants")
|
||||
local mathUtils = require("MathUtils")
|
||||
|
||||
local baseRegisterUtils = require("BaseRegisterUtils")
|
||||
|
||||
-- constants
|
||||
|
||||
local MAGIC_MAXIMUM_BASE_NUMBER = constants.MAGIC_MAXIMUM_BASE_NUMBER
|
||||
|
||||
-- imported functions
|
||||
|
||||
local AI_NEST_COST = constants.AI_NEST_COST
|
||||
local AI_WORM_COST = constants.AI_WORM_COST
|
||||
|
||||
local DOUBLE_CHUNK_SIZE = constants.DOUBLE_CHUNK_SIZE
|
||||
|
||||
local registerEnemyBaseStructure = baseRegisterUtils.registerEnemyBaseStructure
|
||||
local gaussianRandomRange = mathUtils.gaussianRandomRange
|
||||
|
||||
-- module code
|
||||
|
||||
function buildUtils.buildHive(regionMap, base, surface)
|
||||
local valid = false
|
||||
local position = surface.find_non_colliding_position("biter-spawner-hive", base, DOUBLE_CHUNK_SIZE, 2)
|
||||
if position then
|
||||
local biterSpawner = {name="biter-spawner-hive", position=position}
|
||||
local hive = surface.create_entity(biterSpawner)
|
||||
if (#base.hives == 0) then
|
||||
base.x = hive.position.x
|
||||
base.y = hive.position.y
|
||||
end
|
||||
base.hives[#base.hives+1] = hive
|
||||
registerEnemyBaseStructure(regionMap, hive, base)
|
||||
valid = true
|
||||
end
|
||||
return valid
|
||||
end
|
||||
|
||||
function buildUtils.buildOutpost(regionMap, natives, base, surface, position)
|
||||
local foundHive = false
|
||||
for _,_ in pairs(base.hives) do
|
||||
foundHive = true
|
||||
break
|
||||
end
|
||||
if not foundHive or (base.upgradePoints < 10) then
|
||||
return
|
||||
end
|
||||
|
||||
local generator = natives.randomGenerator
|
||||
generator.re_seed(math.random(MAGIC_MAXIMUM_BASE_NUMBER))
|
||||
|
||||
for level=0,(base.level * 0.5) do
|
||||
local slices = (level * 3)
|
||||
slices = gaussianRandomRange(slices, slices * 0.1, slices * 0.6, slices * 1.4, generator)
|
||||
local slice = (2 * math.pi) / slices
|
||||
local pos = 0
|
||||
local thing
|
||||
local cost
|
||||
local radiusAdjustment
|
||||
if (generator() < 0.3) then
|
||||
thing = "small-worm-turret"
|
||||
cost = AI_WORM_COST
|
||||
radiusAdjustment = -4
|
||||
else
|
||||
thing = "biter-spawner"
|
||||
cost = AI_NEST_COST
|
||||
radiusAdjustment = 0
|
||||
end
|
||||
for _ = 1, slices do
|
||||
if (base.upgradePoints < 10) then
|
||||
return
|
||||
end
|
||||
local radius = 10 * level
|
||||
local distortion = gaussianRandomRange(radius, 10, radius - 7.5 + radiusAdjustment, radius + 7.5 + radiusAdjustment, generator)
|
||||
local nestPosition = {x = position.x + (distortion * math.cos(pos)),
|
||||
y = position.y + (distortion * math.sin(pos))}
|
||||
local biterSpawner = {name=thing, position=nestPosition}
|
||||
if surface.can_place_entity(biterSpawner) then
|
||||
registerEnemyBaseStructure(regionMap, surface.create_entity(biterSpawner), base)
|
||||
base.upgradePoints = base.upgradePoints - cost
|
||||
end
|
||||
pos = pos + slice
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function buildUtils.buildOrder(regionMap, natives, base, surface)
|
||||
local foundHive = false
|
||||
for _,_ in pairs(base.hives) do
|
||||
foundHive = true
|
||||
break
|
||||
end
|
||||
if not foundHive or (base.upgradePoints < 10) then
|
||||
return
|
||||
end
|
||||
|
||||
local generator = natives.randomGenerator
|
||||
generator.re_seed(base.pattern)
|
||||
|
||||
for level=0,base.level do
|
||||
local slices = (level * 3)
|
||||
slices = gaussianRandomRange(slices, slices * 0.1, slices * 0.6, slices * 1.4, generator)
|
||||
local slice = (2 * math.pi) / slices
|
||||
local pos = 0
|
||||
local thing
|
||||
local cost
|
||||
local radiusAdjustment
|
||||
if (generator() < 0.3) then
|
||||
thing = "small-worm-turret"
|
||||
cost = AI_WORM_COST
|
||||
radiusAdjustment = -4
|
||||
else
|
||||
thing = "biter-spawner"
|
||||
cost = AI_NEST_COST
|
||||
radiusAdjustment = 0
|
||||
end
|
||||
for _ = 1, slices do
|
||||
if (base.upgradePoints < 10) then
|
||||
return
|
||||
end
|
||||
local radius = 10 * level
|
||||
local distortion = gaussianRandomRange(radius, 10, radius - 7.5 + radiusAdjustment, radius + 7.5 + radiusAdjustment, generator)
|
||||
local nestPosition = {x = base.x + (distortion * math.cos(pos)),
|
||||
y = base.y + (distortion * math.sin(pos))}
|
||||
local biterSpawner = {name=thing, position=nestPosition}
|
||||
if surface.can_place_entity(biterSpawner) then
|
||||
registerEnemyBaseStructure(regionMap, surface.create_entity(biterSpawner), base)
|
||||
base.upgradePoints = base.upgradePoints - cost
|
||||
end
|
||||
pos = pos + slice
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return buildUtils
|
||||
+5
-3
@@ -130,10 +130,12 @@ function chunkUtils.scoreChunk(regionMap, chunk, surface, natives, tick, tempQue
|
||||
if (nests > 0) or (worms > 0) or (biters > 0) then
|
||||
for f=1, #enemies do
|
||||
local enemy = enemies[f]
|
||||
if (enemy.name ~= "biter-spawner-hive") then
|
||||
enemy.destroy()
|
||||
else
|
||||
if (enemy.name == "small-tendril-biter-rampant") then
|
||||
biters = biters - 1
|
||||
elseif (enemy.name == "biter-spawner-hive") then
|
||||
nests = nests - 1
|
||||
else
|
||||
enemy.destroy()
|
||||
end
|
||||
end
|
||||
local foundBase = findNearbyBase(natives, chunk) or createBase(regionMap, natives, chunk, surface, tick)
|
||||
|
||||
+2
-1
@@ -12,6 +12,7 @@ constants.VERSION_20 = 20
|
||||
constants.VERSION_22 = 22
|
||||
constants.VERSION_23 = 23
|
||||
constants.VERSION_25 = 25
|
||||
constants.VERSION_26 = 26
|
||||
|
||||
-- misc
|
||||
|
||||
@@ -33,7 +34,7 @@ constants.INTERVAL_LOGIC = 38
|
||||
|
||||
constants.PLAYER_PHEROMONE_MULTIPLER = 100
|
||||
|
||||
constants.DEV_CUSTOM_AI = false
|
||||
constants.DEV_CUSTOM_AI = true
|
||||
|
||||
-- chunk properties
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ local mapProcessor = {}
|
||||
local unitGroupUtils = require("UnitGroupUtils")
|
||||
|
||||
local pheromoneUtils = require("PheromoneUtils")
|
||||
local aiBuilding = require("AIBuilding")
|
||||
local aiAttackWave = require("AIAttackWave")
|
||||
local aiPredicates = require("AIPredicates")
|
||||
local constants = require("Constants")
|
||||
local mapUtils = require("MapUtils")
|
||||
@@ -40,7 +40,7 @@ local BUILDING_PHEROMONES = constants.BUILDING_PHEROMONES
|
||||
local scents = pheromoneUtils.scents
|
||||
local processPheromone = pheromoneUtils.processPheromone
|
||||
|
||||
local formSquads = aiBuilding.formSquads
|
||||
local formSquads = aiAttackWave.formSquads
|
||||
|
||||
local getChunkByIndex = mapUtils.getChunkByIndex
|
||||
local getChunkByPosition = mapUtils.getChunkByPosition
|
||||
|
||||
@@ -4,8 +4,6 @@ local mapUtils = {}
|
||||
|
||||
local constants = require("Constants")
|
||||
|
||||
local mathUtils = require("MathUtils")
|
||||
|
||||
-- constants
|
||||
|
||||
local CHUNK_NORTH_SOUTH = constants.CHUNK_NORTH_SOUTH
|
||||
@@ -21,8 +19,6 @@ local CHUNK_SIZE = constants.CHUNK_SIZE
|
||||
|
||||
-- imported functions
|
||||
|
||||
local gaussianRandomRange = mathUtils.gaussianRandomRange
|
||||
|
||||
local mFloor = math.floor
|
||||
|
||||
-- module code
|
||||
@@ -43,10 +39,6 @@ function mapUtils.getChunkByIndex(regionMap, x, y)
|
||||
return nil
|
||||
end
|
||||
|
||||
function mapUtils.positionToChunkOffset(position)
|
||||
return mFloor(position.x * 0.03125), mFloor(position.y * 0.03125)
|
||||
end
|
||||
|
||||
--[[
|
||||
1 2 3
|
||||
\|/
|
||||
@@ -116,33 +108,7 @@ function mapUtils.getCardinalChunks(regionMap, chunkX, chunkY)
|
||||
return neighbors
|
||||
end
|
||||
|
||||
function mapUtils.euclideanDistanceNamed(p1, p2)
|
||||
local xs = p1.x - p2.x
|
||||
local ys = p1.y - p2.y
|
||||
return ((xs * xs) + (ys * ys)) ^ 0.5
|
||||
end
|
||||
|
||||
function mapUtils.euclideanDistancePoints(x1, y1, x2, y2)
|
||||
local xs = x1 - x2
|
||||
local ys = y1 - y2
|
||||
return ((xs * xs) + (ys * ys)) ^ 0.5
|
||||
end
|
||||
|
||||
function mapUtils.euclideanDistanceArray(p1, p2)
|
||||
local xs = p1[1] - p2[1]
|
||||
local ys = p1[2] - p2[2]
|
||||
return ((xs * xs) + (ys * ys)) ^ 0.5
|
||||
end
|
||||
|
||||
function mapUtils.distortPosition(position)
|
||||
local xDistort = gaussianRandomRange(1, 0.5, 0, 2) - 1
|
||||
local yDistort = gaussianRandomRange(1, 0.5, 0, 2) - 1
|
||||
position.x = position.x + (xDistort * 48)
|
||||
position.y = position.y + (yDistort * 48)
|
||||
end
|
||||
|
||||
function mapUtils.positionFromDirectionAndChunk(direction, startPosition, position, scaling)
|
||||
-- local position = {x=0, y=0}
|
||||
if (direction == 1) then
|
||||
position.x = startPosition.x - CHUNK_SIZE * scaling
|
||||
position.y = startPosition.y - CHUNK_SIZE * scaling
|
||||
|
||||
@@ -16,6 +16,10 @@ local mMax = math.max
|
||||
local mSqrt = math.sqrt
|
||||
local mLog10 = math.log10
|
||||
|
||||
local mFloor = math.floor
|
||||
|
||||
-- module code
|
||||
|
||||
function mathUtils.roundToNearest(number, multiple)
|
||||
local num = number + (multiple * 0.5)
|
||||
return num - (num % multiple)
|
||||
@@ -60,4 +64,33 @@ function mathUtils.gaussianRandomRange(mean, std_dev, min, max, rg)
|
||||
return q
|
||||
end
|
||||
|
||||
function mathUtils.positionToChunkOffset(position)
|
||||
return mFloor(position.x * 0.03125), mFloor(position.y * 0.03125)
|
||||
end
|
||||
|
||||
function mathUtils.euclideanDistanceNamed(p1, p2)
|
||||
local xs = p1.x - p2.x
|
||||
local ys = p1.y - p2.y
|
||||
return ((xs * xs) + (ys * ys)) ^ 0.5
|
||||
end
|
||||
|
||||
function mathUtils.euclideanDistancePoints(x1, y1, x2, y2)
|
||||
local xs = x1 - x2
|
||||
local ys = y1 - y2
|
||||
return ((xs * xs) + (ys * ys)) ^ 0.5
|
||||
end
|
||||
|
||||
function mathUtils.euclideanDistanceArray(p1, p2)
|
||||
local xs = p1[1] - p2[1]
|
||||
local ys = p1[2] - p2[2]
|
||||
return ((xs * xs) + (ys * ys)) ^ 0.5
|
||||
end
|
||||
|
||||
function mathUtils.distortPosition(position)
|
||||
local xDistort = mathUtils.gaussianRandomRange(1, 0.5, 0, 2) - 1
|
||||
local yDistort = mathUtils.gaussianRandomRange(1, 0.5, 0, 2) - 1
|
||||
position.x = position.x + (xDistort * 48)
|
||||
position.y = position.y + (yDistort * 48)
|
||||
end
|
||||
|
||||
return mathUtils
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
local movementUtils = {}
|
||||
|
||||
-- imports
|
||||
|
||||
local constants = require("Constants")
|
||||
local unitGroupUtils = require("UnitGroupUtils")
|
||||
|
||||
local mathUtils = require("MathUtils")
|
||||
|
||||
-- constants
|
||||
|
||||
local MOVEMENT_PHEROMONE_GENERATOR_AMOUNT = constants.MOVEMENT_PHEROMONE_GENERATOR_AMOUNT
|
||||
local MAX_PENALTY_BEFORE_PURGE = constants.MAX_PENALTY_BEFORE_PURGE
|
||||
|
||||
-- imported functions
|
||||
|
||||
local recycleBiters = unitGroupUtils.recycleBiters
|
||||
|
||||
local tableRemove = table.remove
|
||||
local tableInsert = table.insert
|
||||
|
||||
local distortPosition = mathUtils.distortPosition
|
||||
|
||||
-- module code
|
||||
|
||||
function movementUtils.findMovementPosition(surface, position, distort)
|
||||
local pos = position
|
||||
if not surface.can_place_entity({name="behemoth-biter", position=position}) then
|
||||
pos = surface.find_non_colliding_position("behemoth-biter", position, 5, 2) or position
|
||||
end
|
||||
return (distort and distortPosition(pos)) or pos
|
||||
end
|
||||
|
||||
function movementUtils.addMovementPenalty(natives, units, chunkX, chunkY)
|
||||
local penalties = units.penalties
|
||||
for i=1,#penalties do
|
||||
local penalty = penalties[i]
|
||||
if (penalty.x == chunkX) and (penalty.y == chunkY) then
|
||||
penalty.v = penalty.v + MOVEMENT_PHEROMONE_GENERATOR_AMOUNT
|
||||
if (penalty.v > MAX_PENALTY_BEFORE_PURGE) then
|
||||
local group = units.group
|
||||
if group then
|
||||
recycleBiters(natives, group.members)
|
||||
group.destroy()
|
||||
else
|
||||
units.unit.destroy()
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
if (#penalties == 7) then
|
||||
tableRemove(penalties, 7)
|
||||
end
|
||||
tableInsert(penalties, 1, { v = MOVEMENT_PHEROMONE_GENERATOR_AMOUNT,
|
||||
x = chunkX,
|
||||
y = chunkY })
|
||||
end
|
||||
|
||||
function movementUtils.lookupMovementPenalty(squad, chunkX, chunkY)
|
||||
local penalties = squad.penalties
|
||||
for i=1,#penalties do
|
||||
local penalty = penalties[i]
|
||||
if (penalty.x == chunkX) and (penalty.y == chunkY) then
|
||||
return penalty.v
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
|
||||
return movementUtils
|
||||
@@ -1,4 +1,4 @@
|
||||
local aiAttack = {}
|
||||
local squadAttack = {}
|
||||
|
||||
-- imports
|
||||
|
||||
@@ -7,6 +7,7 @@ local mapUtils = require("MapUtils")
|
||||
local unitGroupUtils = require("UnitGroupUtils")
|
||||
local playerUtils = require("PlayerUtils")
|
||||
local neighborUtils = require("NeighborUtils")
|
||||
local movementUtils = require("MovementUtils")
|
||||
|
||||
-- constants
|
||||
|
||||
@@ -32,9 +33,11 @@ local DEFINES_DISTRACTION_BY_ANYTHING = defines.distraction.by_anything
|
||||
|
||||
-- imported functions
|
||||
|
||||
local findMovementPoint = movementUtils.findMovementPoint
|
||||
|
||||
local getNeighborChunks = mapUtils.getNeighborChunks
|
||||
local getChunkByPosition = mapUtils.getChunkByPosition
|
||||
local addSquadMovementPenalty = unitGroupUtils.addSquadMovementPenalty
|
||||
local addMovementPenalty = unitGroupUtils.addMovementPenalty
|
||||
local lookupSquadMovementPenalty = unitGroupUtils.lookupSquadMovementPenalty
|
||||
local calculateKamikazeThreshold = unitGroupUtils.calculateKamikazeThreshold
|
||||
local positionFromDirectionAndChunk = mapUtils.positionFromDirectionAndChunk
|
||||
@@ -52,7 +55,7 @@ local function scoreAttackLocation(squad, neighborChunk)
|
||||
return damage - lookupSquadMovementPenalty(squad, neighborChunk.cX, neighborChunk.cY)
|
||||
end
|
||||
|
||||
function aiAttack.squadAttack(regionMap, surface, natives)
|
||||
function squadAttack.squadsAttack(regionMap, surface, natives)
|
||||
local squads = natives.squads
|
||||
local attackPosition
|
||||
local attackCmd
|
||||
@@ -80,18 +83,12 @@ function aiAttack.squadAttack(regionMap, surface, natives)
|
||||
chunk.cY),
|
||||
scoreAttackLocation,
|
||||
squad)
|
||||
addSquadMovementPenalty(natives, squad, chunk.cX, chunk.cY)
|
||||
addMovementPenalty(natives, squad, chunk.cX, chunk.cY)
|
||||
if group.valid and attackChunk then
|
||||
if (attackChunk[PLAYER_BASE_GENERATOR] == 0) or
|
||||
((groupState == DEFINES_GROUP_FINISHED) or (groupState == DEFINES_GROUP_GATHERING)) then
|
||||
|
||||
positionFromDirectionAndChunk(attackDirection, groupPosition, attackPosition, 1.35)
|
||||
|
||||
if (#squad.group.members > 80) then
|
||||
squad.cycles = 6
|
||||
else
|
||||
squad.cycles = 4
|
||||
end
|
||||
squad.cycles = ((#squad.group.members > 80) and 6) or 4
|
||||
|
||||
local moreFrenzy = not squad.rabid and squad.frenzy and (euclideanDistanceNamed(groupPosition, squad.frenzyPosition) < 100)
|
||||
squad.frenzy = moreFrenzy
|
||||
@@ -102,19 +99,18 @@ function aiAttack.squadAttack(regionMap, surface, natives)
|
||||
attackCmd.distraction = DEFINES_DISTRACTION_BY_ENEMY
|
||||
end
|
||||
|
||||
if surface.can_place_entity({name="behemoth-biter", position=attackPosition}) then
|
||||
local position = findMovementPoint(surface,
|
||||
positionFromDirectionAndChunk(attackDirection,
|
||||
groupPosition,
|
||||
attackPosition,
|
||||
1.35))
|
||||
if position then
|
||||
attackPosition.x = position.x
|
||||
attackPosition.y = position.y
|
||||
group.set_command(attackCmd)
|
||||
group.start_moving()
|
||||
else
|
||||
local newAttackPosition = surface.find_non_colliding_position("behemoth-biter", attackPosition, 5, 2)
|
||||
if newAttackPosition then
|
||||
attackPosition.x = newAttackPosition.x
|
||||
attackPosition.y = newAttackPosition.y
|
||||
group.set_command(attackCmd)
|
||||
group.start_moving()
|
||||
else
|
||||
addSquadMovementPenalty(natives, squad, attackChunk.cX, attackChunk.cY)
|
||||
end
|
||||
addMovementPenalty(natives, squad, attackChunk.cX, attackChunk.cY)
|
||||
end
|
||||
elseif not squad.frenzy and not squad.rabid and
|
||||
((groupState == DEFINES_GROUP_ATTACKING_DISTRACTION) or (groupState == DEFINES_GROUP_ATTACKING_TARGET) or
|
||||
@@ -130,7 +126,7 @@ function aiAttack.squadAttack(regionMap, surface, natives)
|
||||
end
|
||||
end
|
||||
|
||||
function aiAttack.squadBeginAttack(natives, players)
|
||||
function squadAttack.squadsBeginAttack(natives, players)
|
||||
local squads = natives.squads
|
||||
for i=1,#squads do
|
||||
local squad = squads[i]
|
||||
@@ -154,4 +150,4 @@ function aiAttack.squadBeginAttack(natives, players)
|
||||
end
|
||||
end
|
||||
|
||||
return aiAttack
|
||||
return squadAttack
|
||||
@@ -67,6 +67,7 @@ function aiDefense.retreatUnits(chunk, position, squad, regionMap, surface, nati
|
||||
if exitPath then
|
||||
local retreatPosition = positionFromDirectionAndChunk(exitDirection, position, {x=0,y=0}, 0.98)
|
||||
|
||||
|
||||
if not surface.can_place_entity({name="behemoth-biter", position=retreatPosition}) then
|
||||
local newRetreatPosition = surface.find_non_colliding_position("behemoth-biter", retreatPosition, 5, 2)
|
||||
if newRetreatPosition then
|
||||
+77
-51
@@ -7,6 +7,8 @@ local mapUtils = require("MapUtils")
|
||||
local baseRegisterUtils = require("BaseRegisterUtils")
|
||||
local neighborsUtils = require("NeighborUtils")
|
||||
|
||||
local buildUtils = require("BuildUtils")
|
||||
|
||||
-- constants
|
||||
|
||||
local RESOURCE_PHEROMONE = constants.RESOURCE_PHEROMONE
|
||||
@@ -15,7 +17,7 @@ local NEST_COUNT = constants.NEST_COUNT
|
||||
|
||||
-- imported functions
|
||||
|
||||
local scoreNeighborsWithDirection = neighborsUtils.scoreNeighborsWithDirection
|
||||
local scoreNeighborsForAttack = neighborsUtils.scoreNeighborsForAttack
|
||||
|
||||
local getNeighborChunks = mapUtils.getNeighborChunks
|
||||
|
||||
@@ -25,30 +27,26 @@ local positionFromDirectionAndChunk = mapUtils.positionFromDirectionAndChunk
|
||||
|
||||
local registerEnemyBaseStructure = baseRegisterUtils.registerEnemyBaseStructure
|
||||
|
||||
local canMoveChunkDirection = mapUtils.canMoveChunkDirection
|
||||
local buildOutpost = buildUtils.buildOutpost
|
||||
|
||||
local euclideanDistanceNamed = mapUtils.euclideanDistanceNamed
|
||||
|
||||
-- module code
|
||||
|
||||
local function scoreTendrilChunk(squad, chunk, surface)
|
||||
local function scoreTendrilChunk(squad, chunk)
|
||||
return chunk[RESOURCE_PHEROMONE]
|
||||
end
|
||||
|
||||
local function validTendrilChunk(x, chunk, neighborChunk)
|
||||
return canMoveChunkDirection(x, chunk, neighborChunk)
|
||||
local function colorChunk(x, y, tileType, surface)
|
||||
local tiles = {}
|
||||
for xi=x+5, x + 27 do
|
||||
for yi=y+5, y + 27 do
|
||||
tiles[#tiles+1] = {name=tileType, position={xi, yi}}
|
||||
end
|
||||
end
|
||||
surface.set_tiles(tiles, false)
|
||||
end
|
||||
|
||||
-- local function colorChunk(x, y, tileType, surface)
|
||||
-- local tiles = {}
|
||||
-- for xi=x+5, x + 27 do
|
||||
-- for yi=y+5, y + 27 do
|
||||
-- tiles[#tiles+1] = {name=tileType, position={xi, yi}}
|
||||
-- end
|
||||
-- end
|
||||
-- surface.set_tiles(tiles, false)
|
||||
-- end
|
||||
|
||||
local function removeTendril(base, tendril)
|
||||
for i=1,#base.tendrils do
|
||||
if (base.tendrils[i] == tendril) then
|
||||
@@ -58,57 +56,84 @@ local function removeTendril(base, tendril)
|
||||
end
|
||||
end
|
||||
|
||||
local function buildTendrilPath(regionMap, tendril, surface, base, tick)
|
||||
local chunk = getChunkByPosition(regionMap, tendril.x, tendril.y)
|
||||
local function buildTendrilPath(regionMap, tendril, surface, base, tick, natives)
|
||||
local tendrilUnit = tendril.unit
|
||||
if not tendrilUnit.valid then
|
||||
return
|
||||
end
|
||||
if (tendril.cycles > 0) then
|
||||
tendril.cycles = tendril.cycles - 1
|
||||
return
|
||||
end
|
||||
local tendrilPosition = tendrilUnit.position
|
||||
local chunk = getChunkByPosition(regionMap, tendrilPosition.x, tendrilPosition.y)
|
||||
if chunk then
|
||||
local tendrilPath,tendrilDirection = scoreNeighborsWithDirection(chunk,
|
||||
getNeighborChunks(regionMap,
|
||||
chunk.cX,
|
||||
chunk.cY),
|
||||
validTendrilChunk,
|
||||
scoreTendrilChunk,
|
||||
nil,
|
||||
surface,
|
||||
true)
|
||||
local tendrilPath,tendrilDirection = scoreNeighborsForAttack(chunk,
|
||||
getNeighborChunks(regionMap,
|
||||
chunk.cX,
|
||||
chunk.cY),
|
||||
scoreTendrilChunk,
|
||||
nil)
|
||||
if (tendrilDirection == -1) then
|
||||
removeTendril(base, tendril)
|
||||
tendrilUtils.buildTendril(regionMap, nil, base, surface, tick)
|
||||
-- colorChunk(chunk.x, chunk.y, "hazard-concrete-left", surface)
|
||||
-- removeTendril(base, tendril)
|
||||
-- buildOutpost(regionMap, natives, base, surface, tendril)
|
||||
-- tendrilUtils.buildTendril(regionMap, natives, base, surface, tick)
|
||||
colorChunk(chunk.x, chunk.y, "hazard-concrete-left", surface)
|
||||
return
|
||||
elseif tendrilPath then
|
||||
positionFromDirectionAndChunk(tendrilDirection, tendril, tendril, 0.5)
|
||||
mapUtils.distortPosition(tendril)
|
||||
tendril.path[#tendril.path] = chunk
|
||||
positionFromDirectionAndChunk(tendrilDirection, tendrilPosition, tendrilPosition, 0.5)
|
||||
mapUtils.distortPosition(tendrilPosition)
|
||||
-- tendril.path[#tendril.path] = chunk
|
||||
local position = surface.find_non_colliding_position("spitter-spawner",
|
||||
{x=tendril.x,y=tendril.y},
|
||||
tendrilPosition,
|
||||
32,
|
||||
4)
|
||||
if position and (tendrilPath[NEST_COUNT] <= 3)then
|
||||
tendril.x = position.x
|
||||
tendril.y = position.y
|
||||
local biterSpawner = {name="spitter-spawner", position=position}
|
||||
local hive = surface.create_entity(biterSpawner)
|
||||
registerEnemyBaseStructure(regionMap, hive, base)
|
||||
elseif not position then
|
||||
removeTendril(base, tendril)
|
||||
2)
|
||||
if position then
|
||||
tendril.target = position
|
||||
tendrilUnit.set_command({ type = defines.command.go_to_location,
|
||||
destination = position,
|
||||
distraction = defines.distraction.by_damage })
|
||||
|
||||
-- needs to check to make sure unit still exists as well.
|
||||
--tendril.cycles = 2
|
||||
-- tendril.x = position.x
|
||||
-- tendril.y = position.y
|
||||
-- local biterSpawner = {name="spitter-spawner", position=position}
|
||||
-- local hive = surface.create_entity(biterSpawner)
|
||||
-- registerEnemyBaseStructure(regionMap, hive, base)
|
||||
-- elseif not position then
|
||||
-- removeTendril(base, tendril)
|
||||
end
|
||||
end
|
||||
-- colorChunk(chunk.x, chunk.y, "concrete", surface)
|
||||
colorChunk(chunk.x, chunk.y, "concrete", surface)
|
||||
end
|
||||
end
|
||||
|
||||
function tendrilUtils.advanceTendrils(regionMap, base, surface, tick)
|
||||
function tendrilUtils.advanceTendrils(regionMap, base, surface, tick, natives)
|
||||
for i=1, #base.tendrils do
|
||||
buildTendrilPath(regionMap, base.tendrils[i], surface, base, tick)
|
||||
buildTendrilPath(regionMap, base.tendrils[i], surface, base, tick, natives)
|
||||
end
|
||||
end
|
||||
|
||||
function tendrilUtils.createTendril(base)
|
||||
function tendrilUtils.createTendril(base, surface)
|
||||
local position = surface.find_non_colliding_position("small-tendril-biter-rampant",
|
||||
{x=base.x,y=base.y},
|
||||
32,
|
||||
4)
|
||||
if not position then
|
||||
return nil
|
||||
end
|
||||
|
||||
local entity = surface.create_entity({name="small-tendril-biter-rampant", position=position})
|
||||
|
||||
local tendril = {
|
||||
x = base.x,
|
||||
y = base.y,
|
||||
unit = entity,
|
||||
penalties = {},
|
||||
target = entity.position,
|
||||
cycles = 0,
|
||||
path = {}
|
||||
}
|
||||
|
||||
return tendril
|
||||
end
|
||||
|
||||
@@ -117,10 +142,11 @@ function tendrilUtils.buildTendril(regionMap, natives, base, surface, tick)
|
||||
-- if chunk then
|
||||
-- local tempNeighbors = {nil, nil, nil, nil, nil, nil, nil, nil}
|
||||
-- buildTendrilPath(regionMap, chunk, surface, base, tempNeighbors)
|
||||
base.tendrils[#base.tendrils+1] = tendrilUtils.createTendril(base)
|
||||
local tendril = tendrilUtils.createTendril(base, surface)
|
||||
if tendril then
|
||||
base.tendrils[#base.tendrils+1] = tendril
|
||||
end
|
||||
-- end
|
||||
end
|
||||
|
||||
|
||||
|
||||
return tendrilUtils
|
||||
|
||||
@@ -7,8 +7,6 @@ local constants = require("Constants")
|
||||
|
||||
-- constants
|
||||
|
||||
local MOVEMENT_PHEROMONE_GENERATOR_AMOUNT = constants.MOVEMENT_PHEROMONE_GENERATOR_AMOUNT
|
||||
|
||||
local SQUAD_QUEUE_SIZE = constants.SQUAD_QUEUE_SIZE
|
||||
|
||||
local DEFINES_GROUP_STATE_FINISHED = defines.group_state.finished
|
||||
@@ -17,8 +15,6 @@ local DEFINES_GROUP_STATE_ATTACKING_DISTRACTION = defines.group_state.attacking_
|
||||
local DEFINES_COMMAND_GROUP = defines.command.group
|
||||
local DEFINES_DISTRACTION_NONE = defines.distraction.none
|
||||
|
||||
local MAX_PENALTY_BEFORE_PURGE = constants.MAX_PENALTY_BEFORE_PURGE
|
||||
|
||||
local SQUAD_RETREATING = constants.SQUAD_RETREATING
|
||||
local SQUAD_GUARDING = constants.SQUAD_GUARDING
|
||||
local GROUP_MERGE_DISTANCE = constants.GROUP_MERGE_DISTANCE
|
||||
@@ -36,8 +32,6 @@ local mLog = math.log10
|
||||
|
||||
local mMin = math.min
|
||||
|
||||
local tableRemove = table.remove
|
||||
local tableInsert = table.insert
|
||||
local euclideanDistanceNamed = mapUtils.euclideanDistanceNamed
|
||||
|
||||
-- module code
|
||||
@@ -110,39 +104,6 @@ function unitGroupUtils.convertUnitGroupToSquad(natives, unitGroup)
|
||||
return returnSquad
|
||||
end
|
||||
|
||||
function unitGroupUtils.addSquadMovementPenalty(natives, squad, chunkX, chunkY)
|
||||
local penalties = squad.penalties
|
||||
for i=1,#penalties do
|
||||
local penalty = penalties[i]
|
||||
if (penalty.x == chunkX) and (penalty.y == chunkY) then
|
||||
penalty.v = penalty.v + MOVEMENT_PHEROMONE_GENERATOR_AMOUNT
|
||||
if (penalty.v > MAX_PENALTY_BEFORE_PURGE) then
|
||||
local group = squad.group
|
||||
unitGroupUtils.recycleBiters(natives, group.members)
|
||||
group.destroy()
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
if (#penalties == 7) then
|
||||
tableRemove(penalties, 7)
|
||||
end
|
||||
tableInsert(penalties, 1, { v = MOVEMENT_PHEROMONE_GENERATOR_AMOUNT,
|
||||
x = chunkX,
|
||||
y = chunkY })
|
||||
end
|
||||
|
||||
function unitGroupUtils.lookupSquadMovementPenalty(squad, chunkX, chunkY)
|
||||
local penalties = squad.penalties
|
||||
for i=1,#penalties do
|
||||
local penalty = penalties[i]
|
||||
if (penalty.x == chunkX) and (penalty.y == chunkY) then
|
||||
return penalty.v
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
function unitGroupUtils.calculateKamikazeThreshold(squad, natives)
|
||||
local squadSizeBonus = mLog((#squad.group.members / natives.attackWaveMaxSize) + 0.1) + 1
|
||||
return natives.kamikazeThreshold + (NO_RETREAT_SQUAD_SIZE_BONUS_MAX * squadSizeBonus)
|
||||
|
||||
@@ -11,6 +11,8 @@ small-fire-spitter=Small Fire Spitter
|
||||
|
||||
biter-spawner-hive=Small Hive
|
||||
|
||||
small-tendril-biter-rampant=Small Tendril
|
||||
|
||||
[entity-description]
|
||||
tunnel-entrance=This tunnel is used by the biters to bypass player defenses. Fill the hole using landfill.
|
||||
|
||||
@@ -23,6 +25,8 @@ small-fire-spitter=These biters will spit fire
|
||||
|
||||
biter-spawner-hive=Small Hive
|
||||
|
||||
small-tendril-biter-rampant=Small Tendril
|
||||
|
||||
[mod-setting-name]
|
||||
rampant-useDumbProjectiles=Use Dumb Projectiles
|
||||
rampant-useNEUnitLaunchers=Use Natural Evolution Unit Launchers (Needs NE)
|
||||
|
||||
@@ -77,8 +77,8 @@
|
||||
(copyDirectory "prototypes" modFolder)))
|
||||
|
||||
(define (run)
|
||||
;; (copyFiles modFolder)
|
||||
(copyFiles modFolder)
|
||||
;; (copyFiles zipModFolder)
|
||||
(makeZip modFolder)
|
||||
;;(makeZip modFolder)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
|
||||
-- imports
|
||||
|
||||
local biterUtils = require("BiterUtils")
|
||||
|
||||
-- import functions
|
||||
|
||||
local makeBiter = biterUtils.makeBiter
|
||||
local createSuicideAttack = biterUtils.createSuicideAttack
|
||||
local makeResistance = biterUtils.makeResistance
|
||||
|
||||
-- local
|
||||
|
||||
local smallSuicideBiterScale = 0.75
|
||||
local smallSuicideBiterTint1 = {r=0.0, g=0.0, b=0.70, a=0.8}
|
||||
local smallSuicideBiterTint2 = {r=0.0, g=0.0, b=0.72, a=0.4}
|
||||
|
||||
-- module code
|
||||
|
||||
data:extend({
|
||||
makeBiter({name = "small-tendril-biter-rampant",
|
||||
health = 30,
|
||||
movement = 0.21,
|
||||
distancePerFrame = 0.1,
|
||||
healing = 0.01,
|
||||
scale = smallSuicideBiterScale,
|
||||
tint1 = smallSuicideBiterTint1,
|
||||
tint2 = smallSuicideBiterTint2,
|
||||
explosion = "blood-explosion-small"},
|
||||
createSuicideAttack({ area = 3.5,
|
||||
damage = 20,
|
||||
explosion = "explosion",
|
||||
scorchmark = "small-scorchmark",
|
||||
explosionCount = 2,
|
||||
explosionDistance = 2,
|
||||
scale = smallSuicideBiterScale,
|
||||
tint1 = smallSuicideBiterTint1,
|
||||
tint2 = smallSuicideBiterTint2}),
|
||||
{makeResistance("explosion", 0, -50),
|
||||
makeResistance("laser", 1, 0),
|
||||
makeResistance("fire", 0, -60)}),
|
||||
})
|
||||
Reference in New Issue
Block a user