shuttles are almost fixed i think

This commit is contained in:
Chubbygummibear
2023-12-20 13:08:09 -08:00
parent 863e1b776d
commit 046058827c
57 changed files with 690 additions and 424 deletions

View File

@@ -60,20 +60,23 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
//turf-only flags
#define NOJAUNT_1 (1<<0)
/// If a turf is an usused reservation turf awaiting assignment
#define UNUSED_RESERVATION_TURF_1 (1<<1)
/// If a turf is a reserved turf
#define RESERVATION_TURF_1 (1<<2)
/// If a turf can be made dirty at roundstart. This is also used in areas.
#define CAN_BE_DIRTY_1 (1<<2)
#define CAN_BE_DIRTY_1 (1<<3)
/// Blocks lava rivers being generated on the turf
#define NO_LAVA_GEN_1 (1<<6)
#define NO_LAVA_GEN_1 (1<<3)
/// Blocks ruins spawning on the turf
#define NO_RUINS_1 (1<<18)
#define NO_RUINS_1 (1<<4)
/// Blocks this turf from being rusted
#define NO_RUST (1<<19)
#define NO_RUST (1<<5)
/// If this atom has experienced a decal element "init finished" sourced appearance update
/// We use this to ensure stacked decals don't double up appearance updates for no rasin
/// Flag as an optimization, don't make this a trait without profiling
/// Yes I know this is a stupid flag, no you can't take him from me
#define DECAL_INIT_UPDATE_EXPERIENCED_1 (1<<20)
#define DECAL_INIT_UPDATE_EXPERIENCED_1 (1<<6)
//AREA FLAGS
/// If blobs can spawn there and if it counts towards their score.

View File

@@ -16,8 +16,23 @@ As of 2018-02-04, the typical z-levels for a single-level station are:
12: Empty space
13: Transit space
Multi-Z stations are supported and multi-Z mining and away missions would
require only minor tweaks.
Multi-Z stations are supported and Multi-Z mining and away missions would
require only minor tweaks. They also handle their Z-Levels differently on their
own case by case basis.
This information will absolutely date quickly with how we handle Z-Levels, and will
continue to handle them in the future. Currently, you can go into the Debug tab
of your stat-panel (in game) and hit "Mapping verbs - Enable". You will then get a new tab
called "Mapping", as well as access to the verb "Debug-Z-Levels". Although the information
presented in this comment is factual for the time it was written for, it's ill-advised
to trust the words presented within.
We also provide this information to you so that you can have an at-a-glance look at how
Z-Levels are arranged. It is extremely ill-advised to ever use the location of a Z-Level
to assign traits to it or use it in coding. Use Z-Traits (ZTRAITs) for these.
If you want to start toying around with Z-Levels, do not take these words for fact.
Always compile, always use that verb, and always make sure that it works for what you want to do.
*/
// helpers for modifying jobs, used in various job_changes.dm files
@@ -27,6 +42,23 @@ require only minor tweaks.
#define SPACERUIN_MAP_EDGE_PAD 15
/// Distance from edge to move to another z-level
#define TRANSITIONEDGE 7
// Maploader bounds indices
/// The maploader index for the maps minimum x
#define MAP_MINX 1
/// The maploader index for the maps minimum y
#define MAP_MINY 2
/// The maploader index for the maps minimum z
#define MAP_MINZ 3
/// The maploader index for the maps maximum x
#define MAP_MAXX 4
/// The maploader index for the maps maximum y
#define MAP_MAXY 5
/// The maploader index for the maps maximum z
#define MAP_MAXZ 6
// traits
// boolean - marks a level as having that property if present
#define ZTRAIT_CENTCOM "CentCom"

View File

@@ -57,8 +57,6 @@
#define MANIFEST_ERROR_CONTENTS 2
#define MANIFEST_ERROR_ITEM 4
#define TRANSITIONEDGE 7 //Distance from edge to move to another z-level
#define BE_CLOSE TRUE //in the case of a silicon, to select if they need to be next to the atom
#define NO_DEXTERY TRUE //if other mobs (monkeys, aliens, etc) can use this
#define NO_TK TRUE
@@ -226,14 +224,6 @@ GLOBAL_LIST_INIT(donor_pdas, list(PDA_COLOR_NORMAL, PDA_COLOR_TRANSPARENT, PDA_C
//Just space
#define SPACE_ICON_STATE "[((x + y) ^ ~(x * y) + z) % 25]"
// Maploader bounds indices
#define MAP_MINX 1
#define MAP_MINY 2
#define MAP_MINZ 3
#define MAP_MAXX 4
#define MAP_MAXY 5
#define MAP_MAXZ 6
// Defib stats
#define DEFIB_TIME_LIMIT 15 MINUTES

View File

@@ -1,8 +1,8 @@
/// Attempt to get the turf below the provided one according to Z traits
#define GET_TURF_BELOW(turf) ( \
(turf.turf_flags & RESERVATION_TURF) ? SSmapping.get_reservation_from_turf(turf)?.get_turf_below(turf) : \
(turf.flags_1 & RESERVATION_TURF_1) ? SSmapping.get_reservation_from_turf(turf)?.get_turf_below(turf) : \
(!(turf) || !length(SSmapping.multiz_levels) || !SSmapping.multiz_levels[(turf).z][Z_LEVEL_DOWN]) ? null : get_step((turf), DOWN))
/// Attempt to get the turf above the provided one according to Z traits
#define GET_TURF_ABOVE(turf) ( \
(turf.turf_flags & RESERVATION_TURF) ? SSmapping.get_reservation_from_turf(turf)?.get_turf_above(turf) : \
(turf.flags_1 & RESERVATION_TURF_1) ? SSmapping.get_reservation_from_turf(turf)?.get_turf_above(turf) : \
(!(turf) || !length(SSmapping.multiz_levels) || !SSmapping.multiz_levels[(turf).z][Z_LEVEL_UP]) ? null : get_step((turf), UP))

View File

@@ -8,3 +8,6 @@
* Uses MAPTEXT to format antag points into a more appealing format
*/
#define ANTAG_MAPTEXT(value, color) MAPTEXT("<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='[color]'>[round(value)]</font></div>")
/// Removes characters incompatible with file names.
#define SANITIZE_FILENAME(text) (GLOB.filename_forbidden_chars.Replace(text, ""))

View File

@@ -1,7 +1,7 @@
#define CHANGETURF_DEFER_CHANGE (1<<0)
#define CHANGETURF_IGNORE_AIR (1<<1) // This flag prevents changeturf from gathering air from nearby turfs to fill the new turf with an approximation of local air
#define CHANGETURF_FORCEOP (1<<2)
#define CHANGETURF_SKIP (1<<3) // A flag for PlaceOnTop to just instance the new turf instead of calling ChangeTurf. Used for uninitialized turfs NOTHING ELSE
#define CHANGETURF_SKIP (1<<3) // A flag for place_on_top to just instance the new turf instead of calling ChangeTurf. Used for uninitialized turfs NOTHING ELSE
#define CHANGETURF_INHERIT_AIR (1<<4) // Inherit air from previous turf. Implies CHANGETURF_IGNORE_AIR
#define CHANGETURF_RECALC_ADJACENT (1<<5) //Immediately recalc adjacent atmos turfs instead of queuing.
#define CHANGETURF_TRAPDOOR_INDUCED (1<<6) // Caused by a trapdoor, for trapdoor to know that this changeturf was caused by itself

View File

@@ -158,6 +158,7 @@ DEFINE_BITFIELD(resistance_flags, list(
DEFINE_BITFIELD(flags_1, list(
"NOJAUNT_1" = NOJAUNT_1,
"UNUSED_RESERVATION_TURF_1" = UNUSED_RESERVATION_TURF_1,
"RESERVATION_TURF_1" = RESERVATION_TURF_1,
"CAN_BE_DIRTY_1" = CAN_BE_DIRTY_1,
"HEAR_1" = HEAR_1,
"CHECK_RICOCHET_1" = CHECK_RICOCHET_1,

View File

@@ -6,3 +6,8 @@ GLOBAL_DATUM_INIT(is_email, /regex, regex("\[a-z0-9_-]+@\[a-z0-9_-]+.\[a-z0-9_-]
GLOBAL_DATUM_INIT(is_alphanumeric, /regex, regex("\[a-z0-9]+", "i"))
GLOBAL_DATUM_INIT(is_punctuation, /regex, regex("\[.!?]+", "i"))
GLOBAL_DATUM_INIT(is_color, /regex, regex("^#\[0-9a-fA-F]{6}$"))
//All characters forbidden by filenames: ", \, \n, \t, /, ?, %, *, :, |, <, >, ..
GLOBAL_DATUM_INIT(filename_forbidden_chars, /regex, regex(@{""|[\\\n\t/?%*:|<>]|\.\."}, "g"))
GLOBAL_PROTECT(filename_forbidden_chars)
// had to use the OR operator for quotes instead of putting them in the character class because it breaks the syntax highlighting otherwise.

View File

@@ -132,16 +132,17 @@ SUBSYSTEM_DEF(mapping)
require_area_resort()
process_teleport_locs() //Sets up the wizard teleport locations
preloadTemplates()
run_map_generation()
#ifndef LOWMEMORYMODE
// Create space ruin levels
while (space_levels_so_far < config.space_ruin_levels)
++space_levels_so_far
add_new_zlevel("Empty Area [space_levels_so_far]", ZTRAITS_SPACE)
// and one level with no ruins
for (var/i in 1 to config.space_empty_levels)
++space_levels_so_far
// Create empty space levels
while (space_levels_so_far < config.space_empty_levels + config.space_ruin_levels)
empty_space = add_new_zlevel("Empty Area [space_levels_so_far]", list(ZTRAIT_LINKAGE = CROSSLINKED))
++space_levels_so_far
// Pick a random away mission.
if(CONFIG_GET(flag/roundstart_away))
@@ -194,7 +195,7 @@ SUBSYSTEM_DEF(mapping)
message_admins("A shuttle arena failed to load!")
log_game("A shuttle arena failed to load!")
#endif
run_map_generation()
// Add the transit level
var/datum/space_level/base_transit = add_reservation_zlevel()
require_area_resort()
@@ -218,7 +219,8 @@ SUBSYSTEM_DEF(mapping)
var/packetlen = length(packet)
while(packetlen)
if(MC_TICK_CHECK)
lists_to_reserve.Cut(1, index)
if(index)
lists_to_reserve.Cut(1, index)
return
var/turf/T = packet[packetlen]
T.empty(RESERVED_TURF_TYPE, RESERVED_TURF_TYPE, null, TRUE)
@@ -235,6 +237,25 @@ SUBSYSTEM_DEF(mapping)
index++
lists_to_reserve.Cut(1, index)
/datum/controller/subsystem/mapping/proc/generate_z_level_linkages()
for(var/z_level in 1 to length(z_list))
generate_linkages_for_z_level(z_level)
/datum/controller/subsystem/mapping/proc/generate_linkages_for_z_level(z_level)
if(!isnum(z_level) || z_level <= 0)
return FALSE
if(multiz_levels.len < z_level)
multiz_levels.len = z_level
var/z_above = level_trait(z_level, ZTRAIT_UP)
var/z_below = level_trait(z_level, ZTRAIT_DOWN)
if(!(z_above == TRUE || z_above == FALSE || z_above == null) || !(z_below == TRUE || z_below == FALSE || z_below == null))
stack_trace("Warning, numeric mapping offsets are deprecated. Instead, mark z level connections by setting UP/DOWN to true if the connection is allowed")
multiz_levels[z_level] = new /list(LARGEST_Z_LEVEL_INDEX)
multiz_levels[z_level][Z_LEVEL_UP] = !!z_above
multiz_levels[z_level][Z_LEVEL_DOWN] = !!z_below
/datum/controller/subsystem/mapping/proc/wipe_reservations(wipe_safety_delay = 100)
if(clearing_reserved_turfs || !initialized) //in either case this is just not needed.
return
@@ -264,6 +285,10 @@ SUBSYSTEM_DEF(mapping)
returning += M
qdel(T, TRUE)
/datum/controller/subsystem/mapping/proc/get_reservation_from_turf(turf/T)
RETURN_TYPE(/datum/turf_reservation)
return used_turfs[T]
/* Nuke threats, for making the blue tiles on the station go RED
Used by the AI doomsday and the self destruct nuke.
*/
@@ -348,7 +373,10 @@ SUBSYSTEM_DEF(mapping)
// load the maps
for (var/P in parsed_maps)
var/datum/parsed_map/pm = P
if (!pm.load(1, 1, start_z + parsed_maps[P], no_changeturf = TRUE, new_z = TRUE))
var/bounds = pm.bounds
var/x_offset = bounds ? round(world.maxx / 2 - bounds[MAP_MAXX] / 2) + 1 : 1
var/y_offset = bounds ? round(world.maxy / 2 - bounds[MAP_MAXY] / 2) + 1 : 1
if (!pm.load(x_offset, y_offset, start_z + parsed_maps[P], no_changeturf = TRUE, new_z = TRUE))
errorList |= pm.original_path
if(!silent)
INIT_ANNOUNCE("Loaded [name] in [(REALTIMEOFDAY - start_time)/10]s!")
@@ -495,9 +523,9 @@ GLOBAL_LIST_EMPTY(the_station_areas)
/datum/controller/subsystem/mapping/proc/preloadRuinTemplates()
// Still supporting bans by filename
var/list/banned = generateMapList("[global.config.directory]/lavaruinblacklist.txt")
banned += generateMapList("[global.config.directory]/spaceruinblacklist.txt")
banned += generateMapList("[global.config.directory]/iceruinblacklist.txt")
var/list/banned = generateMapList("lavaruinblacklist.txt")
banned += generateMapList("spaceruinblacklist.txt")
banned += generateMapList("iceruinblacklist.txt")
for(var/item in sortList(subtypesof(/datum/map_template/ruin), /proc/cmp_ruincost_priority))
var/datum/map_template/ruin/ruin_type = item
@@ -524,7 +552,7 @@ GLOBAL_LIST_EMPTY(the_station_areas)
station_room_templates[R.name] = R //yogs
/datum/controller/subsystem/mapping/proc/preloadShuttleTemplates()
var/list/unbuyable = generateMapList("[global.config.directory]/unbuyableshuttles.txt")
var/list/unbuyable = generateMapList("unbuyableshuttles.txt")
for(var/item in subtypesof(/datum/map_template/shuttle))
var/datum/map_template/shuttle/shuttle_type = item
@@ -857,10 +885,6 @@ GLOBAL_LIST_EMPTY(the_station_areas)
GLOB.default_lighting_underlays_by_z.len = z_level
GLOB.default_lighting_underlays_by_z[z_level] = mutable_appearance(LIGHTING_ICON, "transparent", z_level * 0.01, null, LIGHTING_PLANE, 255, RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM, offset_const = GET_Z_PLANE_OFFSET(z_level))
/datum/controller/subsystem/mapping/proc/get_reservation_from_turf(turf/T)
RETURN_TYPE(/datum/turf_reservation)
return used_turfs[T]
/datum/controller/subsystem/mapping/proc/get_map_weights()
var/list/previous_maps = list()

View File

@@ -521,10 +521,10 @@ SUBSYSTEM_DEF(shuttle)
// Then create a transit docking port in the middle
var/coords = M.return_coords(0, 0, dock_dir)
/* 0------2
| |
| |
| x |
3------1
* | |
* | |
* | x |
* 3------1
*/
var/x0 = coords[1]
@@ -541,6 +541,7 @@ SUBSYSTEM_DEF(shuttle)
var/turf/midpoint = locate(transit_x, transit_y, bottomleft.z)
if(!midpoint)
qdel(proposal)
return FALSE
var/area/old_area = midpoint.loc
old_area.turfs_to_uncontain += proposal.reserved_turfs
@@ -718,39 +719,42 @@ SUBSYSTEM_DEF(shuttle)
QDEL_NULL(preview_reservation)
if(!preview_shuttle)
if(load_template(loading_template))
preview_shuttle.linkup(loading_template, destination_port)
load_template(loading_template)
preview_template = loading_template
// get the existing shuttle information, if any
var/timer = 0
var/mode = SHUTTLE_IDLE
var/obj/docking_port/stationary/D
var/obj/docking_port/stationary/dest_dock
if(istype(destination_port))
D = destination_port
else if(existing_shuttle)
dest_dock = destination_port
else if(existing_shuttle && replace)
timer = existing_shuttle.timer
mode = existing_shuttle.mode
D = existing_shuttle.get_docked()
dest_dock = existing_shuttle.get_docked()
if(!D)
if(!dest_dock)
dest_dock = generate_transit_dock(preview_shuttle)
if(!dest_dock)
CRASH("No dock found for preview shuttle ([preview_template.name]), aborting.")
var/result = preview_shuttle.canDock(D)
var/result = preview_shuttle.canDock(dest_dock)
// truthy value means that it cannot dock for some reason
// but we can ignore the someone else docked error because we'll
// be moving into their place shortly
if((result != SHUTTLE_CAN_DOCK) && (result != SHUTTLE_SOMEONE_ELSE_DOCKED))
WARNING("Template shuttle [preview_shuttle] cannot dock at [D] ([result]).")
return
CRASH("Template shuttle [preview_shuttle] cannot dock at [dest_dock] ([result]).")
if(existing_shuttle)
existing_shuttle.jumpToNullSpace()
preview_shuttle.register(replace)
var/list/force_memory = preview_shuttle.movement_force
preview_shuttle.movement_force = list("KNOCKDOWN" = 0, "THROW" = 0)
preview_shuttle.initiate_docking(D)
preview_shuttle.mode = SHUTTLE_PREARRIVAL//No idle shuttle moving. Transit dock get removed if shuttle moves too long.
preview_shuttle.initiate_docking(dest_dock)
preview_shuttle.movement_force = force_memory
. = preview_shuttle
@@ -760,7 +764,7 @@ SUBSYSTEM_DEF(shuttle)
preview_shuttle.timer = timer
preview_shuttle.mode = mode
preview_shuttle.register()
preview_shuttle.postregister(replace)
// TODO indicate to the user that success happened, rather than just
// blanking the modification tab

View File

@@ -4,25 +4,33 @@
/datum/component/rot/Initialize(new_amount)
if(!isatom(parent))
return COMPONENT_INCOMPATIBLE
if(new_amount)
amount = new_amount
if(isliving(parent))
var/mob/living/living_parent = parent
//I think this can break in cases where someone becomes a robot post death, but I uh, I don't know how to account for that
if(!(living_parent.mob_biotypes & (MOB_ORGANIC|MOB_UNDEAD)))
return COMPONENT_INCOMPATIBLE
START_PROCESSING(SSprocessing, src)
/datum/component/rot/process()
var/atom/A = parent
var/turf/open/T = get_turf(A)
if(!istype(T) || T.return_air().return_pressure() > (WARNING_HIGH_PRESSURE - 10))
var/turf/T = get_turf(A)
if(QDELETED(T) || !isopenturf(T))
return
var/datum/gas_mixture/turf_air = T.return_air()
if(!turf_air)
return
if(!istype(T) || turf_air.return_pressure() > (WARNING_HIGH_PRESSURE - 10))
return
var/area/area = get_area(T)
if(area.outdoors)
return
var/datum/gas_mixture/turf_air = T.return_air()
if(!turf_air)
return
var/datum/gas_mixture/stank_breath = T.remove_air(1 / turf_air.return_volume() * turf_air.total_moles())
if(!stank_breath)
return

View File

@@ -0,0 +1,41 @@
/**
* Creates a mirage effect allowing you to see around the world border, by adding the opposite side to its vis_contents.
*/
/datum/element/mirage_border
/datum/element/mirage_border/Attach(datum/target, turf/target_turf, direction, range=world.view)
. = ..()
if(!isturf(target))
return ELEMENT_INCOMPATIBLE
#ifdef TESTING
// This is a highly used proc, and these error states never occur, so limit it to testing.
// If something goes wrong it will runtime anyway.
if(!target_turf || !istype(target_turf) || !direction)
stack_trace("[type] improperly attached with the following args: target=\[[target_turf]\], direction=\[[direction]\], range=\[[range]\]")
return ELEMENT_INCOMPATIBLE
#endif
var/atom/movable/mirage_holder/holder = new(target)
var/x = target_turf.x
var/y = target_turf.y
var/z = clamp(target_turf.z, 1, world.maxz)
var/turf/southwest = locate(clamp(x - (direction & WEST ? range : 0), 1, world.maxx), clamp(y - (direction & SOUTH ? range : 0), 1, world.maxy), z)
var/turf/northeast = locate(clamp(x + (direction & EAST ? range : 0), 1, world.maxx), clamp(y + (direction & NORTH ? range : 0), 1, world.maxy), z)
holder.vis_contents += block(southwest, northeast)
if(direction & SOUTH)
holder.pixel_y -= world.icon_size * range
if(direction & WEST)
holder.pixel_x -= world.icon_size * range
/datum/element/mirage_border/Detach(atom/movable/target)
. = ..()
var/atom/movable/mirage_holder/held = locate() in target.contents
if(held)
qdel(held)
INITIALIZE_IMMEDIATE(/atom/movable/mirage_holder)
// Using /atom/movable because this is a heavily used path
/atom/movable/mirage_holder
name = "Mirage holder"
mouse_opacity = MOUSE_OPACITY_TRANSPARENT

View File

@@ -579,7 +579,7 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list(
playsound(loc, 'sound/weapons/genhit.ogg', 100, 1)
var/turf/open/space/T
for(T in orange(1, src))
T.PlaceOnTop(/turf/open/floor/plating)
T.place_on_top(/turf/open/floor/plating)
else
say("Something slams into the floor around [src] - luckily, it didn't get through!")
playsound(loc, 'sound/effects/bang.ogg', 50, 1)

View File

@@ -447,7 +447,7 @@ GLOBAL_VAR_INIT(cryopods_enabled, FALSE)
if(prob(90))
sleepyhead.adjust_drowsiness(rand(3 SECONDS, 10 SECONDS))
if(prob(75))
sleepyhead.blur_eyes(rand(3, 6))
sleepyhead.adjust_eye_blur(rand(3, 6))
//so much worse
if(prob(66))
sleepyhead.adjust_disgust(rand(25,35))

View File

@@ -212,10 +212,10 @@
for(var/obj/machinery/door/firedoor/FD in here)
qdel(FD)
for(var/turf/closed/T in range(2, src))
here.PlaceOnTop(T.type)
here.place_on_top(T.type)
qdel(src)
return
here.PlaceOnTop(/turf/closed/wall)
here.place_on_top(/turf/closed/wall)
qdel(src)
return
if(10 to 11)

View File

@@ -313,7 +313,7 @@
var/turf/open/space/S = target
occupant_message("Building Floor...")
if(do_after_cooldown(S))
S.PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
S.place_on_top(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
if(play_sound)
playsound(S, 'sound/items/deconstruct.ogg', 50, 1)
chassis.spark_system.start()
@@ -322,7 +322,7 @@
energy_drain = 750
occupant_message("Building Wall...")
if(do_after_cooldown(F))
F.PlaceOnTop(/turf/closed/wall)
F.place_on_top(/turf/closed/wall)
if(play_sound)
playsound(F, 'sound/items/deconstruct.ogg', 50, 1)
chassis.spark_system.start()

View File

@@ -366,7 +366,7 @@
/obj/effect/particle_effect/fluid/foam/metal/smart/make_result() //Smart foam adheres to area borders for walls
var/turf/open/location = loc
if(isspaceturf(location))
location.PlaceOnTop(/turf/open/floor/plating/foam)
location.place_on_top(/turf/open/floor/plating/foam)
for(var/cardinal in GLOB.cardinals)
var/turf/cardinal_turf = get_step(location, cardinal)

View File

@@ -20,9 +20,9 @@
for(var/j = lowBoundY,j<=hiBoundY,j++)
var/turf/T = locate(i,j,z)
if(i == lowBoundX || i == hiBoundX || j == lowBoundY || j == hiBoundY)
T.PlaceOnTop(/turf/closed/wall/vault)
T.place_on_top(/turf/closed/wall/vault)
else
T.PlaceOnTop(/turf/open/floor/vault)
T.place_on_top(/turf/open/floor/vault)
T.icon_state = "[type]vault"
qdel(src)

View File

@@ -217,7 +217,7 @@
var/turf/T = usr.drop_location()
if(!isturf(T))
return
T.PlaceOnTop(R.result_type, flags = CHANGETURF_INHERIT_AIR)
T.place_on_top(R.result_type, flags = CHANGETURF_INHERIT_AIR)
else
O = new R.result_type(usr.drop_location())
if(O)

View File

@@ -84,7 +84,7 @@
/obj/structure/falsewall/proc/ChangeToWall(delete = 1)
var/turf/T = get_turf(src)
T.PlaceOnTop(walltype)
T.place_on_top(walltype)
if(delete)
qdel(src)
return T

View File

@@ -74,7 +74,7 @@
S.use(5)
to_chat(user, span_notice("You add the plating."))
var/turf/T = get_turf(src)
T.PlaceOnTop(/turf/closed/wall/mineral/iron)
T.place_on_top(/turf/closed/wall/mineral/iron)
transfer_fingerprints_to(T)
qdel(src)
return
@@ -108,7 +108,7 @@
S.use(2)
to_chat(user, span_notice("You add the plating."))
var/turf/T = get_turf(src)
T.PlaceOnTop(/turf/closed/wall)
T.place_on_top(/turf/closed/wall)
transfer_fingerprints_to(T)
qdel(src)
return
@@ -138,7 +138,7 @@
S.use(1)
to_chat(user, span_notice("You fully reinforce the wall."))
var/turf/T = get_turf(src)
T.PlaceOnTop(/turf/closed/wall/r_wall)
T.place_on_top(/turf/closed/wall/r_wall)
transfer_fingerprints_to(T)
qdel(src)
return
@@ -182,7 +182,7 @@
S.use(2)
to_chat(user, span_notice("You add the plating."))
var/turf/T = get_turf(src)
T.PlaceOnTop(text2path("/turf/closed/wall/mineral/[M]"))
T.place_on_top(text2path("/turf/closed/wall/mineral/[M]"))
transfer_fingerprints_to(T)
qdel(src)
return
@@ -355,7 +355,7 @@
user.visible_message(span_notice("[user] plates [src] with runed metal."), span_notice("You construct a runed wall."))
R.use(1)
var/turf/T = get_turf(src)
T.PlaceOnTop(/turf/closed/wall/mineral/cult)
T.place_on_top(/turf/closed/wall/mineral/cult)
qdel(src)
else
@@ -382,7 +382,7 @@
switch(passed_mode)
if(RCD_FLOORWALL)
to_chat(user, span_notice("You finish a wall."))
T.PlaceOnTop(/turf/closed/wall)
T.place_on_top(/turf/closed/wall)
qdel(src)
return TRUE
if(RCD_DECONSTRUCT)
@@ -422,7 +422,7 @@
user.visible_message(span_notice("[user] plates [src] with bronze!"), span_notice("You construct a bronze wall."))
B.use(2)
var/turf/T = get_turf(src)
T.PlaceOnTop(/turf/closed/wall/mineral/bronze)
T.place_on_top(/turf/closed/wall/mineral/bronze)
qdel(src)
else

View File

@@ -59,7 +59,7 @@
to_chat(user, span_notice("You build a floor."))
var/turf/T = src.loc
if(isspaceturf(T))
T.PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
T.place_on_top(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
qdel(src)
return TRUE
return FALSE

View File

@@ -1,19 +1,96 @@
/// Places the given turf on the bottom of the turf stack.
/turf/proc/place_on_bottom(turf/bottom_turf)
baseturfs = baseturfs_string_list(
list(initial(bottom_turf.baseturfs), bottom_turf) + baseturfs,
src
)
/// 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 bottommost 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)
/// Places a turf at the top of the stack
/turf/proc/place_on_top(turf/added_layer, flags)
var/list/turf/new_baseturfs = list()
if(baseturfs == type)
return src
new_baseturfs.Add(baseturfs)
if(isopenturf(src))
new_baseturfs.Add(type)
return ChangeTurf(baseturfs, baseturfs, flags) // The bottom baseturf will never go away
return ChangeTurf(added_layer, new_baseturfs, flags)
// 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/place_on_bottom(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 place_on_bottom except they go on top
// Things placed on top of closed turfs will ignore the topmost closed turf
// Returns the new turf
/turf/proc/place_on_top(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 place_on_top 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)
/// Places a turf on top - for map loading
/turf/proc/load_on_top(turf/added_layer, flags)
@@ -22,7 +99,7 @@
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])")
stack_trace("CHANGETURF_SKIP was used in a place_on_top call for a turf that's initialized. This is a mistake. [src]([type])")
assemble_baseturfs()
var/turf/new_turf
@@ -42,6 +119,29 @@
new_turf.baseturfs = baseturfs_string_list(old_baseturfs + (new_turf.baseturfs - GLOB.blacklisted_automated_baseturfs), new_turf)
return new_turf
// 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, flags)
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, flags)
newT.baseturfs = new_baseturfs
return newT
/// Tries to find the given type in baseturfs.
/// If found, returns how deep it is for use in other baseturf procs, or null if it cannot be found.
/// For example, this number can be passed into ScrapeAway to scrape everything until that point.

View File

@@ -91,26 +91,21 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
var/list/old_baseturfs = baseturfs
var/list/post_change_callbacks = list()
SEND_SIGNAL(src, COMSIG_TURF_CHANGE, path, new_baseturfs, flags, post_change_callbacks)
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.ClearFromParent()
changing_turf = TRUE
qdel(src) //Just get the side effects and call Destroy
//We do this here so anything that doesn't want to persist can clear itself
var/list/old_listen_lookup = _listen_lookup?.Copy()
var/list/old_signal_procs = _signal_procs?.Copy()
var/carryover_turf_flags = (RESERVATION_TURF_1 | UNUSED_RESERVATION_TURF_1) & flags_1
var/turf/W = new path(src)
// WARNING WARNING
// Turfs DO NOT lose their signals when they get replaced, REMEMBER THIS
// It's possible because turfs are fucked, and if you have one in a list and it's replaced with another one, the list ref points to the new turf
if(old_listen_lookup)
LAZYOR(W._listen_lookup, old_listen_lookup)
if(old_signal_procs)
LAZYOR(W._signal_procs, old_signal_procs)
for(var/datum/callback/callback as anything in post_change_callbacks)
callback.InvokeAsync(W)
W.flags_1 = carryover_turf_flags
for(var/i in transferring_comps)
W.TakeComponent(i)
if(new_baseturfs)
W.baseturfs = new_baseturfs
@@ -188,124 +183,6 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
if(!istype(air,/datum/gas_mixture))
Initalize_Atmos(0)
/// 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 bottommost 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, flags)
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, flags)
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()

View File

@@ -88,7 +88,7 @@
* This replaces the current turf if it is plating and is passed plating, is tile and is passed tile.
* It places the new turf on top of itself if it is plating and is passed a tile.
* It also replaces the turf if it is tile and is passed plating, essentially destroying the over turf.
* Flags argument is passed directly to ChangeTurf or PlaceOnTop
* Flags argument is passed directly to ChangeTurf or place_on_top
*/
/turf/open/proc/replace_floor(turf/open/new_floor_path, flags)
if (!overfloor_placed && initial(new_floor_path.overfloor_placed))

View File

@@ -40,7 +40,7 @@
switch(passed_mode)
if(RCD_FLOORWALL)
to_chat(user, span_notice("You build a floor."))
PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
place_on_top(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
return TRUE
return FALSE
@@ -72,7 +72,7 @@
playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
to_chat(user, span_notice("You build a floor."))
// Create a floor, which has this chasm underneath it
PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
place_on_top(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
else
to_chat(user, span_warning("You need one floor tile to build a floor!"))
else

View File

@@ -259,7 +259,7 @@
switch(passed_mode)
if(RCD_FLOORWALL)
to_chat(user, span_notice("You build a wall."))
PlaceOnTop(/turf/closed/wall)
place_on_top(/turf/closed/wall)
return TRUE
if(RCD_AIRLOCK)
if((locate(/obj/machinery/door/airlock) in src) || (locate(/obj/machinery/door/window) in src)) // Have to ignore firelocks

View File

@@ -68,7 +68,7 @@
to_chat(user, span_notice("You begin reinforcing the floor..."))
if(do_after(user, 3 SECONDS, src))
if (R.get_amount() >= 1 && !istype(src, /turf/open/floor/engine))
PlaceOnTop(/turf/open/floor/engine, flags = CHANGETURF_INHERIT_AIR)
place_on_top(/turf/open/floor/engine, flags = CHANGETURF_INHERIT_AIR)
playsound(src, 'sound/items/deconstruct.ogg', 80, 1)
R.use(1)
to_chat(user, span_notice("You reinforce the floor."))
@@ -82,7 +82,7 @@
var/obj/item/stack/tile/W = C
if(!W.use(1))
return
var/turf/open/floor/T = PlaceOnTop(W.turf_type, flags = CHANGETURF_INHERIT_AIR)
var/turf/open/floor/T = place_on_top(W.turf_type, flags = CHANGETURF_INHERIT_AIR)
if(istype(W, /obj/item/stack/tile/light)) //TODO: get rid of this ugly check somehow
var/obj/item/stack/tile/light/L = W
var/turf/open/floor/light/F = T

View File

@@ -53,7 +53,7 @@
switch(passed_mode)
if(RCD_FLOORWALL)
to_chat(user, span_notice("You build a floor."))
PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
place_on_top(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
return TRUE
return FALSE

View File

@@ -3,6 +3,7 @@
/turf/open/lava
name = "lava"
icon_state = "lava"
desc = "Looks painful to step in. Don't mine down."
gender = PLURAL //"That's some lava."
baseturfs = /turf/open/lava //lava all the way down
slowdown = 2
@@ -10,6 +11,7 @@
light_range = 2
light_power = 0.75
light_color = LIGHT_COLOR_LAVA
light_on = FALSE
bullet_bounce_sound = 'sound/items/welder2.ogg'
footstep = FOOTSTEP_LAVA
@@ -22,7 +24,14 @@
/// The icon state that covers the lava bits of our turf
var/mask_state = "lava-lightmask"
/* //to add when emissives are added :thumbsup:
/turf/open/lava/Initialize(mapload)
. = ..()
// if(fish_source_type)
// AddElement(/datum/element/lazy_fishing_spot, fish_source_type)
refresh_light()
if(!smoothing_flags)
update_appearance()
/turf/open/lava/update_overlays()
. = ..()
// We need a light overlay here because not every lava turf casts light, only the edge ones
@@ -37,7 +46,52 @@
light_mask.blend_mode = BLEND_MULTIPLY
light_mask.color = list(-1,0,0,0, 0,-1,0,0, 0,0,-1,0, 0,0,0,1, 1,1,1,0)
. += light_mask
*/
/// Refreshes this lava turf's lighting
/turf/open/lava/proc/refresh_light()
var/border_turf = FALSE
var/list/turfs_to_check = RANGE_TURFS(1, src)
if(GET_LOWEST_STACK_OFFSET(z))
var/turf/above = GET_TURF_ABOVE(src)
if(above)
turfs_to_check += RANGE_TURFS(1, above)
var/turf/below = GET_TURF_BELOW(src)
if(below)
turfs_to_check += RANGE_TURFS(1, below)
for(var/turf/around as anything in turfs_to_check)
if(islava(around))
continue
border_turf = TRUE
if(!border_turf)
set_light(l_on = FALSE)
return
set_light(l_on = TRUE)
/turf/open/lava/ChangeTurf(path, list/new_baseturfs, flags)
var/turf/result = ..()
if(result && !islava(result))
// We have gone from a lava turf to a non lava turf, time to let them know
var/list/turfs_to_check = RANGE_TURFS(1, result)
if(GET_LOWEST_STACK_OFFSET(z))
var/turf/above = GET_TURF_ABOVE(result)
if(above)
turfs_to_check += RANGE_TURFS(1, above)
var/turf/below = GET_TURF_BELOW(result)
if(below)
turfs_to_check += RANGE_TURFS(1, below)
for(var/turf/open/lava/inform in turfs_to_check)
inform.set_light(l_on = TRUE)
return result
/turf/open/lava/smooth_icon()
. = ..()
mask_state = icon_state
update_appearance(~UPDATE_SMOOTHING)
/turf/open/lava/ex_act(severity, target)
contents_explosion(severity, target)
@@ -83,7 +137,7 @@
switch(passed_mode)
if(RCD_FLOORWALL)
to_chat(user, span_notice("You build a floor."))
PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
place_on_top(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
return TRUE
return FALSE
@@ -185,17 +239,14 @@
name = "lava"
baseturfs = /turf/open/lava/smooth
icon = 'icons/turf/floors/lava.dmi'
mask_icon = 'icons/turf/floors/lava_mask.dmi'
icon_state = "lava-255"
mask_state = "lava-255"
base_icon_state = "lava"
smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
smoothing_groups = SMOOTH_GROUP_TURF_OPEN + SMOOTH_GROUP_FLOOR_LAVA
canSmoothWith = SMOOTH_GROUP_FLOOR_LAVA
/turf/open/lava/smooth_icon()
. = ..()
mask_state = icon_state
update_appearance(~UPDATE_SMOOTHING)
underfloor_accessibility = 2 //This avoids strangeness when routing pipes / wires along catwalks over lava
/turf/open/lava/smooth/lava_land_surface
initial_gas_mix = LAVALAND_DEFAULT_ATMOS

View File

@@ -1,10 +1,13 @@
/turf/open/openspace
name = "open space"
desc = "Watch your step!"
icon_state = "grey"
// We don't actually draw openspace, but it needs to have color
// In its icon state so we can count it as a "non black" tile
icon_state = MAP_SWITCH("pure_white", "invisible")
baseturfs = /turf/open/openspace
overfloor_placed = FALSE
underfloor_accessibility = UNDERFLOOR_INTERACTABLE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
CanAtmosPassVertical = ATMOS_PASS_YES
flags_1 = NO_RUST
plane = TRANSPARENT_FLOOR_PLANE
@@ -12,18 +15,26 @@
var/can_cover_up = TRUE
var/can_build_on = TRUE
/turf/open/openspace/debug/update_multiz()
..()
return TRUE
// Reminder, any behavior code written here needs to be duped to /turf/open/space/openspace
// I am so sorry
/turf/open/openspace/Initialize(mapload) // handle plane and layer here so that they don't cover other obs/turfs in Dream Maker
. = ..()
RegisterSignal(src, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE, PROC_REF(on_atom_created))
if(PERFORM_ALL_TESTS(focus_only/openspace_clear) && !GET_TURF_BELOW(src))
stack_trace("[src] was inited as openspace with nothing below it at ([x], [y], [z])")
RegisterSignal(src, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON, PROC_REF(on_atom_created))
var/area/our_area = loc
if(istype(our_area, /area/space))
force_no_gravity = TRUE
return INITIALIZE_HINT_LATELOAD
/turf/open/openspace/LateInitialize()
. = ..()
AddElement(/datum/element/turf_z_transparency)
/turf/open/openspace/ChangeTurf(path, list/new_baseturfs, flags)
UnregisterSignal(src, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON)
return ..()
/**
* Drops movables spawned on this turf after they are successfully initialized.
* so that spawned movables that should fall to gravity, will fall.
@@ -38,46 +49,37 @@
return
zFall(movable)
/turf/open/openspace/LateInitialize()
update_multiz(TRUE, TRUE)
/turf/open/openspace/Destroy()
vis_contents.len = 0
return ..()
/turf/open/openspace/update_multiz(prune_on_fail = FALSE, init = FALSE)
. = ..()
var/turf/T = below()
if(!T)
vis_contents.len = 0
if(prune_on_fail)
ChangeTurf(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
return FALSE
if(init)
vis_contents += T
return TRUE
/turf/open/openspace/multiz_turf_del(turf/T, dir)
if(dir != DOWN)
return
update_multiz()
/turf/open/openspace/multiz_turf_new(turf/T, dir)
if(dir != DOWN)
return
update_multiz()
/turf/open/openspace/zAirIn()
return TRUE
/turf/open/openspace/zAirOut()
return TRUE
/turf/open/openspace/zPassIn(atom/movable/A, direction, turf/source)
return TRUE
/turf/open/openspace/zPassIn(direction)
if(direction == DOWN)
for(var/obj/contained_object in contents)
if(contained_object.obj_flags & BLOCK_Z_IN_DOWN)
return FALSE
return TRUE
if(direction == UP)
for(var/obj/contained_object in contents)
if(contained_object.obj_flags & BLOCK_Z_IN_UP)
return FALSE
return TRUE
return FALSE
/turf/open/openspace/zPassOut(atom/movable/A, direction, turf/destination)
return TRUE
/turf/open/openspace/zPassOut(direction)
if(direction == DOWN)
for(var/obj/contained_object in contents)
if(contained_object.obj_flags & BLOCK_Z_OUT_DOWN)
return FALSE
return TRUE
if(direction == UP)
for(var/obj/contained_object in contents)
if(contained_object.obj_flags & BLOCK_Z_OUT_UP)
return FALSE
return TRUE
return FALSE
/turf/open/openspace/proc/CanCoverUp()
return can_cover_up
@@ -121,7 +123,7 @@
qdel(L)
playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
to_chat(user, span_notice("You build a floor."))
PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
place_on_top(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
else
to_chat(user, span_warning("You need one floor tile to build a floor!"))
else

View File

@@ -83,34 +83,6 @@ GLOBAL_LIST_EMPTY(starlight)
//This is used to optimize the map loader
return
/turf/open/space/Initialize(mapload)
SHOULD_CALL_PARENT(FALSE)
icon_state = SPACE_ICON_STATE
if(!space_gas)
space_gas = new
air = space_gas
update_air_ref(0)
vis_contents.Cut() //removes inherited overlays
visibilityChanged()
if (PERFORM_ALL_TESTS(focus_only/multiple_space_initialization))
if(flags_1 & INITIALIZED_1)
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
var/area/our_area = loc
if(!IS_DYNAMIC_LIGHTING(src) && IS_DYNAMIC_LIGHTING(our_area))
add_overlay(/obj/effect/fullbright)
if (light_system == STATIC_LIGHT && light_power && light_range)
update_light()
if (opacity)
directional_opacity = ALL_CARDINALS
return INITIALIZE_HINT_NORMAL
/turf/open/space/Destroy()
GLOB.starlight -= src
return ..()

View File

@@ -0,0 +1,45 @@
/**
* Space Initialize
*
* Doesn't call parent, see [/atom/proc/Initialize].
* When adding new stuff to /atom/Initialize, /turf/Initialize, etc
* don't just add it here unless space actually needs it.
*
* There is a lot of work that is intentionally not done because it is not currently used.
* This includes stuff like smoothing, blocking camera visibility, etc.
* If you are facing some odd bug with specifically space, check if it's something that was
* intentionally ommitted from this implementation.
*/
/turf/open/space/Initialize(mapload)
SHOULD_CALL_PARENT(FALSE)
air = space_gas
if (PERFORM_ALL_TESTS(focus_only/multiple_space_initialization))
if(flags_1 & INITIALIZED_1)
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
// We make the assumption that the space plane will never be blacklisted, as an optimization
if(SSmapping.max_plane_offset)
plane = PLANE_SPACE - (PLANE_RANGE * SSmapping.z_level_to_plane_offset[z])
var/area/our_area = loc
if(!our_area.area_has_base_lighting && space_lit) //Only provide your own lighting if the area doesn't for you
// Intentionally not add_overlay for performance reasons.
// add_overlay does a bunch of generic stuff, like creating a new list for overlays,
// queueing compile, cloning appearance, etc etc etc that is not necessary here.
overlays += GLOB.starlight_overlays[GET_TURF_PLANE_OFFSET(src) + 1]
if (!mapload)
if(requires_activation)
ImmediateCalculateAdjacentTurfs()
if(SSmapping.max_plane_offset)
var/turf/T = GET_TURF_ABOVE(src)
if(T)
T.multiz_turf_new(src, DOWN)
T = GET_TURF_BELOW(src)
if(T)
T.multiz_turf_new(src, UP)
return INITIALIZE_HINT_NORMAL

View File

@@ -16,6 +16,7 @@
/turf/open/space/transit/Destroy()
//Signals are NOT removed from turfs upon replacement, and we get replaced ALOT, so unregister our signal
UnregisterSignal(src, list(COMSIG_TURF_RESERVATION_RELEASED, COMSIG_ATOM_ENTERED, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON))
return ..()
/turf/open/space/transit/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
@@ -23,6 +24,14 @@
underlay_appearance.icon_state = "speedspace_ns_[get_transit_state(asking_turf)]"
underlay_appearance.transform = turn(matrix(), get_transit_angle(asking_turf))
/turf/open/space/transit/update_icon()
. = ..()
transform = turn(matrix(), get_transit_angle(src))
/turf/open/space/transit/update_icon_state()
icon_state = "speedspace_ns_[get_transit_state(src)]"
return ..()
/turf/open/space/transit/proc/initialize_drifting(atom/entered, atom/movable/enterer)
SIGNAL_HANDLER
@@ -88,11 +97,6 @@
/turf/open/space/transit/east
dir = EAST
/turf/open/space/transit/update_icon_state()
. = ..()
icon_state = "speedspace_ns_[get_transit_state(src)]"
transform = turn(matrix(), get_transit_angle(src))
/proc/get_transit_state(turf/T)
var/p = 9
. = 1

View File

@@ -610,12 +610,13 @@ GLOBAL_LIST_EMPTY(station_turfs)
/turf/proc/add_blueprints(atom/movable/AM)
var/image/I = new
SET_PLANE(I, GAME_PLANE, src)
I.layer = OBJ_LAYER
I.appearance = AM.appearance
I.appearance_flags = RESET_COLOR|RESET_ALPHA|RESET_TRANSFORM
I.loc = src
I.setDir(AM.dir)
I.alpha = 128
LAZYADD(blueprint_data, I)

View File

@@ -60,9 +60,9 @@
brass_floor = TRUE
if(W.use(2 - brass_floor))
if(anchored)
T.PlaceOnTop(/turf/closed/wall/clockwork)
T.place_on_top(/turf/closed/wall/clockwork)
else
T.PlaceOnTop(/turf/open/floor/clockwork, flags = CHANGETURF_INHERIT_AIR)
T.place_on_top(/turf/open/floor/clockwork, flags = CHANGETURF_INHERIT_AIR)
new /obj/structure/falsewall/brass(T)
qdel(src)
else

View File

@@ -223,7 +223,7 @@
var/turf/T = safepick(validturfs)
if(T)
if(istype(T, /turf/open/floor/plating))
T.PlaceOnTop(/turf/open/floor/engine/cult, flags = CHANGETURF_IGNORE_AIR)
T.place_on_top(/turf/open/floor/engine/cult, flags = CHANGETURF_IGNORE_AIR)
else
T.ChangeTurf(/turf/open/floor/engine/cult, flags = CHANGETURF_IGNORE_AIR)
else

View File

@@ -226,7 +226,7 @@ RUST PATH SPELLS GO HERE
/datum/action/cooldown/spell/pointed/rust_construction/cast(turf/open/cast_on)
. = ..()
var/rises_message = "rises out of [cast_on]"
var/turf/closed/wall/new_wall = cast_on.PlaceOnTop(/turf/closed/wall)
var/turf/closed/wall/new_wall = cast_on.place_on_top(/turf/closed/wall)
if(!istype(new_wall))
return

View File

@@ -39,6 +39,7 @@ GLOBAL_LIST_INIT(potentialConfigRandomZlevels, generateConfigMapList(directory =
/proc/generateMapList(filename)
. = list()
filename = "[global.config.directory]/[SANITIZE_FILENAME(filename)]"
var/list/Lines = world.file2list(filename)
if(!Lines.len)

View File

@@ -22,13 +22,13 @@
if(istype(object,/turf) && left_click && !alt_click && !ctrl_click)
var/turf/T = object
if(isspaceturf(object) || ischasm(object) || islava(object))
T.PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
T.place_on_top(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
else if(isplatingturf(object))
T.PlaceOnTop(/turf/open/floor/plasteel, flags = CHANGETURF_INHERIT_AIR)
T.place_on_top(/turf/open/floor/plasteel, flags = CHANGETURF_INHERIT_AIR)
else if(isfloorturf(object))
T.PlaceOnTop(/turf/closed/wall)
T.place_on_top(/turf/closed/wall)
else if(iswallturf(object))
T.PlaceOnTop(/turf/closed/wall/r_wall)
T.place_on_top(/turf/closed/wall/r_wall)
log_admin("Build Mode: [key_name(c)] built [T] at [AREACOORD(T)]")
return
else if(right_click)

View File

@@ -59,7 +59,7 @@
else
for(var/turf/T in block(get_turf(cornerA),get_turf(cornerB)))
if(ispath(objholder,/turf))
T.PlaceOnTop(objholder)
T.place_on_top(objholder)
else
var/obj/A = new objholder(T)
A.setDir(BM.build_dir)

View File

@@ -289,7 +289,7 @@
if (openingSound)
playsound(get_turf(holder), openingSound, soundVolume, FALSE, FALSE) //Special admin sound to play
for (var/turf_type in turfs_in_cargo)
turf_underneath.PlaceOnTop(turf_type)
turf_underneath.place_on_top(turf_type)
for (var/cargo in contents)
var/atom/movable/movable_cargo = cargo
movable_cargo.forceMove(turf_underneath)

View File

@@ -13,8 +13,14 @@
/datum/round_event/shuttle_catastrophe
var/datum/map_template/shuttle/new_shuttle
var/list/datum/map_template/shuttle/blacklisted_shuttles = list(/datum/map_template/shuttle/emergency/arena, /datum/map_template/shuttle/emergency/construction,
/datum/map_template/shuttle/emergency/construction/small, /datum/map_template/shuttle/emergency/discoinferno, /datum/map_template/shuttle/emergency/meteor)
var/list/datum/map_template/shuttle/blacklisted_shuttles = list(
/datum/map_template/shuttle/emergency/arena,
/datum/map_template/shuttle/emergency/construction,
/datum/map_template/shuttle/emergency/construction/small,
/datum/map_template/shuttle/emergency/discoinferno,
/datum/map_template/shuttle/emergency/meteor,
)
/datum/round_event/shuttle_catastrophe/announce(fake)
var/cause = pick("was attacked by [syndicate_name()] Operatives", "mysteriously teleported away", "had its refuelling crew mutiny",
"was found with its engines stolen", "\[REDACTED\]", "flew into the sunset, and melted", "fell into a black hole",
@@ -23,19 +29,19 @@
priority_announce("Your emergency shuttle [cause]. Your replacement shuttle will be the [new_shuttle.name] until further notice.", "CentCom Spacecraft Engineering")
/datum/round_event/shuttle_catastrophe/setup()
if(!isnull(new_shuttle)) //If an admin has overridden it don't re-roll it
return
var/list/valid_shuttle_templates = list()
for(var/shuttle_id in SSmapping.shuttle_templates)
var/datum/map_template/shuttle/template = SSmapping.shuttle_templates[shuttle_id]
if(template.credit_cost < INFINITY) //if we could get it from the emagged communications console, it's cool for us to get it here
if (!(template in blacklisted_shuttles))
valid_shuttle_templates += template
if(!(template in blacklisted_shuttles) && template.credit_cost < INFINITY) //if we could get it from the communications console, it's cool for us to get it here
valid_shuttle_templates += template
new_shuttle = pick(valid_shuttle_templates)
/datum/round_event/shuttle_catastrophe/start()
SSshuttle.shuttle_purchased = SHUTTLEPURCHASE_FORCED
SSshuttle.unload_preview()
SSshuttle.load_template(new_shuttle)
SSshuttle.existing_shuttle = SSshuttle.emergency
SSshuttle.emergency.name = new_shuttle.name
SSshuttle.action_load(new_shuttle)
SSshuttle.action_load(new_shuttle, replace = TRUE)
log_game("Shuttle Catastrophe set a new shuttle, [new_shuttle.name].")

View File

@@ -111,6 +111,7 @@
// need these two below?
SSmachines.setup_template_powernets(cables)
SSair.setup_template_machinery(atmos_machines)
//SSshuttle.setup_shuttles(ports)
//calculate all turfs inside the border
var/list/template_and_bordering_turfs = block(
@@ -126,7 +127,7 @@
)
)
for(var/turf/affected_turf as anything in template_and_bordering_turfs)
affected_turf.air_update_turf(TRUE, TRUE)
affected_turf.ImmediateCalculateAdjacentTurfs()
affected_turf.levelupdate()
/datum/map_template/proc/load_new_z(secret = FALSE)
@@ -194,19 +195,19 @@
//initialize things that are normally initialized after map load
initTemplateBounds(bounds)
// if(has_ceiling)
// var/affected_turfs = get_affected_turfs(T, FALSE)
// generate_ceiling(affected_turfs)
if(has_ceiling)
var/affected_turfs = get_affected_turfs(T, FALSE)
generate_ceiling(affected_turfs)
log_game("[name] loaded at [T.x],[T.y],[T.z]")
return bounds
// /datum/map_template/proc/generate_ceiling(affected_turfs)
// for (var/turf/turf in affected_turfs)
// var/turf/ceiling = get_step_multiz(turf, UP)
// if (ceiling)
// if (istype(ceiling, /turf/open/openspace) || istype(ceiling, /turf/open/space/openspace))
// ceiling.ChangeTurf(ceiling_turf, ceiling_baseturfs, CHANGETURF_INHERIT_AIR)
/datum/map_template/proc/generate_ceiling(affected_turfs)
for (var/turf/turf in affected_turfs)
var/turf/ceiling = get_step_multiz(turf, UP)
if (ceiling)
if (istype(ceiling, /turf/open/openspace) || istype(ceiling, /turf/open/space/openspace))
ceiling.ChangeTurf(ceiling_turf, ceiling_baseturfs, CHANGETURF_INHERIT_AIR)
/datum/map_template/proc/post_load()
return

View File

@@ -6,8 +6,9 @@
name = "baseturf editor"
icon = 'icons/effects/mapping_helpers.dmi'
icon_state = ""
/// Replacing a specific turf
var/list/baseturf_to_replace
/// The desired bottom turf
var/baseturf
plane = POINT_PLANE
@@ -18,7 +19,7 @@
/obj/effect/baseturf_helper/LateInitialize()
if(!baseturf_to_replace)
baseturf_to_replace = typecacheof(/turf/open/space)
baseturf_to_replace = typecacheof(list(/turf/open/space,/turf/baseturf_bottom))
else if(!length(baseturf_to_replace))
baseturf_to_replace = list(baseturf_to_replace = TRUE)
else if(baseturf_to_replace[baseturf_to_replace[1]] != TRUE) // It's not associative
@@ -33,20 +34,16 @@
qdel(src)
/// Replaces all the requested baseturfs (usually space/baseturfbottom) with the desired baseturf. Skips if its already there
/obj/effect/baseturf_helper/proc/replace_baseturf(turf/thing)
var/list/baseturf_cache = thing.baseturfs
if(length(baseturf_cache))
for(var/i in baseturf_cache)
if(baseturf_to_replace[i])
baseturf_cache -= i
if(!baseturf_cache.len)
thing.assemble_baseturfs(baseturf)
else
thing.PlaceOnBottom(null, baseturf)
else if(baseturf_to_replace[thing.baseturfs])
thing.assemble_baseturfs(baseturf)
else
thing.PlaceOnBottom(null, baseturf)
thing.remove_baseturfs_from_typecache(baseturf_to_replace)
if(length(thing.baseturfs))
var/turf/tile = thing.baseturfs[1]
if(tile == baseturf)
return
thing.place_on_bottom(baseturf)
@@ -90,6 +87,9 @@
/obj/effect/mapping_helpers
icon = 'icons/effects/mapping_helpers.dmi'
icon_state = ""
anchored = TRUE
// Unless otherwise specified, layer above everything
layer = ABOVE_ALL_MOB_LAYER
var/late = FALSE
/obj/effect/mapping_helpers/Initialize(mapload)

View File

@@ -148,7 +148,7 @@
* - y_upper: The maximum y coordinate to load
* - z_lower: The minimum z coordinate to load
* - z_upper: The maximum z coordinate to load
* - place_on_top: Whether to use /turf/proc/PlaceOnTop rather than /turf/proc/ChangeTurf
* - place_on_top: Whether to use /turf/proc/place_on_top rather than /turf/proc/ChangeTurf
* - new_z: If true, a new z level will be created for the map
*/
/proc/load_map(

View File

@@ -44,22 +44,3 @@
us = next
next = GET_TURF_ABOVE(us)
return us
/proc/dir_inverse_multiz(dir)
var/holder = dir & (UP|DOWN)
if((holder == NONE) || (holder == (UP|DOWN)))
return turn(dir, 180)
dir &= ~(UP|DOWN)
dir = turn(dir, 180)
if(holder == UP)
holder = DOWN
else
holder = UP
dir |= holder
return dir
/turf/proc/above()
return get_step_multiz(src, UP)
/turf/proc/below()
return get_step_multiz(src, DOWN)

View File

@@ -56,20 +56,20 @@
INVOKE_ASYNC(SSmapping, TYPE_PROC_REF(/datum/controller/subsystem/mapping, reserve_turfs), release_turfs)
/// Attempts to calaculate and store a list of turfs around the reservation for cordoning. Returns whether a valid cordon was calculated
/datum/turf_reservation/proc/calculate_cordon_turfs(turf/BL, turf/TR)
if(BL.x < 2 || BL.y < 2 || TR.x > (world.maxx - 2) || TR.y > (world.maxy - 2))
/datum/turf_reservation/proc/calculate_cordon_turfs(turf/bottom_left, turf/top_right)
if(bottom_left.x < 2 || bottom_left.y < 2 || top_right.x > (world.maxx - 2) || top_right.y > (world.maxy - 2))
return FALSE // no space for a cordon here
var/list/possible_turfs = CORNER_OUTLINE(BL, width, height)
var/list/possible_turfs = CORNER_OUTLINE(bottom_left, width, height)
// if they're our cordon turfs, accept them
possible_turfs -= cordon_turfs
for(var/turf/cordon_turf as anything in possible_turfs)
if(!(cordon_turf.flags_1 & UNUSED_RESERVATION_TURF_1))
if(!(cordon_turf.turf_flags & UNUSED_RESERVATION_TURF))
return FALSE
cordon_turfs = possible_turfs
pre_cordon_turfs.Cut()
cordon_turfs |= possible_turfs
if(pre_cordon_distance)
var/turf/offset_turf = locate(BL.x + pre_cordon_distance, BL.y + pre_cordon_distance, BL.z)
var/turf/offset_turf = locate(bottom_left.x + pre_cordon_distance, bottom_left.y + pre_cordon_distance, bottom_left.z)
var/list/to_add = CORNER_OUTLINE(offset_turf, width - pre_cordon_distance * 2, height - pre_cordon_distance * 2) //we step-by-stop move inwards from the outer cordon
for(var/turf/turf_being_added as anything in to_add)
pre_cordon_turfs |= turf_being_added //add one by one so we can filter out duplicates
@@ -136,7 +136,6 @@
if(!HAS_TRAIT(enterer, TRAIT_FREE_HYPERSPACE_SOFTCORDON_MOVEMENT))
space_dump(source, enterer)
/// Internal proc which handles reserving the area for the reservation.
/datum/turf_reservation/proc/_reserve_area(width, height, zlevel)
src.width = width
@@ -179,6 +178,7 @@
reserved_turfs |= T
SSmapping.unused_turfs["[T.z]"] -= T
SSmapping.used_turfs[T] = src
T.flags_1 = (T.flags_1 | RESERVATION_TURF_1) & ~UNUSED_RESERVATION_TURF_1
T.ChangeTurf(turf_type, turf_type)
bottom_left_turfs += BL

View File

@@ -93,13 +93,13 @@
level.set_neigbours(used_points)
point = pick(possible_points)
CHECK_TICK
// Now that we've handed out neighbors, we're gonna handle an edge case
// Need to check if all our levels have neighbors in all directions
// If they don't, we'll make them wrap all the way around to the other side of the grid
for(var/direction in GLOB.cardinals)
var/dir = "[direction]"
var/inverse = "[turn(direction, 180)]"
var/inverse = "[REVERSE_DIR(direction)]"
for(var/datum/space_level/level as anything in transition_levels)
// If we have something in this dir that isn't just us, continue on
if(level.neigbours[dir] && level.neigbours[dir] != level)
@@ -114,16 +114,18 @@
//Lists below are pre-calculated values arranged in the list in such a way to be easily accessable in the loop by the counter
//Its either this or madness with lotsa math
var/inner_max_x = world.maxx - TRANSITIONEDGE
var/inner_max_y = world.maxy - TRANSITIONEDGE
var/list/x_pos_beginning = list(1, 1, inner_max_x, 1) //x values of the lowest-leftest turfs of the respective 4 blocks on each side of zlevel
var/list/y_pos_beginning = list(inner_max_y, 1, 1 + TRANSITIONEDGE, 1 + TRANSITIONEDGE) //y values respectively
var/list/x_pos_ending = list(world.maxx, world.maxx, world.maxx, 1 + TRANSITIONEDGE) //x values of the highest-rightest turfs of the respective 4 blocks on each side of zlevel
var/list/x_pos_ending = list(world.maxx, world.maxx, world.maxx, 1 + TRANSITIONEDGE) //x values of the highest-rightest turfs of the respective 4 blocks on each side of zlevel
var/list/y_pos_ending = list(world.maxy, 1 + TRANSITIONEDGE, inner_max_y, inner_max_y) //y values respectively
var/list/x_pos_transition = list(1, 1, TRANSITIONEDGE + 2, inner_max_x - 1) //values of x for the transition from respective blocks on the side of zlevel, 1 is being translated into turfs respective x value later in the code
var/list/y_pos_transition = list(TRANSITIONEDGE + 2, inner_max_y - 1, 1, 1) //values of y for the transition from respective blocks on the side of zlevel, 1 is being translated into turfs respective y value later in the code
// Cache the range passed to the mirage border element, to reduce world var access in the thousands
var/range_cached = world.view
for(var/datum/space_level/level as anything in cached_z_list)
if(!level.neigbours.len)
continue
@@ -142,7 +144,7 @@
S.destination_x = x_target || S.x
S.destination_y = y_target || S.y
S.destination_z = zdestination
// Mirage border code
var/mirage_dir
if(S.x == 1 + TRANSITIONEDGE)
@@ -157,6 +159,6 @@
continue
var/turf/place = locate(S.destination_x, S.destination_y, zdestination)
S.AddComponent(/datum/component/mirage_border, place, mirage_dir)
S.AddElement(/datum/element/mirage_border, place, mirage_dir, range_cached)
#undef CHORDS_TO_1D

View File

@@ -17,8 +17,10 @@
var/list/features = default_map_traits[I]
var/datum/space_level/S = new(I, features[DL_NAME], features[DL_TRAITS])
manage_z_level(S, filled_with_space = FALSE)
//generate_z_level_linkages() // Default Zs don't use add_new_zlevel() so they don't automatically generate z-linkages.
generate_z_level_linkages() // Default Zs don't use add_new_zlevel() so they don't automatically generate z-linkages.
/// Generates a real, honest to god new z level. Will create the actual space, and also generate a datum that holds info about the new plot of land
/// Accepts the name, traits list, datum type, and if we should manage the turfs we create
/datum/controller/subsystem/mapping/proc/add_new_zlevel(name, traits = list(), z_type = /datum/space_level, contain_turfs = TRUE)
UNTIL(!adding_new_zlevel)
adding_new_zlevel = TRUE
@@ -29,7 +31,7 @@
// TODO: sleep here if the Z level needs to be cleared
var/datum/space_level/S = new z_type(new_z, name, traits)
manage_z_level(S, filled_with_space = TRUE, contain_turfs = contain_turfs)
//generate_linkages_for_z_level(new_z)
generate_linkages_for_z_level(new_z)
adding_new_zlevel = FALSE
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NEW_Z, S)
return S

View File

@@ -323,9 +323,9 @@
sleep(5 SECONDS)
if(mode == BOT_REPAIRING && src.loc == target_turf)
if(autotile) //Build the floor and include a tile.
target_turf.PlaceOnTop(/turf/open/floor/plasteel, flags = CHANGETURF_INHERIT_AIR)
target_turf.place_on_top(/turf/open/floor/plasteel, flags = CHANGETURF_INHERIT_AIR)
else //Build a hull plating without a floor tile.
target_turf.PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
target_turf.place_on_top(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
else
var/turf/open/floor/F = target_turf
@@ -339,7 +339,7 @@
if(mode == BOT_REPAIRING && F && src.loc == F)
F.broken = FALSE
F.burnt = FALSE
F.PlaceOnTop(/turf/open/floor/plasteel, flags = CHANGETURF_INHERIT_AIR)
F.place_on_top(/turf/open/floor/plasteel, flags = CHANGETURF_INHERIT_AIR)
if(replacetiles && F.type != initial(tiletype.turf_type) && specialtiles && !isplatingturf(F))
anchored = TRUE
@@ -350,7 +350,7 @@
if(mode == BOT_REPAIRING && F && src.loc == F)
F.broken = FALSE
F.burnt = FALSE
F.PlaceOnTop(initial(tiletype.turf_type), flags = CHANGETURF_INHERIT_AIR)
F.place_on_top(initial(tiletype.turf_type), flags = CHANGETURF_INHERIT_AIR)
specialtiles -= 1
if(specialtiles == 0)
speak("Requesting refill of custom floortiles to continue replacing.")

View File

@@ -1765,7 +1765,7 @@
/datum/reagent/carpet/reaction_turf(turf/T, reac_volume)
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
var/turf/open/floor/F = T
F.PlaceOnTop(/turf/open/floor/carpet, flags = CHANGETURF_INHERIT_AIR)
F.place_on_top(/turf/open/floor/carpet, flags = CHANGETURF_INHERIT_AIR)
..()
/datum/reagent/bromine

View File

@@ -173,7 +173,7 @@
//Setup random empty tile
empty_tile_id = pick_n_take(left_ids)
var/turf/empty_tile_turf = get_turf_for_id(empty_tile_id)
empty_tile_turf.PlaceOnTop(floor_type,null,CHANGETURF_INHERIT_AIR)
empty_tile_turf.place_on_top(floor_type,null,CHANGETURF_INHERIT_AIR)
var/mutable_appearance/MA = new(puzzle_pieces["[empty_tile_id]"])
MA.layer = empty_tile_turf.layer + 0.1
empty_tile_turf.add_overlay(MA)
@@ -182,7 +182,7 @@
var/list/empty_spots = left_ids.Copy()
for(var/spot_id in empty_spots)
var/turf/T = get_turf_for_id(spot_id)
T = T.PlaceOnTop(floor_type,null,CHANGETURF_INHERIT_AIR)
T = T.place_on_top(floor_type,null,CHANGETURF_INHERIT_AIR)
var/obj/structure/puzzle_element/E = new element_type(T)
elements += E
var/chosen_id = pick_n_take(left_ids)

View File

@@ -34,7 +34,28 @@
///Delete this port after ship fly off.
var/delete_after = FALSE
//these objects are indestructible
///are we registered in SSshuttles?
var/registered = FALSE
///register to SSshuttles
/obj/docking_port/proc/register()
if(registered)
WARNING("docking_port registered multiple times")
unregister()
registered = TRUE
return
///unregister from SSshuttles
/obj/docking_port/proc/unregister()
if(!registered)
WARNING("docking_port unregistered multiple times")
registered = FALSE
return
/obj/docking_port/proc/Check_id()
return
//these objects are indestructible
/obj/docking_port/Destroy(force)
// unless you assert that you know what you're doing. Horrible things
// may result.
@@ -124,7 +145,9 @@
#ifdef DOCKING_PORT_HIGHLIGHT
//Debug proc used to highlight bounding area
/obj/docking_port/proc/highlight(_color)
/obj/docking_port/proc/highlight(_color = "#f00")
SetInvisibility(INVISIBILITY_NONE)
SET_PLANE_IMPLICIT(src, GHOST_PLANE)
var/list/L = return_coords()
var/turf/T0 = locate(L[1],L[2],z)
var/turf/T1 = locate(L[3],L[4],z)
@@ -175,13 +198,17 @@
///If true, the shuttle can always dock at this docking port, despite its area checks, or if something is already docked
var/override_can_dock_checks = FALSE
/obj/docking_port/stationary/Initialize(mapload)
/obj/docking_port/stationary/register(replace = FALSE)
. = ..()
SSshuttle.stationary += src
if(!id)
id = "[SSshuttle.stationary.len]"
if(name == "dock")
name = "dock[SSshuttle.stationary.len]"
SSshuttle.stationary += src
/obj/docking_port/stationary/Initialize(mapload)
. = ..()
register()
if(!area_type)
var/area/place = get_area(src)
area_type = place?.type // We might be created in nullspace
@@ -190,16 +217,20 @@
for(var/turf/T in return_turfs())
T.flags_1 |= NO_RUINS_1
// if(SSshuttle.initialized)
// INVOKE_ASYNC(SSshuttle, TYPE_PROC_REF(/datum/controller/subsystem/shuttle, setup_shuttles), list(src))
if(SSshuttle.initialized)
INVOKE_ASYNC(SSshuttle, TYPE_PROC_REF(/datum/controller/subsystem/shuttle, setup_shuttles), list(src))
#ifdef DOCKING_PORT_HIGHLIGHT
highlight("#f00")
#endif
/obj/docking_port/stationary/unregister()
. = ..()
SSshuttle.stationary -= src
/obj/docking_port/stationary/Destroy(force)
if(force)
SSshuttle.stationary -= src
unregister()
. = ..()
/obj/docking_port/stationary/Moved(atom/oldloc, dir, forced)
@@ -294,7 +325,10 @@
var/launch_status = NOLAUNCH
///Whether or not you want your ship to knock people down, and also whether it will throw them several tiles upon launching.
var/list/movement_force = list("KNOCKDOWN" = 3, "THROW" = 0)
var/list/movement_force = list(
"KNOCKDOWN" = 3,
"THROW" = 0,
)
var/list/ripples = list()
var/engine_coeff = 1
@@ -305,10 +339,84 @@
var/can_move_docking_ports = FALSE
var/list/hidden_turfs = list()
/obj/docking_port/mobile/proc/register()
#define WORLDMAXX_CUTOFF (world.maxx + 1)
#define WORLDMAXY_CUTOFF (world.maxx + 1)
/**
* Calculated and populates the information used for docking and some internal vars.
* This can also be used to calculate from shuttle_areas so that you can expand/shrink shuttles!
*
* Arguments:
* * loading_from - The template that the shuttle was loaded from, if not given we iterate shuttle_areas to calculate information instead
*/
/obj/docking_port/mobile/proc/calculate_docking_port_information(datum/map_template/shuttle/loading_from)
var/port_x_offset = loading_from?.port_x_offset
var/port_y_offset = loading_from?.port_y_offset
var/width = loading_from?.width
var/height = loading_from?.height
if(!loading_from)
if(!length(shuttle_areas))
CRASH("Attempted to calculate a docking port's information without a template before it was assigned any areas!")
// no template given, use shuttle_areas to calculate width and height
var/min_x = -1
var/min_y = -1
var/max_x = WORLDMAXX_CUTOFF
var/max_y = WORLDMAXY_CUTOFF
for(var/area/area as anything in shuttle_areas)
for(var/turf/turf in area)
min_x = max(turf.x, min_x)
max_x = min(turf.x, max_x)
min_y = max(turf.y, min_y)
max_y = min(turf.y, max_y)
CHECK_TICK
if(min_x == -1 || max_x == WORLDMAXX_CUTOFF)
CRASH("Failed to locate shuttle boundaries when iterating through shuttle areas, somehow.")
if(min_y == -1 || max_y == WORLDMAXY_CUTOFF)
CRASH("Failed to locate shuttle boundaries when iterating through shuttle areas, somehow.")
width = (max_x - min_x) + 1
height = (max_y - min_y) + 1
port_x_offset = min_x - x
port_y_offset = min_y - y
if(dir in list(EAST, WEST))
src.width = height
src.height = width
else
src.width = width
src.height = height
switch(dir)
if(NORTH)
dwidth = port_x_offset - 1
dheight = port_y_offset - 1
if(EAST)
dwidth = height - port_y_offset
dheight = port_x_offset - 1
if(SOUTH)
dwidth = width - port_x_offset
dheight = height - port_y_offset
if(WEST)
dwidth = port_y_offset - 1
dheight = width - port_x_offset
#undef WORLDMAXX_CUTOFF
#undef WORLDMAXY_CUTOFF
/obj/docking_port/mobile/register(replace = FALSE)
. = ..()
SSshuttle.mobile += src
/obj/docking_port/mobile/proc/unregister()
/**
* Actions to be taken after shuttle is loaded and has been moved to its final location
*
* Arguments:
* * replace - TRUE if this shuttle is replacing an existing one. FALSE by default.
*/
/obj/docking_port/mobile/proc/postregister(replace = FALSE)
return
/obj/docking_port/mobile/unregister()
. = ..()
SSshuttle.mobile -= src
/obj/docking_port/mobile/Destroy(force)
@@ -414,32 +522,32 @@
/obj/docking_port/mobile/proc/transit_failure()
message_admins("Shuttle [src] repeatedly failed to create transit zone.")
//call the shuttle to destination S
/obj/docking_port/mobile/proc/request(obj/docking_port/stationary/S)
if(!check_dock(S))
//call the shuttle to destination destination_port
/obj/docking_port/mobile/proc/request(obj/docking_port/stationary/destination_port)
if(!check_dock(destination_port))
testing("check_dock failed on request for [src]")
return
if(mode == SHUTTLE_IGNITING && destination == S)
if(mode == SHUTTLE_IGNITING && destination == destination_port)
return
switch(mode)
if(SHUTTLE_CALL)
if(S == destination)
if(destination_port == destination)
if(timeLeft(1) < callTime * engine_coeff)
setTimer(callTime * engine_coeff)
else
destination = S
destination = destination_port
setTimer(callTime * engine_coeff)
if(SHUTTLE_RECALL)
if(S == destination)
if(destination_port == destination)
setTimer(callTime * engine_coeff - timeLeft(1))
else
destination = S
destination = destination_port
setTimer(callTime * engine_coeff)
mode = SHUTTLE_CALL
if(SHUTTLE_IDLE, SHUTTLE_IGNITING)
destination = S
destination = destination_port
mode = SHUTTLE_IGNITING
setTimer(ignitionTime)

View File

@@ -37,7 +37,7 @@
if (spawn_place.overfloor_placed)
spawn_place.ChangeTurf(summoned_object_type, flags = CHANGETURF_INHERIT_AIR)
else
spawn_place.PlaceOnTop(summoned_object_type, flags = CHANGETURF_INHERIT_AIR)
spawn_place.place_on_top(summoned_object_type, flags = CHANGETURF_INHERIT_AIR)
return
else

View File

@@ -34,7 +34,7 @@
// Do this instead of just ChangeTurf to guarantee that baseturfs is completely default on-init behavior
RESET_TO_EXPECTED(run_loc_floor_bottom_left)
run_loc_floor_bottom_left.PlaceOnTop(/turf/closed/wall/rock)
run_loc_floor_bottom_left.place_on_top(/turf/closed/wall/rock)
TEST_ASSERT_EQUAL(run_loc_floor_bottom_left.type, /turf/closed/wall/rock, "Rock wall should've been placed on top")
run_loc_floor_bottom_left.ScrapeAway()
@@ -53,8 +53,8 @@
// Do this instead of just ChangeTurf to guarantee that baseturfs is completely default on-init behavior
RESET_TO_EXPECTED(run_loc_floor_bottom_left)
run_loc_floor_bottom_left.PlaceOnBottom(/turf/closed/wall/rock)
TEST_ASSERT_EQUAL(run_loc_floor_bottom_left.type, EXPECTED_FLOOR_TYPE, "PlaceOnBottom shouldn't have changed turf")
run_loc_floor_bottom_left.place_on_bottom(/turf/closed/wall/rock)
TEST_ASSERT_EQUAL(run_loc_floor_bottom_left.type, EXPECTED_FLOOR_TYPE, "place_on_bottom shouldn't have changed turf")
run_loc_floor_bottom_left.ScrapeAway()
TEST_ASSERT_EQUAL(run_loc_floor_bottom_left.type, /turf/open/floor/plating, "Plasteel floors should scrape away to plating")

View File

@@ -700,6 +700,7 @@
#include "code\datums\elements\frozen.dm"
#include "code\datums\elements\life_drain.dm"
#include "code\datums\elements\light_blocking.dm"
#include "code\datums\elements\mirage_border.dm"
#include "code\datums\elements\movetype_handler.dm"
#include "code\datums\elements\regenerator.dm"
#include "code\datums\elements\rust.dm"
@@ -1576,6 +1577,7 @@
#include "code\game\turfs\open\floor\plating\dirt.dm"
#include "code\game\turfs\open\floor\plating\misc_plating.dm"
#include "code\game\turfs\open\space\space.dm"
#include "code\game\turfs\open\space\space_EXPENSIVE.dm"
#include "code\game\turfs\open\space\transit.dm"
#include "code\modules\admin\admin.dm"
#include "code\modules\admin\admin_investigate.dm"