Merge pull request #3818 from Citadel-Station-13/upstream-merge-32374

[MIRROR] Fixes canceling cavity implants
This commit is contained in:
LetterJay
2017-11-09 03:24:48 -06:00
committed by GitHub
2 changed files with 176 additions and 173 deletions

View File

@@ -17,6 +17,11 @@
var/obj/item/bodypart/chest/CH = target.get_bodypart("chest") var/obj/item/bodypart/chest/CH = target.get_bodypart("chest")
IC = CH.cavity_item IC = CH.cavity_item
if(tool) if(tool)
if(istype(tool, /obj/item/surgical_drapes) || istype(tool, /obj/item/bedsheet))
var/obj/item/inactive = user.get_inactive_held_item()
if(istype(inactive, /obj/item/cautery) || istype(inactive, /obj/item/screwdriver) || iscyborg(user))
attempt_cancel_surgery(surgery, tool, target, user)
return -1
user.visible_message("[user] begins to insert [tool] into [target]'s [target_zone].", "<span class='notice'>You begin to insert [tool] into [target]'s [target_zone]...</span>") user.visible_message("[user] begins to insert [tool] into [target]'s [target_zone].", "<span class='notice'>You begin to insert [tool] into [target]'s [target_zone]...</span>")
else else
user.visible_message("[user] checks for items in [target]'s [target_zone].", "<span class='notice'>You check for items in [target]'s [target_zone]...</span>") user.visible_message("[user] checks for items in [target]'s [target_zone].", "<span class='notice'>You check for items in [target]'s [target_zone]...</span>")

View File

@@ -1,173 +1,171 @@
/proc/attempt_initiate_surgery(obj/item/I, mob/living/M, mob/user) /proc/attempt_initiate_surgery(obj/item/I, mob/living/M, mob/user)
if(!istype(M)) if(!istype(M))
return return
var/mob/living/carbon/C var/mob/living/carbon/C
var/obj/item/bodypart/affecting var/obj/item/bodypart/affecting
var/selected_zone = user.zone_selected var/selected_zone = user.zone_selected
if(iscarbon(M)) if(iscarbon(M))
C = M C = M
affecting = C.get_bodypart(check_zone(selected_zone)) affecting = C.get_bodypart(check_zone(selected_zone))
if(!M.lying && !isslime(M)) //if they're prone or a slime if(!M.lying && !isslime(M)) //if they're prone or a slime
return return
var/datum/surgery/current_surgery var/datum/surgery/current_surgery
for(var/datum/surgery/S in M.surgeries) for(var/datum/surgery/S in M.surgeries)
if(S.location == selected_zone) if(S.location == selected_zone)
current_surgery = S current_surgery = S
if(!current_surgery) if(!current_surgery)
var/list/all_surgeries = GLOB.surgeries_list.Copy() var/list/all_surgeries = GLOB.surgeries_list.Copy()
var/list/available_surgeries = list() var/list/available_surgeries = list()
for(var/datum/surgery/S in all_surgeries) for(var/datum/surgery/S in all_surgeries)
if(!S.possible_locs.Find(selected_zone)) if(!S.possible_locs.Find(selected_zone))
continue continue
if(affecting) if(affecting)
if(!S.requires_bodypart) if(!S.requires_bodypart)
continue continue
if(S.requires_bodypart_type && affecting.status == BODYPART_ROBOTIC) if(S.requires_bodypart_type && affecting.status != S.requires_bodypart_type)
continue continue
if(S.requires_real_bodypart && affecting.is_pseudopart) if(S.requires_real_bodypart && affecting.is_pseudopart)
continue continue
else if(C && S.requires_bodypart) //mob with no limb in surgery zone when we need a limb else if(C && S.requires_bodypart) //mob with no limb in surgery zone when we need a limb
continue continue
if(!S.can_start(user, M)) if(!S.can_start(user, M))
continue continue
for(var/path in S.species) for(var/path in S.species)
if(istype(M, path)) if(istype(M, path))
available_surgeries[S.name] = S available_surgeries[S.name] = S
break break
var/P = input("Begin which procedure?", "Surgery", null, null) as null|anything in available_surgeries var/P = input("Begin which procedure?", "Surgery", null, null) as null|anything in available_surgeries
if(P && user && user.Adjacent(M) && (I in user)) if(P && user && user.Adjacent(M) && (I in user))
var/datum/surgery/S = available_surgeries[P] var/datum/surgery/S = available_surgeries[P]
for(var/datum/surgery/other in M.surgeries) for(var/datum/surgery/other in M.surgeries)
if(other.location == S.location) if(other.location == S.location)
return //during the input() another surgery was started at the same location. return //during the input() another surgery was started at the same location.
//we check that the surgery is still doable after the input() wait. //we check that the surgery is still doable after the input() wait.
if(C) if(C)
affecting = C.get_bodypart(check_zone(selected_zone)) affecting = C.get_bodypart(check_zone(selected_zone))
if(affecting) if(affecting)
if(!S.requires_bodypart) if(!S.requires_bodypart)
return return
if(S.requires_bodypart_type && affecting.status == BODYPART_ROBOTIC) if(S.requires_bodypart_type && affecting.status != S.requires_bodypart_type)
return return
else if(C && S.requires_bodypart) else if(C && S.requires_bodypart)
return return
if(!S.can_start(user, M)) if(!S.can_start(user, M))
return return
if(S.ignore_clothes || get_location_accessible(M, selected_zone)) if(S.ignore_clothes || get_location_accessible(M, selected_zone))
var/datum/surgery/procedure = new S.type(M, selected_zone, affecting) var/datum/surgery/procedure = new S.type(M, selected_zone, affecting)
user.visible_message("[user] drapes [I] over [M]'s [parse_zone(selected_zone)] to prepare for \an [procedure.name].", \ user.visible_message("[user] drapes [I] over [M]'s [parse_zone(selected_zone)] to prepare for \an [procedure.name].", \
"<span class='notice'>You drape [I] over [M]'s [parse_zone(selected_zone)] to prepare for \an [procedure.name].</span>") "<span class='notice'>You drape [I] over [M]'s [parse_zone(selected_zone)] to prepare for \an [procedure.name].</span>")
add_logs(user, M, "operated", addition="Operation type: [procedure.name], location: [selected_zone]") add_logs(user, M, "operated", addition="Operation type: [procedure.name], location: [selected_zone]")
else else
to_chat(user, "<span class='warning'>You need to expose [M]'s [parse_zone(selected_zone)] first!</span>") to_chat(user, "<span class='warning'>You need to expose [M]'s [parse_zone(selected_zone)] first!</span>")
else if(!current_surgery.step_in_progress) else if(!current_surgery.step_in_progress)
if(current_surgery.status == 1) attempt_cancel_surgery(current_surgery, I, M, user)
M.surgeries -= current_surgery
user.visible_message("[user] removes the drapes from [M]'s [parse_zone(selected_zone)].", \ return 1
"<span class='notice'>You remove the drapes from [M]'s [parse_zone(selected_zone)].</span>")
qdel(current_surgery) /proc/attempt_cancel_surgery(datum/surgery/S, obj/item/I, mob/living/M, mob/user)
else if(current_surgery.can_cancel) var/selected_zone = user.zone_selected
if(current_surgery.requires_bodypart_type == BODYPART_ORGANIC) if(S.status == 1)
if(istype(user.get_inactive_held_item(), /obj/item/cautery)) M.surgeries -= S
M.surgeries -= current_surgery user.visible_message("[user] removes [I] from [M]'s [parse_zone(selected_zone)].", \
user.visible_message("[user] mends the incision and removes the drapes from [M]'s [parse_zone(selected_zone)].", \ "<span class='notice'>You remove [I] from [M]'s [parse_zone(selected_zone)].</span>")
"<span class='notice'>You mend the incision and remove the drapes from [M]'s [parse_zone(selected_zone)].</span>") qdel(S)
qdel(current_surgery) else if(S.can_cancel)
else var/close_tool_type = /obj/item/cautery
to_chat(user, "<span class='warning'>You need to hold a cautery in inactive hand to stop [M]'s surgery!</span>") var/obj/item/close_tool = user.get_inactive_held_item()
else if(current_surgery.requires_bodypart_type == BODYPART_ROBOTIC) var/is_robotic = S.requires_bodypart_type == BODYPART_ROBOTIC
if(istype(user.get_inactive_held_item(), /obj/item/screwdriver)) if(is_robotic)
M.surgeries -= current_surgery close_tool_type = /obj/item/screwdriver
user.visible_message("[user] screw the shell and removes the drapes from [M]'s [parse_zone(selected_zone)].", \ if(istype(close_tool, close_tool_type) || iscyborg(user))
"<span class='notice'>You screw the shell and remove the drapes from [M]'s [parse_zone(selected_zone)].</span>") M.surgeries -= S
qdel(current_surgery) user.visible_message("[user] closes [M]'s [parse_zone(selected_zone)] with [close_tool] and removes [I].", \
else "<span class='notice'>You close [M]'s [parse_zone(selected_zone)] with [close_tool] and remove [I].</span>")
to_chat(user, "<span class='warning'>You need to hold a screwdriver in inactive hand to stop [M]'s surgery!</span>") qdel(S)
else
return 1 to_chat(user, "<span class='warning'>You need to hold a [is_robotic ? "screwdriver" : "cautery"] in your inactive hand to stop [M]'s surgery!</span>")
/proc/get_location_modifier(mob/M)
var/turf/T = get_turf(M)
/proc/get_location_modifier(mob/M) if(locate(/obj/structure/table/optable, T))
var/turf/T = get_turf(M) return 1
if(locate(/obj/structure/table/optable, T)) else if(locate(/obj/structure/table, T))
return 1 return 0.8
else if(locate(/obj/structure/table, T)) else if(locate(/obj/structure/bed, T))
return 0.8 return 0.7
else if(locate(/obj/structure/bed, T)) else
return 0.7 return 0.5
else
return 0.5
/proc/get_location_accessible(mob/M, location)
var/covered_locations = 0 //based on body_parts_covered
/proc/get_location_accessible(mob/M, location) var/face_covered = 0 //based on flags_inv
var/covered_locations = 0 //based on body_parts_covered var/eyesmouth_covered = 0 //based on flags_cover
var/face_covered = 0 //based on flags_inv if(iscarbon(M))
var/eyesmouth_covered = 0 //based on flags_cover var/mob/living/carbon/C = M
if(iscarbon(M)) for(var/obj/item/clothing/I in list(C.back, C.wear_mask, C.head))
var/mob/living/carbon/C = M covered_locations |= I.body_parts_covered
for(var/obj/item/clothing/I in list(C.back, C.wear_mask, C.head)) face_covered |= I.flags_inv
covered_locations |= I.body_parts_covered eyesmouth_covered |= I.flags_cover
face_covered |= I.flags_inv if(ishuman(C))
eyesmouth_covered |= I.flags_cover var/mob/living/carbon/human/H = C
if(ishuman(C)) for(var/obj/item/I in list(H.wear_suit, H.w_uniform, H.shoes, H.belt, H.gloves, H.glasses, H.ears))
var/mob/living/carbon/human/H = C covered_locations |= I.body_parts_covered
for(var/obj/item/I in list(H.wear_suit, H.w_uniform, H.shoes, H.belt, H.gloves, H.glasses, H.ears)) face_covered |= I.flags_inv
covered_locations |= I.body_parts_covered eyesmouth_covered |= I.flags_cover
face_covered |= I.flags_inv
eyesmouth_covered |= I.flags_cover switch(location)
if("head")
switch(location) if(covered_locations & HEAD)
if("head") return 0
if(covered_locations & HEAD) if("eyes")
return 0 if(covered_locations & HEAD || face_covered & HIDEEYES || eyesmouth_covered & GLASSESCOVERSEYES)
if("eyes") return 0
if(covered_locations & HEAD || face_covered & HIDEEYES || eyesmouth_covered & GLASSESCOVERSEYES) if("mouth")
return 0 if(covered_locations & HEAD || face_covered & HIDEFACE || eyesmouth_covered & MASKCOVERSMOUTH || eyesmouth_covered & HEADCOVERSMOUTH)
if("mouth") return 0
if(covered_locations & HEAD || face_covered & HIDEFACE || eyesmouth_covered & MASKCOVERSMOUTH || eyesmouth_covered & HEADCOVERSMOUTH) if("chest")
return 0 if(covered_locations & CHEST)
if("chest") return 0
if(covered_locations & CHEST) if("groin")
return 0 if(covered_locations & GROIN)
if("groin") return 0
if(covered_locations & GROIN) if("l_arm")
return 0 if(covered_locations & ARM_LEFT)
if("l_arm") return 0
if(covered_locations & ARM_LEFT) if("r_arm")
return 0 if(covered_locations & ARM_RIGHT)
if("r_arm") return 0
if(covered_locations & ARM_RIGHT) if("l_leg")
return 0 if(covered_locations & LEG_LEFT)
if("l_leg") return 0
if(covered_locations & LEG_LEFT) if("r_leg")
return 0 if(covered_locations & LEG_RIGHT)
if("r_leg") return 0
if(covered_locations & LEG_RIGHT) if("l_hand")
return 0 if(covered_locations & HAND_LEFT)
if("l_hand") return 0
if(covered_locations & HAND_LEFT) if("r_hand")
return 0 if(covered_locations & HAND_RIGHT)
if("r_hand") return 0
if(covered_locations & HAND_RIGHT) if("l_foot")
return 0 if(covered_locations & FOOT_LEFT)
if("l_foot") return 0
if(covered_locations & FOOT_LEFT) if("r_foot")
return 0 if(covered_locations & FOOT_RIGHT)
if("r_foot") return 0
if(covered_locations & FOOT_RIGHT)
return 0 return 1
return 1