z_mirror/Krastorio2

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

Caleb HeuerFix inventory radioactivity checks not running when dying or respawning1182a831

real-fusion-reactor
7.3 KiB279 linesraw
1local flib_position = require("__flib__.position")
2
3--- @class RadioactivityPlayerData
4--- @field entity boolean
5--- @field damaged boolean
6--- @field inventory boolean
7--- @field last_position MapPosition
8
9local default_entities = { "uranium-ore" }
10local default_items = {
11  "nuclear-fuel",
12  "uranium-235",
13  "uranium-238",
14  "uranium-fuel-cell",
15  "uranium-ore",
16  "depleted-uranium-fuel-cell",
17}
18local range = 7
19
20--- @param player LuaPlayer
21local function check_inventory(player)
22  if not storage.radioactivity.enabled or not next(storage.radioactivity.entities) then
23    return
24  end
25
26  local player_data = storage.radioactivity.players[player.index]
27  if not player_data then
28    return
29  end
30
31  if not player.character or not player.character.valid then
32    player_data.inventory = false
33    return
34  end
35
36  for _, item_name in pairs(storage.radioactivity.items) do
37    -- FIXME: This does not check trash inventory
38    if player.get_item_count(item_name) > 0 then
39      player_data.inventory = true
40      return
41    end
42  end
43
44  player_data.inventory = false
45end
46
47--- @param player LuaPlayer
48local function check_around_player(player)
49  if not storage.radioactivity.enabled or not next(storage.radioactivity.items) then
50    return
51  end
52
53  local player_data = storage.radioactivity.players[player.index]
54  if not player_data then
55    return
56  end
57
58  if not player.character or not player.character.valid then
59    player_data.entity = false
60    return
61  end
62
63  local position = flib_position.floor(player.physical_position)
64  local last_position = player_data.last_position
65  if flib_position.eq(position, last_position) then
66    return
67  end
68  player_data.last_position = position
69
70  player_data.entity = player.surface.count_entities_filtered({
71    name = storage.radioactivity.entities,
72    radius = range,
73    position = position,
74  }) > 0
75end
76
77--- @param player LuaPlayer
78local function add_player(player)
79  storage.radioactivity.players[player.index] = {
80    entity = false,
81    damaged = 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      { "gui-alert-tooltip.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_data.damaged = player.character.damage(base_damage, "enemy", "kr-radioactive") > 0
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    if not player_data.damaged then
134      goto continue
135    end
136
137    local player = game.get_player(player_index)
138    if not player or not player.connected then
139      goto continue
140    end
141
142    player.play_sound({
143      path = "kr-radioactive",
144      position = player.physical_position,
145      volume_modifier = 0.5,
146    })
147
148    ::continue::
149  end
150end
151
152--- @param e EventData.on_player_changed_position|EventData.on_player_changed_surface
153local function on_player_moved(e)
154  local player = game.get_player(e.player_index)
155  if player then
156    check_around_player(player)
157  end
158end
159
160--- @param e EventData.on_player_main_inventory_changed|EventData.on_player_trash_inventory_changed
161local function on_player_inventory_changed(e)
162  local player = game.get_player(e.player_index)
163  if player then
164    check_inventory(player)
165  end
166end
167
168--- @param e EventData.on_player_died|EventData.on_player_respawned
169local function on_player_alive_state_changed(e)
170  local player = game.get_player(e.player_index)
171  if player then
172    check_around_player(player)
173    check_inventory(player)
174  end
175end
176
177--- @param e EventData.on_player_created
178local function on_player_created(e)
179  local player = game.get_player(e.player_index)
180  if not player then
181    return
182  end
183
184  add_player(player)
185end
186
187--- @param e EventData.on_player_removed
188local function on_player_removed(e)
189  remove_player(e.player_index)
190end
191
192--- @param e EventData.on_runtime_mod_setting_changed
193local function on_runtime_mod_setting_changed(e)
194  if e.setting ~= "kr-enable-radioactivity" or not storage.radioactivity then
195    return
196  end
197
198  storage.radioactivity.enabled = settings.global["kr-enable-radioactivity"].value --[[@as boolean]]
199end
200
201local radioactivity = {}
202
203function radioactivity.on_init()
204  storage.radioactivity = {
205    enabled = settings.global["kr-enable-radioactivity"].value --[[@as boolean]],
206    --- @type table<uint, RadioactivityPlayerData>
207    players = {},
208  }
209  radioactivity.on_configuration_changed()
210end
211
212function radioactivity.on_configuration_changed()
213  storage.radioactivity.entities = {}
214  for _, entity_name in pairs(default_entities) do
215    if prototypes.entity[entity_name] then
216      table.insert(storage.radioactivity.entities, entity_name)
217    end
218  end
219  storage.radioactivity.items = {}
220  for _, item_name in pairs(default_items) do
221    if prototypes.item[item_name] then
222      table.insert(storage.radioactivity.items, item_name)
223    end
224  end
225end
226
227remote.add_interface("kr-radioactivity", {
228  --- @param name string
229  add_entity = function(name)
230    if not storage.radioactivity then
231      return
232    end
233    if not name or type(name) ~= "string" then
234      error("`name` must be a string.")
235    end
236
237    if not prototypes.entity[name] then
238      error("Entity `" .. name .. "` does not exist.")
239    end
240
241    table.insert(storage.radioactivity.entities, name)
242  end,
243  --- @param name string
244  add_item = function(name)
245    if not storage.radioactivity then
246      return
247    end
248    if not name or type(name) ~= "string" then
249      error("`name` must be a string.")
250    end
251
252    if not prototypes.item[name] then
253      error("Item `" .. name .. "` does not exist.")
254    end
255
256    table.insert(storage.radioactivity.items, name)
257  end,
258})
259
260radioactivity.events = {
261  [defines.events.on_player_changed_position] = on_player_moved,
262  [defines.events.on_player_changed_surface] = on_player_moved,
263  [defines.events.on_player_created] = on_player_created,
264  [defines.events.on_player_cursor_stack_changed] = on_player_inventory_changed,
265  [defines.events.on_player_died] = on_player_alive_state_changed,
266  [defines.events.on_player_main_inventory_changed] = on_player_inventory_changed,
267  [defines.events.on_player_removed] = on_player_removed,
268  [defines.events.on_player_respawned] = on_player_alive_state_changed,
269  [defines.events.on_player_toggled_map_editor] = on_player_moved,
270  [defines.events.on_player_trash_inventory_changed] = on_player_inventory_changed,
271  [defines.events.on_runtime_mod_setting_changed] = on_runtime_mod_setting_changed,
272  [defines.events.on_tick] = update_sounds,
273}
274
275radioactivity.on_nth_tick = {
276  [20] = update_and_damage,
277}
278
279return radioactivity