Muppet9010

Biter Attack V3 test

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