-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcontrol.lua
More file actions
297 lines (272 loc) · 9.62 KB
/
Copy pathcontrol.lua
File metadata and controls
297 lines (272 loc) · 9.62 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
local MY_BRIDGES = {
["rail-bridge"] = true,
["rail-bridge-diagonal-left"] = true,
["rail-bridge-diagonal-right"] = true,
}
local MY_RAILS = {
["rail-bridge-north"] = true,
["rail-bridge-east"] = true,
["rail-bridge-rail-1"] = true,
["rail-bridge-rail-2"] = true,
["rail-bridge-rail-3"] = true,
["rail-bridge-rail-4"] = true,
}
function on_init()
-- Unlock recipe
for _, force in pairs(game.forces) do
if force.technologies["logistics-3"].researched then
force.recipes["rail-bridge"].enabled = true
force.recipes["rail-bridge-diagonal-left"].enabled = true
force.recipes["rail-bridge-diagonal-right"].enabled = true
end
end
end
function on_configuration_changed(event)
on_init()
local changes = event.mod_changes["rail-bridge"]
if not changes then return end
-- Move bridge sprite to the rendering system
if changes.old_version and changes.old_version < "0.0.3" then
for _, surface in pairs(game.surfaces) do
for _, bridge in pairs(surface.find_entities_filtered{name = {
"rail-bridge",
"rail-bridge-diagonal-left",
"rail-bridge-diagonal-right",
}}) do
draw_sprite(bridge)
end
end
end
end
function on_built(event)
local entity = event.created_entity or event.entity
if not entity or not entity.valid then return end
if not MY_BRIDGES[entity.name] then return end
-- Align to rail grid
local mod_x = 0
local mod_y = 0
if entity.name == "rail-bridge-diagonal-left"
or entity.name == "rail-bridge-diagonal-right" then
if entity.direction % 4 == defines.direction.north then
mod_x = 0
mod_y = 1
else
mod_x = 1
mod_y = 0
end
end
local x = entity.position.x
local y = entity.position.y
if x % 2 == mod_x then x = x - 1 end
if y % 2 == mod_y then y = y - 1 end
if entity.position.x ~= x or entity.position.y ~= y then
entity.teleport{x, y}
end
-- Check collisions
local delete_rails = {}
for _, obstacle in pairs(entity.surface.find_entities_filtered{
type = {"straight-rail", "entity-ghost"},
area = area_under(entity),
}) do
if obstacle.type == "straight-rail"
and obstacle.force == entity.force
and obstacle.can_be_destroyed() then
table.insert(delete_rails, obstacle)
elseif obstacle.type == "entity-ghost"
and obstacle.ghost_type == "straight-rail" then
table.insert(delete_rails, obstacle)
else
-- Obstacle can't be destroyed, abort the build!
refund_entity(entity, event, obstacle)
return
end
end
-- Destroy rails in the area
for _, rail in pairs(delete_rails) do
if entity.name == "rail-bridge" and MY_RAILS[rail] and rail.direction % 2 == 1 then
-- Straight bridge can't remove diagonal rails
else
refund_entity(rail, event)
end
end
-- Create bridge sprite
draw_sprite(entity)
-- Create crossing rails
if entity.name == "rail-bridge" then
create_rail("rail-bridge-north", entity, defines.direction.north)
create_rail("rail-bridge-east", entity, defines.direction.east)
elseif entity.name == "rail-bridge-diagonal-left" then
if entity.direction % 4 == defines.direction.north then
create_rail("rail-bridge-rail-1", entity, defines.direction.north, {0, -1})
create_rail("rail-bridge-rail-2", entity, defines.direction.north, {0, 1})
create_rail("rail-bridge-rail-1", entity, defines.direction.southwest, {0, -1})
create_rail("rail-bridge-rail-2", entity, defines.direction.northeast, {0, 1})
else
create_rail("rail-bridge-rail-1", entity, defines.direction.east, {-1, 0})
create_rail("rail-bridge-rail-2", entity, defines.direction.east, {1, 0})
create_rail("rail-bridge-rail-1", entity, defines.direction.southeast, {-1, 0})
create_rail("rail-bridge-rail-2", entity, defines.direction.northwest, {1, 0})
end
elseif entity.name == "rail-bridge-diagonal-right" then
if entity.direction % 4 == defines.direction.north then
create_rail("rail-bridge-rail-3", entity, defines.direction.north, {0, -1})
create_rail("rail-bridge-rail-4", entity, defines.direction.north, {0, 1})
create_rail("rail-bridge-rail-3", entity, defines.direction.southeast, {0, -1})
create_rail("rail-bridge-rail-4", entity, defines.direction.northwest, {0, 1})
else
create_rail("rail-bridge-rail-4", entity, defines.direction.east, {-1, 0})
create_rail("rail-bridge-rail-3", entity, defines.direction.east, {1, 0})
create_rail("rail-bridge-rail-4", entity, defines.direction.northeast, {-1, 0})
create_rail("rail-bridge-rail-3", entity, defines.direction.southwest, {1, 0})
end
end
end
function on_entity_cloned(event)
local entity = event.destination
if not entity or not entity.valid then return end
if MY_BRIDGES[entity.name] then
-- Continue in on_built
on_built({entity=entity, name=event.name})
elseif MY_RAILS[entity.name] then
-- Don't let other mods clone our custom rails
entity.destroy()
end
end
function on_destroyed(event)
local entity = event.entity
if not entity or not entity.valid then return end
if not MY_BRIDGES[entity.name] then return end
-- Remove crossing rails
for _, rail in pairs(entity.surface.find_entities_filtered {
type = "straight-rail",
area = area_under(entity),
force = entity.force,
}) do
if MY_RAILS[rail.name] then
if entity.name == "rail-bridge" and rail.direction % 2 == 1 then
-- Straight bridge can't remove diagonal rails
else
rail.destroy()
end
end
end
end
function on_gui_opened(event)
-- Disable bridge gui
local entity = event.entity
if not entity or not entity.valid then return end
if MY_BRIDGES[event.entity.name] then
game.players[event.player_index].opened = nil
end
end
function create_rail(name, bridge, direction, position)
-- Create one of our custom rails
if not position then position = {0, 0} end
local rail = bridge.surface.create_entity{
name = name,
direction = direction,
force = bridge.force,
position = {bridge.position.x + position[1], bridge.position.y + position[2]},
create_build_effect_smoke = false,
}
if rail then rail.destructible = false end
end
function area_under(entity)
-- Calculate the absolute position of the entity's collision box
local p = entity.position
local box = entity.prototype.collision_box
local dx = (box.right_bottom.x - box.left_top.x) / 2
local dy = (box.right_bottom.y - box.left_top.y) / 2
if entity.direction and entity.direction % 4 ~= defines.direction.north then
dx, dy = dy, dx
end
return {{p.x - dx, p.y - dy}, {p.x + dx, p.y + dy}}
end
function refund_entity(entity, build_event, colliding_entity)
-- Show alert
local player = nil
if build_event and build_event.player_index then
player = game.players[build_event.player_index]
end
if player and colliding_entity then
entity.surface.create_entity{
name = "flying-text",
text = {"cant-build-reason.entity-in-the-way", colliding_entity.localised_name},
position = entity.position,
render_player_index = build_event.player_index,
}
end
if entity.prototype.items_to_place_this then
-- Find the item used to place the entity
local item_count = 0
local item_name = nil
if build_event and build_event.stack and build_event.stack.valid_for_read then
item_name = build_event.stack.name
end
for _, item in pairs(entity.prototype.items_to_place_this) do
if item_name == item.name then
item_count = item.count
break
end
end
if item_count == 0 then
local item = entity.prototype.items_to_place_this[1]
if item then
item_name = item.name
item_count = item.count
end
end
local health = entity.health / entity.prototype.max_health
-- Return item to player inventory
if item_count > 0 and player then
local result = player.insert{name=item_name, count=item_count, health=health}
item_count = item_count - result
end
-- Return item to ground
if item_count > 0 then
entity.surface.spill_item_stack(entity.position, {name=item_name, count=item_count, health=health}, false, entity.force, false)
end
end
-- Destroy entity
entity.destroy{raise_destroy = true}
end
function draw_sprite(entity)
-- Get sprite name
local sprite = nil
if entity.name == "rail-bridge" then
sprite = "rail-bridge"
elseif entity.name == "rail-bridge-diagonal-left" then
if entity.direction % 4 == defines.direction.north then
sprite = "rail-bridge-ne"
else
sprite = "rail-bridge-sw"
end
elseif entity.name == "rail-bridge-diagonal-right" then
if entity.direction % 4 == defines.direction.north then
sprite = "rail-bridge-nw"
else
sprite = "rail-bridge-se"
end
end
-- Draw sprite
if sprite then
rendering.draw_sprite{
sprite = sprite,
surface = entity.surface,
target = entity,
render_layer = "transport-belt",
}
end
end
script.on_init(on_init)
script.on_configuration_changed(on_configuration_changed)
script.on_event(defines.events.on_built_entity, on_built)
script.on_event(defines.events.on_robot_built_entity, on_built)
script.on_event(defines.events.script_raised_built, on_built)
script.on_event(defines.events.script_raised_revive, on_built)
script.on_event(defines.events.on_entity_cloned, on_entity_cloned)
script.on_event(defines.events.on_player_mined_entity, on_destroyed)
script.on_event(defines.events.on_robot_mined_entity, on_destroyed)
script.on_event(defines.events.on_entity_died, on_destroyed)
script.on_event(defines.events.script_raised_destroy, on_destroyed)
script.on_event(defines.events.on_gui_opened, on_gui_opened)