z_mirror/Krastorio2

git clone https://git.raiguard.me/z_mirror/Krastorio2

Caleb HeuerBiomass is minable from biter and spitter nestscb2d9fed

santichu95/patch-1
3.2 KiB128 linesraw
1local flib_math = require("__flib__.math")
2
3local biter_virus_evolution_multiplier = 0.67
4
5local virus_iteration_counts = {
6  [1000] = 20,
7  [5000] = 40,
8  [10000] = 80,
9  [20000] = 160,
10  [30000] = 280,
11  [40000] = 300,
12  [50000] = 400,
13  [flib_math.max_int53] = 800,
14}
15
16--- Modifier to change the quantity of objects iterated for each round of the function, based on the total
17--- @param count number
18local function get_removal_count(count)
19  for limit, per in pairs(virus_iteration_counts) do
20    if count <= limit then
21      return per
22    end
23  end
24end
25
26--- @param virus_data BiterVirusData
27local function iterate_biter_virus(virus_data)
28  local surface = virus_data.surface
29  if not surface or not surface.valid then
30    storage.virus.biter[surface.index] = nil
31    return
32  end
33
34  local entities = virus_data.entities
35  local entities_killed = virus_data.entities_killed
36  local entities_to_kill = virus_data.entities_to_kill
37  local force = virus_data.force
38  local len = virus_data.entities_len
39
40  -- Kill some entities
41  for _ = 1, virus_data.amount_per_iteration do
42    if entities_killed >= entities_to_kill then
43      storage.virus.biter[surface.index] = nil
44      break
45    end
46
47    local i = math.random(1, len)
48    local entity = entities[i]
49    if entity and entity.valid then
50      entity.die(force)
51
52      -- Move the element at the end to the gap
53      -- This removes the element at `i` while achieving O(1) performance
54      entities[i] = entities[len]
55      entities[len] = nil
56
57      entities_killed = entities_killed + 1
58      len = len - 1
59    end
60  end
61
62  virus_data.entities_killed = entities_killed
63  virus_data.tiles_len = len
64end
65
66--- @param player LuaPlayer
67--- @param surface LuaSurface
68local function init_biter_virus(player, surface)
69  local biter_viruses = storage.virus.biter
70  if not biter_viruses[surface.index] then
71    -- Reduce evolution factor
72    local enemy = game.forces.enemy
73    enemy.evolution_factor = enemy.evolution_factor * biter_virus_evolution_multiplier
74
75    -- Begin gradual enemy killoff
76    local enemy_entities = surface.find_entities_filtered({ force = "enemy" })
77    local len = #enemy_entities
78    if len > 0 then
79      --- @class BiterVirusData
80      biter_viruses[surface.index] = {
81        amount_per_iteration = math.ceil(len / get_removal_count(len)),
82        entities = enemy_entities,
83        entities_killed = 0,
84        entities_len = len,
85        entities_to_kill = len / 2.5,
86        force = player.force,
87        surface = surface,
88      }
89    end
90  end
91end
92
93--- @param e EventData.on_player_used_capsule
94local function on_player_used_capsule(e)
95  local item = e.item
96  if not item or not item.valid then
97    return
98  end
99
100  local player = game.get_player(e.player_index) --[[@as LuaPlayer]]
101  local surface = player.surface
102
103  if item.name == "kr-biter-virus" then
104    init_biter_virus(player, surface)
105  end
106end
107
108local function on_tick()
109  for _, biter_virus in pairs(storage.virus.biter) do
110    iterate_biter_virus(biter_virus)
111  end
112end
113
114local virus = {}
115
116function virus.on_init()
117  storage.virus = {
118    --- @type table<uint, BiterVirusData>
119    biter = {},
120  }
121end
122
123virus.events = {
124  [defines.events.on_player_used_capsule] = on_player_used_capsule,
125  [defines.events.on_tick] = on_tick,
126}
127
128return virus