diff --git a/code/modules/vehicles/Securitrain_vr.dm b/code/modules/vehicles/Securitrain_vr.dm
new file mode 100644
index 00000000000..b3698560d64
--- /dev/null
+++ b/code/modules/vehicles/Securitrain_vr.dm
@@ -0,0 +1,423 @@
+//This is the initial set up for the new carts. Feel free to improve and/or rewrite everything here.
+//I don't know what the hell I'm doing right now. Please help. Especially with the update_icons stuff. -Joan Risu
+
+/obj/vehicle/train/securiengine
+ name = "Security Cart"
+ desc = "A ridable electric car designed for pulling trolleys as well as personal transport."
+ icon = 'icons/obj/vehicles_vr.dmi'
+ icon_state = "paddywagon"
+ on = 0
+ powered = 1
+ locked = 0
+ move_delay = 0.5
+
+ //Health stuff
+ health = 100
+ maxhealth = 100
+ fire_dam_coeff = 0.6
+ brute_dam_coeff = 0.5
+
+ load_item_visible = 1
+ load_offset_x = 0
+ mob_offset_y = 7
+
+ var/car_limit = 0 //how many cars an engine can pull before performance degrades. This should be 0 to prevent trailers from unhitching.
+ active_engines = 1
+ var/obj/item/weapon/key/securitrain/key
+ var/siren = 0 //This is for eventually getting the siren sprite to work.
+
+/obj/item/weapon/key/securitrain
+ name = "The Security Cart key"
+ desc = "The Security Cart Key used to start it."
+ icon = 'icons/obj/vehicles_vr.dmi'
+ icon_state = "securikey"
+ w_class = 1
+
+/obj/vehicle/train/securitrolley
+ name = "Train trolley"
+ desc = "A trolly designed to transport security personnel or prisoners."
+ icon = 'icons/obj/vehicles_vr.dmi'
+ icon_state = "paddy_trailer"
+ anchored = 0
+ passenger_allowed = 1
+ locked = 0
+
+ load_item_visible = 1
+ load_offset_x = 0
+ load_offset_y = 4
+ mob_offset_y = 8
+
+/obj/vehicle/train/securitrolley/cargo
+ name = "Train trolley"
+ desc = "A trolley designed to transport security equipment to a scene."
+ icon = 'icons/obj/vehicles_vr.dmi'
+ icon_state = "secitemcarrierbot"
+ passenger_allowed = 0 //Stick a man inside the box. :v
+ load_item_visible = 0 //The load is supposed to be invisible.
+
+//-------------------------------------------
+// Standard procs
+//-------------------------------------------
+/obj/vehicle/train/securiengine/New()
+ ..()
+ cell = new /obj/item/weapon/cell/high(src)
+ key = new(src)
+ var/image/I = new(icon = 'icons/obj/vehicles_vr.dmi', icon_state = null, layer = src.layer + 0.2) //over mobs
+ overlays += I
+ turn_off() //so engine verbs are correctly set
+
+/obj/vehicle/train/securiengine/Move(var/turf/destination)
+ if(on && cell.charge < charge_use)
+ turn_off()
+ update_stats()
+ if(load && is_train_head())
+ load << "The drive motor briefly whines, then drones to a stop."
+
+ if(is_train_head() && !on)
+ return 0
+
+ //space check ~no flying space trains sorry
+ if(on && istype(destination, /turf/space))
+ return 0
+
+ return ..()
+
+/obj/vehicle/train/securitrolley/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if(open && istype(W, /obj/item/weapon/wirecutters))
+ passenger_allowed = !passenger_allowed
+ user.visible_message("[user] [passenger_allowed ? "cuts" : "mends"] a cable in [src].","You [passenger_allowed ? "cut" : "mend"] the load limiter cable.")
+ else
+ ..()
+
+/obj/vehicle/train/securiengine/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if(istype(W, /obj/item/weapon/key/securitrain))
+ if(!key)
+ user.drop_item()
+ W.forceMove(src)
+ key = W
+ verbs += /obj/vehicle/train/securiengine/verb/remove_key
+ return
+ ..()
+
+//cargo trains are open topped, so there is a chance the projectile will hit the mob ridding the train instead
+/obj/vehicle/train/securitrolley/bullet_act(var/obj/item/projectile/Proj)
+ if(buckled_mob && prob(70))
+ buckled_mob.bullet_act(Proj)
+ return
+ ..()
+
+/obj/vehicle/train/securitrolley/update_icon()
+ if(open)
+ icon_state = initial(icon_state) + "_open"
+ else
+ icon_state = initial(icon_state)
+
+/obj/vehicle/train/securitrolley/insert_cell(var/obj/item/weapon/cell/C, var/mob/living/carbon/human/H)
+ return
+
+/obj/vehicle/train/securiengine/insert_cell(var/obj/item/weapon/cell/C, var/mob/living/carbon/human/H)
+ ..()
+ update_stats()
+
+/obj/vehicle/train/securiengine/remove_cell(var/mob/living/carbon/human/H)
+ ..()
+ update_stats()
+
+/obj/vehicle/train/securiengine/Bump(atom/Obstacle)
+ var/obj/machinery/door/D = Obstacle
+ var/mob/living/carbon/human/H = load
+ if(istype(D) && istype(H))
+ D.Bumped(H) //a little hacky, but hey, it works, and respects access rights
+
+ ..()
+
+/obj/vehicle/train/securitrolley/Bump(atom/Obstacle)
+ if(!lead)
+ return //so people can't knock others over by pushing a trolley around
+ ..()
+
+//-------------------------------------------
+// Train procs
+//-------------------------------------------
+/obj/vehicle/train/securiengine/turn_on()
+ if(!key)
+ return
+ else
+ ..()
+ update_stats()
+
+ verbs -= /obj/vehicle/train/securiengine/verb/stop_engine
+ verbs -= /obj/vehicle/train/securiengine/verb/start_engine
+
+ if(on)
+ verbs += /obj/vehicle/train/securiengine/verb/stop_engine
+ else
+ verbs += /obj/vehicle/train/securiengine/verb/start_engine
+
+/obj/vehicle/train/securiengine/turn_off()
+ ..()
+
+ verbs -= /obj/vehicle/train/securiengine/verb/stop_engine
+ verbs -= /obj/vehicle/train/securiengine/verb/start_engine
+
+ if(!on)
+ verbs += /obj/vehicle/train/securiengine/verb/start_engine
+ else
+ verbs += /obj/vehicle/train/securiengine/verb/stop_engine
+
+/obj/vehicle/train/securitrolley/RunOver(var/mob/living/carbon/human/H)
+ var/list/parts = list(BP_HEAD, BP_TORSO, BP_L_LEG, BP_R_LEG, BP_L_ARM, BP_R_ARM)
+
+ H.apply_effects(5, 5)
+ for(var/i = 0, i < rand(1,3), i++)
+ H.apply_damage(rand(1,5), BRUTE, pick(parts))
+
+/obj/vehicle/train/securitrolley/RunOver(var/mob/living/carbon/human/H)
+ ..()
+ attack_log += text("\[[time_stamp()]\] ran over [H.name] ([H.ckey])")
+
+/obj/vehicle/train/securiengine/RunOver(var/mob/living/carbon/human/H)
+ ..()
+
+ if(is_train_head() && istype(load, /mob/living/carbon/human))
+ var/mob/living/carbon/human/D = load
+ D << "\red \b You ran over [H]!"
+ visible_message("\red \The [src] ran over [H]!")
+ attack_log += text("\[[time_stamp()]\] ran over [H.name] ([H.ckey]), driven by [D.name] ([D.ckey])")
+ msg_admin_attack("[D.name] ([D.ckey]) ran over [H.name] ([H.ckey]). (JMP)")
+ else
+ attack_log += text("\[[time_stamp()]\] ran over [H.name] ([H.ckey])")
+
+
+//-------------------------------------------
+// Interaction procs
+//-------------------------------------------
+/obj/vehicle/train/securiengine/relaymove(mob/user, direction)
+ if(user != load)
+ return 0
+
+ if(is_train_head())
+ if(direction == reverse_direction(dir) && tow)
+ return 0
+ if(Move(get_step(src, direction)))
+ return 1
+ return 0
+ else
+ return ..()
+
+
+/obj/vehicle/train/securiengine/examine(mob/user)
+ if(!..(user, 1))
+ return
+
+ if(!istype(usr, /mob/living/carbon/human))
+ return
+
+ user << "The power light is [on ? "on" : "off"].\nThere are[key ? "" : " no"] keys in the ignition."
+ user << "The charge meter reads [cell? round(cell.percent(), 0.01) : 0]%"
+
+/obj/vehicle/train/securiengine/verb/start_engine()
+ set name = "Start engine"
+ set category = "Vehicle"
+ set src in view(0)
+
+ if(!istype(usr, /mob/living/carbon/human))
+ return
+
+ if(on)
+ usr << "The engine is already running."
+ return
+
+ turn_on()
+ if (on)
+ usr << "You start [src]'s engine."
+ else
+ if(cell.charge < charge_use)
+ usr << "[src] is out of power."
+ else
+ usr << "[src]'s engine won't start."
+
+/obj/vehicle/train/securiengine/verb/stop_engine()
+ set name = "Stop engine"
+ set category = "Vehicle"
+ set src in view(0)
+
+ if(!istype(usr, /mob/living/carbon/human))
+ return
+
+ if(!on)
+ usr << "The engine is already stopped."
+ return
+
+ turn_off()
+ if (!on)
+ usr << "You stop [src]'s engine."
+
+/obj/vehicle/train/securiengine/verb/remove_key()
+ set name = "Remove key"
+ set category = "Vehicle"
+ set src in view(0)
+
+ if(!istype(usr, /mob/living/carbon/human))
+ return
+
+ if(!key || (load && load != usr))
+ return
+
+ if(on)
+ turn_off()
+
+ key.loc = usr.loc
+ if(!usr.get_active_hand())
+ usr.put_in_hands(key)
+ key = null
+
+ verbs -= /obj/vehicle/train/securiengine/verb/remove_key
+
+//-------------------------------------------
+// Loading/unloading procs
+//-------------------------------------------
+/obj/vehicle/train/securitrolley/load(var/atom/movable/C)
+ if(ismob(C) && !passenger_allowed)
+ return 0
+ if(!istype(C,/obj/machinery) && !istype(C,/obj/structure/closet) && !istype(C,/obj/structure/largecrate) && !istype(C,/obj/structure/reagent_dispensers) && !istype(C,/obj/structure/ore_box) && !istype(C, /mob/living/carbon/human))
+ return 0
+
+ //if there are any items you don't want to be able to interact with, add them to this check
+ // ~no more shielded, emitter armed death trains
+ if(istype(C, /obj/machinery))
+ load_object(C)
+ else
+ ..()
+
+ if(load)
+ return 1
+
+/obj/vehicle/train/securiengine/load(var/atom/movable/C)
+ if(!istype(C, /mob/living/carbon/human))
+ return 0
+
+ return ..()
+
+//Load the object "inside" the trolley and add an overlay of it.
+//This prevents the object from being interacted with until it has
+// been unloaded. A dummy object is loaded instead so the loading
+// code knows to handle it correctly.
+/obj/vehicle/train/securitrolley/proc/load_object(var/atom/movable/C)
+ if(!isturf(C.loc)) //To prevent loading things from someone's inventory, which wouldn't get handled properly.
+ return 0
+ if(load || C.anchored)
+ return 0
+
+ var/datum/vehicle_dummy_load/dummy_load = new()
+ load = dummy_load
+
+ if(!load)
+ return
+ dummy_load.actual_load = C
+ C.forceMove(src)
+
+ if(load_item_visible)
+ C.pixel_x += load_offset_x
+ C.pixel_y += load_offset_y
+ C.layer = layer
+
+ overlays += C
+
+ //we can set these back now since we have already cloned the icon into the overlay
+ C.pixel_x = initial(C.pixel_x)
+ C.pixel_y = initial(C.pixel_y)
+ C.layer = initial(C.layer)
+
+/obj/vehicle/train/securitrolley/unload(var/mob/user, var/direction)
+ if(istype(load, /datum/vehicle_dummy_load))
+ var/datum/vehicle_dummy_load/dummy_load = load
+ load = dummy_load.actual_load
+ dummy_load.actual_load = null
+ qdel(dummy_load)
+ overlays.Cut()
+ ..()
+
+//-------------------------------------------
+// Latching/unlatching procs
+//-------------------------------------------
+
+/obj/vehicle/train/securiengine/latch(obj/vehicle/train/T, mob/user)
+ if(!istype(T) || !Adjacent(T))
+ return 0
+
+ //if we are attaching a trolley to an engine we don't care what direction
+ // it is in and it should probably be attached with the engine in the lead
+ if(istype(T, /obj/vehicle/train/securitrolley))
+ T.attach_to(src, user)
+ if (istype(T, /obj/vehicle/train/securitrolley/cargo))
+ T.attach_to(src, user)
+ else
+ var/T_dir = get_dir(src, T) //figure out where T is wrt src
+
+ if(dir == T_dir) //if car is ahead
+ src.attach_to(T, user)
+ else if(reverse_direction(dir) == T_dir) //else if car is behind
+ T.attach_to(src, user)
+
+//-------------------------------------------------------
+// Stat update procs
+//
+// Update the trains stats for speed calculations.
+// The longer the train, the slower it will go. car_limit
+// sets the max number of cars one engine can pull at
+// full speed. Adding more cars beyond this will slow the
+// train proportionate to the length of the train. Adding
+// more engines increases this limit by car_limit per
+// engine.
+//-------------------------------------------------------
+/obj/vehicle/train/securiengine/update_car(var/train_length, var/active_engines)
+ src.train_length = train_length
+ src.active_engines = active_engines
+
+ //Update move delay
+ if(!is_train_head() || !on)
+ move_delay = initial(move_delay) //so that engines that have been turned off don't lag behind
+ else
+ move_delay = max(0, (-car_limit * active_engines) + train_length - active_engines) //limits base overweight so you cant overspeed trains
+ move_delay *= (1 / max(1, active_engines)) * 2 //overweight penalty (scaled by the number of engines)
+ move_delay += config.run_speed //base reference speed
+ move_delay *= 1.5 //makes cargo trains 10% slower than running when not overweight
+
+/obj/vehicle/train/securitrolley/update_car(var/train_length, var/active_engines)
+ src.train_length = train_length
+ src.active_engines = active_engines
+
+ if(!lead && !tow)
+ anchored = 0
+ else
+ anchored = 1
+
+//-----------------------------------------------------
+//Update layer stuff
+//
+//This is supposed to update the layers and put the mob in the correct spot.
+//Pls help squirrel get this to work. ;m;
+//-----------------------------------------------------
+/obj/vehicle/train/securiengine/proc/update_layer()
+ if(dir == SOUTH)
+ layer = FLY_LAYER
+ else
+ layer = OBJ_LAYER
+
+/obj/vehicle/train/securiengine/proc/update_mob()
+ if(buckled_mob)
+ buckled_mob.set_dir(dir)
+ switch(dir)
+ if(SOUTH)
+ buckled_mob.pixel_x = 0
+ buckled_mob.pixel_y = 7
+ if(WEST)
+ buckled_mob.pixel_x = 13
+ buckled_mob.pixel_y = 7
+ if(NORTH)
+ buckled_mob.pixel_x = 0
+ buckled_mob.pixel_y = 4
+ if(EAST)
+ buckled_mob.pixel_x = -13
+ buckled_mob.pixel_y = 7
diff --git a/code/modules/vore/fluffstuff/custom_boxes_vr.dm b/code/modules/vore/fluffstuff/custom_boxes_vr.dm
index d66de51a4ef..8f47d57d96b 100644
--- a/code/modules/vore/fluffstuff/custom_boxes_vr.dm
+++ b/code/modules/vore/fluffstuff/custom_boxes_vr.dm
@@ -81,6 +81,10 @@
new /obj/item/weapon/sword/fluff/joanaria(src)
new /obj/item/weapon/flame/lighter/zippo/fluff/joan(src)
new /obj/item/clothing/under/rank/internalaffairs/fluff/joan(src)
+ new /obj/item/clothing/head/helmet/space/fluff/joan(src)
+ new /obj/item/clothing/suit/space/fluff/joan(src)
+
+
//joanrisu:Katarina Eine
/obj/item/weapon/storage/backpack/dufflebag/sec/fluff/Katarina
diff --git a/code/modules/vore/fluffstuff/custom_clothes_vr.dm b/code/modules/vore/fluffstuff/custom_clothes_vr.dm
index dc13fcea657..8cb7d3cac2f 100644
--- a/code/modules/vore/fluffstuff/custom_clothes_vr.dm
+++ b/code/modules/vore/fluffstuff/custom_clothes_vr.dm
@@ -668,9 +668,15 @@
/obj/item/clothing/suit/space/fluff/joan
name = "Joan's Combat Spacesuit"
desc = "A customized combat spacesuit made for a certain squirrely Commissioned Officer, tail slot included. \
- On the right shoulder, the United Federation's Emblem sits proudly. On the left, there are faded indications \
- that there were different ranks painted on and off. On the collar where the suit is softer is a rectangular \
- name-tag with the name 'Joan' on it. There are indications that the suit has seen combat."
+ On the right shoulder, the United Federation's Emblem sits proudly with a Rose weaving through it. \
+ On the left, there are faded indications that there were different ranks painted on and off. On the collar \
+ where the suit is softer is a rectangular name-tag with the name 'Joan' on it. There are indications that the \
+ suit has seen combat."
+
+ armor = list(melee = 80, bullet = 50, laser = 35, energy = 15, bomb = 70, bio = 100, rad = 50) //These values were taken from the combat rigs and adjusted to be weaker than said rigs.
+ slowdown = 0
+ allowed = list(/obj/item/weapon/gun,/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/melee/baton)
+ w_class = 3
icon = 'icons/vore/custom_clothes_vr.dmi'
icon_state = "joansuit"
diff --git a/icons/obj/vehicles_vr.dmi b/icons/obj/vehicles_vr.dmi
index 6fa5ae5e08f..a685e7c6973 100644
Binary files a/icons/obj/vehicles_vr.dmi and b/icons/obj/vehicles_vr.dmi differ