Muppet9010

Biter Attack Test V2

Oct 11th, 2018
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.49 KB | None | 0 0
  1. /c
  2. Settings = function()
  3. --[[
  4. 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 Rampent?
  5. 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.
  6. If you want more than 10 groups at a time call the command after each wave has cleared the spawn area.
  7. ]]
  8. _biterCount = 1000
  9. _biterMaxGroupSize = 100
  10. _biterSpawnTilesLeftOfPlayer = 150
  11. _biterWaveGroupsWide = 5
  12. end
  13.  
  14. --[[
  15. Notes:
  16. - 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.
  17. ]]
  18.  
  19.  
  20. BiterGroups = {}
  21. _monitorBiterGroupsCheckTickDelay = 120
  22. _currentEvolutionProbabilities = {}
  23. _currentEvolutionProbabilitiesTop = {}
  24.  
  25. TriggerBiterGroup = function()
  26. _surface = game.player.surface
  27. _maxBiterGroups = math.ceil(_biterCount / _biterMaxGroupSize)
  28. if _maxBiterGroups < _biterWaveGroupsWide then
  29. _biterWaveGroupsWide = _maxBiterGroups
  30. end
  31. _biterGroupSize = math.ceil(_biterCount / _maxBiterGroups)
  32. _biterGroupTileWidth = 20
  33. _biterGroupTileLength = math.sqrt(_biterMaxGroupSize)
  34. local groupStartPos = FindBiterGatherPoint()
  35. if _maxBiterGroups > 20 then
  36. game.print("too many attack groups will lag the game - stopped")
  37. return
  38. end
  39.  
  40. local waveWidthCount = 0
  41. local waveDepthCount = 0
  42. local triggerTick = game.tick + _monitorBiterGroupsCheckTickDelay
  43. CalculateBiterSelectionProbabilities()
  44. for i=1, _maxBiterGroups do
  45. local thisGroupStartPos = {
  46. x = groupStartPos.x - (waveDepthCount * 6 * _biterGroupTileLength),
  47. y = groupStartPos.y + (waveWidthCount * _biterGroupTileWidth)
  48. }
  49.  
  50. local biterGroup = CreateBiterGroup(thisGroupStartPos)
  51. local groupMembers = SpawnBitersInGroup(biterGroup, thisGroupStartPos, _biterGroupSize)
  52. local finalAttackAreaTarget = FindAttackAreaTarget(waveWidthCount)
  53. BiterGroupAttackMoveArea(biterGroup, FindMoveTarget(waveWidthCount, waveDepthCount), finalAttackAreaTarget)
  54. table.insert(BiterGroups, {triggerTick = triggerTick, group = biterGroup, startPos = thisGroupStartPos, members = groupMembers})
  55.  
  56. waveWidthCount = waveWidthCount + 1
  57. if waveWidthCount == _biterWaveGroupsWide then
  58. waveWidthCount = 0
  59. waveDepthCount = waveDepthCount + 1
  60. end
  61. end
  62. script.on_nth_tick(triggerTick, function() MonitorBiterGroups() end)
  63. end
  64.  
  65. FindBiterGatherPoint = function()
  66. return {
  67. x = game.player.position.x - _biterSpawnTilesLeftOfPlayer,
  68. y = game.player.position.y - ((_biterWaveGroupsWide * _biterGroupTileWidth) / 2)
  69. }
  70. end
  71.  
  72. FindMoveTarget = function(groupWidthCount, groupDepthCount)
  73. return {
  74. x = game.player.position.x + (groupDepthCount),
  75. y = game.player.position.y - ((_biterWaveGroupsWide * _biterGroupTileWidth) / 2) + (groupWidthCount * _biterGroupTileWidth)
  76. }
  77. end
  78.  
  79. FindAttackAreaTarget = function(groupCount)
  80. return {
  81. x = game.player.position.x + groupCount,
  82. y = game.player.position.y
  83. }
  84. end
  85.  
  86. CreateBiterGroup = function(groupPosition)
  87. return _surface.create_unit_group{position = groupPosition, force = game.forces["enemy"]}
  88. end
  89.  
  90. SpawnBitersInGroup = function(unitGroup, spawnCenterPos, groupSize)
  91. local members = {}
  92. for i=1, groupSize do
  93. local biterType = GetBiterType()
  94. local spawnPos = _surface.find_non_colliding_position(biterType, spawnCenterPos, 0, 1)
  95. local biter = _surface.create_entity{
  96. name = biterType,
  97. position = spawnPos,
  98. force = game.forces["enemy"]
  99. }
  100. if not biter then
  101. game.print("creation of biter" .. i .. "failed")
  102. else
  103. unitGroup.add_member(biter)
  104. table.insert(members, biter)
  105. end
  106. end
  107. return members
  108. end
  109.  
  110. CalculateBiterSelectionProbabilities = function()
  111. _currentEvolutionProbabilities = {}
  112. _currentEvolutionProbabilitiesTop = {}
  113. CalculateSpecificBiterSelectionProbabilities("biter-spawner")
  114. CalculateSpecificBiterSelectionProbabilities("spitter-spawner")
  115. end
  116.  
  117. CalculateSpecificBiterSelectionProbabilities = function(spawnerType)
  118. local debug = false
  119. if debug then game.print(spawnerType) end
  120. local rawUnitProbs = game.entity_prototypes[spawnerType].result_units
  121.  
  122. _currentEvolutionProbabilitiesTop[spawnerType] = 0
  123. _currentEvolutionProbabilities[spawnerType] = {}
  124. local currentEvolution = game.forces.enemy.evolution_factor
  125. for unitIndex, possibility in pairs(rawUnitProbs) do
  126. local startSpawnPointIndex = nil
  127. for spawnPointIndex, spawnPoint in pairs(possibility.spawn_points) do
  128. if spawnPoint.evolution_factor <= currentEvolution then
  129. startSpawnPointIndex = spawnPointIndex
  130. end
  131. end
  132. if startSpawnPointIndex ~= nil then
  133. local startSpawnPoint = possibility.spawn_points[startSpawnPointIndex]
  134. local endSpawnPoint = nil
  135. if possibility.spawn_points[startSpawnPointIndex + 1] ~= nil then
  136. endSpawnPoint = possibility.spawn_points[startSpawnPointIndex + 1]
  137. else
  138. endSpawnPoint = {evolution_factor = 1.0, weight = startSpawnPoint.weight}
  139. end
  140.  
  141. local weight = nil
  142. if startSpawnPoint.evolution_factor ~= endSpawnPoint.evolution_factor then
  143. local evoRange = endSpawnPoint.evolution_factor - startSpawnPoint.evolution_factor
  144. local weightRange = endSpawnPoint.weight - startSpawnPoint.weight
  145. local evoRangeMultiplier = (currentEvolution - startSpawnPoint.evolution_factor) / evoRange
  146. weight = (weightRange * evoRangeMultiplier) + startSpawnPoint.weight
  147. else
  148. weight = startSpawnPoint.weight
  149. end
  150. local probability = _currentEvolutionProbabilitiesTop[spawnerType] + weight
  151. if debug then game.print(possibility.unit .. ": " .. weight .. "(" .. probability .. ")") end
  152. _currentEvolutionProbabilities[spawnerType][probability] = possibility.unit
  153. _currentEvolutionProbabilitiesTop[spawnerType] = probability
  154. end
  155. end
  156. end
  157.  
  158. GetBiterType = function()
  159. local debug = false
  160. local spawnerType = "biter-spawner"
  161. if math.random(0,1) == 1 then spawnerType = "spitter-spawner" end
  162. if debug then game.print(spawnerType) end
  163.  
  164. local randNum = nil
  165. while(true) do
  166. randNum = math.random()
  167. if randNum <= _currentEvolutionProbabilitiesTop[spawnerType] then break end
  168. end
  169. if debug then game.print("randNum: " .. randNum) end
  170.  
  171. for topChance, unit in pairs(_currentEvolutionProbabilities[spawnerType]) do
  172. if debug then game.print("check " .. unit) end
  173. if topChance > 0 and topChance >= randNum then
  174. return unit
  175. end
  176. end
  177. end
  178.  
  179. GetBiterGroupAttackAreaCommand = function(targetPos)
  180. return {
  181. type = defines.command.attack_area,
  182. destination = targetPos,
  183. radius = 10,
  184. distraction = defines.distraction.by_anything
  185. }
  186. end
  187.  
  188. GetBiterGroupMoveCommand = function(moveToPos)
  189. return {
  190. type = defines.command.go_to_location,
  191. destination = moveToPos,
  192. distraction = defines.distraction.by_anything
  193. }
  194. end
  195.  
  196. GetBiterGroupAttackSpawnCommand = function()
  197. return {
  198. type = defines.command.attack_area,
  199. destination = {x = 0, y = 0},
  200. radius = 100,
  201. distraction = defines.distraction.by_anything
  202. }
  203. end
  204.  
  205. BiterGroupAttackMoveArea = function(unitGroup, moveToPos, targetPos)
  206. local command = {
  207. type = defines.command.compound,
  208. structure_type = defines.compound_command.return_last,
  209. commands = {
  210. GetBiterGroupMoveCommand(moveToPos),
  211. GetBiterGroupAttackAreaCommand(targetPos),
  212. GetBiterGroupAttackSpawnCommand()
  213. }
  214. }
  215. unitGroup.set_command(command)
  216. unitGroup.start_moving()
  217. end
  218.  
  219. MonitorBiterGroups = function()
  220. script.on_nth_tick(game.tick, nil)
  221. for i, groupDetails in ipairs(BiterGroups) do
  222. if groupDetails.triggerTick <= game.tick then
  223. if not groupDetails.group.valid or groupDetails.group.state ~= defines.group_state.moving then
  224. RecreateGroupAndAttackSpawn(groupDetails)
  225. end
  226. BiterGroups[i] = nil
  227. end
  228. end
  229. end
  230.  
  231. RecreateGroupAndAttackSpawn = function(groupDetails)
  232. local groupSize = #groupDetails.members
  233. local groupStartingPos = groupDetails.startPos
  234. if groupDetails.group.valid then
  235. groupDetails.group.destroy()
  236. end
  237. for _, member in pairs(groupDetails.members) do
  238. member.destroy()
  239. end
  240.  
  241. local biterGroup = CreateBiterGroup(groupStartingPos)
  242. SpawnBitersInGroup(biterGroup, groupStartingPos, groupSize)
  243. biterGroup.set_command(GetBiterGroupAttackSpawnCommand())
  244. biterGroup.start_moving()
  245. end
  246.  
  247.  
  248.  
  249. Settings()
  250. TriggerBiterGroup()
Add Comment
Please, Sign In to add comment