forked from nicholasgower/pelagos
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcontrol.lua
More file actions
506 lines (462 loc) · 15.9 KB
/
Copy pathcontrol.lua
File metadata and controls
506 lines (462 loc) · 15.9 KB
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
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
-------------------------------------------------------------------------------
-- lighthouse: spawn/remove lamp based on fuel state
-------------------------------------------------------------------------------
local function on_built_lighthouse(event)
local lighthouse = event.entity or event.created_entity
if not (lighthouse and lighthouse.valid and lighthouse.name == "lighthouse") then
return
end
storage.pelagos_lighthouse_lamps[lighthouse.unit_number] = { radar = lighthouse, lamp = nil }
end
local function on_removed_lighthouse(event)
local e = event.entity
if not (e and e.valid and e.name == "lighthouse") then
return
end
local data = storage.pelagos_lighthouse_lamps[e.unit_number]
if data and data.lamp and data.lamp.valid then
data.lamp.destroy()
end
storage.pelagos_lighthouse_lamps[e.unit_number] = nil
end
-------------------------------------------------------------------------------
-- check every 2 seconds
-------------------------------------------------------------------------------
script.on_nth_tick(120, function()
if not storage.pelagos_lighthouse_lamps then
return
end
for id, data in pairs(storage.pelagos_lighthouse_lamps) do
local lighthouse = data.radar
if not (lighthouse and lighthouse.valid) then
if data.lamp and data.lamp.valid then
data.lamp.destroy()
end
storage.pelagos_lighthouse_lamps[id] = nil
else
local fluid = lighthouse.fluidbox and lighthouse.fluidbox[1]
local has_fuel = (fluid and fluid.amount or 0) > 0
if has_fuel then
if not (data.lamp and data.lamp.valid) then
local lamp = lighthouse.surface.create_entity({
name = "lighthouse-light",
position = { lighthouse.position.x - 0.1, lighthouse.position.y },
force = lighthouse.force,
create_build_effect_smoke = false,
})
if lamp then
lamp.destructible = false
lamp.operable = false
data.lamp = lamp
end
end
else
if data.lamp and data.lamp.valid then
data.lamp.destroy()
data.lamp = nil
end
end
end
end
end)
-------------------------------------------------------------------------------
-- diesel asteroid collector: manage paired engine
-------------------------------------------------------------------------------
local function on_built_collector(event)
local collector = event.entity or event.created_entity
if not (collector and collector.valid and collector.name == "diesel-asteroid-collector") then
return
end
storage.pelagos_diesel_collectors = storage.pelagos_diesel_collectors or {}
storage.pelagos_diesel_collectors[collector.unit_number] = { collector = collector, engine = nil }
end
local function on_removed_collector(event)
local e = event.entity
if not (e and e.valid and e.name == "diesel-asteroid-collector") then
return
end
local data = storage.pelagos_diesel_collectors and storage.pelagos_diesel_collectors[e.unit_number]
if data and data.engine and data.engine.valid then
data.engine.destroy()
end
if storage.pelagos_diesel_collectors then
storage.pelagos_diesel_collectors[e.unit_number] = nil
end
end
-------------------------------------------------------------------------------
-- every 1 second: ensure engine exists + sync active state
-------------------------------------------------------------------------------
script.on_nth_tick(60, function()
if not storage.pelagos_diesel_collectors then
return
end
for id, data in pairs(storage.pelagos_diesel_collectors) do
local collector = data.collector
if not (collector and collector.valid) then
if data.engine and data.engine.valid then
data.engine.destroy()
end
storage.pelagos_diesel_collectors[id] = nil
else
local engine = data.engine
if not (engine and engine.valid) then
local new_engine = collector.surface.create_entity({
name = "diesel-asteroid-collector-engine",
position = collector.position,
direction = collector.direction,
force = collector.force,
create_build_effect_smoke = false,
move_stuck_players = true,
})
if new_engine then
new_engine.destructible = false
new_engine.operable = false
local recipe = "diesel-asteroid-collector-working"
if new_engine.set_recipe and new_engine.force.recipes[recipe] then
new_engine.set_recipe(recipe)
new_engine.recipe_locked = true
new_engine.active = true
end
data.engine = new_engine
end
end
if data.engine and data.engine.valid then
local engine = data.engine
local collector = data.collector
local fluid = engine.fluidbox and engine.fluidbox[1]
local has_fuel = (fluid and fluid.amount or 0) > 0
local working = (engine.is_crafting() or engine.energy > 0) and has_fuel
if collector.active ~= working then
collector.active = working
end
end
end
end
end)
-------------------------------------------------------------------------------
-- Define the initial machine groups and allowed tiles for each group.
local function build_allowed_entities()
local allowed = {}
local filters = {
{ filter = "subgroup", subgroup = "circuit-network" },
}
local entity_filters = {
{ filter = "type", type = "inserter" },
{ filter = "type", type = "transport-belt" },
}
local entities = prototypes.get_entity_filtered(entity_filters)
for _, ent in pairs(entities) do
allowed[ent.name] = true
end
-- get items from filters
local items = {}
if filters[1] then
items = prototypes.get_item_filtered(filters)
end
for _, item in pairs(items) do
if item.place_result then
allowed[item.place_result.name] = true
end
end
-- chest with size 1x1
local chest_filters = { { filter = "type", type = "container" } }
local chests = prototypes.get_entity_filtered(chest_filters)
for _, chest in pairs(chests) do
local box = chest.selection_box
if box and box.left_top and box.right_bottom then
local width = math.abs(box.right_bottom.x - box.left_top.x)
local height = math.abs(box.right_bottom.y - box.left_top.y)
if width < 1.1 and height < 1.1 then
allowed[chest.name] = true
end
end
end
-- logistic chest with size 1x1
local logistic_chest_filters = { { filter = "type", type = "logistic-container" } }
local logistic_chests = prototypes.get_entity_filtered(logistic_chest_filters)
for _, chest in pairs(logistic_chests) do
local box = chest.selection_box
if box and box.left_top and box.right_bottom then
local width = math.abs(box.right_bottom.x - box.left_top.x)
local height = math.abs(box.right_bottom.y - box.left_top.y)
if width < 1.1 and height < 1.1 then
allowed[chest.name] = true
end
end
end
-- additional stuff
allowed["gun-turret"] = true
allowed["heavy-gun-turret"] = true
allowed["flamethrower-turret"] = true
allowed["rocket-turret"] = true
allowed["pipe"] = true
allowed["steel-chest"] = true
allowed["barreling-machine"] = true
allowed["radar"] = true
allowed["canex-excavator"] = true
allowed["entity-ghost"] = true
allowed["pump"] = true
allowed["long-range-delivery-drone-request-depot"] = true
allowed["cargo_ship"] = true
allowed["cargo_ship_engine"] = true
allowed["oil_tanker"] = true
allowed["indep-boat"] = true
allowed["boat_engine"] = true
allowed["oil_rig"] = true
allowed["or_power_electric"] = true
allowed["or_pole"] = true
allowed["or_radar"] = true
allowed["or_tank"] = true
return allowed
end
-------------------------------------------------------------------------------
--- init
-------------------------------------------------------------------------------
local function register_with_cargo_ships()
-- add pirateship to cargo_ship ships so it can be entered the same way as other ships
if remote.interfaces["cargo-ships"] and remote.interfaces["cargo-ships"].add_boat then
if prototypes.entity["pirateship"] then
remote.call("cargo-ships", "add_boat", {
name = "pirateship",
rail_version = nil,
})
log("Pelagos: Registered Pirate Ship as a boat for Cargo Ships system.")
else
log("Pelagos: Pirate Ship entity not found.")
end
else
log("Pelagos: Cargo Ships API not available (add_boat missing).")
end
end
local function ensure_storage_integrity()
if not storage then
return
end
if not storage.allowed_entities then
storage.allowed_entities = build_allowed_entities()
end
storage.pelagos_lighthouse_lamps = storage.pelagos_lighthouse_lamps or {}
storage.pelagos_diesel_collectors = storage.pelagos_diesel_collectors or {}
end
-------------------------------------------------------------------------------
-- on_entity_built logic
-------------------------------------------------------------------------------
local function on_entity_built(event)
ensure_storage_integrity()
local entity = event.entity
if not (entity and entity.valid) then
return
end
local surface = entity.surface
local bounds = entity.bounding_box
local left = math.floor(bounds.left_top.x + 0.001)
local top = math.floor(bounds.left_top.y + 0.001)
local right = math.floor(bounds.right_bottom.x - 0.001)
local bottom = math.floor(bounds.right_bottom.y - 0.001)
-- Check every tile beneath the entity for allowed terrain.
for tx = left, right do
for ty = top, bottom do
local tile = surface.get_tile(tx, ty)
local tile_name = tile.name
-- check if ground is wooden-platform
if tile_name == "wooden-platform" then
-- check if it's allowed to place
if not storage.allowed_entities[entity.name] then
if event.player_index then
local player = game.get_player(event.player_index)
if player then
local consumed_inv = event.consumed_items
if consumed_inv and consumed_inv.valid then
for _, stack in ipairs(consumed_inv.get_contents()) do
local item_name = stack.name or stack[1]
local item_count = stack.count or stack[2]
local item_quality = stack.quality or stack[3]
local insert_stack = { name = item_name, count = item_count }
if item_quality then
insert_stack.quality = (type(item_quality) == "table" and item_quality.name)
or item_quality
end
local inserted = player.insert(insert_stack)
if inserted < item_count then
surface.spill_item_stack({
position = entity.position,
stack = {
name = item_name,
count = item_count - inserted,
quality = insert_stack.quality,
},
enable_looted = true,
})
end
end
end
end
else
if event.stack and event.stack.valid_for_read then
local item_name = event.stack.name
local item_count = event.stack.count
local quality_proto = event.stack.quality
local spill_stack = { name = item_name, count = item_count }
if quality_proto then
spill_stack.quality = quality_proto.name or quality_proto
end
surface.spill_item_stack({
position = entity.position,
stack = spill_stack,
enable_looted = true,
})
end
end
if entity.valid then
entity.destroy({ raise_destroy = false })
end
return
end
return
end
end
end
end
local function on_built_rocket_silo(event)
local entity = event.entity or event.created_entity
if not (entity and entity.valid) then
return
end
local proto = (entity.name == "entity-ghost") and entity.ghost_prototype or entity.prototype
if not proto or proto.type ~= "rocket-silo" then
return
end
if not proto.crafting_categories or not proto.crafting_categories["rocket-building"] then
return
end
-- set_recipe based on surface
local recipe
if entity.surface.name == "pelagos" then
recipe = "pelagos-rocket-part"
entity.set_recipe(recipe)
entity.recipe_locked = true
end
end
-------------------------------------------------------------------------------
local function on_init(event)
storage.allowed_entities = build_allowed_entities()
storage.pelagos_lighthouse_lamps = storage.pelagos_lighthouse_lamps or {}
storage.pelagos_diesel_collectors = storage.pelagos_diesel_collectors or {}
register_with_cargo_ships()
end
script.on_init(on_init)
local function on_configuration_changed(event)
storage.allowed_entities = build_allowed_entities()
storage.pelagos_lighthouse_lamps = storage.pelagos_lighthouse_lamps or {}
storage.pelagos_diesel_collectors = storage.pelagos_diesel_collectors or {}
register_with_cargo_ships()
end
script.on_configuration_changed(on_configuration_changed)
-------------------------------------------------------------------------------
script.on_event(defines.events.on_built_entity, function(event)
local e = event.created_entity or event.entity
if not e then
return
end
on_entity_built(event)
on_built_rocket_silo(event)
on_built_lighthouse(event)
on_built_collector(event)
end)
script.on_event(defines.events.on_robot_built_entity, function(event)
local e = event.created_entity or event.entity
if not e then
return
end
on_entity_built(event)
on_built_rocket_silo(event)
on_built_lighthouse(event)
on_built_collector(event)
end)
script.on_event(defines.events.on_space_platform_built_entity, function(event)
local e = event.entity
if not (e and e.valid) then
return
end
on_built_rocket_silo(event)
on_built_lighthouse(event)
on_built_collector(event)
end)
script.on_event(
{ defines.events.on_entity_died, defines.events.on_player_mined_entity, defines.events.on_robot_mined_entity },
function(event)
local e = event.entity
if not e then
return
end
on_removed_lighthouse(event)
on_removed_collector(event)
end
)
-------------------------------------------------------------------------------
--- starting ore patch
-------------------------------------------------------------------------------
script.on_event(defines.events.on_player_created, function(event)
storage.init = storage.init or {}
if storage.init[event.player_index] then
return
end
storage.init[event.player_index] = true
if not script.active_mods["any-planet-start"] then
if script.active_mods["depths_of_nauvis"] then
if settings.startup["generate-oil-only-on-water"].value then
game.print(
"Creator of Pelagos and Depths of Nauvis:\nHi. Looks like this combination of mods and settings will lock your progreesion:\n"
.. "Pelagos is a place where you unlock oil rig and ships but you probably spawned on Nauvis.\n"
.. "Depths of nauvis by default remove oil from ground, and leave just offshore oil. And looks like this setting is turned on\n"
.. "Without oil you can't leave Nauvis.\n"
.. "You can enable oil patches on ground in settings and generate new world, or temporarly remove pelagos form list of mods, until you setup oil rig on nauvis"
)
end
end
return
end
local setting = settings.startup["aps-planet"]
if not setting or setting.value ~= "pelagos" then
return
end
if
not script.active_mods["Burner-Leech-Fork"]
and not script.active_mods["Burner-Leech"]
and not script.active_mods["InserterFuelLeech"]
then
game.print(
"Pelagos: You are starting Any Planet Start game without a burner leech mod. "
.. "The intended experience is to use one. You can disable such a mod after the burner phase of the game. "
.. "See the mod page for more details."
)
end
end)
local generated_iron_patch = false
script.on_event(defines.events.on_surface_created, function(event)
local surface = game.surfaces[event.surface_index]
if surface.name == "pelagos" and not generated_iron_patch then
generated_iron_patch = true
local center = { x = 10, y = 10 }
local radius = 12
local max_amount = 3000
for x = -radius, radius do
for y = -radius, radius do
local distance = math.sqrt(x * x + y * y)
if distance <= radius then
local noise = math.random()
local density = 1 - (distance / radius) + (noise - 0.5) * 0.3
if density > 0.2 then
local amount = math.floor(max_amount * density)
surface.create_entity({
name = "iron-ore",
amount = amount,
position = { center.x + x, center.y + y },
})
end
end
end
end
end
end)
-------------------------------------------------------------------------------