mirror of
https://github.com/veden/Rampant.git
synced 2025-02-03 13:11:54 +02:00
added fire biter prototype logic
This commit is contained in:
parent
15a9fa5d51
commit
7a414e9ade
@ -3,7 +3,7 @@ Factorio Mod - Uses potential fields to improve the enemy AI
|
||||
|
||||
# Recommend Map Settings
|
||||
|
||||
Enemy Bases Frequeny:Very Low, Size:Very Big
|
||||
Enemy Bases Frequeny:Very Low, Size:Big
|
||||
Everything else is open to what ever you like
|
||||
|
||||
# Features
|
||||
|
37
control.lua
37
control.lua
@ -18,22 +18,6 @@ local regionMap -- chunk based map
|
||||
local pendingChunks -- pending chunks to be processed
|
||||
local natives -- units that are being commanded
|
||||
|
||||
-- initialization
|
||||
|
||||
chunkProcessor.install(chunkUtils.checkChunkPassability)
|
||||
chunkProcessor.install(chunkUtils.scoreChunk)
|
||||
|
||||
mapProcessor.install(pheromoneUtils.enemyBaseScent, 0, 1)
|
||||
mapProcessor.install(pheromoneUtils.playerDefenseScent, 0, 1)
|
||||
mapProcessor.install(pheromoneUtils.playerBaseScent, 0, 1)
|
||||
mapProcessor.install(aiBuilding.sendScouts, 0.05, 0.10)
|
||||
mapProcessor.install(aiBuilding.formSquads, 0.11, 0.25)
|
||||
mapProcessor.install(pheromoneUtils.processPheromone, 0, 1)
|
||||
|
||||
-- constants
|
||||
|
||||
local DEATH_PHEROMONE_GENERATOR_AMOUNT = constants.DEATH_PHEROMONE_GENERATOR_AMOUNT
|
||||
|
||||
-- imported functions
|
||||
|
||||
local processPendingChunks = chunkProcessor.processPendingChunks
|
||||
@ -43,6 +27,7 @@ local processMap = mapProcessor.processMap
|
||||
local accumulatePoints = aiBuilding.accumulatePoints
|
||||
local removeScout = aiBuilding.removeScout
|
||||
local scouting = aiBuilding.scouting
|
||||
local digTunnel = aiBuilding.digTunnel
|
||||
|
||||
local playerScent = pheromoneUtils.playerScent
|
||||
local deathScent = pheromoneUtils.deathScent
|
||||
@ -58,8 +43,6 @@ local retreatUnits = aiDefense.retreatUnits
|
||||
|
||||
local addRemoveObject = mapUtils.addRemoveObject
|
||||
|
||||
local mRandom = math.random
|
||||
|
||||
-- hook functions
|
||||
|
||||
function onInit()
|
||||
@ -127,8 +110,12 @@ function onTick(event)
|
||||
squadAttackPlayer(regionMap, surface, natives, game.players)
|
||||
|
||||
squadBeginAttack(natives)
|
||||
-- digTunnel(regionMap, surface, natives)
|
||||
squadAttackLocation(regionMap, surface, natives)
|
||||
|
||||
-- print(natives.points)
|
||||
end
|
||||
|
||||
processPendingChunks(regionMap, surface, natives, pendingChunks)
|
||||
|
||||
processMap(regionMap, surface, natives, game.evolution_factor)
|
||||
@ -149,18 +136,13 @@ function onDeath(event)
|
||||
if (entity.type == "unit") then
|
||||
local entityPosition = entity.position
|
||||
-- drop death pheromone where unit died
|
||||
local squad = convertUnitGroupToSquad(natives, entity.unit_group)
|
||||
|
||||
local surface = game.surfaces[1]
|
||||
|
||||
deathScent(regionMap,
|
||||
surface,
|
||||
entityPosition.x,
|
||||
entityPosition.y,
|
||||
squad,
|
||||
DEATH_PHEROMONE_GENERATOR_AMOUNT)
|
||||
deathScent(regionMap, surface, entityPosition.x, entityPosition.y)
|
||||
|
||||
if (event.force ~= nil) and (event.force.name == "player") then
|
||||
local squad = convertUnitGroupToSquad(natives, entity.unit_group)
|
||||
retreatUnits(entityPosition, squad, regionMap, surface, natives)
|
||||
end
|
||||
|
||||
@ -174,7 +156,10 @@ function onDeath(event)
|
||||
end
|
||||
|
||||
function onPutItem(event)
|
||||
print(serpent.dump(event))
|
||||
-- local player = game.players[event.player_index]
|
||||
-- if (player.surface.index==1) then
|
||||
-- aiBuilding.fillTunnel(global.regionMap, player.surface, global.natives, event.positions)
|
||||
-- end
|
||||
end
|
||||
|
||||
-- hooks
|
||||
|
4
data.lua
4
data.lua
@ -3,6 +3,8 @@ if RampantConfig == nil then
|
||||
end
|
||||
|
||||
require("prototypes/buildings/tunnel")
|
||||
|
||||
require("prototypes/tile/fillableDirt")
|
||||
|
||||
require("prototypes/enemies/suicideBiters")
|
||||
require("prototypes/enemies/suicideBiters")
|
||||
require("prototypes/enemies/fireSpitters")
|
@ -61,7 +61,7 @@ function aiAttack.squadAttackLocation(regionMap, surface, natives)
|
||||
local group = squad.group
|
||||
if group.valid and ((squad.status == SQUAD_RAIDING) or (squad.status == SQUAD_SUICIDE_RAID)) then
|
||||
local groupState = group.state
|
||||
if (groupState == GROUP_STATE_FINISHED) or (groupState == GROUP_STATE_GATHERING) or (groupState == GROUP_STATE_MOVING) then
|
||||
if (groupState == GROUP_STATE_FINISHED) or (groupState == GROUP_STATE_GATHERING) or ((groupState == GROUP_STATE_MOVING) and (squad.cycles == 0)) then
|
||||
local chunk = positionToChunk(regionMap, group.position.x, group.position.y)
|
||||
addSquadMovementPenalty(squad, chunk.cX, chunk.cY)
|
||||
local attackLocationNeighbors = getCardinalChunks(regionMap, chunk.cX, chunk.cY)
|
||||
@ -77,7 +77,7 @@ function aiAttack.squadAttackLocation(regionMap, surface, natives)
|
||||
attackPosition.y = neighborChunk.pY
|
||||
local squadMovementPenalty = lookupSquadMovementPenalty(squad, neighborChunk.cX, neighborChunk.cY)
|
||||
local damageScore = surface.get_pollution(attackPosition) + neighborChunk[PLAYER_BASE_PHEROMONE] + neighborChunk[PLAYER_PHEROMONE] + neighborChunk[PLAYER_DEFENSE_GENERATOR]
|
||||
local avoidScore = neighborChunk[DEATH_PHEROMONE] + (neighborChunk[ENEMY_BASE_GENERATOR] * 2) --+ (neighborChunk[ENEMY_BASE_PHEROMONE] * 0.5)
|
||||
local avoidScore = neighborChunk[DEATH_PHEROMONE] + neighborChunk[ENEMY_BASE_PHEROMONE]
|
||||
local score = damageScore - avoidScore - squadMovementPenalty
|
||||
if (score > attackScore) then
|
||||
attackScore = score
|
||||
@ -96,6 +96,8 @@ function aiAttack.squadAttackLocation(regionMap, surface, natives)
|
||||
attackPosition = positionDirectionToChunkCornerCardinal(attackDirection, attackChunk)
|
||||
squad.cX = attackChunk.cX
|
||||
squad.cY = attackChunk.cY
|
||||
squad.cycles = 2
|
||||
squad.direction = attackDirection
|
||||
|
||||
group.set_command({type=COMMAND_ATTACK_AREA,
|
||||
destination=attackPosition,
|
||||
|
@ -8,6 +8,9 @@ local unitGroupUtils = require("UnitGroupUtils")
|
||||
|
||||
-- constants
|
||||
|
||||
local SQUAD_GUARDING = constants.SQUAD_GUARDING
|
||||
local SQUAD_BURROWING = constants.SQUAD_BURROWING
|
||||
|
||||
local PLAYER_BASE_PHEROMONE = constants.PLAYER_BASE_PHEROMONE
|
||||
local PLAYER_PHEROMONE = constants.PLAYER_PHEROMONE
|
||||
local PLAYER_DEFENSE_PHEROMONE = constants.PLAYER_DEFENSE_PHEROMONE
|
||||
@ -20,6 +23,7 @@ local ENEMY_BASE_GENERATOR = constants.ENEMY_BASE_GENERATOR
|
||||
|
||||
local AI_SCOUT_COST = constants.AI_SCOUT_COST
|
||||
local AI_SQUAD_COST = constants.AI_SQUAD_COST
|
||||
local AI_TUNNEL_COST = constants.AI_TUNNEL_COST
|
||||
|
||||
local AI_MAX_SQUAD_COUNT = constants.AI_MAX_SQUAD_COUNT
|
||||
local AI_MAX_SQUAD_SIZE = constants.AI_MAX_SQUAD_SIZE
|
||||
@ -85,10 +89,6 @@ function aiBuilding.scouting(regionMap, surface, natives)
|
||||
-- if ()
|
||||
end
|
||||
|
||||
function aiBuilding.digTunnel(regionMap, surface, natives)
|
||||
|
||||
end
|
||||
|
||||
function aiBuilding.formSquads(regionMap, surface, natives, chunk, neighbors, evolution_factor)
|
||||
if (natives.points > AI_SQUAD_COST) then
|
||||
local score = chunk[PLAYER_BASE_PHEROMONE] + chunk[PLAYER_PHEROMONE] + chunk[PLAYER_DEFENSE_PHEROMONE] + surface.get_pollution({chunk.pX, chunk.pY})
|
||||
|
@ -47,7 +47,7 @@ local retreatFilter = {[SQUAD_RETREATING] = true}
|
||||
|
||||
function aiDefense.retreatUnits(position, squad, regionMap, surface, natives)
|
||||
local chunk = getChunkByPosition(regionMap, position.x, position.y)
|
||||
if (chunk ~= nil) and (chunk[DEATH_PHEROMONE] > (game.evolution_factor * RETREAT_DEATH_PHEROMONE_LEVEL)) then -- TODO sliding scale of death based on evolution
|
||||
if (chunk ~= nil) and (chunk[DEATH_PHEROMONE] > (game.evolution_factor * RETREAT_DEATH_PHEROMONE_LEVEL)) then
|
||||
local performRetreat = false
|
||||
local enemiesToSquad
|
||||
|
||||
@ -93,10 +93,6 @@ function aiDefense.retreatUnits(position, squad, regionMap, surface, natives)
|
||||
-- retreatPosition.x = exitPath.pX + constants.HALF_CHUNK_SIZE
|
||||
-- retreatPosition.y = exitPath.pY + constants.HALF_CHUNK_SIZE
|
||||
|
||||
if (squad ~= nil) and (squad.cX ~= nil) then
|
||||
local chunk = getChunkByIndex(regionMap, squad.cX, squad.cY)
|
||||
chunk[DEATH_PHEROMONE] = chunk[DEATH_PHEROMONE] + DEATH_PHEROMONE_GENERATOR_AMOUNT
|
||||
end
|
||||
|
||||
local newSquad = findNearBySquad(natives,
|
||||
retreatPosition,
|
||||
@ -112,6 +108,10 @@ function aiDefense.retreatUnits(position, squad, regionMap, surface, natives)
|
||||
membersToSquad(newSquad, enemiesToSquad, false, DISTRACTION_NONE)
|
||||
else
|
||||
-- newSquad.penalties = squad.penalties
|
||||
-- newSquad.lastCX = squad.cX
|
||||
-- newSquad.lastCY = squad.cY
|
||||
-- newSquad.lastDirection = squad.direction
|
||||
-- newSquad.canTunnel = true
|
||||
membersToSquad(newSquad, squad.group.members, true, DISTRACTION_NONE)
|
||||
end
|
||||
end
|
||||
|
@ -12,10 +12,8 @@ local CHUNK_MAX_QUEUE_SIZE = constants.CHUNK_MAX_QUEUE_SIZE
|
||||
-- imported functions
|
||||
|
||||
local createChunk = chunkUtils.createChunk
|
||||
|
||||
-- premade tables
|
||||
|
||||
local processors = {}
|
||||
local checkChunkPassability = chunkUtils.checkChunkPassability
|
||||
local scoreChunk = chunkUtils.scoreChunk
|
||||
|
||||
-- module code
|
||||
|
||||
@ -41,9 +39,8 @@ function chunkProcessor.processPendingChunks(regionMap, surface, natives, pendin
|
||||
end
|
||||
regionMap[chunkX][chunk.cY] = chunk
|
||||
|
||||
for i=1, #processors do
|
||||
processors[i](chunk, surface, natives)
|
||||
end
|
||||
checkChunkPassability(chunk, surface, natives)
|
||||
scoreChunk(chunk, surface, natives)
|
||||
|
||||
local processQueue = regionMap.pQ[regionMap.pI]
|
||||
if (#processQueue == CHUNK_MAX_QUEUE_SIZE) then
|
||||
@ -61,8 +58,4 @@ function chunkProcessor.processPendingChunks(regionMap, surface, natives, pendin
|
||||
end
|
||||
end
|
||||
|
||||
function chunkProcessor.install(processor)
|
||||
processors[#processors+1] = processor
|
||||
end
|
||||
|
||||
return chunkProcessor
|
@ -2,15 +2,14 @@ local constants = {}
|
||||
|
||||
-- misc
|
||||
|
||||
constants.MAGIC_MAXIMUM_NUMBER = 1e99 -- used in loops trying to find the lowest score
|
||||
-- constants.MAX_PHEROMONE = 20000
|
||||
constants.RETREAT_DEATH_PHEROMONE_LEVEL = 12000
|
||||
constants.MAGIC_MAXIMUM_NUMBER = 1e99 -- used in loops trying to find the lowest/highest score
|
||||
constants.RETREAT_DEATH_PHEROMONE_LEVEL = 10000
|
||||
|
||||
constants.CHUNK_MAX_QUEUE_SIZE = 400
|
||||
|
||||
-- ai
|
||||
|
||||
constants.AI_POINT_GENERATOR_AMOUNT = 10
|
||||
constants.AI_POINT_GENERATOR_AMOUNT = 5
|
||||
constants.AI_SCOUT_COST = 45
|
||||
constants.AI_SQUAD_COST = 150
|
||||
constants.AI_SETTLER_COST = 75
|
||||
@ -33,13 +32,16 @@ constants.EAST_WEST = 2
|
||||
constants.MOVEMENT_PENALTY_PHEROMONE_GENERATOR_AMOUNT = 500
|
||||
constants.MOVEMENT_PHEROMONE_GENERATOR_AMOUNT = 500
|
||||
constants.ENEMY_BASE_PHEROMONE_GENERATOR_AMOUNT = 35
|
||||
constants.DEATH_PHEROMONE_GENERATOR_AMOUNT = 35
|
||||
constants.DEATH_PHEROMONE_GENERATOR_AMOUNT = 100
|
||||
constants.PLAYER_PHEROMONE_GENERATOR_AMOUNT = 300
|
||||
|
||||
-- pheromone diffusion amounts
|
||||
|
||||
constants.STANDARD_PHERONOME_DIFFUSION_AMOUNT = 0.03
|
||||
constants.DEATH_PHEROMONE_DIFFUSION_AMOUNT = 0.00125
|
||||
constants.DEATH_PHEROMONE_DIFFUSION_AMOUNT = 0.00250
|
||||
|
||||
constants.DEATH_PHEROMONE_PERSISTANCE = 0.99
|
||||
constants.STANDARD_PHEROMONE_PERSISTANCE = 0.95
|
||||
|
||||
-- chunk attributes
|
||||
|
||||
@ -62,13 +64,13 @@ constants.EAST_WEST_PASSABLE = 11
|
||||
constants.SQUAD_RETREATING = 1 -- used during squad retreat
|
||||
constants.SQUAD_GUARDING = 2 -- used when squad is idle
|
||||
constants.SQUAD_ATTACKING = 3 -- used as an attack state to be transitioned into hunt, raid, siege, burrow
|
||||
-- constants.SQUAD_SIEGE = 3
|
||||
constants.SQUAD_HUNTING = 4 -- used when player is close to unit group
|
||||
constants.SQUAD_SUICIDE_HUNT = 5 -- used when player is close with no retreat
|
||||
-- constants.SQUAD_BURROWING = 6
|
||||
-- constants.SQUAD_SCOUTING = 7
|
||||
constants.SQUAD_BURROWING = 6
|
||||
constants.SQUAD_RAIDING = 8 -- used when player stuff is close
|
||||
constants.SQUAD_SUICIDE_RAID = 9 -- when player stuff is close with no retreat
|
||||
-- constants.SQUAD_SCOUTING = 7
|
||||
-- constants.SQUAD_SIEGE = 3
|
||||
|
||||
-- player building pheromones
|
||||
|
||||
|
@ -3,19 +3,21 @@ local mapProcessor = {}
|
||||
-- imports
|
||||
|
||||
local mapUtils = require("MapUtils")
|
||||
local pheromoneUtils = require("PheromoneUtils")
|
||||
local aiBuilding = require("AIBuilding")
|
||||
|
||||
-- imported functions
|
||||
|
||||
local scents = pheromoneUtils.scents
|
||||
local processPheromone = pheromoneUtils.processPheromone
|
||||
|
||||
local sendScouts = aiBuilding.sendScouts
|
||||
local formSquads = aiBuilding.formSquads
|
||||
|
||||
local getCardinalChunks = mapUtils.getCardinalChunks
|
||||
|
||||
local mRandom = math.random
|
||||
|
||||
-- premade tables
|
||||
|
||||
local processors = {}
|
||||
local processorsProbabilityLow = {}
|
||||
local processorsProbabilityHigh = {}
|
||||
|
||||
-- module code
|
||||
|
||||
-- processing is not consistant as it depends on the number of chunks that have been generated
|
||||
@ -23,23 +25,27 @@ local processorsProbabilityHigh = {}
|
||||
-- In theory, this might be fine as smaller bases have less surface to attack and need to have
|
||||
-- pheromone dissipate at a faster rate.
|
||||
function mapProcessor.processMap(regionMap, surface, natives, evolution_factor)
|
||||
local count = 0
|
||||
|
||||
if (regionMap.pP == 1) then
|
||||
regionMap.pR = mRandom()
|
||||
end
|
||||
|
||||
local roll = regionMap.pR
|
||||
|
||||
|
||||
local chunkQueue = regionMap.pQ[regionMap.pP]
|
||||
for x=1, #chunkQueue do
|
||||
local chunk = chunkQueue[x]
|
||||
local cardinalArray = getCardinalChunks(regionMap, chunk.cX, chunk.cY)
|
||||
for i=1, #processors do
|
||||
if (processorsProbabilityLow[i] <= roll) and (roll <= processorsProbabilityHigh[i]) then
|
||||
processors[i](regionMap, surface, natives, chunk, cardinalArray, evolution_factor)
|
||||
end
|
||||
|
||||
scents(regionMap, surface, natives, chunk, cardinalArray, evolution_factor)
|
||||
|
||||
if (0.05 <= roll) and (roll <= 0.10) then
|
||||
sendScouts(regionMap, surface, natives, chunk, cardinalArray, evolution_factor)
|
||||
end
|
||||
if (0.11 <= roll) and (roll <= 0.25) then
|
||||
formSquads(regionMap, surface, natives, chunk, cardinalArray, evolution_factor)
|
||||
end
|
||||
|
||||
processPheromone(regionMap, surface, natives, chunk, cardinalArray, evolution_factor)
|
||||
end
|
||||
|
||||
regionMap.pP = regionMap.pP + 1
|
||||
@ -48,11 +54,4 @@ function mapProcessor.processMap(regionMap, surface, natives, evolution_factor)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function mapProcessor.install(processor, useProbabilityLow, useProbabilityHigh)
|
||||
processors[#processors+1] = processor
|
||||
processorsProbabilityLow[#processorsProbabilityLow+1] = useProbabilityLow
|
||||
processorsProbabilityHigh[#processorsProbabilityHigh+1] = useProbabilityHigh
|
||||
end
|
||||
|
||||
return mapProcessor
|
@ -20,51 +20,43 @@ local PLAYER_BASE_GENERATOR = constants.PLAYER_BASE_GENERATOR
|
||||
local ENEMY_BASE_GENERATOR = constants.ENEMY_BASE_GENERATOR
|
||||
|
||||
local PLAYER_PHEROMONE_GENERATOR_AMOUNT = constants.PLAYER_PHEROMONE_GENERATOR_AMOUNT
|
||||
local DEATH_PHEROMONE_GENERATOR_AMOUNT = constants.DEATH_PHEROMONE_GENERATOR_AMOUNT
|
||||
|
||||
local STANDARD_PHERONOME_DIFFUSION_AMOUNT = constants.STANDARD_PHERONOME_DIFFUSION_AMOUNT
|
||||
local DEATH_PHEROMONE_DIFFUSION_AMOUNT = constants.DEATH_PHEROMONE_DIFFUSION_AMOUNT
|
||||
|
||||
local DEATH_PHEROMONE_PERSISTANCE = constants.DEATH_PHEROMONE_PERSISTANCE
|
||||
local STANDARD_PHEROMONE_PERSISTANCE = constants.STANDARD_PHEROMONE_PERSISTANCE
|
||||
|
||||
-- imported functions
|
||||
|
||||
local getChunkByPosition = mapUtils.getChunkByPosition
|
||||
|
||||
local mFloor = math.floor
|
||||
local mFloor = math.floor
|
||||
|
||||
-- module code
|
||||
|
||||
function pheromoneUtils.deathScent(regionMap, surface, x, y, squad, amount)
|
||||
|
||||
if (squad ~= nil) and (squad.cX ~= nil) then
|
||||
local chunk = getChunkByPosition(regionMap, x, y)
|
||||
if (chunk ~= nil) then
|
||||
chunk[DEATH_PHEROMONE] = chunk[DEATH_PHEROMONE] + (amount * 5)
|
||||
end
|
||||
|
||||
function pheromoneUtils.scents(regionMap, surface, natives, chunk, neighbors, evolution_factor)
|
||||
local amount = chunk[PLAYER_DEFENSE_GENERATOR]
|
||||
if (amount > 0) then
|
||||
chunk[PLAYER_DEFENSE_PHEROMONE] = chunk[PLAYER_DEFENSE_PHEROMONE] + amount
|
||||
end
|
||||
|
||||
amount = chunk[PLAYER_BASE_GENERATOR]
|
||||
if (amount > 0) then
|
||||
chunk[PLAYER_BASE_PHEROMONE] = chunk[PLAYER_BASE_PHEROMONE] + amount
|
||||
end
|
||||
|
||||
amount = chunk[ENEMY_BASE_GENERATOR]
|
||||
if (amount > 0) then
|
||||
chunk[ENEMY_BASE_PHEROMONE] = chunk[ENEMY_BASE_PHEROMONE] + amount
|
||||
end
|
||||
end
|
||||
|
||||
function pheromoneUtils.deathScent(regionMap, surface, x, y)
|
||||
local chunk = getChunkByPosition(regionMap, x, y)
|
||||
if (chunk ~= nil) then
|
||||
chunk[DEATH_PHEROMONE] = chunk[DEATH_PHEROMONE] + amount
|
||||
end
|
||||
end
|
||||
|
||||
function pheromoneUtils.playerDefenseScent(regionMap, surface, natives, chunk, neighbors, evolution_factor)
|
||||
local baseScore = chunk[PLAYER_DEFENSE_GENERATOR]
|
||||
if (baseScore > 0) then
|
||||
chunk[PLAYER_DEFENSE_PHEROMONE] = chunk[PLAYER_DEFENSE_PHEROMONE] + baseScore
|
||||
end
|
||||
end
|
||||
|
||||
function pheromoneUtils.playerBaseScent(regionMap, surface, natives, chunk, neighbors, evolution_factor)
|
||||
local baseScore = chunk[PLAYER_BASE_GENERATOR]
|
||||
if (baseScore > 0) then
|
||||
chunk[PLAYER_BASE_PHEROMONE] = chunk[PLAYER_BASE_PHEROMONE] + baseScore
|
||||
end
|
||||
end
|
||||
|
||||
function pheromoneUtils.enemyBaseScent(regionMap, surface, natives, chunk, neighbors, evolution_factor)
|
||||
local spawners = chunk[ENEMY_BASE_GENERATOR]
|
||||
if (spawners > 0) then
|
||||
chunk[ENEMY_BASE_PHEROMONE] = chunk[ENEMY_BASE_PHEROMONE] + spawners
|
||||
chunk[DEATH_PHEROMONE] = chunk[DEATH_PHEROMONE] + DEATH_PHEROMONE_GENERATOR_AMOUNT
|
||||
end
|
||||
end
|
||||
|
||||
@ -84,13 +76,13 @@ function pheromoneUtils.processPheromone(regionMap, surface, natives, chunk, nei
|
||||
local persistence
|
||||
if (x == DEATH_PHEROMONE) then
|
||||
diffusionAmount = DEATH_PHEROMONE_DIFFUSION_AMOUNT
|
||||
persistence = 0.99
|
||||
persistence = DEATH_PHEROMONE_PERSISTANCE
|
||||
else
|
||||
diffusionAmount = STANDARD_PHERONOME_DIFFUSION_AMOUNT
|
||||
persistence = 0.95
|
||||
persistence = STANDARD_PHEROMONE_PERSISTANCE
|
||||
end
|
||||
local totalDiffused = 0
|
||||
for i=1,4 do
|
||||
for i=1,#neighbors do
|
||||
local neighborChunk = neighbors[i]
|
||||
if (neighborChunk ~= nil) then
|
||||
local diffusedAmount = (chunk[x] * diffusionAmount)
|
||||
|
@ -1,5 +1,14 @@
|
||||
local tunnelUtils = {}
|
||||
|
||||
function tunnelUtils.digTunnel(regionMap, surface, natives, startChunk, endChunk)
|
||||
|
||||
end
|
||||
|
||||
function tunnelUtils.fillTunnel(regionMap, surface, natives, tilePositions)
|
||||
local tunnels = natives.tunnels
|
||||
for i=1, #tunnels do
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
return tunnelUtils
|
@ -2,6 +2,7 @@
|
||||
|
||||
[entity-name]
|
||||
tunnel-entrance = Tunnel Entrance
|
||||
|
||||
small-suicide-biter = Small Suicide Biter
|
||||
medium-suicide-biter = Medium Suicide Biter
|
||||
big-suicide-biter = Big Suicide Biter
|
||||
@ -9,6 +10,7 @@ behemoth-suicide-biter = Behemoth Suicide Biter
|
||||
|
||||
[entity-description]
|
||||
tunnel-entrance = This tunnel is used by the biters to bypass player defenses. Fill the hole using landfill.
|
||||
|
||||
small-suicide-biter = These biters will explode at close range
|
||||
medium-suicide-biter = These biters will explode at close range
|
||||
big-suicide-biter = These biters will explode at close range
|
||||
|
@ -8,18 +8,6 @@ data:extend({
|
||||
order = "b[decorative]-k[tunnel-entrance]-a[big]",
|
||||
collision_box = {{-1.3, -1.3}, {1.3, 1.3}},
|
||||
selection_box = {{-1.5, -1.5}, {1.5, 1.5}},
|
||||
-- minable =
|
||||
-- {
|
||||
-- mining_particle = "stone-particle",
|
||||
-- mining_time = 8,
|
||||
-- result = "stone",
|
||||
-- count = 20
|
||||
-- },
|
||||
-- loot =
|
||||
-- {
|
||||
-- {item = "stone", probability = 1, count_min = 5, count_max = 10}
|
||||
-- },
|
||||
-- mined_sound = { filename = "__base__/sound/deconstruct-bricks.ogg" },
|
||||
render_layer = "remnants",
|
||||
max_health = 0,
|
||||
pictures =
|
||||
|
154
prototypes/enemies/BiterFunctions.lua
Executable file
154
prototypes/enemies/BiterFunctions.lua
Executable file
@ -0,0 +1,154 @@
|
||||
local biterFunctions = {}
|
||||
|
||||
function biterFunctions.makeBiter(biterAttributes, biterAttack, biterResistances)
|
||||
return {
|
||||
type = "unit",
|
||||
name = biterAttributes.name,
|
||||
icon = "__base__/graphics/icons/small-biter.png",
|
||||
flags = {"placeable-player", "placeable-enemy", "placeable-off-grid", "breaths-air"},
|
||||
max_health = biterAttributes.health,
|
||||
order = "b-b-a",
|
||||
subgroup="enemies",
|
||||
healing_per_tick = biterAttributes.healing,
|
||||
resistances = biterResistances,
|
||||
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},
|
||||
{0.7 * biterAttributes.scale, 0.3 * biterAttributes.scale}},
|
||||
sticker_box = {{-0.6 * biterAttributes.scale, -0.8 * biterAttributes.scale},
|
||||
{0.6 * biterAttributes.scale, 0}},
|
||||
attack_parameters = biterAttack,
|
||||
vision_distance = 30,
|
||||
movement_speed = biterAttributes.movement,
|
||||
distance_per_frame = 0.1,
|
||||
pollution_to_join_attack = 200,
|
||||
distraction_cooldown = 300,
|
||||
dying_explosion = biterAttributes.explosion,
|
||||
dying_sound = make_biter_dying_sounds(1.0),
|
||||
working_sound = make_biter_calls(0.7),
|
||||
run_animation = biterrunanimation(biterAttributes.scale, biterAttributes.tint1, biterAttributes.tint2)
|
||||
}
|
||||
end
|
||||
|
||||
function biterFunctions.createSuicideAttack(attributes)
|
||||
return { type = "projectile",
|
||||
range = 0.5,
|
||||
cooldown = 35,
|
||||
ammo_category = "melee",
|
||||
ammo_type = {
|
||||
category = "biological",
|
||||
action = { type = "direct",
|
||||
action_delivery = { type = "instant",
|
||||
target_effects = {
|
||||
{ type = "create-entity",
|
||||
entity_name = attributes.explosion
|
||||
},
|
||||
{ type = "nested-result",
|
||||
action = { type = "area",
|
||||
perimeter = attributes.area,
|
||||
action_delivery = { type = "instant",
|
||||
target_effects = {
|
||||
{
|
||||
type = "damage",
|
||||
damage = {amount = attributes.damage,
|
||||
type = "explosion"}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
type = "create-entity",
|
||||
entity_name = attributes.scorchmark,
|
||||
check_buildability = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
sound = make_biter_roars(0.5),
|
||||
animation = biterattackanimation(smallbiterscale, small_biter_tint1, small_biter_tint2)
|
||||
}
|
||||
end
|
||||
|
||||
local turret_gun_shift = {
|
||||
|
||||
}
|
||||
|
||||
function biterFunctions.createFireAttack(attributes)
|
||||
return {
|
||||
type = "stream",
|
||||
ammo_category = "flame-thrower",
|
||||
cooldown = 4,
|
||||
range = attributes.range,
|
||||
min_range = attributes.minRange,
|
||||
|
||||
turn_range = attributes.turnRange,
|
||||
fire_penalty = attributes.firePenalty,
|
||||
|
||||
animation = biterattackanimation(attributes.scale,
|
||||
attributes.tint1,
|
||||
attributes.tint2),
|
||||
gun_barrel_length = 2 * attributes.scale,
|
||||
gun_center_shift = {
|
||||
north = {0, -0.65 * attributes.scale},
|
||||
east = {0, 0},
|
||||
south = {0, 0},
|
||||
west = {0, 0}
|
||||
},
|
||||
ammo_type =
|
||||
{
|
||||
category = "flame-thrower",
|
||||
action =
|
||||
{
|
||||
type = "direct",
|
||||
action_delivery =
|
||||
{
|
||||
type = "stream",
|
||||
stream = "flamethrower-fire-stream",
|
||||
duration = 160,
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
cyclic_sound =
|
||||
{
|
||||
begin_sound =
|
||||
{
|
||||
{
|
||||
filename = "__base__/sound/fight/flamethrower-start.ogg",
|
||||
volume = 0.7
|
||||
}
|
||||
},
|
||||
middle_sound =
|
||||
{
|
||||
{
|
||||
filename = "__base__/sound/fight/flamethrower-mid.ogg",
|
||||
volume = 0.7
|
||||
}
|
||||
},
|
||||
end_sound =
|
||||
{
|
||||
{
|
||||
filename = "__base__/sound/fight/flamethrower-end.ogg",
|
||||
volume = 0.7
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
function biterFunctions.makeResistance(name, decrease, percentage)
|
||||
local obj = {
|
||||
type = name,
|
||||
}
|
||||
if (decrease ~= 0) then
|
||||
obj.decrease = decrease
|
||||
end
|
||||
if (percentage ~= 0) then
|
||||
obj.percentage = percentage
|
||||
end
|
||||
return obj
|
||||
end
|
||||
|
||||
return biterFunctions
|
22
prototypes/enemies/fireSpitters.lua
Executable file
22
prototypes/enemies/fireSpitters.lua
Executable file
@ -0,0 +1,22 @@
|
||||
local utils = require("BiterFunctions")
|
||||
|
||||
local createFireAttack = utils.createFireAttack
|
||||
local makeBiter = utils.makeBiter
|
||||
|
||||
data:extend({
|
||||
makeBiter({name = "small-fire-spitter",
|
||||
health = 30,
|
||||
movement = 0.25,
|
||||
healing = 0.01,
|
||||
scale = 0.5,
|
||||
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},
|
||||
explosion = "blood-explosion-small"},
|
||||
createFireAttack({ scale = 0.5,
|
||||
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},
|
||||
range = 20,
|
||||
minRange = 1,
|
||||
turnRange = 1.0/3.0,
|
||||
firePenalty = 15}))
|
||||
})
|
@ -1,86 +1,8 @@
|
||||
function makeBiter(biterAttributes, biterAttack, biterResistances)
|
||||
return {
|
||||
type = "unit",
|
||||
name = biterAttributes.name,
|
||||
icon = "__base__/graphics/icons/small-biter.png",
|
||||
flags = {"placeable-player", "placeable-enemy", "placeable-off-grid", "breaths-air"},
|
||||
max_health = biterAttributes.health,
|
||||
order = "b-b-a",
|
||||
subgroup="enemies",
|
||||
healing_per_tick = biterAttributes.healing,
|
||||
resistances = biterResistances,
|
||||
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},
|
||||
{0.7 * biterAttributes.scale, 0.3 * biterAttributes.scale}},
|
||||
sticker_box = {{-0.6 * biterAttributes.scale, -0.8 * biterAttributes.scale},
|
||||
{0.6 * biterAttributes.scale, 0}},
|
||||
attack_parameters = biterAttack,
|
||||
vision_distance = 30,
|
||||
movement_speed = biterAttributes.movement,
|
||||
distance_per_frame = 0.1,
|
||||
pollution_to_join_attack = 200,
|
||||
distraction_cooldown = 300,
|
||||
dying_explosion = biterAttributes.explosion,
|
||||
dying_sound = make_biter_dying_sounds(1.0),
|
||||
working_sound = make_biter_calls(0.7),
|
||||
run_animation = biterrunanimation(biterAttributes.scale, biterAttributes.tint1, biterAttributes.tint2)
|
||||
}
|
||||
end
|
||||
local util = require("BiterFunctions")
|
||||
|
||||
function createSuicideAttack(attributes)
|
||||
return { type = "projectile",
|
||||
range = 0.5,
|
||||
cooldown = 35,
|
||||
ammo_category = "melee",
|
||||
ammo_type = {
|
||||
category = "biological",
|
||||
action = { type = "direct",
|
||||
action_delivery = { type = "instant",
|
||||
target_effects = {
|
||||
{ type = "create-entity",
|
||||
entity_name = attributes.explosion
|
||||
},
|
||||
{ type = "nested-result",
|
||||
action = { type = "area",
|
||||
perimeter = attributes.area,
|
||||
action_delivery = { type = "instant",
|
||||
target_effects = {
|
||||
{
|
||||
type = "damage",
|
||||
damage = {amount = attributes.damage,
|
||||
type = "explosion"}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
type = "create-entity",
|
||||
entity_name = attributes.scorchmark,
|
||||
check_buildability = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
sound = make_biter_roars(0.5),
|
||||
animation = biterattackanimation(smallbiterscale, small_biter_tint1, small_biter_tint2)
|
||||
}
|
||||
end
|
||||
|
||||
function makeResistance(name, decrease, percentage)
|
||||
local obj = {
|
||||
type = name,
|
||||
}
|
||||
if (decrease ~= 0) then
|
||||
obj.decrease = decrease
|
||||
end
|
||||
if (percentage ~= 0) then
|
||||
obj.percentage = percentage
|
||||
end
|
||||
return obj
|
||||
end
|
||||
local makeBiter = util.makeBiter
|
||||
local createSuicideAttack = util.createSuicideAttack
|
||||
local makeResistance = util.makeResistance
|
||||
|
||||
data:extend({
|
||||
makeBiter({name = "small-suicide-biter",
|
||||
|
12
tests.lua
12
tests.lua
@ -14,7 +14,17 @@ function tests.test1()
|
||||
if (global.regionMap[x] ~= nil) then
|
||||
local chunk = global.regionMap[x][y]
|
||||
if (chunk ~= nil) then
|
||||
print(serpent.dump(chunk))
|
||||
local str = ""
|
||||
for i=1,#chunk do
|
||||
str = str .. " " .. tostring(i) .. "/" .. tostring(chunk[i])
|
||||
end
|
||||
if (chunk.cX == playerChunkX) and (chunk.cY == playerChunkY) then
|
||||
print("*", chunk.cX, chunk.cY, str)
|
||||
else
|
||||
print(chunk.cX, chunk.cY, str)
|
||||
end
|
||||
-- print(str)
|
||||
print("-")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user