From op_stage
to surgeryHolder
This is a difficult problem, and the currently implemented solution most importanly works very consistently; it's already worked through most potential corner-cases and potential issues. I am coming to this code with a different objective and perspective, many years on from the original constraints that this design fulfilled.
Thank you for your consideration.
Surgery status is handled via an integer variable stored on an object, usually the organ
, and which "stage" the surgery is in is represented via integers. These integers live on different objects:
/obj/item/organ
(i.e. head, chest, internal organs)
op_stage
- keeps track of the current OPeration STAGEorgan_holder_required_op_stage
- value to check against op_stage
when attaching/obj/item/parts
(i.e. limbs) has the remove_stage
variable/obj/item/organ/head
has the scalp_op_stage
variable/mob/living
has the butt_op_stage
variableThese integers are then gently nudged by large procs custom built for each surgery type. Individual items must specifically call the related surgery proc in order to attempt surgery.
The more surgery steps done with the tool, the greater the complexity of individual procs:
Surgery Proc Name | Lines in File | Number of if s |
---|---|---|
scalpel_surgery | 690 | 81 |
saw_surgery | 361 | 46 |
suture_surgery | 165 | 29 |
cautery_surgery | 150 | 19 |
spoon_surgery | 105 | 16 |
snip_surgery | 271 | 32 |
crowbar_surgery | 54 | 8 |
wrench_surgery | 34 | 8 |
In addition, this complexity spills out into other code; get_desc.dm
can be impenetrable without knowing op_stages. Within surgery_procs
itself, there are duplicated sections of code that resist condensing into helper procs because they are, in essence, data about the surgery step. This style of design makes the data encoded within difficult to use in other contexts without writing bespoke interpretations for the various organs and op_stage
values.
To quote from the code at writing:
This is a difficult problem.
Surgery itself has state, and is also the interface between a surgeon and several other state systems at once:
/datum/human_limbs
system for limbs/datum/organHolder
system for internal organs/obj/item/
attacksIt also interacts more directly with some other play systems:
clumsy
, training_medical
)bioHolder.mutantrace
(tails, skeletons) on some surgery typesRepresent the state of surgery as a set of node graphs, with a state machine-like traversal proc.
This works alongside the existing limb and organHolder
systems; it is not a replacement.
This shows all node graphs, joined together for ease of viewing; not designed to work with the Simulate option.
https://stately.ai/registry/editor/3668c891-176d-4275-9b7c-adca95c720fc?machineId=a9531a72-9fd9-4a9f-a011-c4468208e88b
node
transitions
map, whose keys are other node
datums and values are a map:
conditions
- a list of condition
effects
- a list of effect
condition
check
proc that returns bool TRUE
/FALSE
/datum/surgeryHolder/condition/has/*
has a part in place?/datum/surgeryHolder/condition/tool/*
surgeon's tool?/datum/surgeryHolder/condition/intent/*
surgeon's intent?/datum/surgeryHolder/condition/hand/*
surgeon using specific hand?effect
do_effect
proc/datum/surgeryHolder/effect/damage/*
surgery damage/datum/surgeryHolder/effect/bleed
Bleed damage/animation/datum/surgeryHolder/condition/attach/*
Part (de-)attachmentget_surgery_transition
check
for every condition
attempt_surgery
surgeryHolder
statezone_sel
switch to determine which graph(s) to check
surgeryCheck
- adaptablecalc_screw_up_prob
- as-isFrom some lightweight testing, I think this is the minimum collection of graphs to keep track of.
This is an example of what we'd commonly see on a new /mob/living/carbon/human
, having all their parts together.
/obj/item/organ/head
var/list/surgeryHolders
"neck" = /datum/surgeryHolder/node/neck/attached
"l_eye" = /datum/surgeryHolder/node/l_eye/attached
"r_eye" = /datum/surgeryHolder/node/r_eye/attached
"brain" = /datum/surgeryHolder/node/brain/attached
/obj/item/organ/chest
var/surgeryHolder
/datum/surgeryHolder/node/chest/neutral
/obj/item/limb
var/surgeryHolder
/datum/surgeryHolder/node/limb/attached
surgery_flags
& helper issurgerytool
defines
secret
surgeriesop_stage
checks is a lot of worksecret
content