diff --git a/_maps/RandomRuins/SpaceRuins/caravanambush.dmm b/_maps/RandomRuins/SpaceRuins/caravanambush.dmm index ca3ea5c31d9..27dcfe96808 100644 --- a/_maps/RandomRuins/SpaceRuins/caravanambush.dmm +++ b/_maps/RandomRuins/SpaceRuins/caravanambush.dmm @@ -364,9 +364,7 @@ /turf/open/floor/plating/airless, /area/shuttle/caravan/freighter3) "gc" = ( -/obj/machinery/door/airlock/external{ - req_access_txt = "13" - }, +/obj/machinery/door/airlock/external, /obj/effect/mapping_helpers/airlock/cyclelink_helper, /turf/open/floor/plating/airless, /area/shuttle/caravan/freighter3) @@ -560,9 +558,7 @@ /area/shuttle/caravan/freighter2) "hs" = ( /obj/effect/decal/cleanable/dirt, -/obj/machinery/door/airlock/external{ - req_access_txt = "13" - }, +/obj/machinery/door/airlock/external, /obj/effect/mapping_helpers/airlock/cyclelink_helper, /turf/open/floor/plating/airless, /area/shuttle/caravan/freighter2) @@ -1239,9 +1235,7 @@ /turf/closed/wall/mineral/plastitanium, /area/ruin/unpowered) "vE" = ( -/obj/machinery/door/airlock/external{ - req_access_txt = "13" - }, +/obj/machinery/door/airlock/external, /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 1 }, @@ -1249,9 +1243,7 @@ /area/shuttle/caravan/freighter3) "GL" = ( /obj/effect/decal/cleanable/dirt, -/obj/machinery/door/airlock/external{ - req_access_txt = "13" - }, +/obj/machinery/door/airlock/external, /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 1 }, diff --git a/_maps/RandomZLevels/research.dmm b/_maps/RandomZLevels/research.dmm index 953c5a1d491..e7f037d652a 100644 --- a/_maps/RandomZLevels/research.dmm +++ b/_maps/RandomZLevels/research.dmm @@ -528,9 +528,7 @@ /turf/open/floor/iron/white, /area/awaymission/research/interior/engineering) "bx" = ( -/obj/machinery/door/airlock/external{ - req_access_txt = "13" - }, +/obj/machinery/door/airlock/external, /turf/open/floor/plating, /area/awaymission/research/interior/maint) "by" = ( diff --git a/_maps/map_files/IceBoxStation/IcemoonUnderground_Above.dmm b/_maps/map_files/IceBoxStation/IcemoonUnderground_Above.dmm index 53acd67ae5a..3f6ac242431 100644 --- a/_maps/map_files/IceBoxStation/IcemoonUnderground_Above.dmm +++ b/_maps/map_files/IceBoxStation/IcemoonUnderground_Above.dmm @@ -2917,8 +2917,7 @@ dir = 8 }, /obj/machinery/door/airlock/external{ - name = "External Access"; - req_access_txt = "13" + name = "External Access" }, /turf/open/floor/plating, /area/maintenance/aft) @@ -3591,8 +3590,7 @@ /area/service/chapel) "py" = ( /obj/machinery/door/airlock/external{ - name = "External Access"; - req_access_txt = "13" + name = "External Access" }, /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 4 @@ -7480,8 +7478,7 @@ /area/maintenance/fore) "EW" = ( /obj/machinery/door/airlock/external{ - name = "External Access"; - req_access_txt = "13" + name = "External Access" }, /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 4 @@ -8781,8 +8778,7 @@ dir = 8 }, /obj/machinery/door/airlock/external{ - name = "External Access"; - req_access_txt = "13" + name = "External Access" }, /turf/open/floor/plating/snowed/icemoon, /area/maintenance/fore) diff --git a/_maps/shuttles/emergency_supermatter.dmm b/_maps/shuttles/emergency_supermatter.dmm index 4ae5e8e04c6..3c97c0818d9 100644 --- a/_maps/shuttles/emergency_supermatter.dmm +++ b/_maps/shuttles/emergency_supermatter.dmm @@ -137,7 +137,7 @@ "aL" = ( /obj/machinery/door/airlock/external{ name = "Emergency Launch Catwalk"; - req_access_txt = "10;13" + req_access_txt = "10" }, /turf/open/floor/plating, /area/shuttle/escape) diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm index 3d0afa13b54..a0761a2bc72 100644 --- a/code/datums/helper_datums/teleport.dm +++ b/code/datums/helper_datums/teleport.dm @@ -115,60 +115,67 @@ var/z = pick(zlevels) var/random_location = locate(x,y,z) - if(!isfloorturf(random_location)) - continue - var/turf/open/floor/F = random_location - var/area/destination_area = F.loc + if(is_safe_turf(random_location, extended_safety_checks, dense_atoms, cycle < 300))//if the area is mostly NOTELEPORT (centcom) we gotta give up on this fantasy at some point. + return random_location - if(cycle < 300 && destination_area.area_flags & NOTELEPORT)//if the area is mostly NOTELEPORT (centcom) we gotta give up on this fantasy at some point. - continue - if(!F.air) - continue +/// Checks if a given turf is a "safe" location +/proc/is_safe_turf(turf/random_location, extended_safety_checks = FALSE, dense_atoms = TRUE, no_teleport = FALSE) + . = FALSE + if(!isfloorturf(random_location)) + return + var/turf/open/floor/floor_turf = random_location + var/area/destination_area = floor_turf.loc - var/datum/gas_mixture/A = F.air - var/list/A_gases = A.gases - var/trace_gases - for(var/id in A_gases) - if(id in GLOB.hardcoded_gases) - continue - trace_gases = TRUE - break + if(no_teleport && (destination_area.area_flags & NOTELEPORT)) + return - // Can most things breathe? - if(trace_gases) - continue - if(!(A_gases[/datum/gas/oxygen] && A_gases[/datum/gas/oxygen][MOLES] >= 16)) - continue - if(A_gases[/datum/gas/plasma]) - continue - if(A_gases[/datum/gas/carbon_dioxide] && A_gases[/datum/gas/carbon_dioxide][MOLES] >= 10) - continue + var/datum/gas_mixture/floor_gas_mixture = floor_turf.air + if(!floor_gas_mixture) + return - // Aim for goldilocks temperatures and pressure - if((A.temperature <= 270) || (A.temperature >= 360)) - continue - var/pressure = A.return_pressure() - if((pressure <= 20) || (pressure >= 550)) + var/list/floor_gases = floor_gas_mixture.gases + var/trace_gases + for(var/id in floor_gases) + if(id in GLOB.hardcoded_gases) continue + trace_gases = TRUE + break - if(extended_safety_checks) - if(islava(F)) //chasms aren't /floor, and so are pre-filtered - var/turf/open/lava/L = F - if(!L.is_safe()) - continue + // Can most things breathe? + if(trace_gases) + return + if(!(floor_gases[/datum/gas/oxygen] && floor_gases[/datum/gas/oxygen][MOLES] >= 16)) + return + if(floor_gases[/datum/gas/plasma]) + return + if(floor_gases[/datum/gas/carbon_dioxide] && floor_gases[/datum/gas/carbon_dioxide][MOLES] >= 10) + return - // Check that we're not warping onto a table or window - if(!dense_atoms) - var/density_found = FALSE - for(var/atom/movable/found_movable in F) - if(found_movable.density) - density_found = TRUE - break - if(density_found) - continue + // Aim for goldilocks temperatures and pressure + if((floor_gas_mixture.temperature <= 270) || (floor_gas_mixture.temperature >= 360)) + return + var/pressure = floor_gas_mixture.return_pressure() + if((pressure <= 20) || (pressure >= 550)) + return - // DING! You have passed the gauntlet, and are "probably" safe. - return F + if(extended_safety_checks) + if(islava(floor_turf)) //chasms aren't /floor, and so are pre-filtered + var/turf/open/lava/lava_turf = floor_turf // Cyberboss: okay, this makes no sense and I don't understand the above comment, but I'm too lazy to check history to see what it's supposed to do right now + if(!lava_turf.is_safe()) + return + + // Check that we're not warping onto a table or window + if(!dense_atoms) + var/density_found = FALSE + for(var/atom/movable/found_movable in floor_turf) + if(found_movable.density) + density_found = TRUE + break + if(density_found) + return + + // DING! You have passed the gauntlet, and are "probably" safe. + return TRUE /proc/get_teleport_turfs(turf/center, precision = 0) if(!precision) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 72e53f4a170..6406667640d 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -401,19 +401,6 @@ if(!C.wearing_shock_proof_gloves()) new /datum/hallucination/shock(C) return - if(close_others) - for(var/obj/machinery/door/airlock/otherlock as anything in close_others) - if(!shuttledocked && !emergency && !otherlock.shuttledocked && !otherlock.emergency && allowed(user)) - if(otherlock.operating) - otherlock.delayed_close_requested = TRUE - else - addtimer(CALLBACK(otherlock, .proc/close), 2) - if(cyclelinkedairlock) - if(!shuttledocked && !emergency && !cyclelinkedairlock.shuttledocked && !cyclelinkedairlock.emergency && allowed(user)) - if(cyclelinkedairlock.operating) - cyclelinkedairlock.delayed_close_requested = TRUE - else - addtimer(CALLBACK(cyclelinkedairlock, .proc/close), 2) ..() /obj/machinery/door/airlock/proc/isElectrified() @@ -1115,9 +1102,6 @@ return FALSE use_power(50) playsound(src, doorOpen, 30, TRUE) - - if(closeOther != null && istype(closeOther, /obj/machinery/door/airlock/) && !closeOther.density) - closeOther.close() else //playsound(src, 'sound/machines/airlockforced.ogg', 30, TRUE) - ORIGINAL playsound(src, forcedOpen, 30, TRUE) //SKYRAT EDIT CHANGE - AESTHETICS @@ -1127,6 +1111,25 @@ if(!density) return TRUE + + if(closeOther != null && istype(closeOther, /obj/machinery/door/airlock)) + addtimer(CALLBACK(closeOther, .proc/close), 2) + + if(close_others) + for(var/obj/machinery/door/airlock/otherlock as anything in close_others) + if(!shuttledocked && !emergency && !otherlock.shuttledocked && !otherlock.emergency) + if(otherlock.operating) + otherlock.delayed_close_requested = TRUE + else + addtimer(CALLBACK(otherlock, .proc/close), 2) + + if(cyclelinkedairlock) + if(!shuttledocked && !emergency && !cyclelinkedairlock.shuttledocked && !cyclelinkedairlock.emergency) + if(cyclelinkedairlock.operating) + cyclelinkedairlock.delayed_close_requested = TRUE + else + addtimer(CALLBACK(cyclelinkedairlock, .proc/close), 2) + SEND_SIGNAL(src, COMSIG_AIRLOCK_OPEN, forced) operating = TRUE update_icon(ALL, AIRLOCK_OPENING, TRUE) diff --git a/code/game/machinery/doors/airlock_types.dm b/code/game/machinery/doors/airlock_types.dm index 65b1af06731..e69e2a73b16 100644 --- a/code/game/machinery/doors/airlock_types.dm +++ b/code/game/machinery/doors/airlock_types.dm @@ -342,6 +342,42 @@ overlays_file = 'icons/obj/doors/airlocks/external/overlays.dmi' note_overlay_file = 'icons/obj/doors/airlocks/external/overlays.dmi' assemblytype = /obj/structure/door_assembly/door_assembly_ext + req_access = list(ACCESS_EXTERNAL_AIRLOCKS) + + /// Whether or not the airlock can be opened without access from a certain direction while powered, or with bare hands from any direction while unpowered OR pressurized. + var/space_dir = null + +/obj/machinery/door/airlock/external/LateInitialize() + . = ..() + if(space_dir) + unres_sides |= space_dir + +/obj/machinery/door/airlock/external/examine(mob/user) + . = ..() + if(space_dir) + . += span_notice("It has labels indicating that it has an emergency mechanism to open from the [dir2text(space_dir)] side with just your hands even if there's no power.") + +/obj/machinery/door/airlock/external/cyclelinkairlock() + . = ..() + var/obj/machinery/door/airlock/external/cycle_linked_external_airlock = cyclelinkedairlock + if(istype(cycle_linked_external_airlock)) + cycle_linked_external_airlock.space_dir |= space_dir + space_dir |= cycle_linked_external_airlock.space_dir + +/obj/machinery/door/airlock/external/try_safety_unlock(mob/user) + if(space_dir && density) + if(!hasPower()) + to_chat(user, span_notice("You begin unlocking the airlock safety mechanism...")) + if(do_after(user, 15 SECONDS, target = src)) + try_to_crowbar(null, user, TRUE) + return TRUE + else + // always open from the space side + // get_dir(src, user) & space_dir, checked in unresricted_sides + var/should_safety_open = shuttledocked || cyclelinkedairlock?.shuttledocked || is_safe_turf(get_step(src, space_dir), TRUE, FALSE) + return try_to_activate_door(user, should_safety_open) + + return ..() /obj/machinery/door/airlock/external/glass opacity = FALSE diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 59ee8f19f13..c78d3b2106d 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -40,7 +40,6 @@ var/real_explosion_block //ignore this, just use explosion_block var/red_alert_access = FALSE //if TRUE, this door will always open on red alert var/unres_sides = 0 //Unrestricted sides. A bitflag for which direction (if any) can open the door with no access - var/safety_mode = FALSE ///Whether or not the airlock can be opened with bare hands while unpowered var/can_crush = TRUE /// Whether or not the door can crush mobs. @@ -52,8 +51,6 @@ else . += span_notice("In the event of a red alert, its access requirements will automatically lift.") . += span_notice("Its maintenance panel is screwed in place.") - if(safety_mode) - . += span_notice("It has labels indicating that it has an emergency mechanism to open it with just your hands if there's no power.") /obj/machinery/door/check_access_list(list/access_list) if(red_alert_access && SSsecurity_level.current_level >= SEC_LEVEL_RED) @@ -111,11 +108,6 @@ playsound(src, 'sound/machines/boltsup.ogg', 50, TRUE) /obj/machinery/door/proc/try_safety_unlock(mob/user) - if(safety_mode && !hasPower() && density) - to_chat(user, span_notice("You begin unlocking the airlock safety mechanism...")) - if(do_after(user, 15 SECONDS, target = src)) - try_to_crowbar(null, user) - return TRUE return FALSE /** @@ -204,13 +196,12 @@ return ..() -/obj/machinery/door/proc/try_to_activate_door(mob/user) +/obj/machinery/door/proc/try_to_activate_door(mob/user, access_bypass = FALSE) add_fingerprint(user) if(operating || (obj_flags & EMAGGED)) return - if(!requiresID()) - user = null //so allowed(user) always succeeds - if(allowed(user)) + access_bypass |= !requiresID() + if(access_bypass || allowed(user)) if(density) open() else diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index f80741c278c..0d92e5ca0b8 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -124,7 +124,7 @@ return return ..() -/obj/machinery/door/firedoor/try_to_activate_door(mob/user) +/obj/machinery/door/firedoor/try_to_activate_door(mob/user, access_bypass = FALSE) return /obj/machinery/door/firedoor/try_to_weld(obj/item/weldingtool/W, mob/user) diff --git a/code/game/machinery/doors/passworddoor.dm b/code/game/machinery/doors/passworddoor.dm index 4537484ad8b..543ddbc4768 100644 --- a/code/game/machinery/doors/passworddoor.dm +++ b/code/game/machinery/doors/passworddoor.dm @@ -32,12 +32,12 @@ /obj/machinery/door/password/Bumped(atom/movable/AM) return !density && ..() -/obj/machinery/door/password/try_to_activate_door(mob/user) +/obj/machinery/door/password/try_to_activate_door(mob/user, access_bypass = FALSE) add_fingerprint(user) if(operating) return if(density) - if(ask_for_pass(user)) + if(access_bypass || ask_for_pass(user)) open() else do_animate("deny") diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 36acb2e9947..f6e0c8c3331 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -302,7 +302,7 @@ /obj/machinery/door/window/interact(mob/user) //for sillycones try_to_activate_door(user) -/obj/machinery/door/window/try_to_activate_door(mob/user) +/obj/machinery/door/window/try_to_activate_door(mob/user, access_bypass = FALSE) if (..()) autoclose = FALSE diff --git a/code/game/objects/items/puzzle_pieces.dm b/code/game/objects/items/puzzle_pieces.dm index 174a1c34c61..6f7e8af9e07 100644 --- a/code/game/objects/items/puzzle_pieces.dm +++ b/code/game/objects/items/puzzle_pieces.dm @@ -57,7 +57,7 @@ /obj/machinery/door/keycard/ex_act(severity, target) return FALSE -/obj/machinery/door/keycard/try_to_activate_door(mob/user) +/obj/machinery/door/keycard/try_to_activate_door(mob/user, access_bypass = FALSE) add_fingerprint(user) if(operating) return diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm index 8ad3b489b42..8d4ec34450d 100644 --- a/code/modules/shuttle/on_move.dm +++ b/code/modules/shuttle/on_move.dm @@ -197,19 +197,19 @@ All ShuttleMove procs go here /obj/machinery/door/airlock/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock) . = ..() - for(var/obj/machinery/door/airlock/A in range(1, src)) // includes src - A.shuttledocked = FALSE - A.air_tight = TRUE - INVOKE_ASYNC(A, /obj/machinery/door/.proc/close) + for(var/obj/machinery/door/airlock/other_airlock in range(2, src)) // includes src, extended because some escape pods have 1 plating turf exposed to space + other_airlock.shuttledocked = FALSE + other_airlock.air_tight = TRUE + INVOKE_ASYNC(other_airlock, /obj/machinery/door/.proc/close, FALSE, TRUE) // force crush /obj/machinery/door/airlock/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() var/current_area = get_area(src) - for(var/obj/machinery/door/airlock/A in orange(1, src)) // does not include src - if(get_area(A) != current_area) // does not include double-wide airlocks unless actually docked + for(var/obj/machinery/door/airlock/other_airlock in orange(2, src)) // does not include src, extended because some escape pods have 1 plating turf exposed to space + if(get_area(other_airlock) != current_area) // does not include double-wide airlocks unless actually docked // Cycle linking is only disabled if we are actually adjacent to another airlock shuttledocked = TRUE - A.shuttledocked = TRUE + other_airlock.shuttledocked = TRUE /obj/machinery/camera/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock) . = ..()