Files
Paradise/code/modules/surgery/surgery.dm
alex-gh fc2b99bd51 Surgery refactors (#18183)
* Remove dead code

* Refactor magic numbers to defines
2022-07-05 21:20:38 +02:00

208 lines
7.2 KiB
Plaintext

///Datum Surgery Helpers//
/datum/surgery
var/name
var/status = 1
var/list/steps = list() //Steps in a surgery
var/can_cancel = TRUE
var/step_in_progress = FALSE
var/list/in_progress = list() //Actively performing a Surgery
var/location = "chest" //Surgery location
var/requires_organic_bodypart = TRUE //Prevents you from performing an operation on robotic limbs
var/list/possible_locs = list() //Multiple locations -- c0
var/obj/item/organ/organ_ref //Operable body part
var/current_organ = "organ"
var/list/allowed_mob = list(/mob/living/carbon/human)
/datum/surgery/proc/can_start(mob/user, mob/living/carbon/target)
// if FALSE surgery wont show up in list
// put special restrictions here
return TRUE
/datum/surgery/proc/next_step(mob/user, mob/living/carbon/target)
if(step_in_progress) return
var/datum/surgery_step/S = get_surgery_step()
if(S)
if(S.try_op(user, target, user.zone_selected, user.get_active_hand(), src))
return TRUE
return FALSE
/datum/surgery/proc/get_surgery_step()
var/step_type = steps[status]
return new step_type
/datum/surgery/proc/complete(mob/living/carbon/human/target)
target.surgeries -= src
qdel(src)
/* SURGERY STEPS */
/datum/surgery_step
// type path referencing tools that can be used for this step, and how well are they suited for it
var/list/allowed_tools = null
var/implement_type = null
// duration of the step
var/time = 10
var/name
var/accept_hand = FALSE //does the surgery step require an open hand? If true, ignores implements. Compatible with accept_any_item.
var/accept_any_item = FALSE
// evil infection stuff that will make everyone hate me
var/can_infect = FALSE
//How much blood this step can get on surgeon. 1 - hands, 2 - full body.
var/blood_level = 0
/datum/surgery_step/proc/try_op(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
var/success = FALSE
if(accept_hand)
if(!tool)
success = TRUE
if(accept_any_item)
if(tool && tool_quality(tool))
success = TRUE
else
for(var/path in allowed_tools)
if(istype(tool, path))
implement_type = path
if(tool_quality(tool))
success = TRUE
if(success)
if(target_zone == surgery.location)
initiate(user, target, target_zone, tool, surgery)
return TRUE //returns TRUE so we don't stab the guy in the dick or wherever.
return FALSE
/datum/surgery_step/proc/initiate(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(!can_use(user, target, target_zone, tool, surgery))
return
surgery.step_in_progress = TRUE
var/speed_mod = 1
if(begin_step(user, target, target_zone, tool, surgery) == -1)
surgery.step_in_progress = FALSE
return
if(tool)
speed_mod = tool.toolspeed
if(do_after(user, time * speed_mod, target = target))
var/advance = FALSE
var/prob_chance = 100
if(implement_type) //this means it isn't a require nd or any item step.
prob_chance = allowed_tools[implement_type]
prob_chance *= get_location_modifier(target)
if(!ispath(surgery.steps[surgery.status], /datum/surgery_step/robotics))//Repairing robotic limbs doesn't hurt, and neither does cutting someone out of a rig
if(ishuman(target))
var/mob/living/carbon/human/H = target //typecast to human
var/pain_mod = get_pain_modifier(H)
var/datum/status_effect/incapacitating/sleeping/S = H.IsSleeping()
if(S?.voluntary)
H.SetSleeping(0) // wake up people who are napping through the surgery
if(pain_mod < 0.95)
to_chat(H, "<span class='danger'>The surgery on your [parse_zone(target_zone)] is agonizingly painful, and rips you out of your shallow slumber!</span>")
else
// Still wake people up, but they shouldn't be as alarmed.
to_chat(H, "<span class='warning'>The surgery being performed on your [parse_zone(target_zone)] wakes you up.</span>")
prob_chance *= pain_mod //operating on conscious people is hard.
if(prob(prob_chance) || isrobot(user))
if(end_step(user, target, target_zone, tool, surgery))
advance = TRUE
else
if(fail_step(user, target, target_zone, tool, surgery))
advance = TRUE
if(advance)
surgery.status++
if(surgery.status > surgery.steps.len)
surgery.complete(target)
surgery.step_in_progress = FALSE
//returns how well tool is suited for this step
/datum/surgery_step/proc/tool_quality(obj/item/tool)
for(var/T in allowed_tools)
if(istype(tool,T))
return allowed_tools[T]
return 0
// Checks if this step applies to the user mob at all
/datum/surgery_step/proc/is_valid_target(mob/living/carbon/human/target)
if(!hasorgans(target))
return FALSE
return TRUE
// checks whether this step can be applied with the given user and target
/datum/surgery_step/proc/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery)
return TRUE
// does stuff to begin the step, usually just printing messages. Moved germs transfering and bloodying here too
/datum/surgery_step/proc/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery)
if(ishuman(target))
var/obj/item/organ/external/affected = target.get_organ(target_zone)
if(can_infect && affected)
spread_germs_to_organ(affected, user, tool)
if(ishuman(user) && !(istype(target,/mob/living/carbon/alien)) && prob(60))
var/mob/living/carbon/human/H = user
if(blood_level)
H.bloody_hands(target,0)
if(blood_level > 1)
H.bloody_body(target,0)
return
// does stuff to end the step, which is normally print a message + do whatever this step changes
/datum/surgery_step/proc/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery)
return
// stuff that happens when the step fails
/datum/surgery_step/proc/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery)
return null
/proc/spread_germs_to_organ(obj/item/organ/E, mob/living/carbon/human/user, obj/item/tool)
if(!istype(user) || !istype(E) || E.is_robotic() || E.sterile)
return
var/germ_level = user.germ_level
//germ spread from surgeon touching the patient
if(user.gloves)
germ_level = user.gloves.germ_level
E.germ_level = max(germ_level, E.germ_level)
spread_germs_by_incision(E, tool) //germ spread from environement to patient
/proc/spread_germs_by_incision(obj/item/organ/external/E,obj/item/tool)
if(!istype(E, /obj/item/organ/external))
return
var/germs = 0
for(var/mob/living/carbon/human/H in view(2, E.loc))//germs from people
if(AStar(E.loc, H.loc, /turf/proc/Distance, 2, simulated_only = 0))
if(!HAS_TRAIT(H, TRAIT_NOBREATH) && !H.wear_mask) //wearing a mask helps preventing people from breathing cooties into open incisions
germs += H.germ_level * 0.25
for(var/obj/effect/decal/cleanable/M in view(2, E.loc))//germs from messes
if(AStar(E.loc, M.loc, /turf/proc/Distance, 2, simulated_only = 0))
germs++
if(tool && tool.blood_DNA && tool.blood_DNA.len) //germs from blood-stained tools
germs += 30
if(E.internal_organs.len)
germs = germs / (E.internal_organs.len + 1) // +1 for the external limb this eventually applies to; let's not multiply germs now.
for(var/obj/item/organ/internal/O in E.internal_organs)
if(!O.is_robotic())
O.germ_level += germs
E.germ_level += germs