Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /c
- Settings = function()
- --[[
- Advised to use max group size of 200 or less to avoid them getting in each others way too much. when biter group is attacked each biter targets a random targets, so they get in each others way breaking pack formation. could reduce collision box size to 40% like Rampant?
- More than 10 groups total in a wave will tend to loose formation and partially form in to a mass single group column, rather than hold the shape. built in AI UPS protection.
- If you want more than 10 groups at a time call the command after each wave has cleared the spawn area.
- ]]
- _biterCount = 2000
- _biterMaxGroupSize = 200
- _biterSpawnTilesLeftOfPlayer = 150
- _biterWaveGroupsWide = 5
- _usingRampantAI = false
- end
- --[[
- Notes:
- - Should a UnitGroup not be able to start moving towards its move position after 2 seconds the units and group are replaced and targeted at spawn as fallback. All units will attack spawn after their given target.
- ]]
- BiterGroups = {}
- _monitorBiterGroupsCheckTickDelay = 120
- _currentEvolutionProbabilities = {}
- _currentEvolutionProbabilitiesTop = {}
- TriggerBiterGroup = function()
- _surface = game.player.surface
- _maxBiterGroups = math.ceil(_biterCount / _biterMaxGroupSize)
- if _maxBiterGroups < _biterWaveGroupsWide then
- _biterWaveGroupsWide = _maxBiterGroups
- end
- _biterGroupSize = math.ceil(_biterCount / _maxBiterGroups)
- _biterGroupTileWidth = 20
- _biterGroupTileLength = math.sqrt(_biterMaxGroupSize)
- local groupStartPos = FindBiterGatherPoint()
- if _maxBiterGroups > 20 then
- game.print("too many attack groups will lag the game - stopped")
- return
- end
- local waveWidthCount = 0
- local waveDepthCount = 0
- local triggerTick = game.tick + _monitorBiterGroupsCheckTickDelay
- CalculateBiterSelectionProbabilities()
- for i=1, _maxBiterGroups do
- local thisGroupStartPos = {
- x = groupStartPos.x - (waveDepthCount * 6 * _biterGroupTileLength),
- y = groupStartPos.y + (waveWidthCount * _biterGroupTileWidth)
- }
- local biterGroup = CreateBiterGroup(thisGroupStartPos)
- local groupMembers = SpawnBitersInGroup(biterGroup, thisGroupStartPos, _biterGroupSize)
- if _usingRampantAI then
- remote.call("rampant", "registerUnitGroup", biterGroup)
- else
- local finalAttackAreaTarget = FindAttackAreaTarget(waveWidthCount)
- BiterGroupAttackMoveArea(biterGroup, FindMoveTarget(waveWidthCount, waveDepthCount), finalAttackAreaTarget)
- table.insert(BiterGroups, {triggerTick = triggerTick, group = biterGroup, startPos = thisGroupStartPos, members = groupMembers})
- end
- waveWidthCount = waveWidthCount + 1
- if waveWidthCount == _biterWaveGroupsWide then
- waveWidthCount = 0
- waveDepthCount = waveDepthCount + 1
- end
- end
- if not _usingRampantAI then
- script.on_nth_tick(triggerTick, function() MonitorBiterGroups() end)
- end
- end
- FindBiterGatherPoint = function()
- return {
- x = game.player.position.x - _biterSpawnTilesLeftOfPlayer,
- y = game.player.position.y - ((_biterWaveGroupsWide * _biterGroupTileWidth) / 2)
- }
- end
- FindMoveTarget = function(groupWidthCount, groupDepthCount)
- return {
- x = game.player.position.x + (groupDepthCount),
- y = game.player.position.y - ((_biterWaveGroupsWide * _biterGroupTileWidth) / 2) + (groupWidthCount * _biterGroupTileWidth)
- }
- end
- FindAttackAreaTarget = function(groupCount)
- return {
- x = game.player.position.x + groupCount,
- y = game.player.position.y
- }
- end
- CreateBiterGroup = function(groupPosition)
- return _surface.create_unit_group{position = groupPosition, force = game.forces["enemy"]}
- end
- SpawnBitersInGroup = function(unitGroup, spawnCenterPos, groupSize)
- local members = {}
- for i=1, groupSize do
- local biterType = GetBiterType()
- local spawnPos = _surface.find_non_colliding_position(biterType, spawnCenterPos, 0, 1)
- local biter = _surface.create_entity{
- name = biterType,
- position = spawnPos,
- force = game.forces["enemy"]
- }
- if not biter then
- game.print("creation of biter" .. i .. "failed")
- else
- unitGroup.add_member(biter)
- table.insert(members, biter)
- end
- end
- return members
- end
- CalculateBiterSelectionProbabilities = function()
- _currentEvolutionProbabilities = {}
- _currentEvolutionProbabilitiesTop = {}
- CalculateSpecificBiterSelectionProbabilities("biter-spawner")
- CalculateSpecificBiterSelectionProbabilities("spitter-spawner")
- end
- CalculateSpecificBiterSelectionProbabilities = function(spawnerType)
- local debug = false
- if debug then game.print(spawnerType) end
- local rawUnitProbs = game.entity_prototypes[spawnerType].result_units
- _currentEvolutionProbabilitiesTop[spawnerType] = 0
- _currentEvolutionProbabilities[spawnerType] = {}
- local currentEvolution = game.forces.enemy.evolution_factor
- for unitIndex, possibility in pairs(rawUnitProbs) do
- local startSpawnPointIndex = nil
- for spawnPointIndex, spawnPoint in pairs(possibility.spawn_points) do
- if spawnPoint.evolution_factor <= currentEvolution then
- startSpawnPointIndex = spawnPointIndex
- end
- end
- if startSpawnPointIndex ~= nil then
- local startSpawnPoint = possibility.spawn_points[startSpawnPointIndex]
- local endSpawnPoint = nil
- if possibility.spawn_points[startSpawnPointIndex + 1] ~= nil then
- endSpawnPoint = possibility.spawn_points[startSpawnPointIndex + 1]
- else
- endSpawnPoint = {evolution_factor = 1.0, weight = startSpawnPoint.weight}
- end
- local weight = nil
- if startSpawnPoint.evolution_factor ~= endSpawnPoint.evolution_factor then
- local evoRange = endSpawnPoint.evolution_factor - startSpawnPoint.evolution_factor
- local weightRange = endSpawnPoint.weight - startSpawnPoint.weight
- local evoRangeMultiplier = (currentEvolution - startSpawnPoint.evolution_factor) / evoRange
- weight = (weightRange * evoRangeMultiplier) + startSpawnPoint.weight
- else
- weight = startSpawnPoint.weight
- end
- local probability = _currentEvolutionProbabilitiesTop[spawnerType] + weight
- if debug then game.print(possibility.unit .. ": " .. weight .. "(" .. probability .. ")") end
- _currentEvolutionProbabilities[spawnerType][probability] = possibility.unit
- _currentEvolutionProbabilitiesTop[spawnerType] = probability
- end
- end
- end
- GetBiterType = function()
- local debug = false
- local spawnerType = "biter-spawner"
- if math.random(0,1) == 1 then spawnerType = "spitter-spawner" end
- if debug then game.print(spawnerType) end
- local randNum = nil
- while(true) do
- randNum = math.random()
- if randNum <= _currentEvolutionProbabilitiesTop[spawnerType] then break end
- end
- if debug then game.print("randNum: " .. randNum) end
- for topChance, unit in pairs(_currentEvolutionProbabilities[spawnerType]) do
- if debug then game.print("check " .. unit) end
- if topChance > 0 and topChance >= randNum then
- return unit
- end
- end
- end
- GetBiterGroupAttackAreaCommand = function(targetPos)
- return {
- type = defines.command.attack_area,
- destination = targetPos,
- radius = 10,
- distraction = defines.distraction.by_anything
- }
- end
- GetBiterGroupMoveCommand = function(moveToPos)
- return {
- type = defines.command.go_to_location,
- destination = moveToPos,
- distraction = defines.distraction.by_anything
- }
- end
- GetBiterGroupAttackSpawnCommand = function()
- return {
- type = defines.command.attack_area,
- destination = {x = 0, y = 0},
- radius = 100,
- distraction = defines.distraction.by_anything
- }
- end
- BiterGroupAttackMoveArea = function(unitGroup, moveToPos, targetPos)
- local command = {
- type = defines.command.compound,
- structure_type = defines.compound_command.return_last,
- commands = {
- GetBiterGroupMoveCommand(moveToPos),
- GetBiterGroupAttackAreaCommand(targetPos),
- GetBiterGroupAttackSpawnCommand()
- }
- }
- unitGroup.set_command(command)
- unitGroup.start_moving()
- end
- MonitorBiterGroups = function()
- script.on_nth_tick(game.tick, nil)
- for i, groupDetails in ipairs(BiterGroups) do
- if groupDetails.triggerTick <= game.tick then
- if not groupDetails.group.valid or groupDetails.group.state ~= defines.group_state.moving then
- RecreateGroupAndAttackSpawn(groupDetails)
- end
- BiterGroups[i] = nil
- end
- end
- end
- RecreateGroupAndAttackSpawn = function(groupDetails)
- local groupSize = #groupDetails.members
- local groupStartingPos = groupDetails.startPos
- if groupDetails.group.valid then
- groupDetails.group.destroy()
- end
- for _, member in pairs(groupDetails.members) do
- member.destroy()
- end
- local biterGroup = CreateBiterGroup(groupStartingPos)
- SpawnBitersInGroup(biterGroup, groupStartingPos, groupSize)
- biterGroup.set_command(GetBiterGroupAttackSpawnCommand())
- biterGroup.start_moving()
- end
- Settings()
- TriggerBiterGroup()
Add Comment
Please, Sign In to add comment