mirror of
https://github.com/veden/Rampant.git
synced 2026-06-19 22:15:20 +02:00
first attempt
This commit is contained in:
+3
-3
@@ -163,10 +163,10 @@ function upgrade.attempt(natives)
|
||||
game.surfaces[1].print("Rampant - Version 0.15.23")
|
||||
global.version = constants.VERSION_33
|
||||
end
|
||||
if (global.version < constants.VERSION_35) then
|
||||
if (global.version < constants.VERSION_36) then
|
||||
|
||||
game.surfaces[1].print("Rampant - Version 0.16.0")
|
||||
global.version = constants.VERSION_35
|
||||
game.surfaces[1].print("Rampant - Version 0.16.1")
|
||||
global.version = constants.VERSION_36
|
||||
end
|
||||
return starting ~= global.version, natives
|
||||
end
|
||||
|
||||
+6
-4
@@ -154,12 +154,14 @@ local function rebuildRegionMap()
|
||||
SENTINEL_IMPASSABLE_CHUNK,
|
||||
SENTINEL_IMPASSABLE_CHUNK,
|
||||
SENTINEL_IMPASSABLE_CHUNK }
|
||||
regionMap.chunkTiles = {}
|
||||
regionMap.position = {x=0,
|
||||
y=0}
|
||||
for i=1,1024 do
|
||||
regionMap.chunkTiles[i] = nil
|
||||
end
|
||||
|
||||
--this is shared between two different queries
|
||||
local sharedFilterArea = {{0, 0}, {0, 0}}
|
||||
regionMap.filteredEntitiesQuery = { area=sharedFilterArea, force=false }
|
||||
regionMap.cliffQuery = { type="cliff", area={{0, 0}, {0, 0}} }
|
||||
regionMap.filteredTilesQuery = { name="", area=sharedFilterArea }
|
||||
|
||||
-- switched over to tick event
|
||||
regionMap.logicTick = roundToNearest(game.tick + INTERVAL_LOGIC, INTERVAL_LOGIC)
|
||||
|
||||
@@ -11,6 +11,14 @@ if settings.startup["rampant-enableSwarm"] then
|
||||
end
|
||||
end
|
||||
|
||||
for k, cliff in pairs(data.raw["cliff"]) do
|
||||
if not cliff.collision_mask then
|
||||
cliff.collision_mask = {}
|
||||
end
|
||||
cliff.collision_mask[#cliff.collision_mask+1] = "water-tile"
|
||||
|
||||
end
|
||||
|
||||
if settings.startup["rampant-addWallResistanceAcid"].value then
|
||||
vanillaBuildings.addWallAcidResistance()
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name" : "Rampant",
|
||||
"factorio_version" : "0.16",
|
||||
"version" : "0.16.0",
|
||||
"version" : "0.16.1",
|
||||
"title" : "Rampant",
|
||||
"author" : "Veden",
|
||||
"homepage" : "https://forums.factorio.com/viewtopic.php?f=94&t=31445",
|
||||
|
||||
+15
-21
@@ -13,7 +13,6 @@ local SENTINEL_IMPASSABLE_CHUNK = constants.SENTINEL_IMPASSABLE_CHUNK
|
||||
|
||||
-- imported functions
|
||||
|
||||
local remakeChunk = chunkUtils.remakeChunk
|
||||
local createChunk = chunkUtils.createChunk
|
||||
local checkChunkPassability = chunkUtils.checkChunkPassability
|
||||
local scoreChunk = chunkUtils.scoreChunk
|
||||
@@ -21,17 +20,16 @@ local registerChunkEnemies = chunkUtils.registerChunkEnemies
|
||||
|
||||
-- module code
|
||||
|
||||
function chunkProcessor.processPendingChunks(natives, regionMap, surface, pendingStack, tick)
|
||||
function chunkProcessor.processPendingChunks(natives, regionMap, surface, pendingStack)
|
||||
local processQueue = regionMap.processQueue
|
||||
|
||||
local offset = {0, 0}
|
||||
local areaBoundingBox = {false, offset}
|
||||
local query = {area=areaBoundingBox,
|
||||
force=false}
|
||||
local filteredEntitiesQuery = regionMap.filteredEntitiesQuery
|
||||
|
||||
local vanillaAI = not natives.useCustomAI
|
||||
local topOffset = filteredEntitiesQuery.area[1]
|
||||
local bottomOffset = filteredEntitiesQuery.area[2]
|
||||
|
||||
local chunkTiles = regionMap.chunkTiles
|
||||
local filteredTilesQuery = regionMap.filteredTilesQuery
|
||||
local cliffQuery = regionMap.cliffQuery
|
||||
|
||||
for i=#pendingStack, 1, -1 do
|
||||
local event = pendingStack[i]
|
||||
@@ -41,21 +39,17 @@ function chunkProcessor.processPendingChunks(natives, regionMap, surface, pendin
|
||||
local x = topLeft.x
|
||||
local y = topLeft.y
|
||||
local chunk = createChunk(x, y)
|
||||
|
||||
chunk = checkChunkPassability(chunkTiles, chunk, surface)
|
||||
|
||||
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then
|
||||
topOffset[1] = x
|
||||
topOffset[2] = y
|
||||
bottomOffset[1] = x + CHUNK_SIZE
|
||||
bottomOffset[2] = y + CHUNK_SIZE
|
||||
|
||||
areaBoundingBox[1] = chunk
|
||||
offset[1] = x + CHUNK_SIZE
|
||||
offset[2] = y + CHUNK_SIZE
|
||||
|
||||
if vanillaAI then
|
||||
registerChunkEnemies(regionMap, chunk, surface, query)
|
||||
else
|
||||
remakeChunk(regionMap, chunk, surface, natives, tick, query)
|
||||
end
|
||||
scoreChunk(regionMap, chunk, surface, natives, query)
|
||||
chunk = checkChunkPassability(chunk, surface, filteredTilesQuery, cliffQuery)
|
||||
|
||||
if (chunk ~= SENTINEL_IMPASSABLE_CHUNK) then
|
||||
registerChunkEnemies(regionMap, chunk, surface, filteredEntitiesQuery)
|
||||
scoreChunk(regionMap, chunk, surface, natives, filteredEntitiesQuery)
|
||||
|
||||
local chunkX = chunk.x
|
||||
|
||||
|
||||
+80
-114
@@ -7,6 +7,8 @@ local mapUtils = require("MapUtils")
|
||||
|
||||
-- constants
|
||||
|
||||
local WATER_TILE_NAMES = constants.WATER_TILE_NAMES
|
||||
|
||||
local DEFINES_DIRECTION_EAST = defines.direction.east
|
||||
local DEFINES_WIRE_TYPE_RED = defines.wire_type.red
|
||||
local DEFINES_WIRE_TYPE_GREEN = defines.wire_type.green
|
||||
@@ -26,6 +28,7 @@ local CHUNK_ALL_DIRECTIONS = constants.CHUNK_ALL_DIRECTIONS
|
||||
local CHUNK_IMPASSABLE = constants.CHUNK_IMPASSABLE
|
||||
|
||||
local CHUNK_TICK = constants.CHUNK_TICK
|
||||
local CHUNK_SIZE = constants.CHUNK_SIZE
|
||||
|
||||
local PATH_RATING = constants.PATH_RATING
|
||||
|
||||
@@ -39,67 +42,37 @@ local mFloor = math.floor
|
||||
|
||||
-- module code
|
||||
|
||||
local function fullScan(chunkTiles, x, y, get_tile)
|
||||
local endY = y + 31
|
||||
local i = 0
|
||||
local validTiles = 0
|
||||
|
||||
local function fullScan(x, y, count_entities_filtered, cliffQuery)
|
||||
local passableNorthSouth = false
|
||||
local passableEastWest = false
|
||||
|
||||
local area = cliffQuery.area
|
||||
local top = area[1]
|
||||
local bottom = area[2]
|
||||
top[2] = y
|
||||
bottom[2] = y + CHUNK_SIZE
|
||||
|
||||
for xi=x, x + 31 do
|
||||
local northSouth = true
|
||||
for yi=y, endY do
|
||||
i = i + 1
|
||||
local tile = get_tile(xi, yi)
|
||||
if not tile.collides_with("player-layer") then
|
||||
validTiles = validTiles + 1
|
||||
chunkTiles[i] = tile
|
||||
else
|
||||
northSouth = false
|
||||
chunkTiles[i] = nil
|
||||
end
|
||||
end
|
||||
if ((validTiles + (1024 - i)) < 615) then
|
||||
return 0, false, false
|
||||
end
|
||||
if northSouth then
|
||||
top[1] = xi
|
||||
bottom[1] = xi + 1
|
||||
if (count_entities_filtered(cliffQuery) == 0) then
|
||||
passableNorthSouth = true
|
||||
break
|
||||
end
|
||||
end
|
||||
for yi=1, 32 do
|
||||
local westEast = true
|
||||
for xi=0, 992, 32 do
|
||||
if not chunkTiles[yi + xi] then
|
||||
westEast = false
|
||||
break
|
||||
end
|
||||
end
|
||||
if westEast then
|
||||
|
||||
top[1] = x
|
||||
bottom[1] = x + CHUNK_SIZE
|
||||
for yi=y, y + 31 do
|
||||
top[2] = yi
|
||||
bottom[2] = yi + 1
|
||||
if (count_entities_filtered(cliffQuery) == 0) then
|
||||
passableEastWest = true
|
||||
break
|
||||
end
|
||||
end
|
||||
return validTiles * 0.0009765625, passableNorthSouth, passableEastWest
|
||||
end
|
||||
|
||||
local function spotCheck(x, y, get_tile)
|
||||
local valid = 0
|
||||
local i = 0
|
||||
for offsetX = 0, 31, 5 do
|
||||
for offsetY = 0, 31, 5 do
|
||||
i = i + 1
|
||||
local tile = get_tile(x + offsetX,
|
||||
y + offsetY)
|
||||
if not tile.collides_with("player-layer") then
|
||||
valid = valid + 1
|
||||
end
|
||||
end
|
||||
if ((valid + (49 - i)) < 12) then
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
return valid
|
||||
return passableNorthSouth, passableEastWest
|
||||
end
|
||||
|
||||
local function addEnemyStructureToChunk(regionMap, chunk, entity, base)
|
||||
@@ -217,77 +190,66 @@ end
|
||||
|
||||
-- external functions
|
||||
|
||||
function chunkUtils.checkChunkPassability(chunkTiles, chunk, surface)
|
||||
local x = chunk.x
|
||||
local y = chunk.y
|
||||
function chunkUtils.checkChunkPassability(chunk, surface, filteredTilesQuery, cliffQuery)
|
||||
local count_tiles_filtered = surface.count_tiles_filtered
|
||||
local count_entities_filtered = surface.count_entities_filtered
|
||||
|
||||
local get_tile = surface.get_tile
|
||||
local passScore = 0
|
||||
for i=1,#WATER_TILE_NAMES do
|
||||
filteredTilesQuery.name = WATER_TILE_NAMES[i]
|
||||
passScore = passScore + count_tiles_filtered(filteredTilesQuery)
|
||||
end
|
||||
|
||||
--[[
|
||||
0-12 represents water chunk
|
||||
13-44 chunk requires full scan
|
||||
45-49 assume chunk is passable in all directions
|
||||
--]]
|
||||
local cleanSpotCheck = spotCheck(x, y, get_tile)
|
||||
|
||||
local pass = CHUNK_ALL_DIRECTIONS
|
||||
if (cleanSpotCheck < 13) then
|
||||
pass = CHUNK_IMPASSABLE
|
||||
elseif (cleanSpotCheck < 45) then
|
||||
local rating, passableNorthSouth, passableEastWest = fullScan(chunkTiles, x, y, get_tile)
|
||||
chunk[PATH_RATING] = rating
|
||||
if (rating < 0.6) then
|
||||
pass = CHUNK_IMPASSABLE
|
||||
else
|
||||
if passableEastWest and passableNorthSouth then
|
||||
pass = CHUNK_ALL_DIRECTIONS
|
||||
elseif passableEastWest then
|
||||
pass = CHUNK_EAST_WEST
|
||||
elseif passableNorthSouth then
|
||||
pass = CHUNK_NORTH_SOUTH
|
||||
else
|
||||
pass = CHUNK_IMPASSABLE
|
||||
end
|
||||
passScore = 1 - (passScore * 0.0009765625)
|
||||
|
||||
local pass = CHUNK_IMPASSABLE
|
||||
if (passScore >= 0.60) then
|
||||
local passableNorthSouth, passableEastWest = fullScan(chunk.x, chunk.y, count_entities_filtered, cliffQuery)
|
||||
if passableEastWest and passableNorthSouth then
|
||||
pass = CHUNK_ALL_DIRECTIONS
|
||||
elseif passableEastWest then
|
||||
pass = CHUNK_EAST_WEST
|
||||
elseif passableNorthSouth then
|
||||
pass = CHUNK_NORTH_SOUTH
|
||||
end
|
||||
else
|
||||
chunk[PATH_RATING] = 1
|
||||
end
|
||||
if (pass == CHUNK_IMPASSABLE) then
|
||||
return SENTINEL_IMPASSABLE_CHUNK
|
||||
else
|
||||
chunk[PASSABLE] = pass
|
||||
chunk[PATH_RATING] = passScore
|
||||
return chunk
|
||||
end
|
||||
end
|
||||
|
||||
function chunkUtils.remakeChunk(regionMap, chunk, surface, natives, tick, tempQuery)
|
||||
tempQuery.force = "enemy"
|
||||
local enemies = surface.find_entities_filtered(tempQuery)
|
||||
-- function chunkUtils.remakeChunk(regionMap, chunk, surface, natives, tick, tempQuery)
|
||||
-- tempQuery.force = "enemy"
|
||||
-- local enemies = surface.find_entities_filtered(tempQuery)
|
||||
|
||||
local points = 0
|
||||
for f=1, #enemies do
|
||||
local enemy = enemies[f]
|
||||
local entityType = enemies[f].type
|
||||
if not ((enemy.name == "small-tendril-biter-rampant") or (enemy.name == "biter-spawner-hive-rampant")) then
|
||||
if (entityType == "unit-spawner") then
|
||||
points = points + 3
|
||||
elseif (entityType == "turret") then
|
||||
points = points + 2
|
||||
elseif (entityType == "unit") then
|
||||
points = points + 1
|
||||
end
|
||||
enemy.destroy()
|
||||
end
|
||||
end
|
||||
-- local foundBase = findNearbyBase(natives, chunk) or createBase(regionMap, natives, chunk, surface, tick)
|
||||
-- if foundBase then
|
||||
-- foundBase.upgradePoints = foundBase.upgradePoints + points
|
||||
-- end
|
||||
end
|
||||
-- local points = 0
|
||||
-- for f=1, #enemies do
|
||||
-- local enemy = enemies[f]
|
||||
-- local entityType = enemies[f].type
|
||||
-- if not ((enemy.name == "small-tendril-biter-rampant") or (enemy.name == "biter-spawner-hive-rampant")) then
|
||||
-- if (entityType == "unit-spawner") then
|
||||
-- points = points + 3
|
||||
-- elseif (entityType == "turret") then
|
||||
-- points = points + 2
|
||||
-- elseif (entityType == "unit") then
|
||||
-- points = points + 1
|
||||
-- end
|
||||
-- enemy.destroy()
|
||||
-- end
|
||||
-- end
|
||||
-- -- local foundBase = findNearbyBase(natives, chunk) or createBase(regionMap, natives, chunk, surface, tick)
|
||||
-- -- if foundBase then
|
||||
-- -- foundBase.upgradePoints = foundBase.upgradePoints + points
|
||||
-- -- end
|
||||
-- end
|
||||
|
||||
function chunkUtils.registerChunkEnemies(regionMap, chunk, surface, tempQuery)
|
||||
tempQuery.force = "enemy"
|
||||
local enemies = surface.find_entities_filtered(tempQuery)
|
||||
function chunkUtils.registerChunkEnemies(regionMap, chunk, surface, filteredEntitiesQuery)
|
||||
filteredEntitiesQuery.force = "enemy"
|
||||
local enemies = surface.find_entities_filtered(filteredEntitiesQuery)
|
||||
|
||||
for i=1, #enemies do
|
||||
local enemy = enemies[i]
|
||||
@@ -306,6 +268,10 @@ function chunkUtils.getWormCount(regionMap, chunk)
|
||||
return regionMap.chunkToWorms[chunk] or 0
|
||||
end
|
||||
|
||||
function chunkUtils.getEnemyStructureCount(regionMap, chunk)
|
||||
return (regionMap.chunkToNests[chunk] or 0) + (regionMap.chunkToWorms[chunk] or 0)
|
||||
end
|
||||
|
||||
function chunkUtils.getRetreatTick(regionMap, chunk)
|
||||
return regionMap.chunkToRetreats[chunk] or 0
|
||||
end
|
||||
@@ -342,14 +308,14 @@ function chunkUtils.addPlayerBaseGenerator(regionMap, chunk, playerGenerator)
|
||||
regionMap.chunkToPlayerBase[chunk] = regionMap.chunkToPlayerBase[chunk] + playerGenerator
|
||||
end
|
||||
|
||||
function chunkUtils.scoreChunk(regionMap, chunk, surface, natives, tempQuery)
|
||||
tempQuery.force = nil
|
||||
tempQuery.type = "resource"
|
||||
chunkUtils.setResourceGenerator(regionMap, chunk, surface.count_entities_filtered(tempQuery) * 0.001)
|
||||
function chunkUtils.scoreChunk(regionMap, chunk, surface, natives, filteredEntitiesQuery)
|
||||
filteredEntitiesQuery.force = nil
|
||||
filteredEntitiesQuery.type = "resource"
|
||||
chunkUtils.setResourceGenerator(regionMap, chunk, surface.count_entities_filtered(filteredEntitiesQuery) * 0.001)
|
||||
|
||||
tempQuery.type = nil
|
||||
tempQuery.force = "player"
|
||||
local entities = surface.find_entities_filtered(tempQuery)
|
||||
filteredEntitiesQuery.type = nil
|
||||
filteredEntitiesQuery.force = "player"
|
||||
local entities = surface.find_entities_filtered(filteredEntitiesQuery)
|
||||
|
||||
local playerObjects = 0
|
||||
local safeBuildings = natives.safeBuildings
|
||||
|
||||
+3
-1
@@ -16,11 +16,13 @@ constants.VERSION_26 = 26
|
||||
constants.VERSION_27 = 27
|
||||
constants.VERSION_28 = 28
|
||||
constants.VERSION_33 = 33
|
||||
constants.VERSION_35 = 35
|
||||
constants.VERSION_36 = 36
|
||||
|
||||
|
||||
-- misc
|
||||
|
||||
constants.WATER_TILE_NAMES = { "water", "deepwater", "water-green", "deepwater-green" }
|
||||
|
||||
constants.CHUNK_SIZE_DIVIDER = 0.03125
|
||||
constants.MAGIC_MAXIMUM_NUMBER = 1e99 -- used in loops trying to find the lowest/highest score
|
||||
constants.MAGIC_MAXIMUM_BASE_NUMBER = 100000000
|
||||
|
||||
@@ -39,11 +39,11 @@ function movementUtils.findMovementPosition(surface, position, distort)
|
||||
return (distort and distortPosition(pos)) or pos
|
||||
end
|
||||
|
||||
function movementUtils.addMovementPenalty(natives, units, x, y)
|
||||
function movementUtils.addMovementPenalty(natives, units, chunk)
|
||||
local penalties = units.penalties
|
||||
for i=1,#penalties do
|
||||
local penalty = penalties[i]
|
||||
if (penalty.x == x) and (penalty.y == y) then
|
||||
if (penalty.c == chunk) then
|
||||
penalty.v = penalty.v + MOVEMENT_PHEROMONE_GENERATOR_AMOUNT
|
||||
if (penalty.v > MAX_PENALTY_BEFORE_PURGE) then
|
||||
local group = units.group
|
||||
@@ -60,9 +60,10 @@ function movementUtils.addMovementPenalty(natives, units, x, y)
|
||||
if (#penalties == 7) then
|
||||
tableRemove(penalties, 7)
|
||||
end
|
||||
tableInsert(penalties, 1, { v = MOVEMENT_PHEROMONE_GENERATOR_AMOUNT,
|
||||
x = x,
|
||||
y = y })
|
||||
tableInsert(penalties,
|
||||
1,
|
||||
{ v = MOVEMENT_PHEROMONE_GENERATOR_AMOUNT,
|
||||
c = chunk })
|
||||
end
|
||||
|
||||
function movementUtils.lookupMovementPenalty(squad, x, y)
|
||||
|
||||
@@ -60,7 +60,7 @@ local scoreNeighborsForAttack = movementUtils.scoreNeighborsForAttack
|
||||
|
||||
local function scoreAttackLocation(squad, neighborChunk)
|
||||
local damage = (2*neighborChunk[MOVEMENT_PHEROMONE]) + neighborChunk[BASE_PHEROMONE] + (neighborChunk[PLAYER_PHEROMONE] * PLAYER_PHEROMONE_MULTIPLER)
|
||||
return damage - lookupMovementPenalty(squad, neighborChunk.x, neighborChunk.y)
|
||||
return damage - lookupMovementPenalty(squad, neighborChunk)
|
||||
end
|
||||
|
||||
function squadAttack.squadsAttack(regionMap, surface, natives)
|
||||
@@ -90,7 +90,7 @@ function squadAttack.squadsAttack(regionMap, surface, natives)
|
||||
getNeighborChunks(regionMap, chunkX, chunkY),
|
||||
scoreAttackLocation,
|
||||
squad)
|
||||
addMovementPenalty(natives, squad, chunkX, chunkY)
|
||||
addMovementPenalty(natives, squad, chunk)
|
||||
if group.valid and (attackChunk ~= SENTINEL_IMPASSABLE_CHUNK) then
|
||||
local playerBaseGenerator = getPlayerBaseGenerator(regionMap, attackChunk)
|
||||
if (playerBaseGenerator == 0) or ((groupState == DEFINES_GROUP_FINISHED) or (groupState == DEFINES_GROUP_GATHERING)) then
|
||||
@@ -110,6 +110,7 @@ function squadAttack.squadsAttack(regionMap, surface, natives)
|
||||
if position then
|
||||
attackPosition.x = position.x
|
||||
attackPosition.y = position.y
|
||||
|
||||
group.set_command(attackCmd)
|
||||
group.start_moving()
|
||||
else
|
||||
@@ -138,17 +139,14 @@ function squadAttack.squadsBeginAttack(natives, players)
|
||||
local groupPosition = group.position
|
||||
local kamikazeThreshold = calculateKamikazeThreshold(squad, natives)
|
||||
|
||||
local playerNearby = playersWithinProximityToPosition(players, groupPosition, 100)
|
||||
if playerNearby then
|
||||
if playersWithinProximityToPosition(players, groupPosition, 100) then
|
||||
squad.frenzy = true
|
||||
squad.frenzyPosition.x = groupPosition.x
|
||||
squad.frenzyPosition.y = groupPosition.y
|
||||
end
|
||||
|
||||
if (mRandom() < 0.70) then
|
||||
squad.kamikaze = mRandom() < kamikazeThreshold
|
||||
squad.status = SQUAD_RAIDING
|
||||
end
|
||||
squad.kamikaze = mRandom() < kamikazeThreshold
|
||||
squad.status = SQUAD_RAIDING
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -40,8 +40,7 @@ local findMovementPosition = movementUtils.findMovementPosition
|
||||
local getRetreatTick = chunkUtils.getRetreatTick
|
||||
local getPlayerBaseGenerator = chunkUtils.getPlayerBaseGenerator
|
||||
local setRetreatTick = chunkUtils.setRetreatTick
|
||||
local getNestCount = chunkUtils.getNestCount
|
||||
local getWormCount = chunkUtils.getWormCount
|
||||
local getEnemyStructureCount = chunkUtils.getEnemyStructureCount
|
||||
|
||||
-- module code
|
||||
|
||||
@@ -50,7 +49,7 @@ local function scoreRetreatLocation(regionMap, neighborChunk)
|
||||
end
|
||||
|
||||
function aiDefense.retreatUnits(chunk, position, squad, regionMap, surface, natives, tick)
|
||||
if (tick - getRetreatTick(regionMap, chunk) > INTERVAL_LOGIC) and (getNestCount(regionMap, chunk) == 0) and (getWormCount(regionMap, chunk) == 0) then
|
||||
if (tick - getRetreatTick(regionMap, chunk) > INTERVAL_LOGIC) and (getEnemyStructureCount(regionMap, chunk) == 0) then
|
||||
local performRetreat = false
|
||||
local enemiesToSquad = nil
|
||||
|
||||
@@ -97,7 +96,7 @@ function aiDefense.retreatUnits(chunk, position, squad, regionMap, surface, nati
|
||||
newSquad.rabid = true
|
||||
end
|
||||
end
|
||||
addMovementPenalty(natives, newSquad, chunk.x, chunk.y)
|
||||
addMovementPenalty(natives, newSquad, chunk)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -80,8 +80,8 @@
|
||||
(copyDirectory "prototypes" modFolder)))
|
||||
|
||||
(define (run)
|
||||
;;(copyFiles modFolder)
|
||||
(copyFiles modFolder)
|
||||
;;(copyFiles zipModFolder)
|
||||
(makeZip modFolder)
|
||||
;;(makeZip modFolder)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -186,6 +186,190 @@ data:extend({
|
||||
max_spawn_shift = 0,
|
||||
max_richness_for_spawn_shift = 100,
|
||||
call_for_help_radius = 50
|
||||
},
|
||||
|
||||
{
|
||||
type = "unit-spawner",
|
||||
name = "chunk-scanner-ew-rampant",
|
||||
icon = "__base__/graphics/icons/biter-spawner.png",
|
||||
icon_size = 32,
|
||||
flags = {},
|
||||
|
||||
collision_mask = {"player-layer"},
|
||||
|
||||
selectable_in_game = false,
|
||||
max_health = 350,
|
||||
order="b-b-g",
|
||||
subgroup="enemies",
|
||||
resistances =
|
||||
{
|
||||
{
|
||||
type = "physical",
|
||||
decrease = 2,
|
||||
percent = 15
|
||||
},
|
||||
{
|
||||
type = "explosion",
|
||||
decrease = 5,
|
||||
percent = 15,
|
||||
},
|
||||
{
|
||||
type = "fire",
|
||||
decrease = 3,
|
||||
percent = 60,
|
||||
}
|
||||
},
|
||||
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 = 0.02,
|
||||
collision_box = {{0, -0.5}, {32, 0}},
|
||||
selection_box = {{0, 0}, {32, 1}},
|
||||
-- in ticks per 1 pu
|
||||
pollution_absorbtion_absolute = 20,
|
||||
pollution_absorbtion_proportional = 0.01,
|
||||
corpse = "biter-spawner-corpse",
|
||||
dying_explosion = "blood-explosion-huge",
|
||||
max_count_of_owned_units = 7,
|
||||
max_friends_around_to_spawn = 5,
|
||||
animations =
|
||||
{
|
||||
spawner_idle_animation(0, biter_spawner_powered_tint),
|
||||
spawner_idle_animation(1, biter_spawner_powered_tint),
|
||||
spawner_idle_animation(2, biter_spawner_powered_tint),
|
||||
spawner_idle_animation(3, biter_spawner_powered_tint)
|
||||
},
|
||||
result_units = (function()
|
||||
local res = {}
|
||||
res[1] = {"small-biter", {{0.0, 0.3}, {0.6, 0.0}}}
|
||||
if not data.is_demo then
|
||||
-- from evolution_factor 0.3 the weight for medium-biter is linearly rising from 0 to 0.3
|
||||
-- this means for example that when the evolution_factor is 0.45 the probability of spawning
|
||||
-- a small biter is 66% while probability for medium biter is 33%.
|
||||
res[2] = {"medium-biter", {{0.2, 0.0}, {0.6, 0.3}, {0.7, 0.1}}}
|
||||
-- for evolution factor of 1 the spawning probabilities are: small-biter 0%, medium-biter 1/8, big-biter 4/8, behemoth biter 3/8
|
||||
res[3] = {"big-biter", {{0.5, 0.0}, {1.0, 0.4}}}
|
||||
res[4] = {"behemoth-biter", {{0.9, 0.0}, {1.0, 0.3}}}
|
||||
end
|
||||
return res
|
||||
end)(),
|
||||
-- With zero evolution the spawn rate is 6 seconds, with max evolution it is 2.5 seconds
|
||||
spawning_cooldown = {360, 150},
|
||||
spawning_radius = 10,
|
||||
spawning_spacing = 3,
|
||||
max_spawn_shift = 0,
|
||||
max_richness_for_spawn_shift = 100,
|
||||
call_for_help_radius = 50
|
||||
},
|
||||
|
||||
{
|
||||
type = "unit-spawner",
|
||||
name = "chunk-scanner-ns-rampant",
|
||||
icon = "__base__/graphics/icons/biter-spawner.png",
|
||||
icon_size = 32,
|
||||
flags = {},
|
||||
|
||||
collision_mask = {"player-layer"},
|
||||
|
||||
selectable_in_game = false,
|
||||
max_health = 350,
|
||||
order="b-b-g",
|
||||
subgroup="enemies",
|
||||
resistances =
|
||||
{
|
||||
{
|
||||
type = "physical",
|
||||
decrease = 2,
|
||||
percent = 15
|
||||
},
|
||||
{
|
||||
type = "explosion",
|
||||
decrease = 5,
|
||||
percent = 15,
|
||||
},
|
||||
{
|
||||
type = "fire",
|
||||
decrease = 3,
|
||||
percent = 60,
|
||||
}
|
||||
},
|
||||
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 = 0.02,
|
||||
collision_box = {{-0.5, 0}, {0, 32}},
|
||||
selection_box = {{0, 0}, {32, 1}},
|
||||
-- in ticks per 1 pu
|
||||
pollution_absorbtion_absolute = 20,
|
||||
pollution_absorbtion_proportional = 0.01,
|
||||
corpse = "biter-spawner-corpse",
|
||||
dying_explosion = "blood-explosion-huge",
|
||||
max_count_of_owned_units = 7,
|
||||
max_friends_around_to_spawn = 5,
|
||||
animations =
|
||||
{
|
||||
spawner_idle_animation(0, biter_spawner_powered_tint),
|
||||
spawner_idle_animation(1, biter_spawner_powered_tint),
|
||||
spawner_idle_animation(2, biter_spawner_powered_tint),
|
||||
spawner_idle_animation(3, biter_spawner_powered_tint)
|
||||
},
|
||||
result_units = (function()
|
||||
local res = {}
|
||||
res[1] = {"small-biter", {{0.0, 0.3}, {0.6, 0.0}}}
|
||||
if not data.is_demo then
|
||||
-- from evolution_factor 0.3 the weight for medium-biter is linearly rising from 0 to 0.3
|
||||
-- this means for example that when the evolution_factor is 0.45 the probability of spawning
|
||||
-- a small biter is 66% while probability for medium biter is 33%.
|
||||
res[2] = {"medium-biter", {{0.2, 0.0}, {0.6, 0.3}, {0.7, 0.1}}}
|
||||
-- for evolution factor of 1 the spawning probabilities are: small-biter 0%, medium-biter 1/8, big-biter 4/8, behemoth biter 3/8
|
||||
res[3] = {"big-biter", {{0.5, 0.0}, {1.0, 0.4}}}
|
||||
res[4] = {"behemoth-biter", {{0.9, 0.0}, {1.0, 0.3}}}
|
||||
end
|
||||
return res
|
||||
end)(),
|
||||
-- With zero evolution the spawn rate is 6 seconds, with max evolution it is 2.5 seconds
|
||||
spawning_cooldown = {360, 150},
|
||||
spawning_radius = 10,
|
||||
spawning_spacing = 3,
|
||||
max_spawn_shift = 0,
|
||||
max_richness_for_spawn_shift = 100,
|
||||
call_for_help_radius = 50
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
@@ -150,11 +150,15 @@ function tests.tunnelTest()
|
||||
game.surfaces[1].create_entity({name="tunnel-entrance-rampant", position={chunkX, chunkY}})
|
||||
end
|
||||
|
||||
function tests.createEnemy(x)
|
||||
function tests.createEnemy(x,d)
|
||||
local playerPosition = game.players[1].position
|
||||
local chunkX = math.floor(playerPosition.x * 0.03125) * 32
|
||||
local chunkY = math.floor(playerPosition.y * 0.03125) * 32
|
||||
return game.surfaces[1].create_entity({name=x, position={chunkX, chunkY}})
|
||||
local a = {name=x, position={chunkX, chunkY}}
|
||||
if d then
|
||||
a['direction'] = d
|
||||
end
|
||||
return game.surfaces[1].create_entity(a)
|
||||
end
|
||||
|
||||
function tests.registeredNest(x)
|
||||
|
||||
Reference in New Issue
Block a user