You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

331 lines
11 KiB

  1. // This is a list of turf types we dont want to assign to baseturfs unless through initialization or explicitly
  2. GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
  3. /turf/open/space,
  4. /turf/baseturf_bottom,
  5. )))
  6. /turf/proc/empty(turf_type=/turf/open/space, baseturf_type, list/ignore_typecache, flags)
  7. // Remove all atoms except observers, landmarks, docking ports
  8. var/static/list/ignored_atoms = typecacheof(list(/mob/dead, /obj/effect/landmark, /obj/docking_port, /atom/movable/lighting_object))
  9. var/list/allowed_contents = typecache_filter_list_reverse(GetAllContentsIgnoring(ignore_typecache), ignored_atoms)
  10. allowed_contents -= src
  11. for(var/i in 1 to allowed_contents.len)
  12. var/thing = allowed_contents[i]
  13. qdel(thing, force=TRUE)
  14. if(turf_type)
  15. var/turf/newT = ChangeTurf(turf_type, baseturf_type, flags)
  16. SSair.remove_from_active(newT)
  17. CALCULATE_ADJACENT_TURFS(newT)
  18. SSair.add_to_active(newT,1)
  19. /turf/proc/copyTurf(turf/T)
  20. if(T.type != type)
  21. var/obj/O
  22. 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
  23. O = new()
  24. O.underlays.Add(T)
  25. T.ChangeTurf(type)
  26. if(underlays.len)
  27. T.underlays = O.underlays
  28. if(T.icon_state != icon_state)
  29. T.icon_state = icon_state
  30. if(T.icon != icon)
  31. T.icon = icon
  32. if(color)
  33. T.atom_colours = atom_colours.Copy()
  34. T.update_atom_colour()
  35. if(T.dir != dir)
  36. T.setDir(dir)
  37. return T
  38. /turf/open/copyTurf(turf/T, copy_air = FALSE)
  39. . = ..()
  40. if (isopenturf(T))
  41. var/datum/component/wet_floor/slip = GetComponent(/datum/component/wet_floor)
  42. if(slip)
  43. var/datum/component/wet_floor/WF = T.AddComponent(/datum/component/wet_floor)
  44. WF.InheritComponent(slip)
  45. if (copy_air)
  46. var/turf/open/openTurf = T
  47. openTurf.air.copy_from(air)
  48. //wrapper for ChangeTurf()s that you want to prevent/affect without overriding ChangeTurf() itself
  49. /turf/proc/TerraformTurf(path, new_baseturf, flags)
  50. return ChangeTurf(path, new_baseturf, flags)
  51. // Creates a new turf
  52. // new_baseturfs can be either a single type or list of types, formated the same as baseturfs. see turf.dm
  53. /turf/proc/ChangeTurf(path, list/new_baseturfs, flags)
  54. switch(path)
  55. if(null)
  56. return
  57. if(/turf/baseturf_bottom)
  58. path = SSmapping.level_trait(z, ZTRAIT_BASETURF) || /turf/open/space
  59. if (!ispath(path))
  60. path = text2path(path)
  61. if (!ispath(path))
  62. warning("Z-level [z] has invalid baseturf '[SSmapping.level_trait(z, ZTRAIT_BASETURF)]'")
  63. path = /turf/open/space
  64. if(/turf/open/space/basic)
  65. // basic doesn't initialize and this will cause issues
  66. // no warning though because this can happen naturaly as a result of it being built on top of
  67. path = /turf/open/space
  68. if(!GLOB.use_preloader && path == type && !(flags & CHANGETURF_FORCEOP)) // Don't no-op if the map loader requires it to be reconstructed
  69. return src
  70. if(flags & CHANGETURF_SKIP)
  71. return new path(src)
  72. var/old_opacity = opacity
  73. var/old_dynamic_lighting = dynamic_lighting
  74. var/old_affecting_lights = affecting_lights
  75. var/old_lighting_object = lighting_object
  76. var/old_corners = corners
  77. var/old_exl = explosion_level
  78. var/old_exi = explosion_id
  79. var/old_bp = blueprint_data
  80. blueprint_data = null
  81. var/list/old_baseturfs = baseturfs
  82. var/list/transferring_comps = list()
  83. SEND_SIGNAL(src, COMSIG_TURF_CHANGE, path, new_baseturfs, flags, transferring_comps)
  84. for(var/i in transferring_comps)
  85. var/datum/component/comp = i
  86. comp.RemoveComponent()
  87. changing_turf = TRUE
  88. qdel(src) //Just get the side effects and call Destroy
  89. var/turf/W = new path(src)
  90. for(var/i in transferring_comps)
  91. W.TakeComponent(i)
  92. if(new_baseturfs)
  93. W.baseturfs = new_baseturfs
  94. else
  95. W.baseturfs = old_baseturfs
  96. W.explosion_id = old_exi
  97. W.explosion_level = old_exl
  98. if(!(flags & CHANGETURF_DEFER_CHANGE))
  99. W.AfterChange(flags)
  100. W.blueprint_data = old_bp
  101. if(SSlighting.initialized)
  102. recalc_atom_opacity()
  103. lighting_object = old_lighting_object
  104. affecting_lights = old_affecting_lights
  105. corners = old_corners
  106. if (old_opacity != opacity || dynamic_lighting != old_dynamic_lighting)
  107. reconsider_lights()
  108. if (dynamic_lighting != old_dynamic_lighting)
  109. if (IS_DYNAMIC_LIGHTING(src))
  110. lighting_build_overlay()
  111. else
  112. lighting_clear_overlay()
  113. for(var/turf/open/space/S in RANGE_TURFS(1, src)) //RANGE_TURFS is in code\__HELPERS\game.dm
  114. S.update_starlight()
  115. SSdemo.mark_turf(W)
  116. return W
  117. /turf/open/ChangeTurf(path, list/new_baseturfs, flags) //Resist the temptation to make this default to keeping air.
  118. if ((flags & CHANGETURF_INHERIT_AIR) && ispath(path, /turf/open))
  119. SSair.remove_from_active(src)
  120. var/datum/gas_mixture/stashed_air = new()
  121. stashed_air.copy_from(air)
  122. . = ..()
  123. if (!.) // changeturf failed or didn't do anything
  124. QDEL_NULL(stashed_air)
  125. return
  126. var/turf/open/newTurf = .
  127. newTurf.air.copy_from(stashed_air)
  128. QDEL_NULL(stashed_air)
  129. SSair.add_to_active(newTurf)
  130. else
  131. if(ispath(path,/turf/closed))
  132. flags |= CHANGETURF_RECALC_ADJACENT
  133. return ..()
  134. // Take off the top layer turf and replace it with the next baseturf down
  135. /turf/proc/ScrapeAway(amount=1, flags)
  136. if(!amount)
  137. return
  138. if(length(baseturfs))
  139. var/list/new_baseturfs = baseturfs.Copy()
  140. var/turf_type = new_baseturfs[max(1, new_baseturfs.len - amount + 1)]
  141. while(ispath(turf_type, /turf/baseturf_skipover))
  142. amount++
  143. if(amount > new_baseturfs.len)
  144. CRASH("The bottomost baseturf of a turf is a skipover [src]([type])")
  145. turf_type = new_baseturfs[max(1, new_baseturfs.len - amount + 1)]
  146. new_baseturfs.len -= min(amount, new_baseturfs.len - 1) // No removing the very bottom
  147. if(new_baseturfs.len == 1)
  148. new_baseturfs = new_baseturfs[1]
  149. return ChangeTurf(turf_type, new_baseturfs, flags)
  150. if(baseturfs == type)
  151. return src
  152. return ChangeTurf(baseturfs, baseturfs, flags) // The bottom baseturf will never go away
  153. // Take the input as baseturfs and put it underneath the current baseturfs
  154. // If fake_turf_type is provided and new_baseturfs is not the baseturfs list will be created identical to the turf type's
  155. // If both or just new_baseturfs is provided they will be inserted below the existing baseturfs
  156. /turf/proc/PlaceOnBottom(list/new_baseturfs, turf/fake_turf_type)
  157. if(fake_turf_type)
  158. if(!new_baseturfs)
  159. if(!length(baseturfs))
  160. baseturfs = list(baseturfs)
  161. var/list/old_baseturfs = baseturfs.Copy()
  162. assemble_baseturfs(fake_turf_type)
  163. if(!length(baseturfs))
  164. baseturfs = list(baseturfs)
  165. baseturfs -= baseturfs & GLOB.blacklisted_automated_baseturfs
  166. baseturfs += old_baseturfs
  167. return
  168. else if(!length(new_baseturfs))
  169. new_baseturfs = list(new_baseturfs, fake_turf_type)
  170. else
  171. new_baseturfs += fake_turf_type
  172. if(!length(baseturfs))
  173. baseturfs = list(baseturfs)
  174. baseturfs.Insert(1, new_baseturfs)
  175. // Make a new turf and put it on top
  176. // The args behave identical to PlaceOnBottom except they go on top
  177. // Things placed on top of closed turfs will ignore the topmost closed turf
  178. // Returns the new turf
  179. /turf/proc/PlaceOnTop(list/new_baseturfs, turf/fake_turf_type, flags)
  180. var/area/turf_area = loc
  181. if(new_baseturfs && !length(new_baseturfs))
  182. new_baseturfs = list(new_baseturfs)
  183. flags = turf_area.PlaceOnTopReact(new_baseturfs, fake_turf_type, flags) // A hook so areas can modify the incoming args
  184. var/turf/newT
  185. if(flags & CHANGETURF_SKIP) // We haven't been initialized
  186. if(flags_1 & INITIALIZED_1)
  187. stack_trace("CHANGETURF_SKIP was used in a PlaceOnTop call for a turf that's initialized. This is a mistake. [src]([type])")
  188. assemble_baseturfs()
  189. if(fake_turf_type)
  190. if(!new_baseturfs) // If no baseturfs list then we want to create one from the turf type
  191. if(!length(baseturfs))
  192. baseturfs = list(baseturfs)
  193. var/list/old_baseturfs = baseturfs.Copy()
  194. if(!istype(src, /turf/closed))
  195. old_baseturfs += type
  196. newT = ChangeTurf(fake_turf_type, null, flags)
  197. newT.assemble_baseturfs(initial(fake_turf_type.baseturfs)) // The baseturfs list is created like roundstart
  198. if(!length(newT.baseturfs))
  199. newT.baseturfs = list(baseturfs)
  200. newT.baseturfs -= GLOB.blacklisted_automated_baseturfs
  201. newT.baseturfs.Insert(1, old_baseturfs) // The old baseturfs are put underneath
  202. return newT
  203. if(!length(baseturfs))
  204. baseturfs = list(baseturfs)
  205. if(!istype(src, /turf/closed))
  206. baseturfs += type
  207. baseturfs += new_baseturfs
  208. return ChangeTurf(fake_turf_type, null, flags)
  209. if(!length(baseturfs))
  210. baseturfs = list(baseturfs)
  211. if(!istype(src, /turf/closed))
  212. baseturfs += type
  213. var/turf/change_type
  214. if(length(new_baseturfs))
  215. change_type = new_baseturfs[new_baseturfs.len]
  216. new_baseturfs.len--
  217. if(new_baseturfs.len)
  218. baseturfs += new_baseturfs
  219. else
  220. change_type = new_baseturfs
  221. return ChangeTurf(change_type, null, flags)
  222. // Copy an existing turf and put it on top
  223. // Returns the new turf
  224. /turf/proc/CopyOnTop(turf/copytarget, ignore_bottom=1, depth=INFINITY, copy_air = FALSE)
  225. var/list/new_baseturfs = list()
  226. new_baseturfs += baseturfs
  227. new_baseturfs += type
  228. if(depth)
  229. var/list/target_baseturfs
  230. if(length(copytarget.baseturfs))
  231. // with default inputs this would be Copy(clamp(2, -INFINITY, baseturfs.len))
  232. // Don't forget a lower index is lower in the baseturfs stack, the bottom is baseturfs[1]
  233. target_baseturfs = copytarget.baseturfs.Copy(clamp(1 + ignore_bottom, 1 + copytarget.baseturfs.len - depth, copytarget.baseturfs.len))
  234. else if(!ignore_bottom)
  235. target_baseturfs = list(copytarget.baseturfs)
  236. if(target_baseturfs)
  237. target_baseturfs -= new_baseturfs & GLOB.blacklisted_automated_baseturfs
  238. new_baseturfs += target_baseturfs
  239. var/turf/newT = copytarget.copyTurf(src, copy_air)
  240. newT.baseturfs = new_baseturfs
  241. return newT
  242. //If you modify this function, ensure it works correctly with lateloaded map templates.
  243. /turf/proc/AfterChange(flags) //called after a turf has been replaced in ChangeTurf()
  244. levelupdate()
  245. if(flags & CHANGETURF_RECALC_ADJACENT)
  246. ImmediateCalculateAdjacentTurfs()
  247. else
  248. CALCULATE_ADJACENT_TURFS(src)
  249. //update firedoor adjacency
  250. var/list/turfs_to_check = get_adjacent_open_turfs(src) | src
  251. for(var/I in turfs_to_check)
  252. var/turf/T = I
  253. for(var/obj/machinery/door/firedoor/FD in T)
  254. FD.CalculateAffectingAreas()
  255. queue_smooth_neighbors(src)
  256. HandleTurfChange(src)
  257. /turf/open/AfterChange(flags)
  258. ..()
  259. RemoveLattice()
  260. if(!(flags & (CHANGETURF_IGNORE_AIR | CHANGETURF_INHERIT_AIR)))
  261. Assimilate_Air()
  262. //////Assimilate Air//////
  263. /turf/open/proc/Assimilate_Air()
  264. var/turf_count = LAZYLEN(atmos_adjacent_turfs)
  265. if(blocks_air || !turf_count) //if there weren't any open turfs, no need to update.
  266. return
  267. var/datum/gas_mixture/total = new//Holders to assimilate air from nearby turfs
  268. var/list/total_gases = total.gases
  269. for(var/T in atmos_adjacent_turfs)
  270. var/turf/open/S = T
  271. if(!S.air)
  272. continue
  273. var/list/S_gases = S.air.gases
  274. for(var/id in S_gases)
  275. ASSERT_GAS(id, total)
  276. total_gases[id][MOLES] += S_gases[id][MOLES]
  277. total.temperature += S.air.temperature
  278. air.copy_from(total)
  279. var/list/air_gases = air.gases
  280. for(var/id in air_gases)
  281. air_gases[id][MOLES] /= turf_count //Averages contents of the turfs, ignoring walls and the like
  282. air.temperature /= turf_count
  283. SSair.add_to_active(src)
  284. /turf/proc/ReplaceWithLattice()
  285. ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
  286. new /obj/structure/lattice(locate(x, y, z))