-
Notifications
You must be signed in to change notification settings - Fork 18
/
control.lua
291 lines (261 loc) · 9.2 KB
/
control.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
require "__pypostprocessing__.lib"
require "scripts/wiki/text-pages"
local update_rate = 67
py.on_event(py.events.on_init(), function()
if storage.first_chunk == nil then storage.first_chunk = false end
storage.oil_derricks = storage.oil_derricks or {}
end)
-- This script manages oil seep resources, mining them, and transforming them from seeps to the appropriate type when depleted
-- if you need the commented code that was here, go to git revision <= 4e9cd2f4bc7916ea438986d8037d63338463438e
-- Correlates our derricks and what replaces them with the seep transition, along with their hidden assembler names
local derrick_types = {}
for i = 1, 4 do
derrick_types["bitumen-seep-mk0" .. i] = {
base = "bitumen-seep-mk0" .. i .. "-base",
replacement = "oil-derrick-mk0" .. i,
resource = "oil-mk0" .. i
}
derrick_types["tar-seep-mk0" .. i] = {
base = "tar-seep-mk01-base",
replacement = "tar-extractor-mk0" .. i,
resource = "tar-patch"
}
derrick_types["natural-gas-seep-mk0" .. i] = {
base = "natural-gas-seep-mk01-base",
replacement = "natural-gas-extractor-mk0" .. i,
resource = "natural-gas-mk01"
}
end
local resource_types = {
["oil"] = "oil-derrick-mk0",
["tar"] = "tar-extractor-mk0",
["natural-gas"] = "natural-gas-extractor-mk0"
}
local event_filter = {
{
filter = "type",
type = "mining-drill"
}
}
-- Adds each drill mk01-mk04 to the event filter as "or" statements
for drill in pairs(derrick_types) do
local i = #event_filter
event_filter[i + 1] = {
filter = "name",
name = drill,
-- 1 and 2 or 3 or 4 or 5 etc
mode = i == 1 and "and" or "or"
}
end
-- Renders some text showing how close the seep is to opening
local function render_text(drill, time_to_live)
local patch = drill.patch
if not patch or not patch.valid then return end
rendering.draw_text {
time_to_live = 68,
target = drill.entity,
text = patch.amount,
surface = drill.entity.surface,
color = {1, 1, 1},
scale = 2,
alignment = "center",
target_offset = {0, -1.5}
}
end
py.on_event(py.events.on_built(), function(event)
local drill = event.entity
local drill_base = derrick_types[drill.name]
if not drill_base then return end
local patches = drill.surface.find_entities_filtered {
area = {{drill.position.x - 1, drill.position.y - 1}, {drill.position.x + 1, drill.position.y + 1}},
type = "resource"
}
for _, patch in pairs(patches) do
if patch.name == "bitumen-seep" then
local assembler = drill.surface.create_entity {
name = drill_base.base,
force = drill.force,
position = drill.position,
quality = drill.quality.name,
direction = drill.direction
}
assembler.set_recipe("drilling-fluids")
assembler.active = false
assembler.destructible = false
storage.oil_derricks[drill.unit_number] = {
entity = drill,
base = assembler,
drilling_fluid = "",
patch = patch
}
drill.active = false
-- Register for destruction event to handle removal via editor etc
script.register_on_object_destroyed(drill)
render_text(storage.oil_derricks[drill.unit_number], update_rate - game.tick % update_rate)
else
local resource_type = patch.name:match("(.*)(%-%w*)$")
drill.surface.create_entity {
name = resource_types[resource_type] .. drill.name:match("%d$"),
force = drill.force,
position = drill.position,
quality = drill.quality.name
}
drill.destroy()
end
break
end
end)
-- Destroy hidden assembler when removing drill
local function remove_seep(assembler, source, source_id)
assembler.destroy()
storage.oil_derricks[source_id or source.unit_number] = nil
end
-- Match hidden assembler rotation to drill rotation
local function rotate_seep(assembler, source)
assembler.direction = source.direction
end
local actions = {
[defines.events.on_player_mined_entity] = remove_seep,
[defines.events.on_robot_mined_entity] = remove_seep,
[defines.events.on_space_platform_mined_entity] = remove_seep,
[defines.events.on_entity_died] = remove_seep,
[defines.events.on_object_destroyed] = remove_seep,
[defines.events.on_player_rotated_entity] = rotate_seep
}
local function on_entity_modified(event)
local building = event.entity
local unit_no = event.useful_id
if event.entity then -- All but on_object_destroyed
-- on_player_rotated_entity can't be filtered :)
if derrick_types[building.name] then
local child_entity = building.surface.find_entities_filtered {
position = building.position,
type = "assembling-machine",
limit = 1
}[1]
if child_entity then actions[event.name](child_entity, building) end
end
elseif unit_no then -- on_object_destroyed provides a unit number and no entity
local child_entity = (storage.oil_derricks[unit_no] or {}).base
if child_entity and child_entity.valid then
actions[event.name](child_entity, nil, unit_no)
end
end
end
script.on_event(defines.events.on_player_mined_entity, on_entity_modified, event_filter)
script.on_event(defines.events.on_robot_mined_entity, on_entity_modified, event_filter)
script.on_event(defines.events.on_entity_died, on_entity_modified, event_filter)
script.on_event(defines.events.on_space_platform_mined_entity, on_entity_modified, event_filter)
script.on_event(defines.events.on_player_rotated_entity, on_entity_modified)
script.on_event(defines.events.on_object_destroyed, on_entity_modified)
-- Activates/deactivates derricks based on how much drilling fluid they have
-- Selects the best available drilling fluid to use
local fluid_threshold = 50
local fluid_max_tier = 3
local fluid_min_tier = 0 -- Tiers are zero-indexed here, god knows why
py.register_on_nth_tick(update_rate, "drills", "pyph", function()
for drill_id, drill in pairs(storage.oil_derricks) do
if not drill.base.valid then
if drill.entity and drill.entity.valid then
drill.entity.destroy()
end
storage.oil_derricks[drill_id] = nil
return
end
local drill_active = false
local drill_contents = drill.base.get_fluid_contents()
local drill_empty = next(drill_contents) == nil
if not drill.entity.valid then
log("invalid drill encountered during update cycle, id: " .. drill_id)
on_entity_modified {
name = defines.events.on_object_destroyed,
unit_number = drill_id
}
else
if not drill_empty then
-- Check possible drilling fluids in descending order of quality
for current_tier = fluid_max_tier, fluid_min_tier, -1 do
local fluid_type = "drilling-fluid-" .. current_tier
local contained_fluid = drill_contents[fluid_type]
if contained_fluid then
if contained_fluid >= fluid_threshold then
storage.oil_derricks[drill_id].drilling_fluid = fluid_type
drill.base.remove_fluid {name = fluid_type, amount = 10}
drill.entity.force.get_fluid_production_statistics(drill.entity.surface_index).on_flow(fluid_type, -10)
drill_active = true
end
break
end
end
end
drill.entity.active = drill_active
render_text(drill, update_rate + 1)
end
end
end)
-- Overwrites seep amounts when they are generated
script.on_event(defines.events.on_chunk_generated, function(event)
local bitumen_patches = event.surface.find_entities_filtered {name = "bitumen-seep", area = event.area}
for _, patch in pairs(bitumen_patches) do
patch.amount = math.random(1000, 2500)
end
end)
local function swap_drill(drill, replacement)
local surface = drill.surface
local parameters = {
name = replacement,
position = drill.position,
force = drill.force,
direction = drill.direction,
player = drill.last_user,
quality = drill.quality.name,
}
local source_module_inventory = drill.get_module_inventory()
local module_contents
if source_module_inventory then module_contents = source_module_inventory.get_contents() end
drill.destroy()
local new_drill = surface.create_entity(parameters)
local destination_module_inventory = new_drill.get_module_inventory()
if source_module_inventory and destination_module_inventory then
for _, item in pairs(module_contents) do
destination_module_inventory.insert(item)
end
end
end
script.on_event(defines.events.on_resource_depleted, function(event)
local resource = event.entity
if resource.name ~= "bitumen-seep" then
return
end
local active_drills = resource.surface.find_entities_filtered {
area = {{resource.position.x - 1, resource.position.y - 1}, {resource.position.x + 1, resource.position.y + 1}},
type = "mining-drill"
}
for _, drill in pairs(active_drills) do
local drill_data = derrick_types[drill.name]
if drill_data then
local drill_fluid = storage.oil_derricks[drill.unit_number].drilling_fluid
local fluid_tier = ((drill_fluid:match("%d$") + 1) * 4)
local drill_tier = (drill.name:match("%d$") * 4)
local random_factor = math.random(4, 16)
local new_patch_size = 40000 * random_factor * drill_tier * fluid_tier
local base = storage.oil_derricks[drill.unit_number].base
if base and base.valid then base.destroy() end
storage.oil_derricks[drill.unit_number] = nil
resource.surface.create_entity {
name = drill_data.resource,
amount = new_patch_size,
position = resource.position,
quality = resource.quality.name
}
swap_drill(drill, drill_data.replacement)
end
end
end)
remote.add_interface("pyph", {
---@param func string
execute_on_nth_tick = function(func)
py.mod_nth_tick_funcs[func]()
end
})
py.finalize_events()