z_mirror/Krastorio2

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

Caleb HeuerFix geiger counter earrape26acaf0d

santichu95/patch-1
7.0 KiB276 linesraw
1local flib_position = require("__flib__.position")
2
3local util = require("scripts.util")
4
5--- @class RadioactivityPlayerData
6--- @field entity boolean
7--- @field inventory boolean
8--- @field last_position MapPosition
9
10local default_entities = { "uranium-ore" }
11local default_items = {
12  "nuclear-fuel",
13  "uranium-235",
14  "uranium-238",
15  "uranium-fuel-cell",
16  "uranium-ore",
17  "depleted-uranium-fuel-cell",
18}
19local range = 7
20
21--- @param player LuaPlayer
22local function check_inventory(player)
23  if not storage.radioactivity.enabled or not next(storage.radioactivity.entities) then
24    return
25  end
26
27  local player_data = storage.radioactivity.players[player.index]
28  if not player_data then
29    return
30  end
31
32  if not player.character or not player.character.valid then
33    player_data.inventory = false
34    return
35  end
36
37  for _, item_name in pairs(storage.radioactivity.items) do
38    -- FIXME: This does not check trash inventory
39    if player.get_item_count(item_name) > 0 then
40      player_data.inventory = true
41      return
42    end
43  end
44
45  player_data.inventory = false
46end
47
48--- @param player LuaPlayer
49local function check_around_player(player)
50  if not storage.radioactivity.enabled or not next(storage.radioactivity.items) then
51    return
52  end
53
54  local player_data = storage.radioactivity.players[player.index]
55  if not player_data then
56    return
57  end
58
59  if not player.character or not player.character.valid then
60    player_data.entity = false
61    return
62  end
63
64  local position = flib_position.floor(player.physical_position)
65  local last_position = player_data.last_position
66  if flib_position.eq(position, last_position) then
67    return
68  end
69  player_data.last_position = position
70
71  player_data.entity = player.surface.count_entities_filtered({
72    name = storage.radioactivity.entities,
73    radius = range,
74    position = position,
75  }) > 0
76end
77
78--- @param player LuaPlayer
79local function add_player(player)
80  storage.radioactivity.players[player.index] = {
81    entity = false,
82    inventory = false,
83    last_position = { x = 0, y = 0 },
84  }
85end
86
87--- @param player_index uint
88local function remove_player(player_index)
89  storage.radioactivity.players[player_index] = nil
90end
91
92local function update_and_damage()
93  if not storage.radioactivity.enabled then
94    return
95  end
96
97  for player_index, player_data in pairs(storage.radioactivity.players) do
98    if not player_data.entity and not player_data.inventory then
99      goto continue
100    end
101
102    local player = game.get_player(player_index)
103    if not player or not player.connected or not player.character then
104      goto continue
105    end
106
107    player.add_custom_alert(
108      player.character,
109      { type = "virtual", name = "kr-nuclear-2" },
110      { "other.kr-taking-radioactive-damage" },
111      false
112    )
113
114    -- Damage the player
115    -- TODO: Account for armor and energy shields
116    local base_damage = 7.25
117    player.character.damage(base_damage, "enemy", "radioactive")
118
119    ::continue::
120  end
121end
122
123local function update_sounds()
124  if not storage.radioactivity.enabled then
125    return
126  end
127
128  for player_index, player_data in pairs(storage.radioactivity.players) do
129    if not player_data.entity and not player_data.inventory then
130      goto continue
131    end
132
133    local player = game.get_player(player_index)
134    if not player or not player.connected then
135      goto continue
136    end
137
138    player.play_sound({
139      path = "kr-radioactive",
140      position = player.physical_position,
141      volume_modifier = 0.5,
142    })
143
144    ::continue::
145  end
146end
147
148--- @param e EventData.on_player_changed_position|EventData.on_player_changed_surface
149local function on_player_moved(e)
150  local player = game.get_player(e.player_index)
151  if player then
152    check_around_player(player)
153  end
154end
155
156--- @param e EventData.on_player_main_inventory_changed|EventData.on_player_trash_inventory_changed
157local function on_player_inventory_changed(e)
158  local player = game.get_player(e.player_index)
159  if player then
160    check_inventory(player)
161  end
162end
163
164--- @param e EventData.on_player_created
165local function on_player_created(e)
166  local player = game.get_player(e.player_index)
167  if not player then
168    return
169  end
170
171  add_player(player)
172end
173
174--- @param e EventData.on_player_removed
175local function on_player_removed(e)
176  remove_player(e.player_index)
177end
178
179local radioactivity = {}
180
181function radioactivity.on_init()
182  storage.radioactivity = {
183    enabled = true,
184    --- @type table<uint, RadioactivityPlayerData>
185    players = {},
186  }
187  radioactivity.on_configuration_changed()
188end
189
190function radioactivity.on_configuration_changed()
191  -- TODO: Migration
192  storage.radioactivity.entities = {}
193  for _, entity_name in pairs(default_entities) do
194    if prototypes.entity[entity_name] then
195      table.insert(storage.radioactivity.entities, entity_name)
196    end
197  end
198  storage.radioactivity.items = {}
199  for _, item_name in pairs(default_items) do
200    if prototypes.item[item_name] then
201      table.insert(storage.radioactivity.items, item_name)
202    end
203  end
204end
205
206remote.add_interface("kr-radioactivity", {
207  add_entity = function(name)
208    if not storage.radioactivity then
209      return
210    end
211    if not name or type(name) ~= "string" then
212      error("`name` must be a string.")
213    end
214
215    if not prototypes.entity[name] then
216      error("Entity `" .. name .. "` does not exist.")
217    end
218
219    table.insert(storage.radioactivity.entities, name)
220  end,
221  add_item = function(name)
222    if not storage.radioactivity then
223      return
224    end
225    if not name or type(name) ~= "string" then
226      error("`name` must be a string.")
227    end
228
229    if not prototypes.item[name] then
230      error("Item `" .. name .. "` does not exist.")
231    end
232
233    table.insert(storage.radioactivity.items, name)
234  end,
235  set_enabled = function(to_state)
236    if not storage.radioactivity then
237      return
238    end
239    if to_state == nil or type(to_state) ~= "boolean" then
240      error("`to_state` must be a boolean.")
241    end
242
243    storage.radioactivity.enabled = to_state
244  end,
245})
246
247util.add_commands({
248  ["kr-disable-radioactivity"] = function()
249    storage.radioactivity.enabled = false
250    game.print({ "message.kr-radioactivity-disabled" })
251  end,
252  ["kr-enable-radioactivity"] = function()
253    storage.radioactivity.enabled = true
254    game.print({ "message.kr-radioactivity-enabled" })
255  end,
256})
257
258radioactivity.events = {
259  [defines.events.on_player_changed_position] = on_player_moved,
260  [defines.events.on_player_changed_surface] = on_player_moved,
261  [defines.events.on_player_created] = on_player_created,
262  [defines.events.on_player_cursor_stack_changed] = on_player_inventory_changed,
263  [defines.events.on_player_died] = on_player_moved,
264  [defines.events.on_player_main_inventory_changed] = on_player_inventory_changed,
265  [defines.events.on_player_removed] = on_player_removed,
266  [defines.events.on_player_respawned] = on_player_moved,
267  [defines.events.on_player_toggled_map_editor] = on_player_moved,
268  [defines.events.on_player_trash_inventory_changed] = on_player_inventory_changed,
269  [defines.events.on_tick] = update_sounds,
270}
271
272radioactivity.on_nth_tick = {
273  [20] = update_and_damage,
274}
275
276return radioactivity