diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 1cc90d4f29..77cbcb7536 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -60,8 +60,19 @@ #define BRAIN_TRAUMA_SEVERE /datum/brain_trauma/severe #define BRAIN_TRAUMA_SPECIAL /datum/brain_trauma/special +#define TRAUMA_RESILIENCE_BASIC 1 //Curable with chems +#define TRAUMA_RESILIENCE_SURGERY 2 //Curable with brain surgery +#define TRAUMA_RESILIENCE_LOBOTOMY 3 //Curable with lobotomy +#define TRAUMA_RESILIENCE_MAGIC 4 //Curable only with magic +#define TRAUMA_RESILIENCE_ABSOLUTE 5 //This is here to stay + #define BRAIN_DAMAGE_INTEGRITY_MULTIPLIER 0.5 +//Surgery Defines +#define BIOWARE_GENERIC "generic" +#define BIOWARE_NERVES "nerves" +#define BIOWARE_CIRCULATION "circulation" + //Health hud screws for carbon mobs #define SCREWYHUD_NONE 0 #define SCREWYHUD_CRIT 1 diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index 8c2791670c..5a9b8181af 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -26,7 +26,8 @@ #define ROLE_SERVANT_OF_RATVAR "servant of Ratvar" #define ROLE_BORER "borer" #define ROLE_BROTHER "blood brother" -#define ROLE_MISCREANT "miscreant" +#define ROLE_BRAINWASHED "brainwashed victim" +#define ROLE_MISCREANT "miscreant" //Missing assignment means it's not a gamemode specific role, IT'S NOT A BUG OR ERROR. //The gamemode specific ones are just so the gamemodes can query whether a player is old enough diff --git a/code/datums/brain_damage/brain_trauma.dm b/code/datums/brain_damage/brain_trauma.dm index 53b0fbe056..508dccef4a 100644 --- a/code/datums/brain_damage/brain_trauma.dm +++ b/code/datums/brain_damage/brain_trauma.dm @@ -10,12 +10,13 @@ var/gain_text = "You feel traumatized." var/lose_text = "You no longer feel traumatized." var/can_gain = TRUE //can this be gained through random traumas? - var/permanent = FALSE //can this be cured? + var/resilience = TRAUMA_RESILIENCE_BASIC //how hard is this to cure? -/datum/brain_trauma/New(obj/item/organ/brain/B, _permanent) +/datum/brain_trauma/New(obj/item/organ/brain/B, _resilience) brain = B owner = B.owner - permanent = _permanent + if(_resilience) + resilience = _resilience if(owner) on_gain() diff --git a/code/datums/brain_damage/severe.dm b/code/datums/brain_damage/severe.dm index b4d1951eb5..821770e9c5 100644 --- a/code/datums/brain_damage/severe.dm +++ b/code/datums/brain_damage/severe.dm @@ -3,6 +3,7 @@ //They cannot be cured with chemicals, and require brain surgery to solve. /datum/brain_trauma/severe + resilience = TRAUMA_RESILIENCE_SURGERY /datum/brain_trauma/severe/mute name = "Mutism" diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 59cbf745f8..4e9aab7b4c 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -964,7 +964,7 @@ var/angle = input(usr, "Choose angle to rotate","Transform Mod") as null|num if(!isnull(angle)) A.transform = M.Turn(angle) - + href_list["datumrefresh"] = href_list["modtransform"] else if(href_list["rotatedatum"]) @@ -1006,7 +1006,6 @@ var/list/traumas = subtypesof(/datum/brain_trauma) var/result = input(usr, "Choose the brain trauma to apply","Traumatize") as null|anything in traumas - var/permanent = alert("Do you want to make the trauma unhealable?", "Permanently Traumatize", "Yes", "No") if(!usr) return if(QDELETED(C)) @@ -1014,7 +1013,7 @@ return if(result) - C.gain_trauma(result, permanent) + C.gain_trauma(result) href_list["datumrefresh"] = href_list["givetrauma"] @@ -1027,7 +1026,7 @@ to_chat(usr, "This can only be done to instances of type /mob/living/carbon") return - C.cure_all_traumas(TRUE, TRUE) + C.cure_all_traumas(TRUE, TRAUMA_RESILIENCE_ABSOLUTE) href_list["datumrefresh"] = href_list["curetraumas"] diff --git a/code/datums/diseases/advance/symptoms/sensory.dm b/code/datums/diseases/advance/symptoms/sensory.dm index bb1170bc58..de146fd9d1 100644 --- a/code/datums/diseases/advance/symptoms/sensory.dm +++ b/code/datums/diseases/advance/symptoms/sensory.dm @@ -54,12 +54,11 @@ M.adjustBrainLoss(-3) if(trauma_heal_mild && iscarbon(M)) var/mob/living/carbon/C = M - if(prob(30) && C.has_trauma_type(BRAIN_TRAUMA_SPECIAL)) - C.cure_trauma_type(BRAIN_TRAUMA_SPECIAL) - if(prob(10) && C.has_trauma_type(BRAIN_TRAUMA_MILD)) - C.cure_trauma_type(BRAIN_TRAUMA_MILD) - if(trauma_heal_severe && prob(10) && C.has_trauma_type(BRAIN_TRAUMA_SEVERE)) - C.cure_trauma_type(BRAIN_TRAUMA_SEVERE) + if(prob(10)) + if(trauma_heal_severe) + C.cure_trauma_type(TRAUMA_RESILIENCE_LOBOTOMY) + else + C.cure_trauma_type(TRAUMA_RESILIENCE_BASIC) diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm index 8d53987a2b..4dca5017b9 100644 --- a/code/game/machinery/computer/Operating.dm +++ b/code/game/machinery/computer/Operating.dm @@ -6,12 +6,24 @@ circuit = /obj/item/circuitboard/computer/operating var/mob/living/carbon/human/patient var/obj/structure/table/optable/table + var/list/advanced_surgeries = list() light_color = LIGHT_COLOR_BLUE /obj/machinery/computer/operating/Initialize() . = ..() find_table() +/obj/machinery/computer/operating/attackby(obj/item/O, mob/user, params) + if(istype(O, /obj/item/disk/surgery)) + user.visible_message("[user] begins to load \the [O] in \the [src]...", + "You begin to load a surgery protocol from \the [O]...", + "You hear the chatter of a floppy drive.") + var/obj/item/disk/surgery/D = O + if(do_after(user, 10, target = src)) + advanced_surgeries |= D.surgeries + return TRUE + return ..() + /obj/machinery/computer/operating/proc/find_table() for(var/direction in GLOB.cardinals) table = locate(/obj/structure/table/optable, get_step(src, direction)) @@ -69,4 +81,4 @@ "next_step" = capitalize(surgery_step.name), "alternative_step" = alternative_step )) - return data + return data \ No newline at end of file diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index acfa74980b..3c778818a5 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -161,7 +161,16 @@ GAS ANALYZER if(LAZYLEN(C.get_traumas())) var/list/trauma_text = list() for(var/datum/brain_trauma/B in C.get_traumas()) - trauma_text += B.scan_desc + var/trauma_desc = "" + switch(B.resilience) + if(TRAUMA_RESILIENCE_SURGERY) + trauma_desc += "severe " + if(TRAUMA_RESILIENCE_LOBOTOMY) + trauma_desc += "deep-rooted " + if(TRAUMA_RESILIENCE_MAGIC, TRAUMA_RESILIENCE_ABSOLUTE) + trauma_desc += "permanent " + trauma_desc += B.scan_desc + trauma_text += trauma_desc to_chat(user, "\tCerebral traumas detected: subjects appears to be suffering from [english_list(trauma_text)].") if(advanced) to_chat(user, "\tBrain Activity Level: [(200 - M.getBrainLoss())/2]%.") diff --git a/code/game/objects/items/implants/implant_loyality.dm b/code/game/objects/items/implants/implant_loyality.dm index 186730d0fc..773d784fbd 100644 --- a/code/game/objects/items/implants/implant_loyality.dm +++ b/code/game/objects/items/implants/implant_loyality.dm @@ -20,13 +20,17 @@ if(..()) if(!target.mind) return TRUE + + if(target.mind.has_antag_datum(/datum/antagonist/brainwashed)) + target.mind.remove_antag_datum(/datum/antagonist/brainwashed) + if(target.mind.has_antag_datum(/datum/antagonist/rev/head) || target.mind.unconvertable) if(!silent) target.visible_message("[target] seems to resist the implant!", "You feel something interfering with your mental conditioning, but you resist it!") removed(target, 1) qdel(src) return FALSE - + var/datum/antagonist/rev/rev = target.mind.has_antag_datum(/datum/antagonist/rev) if(rev) rev.remove_revolutionary(FALSE, user) diff --git a/code/game/objects/items/implants/implantchair.dm b/code/game/objects/items/implants/implantchair.dm index 448b32e2d5..e8933b7151 100644 --- a/code/game/objects/items/implants/implantchair.dm +++ b/code/game/objects/items/implants/implantchair.dm @@ -179,17 +179,16 @@ /obj/machinery/implantchair/brainwash/implant_action(mob/living/C,mob/user) if(!istype(C) || !C.mind) // I don't know how this makes any sense for silicons but laws trump objectives anyway. - return 0 + return FALSE if(custom) if(!user || !user.Adjacent(src)) - return 0 + return FALSE objective = stripped_input(usr,"What order do you want to imprint on [C]?","Enter the order","",120) message_admins("[key_name_admin(user)] set brainwash machine objective to '[objective]'.") log_game("[key_name(user)] set brainwash machine objective to '[objective]'.") - var/datum/objective/custom_objective = new/datum/objective(objective) - custom_objective.owner = C.mind - C.mind.objectives += custom_objective - C.mind.announce_objectives() + if(C.isloyal()) + return FALSE + brainwash(C, objective) message_admins("[key_name_admin(user)] brainwashed [key_name_admin(C)] with objective '[objective]'.") log_game("[key_name(user)] brainwashed [key_name(C)] with objective '[objective]'.") - return 1 + return TRUE \ No newline at end of file diff --git a/code/modules/antagonists/abductor/abductor.dm b/code/modules/antagonists/abductor/abductor.dm index 2f6ef07afd..8e29b38fe1 100644 --- a/code/modules/antagonists/abductor/abductor.dm +++ b/code/modules/antagonists/abductor/abductor.dm @@ -11,7 +11,7 @@ var/outfit var/landmark_type var/greet_text - + /datum/antagonist/abductor/agent name = "Abductor Agent" @@ -167,7 +167,7 @@ /datum/antagonist/abductee/proc/give_objective() var/mob/living/carbon/human/H = owner.current if(istype(H)) - H.gain_trauma_type(BRAIN_TRAUMA_MILD) + H.gain_trauma_type(BRAIN_TRAUMA_MILD, TRAUMA_RESILIENCE_LOBOTOMY) var/objtype = (prob(75) ? /datum/objective/abductee/random : pick(subtypesof(/datum/objective/abductee/) - /datum/objective/abductee/random)) var/datum/objective/abductee/O = new objtype() objectives += O diff --git a/code/modules/antagonists/abductor/equipment/abduction_surgery.dm b/code/modules/antagonists/abductor/equipment/abduction_surgery.dm index ffce85e435..656fb61f43 100644 --- a/code/modules/antagonists/abductor/equipment/abduction_surgery.dm +++ b/code/modules/antagonists/abductor/equipment/abduction_surgery.dm @@ -52,49 +52,4 @@ user.temporarilyRemoveItemFromInventory(tool, TRUE) var/obj/item/organ/heart/gland/gland = tool gland.Insert(target, 2) - return 1 - -/datum/surgery/pacify - name = "violence neutralization" - steps = list(/datum/surgery_step/incise, - /datum/surgery_step/retract_skin, - /datum/surgery_step/saw, - /datum/surgery_step/clamp_bleeders, - /datum/surgery_step/pacify, - /datum/surgery_step/close) - - species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) - possible_locs = list("head") - requires_bodypart_type = 0 - -/datum/surgery/pacify/can_start(mob/user, mob/living/carbon/target) - if(!ishuman(user)) - return FALSE - var/mob/living/carbon/human/H = user - . = FALSE - if(!(H.dna.species.id == "abductor")) - . = TRUE - for(var/obj/item/implant/abductor/A in H.implants) - . = TRUE - var/obj/item/organ/brain/B = target.getorganslot(ORGAN_SLOT_BRAIN) - if(!B) - to_chat(user, "It's hard to do surgery on someone's brain when they don't have one.") - return FALSE - -/datum/surgery_step/pacify - name = "rewire brain" - implements = list(/obj/item/hemostat = 100, /obj/item/screwdriver = 35, /obj/item/pen = 15) - time = 40 - -/datum/surgery_step/pacify/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - user.visible_message("[user] begins to reshape [target]'s brain.", "You begin to reshape [target]'s brain...") - -/datum/surgery_step/pacify/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - user.visible_message("[user] successfully reshapes [target]'s brain!", "You succeed in reshaping [target]'s brain.") - target.gain_trauma(/datum/brain_trauma/severe/pacifism) - return TRUE - -/datum/surgery_step/pacify/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - user.visible_message("[user] successfully reshapes [target]'s brain!", "You screwed up, and rewired [target]'s brain the wrong way around...") - target.gain_trauma_type(BRAIN_TRAUMA_SEVERE) - return FALSE \ No newline at end of file + return 1 \ No newline at end of file diff --git a/code/modules/antagonists/abductor/equipment/gland.dm b/code/modules/antagonists/abductor/equipment/gland.dm index b9114da9ea..192bfcdf84 100644 --- a/code/modules/antagonists/abductor/equipment/gland.dm +++ b/code/modules/antagonists/abductor/equipment/gland.dm @@ -230,12 +230,12 @@ /obj/item/organ/heart/gland/trauma/activate() to_chat(owner, "You feel a spike of pain in your head.") if(prob(33)) - owner.gain_trauma_type(BRAIN_TRAUMA_SPECIAL, TRUE) + owner.gain_trauma_type(BRAIN_TRAUMA_SPECIAL, TRAUMA_RESILIENCE_LOBOTOMY) else if(prob(20)) - owner.gain_trauma_type(BRAIN_TRAUMA_SEVERE, TRUE) + owner.gain_trauma_type(BRAIN_TRAUMA_SEVERE, TRAUMA_RESILIENCE_LOBOTOMY) else - owner.gain_trauma_type(BRAIN_TRAUMA_MILD, TRUE) + owner.gain_trauma_type(BRAIN_TRAUMA_MILD, TRAUMA_RESILIENCE_LOBOTOMY) /obj/item/organ/heart/gland/spiderman cooldown_low = 450 diff --git a/code/modules/antagonists/brainwashing/brainwashing.dm b/code/modules/antagonists/brainwashing/brainwashing.dm new file mode 100644 index 0000000000..1bc14ec8b3 --- /dev/null +++ b/code/modules/antagonists/brainwashing/brainwashing.dm @@ -0,0 +1,84 @@ +/proc/brainwash(mob/living/L, directives) + if(!L.mind) + return + if(!islist(directives)) + directives = list(directives) + var/datum/mind/M = L.mind + var/datum/antagonist/brainwashed/B = M.has_antag_datum(/datum/antagonist/brainwashed) + if(B) + for(var/O in directives) + var/datum/objective/brainwashing/objective = new(O) + B.objectives += objective + M.objectives += objective + B.greet() + else + B = new() + for(var/O in directives) + var/datum/objective/brainwashing/objective = new(O) + B.objectives += objective + M.add_antag_datum(B) + + var/begin_message = "[L] has been brainwashed with the following objectives: " + var/obj_message = english_list(directives) + var/end_message = "." + var/rendered = begin_message + obj_message + end_message + deadchat_broadcast(rendered, follow_target = L, turf_target = get_turf(L), message_type=DEADCHAT_REGULAR) + +/datum/antagonist/brainwashed + name = "Brainwashed Victim" + job_rank = ROLE_BRAINWASHED + roundend_category = "brainwashed victims" + show_in_antagpanel = TRUE + antagpanel_category = "Other" + show_name_in_check_antagonists = TRUE + +/datum/antagonist/brainwashed/on_gain() + owner.objectives |= objectives + . = ..() + +/datum/antagonist/brainwashed/on_removal() + owner.objectives -= objectives + . = ..() + +/datum/antagonist/brainwashed/greet() + to_chat(owner, "Your mind reels as it begins focusing on a single purpose...") + to_chat(owner, "Follow the Directives, at any cost!") + var/i = 1 + for(var/X in objectives) + var/datum/objective/O = X + to_chat(owner, "[i]. [O.explanation_text]") + i++ + +/datum/antagonist/brainwashed/farewell() + to_chat(owner, "Your mind suddenly clears...") + to_chat(owner, "You feel the weight of the Directives disappear! You no longer have to obey them.") + owner.announce_objectives() + +/datum/antagonist/brainwashed/admin_add(datum/mind/new_owner,mob/admin) + var/mob/living/carbon/C = new_owner.current + if(!istype(C)) + return + var/list/objectives = list() + do + var/objective = stripped_input(admin, "Add an objective, or leave empty to finish.", "Brainwashing", null, MAX_MESSAGE_LEN) + if(objective) + objectives += objective + while(alert(admin,"Add another objective?","More Brainwashing","Yes","No") == "Yes") + + if(alert(admin,"Confirm Brainwashing?","Are you sure?","Yes","No") == "No") + return + + if(!LAZYLEN(objectives)) + return + + if(QDELETED(C)) + to_chat(admin, "Mob doesn't exist anymore") + return + + brainwash(C, objectives) + var/obj_list = english_list(objectives) + message_admins("[key_name_admin(admin)] has brainwashed [key_name_admin(C)] with the following objectives: [obj_list].") + log_admin("[key_name(admin)] has brainwashed [key_name(C)] with the following objectives: [obj_list].") + +/datum/objective/brainwashing + completed = TRUE diff --git a/code/modules/jobs/job_types/civilian.dm b/code/modules/jobs/job_types/civilian.dm index 67bc2143f8..9a2030d7ed 100644 --- a/code/modules/jobs/job_types/civilian.dm +++ b/code/modules/jobs/job_types/civilian.dm @@ -152,7 +152,7 @@ Curator return H.grant_all_languages(omnitongue=TRUE) - H.gain_trauma(/datum/brain_trauma/mild/phobia, FALSE, "snakes") //why does it have to be snakes... + H.gain_trauma(/datum/brain_trauma/mild/phobia, TRAUMA_RESILIENCE_SURGERY, "snakes") //why does it have to be snakes... /* Lawyer */ diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm index f6fbbaab4b..dd8c84c969 100644 --- a/code/modules/mob/living/blood.dm +++ b/code/modules/mob/living/blood.dm @@ -98,6 +98,7 @@ add_splatter_floor(src.loc, 1) /mob/living/carbon/human/bleed(amt) + amt *= physiology.bleed_mod if(!(NOBLOOD in dna.species.species_traits)) ..() diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm index ad58d2fa8e..ac2f8ae58e 100644 --- a/code/modules/mob/living/brain/brain_item.dm +++ b/code/modules/mob/living/brain/brain_item.dm @@ -179,27 +179,28 @@ ////////////////////////////////////TRAUMAS//////////////////////////////////////// -/obj/item/organ/brain/proc/has_trauma_type(brain_trauma_type, consider_permanent = FALSE) +/obj/item/organ/brain/proc/has_trauma_type(brain_trauma_type, resilience = TRAUMA_RESILIENCE_ABSOLUTE) for(var/X in traumas) var/datum/brain_trauma/BT = X - if(istype(BT, brain_trauma_type) && (consider_permanent || !BT.permanent)) + if(istype(BT, brain_trauma_type) && (BT.resilience <= resilience)) return BT //Add a specific trauma -/obj/item/organ/brain/proc/gain_trauma(datum/brain_trauma/trauma, permanent = FALSE, list/arguments) +/obj/item/organ/brain/proc/gain_trauma(datum/brain_trauma/trauma, resilience, list/arguments) var/trauma_type if(ispath(trauma)) trauma_type = trauma SSblackbox.record_feedback("tally", "traumas", 1, trauma_type) - traumas += new trauma_type(arglist(list(src, permanent) + arguments)) + traumas += new trauma_type(arglist(list(src, resilience) + arguments)) else SSblackbox.record_feedback("tally", "traumas", 1, trauma.type) traumas += trauma - trauma.permanent = permanent + if(resilience) + trauma.resilience = resilience //Add a random trauma of a certain subtype -/obj/item/organ/brain/proc/gain_trauma_type(brain_trauma_type = /datum/brain_trauma, permanent = FALSE) +/obj/item/organ/brain/proc/gain_trauma_type(brain_trauma_type = /datum/brain_trauma, resilience) var/list/datum/brain_trauma/possible_traumas = list() for(var/T in subtypesof(brain_trauma_type)) var/datum/brain_trauma/BT = T @@ -208,16 +209,16 @@ var/trauma_type = pick(possible_traumas) SSblackbox.record_feedback("tally", "traumas", 1, trauma_type) - traumas += new trauma_type(src, permanent) + traumas += new trauma_type(src, resilience) -//Cure a random trauma of a certain subtype -/obj/item/organ/brain/proc/cure_trauma_type(brain_trauma_type, cure_permanent = FALSE) - var/datum/brain_trauma/trauma = has_trauma_type(brain_trauma_type) - if(trauma && (cure_permanent || !trauma.permanent)) +//Cure a random trauma of a certain resilience level +/obj/item/organ/brain/proc/cure_trauma_type(resilience = TRAUMA_RESILIENCE_BASIC) + var/datum/brain_trauma/trauma = has_trauma_type(resilience) + if(trauma) qdel(trauma) -/obj/item/organ/brain/proc/cure_all_traumas(cure_permanent = FALSE) +/obj/item/organ/brain/proc/cure_all_traumas(resilience = TRAUMA_RESILIENCE_BASIC) for(var/X in traumas) var/datum/brain_trauma/trauma = X - if(cure_permanent || !trauma.permanent) + if(trauma.resilience <= resilience) qdel(trauma) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index fee97c1d01..c38799e9b4 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -746,16 +746,16 @@ update_inv_handcuffed() update_hud_handcuffed() -/mob/living/carbon/fully_heal(admin_revive = 0) +/mob/living/carbon/fully_heal(admin_revive = FALSE) if(reagents) reagents.clear_reagents() var/obj/item/organ/brain/B = getorgan(/obj/item/organ/brain) if(B) - B.damaged_brain = 0 + B.damaged_brain = FALSE for(var/thing in viruses) var/datum/disease/D = thing if(D.severity != VIRUS_SEVERITY_POSITIVE) - D.cure(0) + D.cure(FALSE) if(admin_revive) regenerate_limbs() regenerate_organs() @@ -765,7 +765,7 @@ update_handcuffed() if(reagents) reagents.addiction_list = list() - cure_all_traumas(TRUE, TRUE) + cure_all_traumas(TRUE, TRAUMA_RESILIENCE_MAGIC) ..() // heal ears after healing traits, since ears check TRAIT_DEAF trait // when healing. diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 81f64d1d26..56420df35a 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -121,9 +121,9 @@ ContactContractDisease(D) if(lying && surgeries.len) - if(user.a_intent == INTENT_HELP) + if(user.a_intent == INTENT_HELP || user.a_intent == INTENT_DISARM) for(var/datum/surgery/S in surgeries) - if(S.next_step(user)) + if(S.next_step(user, user.a_intent)) return 1 return 0 diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index d59c3cfba2..7ff6c5a13f 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -22,6 +22,7 @@ //initialise organs create_internal_organs() //most of it is done in set_species now, this is only for parent call + physiology = new() handcrafting = new() @@ -29,6 +30,10 @@ AddComponent(/datum/component/redirect, list(COMSIG_COMPONENT_CLEAN_ACT), CALLBACK(src, .proc/clean_blood)) +/mob/living/carbon/human/Destroy() + QDEL_NULL(physiology) + return ..() + /mob/living/carbon/human/OpenCraftingMenu() handcrafting.ui_interact(src) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 918b66c6c5..e6fbfe7be9 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -29,6 +29,7 @@ var/obj/item/clothing/C = bp if(C.body_parts_covered & def_zone.body_part) protection += C.armor.getRating(d_type) + protection += physiology.armor.getRating(d_type) return protection /mob/living/carbon/human/on_hit(obj/item/projectile/P) @@ -458,6 +459,7 @@ heart.beating = TRUE if(stat == CONSCIOUS) to_chat(src, "You feel your heart beating again!") + siemens_coeff *= physiology.siemens_coeff . = ..(shock_damage,source,siemens_coeff,safety,override,tesla_shock, illusion, stun) if(.) electrocution_animation(40) diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 7c4d12aaa1..2bc4de894e 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -45,6 +45,9 @@ var/drunkenness = 0 //Overall drunkenness - check handle_alcohol() in life.dm for effects var/datum/personal_crafting/handcrafting + var/datum/physiology/physiology + + var/list/datum/bioware = list() var/creamed = FALSE //to use with creampie overlays var/static/list/can_ride_typecache = typecacheof(list(/mob/living/carbon/human, /mob/living/simple_animal/slime, /mob/living/simple_animal/parrot)) diff --git a/code/modules/mob/living/carbon/human/physiology.dm b/code/modules/mob/living/carbon/human/physiology.dm new file mode 100644 index 0000000000..3d1cae8f41 --- /dev/null +++ b/code/modules/mob/living/carbon/human/physiology.dm @@ -0,0 +1,27 @@ +//Stores several modifiers in a way that isn't cleared by changing species + +/datum/physiology + var/brute_mod = 1 // % of brute damage taken from all sources + var/burn_mod = 1 // % of burn damage taken from all sources + var/tox_mod = 1 // % of toxin damage taken from all sources + var/oxy_mod = 1 // % of oxygen damage taken from all sources + var/clone_mod = 1 // % of clone damage taken from all sources + var/stamina_mod = 1 // % of stamina damage taken from all sources + var/brain_mod = 1 // % of brain damage taken from all sources + + var/pressure_mod = 1// % of brute damage taken from low or high pressure (stacks with brute_mod) + var/heat_mod = 1 // % of burn damage taken from heat (stacks with burn_mod) + var/cold_mod = 1 // % of burn damage taken from cold (stacks with burn_mod) + + var/damage_resistance = 0 // %damage reduction from all sources + + var/siemens_coeff = 1 // resistance to shocks + + var/stun_mod = 1 // % stun modifier + var/bleed_mod = 1 // % bleeding modifier + var/datum/armor/armor // internal armor datum + + var/speed_mod = 0 //tick modifier for each step. Positive is slower, negative is faster. + +/datum/physiology/New() + armor = new diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index f4822a066e..21c24eac9b 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -1213,19 +1213,20 @@ GLOBAL_LIST_EMPTY(roundstart_races) if(H.movement_type & FLYING) flight = 1 - if(!flightpack) //Check for chemicals and innate speedups and slowdowns if we're moving using our body and not a flying suit + if(H.has_gravity()) + gravity = TRUE + + if(!flightpack && gravity) //Check for chemicals and innate speedups and slowdowns if we're moving using our body and not a flying suit if(H.has_trait(TRAIT_GOTTAGOFAST)) . -= 1 if(H.has_trait(TRAIT_GOTTAGOREALLYFAST)) . -= 2 . += speedmod + . += H.physiology.speed_mod if(H.has_trait(TRAIT_IGNORESLOWDOWN)) ignoreslow = 1 - if(H.has_gravity()) - gravity = 1 - if(!gravity) var/obj/item/tank/jetpack/J = H.back var/obj/item/clothing/suit/space/hardsuit/C = H.wear_suit @@ -1551,6 +1552,7 @@ GLOBAL_LIST_EMPTY(roundstart_races) /datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H) var/hit_percent = (100-(blocked+armor))/100 + hit_percent = (hit_percent * (100-H.physiology.damage_resistance))/100 if(!damage || hit_percent <= 0) return 0 @@ -1568,27 +1570,27 @@ GLOBAL_LIST_EMPTY(roundstart_races) if(BRUTE) H.damageoverlaytemp = 20 if(BP) - if(BP.receive_damage(damage * hit_percent * brutemod, 0)) + if(BP.receive_damage(damage * hit_percent * brutemod * H.physiology.brute_mod, 0)) H.update_damage_overlays() else//no bodypart, we deal damage with a more general method. - H.adjustBruteLoss(damage * hit_percent * brutemod) + H.adjustBruteLoss(damage * hit_percent * brutemod * H.physiology.brute_mod) if(BURN) H.damageoverlaytemp = 20 if(BP) - if(BP.receive_damage(0, damage * hit_percent * burnmod)) + if(BP.receive_damage(0, damage * hit_percent * burnmod * H.physiology.burn_mod)) H.update_damage_overlays() else - H.adjustFireLoss(damage * hit_percent* burnmod) + H.adjustFireLoss(damage * hit_percent * burnmod * H.physiology.burn_mod) if(TOX) - H.adjustToxLoss(damage * hit_percent) + H.adjustToxLoss(damage * hit_percent * H.physiology.tox_mod) if(OXY) - H.adjustOxyLoss(damage * hit_percent) + H.adjustOxyLoss(damage * hit_percent * H.physiology.oxy_mod) if(CLONE) - H.adjustCloneLoss(damage * hit_percent) + H.adjustCloneLoss(damage * hit_percent * H.physiology.clone_mod) if(STAMINA) - H.adjustStaminaLoss(damage * hit_percent) + H.adjustStaminaLoss(damage * hit_percent * H.physiology.stamina_mod) if(BRAIN) - H.adjustBrainLoss(damage * hit_percent) + H.adjustBrainLoss(damage * hit_percent * H.physiology.brain_mod) return 1 /datum/species/proc/on_hit(obj/item/projectile/P, mob/living/carbon/human/H) @@ -1656,7 +1658,7 @@ GLOBAL_LIST_EMPTY(roundstart_races) burn_damage = HEAT_DAMAGE_LEVEL_3 else burn_damage = HEAT_DAMAGE_LEVEL_2 - burn_damage *= heatmod + burn_damage = burn_damage * heatmod * H.physiology.heat_mod if (H.stat < UNCONSCIOUS && (prob(burn_damage) * 10) / 4) //40% for level 3 damage on humans H.emote("scream") H.apply_damage(burn_damage, BURN) @@ -1664,13 +1666,13 @@ GLOBAL_LIST_EMPTY(roundstart_races) switch(H.bodytemperature) if(200 to BODYTEMP_COLD_DAMAGE_LIMIT) H.throw_alert("temp", /obj/screen/alert/cold, 1) - H.apply_damage(COLD_DAMAGE_LEVEL_1*coldmod, BURN) + H.apply_damage(COLD_DAMAGE_LEVEL_1*coldmod*H.physiology.cold_mod, BURN) if(120 to 200) H.throw_alert("temp", /obj/screen/alert/cold, 2) - H.apply_damage(COLD_DAMAGE_LEVEL_2*coldmod, BURN) + H.apply_damage(COLD_DAMAGE_LEVEL_2*coldmod*H.physiology.cold_mod, BURN) else H.throw_alert("temp", /obj/screen/alert/cold, 3) - H.apply_damage(COLD_DAMAGE_LEVEL_3*coldmod, BURN) + H.apply_damage(COLD_DAMAGE_LEVEL_3*coldmod*H.physiology.cold_mod, BURN) else H.clear_alert("temp") @@ -1680,7 +1682,7 @@ GLOBAL_LIST_EMPTY(roundstart_races) switch(adjusted_pressure) if(HAZARD_HIGH_PRESSURE to INFINITY) if(!(RESISTPRESSURE in species_traits)) - H.adjustBruteLoss( min( ( (adjusted_pressure / HAZARD_HIGH_PRESSURE) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE) ) + H.adjustBruteLoss(min(((adjusted_pressure / HAZARD_HIGH_PRESSURE) -1 ) * PRESSURE_DAMAGE_COEFFICIENT, MAX_HIGH_PRESSURE_DAMAGE) * H.physiology.pressure_mod) H.throw_alert("pressure", /obj/screen/alert/highpressure, 2) else H.clear_alert("pressure") @@ -1694,7 +1696,7 @@ GLOBAL_LIST_EMPTY(roundstart_races) if(H.dna.check_mutation(COLDRES) || (RESISTPRESSURE in species_traits)) H.clear_alert("pressure") else - H.adjustBruteLoss( LOW_PRESSURE_DAMAGE ) + H.adjustBruteLoss(LOW_PRESSURE_DAMAGE * H.physiology.pressure_mod) H.throw_alert("pressure", /obj/screen/alert/lowpressure, 2) ////////// @@ -1782,7 +1784,7 @@ GLOBAL_LIST_EMPTY(roundstart_races) //////////// /datum/species/proc/spec_stun(mob/living/carbon/human/H,amount) - . = stunmod * amount + . = stunmod * H.physiology.stun_mod * amount ////////////// //Space Move// diff --git a/code/modules/mob/living/carbon/status_procs.dm b/code/modules/mob/living/carbon/status_procs.dm index 300455a174..eccdd5d2cf 100644 --- a/code/modules/mob/living/carbon/status_procs.dm +++ b/code/modules/mob/living/carbon/status_procs.dm @@ -73,28 +73,28 @@ if(B) . = B.traumas -/mob/living/carbon/proc/has_trauma_type(brain_trauma_type, consider_permanent = FALSE) +/mob/living/carbon/proc/has_trauma_type(brain_trauma_type, resilience) var/obj/item/organ/brain/B = getorganslot(ORGAN_SLOT_BRAIN) if(B) - . = B.has_trauma_type(brain_trauma_type, consider_permanent) + . = B.has_trauma_type(brain_trauma_type, resilience) -/mob/living/carbon/proc/gain_trauma(datum/brain_trauma/trauma, permanent = FALSE, list/arguments) +/mob/living/carbon/proc/gain_trauma(datum/brain_trauma/trauma, resilience, list/arguments) var/obj/item/organ/brain/B = getorganslot(ORGAN_SLOT_BRAIN) if(B) - . = B.gain_trauma(trauma, permanent, arguments) + . = B.gain_trauma(trauma, resilience, arguments) -/mob/living/carbon/proc/gain_trauma_type(brain_trauma_type = /datum/brain_trauma, permanent = FALSE) +/mob/living/carbon/proc/gain_trauma_type(brain_trauma_type = /datum/brain_trauma, resilience) var/obj/item/organ/brain/B = getorganslot(ORGAN_SLOT_BRAIN) if(B) - . = B.gain_trauma_type(brain_trauma_type, permanent) + . = B.gain_trauma_type(brain_trauma_type, resilience) -/mob/living/carbon/proc/cure_trauma_type(brain_trauma_type, cure_permanent = FALSE) +/mob/living/carbon/proc/cure_trauma_type(resilience) var/obj/item/organ/brain/B = getorganslot(ORGAN_SLOT_BRAIN) if(B) - . = B.cure_trauma_type(brain_trauma_type, cure_permanent) + . = B.cure_trauma_type(resilience) -/mob/living/carbon/proc/cure_all_traumas(cure_permanent = FALSE) +/mob/living/carbon/proc/cure_all_traumas(resilience) var/obj/item/organ/brain/B = getorganslot(ORGAN_SLOT_BRAIN) if(B) - . = B.cure_all_traumas(cure_permanent) + . = B.cure_all_traumas(resilience) diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 01c1bb6815..64454b130e 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -78,9 +78,6 @@ O.setBrainLoss(getBrainLoss(), 0) O.updatehealth() O.radiation = radiation - for(var/T in get_traumas()) - var/datum/brain_trauma/BT = T - O.gain_trauma(BT.type, BT.permanent) //re-add implants to new mob if (tr_flags & TR_KEEPIMPLANTS) @@ -238,9 +235,6 @@ O.setBrainLoss(getBrainLoss(), 0) O.updatehealth() O.radiation = radiation - for(var/T in get_traumas()) - var/datum/brain_trauma/BT = T - O.gain_trauma(BT.type, BT.permanent) //re-add implants to new mob if (tr_flags & TR_KEEPIMPLANTS) diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index ee25eed30d..dabbec25a8 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -59,7 +59,7 @@ M.confused = 0 M.SetSleeping(0, 0) M.jitteriness = 0 - M.cure_all_traumas(TRUE, TRUE) + M.cure_all_traumas(TRUE, TRAUMA_RESILIENCE_MAGIC) for(var/thing in M.viruses) var/datum/disease/D = thing if(D.severity == VIRUS_SEVERITY_POSITIVE) @@ -832,10 +832,8 @@ M.adjustBrainLoss(-2*REM) if(iscarbon(M)) var/mob/living/carbon/C = M - if(prob(30) && C.has_trauma_type(BRAIN_TRAUMA_SPECIAL)) - C.cure_trauma_type(BRAIN_TRAUMA_SPECIAL) - if(prob(10) && C.has_trauma_type(BRAIN_TRAUMA_MILD)) - C.cure_trauma_type(BRAIN_TRAUMA_MILD) + if(prob(10)) + C.cure_trauma_type(TRAUMA_RESILIENCE_BASIC) ..() /datum/reagent/medicine/mutadone diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index c3f0df7b14..9f287c6ee2 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -457,3 +457,103 @@ build_path = /obj/item/organ/lungs/cybernetic/upgraded category = list("Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL + +/datum/design/surgery_lobotomy + name = "Lobotomy Surgery Disk" + desc = "A disk containing the instructions for a Lobotomy surgery." + id = "surgery_lobotomy" + build_type = PROTOLATHE + materials = list(MAT_METAL = 300, MAT_GLASS = 100) + build_path = /obj/item/disk/surgery/lobotomy + category = list("Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/surgery_pacify + name = "Pacification Surgery Disk" + desc = "A disk containing the instructions for a Pacification surgery." + id = "surgery_pacify" + build_type = PROTOLATHE + materials = list(MAT_METAL = 300, MAT_GLASS = 100) + build_path = /obj/item/disk/surgery/pacification + category = list("Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/surgery_viral_bonding + name = "Viral Bonding Surgery Disk" + desc = "A disk containing the instructions for a Viral Bonding surgery." + id = "surgery_viral_bond" + build_type = PROTOLATHE + materials = list(MAT_METAL = 300, MAT_GLASS = 100) + build_path = /obj/item/disk/surgery/viral_bonding + category = list("Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/surgery_reconstruction + name = "Reconstruction Surgery Disk" + desc = "A disk containing the instructions for a Reconstruction surgery." + id = "surgery_reconstruction" + build_type = PROTOLATHE + materials = list(MAT_METAL = 300, MAT_GLASS = 100) + build_path = /obj/item/disk/surgery/reconstruction + category = list("Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/surgery_revival + name = "Revival Surgery Disk" + desc = "A disk containing the instructions for a Revival surgery." + id = "surgery_revival" + build_type = PROTOLATHE + materials = list(MAT_METAL = 300, MAT_GLASS = 100) + build_path = /obj/item/disk/surgery/revival + category = list("Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/surgery_brainwashing + name = "Brainwashing Surgery Disk" + desc = "A disk containing the instructions for a Brainwashing surgery." + id = "surgery_brainwashing" + build_type = PROTOLATHE + materials = list(MAT_METAL = 300, MAT_GLASS = 100) + build_path = /obj/item/disk/surgery/brainwashing + category = list("Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/surgery_nerve_splicing + name = "Nerve Splicing Surgery Disk" + desc = "A disk containing the instructions for a Nerve Splicing surgery." + id = "surgery_nerve_splice" + build_type = PROTOLATHE + materials = list(MAT_METAL = 300, MAT_GLASS = 100) + build_path = /obj/item/disk/surgery/nerve_splicing + category = list("Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/surgery_nerve_grounding + name = "Nerve Grounding Surgery Disk" + desc = "A disk containing the instructions for a Nerve Grounding surgery." + id = "surgery_nerve_ground" + build_type = PROTOLATHE + materials = list(MAT_METAL = 300, MAT_GLASS = 100) + build_path = /obj/item/disk/surgery/nerve_grounding + category = list("Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/surgery_vein_threading + name = "Vein Threading Surgery Disk" + desc = "A disk containing the instructions for a Vein Threading surgery." + id = "surgery_vein_thread" + build_type = PROTOLATHE + materials = list(MAT_METAL = 300, MAT_GLASS = 100) + build_path = /obj/item/disk/surgery/vein_threading + category = list("Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/surgery_necrotic_revival + name = "Necrotic Revival Surgery Disk" + desc = "A disk containing the instructions for a Necrotic Revival surgery." + id = "surgery_zombie" + build_type = PROTOLATHE + materials = list(MAT_METAL = 300, MAT_GLASS = 100) + build_path = /obj/item/disk/surgery/necrotic_revival + category = list("Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE \ No newline at end of file diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 4b5a231439..2842068c66 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -39,6 +39,34 @@ research_cost = 2500 export_price = 5000 +/////////////////////////Advanced Surgery///////////////////////// +/datum/techweb_node/adv_surgery + id = "adv_surgery" + display_name = "Advanced Surgery" + description = "When simple medicine doesn't cut it." + prereq_ids = list("adv_biotech") + design_ids = list("surgery_lobotomy", "surgery_reconstruction") + research_cost = 2500 + export_price = 5000 + +/datum/techweb_node/exp_surgery + id = "exp_surgery" + 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_viral_bond") + research_cost = 5000 + export_price = 5000 + +/datum/techweb_node/alien_surgery + id = "alien_surgery" + display_name = "Alien Surgery" + description = "Abductors did nothing wrong." + prereq_ids = list("exp_surgery", "alientech") + design_ids = list("surgery_brainwashing","surgery_zombie") + research_cost = 10000 + export_price = 5000 + /////////////////////////data theory tech///////////////////////// /datum/techweb_node/datatheory //Computer science id = "datatheory" diff --git a/code/modules/surgery/advanced/bioware/bioware.dm b/code/modules/surgery/advanced/bioware/bioware.dm new file mode 100644 index 0000000000..6c0a7529d0 --- /dev/null +++ b/code/modules/surgery/advanced/bioware/bioware.dm @@ -0,0 +1,30 @@ +//Bioware +//Body modifications applied through surgery. They generally affect physiology. + +/datum/bioware + var/name = "Generic Bioware" + var/mob/living/carbon/human/owner + var/desc = "If you see this something's wrong, warn a coder." + var/active = FALSE + var/mod_type = BIOWARE_GENERIC + +/datum/bioware/New(mob/living/carbon/human/_owner) + owner = _owner + for(var/X in owner.bioware) + var/datum/bioware/B = X + if(B.mod_type == mod_type) + qdel(src) + return + on_gain() + +/datum/bioware/Destroy() + owner = null + if(active) + on_lose() + return ..() + +/datum/bioware/proc/on_gain() + active = TRUE + +/datum/bioware/proc/on_lose() + return \ No newline at end of file diff --git a/code/modules/surgery/advanced/bioware/bioware_surgery.dm b/code/modules/surgery/advanced/bioware/bioware_surgery.dm new file mode 100644 index 0000000000..86817b9b09 --- /dev/null +++ b/code/modules/surgery/advanced/bioware/bioware_surgery.dm @@ -0,0 +1,12 @@ +/datum/surgery/advanced/bioware + name = "enhancement surgery" + var/bioware_target = BIOWARE_GENERIC + +/datum/surgery/advanced/bioware/can_start(mob/user, mob/living/carbon/human/target) + if(!..()) + return FALSE + for(var/X in target.bioware) + var/datum/bioware/B = X + if(B.mod_type == bioware_target) + return FALSE + return TRUE \ No newline at end of file diff --git a/code/modules/surgery/advanced/bioware/nerve_grounding.dm b/code/modules/surgery/advanced/bioware/nerve_grounding.dm new file mode 100644 index 0000000000..dd2be71026 --- /dev/null +++ b/code/modules/surgery/advanced/bioware/nerve_grounding.dm @@ -0,0 +1,43 @@ +/obj/item/disk/surgery/nerve_grounding + desc = "The disk provides instructions on how to reroute the nervous system to ground electric shocks." + surgeries = list(/datum/surgery/advanced/bioware/nerve_grounding) + +/datum/surgery/advanced/bioware/nerve_grounding + name = "nerve grounding" + steps = list(/datum/surgery_step/incise, + /datum/surgery_step/retract_skin, + /datum/surgery_step/clamp_bleeders, + /datum/surgery_step/incise, + /datum/surgery_step/incise, + /datum/surgery_step/ground_nerves, + /datum/surgery_step/close) + possible_locs = list("chest") + bioware_target = BIOWARE_NERVES + +/datum/surgery_step/ground_nerves + name = "ground nerves" + accept_hand = TRUE + time = 155 + +/datum/surgery_step/ground_nerves/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] starts splicing together [target]'s nerves.", "You start splicing together [target]'s nerves.") + +/datum/surgery_step/ground_nerves/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] successfully splices [target]'s nervous system!", "You successfully splice [target]'s nervous system!") + new /datum/bioware/grounded_nerves(target) + return TRUE + +/datum/bioware/grounded_nerves + name = "Grounded Nerves" + desc = "Nerves form a safe path for electricity to traverse, protecting the body from electric shocks." + mod_type = "nerves" + var/prev_coeff + +/datum/bioware/grounded_nerves/on_gain() + ..() + prev_coeff = owner.physiology.siemens_coeff + owner.physiology.siemens_coeff = 0 + +/datum/bioware/grounded_nerves/on_lose() + ..() + owner.physiology.siemens_coeff = prev_coeff \ No newline at end of file diff --git a/code/modules/surgery/advanced/bioware/nerve_splicing.dm b/code/modules/surgery/advanced/bioware/nerve_splicing.dm new file mode 100644 index 0000000000..8579f9b107 --- /dev/null +++ b/code/modules/surgery/advanced/bioware/nerve_splicing.dm @@ -0,0 +1,41 @@ +/obj/item/disk/surgery/nerve_splicing + desc = "The disk provides instructions on how to splice the circulatory system to counter stuns and paralysis." + surgeries = list(/datum/surgery/advanced/bioware/nerve_splicing) + +/datum/surgery/advanced/bioware/nerve_splicing + name = "nerve splicing" + steps = list(/datum/surgery_step/incise, + /datum/surgery_step/retract_skin, + /datum/surgery_step/clamp_bleeders, + /datum/surgery_step/incise, + /datum/surgery_step/incise, + /datum/surgery_step/splice_nerves, + /datum/surgery_step/close) + possible_locs = list("chest") + bioware_target = BIOWARE_NERVES + +/datum/surgery_step/splice_nerves + name = "splice nerves" + accept_hand = TRUE + time = 155 + +/datum/surgery_step/splice_nerves/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] starts splicing together [target]'s nerves.", "You start splicing together [target]'s nerves.") + +/datum/surgery_step/splice_nerves/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] successfully splices [target]'s nervous system!", "You successfully splice [target]'s nervous system!") + new /datum/bioware/spliced_nerves(target) + return TRUE + +/datum/bioware/spliced_nerves + name = "Spliced Nerves" + desc = "Nerves are connected to each other multiple times, greatly reducing the impact of stunning effects." + mod_type = "nerves" + +/datum/bioware/spliced_nerves/on_gain() + ..() + owner.physiology.stun_mod *= 0.5 + +/datum/bioware/spliced_nerves/on_lose() + ..() + owner.physiology.stun_mod *= 2 \ No newline at end of file diff --git a/code/modules/surgery/advanced/bioware/vein_threading.dm b/code/modules/surgery/advanced/bioware/vein_threading.dm new file mode 100644 index 0000000000..082b87109e --- /dev/null +++ b/code/modules/surgery/advanced/bioware/vein_threading.dm @@ -0,0 +1,41 @@ +/obj/item/disk/surgery/vein_threading + desc = "The disk provides instructions on how to modify the circulatory system to greatly slow down bleeding." + surgeries = list(/datum/surgery/advanced/bioware/vein_threading) + +/datum/surgery/advanced/bioware/vein_threading + name = "vein threading" + steps = list(/datum/surgery_step/incise, + /datum/surgery_step/retract_skin, + /datum/surgery_step/clamp_bleeders, + /datum/surgery_step/incise, + /datum/surgery_step/incise, + /datum/surgery_step/thread_veins, + /datum/surgery_step/close) + possible_locs = list("chest") + bioware_target = BIOWARE_CIRCULATION + +/datum/surgery_step/thread_veins + name = "thread veins" + accept_hand = TRUE + time = 125 + +/datum/surgery_step/thread_veins/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] starts weaving [target]'s circulatory system.", "You start weaving [target]'s circulatory system.") + +/datum/surgery_step/thread_veins/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] weaves [target]'s circulatory system into a resistant mesh!", "You weave [target]'s circulatory system into a resistant mesh!") + new /datum/bioware/threaded_veins(target) + return TRUE + +/datum/bioware/threaded_veins + name = "Threaded Veins" + desc = "The circulatory system is woven into a mesh, severely reducing the amount of blood lost from wounds." + mod_type = "circulation" + +/datum/bioware/threaded_veins/on_gain() + ..() + owner.physiology.bleed_mod *= 0.25 + +/datum/bioware/threaded_veins/on_lose() + ..() + owner.physiology.bleed_mod *= 4 \ No newline at end of file diff --git a/code/modules/surgery/advanced/brainwashing.dm b/code/modules/surgery/advanced/brainwashing.dm new file mode 100644 index 0000000000..bc397b7c66 --- /dev/null +++ b/code/modules/surgery/advanced/brainwashing.dm @@ -0,0 +1,58 @@ +/obj/item/disk/surgery/brainwashing + desc = "The disk provides instructions on how to impress an order on a brain, making it the primary objective of the patient." + surgeries = list(/datum/surgery/advanced/brainwashing) + +/datum/surgery/advanced/brainwashing + name = "brainwashing" + steps = list( + /datum/surgery_step/incise, + /datum/surgery_step/retract_skin, + /datum/surgery_step/saw, + /datum/surgery_step/clamp_bleeders, + /datum/surgery_step/brainwash, + /datum/surgery_step/close) + + species = list(/mob/living/carbon/human) + possible_locs = list("head") + +/datum/surgery/advanced/brainwashing/can_start(mob/user, mob/living/carbon/target) + if(!..()) + return FALSE + var/obj/item/organ/brain/B = target.getorganslot(ORGAN_SLOT_BRAIN) + if(!B) + return FALSE + return TRUE + +/datum/surgery_step/brainwash + name = "brainwash" + implements = list(/obj/item/hemostat = 85, /obj/item/wirecutters = 50, /obj/item/stack/packageWrap = 35, /obj/item/stack/cable_coil = 15) + time = 200 + var/objective + +/datum/surgery_step/brainwash/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + objective = stripped_input(user, "Choose the objective to imprint on your victim's brain.", "Brainwashing", null, MAX_MESSAGE_LEN) + if(!objective) + return -1 + user.visible_message("[user] begins to tinker with [target]'s brain.", "You begin to brainwash [target]...") + +/datum/surgery_step/brainwash/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + if(!target.mind) + user.visible_message("[target] doesn't respond to the brainwashing, as if [target.p_they()] lacked a mind...") + return FALSE + if(target.isloyal()) + user.visible_message("You hear a faint buzzing from a device inside [target]'s brain, and the brainwashing is erased.") + return FALSE + user.visible_message("[user] successfully brainwashes [target]!", "You succeed in brainwashing [target].") + to_chat(target, "A new compulsion fills your mind... you feel forced to obey it!") + brainwash(target, objective) + message_admins("[key_name_admin(user)] surgically brainwashed [key_name_admin(target)] with the objective '[objective]'.") + log_game("[key_name(user)] surgically brainwashed [key_name(target)] with the objective '[objective]'.") + return TRUE + +/datum/surgery_step/brainwash/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + if(target.getorganslot(ORGAN_SLOT_BRAIN)) + user.visible_message("[user] damages some brain tissue!", "You bruise some brain tissue!") + target.adjustBrainLoss(40) + else + user.visible_message("[user] suddenly notices that the brain [user.p_they()] [user.p_were()] working on is not there anymore.", "You suddenly notice that the brain you were working on is not there anymore.") + return FALSE \ No newline at end of file diff --git a/code/modules/surgery/advanced/lobotomy.dm b/code/modules/surgery/advanced/lobotomy.dm new file mode 100644 index 0000000000..1e2db03e09 --- /dev/null +++ b/code/modules/surgery/advanced/lobotomy.dm @@ -0,0 +1,68 @@ +/obj/item/disk/surgery/lobotomy + desc = "The disk provides instructions on how to perform a lobotomy, to cure the most resilient brain ailments." + surgeries = list(/datum/surgery/advanced/lobotomy) + +/datum/surgery/advanced/lobotomy + name = "lobotomy" + steps = list( + /datum/surgery_step/incise, + /datum/surgery_step/retract_skin, + /datum/surgery_step/saw, + /datum/surgery_step/clamp_bleeders, + /datum/surgery_step/lobotomize, + /datum/surgery_step/close) + + species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + possible_locs = list("head") + requires_bodypart_type = 0 + +/datum/surgery/advanced/lobotomy/can_start(mob/user, mob/living/carbon/target) + if(!..()) + return FALSE + var/obj/item/organ/brain/B = target.getorganslot(ORGAN_SLOT_BRAIN) + if(!B) + return FALSE + return TRUE + +/datum/surgery_step/lobotomize + name = "perform lobotomy" + implements = list(/obj/item/scalpel = 85, /obj/item/melee/transforming/energy/sword = 55, /obj/item/kitchen/knife = 35, + /obj/item/shard = 25, /obj/item = 20) + time = 100 + +/datum/surgery_step/lobotomize/tool_check(mob/user, obj/item/tool) + if(implement_type == /obj/item && !tool.is_sharp()) + return FALSE + return TRUE + +/datum/surgery_step/lobotomize/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] begins to cut a piece of [target]'s brain.", "You begin to cut a piece of [target]'s brain...") + +/datum/surgery_step/lobotomize/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] successfully lobotomizes [target]!", "You succeed in lobotomizing [target].") + target.cure_all_traumas(TRAUMA_RESILIENCE_LOBOTOMY) + if(target.mind && target.mind.has_antag_datum(/datum/antagonist/brainwashed)) + target.mind.remove_antag_datum(/datum/antagonist/brainwashed) + switch(rand(1,4))//Now let's see what hopefully-not-important part of the brain we cut off + if(1) + target.gain_trauma_type(BRAIN_TRAUMA_MILD, TRAUMA_RESILIENCE_MAGIC) + if(2) + target.gain_trauma_type(BRAIN_TRAUMA_SEVERE, TRAUMA_RESILIENCE_MAGIC) + if(3) + target.gain_trauma_type(BRAIN_TRAUMA_SPECIAL, TRAUMA_RESILIENCE_MAGIC) + return TRUE + +/datum/surgery_step/lobotomize/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + if(target.getorganslot(ORGAN_SLOT_BRAIN)) + user.visible_message("[user] removes the wrong part, causing more damage!", "You remove the wrong part, causing more damage!") + target.adjustBrainLoss(80) + switch(rand(1,3)) + if(1) + target.gain_trauma_type(BRAIN_TRAUMA_MILD, TRAUMA_RESILIENCE_MAGIC) + if(2) + target.gain_trauma_type(BRAIN_TRAUMA_SEVERE, TRAUMA_RESILIENCE_MAGIC) + if(3) + target.gain_trauma_type(BRAIN_TRAUMA_SPECIAL, TRAUMA_RESILIENCE_MAGIC) + else + user.visible_message("[user] suddenly notices that the brain [user.p_they()] [user.p_were()] working on is not there anymore.", "You suddenly notice that the brain you were working on is not there anymore.") + return FALSE \ No newline at end of file diff --git a/code/modules/surgery/advanced/necrotic_revival.dm b/code/modules/surgery/advanced/necrotic_revival.dm new file mode 100644 index 0000000000..877fd40adf --- /dev/null +++ b/code/modules/surgery/advanced/necrotic_revival.dm @@ -0,0 +1,38 @@ +/obj/item/disk/surgery/necrotic_revival + desc = "The disk provides instructions on how to make bodies keep working past death." + surgeries = list(/datum/surgery/advanced/necrotic_revival) + +/datum/surgery/advanced/necrotic_revival + name = "necrotic revival" + steps = list(/datum/surgery_step/incise, + /datum/surgery_step/retract_skin, + /datum/surgery_step/saw, + /datum/surgery_step/clamp_bleeders, + /datum/surgery_step/bionecrosis, + /datum/surgery_step/close) + + possible_locs = list("head") + +/datum/surgery/advanced/necrotic_revival/can_start(mob/user, mob/living/carbon/target) + . = ..() + var/obj/item/organ/zombie_infection/ZI = target.getorganslot(ORGAN_SLOT_ZOMBIE) + if(ZI) + return FALSE + +/datum/surgery_step/bionecrosis + name = "start bionecrosis" + implements = list(/obj/item/hemostat = 100, /obj/item/screwdriver = 35, /obj/item/pen = 15) + time = 50 + +/datum/surgery_step/bionecrosis/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] begins to stimulate [target]'s brain.", "You begin to stimulate [target]'s brain...") + +/datum/surgery_step/bionecrosis/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + if(!target.reagents.has_reagent("zombiepowder", 5) && !target.reagents.has_reagent("rezadone", 5)) + user.visible_message("[target]'s brain seems unaffected.", "[target]'s body must be dosed with zombie powder or rezadone to complete the surgery!") + return FALSE + user.visible_message("[user] successfully grows a necrotic tumor on [target]'s brain!", "You succeed in growing a necrotic tumor on [target]'s brain.") + if(!target.getorganslot(ORGAN_SLOT_ZOMBIE)) + var/obj/item/organ/zombie_infection/ZI = new() + ZI.Insert(target) + return TRUE \ No newline at end of file diff --git a/code/modules/surgery/advanced/pacification.dm b/code/modules/surgery/advanced/pacification.dm new file mode 100644 index 0000000000..f692e12fce --- /dev/null +++ b/code/modules/surgery/advanced/pacification.dm @@ -0,0 +1,40 @@ +/obj/item/disk/surgery/pacification + desc = "The disk provides instructions on how to suppress violence by manipulating the patient's brain." + surgeries = list(/datum/surgery/advanced/pacify) + +/datum/surgery/advanced/pacify + name = "violence neutralization" + steps = list(/datum/surgery_step/incise, + /datum/surgery_step/retract_skin, + /datum/surgery_step/saw, + /datum/surgery_step/clamp_bleeders, + /datum/surgery_step/pacify, + /datum/surgery_step/close) + + species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + possible_locs = list("head") + requires_bodypart_type = 0 + +/datum/surgery/advanced/pacify/can_start(mob/user, mob/living/carbon/target) + . = ..() + var/obj/item/organ/brain/B = target.getorganslot(ORGAN_SLOT_BRAIN) + if(!B) + return FALSE + +/datum/surgery_step/pacify + name = "rewire brain" + implements = list(/obj/item/hemostat = 100, /obj/item/screwdriver = 35, /obj/item/pen = 15) + time = 40 + +/datum/surgery_step/pacify/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] begins to reshape [target]'s brain.", "You begin to reshape [target]'s brain...") + +/datum/surgery_step/pacify/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] reshapes [target]'s brain!", "You succeed in reshaping [target]'s brain.") + target.gain_trauma(/datum/brain_trauma/severe/pacifism, TRAUMA_RESILIENCE_LOBOTOMY) + return TRUE + +/datum/surgery_step/pacify/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] reshapes [target]'s brain!", "You screwed up, and rewired [target]'s brain the wrong way around...") + target.gain_trauma_type(BRAIN_TRAUMA_SEVERE, TRAUMA_RESILIENCE_LOBOTOMY) + return FALSE \ No newline at end of file diff --git a/code/modules/surgery/advanced/reconstruction.dm b/code/modules/surgery/advanced/reconstruction.dm new file mode 100644 index 0000000000..39758a4b98 --- /dev/null +++ b/code/modules/surgery/advanced/reconstruction.dm @@ -0,0 +1,38 @@ +/obj/item/disk/surgery/reconstruction + desc = "The disk provides instructions on how to repair a body without the use of chemicals." + surgeries = list(/datum/surgery/advanced/reconstruction) + +/datum/surgery/advanced/reconstruction + name = "body reconstruction" + steps = list(/datum/surgery_step/incise, + /datum/surgery_step/incise, + /datum/surgery_step/retract_skin, + /datum/surgery_step/incise, + /datum/surgery_step/clamp_bleeders, + /datum/surgery_step/incise, + /datum/surgery_step/retract_skin, + /datum/surgery_step/reconstruct, + /datum/surgery_step/close) + + species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + possible_locs = list("chest") + requires_bodypart_type = 0 + +/datum/surgery_step/reconstruct + name = "repair body" + implements = list(/obj/item/hemostat = 100, /obj/item/screwdriver = 35, /obj/item/pen = 15) + repeatable = TRUE + time = 25 + +/datum/surgery_step/reconstruct/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] starts knitting some of [target]'s flesh back together.", "You start knitting some of [target]'s flesh back together.") + +/datum/surgery_step/reconstruct/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] fixes some of [target]'s wounds.", "You succeed in fixing some of [target]'s wounds.") + target.heal_bodypart_damage(10,10) + return TRUE + +/datum/surgery_step/reconstruct/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] screws up!", "You screwed up!") + target.take_bodypart_damage(5,0) + return FALSE \ No newline at end of file diff --git a/code/modules/surgery/advanced/revival.dm b/code/modules/surgery/advanced/revival.dm new file mode 100644 index 0000000000..eb48968a0c --- /dev/null +++ b/code/modules/surgery/advanced/revival.dm @@ -0,0 +1,78 @@ +/obj/item/disk/surgery/revival + desc = "The disk provides instructions on how to bring a corpse back to life." + surgeries = list(/datum/surgery/advanced/revival) + +/datum/surgery/advanced/revival + name = "revival" + steps = list(/datum/surgery_step/incise, + /datum/surgery_step/retract_skin, + /datum/surgery_step/saw, + /datum/surgery_step/clamp_bleeders, + /datum/surgery_step/incise, + /datum/surgery_step/revive, + /datum/surgery_step/close) + + species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + possible_locs = list("head") + requires_bodypart_type = 0 + +/datum/surgery/advanced/revival/can_start(mob/user, mob/living/carbon/target) + if(!..()) + return FALSE + if(target.stat != DEAD) + return FALSE + if(target.suiciding || target.has_trait(TRAIT_NOCLONE) || target.hellbound) + return FALSE + var/obj/item/organ/brain/B = target.getorganslot(ORGAN_SLOT_BRAIN) + if(!B) + return FALSE + return TRUE + +/datum/surgery_step/revive + name = "repair body" + implements = list(/obj/item/twohanded/shockpaddles = 100, /obj/item/melee/baton = 75, /obj/item/gun/energy = 60) + time = 120 + +/datum/surgery_step/revive/tool_check(mob/user, obj/item/tool) + . = TRUE + if(istype(tool, /obj/item/twohanded/shockpaddles)) + var/obj/item/twohanded/shockpaddles/S = tool + if((S.req_defib && !S.defib.powered) || !S.wielded || S.cooldown || S.busy) + to_chat(user, "You need to wield both paddles, and [S.defib] must be powered!") + return FALSE + if(istype(tool, /obj/item/melee/baton)) + var/obj/item/melee/baton/B = tool + if(!B.status) + to_chat(user, "[B] needs to be active!") + return FALSE + if(istype(tool, /obj/item/gun/energy)) + var/obj/item/gun/energy/E = tool + if(E.chambered && istype(E.chambered, /obj/item/ammo_casing/energy/electrode)) + return TRUE + else + to_chat(user, "You need an electrode for this!") + return FALSE + +/datum/surgery_step/revive/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] prepares to shock [target]'s brain with [tool].", "You prepare to give [target]'s brain the spark of life with [tool].") + target.notify_ghost_cloning("Someone is trying to zap your brain. Re-enter your corpse if you want to be revived!", source = target) + +/datum/surgery_step/revive/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] send a powerful shock to [target]'s brain with [tool]...", "You successfully shock [target]'s brain with [tool]...") + playsound(get_turf(target), 'sound/magic/lightningbolt.ogg', 50, 1) + target.adjustOxyLoss(-50, 0) + target.updatehealth() + if(target.revive()) + user.visible_message("...[target] wakes up, alive and aware!", "IT'S ALIVE!") + target.emote("gasp") + target.adjustBrainLoss(50, 199) //MAD SCIENCE + return TRUE + else + user.visible_message("...[target.p_they()] convulses, then lies still.") + return FALSE + +/datum/surgery_step/revive/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] send a powerful shock to [target]'s brain with [tool], but [target.p_they()] doesn't react.", "You shock [target]'s brain with [tool], but [target.p_they()] doesn't react.") + playsound(get_turf(target), 'sound/magic/lightningbolt.ogg', 50, 1) + target.adjustBrainLoss(15, 199) + return FALSE \ No newline at end of file diff --git a/code/modules/surgery/advanced/viral_bonding.dm b/code/modules/surgery/advanced/viral_bonding.dm new file mode 100644 index 0000000000..bf1e90622b --- /dev/null +++ b/code/modules/surgery/advanced/viral_bonding.dm @@ -0,0 +1,61 @@ +/obj/item/disk/surgery/viral_bonding + desc = "The disk provides instructions on how to force symbiosis between a virus and its host." + surgeries = list(/datum/surgery/advanced/viral_bonding) + +/datum/surgery/advanced/viral_bonding + name = "viral bonding" + steps = list(/datum/surgery_step/incise, + /datum/surgery_step/retract_skin, + /datum/surgery_step/clamp_bleeders, + /datum/surgery_step/incise, + /datum/surgery_step/viral_bond, + /datum/surgery_step/close) + + species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + possible_locs = list("chest") + +/datum/surgery/advanced/viral_bonding/can_start(mob/user, mob/living/carbon/target) + if(!..()) + return FALSE + if(!LAZYLEN(target.viruses)) + return FALSE + return TRUE + +/datum/surgery_step/viral_bond + name = "viral bond" + implements = list(/obj/item/cautery = 100, /obj/item/weldingtool = 50, + /obj/item/lighter = 35, /obj/item/match = 30) + time = 100 + +/datum/surgery_step/viral_bond/tool_check(mob/user, obj/item/tool) + if(istype(tool, /obj/item/cautery)) + return TRUE + + if(istype(tool, /obj/item/weldingtool)) + var/obj/item/weldingtool/WT = tool + if(WT.isOn()) + return TRUE + + else if(istype(tool, /obj/item/lighter)) + var/obj/item/lighter/L = tool + if(L.lit) + return TRUE + + else if(istype(tool, /obj/item/match)) + var/obj/item/match/M = tool + if(M.lit) + return TRUE + return FALSE + +/datum/surgery_step/viral_bond/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] starts heating [target]'s bone marrow with [tool]...", "You start heating [target]'s bone marrow with [tool]...") + +/datum/surgery_step/viral_bond/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + if(!target.reagents.has_reagent("spaceacillin", 5) || !target.reagents.has_reagent("virusfood", 5) || !target.reagents.has_reagent("formaldehyde", 5)) + user.visible_message("[target]'s seems unaffected.", "[target]'s body must be dosed with spaceacillin, virus food and formaldehyde to complete the surgery!") + return FALSE + user.visible_message("[target]'s bone marrow begins pulsing slowly.", "[target]'s bone marrow begins pulsing slowly. The viral bonding is complete.") + for(var/X in target.viruses) + var/datum/disease/D = X + D.carrier = TRUE + return TRUE \ No newline at end of file diff --git a/code/modules/surgery/brain_surgery.dm b/code/modules/surgery/brain_surgery.dm index f2884d1da8..840c40a102 100644 --- a/code/modules/surgery/brain_surgery.dm +++ b/code/modules/surgery/brain_surgery.dm @@ -20,7 +20,6 @@ /datum/surgery/brain_surgery/can_start(mob/user, mob/living/carbon/target) var/obj/item/organ/brain/B = target.getorganslot(ORGAN_SLOT_BRAIN) if(!B) - to_chat(user, "It's hard to do surgery on someone's brain when they don't have one.") return FALSE return TRUE @@ -29,14 +28,17 @@ /datum/surgery_step/fix_brain/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) user.visible_message("[user] successfully fixes [target]'s brain!", "You succeed in fixing [target]'s brain.") + if(target.mind && target.mind.has_antag_datum(/datum/antagonist/brainwashed)) + target.mind.remove_antag_datum(/datum/antagonist/brainwashed) target.adjustBrainLoss(-60) - target.cure_all_traumas() + target.cure_all_traumas(TRAUMA_RESILIENCE_SURGERY) return TRUE /datum/surgery_step/fix_brain/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) if(target.getorganslot(ORGAN_SLOT_BRAIN)) user.visible_message("[user] screws up, causing more damage!", "You screw up, causing more damage!") - target.adjustBrainLoss(80) + target.adjustBrainLoss(60) + target.gain_trauma_type(BRAIN_TRAUMA_SEVERE, TRAUMA_RESILIENCE_LOBOTOMY) else user.visible_message("[user] suddenly notices that the brain [user.p_they()] [user.p_were()] working on is not there anymore.", "You suddenly notice that the brain you were working on is not there anymore.") return FALSE \ No newline at end of file diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm index e293d7c401..7b40b790fa 100644 --- a/code/modules/surgery/surgery.dm +++ b/code/modules/surgery/surgery.dm @@ -38,14 +38,17 @@ // put special restrictions here return 1 - -/datum/surgery/proc/next_step(mob/user) +/datum/surgery/proc/next_step(mob/user, intent) if(step_in_progress) return 1 + var/try_to_fail = FALSE + if(intent == INTENT_DISARM) + try_to_fail = TRUE + var/datum/surgery_step/S = get_surgery_step() if(S) - if(S.try_op(user, target, user.zone_selected, user.get_active_held_item(), src)) + if(S.try_op(user, target, user.zone_selected, user.get_active_held_item(), src, try_to_fail)) return 1 return 0 @@ -78,8 +81,44 @@ return propability + success_multiplier +/datum/surgery/advanced + name = "advanced surgery" +/datum/surgery/advanced/can_start(mob/user, mob/living/carbon/target) + if(!..()) + return FALSE + //Abductor scientists need no instructions + if(isabductor(user)) + var/mob/living/carbon/human/H = user + var/datum/species/abductor/S = H.dna.species + if(S.scientist) + return TRUE + var/turf/T = get_turf(target) + var/obj/structure/table/optable/table = locate(/obj/structure/table/optable, T) + if(!table || !table.computer) + return FALSE + if(table.computer.stat & (NOPOWER|BROKEN)) + return FALSE + if(type in table.computer.advanced_surgeries) + return 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 = subtypesof(/datum/surgery/advanced) //INFO //Check /mob/living/carbon/attackby for how surgery progresses, and also /mob/living/carbon/attack_hand. diff --git a/code/modules/surgery/surgery_step.dm b/code/modules/surgery/surgery_step.dm index fa9e45ca4b..d392190cd8 100644 --- a/code/modules/surgery/surgery_step.dm +++ b/code/modules/surgery/surgery_step.dm @@ -1,108 +1,108 @@ -/datum/surgery_step - var/name - var/list/implements = list() //format is path = probability of success. alternatively - var/implement_type = null //the current type of implement used. This has to be stored, as the actual typepath of the tool may not match the list type. - var/accept_hand = 0 //does the surgery step require an open hand? If true, ignores implements. Compatible with accept_any_item. - var/accept_any_item = 0 //does the surgery step accept any item? If true, ignores implements. Compatible with require_hand. - var/time = 10 //how long does the step take? - var/repeatable = 0 //does this step may 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 - - -/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_check(user, tool)) - success = TRUE - - else if(tool) - for(var/key in implements) - var/match = FALSE - - if(ispath(key) && istype(tool, key)) - match = TRUE - else if(tool.tool_behaviour == key) - match = TRUE - - if(match) - implement_type = key - if(tool_check(user, tool)) - success = TRUE - break - - if(success) - if(target_zone == surgery.location) - if(get_location_accessible(target, target_zone) || surgery.ignore_clothes) - initiate(user, target, target_zone, tool, surgery) - return 1 - else - to_chat(user, "You need to expose [target]'s [parse_zone(target_zone)] to perform surgery on it!") - return 1 //returns 1 so we don't stab the guy in the dick or wherever. - - if(repeatable) - var/datum/surgery_step/next_step = surgery.get_surgery_next_step() - if(next_step) - surgery.status++ - if(next_step.try_op(user, target, user.zone_selected, user.get_active_held_item(), surgery)) - return 1 - else - surgery.status-- - - if(iscyborg(user) && user.a_intent != INTENT_HARM) //to save asimov borgs a LOT of heartache - return 1 - - return 0 - - -/datum/surgery_step/proc/initiate(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - surgery.step_in_progress = 1 - - var/speed_mod = 1 - - if(preop(user, target, target_zone, tool, surgery) == -1) - surgery.step_in_progress = 0 - return - - if(tool) - speed_mod = tool.toolspeed - - if(do_after(user, time * speed_mod, target = target)) - var/advance = 0 - var/prob_chance = 100 - - 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)) - if(success(user, target, target_zone, tool, surgery)) - advance = 1 - else - if(failure(user, target, target_zone, tool, surgery)) - advance = 1 - - if(advance && !repeatable) - surgery.status++ - if(surgery.status > surgery.steps.len) - surgery.complete() - - surgery.step_in_progress = 0 - - -/datum/surgery_step/proc/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - user.visible_message("[user] begins to perform surgery on [target].", "You begin to perform surgery on [target]...") - - -/datum/surgery_step/proc/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - user.visible_message("[user] succeeds!", "You succeed.") - return 1 - -/datum/surgery_step/proc/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - user.visible_message("[user] screws up!", "You screw up!") - return 0 - -/datum/surgery_step/proc/tool_check(mob/user, obj/item/tool) - return 1 +/datum/surgery_step + var/name + var/list/implements = list() //format is path = probability of success. alternatively + var/implement_type = null //the current type of implement used. This has to be stored, as the actual typepath of the tool may not match the list type. + var/accept_hand = 0 //does the surgery step require an open hand? If true, ignores implements. Compatible with accept_any_item. + var/accept_any_item = 0 //does the surgery step accept any item? If true, ignores implements. Compatible with require_hand. + var/time = 10 //how long does the step take? + var/repeatable = 0 //does this step may 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 + + +/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/success = FALSE + if(accept_hand) + if(!tool) + success = TRUE + + if(accept_any_item) + if(tool && tool_check(user, tool)) + success = TRUE + + else if(tool) + for(var/key in implements) + var/match = FALSE + + if(ispath(key) && istype(tool, key)) + match = TRUE + else if(tool.tool_behaviour == key) + match = TRUE + + if(match) + implement_type = key + if(tool_check(user, tool)) + success = TRUE + break + + if(success) + if(target_zone == surgery.location) + if(get_location_accessible(target, target_zone) || surgery.ignore_clothes) + initiate(user, target, target_zone, tool, surgery, try_to_fail) + return 1 + else + to_chat(user, "You need to expose [target]'s [parse_zone(target_zone)] to perform surgery on it!") + return 1 //returns 1 so we don't stab the guy in the dick or wherever. + + if(repeatable) + var/datum/surgery_step/next_step = surgery.get_surgery_next_step() + if(next_step) + surgery.status++ + if(next_step.try_op(user, target, user.zone_selected, user.get_active_held_item(), surgery)) + return 1 + else + surgery.status-- + + if(iscyborg(user) && user.a_intent != INTENT_HARM) //to save asimov borgs a LOT of heartache + return 1 + + return 0 + + +/datum/surgery_step/proc/initiate(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE) + surgery.step_in_progress = 1 + + var/speed_mod = 1 + + if(preop(user, target, target_zone, tool, surgery) == -1) + surgery.step_in_progress = 0 + return + + if(tool) + speed_mod = tool.toolspeed + + if(do_after(user, time * speed_mod, target = target)) + var/advance = 0 + var/prob_chance = 100 + + 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)) && !try_to_fail) + if(success(user, target, target_zone, tool, surgery)) + advance = 1 + else + if(failure(user, target, target_zone, tool, surgery)) + advance = 1 + + if(advance && !repeatable) + surgery.status++ + if(surgery.status > surgery.steps.len) + surgery.complete() + + surgery.step_in_progress = 0 + + +/datum/surgery_step/proc/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] begins to perform surgery on [target].", "You begin to perform surgery on [target]...") + + +/datum/surgery_step/proc/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] succeeds!", "You succeed.") + return 1 + +/datum/surgery_step/proc/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] screws up!", "You screw up!") + return 0 + +/datum/surgery_step/proc/tool_check(mob/user, obj/item/tool) + return 1 diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm index d02ee0373d..89983a946e 100644 --- a/code/modules/uplink/uplink_items.dm +++ b/code/modules/uplink/uplink_items.dm @@ -710,7 +710,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once. name = "Chameleon Kit" desc = "A set of items that contain chameleon technology allowing you to disguise as pretty much anything on the station, and more!" item = /obj/item/storage/box/syndie_kit/chameleon - cost = 2 + cost = 2 exclude_modes = list(/datum/game_mode/nuclear) /datum/uplink_item/stealthy_tools/syndigaloshes @@ -879,6 +879,14 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once. item = /obj/item/storage/backpack/duffelbag/syndie/surgery cost = 3 +/datum/uplink_item/device_tools/brainwash_disk + name = "Brainwashing Surgery Program" + desc = "A disk containing the procedure to perform a brainwashing surgery, allowing you to implant an objective onto a target. \ + Insert into an Operating Console to enable the procedure." + item = /obj/item/disk/surgery/brainwashing + restricted_roles = list("Medical Doctor") + cost = 5 + /datum/uplink_item/device_tools/military_belt name = "Chest Rig" desc = "A robust seven-slot set of webbing that is capable of holding all manner of tactical equipment." diff --git a/tgstation.dme b/tgstation.dme index cb9e557f2b..4052c7ee8e 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -1113,6 +1113,7 @@ #include "code\modules\antagonists\blob\blob\blobs\node.dm" #include "code\modules\antagonists\blob\blob\blobs\resource.dm" #include "code\modules\antagonists\blob\blob\blobs\shield.dm" +#include "code\modules\antagonists\brainwashing\brainwashing.dm" #include "code\modules\antagonists\brother\brother.dm" #include "code\modules\antagonists\changeling\cellular_emporium.dm" #include "code\modules\antagonists\changeling\changeling.dm" @@ -1860,6 +1861,7 @@ #include "code\modules\mob\living\carbon\human\interactive.dm" #include "code\modules\mob\living\carbon\human\inventory.dm" #include "code\modules\mob\living\carbon\human\life.dm" +#include "code\modules\mob\living\carbon\human\physiology.dm" #include "code\modules\mob\living\carbon\human\say.dm" #include "code\modules\mob\living\carbon\human\species.dm" #include "code\modules\mob\living\carbon\human\status_procs.dm" @@ -2430,6 +2432,18 @@ #include "code\modules\surgery\surgery.dm" #include "code\modules\surgery\surgery_step.dm" #include "code\modules\surgery\tools.dm" +#include "code\modules\surgery\advanced\brainwashing.dm" +#include "code\modules\surgery\advanced\lobotomy.dm" +#include "code\modules\surgery\advanced\necrotic_revival.dm" +#include "code\modules\surgery\advanced\pacification.dm" +#include "code\modules\surgery\advanced\reconstruction.dm" +#include "code\modules\surgery\advanced\revival.dm" +#include "code\modules\surgery\advanced\viral_bonding.dm" +#include "code\modules\surgery\advanced\bioware\bioware.dm" +#include "code\modules\surgery\advanced\bioware\bioware_surgery.dm" +#include "code\modules\surgery\advanced\bioware\nerve_grounding.dm" +#include "code\modules\surgery\advanced\bioware\nerve_splicing.dm" +#include "code\modules\surgery\advanced\bioware\vein_threading.dm" #include "code\modules\surgery\bodyparts\bodyparts.dm" #include "code\modules\surgery\bodyparts\dismemberment.dm" #include "code\modules\surgery\bodyparts\head.dm"