diff --git a/_maps/map_files/YogStation/YogStation.dmm b/_maps/map_files/YogStation/YogStation.dmm
index b3bba9670734..1b49bd60d29c 100644
--- a/_maps/map_files/YogStation/YogStation.dmm
+++ b/_maps/map_files/YogStation/YogStation.dmm
@@ -22074,22 +22074,6 @@
},
/turf/open/floor/plasteel,
/area/quartermaster/qm)
-"boX" = (
-/obj/machinery/door/poddoor/shutters/preopen{
- id = "hopqueue";
- name = "HoP Queue Shutters"
- },
-/obj/effect/turf_decal/loading_area{
- dir = 8
- },
-/obj/machinery/door/firedoor/border_only{
- dir = 4
- },
-/obj/machinery/door/firedoor/border_only{
- dir = 8
- },
-/turf/open/floor/plasteel,
-/area/hallway/primary/central)
"boY" = (
/obj/effect/turf_decal/tile/red,
/obj/effect/turf_decal/tile/red{
@@ -24274,22 +24258,6 @@
},
/turf/open/floor/plating,
/area/maintenance/port)
-"bwg" = (
-/obj/machinery/door/poddoor/shutters/preopen{
- id = "hopqueue";
- name = "HoP Queue Shutters"
- },
-/obj/effect/turf_decal/loading_area{
- dir = 4
- },
-/obj/machinery/door/firedoor/border_only{
- dir = 4
- },
-/obj/machinery/door/firedoor/border_only{
- dir = 8
- },
-/turf/open/floor/plasteel,
-/area/hallway/primary/central)
"bwh" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{
dir = 4
@@ -36493,6 +36461,25 @@
/obj/structure/lattice/catwalk,
/turf/open/space/basic,
/area/solar/port/aft)
+"fan" = (
+/obj/machinery/door/poddoor/shutters/preopen{
+ id = "hopqueue";
+ name = "HoP Queue Shutters"
+ },
+/obj/effect/turf_decal/loading_area{
+ dir = 8
+ },
+/obj/machinery/door/firedoor/border_only{
+ dir = 4
+ },
+/obj/machinery/door/firedoor/border_only{
+ dir = 8
+ },
+/obj/machinery/ministile/hop{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/hallway/primary/central)
"faE" = (
/obj/structure/closet/crate/freezer,
/obj/item/reagent_containers/blood,
@@ -37507,6 +37494,25 @@
},
/turf/open/floor/circuit,
/area/ai_monitored/turret_protected/ai)
+"fMu" = (
+/obj/machinery/door/poddoor/shutters/preopen{
+ id = "hopqueue";
+ name = "HoP Queue Shutters"
+ },
+/obj/effect/turf_decal/loading_area{
+ dir = 4
+ },
+/obj/machinery/door/firedoor/border_only{
+ dir = 4
+ },
+/obj/machinery/door/firedoor/border_only{
+ dir = 8
+ },
+/obj/machinery/ministile/hop{
+ dir = 8
+ },
+/turf/open/floor/plasteel,
+/area/hallway/primary/central)
"fMS" = (
/obj/effect/mapping_helpers/airlock/cyclelink_helper{
dir = 8
@@ -92124,12 +92130,12 @@ mlj
bkT
mlj
mlj
-boX
+fan
nfX
ehN
vZM
cmg
-bwg
+fMu
aJw
aJq
aJq
diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm
index a7d40547b021..4edc9ae21b1b 100644
--- a/code/game/machinery/_machinery.dm
+++ b/code/game/machinery/_machinery.dm
@@ -125,6 +125,10 @@ Class Procs:
var/payment_department = ACCOUNT_ENG
/// For storing and overriding ui id
var/tgui_id // ID of TGUI interface
+ var/climbable = FALSE
+ var/climb_time = 20
+ var/climb_stun = 20
+ var/mob/living/machineclimber
/obj/machinery/Initialize()
if(!armor)
@@ -580,3 +584,52 @@ Class Procs:
/obj/machinery/rust_heretic_act()
take_damage(500, BRUTE, "melee", 1)
+
+/obj/machinery/MouseDrop_T(atom/movable/O, mob/user)
+ . = ..()
+ if(!climbable)
+ return
+ if(user == O && iscarbon(O))
+ var/mob/living/carbon/C = O
+ if(C.mobility_flags & MOBILITY_MOVE)
+ climb_machine(user)
+ return
+ if(!istype(O, /obj/item) || user.get_active_held_item() != O)
+ return
+ if(iscyborg(user))
+ return
+ if(!user.dropItemToGround(O))
+ return
+ if (O.loc != src.loc)
+ step(O, get_dir(O, src))
+
+/obj/machinery/proc/do_climb(atom/movable/A)
+ if(climbable)
+ density = FALSE
+ . = step(A,get_dir(A,src.loc))
+ density = TRUE
+
+/obj/machinery/proc/climb_machine(mob/living/user)
+ src.add_fingerprint(user)
+ user.visible_message("[user] starts climbing onto [src].", \
+ "You start climbing onto [src]...")
+ var/adjusted_climb_time = climb_time
+ if(user.restrained()) //climbing takes twice as long when restrained.
+ adjusted_climb_time *= 2
+ if(isalien(user))
+ adjusted_climb_time *= 0.25 //aliens are terrifyingly fast
+ if(HAS_TRAIT(user, TRAIT_FREERUNNING)) //do you have any idea how fast I am???
+ adjusted_climb_time *= 0.8
+ machineclimber = user
+ if(do_mob(user, user, adjusted_climb_time))
+ if(src.loc) //Checking if structure has been destroyed
+ if(do_climb(user))
+ user.visible_message("[user] climbs onto [src].", \
+ "You climb onto [src].")
+ log_combat(user, src, "climbed onto")
+ if(climb_stun)
+ user.Stun(climb_stun)
+ . = 1
+ else
+ to_chat(user, "You fail to climb onto [src].")
+ machineclimber = null
diff --git a/code/game/machinery/doors/ministile.dm b/code/game/machinery/doors/ministile.dm
new file mode 100644
index 000000000000..50ab911a34e8
--- /dev/null
+++ b/code/game/machinery/doors/ministile.dm
@@ -0,0 +1,48 @@
+/obj/machinery/ministile
+ name = "ministile"
+ desc = "A mechanical door that permits one-way access to an area."
+ icon = 'icons/obj/objects.dmi'
+ icon_state = "ministile_map"
+ power_channel = ENVIRON
+ density = TRUE
+ obj_integrity = 150
+ max_integrity = 150
+ //Smaller turnstile easier to smash
+ armor = list("melee" = 30, "bullet" = 20, "laser" = 0, "energy" = 60, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 50)
+ anchored = TRUE
+ use_power = FALSE
+ idle_power_usage = 2
+ resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
+ layer = OPEN_DOOR_LAYER
+ climbable = TRUE
+
+/obj/machinery/ministile/hop
+ name = "HOP line turnstile"
+ req_one_access = list(ACCESS_HEADS)
+
+/obj/machinery/ministile/Initialize()
+ . = ..()
+ icon_state = "ministile"
+
+/obj/machinery/ministile/CanAtmosPass(turf/T)
+ return TRUE
+
+/obj/machinery/ministile/Cross(atom/movable/mover)
+ . = ..()
+ if(istype(mover) && (mover.pass_flags & PASSGLASS))
+ return TRUE
+ if(!isliving(mover))
+ return TRUE
+ var/allowed = allowed(mover)
+ //Sec can drag you out unceremoniously.
+ if(!allowed && mover.pulledby)
+ allowed = allowed(mover.pulledby)
+
+ if(get_dir(loc, mover.loc) == dir || allowed || mover==machineclimber) //Make sure looking at appropriate border, loc is first so the turnstyle faces the mover
+ flick("ministile_operate", src)
+ playsound(src,'sound/items/ratchet.ogg',50,0,3)
+ return TRUE
+ else
+ flick("ministile_deny", src)
+ playsound(src,'sound/machines/deniedbeep.ogg',50,0,3)
+ return FALSE
diff --git a/code/game/machinery/doors/turnstile.dm b/code/game/machinery/doors/turnstile.dm
new file mode 100644
index 000000000000..db44bd4a1ca2
--- /dev/null
+++ b/code/game/machinery/doors/turnstile.dm
@@ -0,0 +1,48 @@
+/obj/machinery/turnstile
+ name = "turnstile"
+ desc = "A mechanical door that permits one-way access to an area."
+ icon = 'icons/obj/objects.dmi'
+ icon_state = "turnstile_map"
+ power_channel = ENVIRON
+ density = TRUE
+ obj_integrity = 250
+ max_integrity = 250
+ //Robust! It'll be tough to break...
+ armor = list("melee" = 50, "bullet" = 20, "laser" = 0, "energy" = 80, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 50)
+ anchored = TRUE
+ use_power = FALSE
+ idle_power_usage = 2
+ resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
+ layer = OPEN_DOOR_LAYER
+ climbable = FALSE
+/obj/machinery/turnstile/brig
+ name = "Brig turnstile"
+ //Seccies and brig phys may always pass, either way.
+ req_one_access = list(ACCESS_BRIG)
+
+/obj/machinery/turnstile/Initialize()
+ . = ..()
+ icon_state = "turnstile"
+
+/obj/machinery/turnstile/CanAtmosPass(turf/T)
+ return TRUE
+
+/obj/machinery/turnstile/Cross(atom/movable/mover)
+ . = ..()
+ if(istype(mover) && (mover.pass_flags & PASSGLASS))
+ return TRUE
+ if(!isliving(mover))
+ return TRUE
+ var/allowed = allowed(mover)
+ //Sec can drag you out unceremoniously.
+ if(!allowed && mover.pulledby)
+ allowed = allowed(mover.pulledby)
+
+ if(get_dir(loc, mover.loc) == dir || allowed) //Make sure looking at appropriate border, loc is first so the turnstyle faces the mover
+ flick("operate", src)
+ playsound(src,'sound/items/ratchet.ogg',50,0,3)
+ return TRUE
+ else
+ flick("deny", src)
+ playsound(src,'sound/machines/deniedbeep.ogg',50,0,3)
+ return FALSE
diff --git a/icons/obj/objects.dmi b/icons/obj/objects.dmi
index 93b75c1f81fb..9966531023bd 100644
Binary files a/icons/obj/objects.dmi and b/icons/obj/objects.dmi differ
diff --git a/yogstation.dme b/yogstation.dme
index 041b02ebeeff..67880a8277c1 100644
--- a/yogstation.dme
+++ b/yogstation.dme
@@ -785,9 +785,11 @@
#include "code\game\machinery\doors\checkForMultipleDoors.dm"
#include "code\game\machinery\doors\door.dm"
#include "code\game\machinery\doors\firedoor.dm"
+#include "code\game\machinery\doors\ministile.dm"
#include "code\game\machinery\doors\passworddoor.dm"
#include "code\game\machinery\doors\poddoor.dm"
#include "code\game\machinery\doors\shutters.dm"
+#include "code\game\machinery\doors\turnstile.dm"
#include "code\game\machinery\doors\unpowered.dm"
#include "code\game\machinery\doors\windowdoor.dm"
#include "code\game\machinery\embedded_controller\access_controller.dm"