This repository has been archived by the owner on Sep 12, 2021. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 66
/
change_turf.dm
324 lines (281 loc) · 11 KB
/
change_turf.dm
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
// This is a list of turf types we dont want to assign to baseturfs unless through initialization or explicitly
GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
/turf/open/space,
/turf/baseturf_bottom,
)))
/turf/proc/empty(turf_type=/turf/open/space, baseturf_type, list/ignore_typecache, flags)
// Remove all atoms except observers, landmarks, docking ports
var/static/list/ignored_atoms = typecacheof(list(/mob/dead, /obj/effect/landmark, /obj/docking_port, /atom/movable/lighting_object))
var/list/allowed_contents = typecache_filter_list_reverse(GetAllContentsIgnoring(ignore_typecache), ignored_atoms)
allowed_contents -= src
for(var/i in 1 to allowed_contents.len)
var/thing = allowed_contents[i]
qdel(thing, force=TRUE)
if(turf_type)
var/turf/newT = ChangeTurf(turf_type, baseturf_type, flags)
SSair.remove_from_active(newT)
CALCULATE_ADJACENT_TURFS(newT)
SSair.add_to_active(newT,1)
/turf/proc/copyTurf(turf/T)
if(T.type != type)
var/obj/O
if(underlays.len) //we have underlays, which implies some sort of transparency, so we want to a snapshot of the previous turf as an underlay
O = new()
O.underlays.Add(T)
T.ChangeTurf(type)
if(underlays.len)
T.underlays = O.underlays
if(T.icon_state != icon_state)
T.icon_state = icon_state
if(T.icon != icon)
T.icon = icon
if(color)
T.atom_colours = atom_colours.Copy()
T.update_atom_colour()
if(T.dir != dir)
T.setDir(dir)
return T
/turf/open/copyTurf(turf/T, copy_air = FALSE)
. = ..()
if (isopenturf(T))
var/datum/component/wet_floor/slip = GetComponent(/datum/component/wet_floor)
if(slip)
var/datum/component/wet_floor/WF = T.AddComponent(/datum/component/wet_floor)
WF.InheritComponent(slip)
if (copy_air)
var/turf/open/openTurf = T
openTurf.air.copy_from(air)
//wrapper for ChangeTurf()s that you want to prevent/affect without overriding ChangeTurf() itself
/turf/proc/TerraformTurf(path, new_baseturf, flags)
return ChangeTurf(path, new_baseturf, flags)
// Creates a new turf
// new_baseturfs can be either a single type or list of types, formated the same as baseturfs. see turf.dm
/turf/proc/ChangeTurf(path, list/new_baseturfs, flags)
switch(path)
if(null)
return
if(/turf/baseturf_bottom)
path = SSmapping.level_trait(z, ZTRAIT_BASETURF) || /turf/open/space
if (!ispath(path))
path = text2path(path)
if (!ispath(path))
warning("Z-level [z] has invalid baseturf '[SSmapping.level_trait(z, ZTRAIT_BASETURF)]'")
path = /turf/open/space
if(/turf/open/space/basic)
// basic doesn't initialize and this will cause issues
// no warning though because this can happen naturaly as a result of it being built on top of
path = /turf/open/space
if(!GLOB.use_preloader && path == type && !(flags & CHANGETURF_FORCEOP) && (baseturfs == new_baseturfs)) // Don't no-op if the map loader requires it to be reconstructed, or if this is a new set of baseturfs
return src
if(flags & CHANGETURF_SKIP)
return new path(src)
var/old_dynamic_lighting = dynamic_lighting
var/old_affecting_lights = affecting_lights
var/old_lighting_object = lighting_object
var/old_corners = corners
var/old_directional_opacity = directional_opacity
var/old_exl = explosion_level
var/old_exi = explosion_id
var/old_bp = blueprint_data
blueprint_data = null
var/list/old_baseturfs = baseturfs
var/list/transferring_comps = list()
SEND_SIGNAL(src, COMSIG_TURF_CHANGE, path, new_baseturfs, flags, transferring_comps)
for(var/i in transferring_comps)
var/datum/component/comp = i
comp.RemoveComponent()
changing_turf = TRUE
qdel(src) //Just get the side effects and call Destroy
var/turf/W = new path(src)
for(var/i in transferring_comps)
W.TakeComponent(i)
if(new_baseturfs)
W.baseturfs = new_baseturfs
else
W.baseturfs = old_baseturfs
W.explosion_id = old_exi
W.explosion_level = old_exl
if(!(flags & CHANGETURF_DEFER_CHANGE))
W.AfterChange(flags)
W.blueprint_data = old_bp
if(SSlighting.initialized)
lighting_object = old_lighting_object
affecting_lights = old_affecting_lights
corners = old_corners
directional_opacity = old_directional_opacity
recalculate_directional_opacity()
if (dynamic_lighting != old_dynamic_lighting)
if (IS_DYNAMIC_LIGHTING(src))
lighting_build_overlay()
else
lighting_clear_overlay()
for(var/turf/open/space/S in RANGE_TURFS(1, src)) //RANGE_TURFS is in code\__HELPERS\game.dm
S.update_starlight()
QUEUE_SMOOTH_NEIGHBORS(src)
QUEUE_SMOOTH(src)
return W
/turf/open/ChangeTurf(path, list/new_baseturfs, flags) //Resist the temptation to make this default to keeping air.
if ((flags & CHANGETURF_INHERIT_AIR) && ispath(path, /turf/open))
SSair.remove_from_active(src)
var/datum/gas_mixture/stashed_air = new()
stashed_air.copy_from(air)
. = ..()
if (!.) // changeturf failed or didn't do anything
QDEL_NULL(stashed_air)
return
var/turf/open/newTurf = .
newTurf.air.copy_from(stashed_air)
QDEL_NULL(stashed_air)
update_air_ref()
SSair.add_to_active(newTurf)
else
if(ispath(path,/turf/closed))
flags |= CHANGETURF_RECALC_ADJACENT
return ..()
/turf/closed/ChangeTurf(path, list/new_baseturfs, flags)
if(ispath(path,/turf/open))
flags |= CHANGETURF_RECALC_ADJACENT
return ..()
// Take off the top layer turf and replace it with the next baseturf down
/turf/proc/ScrapeAway(amount=1, flags)
if(!amount)
return
if(length(baseturfs))
var/list/new_baseturfs = baseturfs.Copy()
var/turf_type = new_baseturfs[max(1, new_baseturfs.len - amount + 1)]
while(ispath(turf_type, /turf/baseturf_skipover))
amount++
if(amount > new_baseturfs.len)
CRASH("The bottomost baseturf of a turf is a skipover [src]([type])")
turf_type = new_baseturfs[max(1, new_baseturfs.len - amount + 1)]
new_baseturfs.len -= min(amount, new_baseturfs.len - 1) // No removing the very bottom
if(new_baseturfs.len == 1)
new_baseturfs = new_baseturfs[1]
return ChangeTurf(turf_type, new_baseturfs, flags)
if(baseturfs == type)
return src
return ChangeTurf(baseturfs, baseturfs, flags) // The bottom baseturf will never go away
// Take the input as baseturfs and put it underneath the current baseturfs
// If fake_turf_type is provided and new_baseturfs is not the baseturfs list will be created identical to the turf type's
// If both or just new_baseturfs is provided they will be inserted below the existing baseturfs
/turf/proc/PlaceOnBottom(list/new_baseturfs, turf/fake_turf_type)
if(fake_turf_type)
if(!new_baseturfs)
if(!length(baseturfs))
baseturfs = list(baseturfs)
var/list/old_baseturfs = baseturfs.Copy()
assemble_baseturfs(fake_turf_type)
if(!length(baseturfs))
baseturfs = list(baseturfs)
baseturfs -= baseturfs & GLOB.blacklisted_automated_baseturfs
baseturfs += old_baseturfs
return
else if(!length(new_baseturfs))
new_baseturfs = list(new_baseturfs, fake_turf_type)
else
new_baseturfs += fake_turf_type
if(!length(baseturfs))
baseturfs = list(baseturfs)
baseturfs.Insert(1, new_baseturfs)
// Make a new turf and put it on top
// The args behave identical to PlaceOnBottom except they go on top
// Things placed on top of closed turfs will ignore the topmost closed turf
// Returns the new turf
/turf/proc/PlaceOnTop(list/new_baseturfs, turf/fake_turf_type, flags)
var/area/turf_area = loc
if(new_baseturfs && !length(new_baseturfs))
new_baseturfs = list(new_baseturfs)
flags = turf_area.PlaceOnTopReact(new_baseturfs, fake_turf_type, flags) // A hook so areas can modify the incoming args
var/turf/newT
if(flags & CHANGETURF_SKIP) // We haven't been initialized
if(flags_1 & INITIALIZED_1)
stack_trace("CHANGETURF_SKIP was used in a PlaceOnTop call for a turf that's initialized. This is a mistake. [src]([type])")
assemble_baseturfs()
if(fake_turf_type)
if(!new_baseturfs) // If no baseturfs list then we want to create one from the turf type
if(!length(baseturfs))
baseturfs = list(baseturfs)
var/list/old_baseturfs = baseturfs.Copy()
if(!istype(src, /turf/closed))
old_baseturfs += type
newT = ChangeTurf(fake_turf_type, null, flags)
newT.assemble_baseturfs(initial(fake_turf_type.baseturfs)) // The baseturfs list is created like roundstart
if(!length(newT.baseturfs))
newT.baseturfs = list(baseturfs)
newT.baseturfs -= GLOB.blacklisted_automated_baseturfs
newT.baseturfs.Insert(1, old_baseturfs) // The old baseturfs are put underneath
return newT
if(!length(baseturfs))
baseturfs = list(baseturfs)
if(!istype(src, /turf/closed))
baseturfs += type
baseturfs += new_baseturfs
return ChangeTurf(fake_turf_type, null, flags)
if(!length(baseturfs))
baseturfs = list(baseturfs)
if(!istype(src, /turf/closed))
baseturfs += type
var/turf/change_type
if(length(new_baseturfs))
change_type = new_baseturfs[new_baseturfs.len]
new_baseturfs.len--
if(new_baseturfs.len)
baseturfs += new_baseturfs
else
change_type = new_baseturfs
return ChangeTurf(change_type, null, flags)
// Copy an existing turf and put it on top
// Returns the new turf
/turf/proc/CopyOnTop(turf/copytarget, ignore_bottom=1, depth=INFINITY, copy_air = FALSE)
var/list/new_baseturfs = list()
new_baseturfs += baseturfs
new_baseturfs += type
if(depth)
var/list/target_baseturfs
if(length(copytarget.baseturfs))
// with default inputs this would be Copy(clamp(2, -INFINITY, baseturfs.len))
// Don't forget a lower index is lower in the baseturfs stack, the bottom is baseturfs[1]
target_baseturfs = copytarget.baseturfs.Copy(clamp(1 + ignore_bottom, 1 + copytarget.baseturfs.len - depth, copytarget.baseturfs.len))
else if(!ignore_bottom)
target_baseturfs = list(copytarget.baseturfs)
if(target_baseturfs)
target_baseturfs -= new_baseturfs & GLOB.blacklisted_automated_baseturfs
new_baseturfs += target_baseturfs
var/turf/newT = copytarget.copyTurf(src, copy_air)
newT.baseturfs = new_baseturfs
return newT
//If you modify this function, ensure it works correctly with lateloaded map templates.
/turf/proc/AfterChange(flags) //called after a turf has been replaced in ChangeTurf()
levelupdate()
if(flags & CHANGETURF_RECALC_ADJACENT)
ImmediateCalculateAdjacentTurfs()
else
CALCULATE_ADJACENT_TURFS(src)
//update firedoor adjacency
var/list/turfs_to_check = get_adjacent_open_turfs(src) | src
for(var/I in turfs_to_check)
var/turf/T = I
for(var/obj/machinery/door/firedoor/FD in T)
FD.CalculateAffectingAreas()
HandleTurfChange(src)
/turf/open/AfterChange(flags)
..()
RemoveLattice()
if(!(flags & (CHANGETURF_IGNORE_AIR | CHANGETURF_INHERIT_AIR)))
Assimilate_Air()
//////Assimilate Air//////
/turf/open/proc/Assimilate_Air()
var/turf_count = LAZYLEN(atmos_adjacent_turfs)
if(blocks_air || !turf_count) //if there weren't any open turfs, no need to update.
return
var/datum/gas_mixture/total = new//Holders to assimilate air from nearby turfs
for(var/T in atmos_adjacent_turfs)
var/turf/open/S = T
if(!S.air)
continue
total.merge(S.air)
air.copy_from(total.remove_ratio(1/turf_count))
SSair.add_to_active(src)
/turf/proc/ReplaceWithLattice()
ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
new /obj/structure/lattice(locate(x, y, z))