Files
Yogstation/code/modules/surgery/helpers.dm
Molti 9fd5437ae1 Can no longer do mechanical surgeries on simple mobs (#20693)
* Update helpers.dm

* Update helpers.dm

* Update helpers.dm
2023-11-03 02:22:55 -05:00

190 lines
6.6 KiB
Plaintext

/proc/attempt_initiate_surgery(obj/item/I, mob/living/M, mob/user)
if(!istype(M))
return
var/mob/living/carbon/C
var/obj/item/bodypart/affecting
var/selected_zone = user.zone_selected
if(user.a_intent == INTENT_HARM)
return FALSE
if(iscarbon(M))
C = M
affecting = C.get_bodypart(check_zone(selected_zone))
var/datum/surgery/current_surgery
for(var/datum/surgery/S in M.surgeries)
if(S.location == selected_zone)
current_surgery = S
if(!current_surgery)
var/list/all_surgeries = GLOB.surgeries_list.Copy()
var/list/available_surgeries = list()
var/list/radial_list = list()
for(var/datum/surgery/S in all_surgeries)
if(!S.possible_locs.Find(selected_zone))
continue
if(affecting)
if(!S.requires_bodypart)
continue
if(S.requires_bodypart_type && affecting.status != S.requires_bodypart_type)
continue
if(S.requires_real_bodypart && affecting.is_pseudopart)
continue
else if(C && S.requires_bodypart) //mob with no limb in surgery zone when we need a limb
continue
else if(S.requires_bodypart_type == BODYPART_ORGANIC && !(M.mob_biotypes & MOB_ORGANIC))
continue //simplemob surgeries based on biotypes
else if(S.requires_bodypart_type == BODYPART_ROBOTIC && !(M.mob_biotypes & MOB_ROBOTIC))
continue
if(S.lying_required && (M.mobility_flags & MOBILITY_STAND))
continue
if(!S.can_start(user, M))
continue
for(var/path in S.target_mobtypes)
if(istype(M, path))
available_surgeries[S.name] = S
var/datum/radial_menu_choice/choice = new
choice.image = S.get_icon()
choice.info = S.desc
radial_list[S.name] = choice
break
if(!available_surgeries.len)
to_chat(user, span_warning("You can't perform any surgeries on [M]'s [parse_zone(selected_zone)]!"))
return TRUE
var/P = show_radial_menu(user, M, radial_list, radius = 40, require_near = TRUE, tooltips = TRUE)
if(P && user && user.Adjacent(M) && (I in user))
var/datum/surgery/S = available_surgeries[P]
for(var/datum/surgery/other in M.surgeries)
if(other.location == selected_zone)
return TRUE //during the input() another surgery was started at the same location.
//we check that the surgery is still doable after the input() wait.
if(C)
affecting = C.get_bodypart(check_zone(selected_zone))
if(affecting)
if(!S.requires_bodypart)
return TRUE
if(S.requires_bodypart_type && affecting.status != S.requires_bodypart_type)
return TRUE
else if(C && S.requires_bodypart)
return TRUE
if(S.lying_required && (M.mobility_flags & MOBILITY_STAND))
return TRUE
if(!S.can_start(user, M))
return TRUE
if(S.ignore_clothes || get_location_accessible(M, selected_zone))
var/datum/surgery/procedure = new S.type(M, selected_zone, affecting)
user.visible_message("[user] prepares to operate on [M]'s [parse_zone(selected_zone)].", \
span_notice("You prepare to operate on [M]'s [parse_zone(selected_zone)]."))
playsound(get_turf(M), 'sound/items/handling/cloth_drop.ogg', 30, TRUE, falloff_exponent = 1)
log_combat(user, M, "operated on", null, "(OPERATION TYPE: [procedure.name]) (TARGET AREA: [selected_zone])")
if(S.self_operable || user != M)
procedure.next_step(user, user.a_intent)
else
M.balloon_or_message(user, "need to expose the [parse_zone(selected_zone)]", \
span_warning("You need to expose [M]'s [parse_zone(selected_zone)] first!"))
return TRUE
/proc/attempt_cancel_surgery(datum/surgery/S, obj/item/I, mob/living/M, mob/user)
var/selected_zone = user.zone_selected
to_chat(user, span_notice("You begin to cancel \the [S]."))
if(!do_after(user, 3 SECONDS, M))
return
if(S.status == 1)
M.surgeries -= S
user.visible_message("[user] stops the surgery on [M]'s [parse_zone(selected_zone)].", \
span_notice("You stop the surgery on [M]'s [parse_zone(selected_zone)]."))
qdel(S)
else if(S.can_cancel)
var/obj/item/close_tool = user.get_active_held_item()
if(close_tool.tool_behaviour == (S.requires_bodypart_type == BODYPART_ROBOTIC ? TOOL_SCREWDRIVER : TOOL_CAUTERY) || iscyborg(user))
if(S.operated_bodypart)
S.operated_bodypart.generic_bleedstacks -= 10
M.surgeries -= S
user.visible_message("[user] closes [M]'s [parse_zone(selected_zone)] with [close_tool].", \
span_notice("You close [M]'s [parse_zone(selected_zone)] with [close_tool]."))
qdel(S)
else
to_chat(user, span_warning("You need to hold a [S.requires_bodypart_type == BODYPART_ROBOTIC ? "screwdriver" : "cautery"] in your active hand to stop [M]'s surgery!"))
/proc/get_location_modifier(mob/M)
var/turf/T = get_turf(M)
if(locate(/obj/structure/table/optable, T))
return 1
else if(locate(/obj/structure/table, T))
return 0.8
else if(locate(/obj/structure/bed, T))
return 0.7
else
return 0.5
/proc/get_location_accessible(mob/M, location)
var/covered_locations = 0 //based on body_parts_covered
var/face_covered = 0 //based on flags_inv
var/eyesmouth_covered = 0 //based on flags_cover
if(iscarbon(M))
var/mob/living/carbon/C = M
for(var/obj/item/clothing/I in list(C.back, C.wear_mask, C.head))
covered_locations |= I.body_parts_covered
face_covered |= I.flags_inv
eyesmouth_covered |= I.flags_cover
if(ishuman(C))
var/mob/living/carbon/human/H = C
for(var/obj/item/I in list(H.wear_suit, H.w_uniform, H.shoes, H.belt, H.gloves, H.glasses, H.ears))
covered_locations |= I.body_parts_covered
face_covered |= I.flags_inv
eyesmouth_covered |= I.flags_cover
switch(location)
if(BODY_ZONE_HEAD)
if(covered_locations & HEAD)
return 0
if(BODY_ZONE_PRECISE_EYES)
if(face_covered & HIDEEYES || eyesmouth_covered & GLASSESCOVERSEYES || eyesmouth_covered & HEADCOVERSEYES || eyesmouth_covered & MASKCOVERSEYES)
return 0
if(BODY_ZONE_PRECISE_MOUTH)
if(face_covered & HIDEFACE || eyesmouth_covered & MASKCOVERSMOUTH || eyesmouth_covered & HEADCOVERSMOUTH)
return 0
if(BODY_ZONE_CHEST)
if(covered_locations & CHEST)
return 0
if(BODY_ZONE_PRECISE_GROIN)
if(covered_locations & GROIN)
return 0
if(BODY_ZONE_L_ARM)
if(covered_locations & ARM_LEFT)
return 0
if(BODY_ZONE_R_ARM)
if(covered_locations & ARM_RIGHT)
return 0
if(BODY_ZONE_L_LEG)
if(covered_locations & LEG_LEFT)
return 0
if(BODY_ZONE_R_LEG)
if(covered_locations & LEG_RIGHT)
return 0
if(BODY_ZONE_PRECISE_L_HAND)
if(covered_locations & HAND_LEFT)
return 0
if(BODY_ZONE_PRECISE_R_HAND)
if(covered_locations & HAND_RIGHT)
return 0
if(BODY_ZONE_PRECISE_L_FOOT)
if(covered_locations & FOOT_LEFT)
return 0
if(BODY_ZONE_PRECISE_R_FOOT)
if(covered_locations & FOOT_RIGHT)
return 0
return 1