diff --git a/code/game/objects/items/devices/defib.dm b/code/game/objects/items/devices/defib.dm
new file mode 100644
index 0000000000..17e50105f9
--- /dev/null
+++ b/code/game/objects/items/devices/defib.dm
@@ -0,0 +1,243 @@
+//The case the paddles are kept in.
+/obj/item/device/defib_kit
+ name = "defibrilator kit"
+ desc = "This KHI-branded defib kit is a semi-automated model. Remove pads, slap on chest, wait."
+ icon = 'icons/obj/device.dmi'
+ icon_state = "defib_kit"
+ w_class = ITEMSIZE_LARGE
+
+ var/state //0 off, 1 open, 2 working, 3 dead
+ var/uses = 3 //Calculates initial uses based on starting cell size
+ var/charge_cost //Set in New() based on uses
+ var/obj/item/weapon/cell/device/cell //The size is mostly irrelevant, see 'uses'
+ var/obj/item/clothing/under/defib_paddles/paddles //Reference to connected paddles
+ var/mob/living/carbon/human/patient //The person the paddles are on
+
+/obj/item/device/defib_kit/New()
+ ..()
+ //Create cell and determine uses (futureproofing against cell size changes)
+ cell = new(src)
+ charge_cost = cell.maxcharge / uses
+
+ //Create paddles and associate them with the kit
+ paddles = new(src)
+ paddles.kit = src
+
+ statechange(0)
+
+/obj/item/device/defib_kit/attack_hand(mob/user as mob)
+ if(user.get_inactive_hand() == src)
+ get_paddles(user)
+ else
+ return ..()
+
+/obj/item/device/defib_kit/MouseDrop(var/mob/living/carbon/human/onto)
+ if(istype(onto) && usr == onto && Adjacent(usr) && !usr.restrained() && !usr.stat)
+ get_paddles(onto)
+ else
+ return ..()
+
+/obj/item/device/defib_kit/attackby(var/obj/item/A as obj, mob/living/user as mob)
+ ..()
+
+ if(istype(A,/obj/item/clothing/under/defib_paddles))
+ put_paddles(A, user)
+
+ else if(!cell && istype(A,/obj/item/weapon/cell/device))
+ if(!user.unEquip(A)) return
+ user << "You jack \the [A] into \the [src]'s battery mount."
+ A.forceMove(src)
+ src.cell = A
+
+ else if(istype(A,/obj/item/weapon/screwdriver))
+ if(cell)
+ user << "You remove \the [cell] from \the [src]."
+ if(user.r_hand && user.l_hand)
+ cell.forceMove(get_turf(user))
+ else
+ cell.forceMove(user.put_in_hands(cell))
+ cell = null
+ else
+ user << "The power source has already been removed!"
+
+
+/obj/item/device/defib_kit/proc/get_paddles(mob/user)
+ if(paddles && state == 0)
+ if(paddles.grabbed(src, user))
+ statechange(1)
+ processing_objects |= src
+ playsound(src.loc, 'sound/weapons/empty.ogg', 50, 1)
+ else if(paddles && state > 0)
+ user << "The paddles have already been removed and are on/in [paddles.loc]."
+ else if(!paddles)
+ user << "The paddles are missing!"
+
+/obj/item/device/defib_kit/proc/put_paddles(var/obj/item/clothing/under/defib_paddles/P, mob/user)
+ if(state == 0) //Weird case, shouldn't happen unless you're being weird with more than one defib kit.
+ user << "This defib kit doesn't need more paddles!"
+ return
+
+ if(state > 0 && !paddles) //Reconnecting paddles
+ if(P.reconnected(src, user))
+ playsound(src.loc, 'sound/weapons/flipblade.ogg', 50, 1)
+
+ else if(P == paddles)//Returning paddles
+ if(P.replaced(src, user))
+ playsound(src.loc, 'sound/weapons/flipblade.ogg', 50, 1)
+ statechange(0)
+
+/obj/item/device/defib_kit/proc/statechange(var/new_state)
+ if(state == new_state) return //Let's just save ourselves some time
+ state = new_state
+ icon_state = "[initial(icon_state)][state]"
+ var/turf/T = get_turf(src)
+ var/state_words = ""
+ switch(state)
+ if(0)
+ state_words = "It is currently closed."
+ if(1)
+ state_words = "A green light is lit; it has charge."
+ if(2)
+ state_words = "A yellow light is flashing: it's in the process of reviving a patient."
+ T.visible_message("A yellow light starts flashing on \the [src].")
+ playsound(T, 'sound/machines/chime.ogg', 50, 0)
+ if(3)
+ state_words = "A red light is flashing: the battery needs to be recharged."
+ T.visible_message("A red light starts flashing on \the [src].")
+ playsound(T, 'sound/machines/buzz-sigh.ogg', 50, 0)
+
+ desc = "[initial(desc)] [state_words]"
+ update_icon()
+
+/obj/item/device/defib_kit/process()
+ if(!state) //0 or null
+ statechange(0)
+ processing_objects -= src
+ return
+
+ //Battery died
+ if(!cell || cell.charge < charge_cost)
+ statechange(3)
+ return
+
+ //Everything below here requires paddles
+ if(!paddles) return
+
+ //Paddles moved too far
+ if(!(get_dist(src,paddles) <= 1)) //You separated the kit and pads too far
+ audible_message("There's a clatter as \the [paddles] connector cables are yanked out of \the [src].")
+ paddles.kit = null
+ paddles = null
+ patient = null
+ return
+
+ //A patient isn't being worked on, but we have one, so start
+ if(patient && patient.stat == DEAD && state != 2)
+ statechange(2)
+ if(attempt_shock()) //Try to shock them, has timer and such
+ patient.visible_message("[patient] convulses!")
+ playsound(src.loc, 'sound/effects/sparks2.ogg', 50, 1)
+ //Actual rezzing code
+ if(prob(75) && !((world.time - patient.tod) > (10 MINUTES))) //Can only revive within a few minutes
+ if(!patient.client && patient.mind) //Don't force the dead person to come back if they don't want to.
+ for(var/mob/observer/dead/ghost in player_list)
+ if(ghost.mind == patient.mind)
+ ghost << "Someone is trying to \
+ revive you. Return to your body if you want to be revived! \
+ (Verbs -> Ghost -> Re-enter corpse). You have 15 seconds to do this!"
+ sleep(15 SECONDS)
+ break
+
+ if(patient.client)
+ patient.adjustOxyLoss(-20) //Look, blood stays oxygenated for quite some time, but I'm not recoding the entire oxy system
+ patient.stat = CONSCIOUS //Note that if whatever killed them in the first place wasn't fixed, they're likely to die again.
+ dead_mob_list -= patient
+ living_mob_list += patient
+ patient.timeofdeath = null
+ patient.visible_message("[patient]'s eyes open!")
+ log_and_message_admins("[patient] was revived.")
+ cell.charge -= charge_cost //Always charge the cost after any attempt, failed or not
+ sleep(20) //Wait 2 seconds before next attempt
+ statechange(1) //Back to ready
+
+/obj/item/device/defib_kit/proc/attempt_shock()
+ if(!paddles || !patient || cell.charge < charge_cost) return
+
+ var/zap_time = world.time + (5 SECONDS)
+ var/o_patient_loc = patient.loc
+ . = 1
+
+ while(world.time < zap_time) //This is basically a custom do_after() call
+ sleep(1)
+
+ //Failed: We lost something important
+ if(!paddles || !patient || !cell || cell.charge < charge_cost)
+ . = 0
+ break
+
+ //Failed: The locations aren't right
+ if((o_patient_loc != patient.loc) || !Adjacent(paddles))
+ . = 0
+ break
+
+ //Failed: The paddles aren't on the patient
+ if(patient.w_uniform != paddles)
+ patient = null
+ . = 0
+ break
+
+ return
+
+
+// --------------------------------------
+//The paddles themselves. ZAP.
+/obj/item/clothing/under/defib_paddles
+ name = "defibrilator pads"
+ desc = "Adhesive! Apply to dead person."
+ icon = 'icons/obj/device.dmi'
+ icon_override = 'icons/obj/device.dmi'
+ icon_state = "defib_pads"
+
+ var/obj/item/device/defib_kit/kit
+ has_sensor = 0 //Naaah.
+
+/obj/item/clothing/under/defib_paddles/proc/replaced(var/obj/item/device/defib_kit/K, var/mob/user)
+ if(!kit) //Sanity: should not fire due to logic in kit
+ return
+
+ if(kit && K != kit)
+ user << "The pads are connected to a different kit!"
+ return
+
+ user.visible_message("[user] returns \the [src] and closes \the [kit].", "You return \the [src] and close \the [kit].")
+ user.remove_from_mob(src)
+ src.forceMove(K)
+ layer = initial(layer)
+ return 1
+
+/obj/item/clothing/under/defib_paddles/proc/reconnected(var/obj/item/device/defib_kit/K, var/mob/user)
+ if(kit && K != kit)
+ user << "The pads are connected to a different kit!"
+ return
+
+ user.visible_message("[user] reconnects \the [src] to \the [K].", "You reconnect \the [src] to \the [K].")
+ kit = K
+ kit.paddles = src
+ return 1
+
+/obj/item/clothing/under/defib_paddles/proc/grabbed(var/obj/item/device/defib_kit/K, var/mob/user)
+ if(K != kit && istype(K)) //Mostly for sanity
+ K.paddles = null //Stop talking to me!
+ return
+
+ user.visible_message("[user] removes \the [src] from \the [kit].", "You remove \the [src] from \the [kit].")
+ if(!user.put_in_hands(src))
+ src.forceMove(get_turf(src))
+ return 1
+
+/obj/item/clothing/under/defib_paddles/equipped(var/mob/living/carbon/human/user, var/slot)
+ . = ..()
+ if(kit && istype(user) && slot == slot_w_uniform)
+ kit.patient = user
+ if(kit.patient.stat == DEAD)
+ kit.patient.dir = 2 //Looks better this way
diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi
index 41da2fe40a..ce0c7a5a24 100644
Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ