z_mirror/Krastorio2

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

Caleb HeuerRemove outdated storage tables20f5f8fb

discrete-steel-pipes
7.0 KiB269 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    inventory = false,
82    last_position = { x = 0, y = 0 },
83  }
84end
85
86--- @param player_index uint
87local function remove_player(player_index)
88  storage.radioactivity.players[player_index] = nil
89end
90
91local function update_and_damage()
92  if not storage.radioactivity.enabled then
93    return
94  end
95
96  for player_index, player_data in pairs(storage.radioactivity.players) do
97    if not player_data.entity and not player_data.inventory then
98      goto continue
99    end
100
101    local player = game.get_player(player_index)
102    if not player or not player.connected or not player.character then
103      goto continue
104    end
105
106    player.add_custom_alert(
107      player.character,
108      { type = "virtual", name = "kr-nuclear-2" },
109      { "other.kr-taking-radioactive-damage" },
110      false
111    )
112
113    -- Damage the player
114    -- TODO: Account for armor and energy shields
115    local base_damage = 7.25
116    player_data.damaged = player.character.damage(base_damage, "enemy", "kr-radioactive") > 0
117
118    ::continue::
119  end
120end
121
122local function update_sounds()
123  if not storage.radioactivity.enabled then
124    return
125  end
126
127  for player_index, player_data in pairs(storage.radioactivity.players) do
128    if not player_data.entity and not player_data.inventory then
129      goto continue
130    end
131
132    if not player_data.damaged then
133      goto continue
134    end
135
136    local player = game.get_player(player_index)
137    if not player or not player.connected then
138      goto continue
139    end
140
141    player.play_sound({
142      path = "kr-radioactive",
143      position = player.physical_position,
144      volume_modifier = 0.5,
145    })
146
147    ::continue::
148  end
149end
150
151--- @param e EventData.on_player_changed_position|EventData.on_player_changed_surface
152local function on_player_moved(e)
153  local player = game.get_player(e.player_index)
154  if player then
155    check_around_player(player)
156  end
157end
158
159--- @param e EventData.on_player_main_inventory_changed|EventData.on_player_trash_inventory_changed
160local function on_player_inventory_changed(e)
161  local player = game.get_player(e.player_index)
162  if player then
163    check_inventory(player)
164  end
165end
166
167--- @param e EventData.on_player_created
168local function on_player_created(e)
169  local player = game.get_player(e.player_index)
170  if not player then
171    return
172  end
173
174  add_player(player)
175end
176
177--- @param e EventData.on_player_removed
178local function on_player_removed(e)
179  remove_player(e.player_index)
180end
181
182--- @param e EventData.on_runtime_mod_setting_changed
183local function on_runtime_mod_setting_changed(e)
184  if e.setting ~= "kr-enable-radioactivity" or not storage.radioactivity then
185    return
186  end
187
188  storage.radioactivity.enabled = settings.global["kr-enable-radioactivity"].value --[[@as boolean]]
189end
190
191local radioactivity = {}
192
193function radioactivity.on_init()
194  storage.radioactivity = {
195    enabled = settings.global["kr-enable-radioactivity"].value --[[@as boolean]],
196    --- @type table<uint, RadioactivityPlayerData>
197    players = {},
198  }
199  radioactivity.on_configuration_changed()
200end
201
202function radioactivity.on_configuration_changed()
203  storage.radioactivity.entities = {}
204  for _, entity_name in pairs(default_entities) do
205    if prototypes.entity[entity_name] then
206      table.insert(storage.radioactivity.entities, entity_name)
207    end
208  end
209  storage.radioactivity.items = {}
210  for _, item_name in pairs(default_items) do
211    if prototypes.item[item_name] then
212      table.insert(storage.radioactivity.items, item_name)
213    end
214  end
215end
216
217remote.add_interface("kr-radioactivity", {
218  --- @param name string
219  add_entity = function(name)
220    if not storage.radioactivity then
221      return
222    end
223    if not name or type(name) ~= "string" then
224      error("`name` must be a string.")
225    end
226
227    if not prototypes.entity[name] then
228      error("Entity `" .. name .. "` does not exist.")
229    end
230
231    table.insert(storage.radioactivity.entities, name)
232  end,
233  --- @param name string
234  add_item = function(name)
235    if not storage.radioactivity then
236      return
237    end
238    if not name or type(name) ~= "string" then
239      error("`name` must be a string.")
240    end
241
242    if not prototypes.item[name] then
243      error("Item `" .. name .. "` does not exist.")
244    end
245
246    table.insert(storage.radioactivity.items, name)
247  end,
248})
249
250radioactivity.events = {
251  [defines.events.on_player_changed_position] = on_player_moved,
252  [defines.events.on_player_changed_surface] = on_player_moved,
253  [defines.events.on_player_created] = on_player_created,
254  [defines.events.on_player_cursor_stack_changed] = on_player_inventory_changed,
255  [defines.events.on_player_died] = on_player_moved,
256  [defines.events.on_player_main_inventory_changed] = on_player_inventory_changed,
257  [defines.events.on_player_removed] = on_player_removed,
258  [defines.events.on_player_respawned] = on_player_moved,
259  [defines.events.on_player_toggled_map_editor] = on_player_moved,
260  [defines.events.on_player_trash_inventory_changed] = on_player_inventory_changed,
261  [defines.events.on_runtime_mod_setting_changed] = on_runtime_mod_setting_changed,
262  [defines.events.on_tick] = update_sounds,
263}
264
265radioactivity.on_nth_tick = {
266  [20] = update_and_damage,
267}
268
269return radioactivity