diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index 96f9c11e17..c53ba430e0 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -725,12 +725,22 @@ var/surgery /datum/design/surgery/experimental_dissection - name = "Experimental Dissection" - desc = "A surgical procedure which deeply analyzes the biology of a corpse, and automatically adds new findings to the research database." - id = "surgery_exp_dissection" - surgery = /datum/surgery/experimental_dissection + name = "Advanced Dissection" + desc = "A surgical procedure which analyzes the biology of a corpse, and automatically adds new findings to the research database." + id = "surgery_adv_dissection" + surgery = /datum/surgery/advanced/experimental_dissection/adv research_icon_state = "surgery_chest" +/datum/design/surgery/experimental_dissection/exp + name = "Experimental Dissection" + id = "surgery_exp_dissection" + surgery = /datum/surgery/advanced/experimental_dissection/exp + +/datum/design/surgery/experimental_dissection/exp + name = "Extraterrestrial Dissection" + id = "surgery_ext_dissection" + surgery = /datum/surgery/advanced/experimental_dissection/alien + /datum/design/surgery/lobotomy name = "Lobotomy" desc = "An invasive surgical procedure which guarantees removal of almost all brain traumas, but might cause another permanent trauma in return." diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 93370af547..cb5112353e 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -115,7 +115,7 @@ display_name = "Advanced Surgery" description = "When simple medicine doesn't cut it." prereq_ids = list("adv_biotech") - design_ids = list("surgery_lobotomy", "surgery_reconstruction", "surgery_toxinhealing", "organbox") + design_ids = list("surgery_lobotomy", "surgery_reconstruction", "surgery_toxinhealing", "organbox", "surgery_adv_dissection") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) export_price = 5000 @@ -124,7 +124,7 @@ display_name = "Experimental Surgery" description = "When evolution isn't fast enough." prereq_ids = list("adv_surgery") - design_ids = list("surgery_revival","surgery_pacify","surgery_vein_thread","surgery_nerve_splice","surgery_nerve_ground","surgery_ligament_hook","surgery_ligament_reinforcement","surgery_viral_bond") + design_ids = list("surgery_revival","surgery_pacify","surgery_vein_thread","surgery_nerve_splice","surgery_nerve_ground","surgery_ligament_hook","surgery_ligament_reinforcement","surgery_viral_bond", "surgery_exp_dissection") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) export_price = 5000 @@ -133,7 +133,7 @@ display_name = "Alien Surgery" description = "Abductors did nothing wrong." prereq_ids = list("exp_surgery", "alientech") - design_ids = list("surgery_brainwashing","surgery_zombie") + design_ids = list("surgery_brainwashing","surgery_zombie", "surgery_ext_dissection") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) export_price = 5000 diff --git a/code/modules/surgery/experimental_dissection.dm b/code/modules/surgery/experimental_dissection.dm index c8daf9412e..6dc9441b0c 100644 --- a/code/modules/surgery/experimental_dissection.dm +++ b/code/modules/surgery/experimental_dissection.dm @@ -1,61 +1,87 @@ -/datum/surgery/experimental_dissection - name = "Experimental Dissection" - desc = "A surgical procedure which deeply analyzes the biology of a corpse, and automatically adds new findings to the research database." +#define BASE_HUMAN_REWARD 500 +#define EXPDIS_FAIL_MSG "You dissect [target], but do not find anything particularly interesting." + +/datum/surgery/advanced/experimental_dissection + name = "Dissection" + desc = "A surgical procedure which analyzes the biology of a corpse, and automatically adds new findings to the research database." steps = list(/datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/clamp_bleeders, - /datum/surgery_step/incise, /datum/surgery_step/dissection, + /datum/surgery_step/clamp_bleeders, /datum/surgery_step/close) possible_locs = list(BODY_ZONE_CHEST) - target_mobtypes = list(/mob/living/carbon) //Feel free to dissect devils but they're magic. + target_mobtypes = list(/mob/living) //Feel free to dissect devils but they're magic. + replaced_by = /datum/surgery/advanced/experimental_dissection/adv + requires_tech = FALSE + var/value_multiplier = 1 -/datum/surgery/experimental_dissection/can_start(mob/user, mob/living/carbon/target) +/datum/surgery/advanced/experimental_dissection/can_start(mob/user, mob/living/target) . = ..() - if(HAS_TRAIT(target, TRAIT_DISSECTED)) + if(HAS_TRAIT_FROM(target, TRAIT_DISSECTED,"[name]")) return FALSE - if(iscyborg(user)) - return FALSE //robots cannot be creative - //(also this surgery shouldn't be consistently successful, and cyborgs have a 100% success rate on surgery) if(target.stat != DEAD) return FALSE /datum/surgery_step/dissection name = "dissection" - implements = list(/obj/item/scalpel = 60, /obj/item/kitchen/knife = 30, /obj/item/shard = 15) + implements = list(/obj/item/scalpel/augment = 75, /obj/item/scalpel/advanced = 60, /obj/item/scalpel = 45, /obj/item/kitchen/knife = 20, /obj/item/shard = 10)// special tools not only cut down time but also improve probability time = 125 + silicons_obey_prob = TRUE + repeatable = TRUE /datum/surgery_step/dissection/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You start dissecting [target].", "[user] starts dissecting [target].", "[user] starts dissecting [target].") -/datum/surgery_step/dissection/proc/check_value(mob/living/carbon/target) +/datum/surgery_step/dissection/proc/check_value(mob/living/target, datum/surgery/advanced/experimental_dissection/ED) + var/cost = BASE_HUMAN_REWARD + var/multi_surgery_adjust = 0 + + //determine bonus applied if(isalienroyal(target)) - return 10000 + cost = (BASE_HUMAN_REWARD*10) else if(isalienadult(target)) - return 5000 + cost = (BASE_HUMAN_REWARD*5) else if(ismonkey(target)) - return 1000 + cost = (BASE_HUMAN_REWARD*0.5) else if(ishuman(target)) var/mob/living/carbon/human/H = target - if(H.dna && H.dna.species) + if(H?.dna?.species) if(isabductor(H)) - return 8000 - if(isgolem(H) || iszombie(H)) - return 4000 - if(isjellyperson(H) || ispodperson(H)) - return 3000 - return 2000 + cost = (BASE_HUMAN_REWARD*4) + else if(isgolem(H) || iszombie(H)) + cost = (BASE_HUMAN_REWARD*3) + /*else if(isjellyperson(H) || ispodperson(H)) CITADEL CHANGE: jelly and pod being available roundstart shouldn't give additional points + cost = (BASE_HUMAN_REWARD*2)*/ + else + cost = (BASE_HUMAN_REWARD * 0.6) -/datum/surgery_step/dissection/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, "You dissect [target], and add your discoveries to the research database!", - "[user] dissects [target], adding [user.p_their()] discoveries to the research database!", + + + //now we do math for surgeries already done (no double dipping!). + for(var/i in typesof(/datum/surgery/advanced/experimental_dissection)) + var/datum/surgery/advanced/experimental_dissection/cringe = i + if(HAS_TRAIT_FROM(target,TRAIT_DISSECTED,"[initial(cringe.name)]")) + multi_surgery_adjust = max(multi_surgery_adjust,initial(cringe.value_multiplier)) - 1 + + multi_surgery_adjust *= cost + + //multiply by multiplier in surgery + cost *= ED.value_multiplier + return (cost-multi_surgery_adjust) + +/datum/surgery_step/dissection/success(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery) + var/points_earned = check_value(target, surgery) + display_results(user, target, "You dissect [target], and add your [points_earned] point\s worth of discoveries to the research database!", + "[user] dissects [target], discovering [points_earned] point\s of data!", "[user] dissects [target]!") - SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = check_value(target))) + SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = points_earned)) var/obj/item/bodypart/L = target.get_bodypart(BODY_ZONE_CHEST) target.apply_damage(80, BRUTE, L) - ADD_TRAIT(target, TRAIT_DISSECTED, "surgery") + ADD_TRAIT(target, TRAIT_DISSECTED, "[surgery.name]") + repeatable = FALSE return TRUE /datum/surgery_step/dissection/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) @@ -63,7 +89,28 @@ "[user] dissects [target], however it seems [user.p_they()] didn't find anything useful.", "[user] dissects [target], but looks a little dissapointed.") SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = (check_value(target) * 0.2))) + SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = (round(check_value(target, surgery) * 0.01)))) var/obj/item/bodypart/L = target.get_bodypart(BODY_ZONE_CHEST) target.apply_damage(80, BRUTE, L) - ADD_TRAIT(target, TRAIT_DISSECTED, "surgery") - return TRUE \ No newline at end of file + return TRUE + +/datum/surgery/advanced/experimental_dissection/adv + name = "Thorough Dissection" + value_multiplier = 2 + replaced_by = /datum/surgery/advanced/experimental_dissection/exp + requires_tech = TRUE + +/datum/surgery/advanced/experimental_dissection/exp + name = "Experimental Dissection" + value_multiplier = 5 + replaced_by = /datum/surgery/advanced/experimental_dissection/alien + requires_tech = TRUE + +/datum/surgery/advanced/experimental_dissection/alien + name = "Extraterrestrial Dissection" + value_multiplier = 10 + requires_tech = TRUE + + +#undef BASE_HUMAN_REWARD +#undef EXPDIS_FAIL_MSG diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm index ccf5ad4386..a220abba6c 100644 --- a/code/modules/surgery/surgery.dm +++ b/code/modules/surgery/surgery.dm @@ -1,3 +1,4 @@ +<<<<<<< HEAD /datum/surgery var/name = "surgery" var/desc = "surgery description" @@ -154,3 +155,179 @@ //RESOLVED ISSUES //"Todo" jobs that have been completed //combine hands/feet into the arms - Hands/feet were removed - RR //surgeries (not steps) that can be initiated on any body part (corresponding with damage locations) - Call this one done, see possible_locs var - c0 +======= +/datum/surgery + var/name = "surgery" + var/desc = "surgery description" + var/status = 1 + var/list/steps = list() //Steps in a surgery + var/step_in_progress = FALSE //Actively performing a Surgery + var/can_cancel = TRUE //Can cancel this surgery after step 1 with cautery + var/list/target_mobtypes = list(/mob/living/carbon/human) //Acceptable Species + var/location = BODY_ZONE_CHEST //Surgery location + var/requires_bodypart_type = BODYPART_ORGANIC //Prevents you from performing an operation on incorrect limbs. 0 for any limb type + var/list/possible_locs = list() //Multiple locations + var/ignore_clothes = FALSE //This surgery ignores clothes + var/mob/living/carbon/target //Operation target mob + var/obj/item/bodypart/operated_bodypart //Operable body part + var/requires_bodypart = TRUE //Surgery available only when a bodypart is present, or only when it is missing. + var/success_multiplier = 0 //Step success propability multiplier + var/requires_real_bodypart = FALSE //Some surgeries don't work on limbs that don't really exist + var/lying_required = TRUE //Does the vicitm needs to be lying down. + var/self_operable = FALSE //Can the surgery be performed on yourself. + var/requires_tech = FALSE //handles techweb-oriented surgeries, previously restricted to the /advanced subtype (You still need to add designs) + var/replaced_by //type; doesn't show up if this type exists. Set to /datum/surgery if you want to hide a "base" surgery (useful for typing parents IE healing.dm just make sure to null it out again) + +/datum/surgery/New(surgery_target, surgery_location, surgery_bodypart) + ..() + if(surgery_target) + target = surgery_target + target.surgeries += src + if(surgery_location) + location = surgery_location + if(surgery_bodypart) + operated_bodypart = surgery_bodypart + +/datum/surgery/Destroy() + if(target) + target.surgeries -= src + target = null + operated_bodypart = null + return ..() + + +/datum/surgery/proc/can_start(mob/user, mob/living) //FALSE to not show in list + . = TRUE + if(replaced_by == /datum/surgery) + return FALSE + + if(HAS_TRAIT(user, TRAIT_SURGEON) || HAS_TRAIT(user.mind, TRAIT_SURGEON)) + if(replaced_by) + return FALSE + else + return TRUE + + if(!requires_tech && !replaced_by) + return TRUE + // True surgeons (like abductor scientists) need no instructions + + if(requires_tech) + . = FALSE + + if(iscyborg(user)) + var/mob/living/silicon/robot/R = user + var/obj/item/surgical_processor/SP = locate() in R.module.modules + if(!SP || (replaced_by in SP.advanced_surgeries)) + return FALSE + if(type in SP.advanced_surgeries) + return TRUE + + + var/turf/T = get_turf(target) + var/obj/structure/table/optable/table = locate(/obj/structure/table/optable, T) + if(table) + if(!table.computer) + return FALSE + if(table.computer.stat & (NOPOWER|BROKEN) || (replaced_by in table.computer.advanced_surgeries)) + return FALSE + if(type in table.computer.advanced_surgeries) + return TRUE + + +/datum/surgery/proc/next_step(mob/user, intent) + if(step_in_progress) + return TRUE + + var/try_to_fail = FALSE + if(intent == INTENT_DISARM) + try_to_fail = TRUE + + var/datum/surgery_step/S = get_surgery_step() + if(S) + var/obj/item/tool = user.get_active_held_item() + if(S.try_op(user, target, user.zone_selected, tool, src, try_to_fail)) + return TRUE + if(iscyborg(user) && user.a_intent != INTENT_HARM) //to save asimov borgs a LOT of heartache + return TRUE + if(tool.item_flags & SURGICAL_TOOL) //Just because you used the wrong tool it doesn't mean you meant to whack the patient with it + to_chat(user, "This step requires a different tool!") + return TRUE + return FALSE + +/datum/surgery/proc/get_surgery_step() + var/step_type = steps[status] + return new step_type + +/datum/surgery/proc/get_surgery_next_step() + if(status < steps.len) + var/step_type = steps[status + 1] + return new step_type + else + return null + +/datum/surgery/proc/complete() + SSblackbox.record_feedback("tally", "surgeries_completed", 1, type) + qdel(src) + +/datum/surgery/proc/get_propability_multiplier() + var/propability = 0.5 + var/turf/T = get_turf(target) + + if(locate(/obj/structure/table/optable, T)) + propability = 1 + else if(locate(/obj/machinery/stasis, T)) + propability = 0.9 + else if(locate(/obj/structure/table, T)) + propability = 0.8 + else if(locate(/obj/structure/bed, T)) + propability = 0.7 + + return propability + success_multiplier + +/datum/surgery/advanced + name = "advanced surgery" + requires_tech = TRUE + +/obj/item/disk/surgery + name = "Surgery Procedure Disk" + desc = "A disk that contains advanced surgery procedures, must be loaded into an Operating Console." + icon_state = "datadisk1" + materials = list(MAT_METAL=300, MAT_GLASS=100) + var/list/surgeries + +/obj/item/disk/surgery/debug + name = "Debug Surgery Disk" + desc = "A disk that contains all existing surgery procedures." + icon_state = "datadisk1" + materials = list(MAT_METAL=300, MAT_GLASS=100) + +/obj/item/disk/surgery/debug/Initialize() + . = ..() + surgeries = list() + var/list/req_tech_surgeries = subtypesof(/datum/surgery) + for(var/i in req_tech_surgeries) + var/datum/surgery/beep = i + if(beep.requires_tech) + surgeries += beep + +//INFO +//Check /mob/living/carbon/attackby for how surgery progresses, and also /mob/living/carbon/attack_hand. +//As of Feb 21 2013 they are in code/modules/mob/living/carbon/carbon.dm, lines 459 and 51 respectively. +//Other important variables are var/list/surgeries (/mob/living) and var/list/internal_organs (/mob/living/carbon) +// var/list/bodyparts (/mob/living/carbon/human) is the LIMBS of a Mob. +//Surgical procedures are initiated by attempt_initiate_surgery(), which is called by surgical drapes and bedsheets. + + +//TODO +//specific steps for some surgeries (fluff text) +//more interesting failure options +//randomised complications +//more surgeries! +//add a probability modifier for the state of the surgeon- health, twitching, etc. blindness, god forbid. +//helper for converting a zone_sel.selecting to body part (for damage) + + +//RESOLVED ISSUES //"Todo" jobs that have been completed +//combine hands/feet into the arms - Hands/feet were removed - RR +//surgeries (not steps) that can be initiated on any body part (corresponding with damage locations) - Call this one done, see possible_locs var - c0 +>>>>>>> 8fcf42eff9... Experimental Cobbisection [150+ Hours and Ready] (#44821) diff --git a/code/modules/surgery/surgery_step.dm b/code/modules/surgery/surgery_step.dm index c5a944fbb2..71f813a5b5 100644 --- a/code/modules/surgery/surgery_step.dm +++ b/code/modules/surgery/surgery_step.dm @@ -8,7 +8,9 @@ var/repeatable = FALSE //can this step be repeated? Make shure it isn't last step, or it used in surgery with `can_cancel = 1`. Or surgion will be stuck in the loop var/list/chems_needed = list() //list of chems needed to complete the step. Even on success, the step will have no effect if there aren't the chems required in the mob. var/require_all_chems = TRUE //any on the list or all on the list? -/datum/surgery_step/proc/try_op(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE) + var/silicons_obey_prob = FALSE + +/datum/surgery_step/proc/try_op(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE) var/success = FALSE if(accept_hand) if(!tool) @@ -46,7 +48,8 @@ else surgery.status-- return FALSE -/datum/surgery_step/proc/initiate(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE) + +/datum/surgery_step/proc/initiate(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE) surgery.step_in_progress = TRUE var/speed_mod = 1 var/advance = FALSE @@ -60,7 +63,8 @@ if(implement_type) //this means it isn't a require hand or any item step. prob_chance = implements[implement_type] prob_chance *= surgery.get_propability_multiplier() - if((prob(prob_chance) || iscyborg(user)) && chem_check(target) && !try_to_fail) + + if((prob(prob_chance) || (iscyborg(user) && !silicons_obey_prob)) && chem_check(target) && !try_to_fail) if(success(user, target, target_zone, tool, surgery)) advance = TRUE else @@ -73,19 +77,18 @@ surgery.step_in_progress = FALSE return advance - -/datum/surgery_step/proc/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/proc/preop(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You begin to perform surgery on [target]...", "[user] begins to perform surgery on [target].", "[user] begins to perform surgery on [target].") -/datum/surgery_step/proc/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/proc/success(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You succeed.", "[user] succeeds!", "[user] finishes.") return TRUE -/datum/surgery_step/proc/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/proc/failure(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You screw up!", "[user] screws up!", "[user] finishes.", TRUE) //By default the patient will notice if the wrong thing has been cut @@ -93,7 +96,8 @@ /datum/surgery_step/proc/tool_check(mob/user, obj/item/tool) return TRUE -/datum/surgery_step/proc/chem_check(mob/living/carbon/target) + +/datum/surgery_step/proc/chem_check(mob/living/target) if(!LAZYLEN(chems_needed)) return TRUE if(require_all_chems)