diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm
index 8eedb95a8de..d6daf0f4516 100644
--- a/code/game/machinery/rechargestation.dm
+++ b/code/game/machinery/rechargestation.dm
@@ -115,7 +115,7 @@
R.cell.charge = min(R.cell.charge + recharge_speed, R.cell.maxcharge)
else if(istype(occupant, /mob/living/carbon/human))
var/mob/living/carbon/human/H = occupant
- if(H.get_int_organ(/obj/item/organ/internal/cell) && H.nutrition < 450)
+ if(!isnull(H.internal_organs_by_name["cell"]) && H.nutrition < 450)
H.nutrition = min(H.nutrition+recharge_speed_nutrition, 450)
if(repairs)
H.heal_overall_damage(repairs, repairs, 0, 1)
@@ -145,7 +145,7 @@
// ^ makes sinle list of active (R.contents) and inactive modules (R.module.modules)
for(var/obj/O in um)
// Engineering
- if(istype(O,/obj/item/stack/sheet/metal) || istype(O,/obj/item/stack/sheet/rglass) || istype(O,/obj/item/stack/cable_coil))
+ if(istype(O,/obj/item/stack/sheet))
var/obj/item/stack/sheet/S = O
if(S.amount < 50)
S.amount += 1 * coeff
@@ -242,7 +242,7 @@
if(occupant)
H << "The cell is already occupied!"
return
- if(!H.get_int_organ(/obj/item/organ/internal/cell))
+ if(isnull(H.internal_organs_by_name["cell"]))
return
can_accept_user = 1
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 8dd72489b76..bd0c2a4fc5a 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -419,8 +419,10 @@
add_logs(M, user, "attacked", "[src.name]", "(INTENT: [uppertext(user.a_intent)])")
if(istype(H))
- var/obj/item/organ/internal/eyes/eyes = H.get_int_organ(/obj/item/organ/internal/eyes)
- if(!eyes)
+ var/obj/item/organ/eyes/eyes = H.internal_organs_by_name["eyes"]
+ if(!eyes) // should still get stabbed in the head
+ var/obj/item/organ/external/head/head = H.organs_by_name["head"]
+ head.take_damage(rand(10,14), 1)
return
eyes.take_damage(rand(3,4), 1)
if(eyes.damage >= eyes.min_bruised_damage)
diff --git a/code/modules/surgery/organs/organs_internal.dm b/code/modules/surgery/organs/organs_internal.dm
new file mode 100644
index 00000000000..ca8cf5eefe2
--- /dev/null
+++ b/code/modules/surgery/organs/organs_internal.dm
@@ -0,0 +1,463 @@
+// Internal surgeries.
+/datum/surgery_step/internal
+ priority = 2
+ can_infect = 1
+ blood_level = 1
+
+/datum/surgery_step/internal/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+
+ if (!hasorgans(target))
+ return 0
+
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ return affected && affected.open_enough_for_surgery()
+
+//////////////////////////////////////////////////////////////////
+// Dethrall Shadowling //
+//////////////////////////////////////////////////////////////////
+/datum/surgery_step/internal/dethrall
+ allowed_tools = list(
+ /obj/item/weapon/hemostat = 100, \
+ /obj/item/weapon/wirecutters = 75, \
+ /obj/item/weapon/kitchen/utensil/fork = 20
+ )
+
+ min_duration = 120
+ max_duration = 120
+
+ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ if (!hasorgans(target))
+ return
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ return ..() && affected && is_thrall(target) && affected.open_enough_for_surgery() && target_zone == target.named_organ_parent("brain")
+
+ begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/braincase = target.named_organ_parent("brain")
+ user.visible_message("[user] begins looking around in [target]'s [braincase].", "You begin looking for foreign influences on [target]'s brain...")
+ user << "You locate a small, pulsing black tumor on the side of [target]'s brain and begin to remove it."
+ target << "A small part of your [braincase] pulses with agony as the light impacts it."
+ user.visible_message("[user] begins removing something from [target]'s [braincase].", \
+ "You begin carefully extracting the tumor...")
+ ..()
+
+ end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/braincase = target.named_organ_parent("brain")
+ user.visible_message("[user] carefully extracts the tumor from [target]'s brain!", \
+ "You extract the black tumor from [target]'s [braincase]. It quickly shrivels and burns away.")
+ ticker.mode.remove_thrall(target.mind,0)
+
+ fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/braincase = target.named_organ_parent("brain")
+ if(prob(50))
+ user.visible_message("[user] slips and rips the tumor out from [target]'s [braincase]!", \
+ "You fumble and tear out [target]'s tumor!")
+ target.adjustBrainLoss(110) // This is so you can't just defib'n go
+ ticker.mode.remove_thrall(target.mind,1)
+ else
+ user.visible_message("[user]'s hand slips and fumbles! Luckily, they didn't damage anything!")
+
+//////////////////////////////////////////////////////////////////
+// ALIEN EMBRYO SURGERY //
+//////////////////////////////////////////////////////////////////
+/datum/surgery_step/internal/remove_embryo
+ allowed_tools = list(
+ /obj/item/weapon/hemostat = 100, \
+ /obj/item/weapon/wirecutters = 75, \
+ /obj/item/weapon/kitchen/utensil/fork = 20
+ )
+ blood_level = 2
+
+ min_duration = 80
+ max_duration = 100
+
+ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/embryo = 0
+ for(var/obj/item/alien_embryo/A in target)
+ embryo = 1
+ break
+
+ if (!hasorgans(target))
+ return
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ return ..() && affected && embryo && affected.open_enough_for_surgery() && target_zone == "chest"
+
+ begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/msg = "[user] starts to pull something out from [target]'s ribcage with \the [tool]."
+ var/self_msg = "You start to pull something out from [target]'s ribcage with \the [tool]."
+ user.visible_message(msg, self_msg)
+ target.custom_pain("Something hurts horribly in your chest!",1)
+ ..()
+
+ end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ user.visible_message("\red [user] rips the larva out of [target]'s ribcage!",
+ "You rip the larva out of [target]'s ribcage!")
+
+ for(var/obj/item/alien_embryo/A in target)
+ A.loc = A.loc.loc
+
+
+//////////////////////////////////////////////////////////////////
+// CHEST INTERNAL ORGAN SURGERY //
+//////////////////////////////////////////////////////////////////
+/datum/surgery_step/internal/fix_organ
+ allowed_tools = list(
+ /obj/item/stack/medical/advanced/bruise_pack= 100, \
+ /obj/item/stack/medical/bruise_pack = 20
+ )
+
+ min_duration = 70
+ max_duration = 90
+
+ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+
+ if (!hasorgans(target))
+ return
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ if(!affected)
+ return
+ var/is_organ_damaged = 0
+ for(var/obj/item/organ/I in affected.internal_organs)
+ if(I.damage > 0 && I.robotic < 2)
+ is_organ_damaged = 1
+ break
+ return ..() && is_organ_damaged
+
+ begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/tool_name = "\the [tool]"
+ if (istype(tool, /obj/item/stack/medical/advanced/bruise_pack))
+ tool_name = "regenerative membrane"
+ else if (istype(tool, /obj/item/stack/medical/bruise_pack))
+ tool_name = "the bandaid"
+
+ if (!hasorgans(target))
+ return
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+
+ for(var/obj/item/organ/I in affected.internal_organs)
+ if(I && I.damage > 0)
+ if(I.robotic < 2)
+ spread_germs_to_organ(I, user)
+ user.visible_message("[user] starts treating damage to [target]'s [I.name] with [tool_name].", \
+ "You start treating damage to [target]'s [I.name] with [tool_name]." )
+
+ target.custom_pain("The pain in your [affected.name] is living hell!",1)
+ ..()
+
+ end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/tool_name = "\the [tool]"
+ if (istype(tool, /obj/item/stack/medical/advanced/bruise_pack))
+ tool_name = "regenerative membrane"
+ if (istype(tool, /obj/item/stack/medical/bruise_pack))
+ tool_name = "the bandaid"
+
+ if (!hasorgans(target))
+ return
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+
+ for(var/obj/item/organ/I in affected.internal_organs)
+ if(I)
+ I.surgeryize()
+ if(I && I.damage > 0)
+ if(I.robotic < 2)
+ user.visible_message("\blue [user] treats damage to [target]'s [I.name] with [tool_name].", \
+ "\blue You treat damage to [target]'s [I.name] with [tool_name]." )
+ I.damage = 0
+
+ fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+
+ if (!hasorgans(target))
+ return
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+
+ user.visible_message("\red [user]'s hand slips, getting mess and tearing the inside of [target]'s [affected.name] with \the [tool]!", \
+ "\red Your hand slips, getting mess and tearing the inside of [target]'s [affected.name] with \the [tool]!")
+ var/dam_amt = 2
+
+ if (istype(tool, /obj/item/stack/medical/advanced/bruise_pack))
+ target.adjustToxLoss(5)
+
+ else if (istype(tool, /obj/item/stack/medical/bruise_pack))
+ dam_amt = 5
+ target.adjustToxLoss(10)
+ affected.createwound(CUT, 5)
+
+ for(var/obj/item/organ/I in affected.internal_organs)
+ if(I && I.damage > 0)
+ I.take_damage(dam_amt,0)
+
+/datum/surgery_step/internal/detatch_organ
+
+ allowed_tools = list(
+ /obj/item/weapon/scalpel = 100, \
+ /obj/item/weapon/kitchen/knife = 75, \
+ /obj/item/weapon/shard = 50, \
+ )
+
+ min_duration = 90
+ max_duration = 110
+
+ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+
+ if (!..())
+ return 0
+
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+
+ if(!(affected && !(affected.status & ORGAN_ROBOT)))
+ return 0
+
+ target.op_stage.current_organ = null
+ target.op_stage.organ_ref = null
+
+ var/list/attached_organs = list()
+ for(var/organ in affected.internal_organs)
+ var/obj/item/organ/I = organ
+ if(I && !(I.status & ORGAN_CUT_AWAY) && I.parent_organ == target_zone)
+ attached_organs[I.organ_tag] = I
+
+ var/organ_to_remove = input(user, "Which organ do you want to prepare for removal?") as null|anything in attached_organs
+ if(!organ_to_remove)
+ return 0
+
+ target.op_stage.current_organ = organ_to_remove
+ target.op_stage.organ_ref = attached_organs[organ_to_remove]
+
+ return ..() && organ_to_remove
+
+ begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+
+ user.visible_message("[user] starts to separate [target]'s [target.op_stage.current_organ] with \the [tool].", \
+ "You start to separate [target]'s [target.op_stage.current_organ] with \the [tool]." )
+ target.custom_pain("The pain in your [affected.name] is living hell!",1)
+ ..()
+
+ end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ user.visible_message("\blue [user] has separated [target]'s [target.op_stage.current_organ] with \the [tool]." , \
+ "\blue You have separated [target]'s [target.op_stage.current_organ] with \the [tool].")
+
+ var/obj/item/organ/I = target.op_stage.organ_ref
+ if(I && istype(I))
+ spread_germs_to_organ(I, user)
+ I.status |= ORGAN_CUT_AWAY
+
+ fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ user.visible_message("\red [user]'s hand slips, slicing an artery inside [target]'s [affected.name] with \the [tool]!", \
+ "\red Your hand slips, slicing an artery inside [target]'s [affected.name] with \the [tool]!")
+ affected.createwound(CUT, rand(30,50), 1)
+
+/datum/surgery_step/internal/remove_organ
+
+ allowed_tools = list(
+ /obj/item/weapon/hemostat = 100, \
+ /obj/item/weapon/wirecutters = 75, \
+ /obj/item/weapon/kitchen/utensil/fork = 20
+ )
+
+ min_duration = 60
+ max_duration = 80
+
+ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+
+ if (!..())
+ return 0
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+
+ if(!istype(affected))
+ return 0
+
+ target.op_stage.current_organ = null
+ target.op_stage.organ_ref = null
+
+ var/list/removable_organs = list()
+ for(var/organ in affected.internal_organs)
+ var/obj/item/organ/I = organ
+ if(istype(I) && (I.status & ORGAN_CUT_AWAY) && I.parent_organ == target_zone)
+ removable_organs[I.organ_tag] = I
+
+ var/organ_to_remove = input(user, "Which organ do you want to remove?") as null|anything in removable_organs
+ if(!organ_to_remove)
+ return 0
+
+ target.op_stage.current_organ = organ_to_remove
+ target.op_stage.organ_ref = removable_organs[organ_to_remove]
+ return ..()
+
+ begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ user.visible_message("[user] starts removing [target]'s [target.op_stage.current_organ] with \the [tool].", \
+ "You start removing [target]'s [target.op_stage.current_organ] with \the [tool].")
+ target.custom_pain("Someone's ripping out your [target.op_stage.current_organ]!",1)
+ ..()
+
+ end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ user.visible_message("\blue [user] has removed [target]'s [target.op_stage.current_organ] with \the [tool].", \
+ "\blue You have removed [target]'s [target.op_stage.current_organ] with \the [tool].")
+
+ // Extract the organ!
+ if(target.op_stage.current_organ)
+ var/obj/item/organ/O = target.op_stage.organ_ref
+ if(O && istype(O))
+ spread_germs_to_organ(O, user)
+ O.removed(user)
+
+ fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ user.visible_message("\red [user]'s hand slips, damaging [target]'s [affected.name] with \the [tool]!", \
+ "\red Your hand slips, damaging [target]'s [affected.name] with \the [tool]!")
+ affected.createwound(BRUISE, 20)
+
+/datum/surgery_step/internal/replace_organ
+ allowed_tools = list(
+ /obj/item/organ = 100
+ )
+
+ min_duration = 60
+ max_duration = 80
+
+ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+
+ var/obj/item/organ/O = tool
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ if(!affected) return
+ var/organ_compatible
+ var/organ_missing
+
+ if(!istype(O))
+ return 0
+
+ if((affected.status & ORGAN_ROBOT) && !(O.status & ORGAN_ROBOT))
+ user << "You cannot install a naked organ into a robotic body."
+ return 2
+
+ if(!target.species)
+ user << "\red You have no idea what species this person is. Report this on the bug tracker."
+ return 2
+
+ var/o_is = (O.gender == PLURAL) ? "are" : "is"
+ var/o_a = (O.gender == PLURAL) ? "" : "a "
+ var/o_do = (O.gender == PLURAL) ? "don't" : "doesn't"
+
+ if(O.organ_tag == "limb")
+ return 0
+ else if(target.species.has_organ[O.organ_tag])
+
+ if(O.damage > (O.max_damage * 0.75))
+ user << "\red \The [O.organ_tag] [o_is] in no state to be transplanted."
+ return 2
+
+ if(!target.internal_organs_by_name[O.organ_tag])
+ organ_missing = 1
+ else
+ user << "\red \The [target] already has [o_a][O.organ_tag]."
+ return 2
+
+ if(O && affected.limb_name == O.parent_organ)
+ organ_compatible = 1
+ else
+ user << "\red \The [O.organ_tag] [o_do] normally go in \the [affected.name]."
+ return 2
+ else
+ user << "\red You're pretty sure [target.species.name] don't normally have [o_a][O.organ_tag]."
+ return 2
+
+ return ..() && organ_missing && organ_compatible
+
+ begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ user.visible_message("[user] starts transplanting \the [tool] into [target]'s [affected.name].", \
+ "You start transplanting \the [tool] into [target]'s [affected.name].")
+ target.custom_pain("Someone's rooting around in your [affected.name]!",1)
+ ..()
+
+ end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ user.visible_message("\blue [user] has transplanted \the [tool] into [target]'s [affected.name].", \
+ "\blue You have transplanted \the [tool] into [target]'s [affected.name].")
+ user.drop_item(tool)
+ var/obj/item/organ/O = tool
+ if(istype(O))
+ O.replaced(target,affected)
+ spread_germs_to_organ(O, user)
+
+ fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ user.visible_message("\red [user]'s hand slips, damaging \the [tool]!", \
+ "\red Your hand slips, damaging \the [tool]!")
+ var/obj/item/organ/I = tool
+ if(istype(I))
+ I.take_damage(rand(3,5),0)
+
+/datum/surgery_step/internal/attach_organ
+ allowed_tools = list(
+ /obj/item/weapon/FixOVein = 100, \
+ /obj/item/stack/cable_coil = 75
+ )
+
+ min_duration = 100
+ max_duration = 120
+
+ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+
+ if (!..())
+ return 0
+
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+
+ if(!istype(affected))
+ return 0
+
+ target.op_stage.current_organ = null
+ target.op_stage.organ_ref = null
+
+ var/list/removable_organs = list()
+ for(var/organ in affected.internal_organs)
+ var/obj/item/organ/I = organ
+ if(I && istype(I) && (I.status & ORGAN_CUT_AWAY) && !(I.status & ORGAN_ROBOT) && I.parent_organ == target_zone)
+ removable_organs[I.organ_tag] = I
+
+ var/organ_to_replace = input(user, "Which organ do you want to reattach?") as null|anything in removable_organs
+ if(!organ_to_replace)
+ return 0
+
+ target.op_stage.current_organ = organ_to_replace
+ target.op_stage.organ_ref = removable_organs[organ_to_replace]
+ return ..()
+
+ begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ user.visible_message("[user] begins reattaching [target]'s [target.op_stage.current_organ] with \the [tool].", \
+ "You start reattaching [target]'s [target.op_stage.current_organ] with \the [tool].")
+ target.custom_pain("Someone's digging needles into your [target.op_stage.current_organ]!",1)
+ ..()
+
+ end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ user.visible_message("\blue [user] has reattached [target]'s [target.op_stage.current_organ] with \the [tool]." , \
+ "\blue You have reattached [target]'s [target.op_stage.current_organ] with \the [tool].")
+
+ var/obj/item/organ/I = target.op_stage.organ_ref
+ if(I && istype(I))
+ I.status &= ~ORGAN_CUT_AWAY
+ spread_germs_to_organ(I, user)
+
+ fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ user.visible_message("\red [user]'s hand slips, damaging the flesh in [target]'s [affected.name] with \the [tool]!", \
+ "\red Your hand slips, damaging the flesh in [target]'s [affected.name] with \the [tool]!")
+ affected.createwound(BRUISE, 20)
+
+//////////////////////////////////////////////////////////////////
+// HEART SURGERY //
+//////////////////////////////////////////////////////////////////
+// To be finished after some tests.
+// /datum/surgery_step/ribcage/heart/cut
+// allowed_tools = list(
+// /obj/item/weapon/scalpel = 100, \
+// /obj/item/weapon/kitchen/knife = 75, \
+// /obj/item/weapon/shard = 50, \
+// )
+
+// min_duration = 30
+// max_duration = 40
+
+// can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+// return ..() && target.op_stage.ribcage == 2
\ No newline at end of file