diff --git a/code/game/objects/items/pet_carrier.dm b/code/game/objects/items/pet_carrier.dm
new file mode 100644
index 0000000000..dfec9ca2b8
--- /dev/null
+++ b/code/game/objects/items/pet_carrier.dm
@@ -0,0 +1,194 @@
+#define pet_carrier_full(carrier) carrier.occupants.len >= carrier.max_occupants || carrier.occupant_weight >= carrier.max_occupant_weight
+
+//Used to transport little animals without having to drag them across the station.
+//Comes with a handy lock to prevent them from running off.
+/obj/item/pet_carrier
+ name = "pet carrier"
+ desc = "A big white-and-blue pet carrier. Good for carrying meat to the chef cute animals around."
+ icon = 'icons/obj/pet_carrier.dmi'
+ icon_state = "pet_carrier_open"
+ item_state = "pet_carrier"
+ lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/items_righthand.dmi'
+ force = 5
+ attack_verb = list("bashed", "carried")
+ w_class = WEIGHT_CLASS_BULKY
+ throw_speed = 2
+ throw_range = 3
+ materials = list(MAT_METAL = 7500, MAT_GLASS = 100)
+ var/open = TRUE
+ var/locked = FALSE
+ var/list/occupants = list()
+ var/occupant_weight = 0
+ var/max_occupants = 3 //Hard-cap so you can't have infinite mice or something in one carrier
+ var/max_occupant_weight = MOB_SIZE_SMALL //This is calculated from the mob sizes of occupants
+
+/obj/item/pet_carrier/Destroy()
+ if(occupants.len)
+ for(var/V in occupants)
+ remove_occupant(V)
+ return ..()
+
+/obj/item/pet_carrier/Exited(atom/movable/occupant)
+ if(occupant in occupants && isliving(occupant))
+ var/mob/living/L = occupant
+ occupants -= occupant
+ occupant_weight -= L.mob_size
+
+/obj/item/pet_carrier/handle_atom_del(atom/A)
+ if(A in occupants && isliving(A))
+ var/mob/living/L = A
+ occupants -= L
+ occupant_weight -= L.mob_size
+ ..()
+
+/obj/item/pet_carrier/examine(mob/user)
+ ..()
+ if(occupants.len)
+ for(var/V in occupants)
+ var/mob/living/L = V
+ to_chat(user, "It has [L] inside.")
+ else
+ to_chat(user, "It has nothing inside.")
+ if(user.canUseTopic(src))
+ to_chat(user, "Activate it in your hand to [open ? "close" : "open"] its door.")
+ if(!open)
+ to_chat(user, "Alt-click to [locked ? "unlock" : "lock"] its door.")
+
+/obj/item/pet_carrier/attack_self(mob/living/user)
+ if(open)
+ to_chat(user, "You close [src]'s door.")
+ playsound(user, 'sound/effects/bin_close.ogg', 50, TRUE)
+ open = FALSE
+ else
+ if(locked)
+ to_chat(user, "[src] is locked!")
+ return
+ to_chat(user, "You open [src]'s door.")
+ playsound(user, 'sound/effects/bin_open.ogg', 50, TRUE)
+ open = TRUE
+ update_icon()
+
+/obj/item/pet_carrier/AltClick(mob/living/user)
+ if(open)
+ return
+ locked = !locked
+ to_chat(user, "You flip the lock switch [locked ? "down" : "up"].")
+ if(locked)
+ playsound(user, 'sound/machines/boltsdown.ogg', 30, TRUE)
+ else
+ playsound(user, 'sound/machines/boltsup.ogg', 30, TRUE)
+ update_icon()
+
+/obj/item/pet_carrier/attack(mob/living/target, mob/living/user)
+ if(user.a_intent == INTENT_HARM)
+ return ..()
+ if(!open)
+ to_chat(user, "You need to open [src]'s door!")
+ return
+ if(target.mob_size > max_occupant_weight)
+ if(ishuman(target))
+ var/mob/living/carbon/human/H = target
+ if(iscatperson(H))
+ to_chat(user, "You'd need a lot of catnip and treats, plus maybe a laser pointer, for that to work.")
+ else
+ to_chat(user, "Humans, generally, do not fit into pet carriers.")
+ else
+ to_chat(user, "You get the feeling [target] isn't meant for a [name].")
+ return
+ if(user == target)
+ to_chat(user, "Why would you ever do that?")
+ return
+ load_occupant(user, target)
+
+/obj/item/pet_carrier/relaymove(mob/living/user, direction)
+ if(open)
+ loc.visible_message("[user] climbs out of [src]!", \
+ "[user] jumps out of [src]!")
+ remove_occupant(user)
+ return
+ else if(!locked)
+ loc.visible_message("[user] pushes open the door to [src]!", \
+ "[user] pushes open the door of [src]!")
+ open = TRUE
+ update_icon()
+ return
+ else if(user.client)
+ container_resist(user)
+
+/obj/item/pet_carrier/container_resist(mob/living/user)
+ user.changeNext_move(CLICK_CD_BREAKOUT)
+ user.last_special = world.time + CLICK_CD_BREAKOUT
+ if(user.mob_size <= MOB_SIZE_SMALL)
+ to_chat(user, "You poke a limb through [src]'s bars and start fumbling for the lock switch... (This will take some time.)")
+ to_chat(loc, "You see [user] reach through the bars and fumble for the lock switch!")
+ if(!do_after(user, rand(300, 400), target = user) || open || !locked || !user in occupants)
+ return
+ loc.visible_message("[user] flips the lock switch on [src] by reaching through!", ignored_mob = user)
+ to_chat(user, "Bingo! The lock pops open!")
+ locked = FALSE
+ playsound(src, 'sound/machines/boltsup.ogg', 30, TRUE)
+ update_icon()
+ else
+ loc.visible_message("[src] starts rattling as something pushes against the door!", ignored_mob = user)
+ to_chat(user, "You start pushing out of [src]... (This will take about 20 seconds.)")
+ if(!do_after(user, 200, target = user) || open || !locked || !user in occupants)
+ return
+ loc.visible_message("[user] shoves out of [src]!", ignored_mob = user)
+ to_chat(user, "You shove open [src]'s door against the lock's resistance and fall out!")
+ locked = FALSE
+ open = TRUE
+ update_icon()
+ remove_occupant(user)
+
+/obj/item/pet_carrier/update_icon()
+ cut_overlay("unlocked")
+ cut_overlay("locked")
+ if(open)
+ icon_state = initial(icon_state)
+ else
+ icon_state = "pet_carrier_[!occupants.len ? "closed" : "occupied"]"
+ add_overlay("[locked ? "" : "un"]locked")
+
+/obj/item/pet_carrier/MouseDrop(atom/over_atom)
+ if(isopenturf(over_atom) && usr.Adjacent(over_atom) && open && occupants.len)
+ usr.visible_message("[usr] unloads [src].", \
+ "You unload [src] onto [over_atom].")
+ for(var/V in occupants)
+ remove_occupant(V, over_atom)
+
+/obj/item/pet_carrier/proc/load_occupant(mob/living/user, mob/living/target)
+ if(pet_carrier_full(src))
+ to_chat(user, "[src] is already carrying too much!")
+ return
+ user.visible_message("[user] starts loading [target] into [src].", \
+ "You start loading [target] into [src]...", ignored_mob = target)
+ to_chat(target, "[user] starts loading you into their [name]!")
+ if(!do_mob(user, target, 30))
+ return
+ if(target in occupants)
+ return
+ if(pet_carrier_full(src)) //Run the checks again, just in case
+ to_chat(user, "[src] is already carrying too much!")
+ return
+ user.visible_message("[user] loads [target] into [src]!", \
+ "You load [target] into [src].", ignored_mob = target)
+ to_chat(target, "[user] loads you into their [name]!")
+ add_occupant(target)
+
+/obj/item/pet_carrier/proc/add_occupant(mob/living/occupant)
+ if(occupant in occupants || !istype(occupant))
+ return
+ occupant.forceMove(src)
+ occupants += occupant
+ occupant_weight += occupant.mob_size
+
+/obj/item/pet_carrier/proc/remove_occupant(mob/living/occupant, turf/new_turf)
+ if(!occupant in occupants || !istype(occupant))
+ return
+ occupant.forceMove(new_turf ? new_turf : drop_location())
+ occupants -= occupant
+ occupant_weight -= occupant.mob_size
+ occupant.setDir(SOUTH)
+
+#undef pet_carrier_full
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm
index 0351fdc596..dfd9ac8153 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm
@@ -73,6 +73,11 @@
new /obj/item/device/autosurgeon/cmo(src)
new /obj/item/door_remote/chief_medical_officer(src)
new /obj/item/clothing/neck/petcollar(src)
+<<<<<<< HEAD
+=======
+ new /obj/item/pet_carrier(src)
+ new /obj/item/circuitboard/machine/protolathe/department/medical(src)
+>>>>>>> 6e8401e... Adds pet carriers (#33231)
/obj/structure/closet/secure_closet/animal
name = "animal control"
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
index 3cb3edb8c2..7f36acaae9 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
@@ -12,6 +12,7 @@
new /obj/item/storage/backpack/satchel/cap(src)
new /obj/item/clothing/neck/cloak/cap(src)
new /obj/item/clothing/neck/petcollar(src)
+ new /obj/item/pet_carrier(src)
new /obj/item/storage/backpack/duffelbag/captain(src)
new /obj/item/clothing/head/crown/fancy(src)
new /obj/item/clothing/suit/captunic(src)
@@ -53,6 +54,7 @@
new /obj/item/restraints/handcuffs/cable/zipties(src)
new /obj/item/gun/energy/e_gun/cx(src)
new /obj/item/clothing/neck/petcollar(src)
+ new /obj/item/pet_carrier(src)
new /obj/item/door_remote/civillian(src)
/obj/structure/closet/secure_closet/hos
diff --git a/code/modules/research/designs/autolathe_designs.dm b/code/modules/research/designs/autolathe_designs.dm
index d8ace5f9c9..39fd0bf182 100644
--- a/code/modules/research/designs/autolathe_designs.dm
+++ b/code/modules/research/designs/autolathe_designs.dm
@@ -800,6 +800,13 @@
build_path = /obj/item/device/slime_scanner
category = list("initial", "Misc")
+/datum/design/pet_carrier
+ name = "Pet Carrier"
+ id = "pet_carrier"
+ build_type = AUTOLATHE
+ materials = list(MAT_METAL = 7500, MAT_GLASS = 100)
+ build_path = /obj/item/pet_carrier
+
/datum/design/miniature_power_cell
name = "Light Fixture Battery"
id = "miniature_power_cell"
diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi
index 198c2ee663..9a7b318e19 100644
Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ
diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi
index cef6409ca2..9d9350e644 100644
Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ
diff --git a/icons/obj/pet_carrier.dmi b/icons/obj/pet_carrier.dmi
new file mode 100644
index 0000000000..340636056c
Binary files /dev/null and b/icons/obj/pet_carrier.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index e8b81cbbb8..82f0230c72 100755
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -870,6 +870,7 @@
#include "code\game\objects\items\mop.dm"
#include "code\game\objects\items\paint.dm"
#include "code\game\objects\items\paiwire.dm"
+#include "code\game\objects\items\pet_carrier.dm"
#include "code\game\objects\items\pinpointer.dm"
#include "code\game\objects\items\plushes.dm"
#include "code\game\objects\items\pneumaticCannon.dm"