/datum/surgery/cavity_implant name = "Cavity Implant/Removal" steps = list( /datum/surgery_step/generic/cut_open, /datum/surgery_step/generic/clamp_bleeders, /datum/surgery_step/generic/retract_skin, /datum/surgery_step/proxy/ib, // just do IB here since we're sawing the bone anyway /datum/surgery_step/open_encased/saw, /datum/surgery_step/open_encased/retract, /datum/surgery_step/cavity/make_space, /datum/surgery_step/proxy/cavity_manipulation, /datum/surgery_step/cavity/close_space, /datum/surgery_step/open_encased/close, /datum/surgery_step/glue_bone, /datum/surgery_step/set_bone, /datum/surgery_step/finish_bone, /datum/surgery_step/generic/cauterize ) possible_locs = list(BODY_ZONE_CHEST, BODY_ZONE_HEAD) /datum/surgery/cavity_implant/can_start(mob/user, mob/living/carbon/target) if(HAS_TRAIT(target, TRAIT_NO_BONES)) return FALSE return TRUE /datum/surgery/cavity_implant/soft desc = "Implant an object into a cavity not protected by bone." steps = list( /datum/surgery_step/generic/cut_open, /datum/surgery_step/generic/clamp_bleeders, /datum/surgery_step/generic/retract_skin, /datum/surgery_step/proxy/ib, // just do IB here since we're sawing the bone anyway /datum/surgery_step/generic/cut_open, /datum/surgery_step/cavity/make_space, /datum/surgery_step/proxy/cavity_manipulation, /datum/surgery_step/cavity/close_space, /datum/surgery_step/generic/cauterize ) possible_locs = list(BODY_ZONE_PRECISE_GROIN) /datum/surgery/cavity_implant/soft/boneless possible_locs = list(BODY_ZONE_CHEST, BODY_ZONE_HEAD) /datum/surgery/cavity_implant/soft/boneless/can_start(mob/user, mob/living/carbon/target) if(!HAS_TRAIT(target, TRAIT_NO_BONES)) return FALSE return TRUE /datum/surgery/cavity_implant/synth name = "Robotic Cavity Implant/Removal" steps = list( /datum/surgery_step/robotics/external/unscrew_hatch, /datum/surgery_step/robotics/external/open_hatch, /datum/surgery_step/proxy/cavity_manipulation/robotic, /datum/surgery_step/cavity/close_space/synth, /datum/surgery_step/robotics/external/close_hatch ) possible_locs = list(BODY_ZONE_CHEST, BODY_ZONE_HEAD, BODY_ZONE_PRECISE_GROIN) requires_organic_bodypart = FALSE /datum/surgery_step/proxy/cavity_manipulation name = "Cavity Manipulation (proxy)" branches = list( /datum/surgery/intermediate/open_cavity/implant, /datum/surgery/intermediate/open_cavity/extract, /datum/surgery/intermediate/bleeding ) /datum/surgery_step/proxy/cavity_manipulation/robotic name = "Robotic Cavity Manipulation (proxy)" branches = list( /datum/surgery/intermediate/open_cavity/implant/robotic, /datum/surgery/intermediate/open_cavity/extract/robotic ) /datum/surgery/intermediate/open_cavity possible_locs = list(BODY_ZONE_CHEST, BODY_ZONE_HEAD) /datum/surgery/intermediate/open_cavity/implant name = "implant object" steps = list( /datum/surgery_step/cavity/place_item ) /datum/surgery/intermediate/open_cavity/extract name = "extract object" steps = list( /datum/surgery_step/cavity/remove_item ) /datum/surgery/intermediate/open_cavity/implant/robotic requires_organic_bodypart = FALSE /datum/surgery/intermediate/open_cavity/extract/robotic requires_organic_bodypart = FALSE /datum/surgery_step/cavity /datum/surgery_step/cavity/proc/get_max_wclass(obj/item/organ/external/affected) switch(affected.limb_name) if(BODY_ZONE_HEAD) return WEIGHT_CLASS_TINY if(BODY_ZONE_CHEST) return WEIGHT_CLASS_NORMAL if(BODY_ZONE_PRECISE_GROIN) return WEIGHT_CLASS_SMALL return 0 /datum/surgery_step/cavity/proc/get_cavity(obj/item/organ/external/affected) switch(affected.limb_name) if(BODY_ZONE_HEAD) return "cranial" if(BODY_ZONE_CHEST) return "thoracic" if(BODY_ZONE_PRECISE_GROIN) return "abdominal" return "" /datum/surgery_step/cavity/proc/get_item_inside(obj/item/organ/external/affected) var/obj/item/extracting for(var/obj/item/I in affected.contents) if(!istype(I, /obj/item/organ)) extracting = I break if(!extracting && affected.hidden) extracting = affected.hidden return extracting /datum/surgery_step/cavity/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery) var/obj/item/organ/external/chest/affected = target.get_organ(target_zone) user.visible_message( SPAN_WARNING("[user]'s hand slips, scraping around inside [target]'s [affected.name] with \the [tool]!"), SPAN_WARNING("Your hand slips, scraping around inside [target]'s [affected.name] with \the [tool]!"), chat_message_type = MESSAGE_TYPE_COMBAT ) affected.receive_damage(20) return SURGERY_STEP_RETRY /datum/surgery_step/cavity/make_space name = "make cavity space" allowed_tools = list( TOOL_DRILL = 100, /obj/item/screwdriver/power = 90, /obj/item/pen = 90, /obj/item/stack/rods = 60 ) preop_sound = list( TOOL_DRILL = 'sound/items/drill_hit.ogg', /obj/item/screwdriver/power = 'sound/items/drill_hit.ogg', /obj/item/pen = 'sound/surgery/organ2.ogg', /obj/item/stack/rods = 'sound/surgery/organ2.ogg' ) time = 5.4 SECONDS /datum/surgery_step/cavity/make_space/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery) var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message( "[user] starts making some space inside [target]'s [get_cavity(affected)] cavity with \the [tool].", "You start making some space inside [target]'s [get_cavity(affected)] cavity with \the [tool].", chat_message_type = MESSAGE_TYPE_COMBAT ) affected.custom_pain("The pain in your chest is living hell!") return ..() /datum/surgery_step/cavity/make_space/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery) var/obj/item/organ/external/chest/affected = target.get_organ(target_zone) user.visible_message( SPAN_NOTICE("[user] makes some space inside [target]'s [get_cavity(affected)] cavity with \the [tool]."), SPAN_NOTICE("You make some space inside [target]'s [get_cavity(affected)] cavity with \the [tool]."), chat_message_type = MESSAGE_TYPE_COMBAT ) return SURGERY_STEP_CONTINUE /datum/surgery_step/cavity/close_space name = "close cavity space" allowed_tools = list( /obj/item/scalpel/laser = 100, TOOL_CAUTERY = 100, /obj/item/clothing/mask/cigarette = 90, /obj/item/lighter = 60, TOOL_WELDER = 30 ) preop_sound = 'sound/surgery/cautery1.ogg' success_sound = 'sound/surgery/cautery2.ogg' failure_sound = 'sound/items/welder.ogg' time = 2.4 SECONDS /datum/surgery_step/cavity/close_space/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery) var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message( "[user] starts mending [target]'s [get_cavity(affected)] cavity wall with \the [tool].", "You start mending [target]'s [get_cavity(affected)] cavity wall with \the [tool].", chat_message_type = MESSAGE_TYPE_COMBAT ) affected.custom_pain("The pain in your chest is living hell!") return ..() /datum/surgery_step/cavity/close_space/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery) var/obj/item/organ/external/chest/affected = target.get_organ(target_zone) user.visible_message( SPAN_NOTICE("[user] mends [target]'s [get_cavity(affected)] cavity walls with \the [tool]."), SPAN_NOTICE("You mend [target]'s [get_cavity(affected)] cavity walls with \the [tool]."), chat_message_type = MESSAGE_TYPE_COMBAT ) return SURGERY_STEP_CONTINUE /datum/surgery_step/cavity/close_space/synth name = "seal cavity" allowed_tools = list( TOOL_WELDER = 100, /obj/item/scalpel/laser = 60, TOOL_CAUTERY = 50, /obj/item/lighter = 30, ) /datum/surgery_step/cavity/remove_item name = "extract object" accept_hand = TRUE /datum/surgery_step/cavity/remove_item/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery) // Check even if there isn't anything inside user.visible_message( "[user] checks for items in [target]'s [target_zone].", SPAN_NOTICE("You check for items in [target]'s [target_zone]..."), chat_message_type = MESSAGE_TYPE_COMBAT ) return ..() /datum/surgery_step/cavity/remove_item/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery) var/obj/item/extracting var/obj/item/organ/external/affected = target.get_organ(target_zone) extracting = get_item_inside(affected) if(!extracting) to_chat(user, SPAN_WARNING("You don't find anything in [target]'s [target_zone].")) return SURGERY_STEP_CONTINUE user.visible_message( SPAN_NOTICE("[user] pulls [extracting] out of [target]'s [target_zone]!"), SPAN_NOTICE("You pull [extracting] out of [target]'s [target_zone]."), chat_message_type = MESSAGE_TYPE_COMBAT ) user.put_in_hands(extracting) if(extracting == affected.hidden) affected.hidden = null return SURGERY_STEP_CONTINUE /datum/surgery_step/cavity/remove_item/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery) var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message( SPAN_WARNING("[user] grabs onto something else by mistake, damaging it!."), SPAN_WARNING("You grab onto something else inside [target]'s [get_cavity(affected)] cavity by mistake, damaging it!"), chat_message_type = MESSAGE_TYPE_COMBAT ) affected.receive_damage(rand(3, 5)) return SURGERY_STEP_INCOMPLETE /datum/surgery_step/cavity/place_item name = "implant object" accept_any_item = TRUE time = 3.2 SECONDS /datum/surgery_step/cavity/place_item/tool_check(mob/user, obj/item/tool) if(istype(tool, /obj/item/disk/nuclear)) to_chat(user, SPAN_WARNING("Central command would kill you if you implanted the disk into someone.")) return FALSE var/obj/item/disk/nuclear/datdisk = locate() in tool if(datdisk) to_chat(user, SPAN_WARNING("Central Command would kill you if you implanted the disk into someone. Especially if in a [tool].")) return FALSE if(istype(tool, /obj/item/organ)) to_chat(user, SPAN_WARNING("This isn't the type of surgery for organ transplants!")) return FALSE if(!user.canUnEquip(tool, 0)) to_chat(user, SPAN_WARNING("[tool] is stuck to your hand!")) return FALSE if(istype(tool, /obj/item/cautery)) // Pass it to the next step return FALSE return TRUE /datum/surgery_step/cavity/place_item/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery) var/obj/item/organ/external/affected = target.get_organ(target_zone) var/can_fit = !affected.hidden && tool.w_class <= get_max_wclass(affected) if(!can_fit) to_chat(user, SPAN_WARNING("\The [tool] won't fit in \the [affected]!")) return SURGERY_BEGINSTEP_SKIP user.visible_message( "[user] starts putting \the [tool] inside [target]'s [get_cavity(affected)] cavity.", "You start putting \the [tool] inside [target]'s [get_cavity(affected)] cavity.", chat_message_type = MESSAGE_TYPE_COMBAT ) affected.custom_pain("The pain in your [target_zone] is living hell!") return ..() /datum/surgery_step/cavity/place_item/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery) var/obj/item/organ/external/chest/affected = target.get_organ(target_zone) if(get_item_inside(affected)) to_chat(user, SPAN_NOTICE("There seems to be something in there already!")) return SURGERY_STEP_CONTINUE user.visible_message( SPAN_NOTICE("[user] puts \the [tool] inside [target]'s [get_cavity(affected)] cavity."), SPAN_NOTICE("You put \the [tool] inside [target]'s [get_cavity(affected)] cavity."), chat_message_type = MESSAGE_TYPE_COMBAT ) if((tool.w_class > get_max_wclass(affected) / 2 && prob(50) && !affected.is_robotic())) user.visible_message( SPAN_WARNING("[user] tears some blood vessels trying to fit the object in the cavity!"), SPAN_DANGER("You tear some blood vessels trying to fit the object into the cavity!"), SPAN_WARNING("You hear some gentle tearing."), MESSAGE_TYPE_COMBAT) affected.cause_internal_bleeding() user.drop_item() affected.hidden = tool tool.forceMove(target) return SURGERY_STEP_CONTINUE