From 88a319a574a811818e17b2a9e8b086a638c832d9 Mon Sep 17 00:00:00 2001 From: Matt Atlas Date: Mon, 25 Nov 2019 07:23:16 +0100 Subject: [PATCH] Splitting human life into organs + removes the advanced operating table (#7473) --- aurorastation.dme | 1 - code/game/machinery/OpTable.dm | 4 +- code/game/machinery/Sleeper.dm | 6 +- code/game/machinery/computer/Operating.dm | 163 +------ code/game/machinery/optableadv.dm | 450 ------------------ code/game/objects/items/devices/scanners.dm | 2 +- .../circuitboards/computer/computer.dm | 5 - .../circuitboards/machinery/miscboards.dm | 14 - code/modules/item_worth/worths_list.dm | 2 +- .../mob/living/carbon/brain/brain_item.dm | 31 +- code/modules/mob/living/carbon/breathe.dm | 1 - code/modules/mob/living/carbon/carbon.dm | 20 - .../mob/living/carbon/carbon_defines.dm | 2 - .../mob/living/carbon/human/examine.dm | 2 +- code/modules/mob/living/carbon/human/human.dm | 71 ++- .../mob/living/carbon/human/human_organs.dm | 2 +- code/modules/mob/living/carbon/human/life.dm | 307 +----------- .../carbon/human/species/outsider/vox.dm | 2 +- code/modules/organs/blood.dm | 134 ------ code/modules/organs/internal/brain.dm | 74 +++ code/modules/organs/internal/heart.dm | 149 +++++- code/modules/organs/internal/lungs.dm | 234 ++++++++- code/modules/organs/organ.dm | 3 - .../research/designs/circuit_designs.dm | 15 - .../mattatlas-fromtheashesofcalamity.yml | 48 ++ nano/templates/operating_computer.tmpl | 260 ---------- 26 files changed, 571 insertions(+), 1431 deletions(-) delete mode 100644 code/game/machinery/optableadv.dm create mode 100644 html/changelogs/mattatlas-fromtheashesofcalamity.yml delete mode 100644 nano/templates/operating_computer.tmpl diff --git a/aurorastation.dme b/aurorastation.dme index 34a014bb6f0..58040f1926c 100644 --- a/aurorastation.dme +++ b/aurorastation.dme @@ -571,7 +571,6 @@ #include "code\game\machinery\newscaster.dm" #include "code\game\machinery\nuclear_bomb.dm" #include "code\game\machinery\OpTable.dm" -#include "code\game\machinery\optableadv.dm" #include "code\game\machinery\overview.dm" #include "code\game\machinery\portable_turret.dm" #include "code\game\machinery\recharger.dm" diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm index 6a85c96c8fa..444ef8abb78 100644 --- a/code/game/machinery/OpTable.dm +++ b/code/game/machinery/OpTable.dm @@ -94,7 +94,7 @@ var/mob/living/carbon/human/H = locate() in loc if(istype(H)) if(H.lying) - icon_state = H.pulse ? "[modify_state]-active" : "[modify_state]-idle" + icon_state = H.is_pulse_present() ? "[modify_state]-active" : "[modify_state]-idle" victim = H if(victim) if(suppressing && victim.sleeping < 3) @@ -120,7 +120,7 @@ if(ishuman(C)) var/mob/living/carbon/human/H = C src.victim = H - icon_state = H.pulse ? "[modify_state]-active" : "[modify_state]-idle" + icon_state = H.is_pulse_present() ? "[modify_state]-active" : "[modify_state]-idle" else icon_state = "[modify_state]-idle" diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 7cf80099952..6e1156008f5 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -97,9 +97,9 @@ if(DEAD) data["stat"] = "Dead" data["health"] = occupant.health - if(iscarbon(occupant)) - var/mob/living/carbon/C = occupant - data["pulse"] = C.get_pulse(GETPULSE_TOOL) + if(ishuman(occupant)) + var/mob/living/carbon/human/H = occupant + data["pulse"] = H.get_pulse(GETPULSE_TOOL) data["brute"] = occupant.getBruteLoss() data["burn"] = occupant.getFireLoss() data["oxy"] = occupant.getOxyLoss() diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm index 87cdea1f99e..9364e4e2f42 100644 --- a/code/game/machinery/computer/Operating.dm +++ b/code/game/machinery/computer/Operating.dm @@ -81,165 +81,4 @@ /obj/machinery/computer/operating/machinery_process() if(operable()) - src.updateDialog() - - - - -/obj/machinery/computer/operating/advanced - name = "advanced operating computer" - density = 1 - anchored = 1.0 - icon_state = "crew" - icon_state = "computer" - circuit = /obj/item/circuitboard/advoperating - interact_offline = 0 - var/screen = 1 - -/obj/machinery/computer/operating/advanced/New() - ..() - for(dir in list(NORTH,EAST,SOUTH,WEST)) - table = locate(/obj/machinery/optable/lifesupport, get_step(src, dir)) - if (table) - table.computer = src - break - -/obj/machinery/computer/operating/advanced/attack_ai(mob/user) - add_fingerprint(user) - if(stat & (BROKEN|NOPOWER)) - return - interact(user) - - -/obj/machinery/computer/operating/advanced/attack_hand(mob/user) - add_fingerprint(user) - if(stat & (BROKEN|NOPOWER)) - return - ui_interact(user) - -/obj/machinery/computer/operating/advanced/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - - if (user.stat) - return - - if (table && table.victim == user) - return - - var/data[0] - - data["table"] = 0 - data["screen"] = screen - if (table) - if (istype(table, /obj/machinery/optable/lifesupport)) - data["table"] = 2 - else - data["table"] = 1 - - if (screen == 1) - var/patientgeneral[0] - var/patienthealth[0] - if (table.victim) - var/mob/living/carbon/human/patient = table.victim - patientgeneral["Name"] = patient.real_name - patientgeneral["Age"] = patient.age - patientgeneral["BloodType"] = patient.b_type - data["patientgeneral"] = patientgeneral; - - patienthealth["Health"] = round(patient.health) - patienthealth["Brute"] = round(patient.getBruteLoss()) - patienthealth["Toxins"] = round(patient.getToxLoss()) - patienthealth["Burn"] = round(patient.getFireLoss()) - patienthealth["Suffocation"] = round(patient.getOxyLoss()) - patienthealth["Status"] = patient.stat ? "Non-responsive" : "Stable" - patienthealth["Heartrate"] = patient.get_pulse(GETPULSE_TOOL) - if (data["table"] == 2) - patienthealth["BloodLevel"] = round(patient.vessel.get_reagent_amount("blood")) - data["patienthealth"] = patienthealth; - - if (data["table"] == 2) - var/obj/machinery/optable/lifesupport/A = table - data["buckled"] = A.buckled - data["lifesupport"] = A.onlifesupport() - - if (A.reagents.reagent_list.len) - data["hasreagents"] = 1 - var/loadedreagents[0] - for(var/datum/reagent/chem in A.reagents.reagent_list) - loadedreagents.Add(list(list("name" = chem.name, "volume" = round(chem.volume)))) - data["loadedreagents"] = loadedreagents; - else - data["hasreagents"] = 0 - - if (A.airsupply) - data["hasair"] = 1 - var/air[0] - air["internalpressure"] = round(A.airsupply.air_contents.return_pressure()) - air["releasepressure"] = round(A.airsupply.distribute_pressure) - data["air"] = air; - else - data["hasair"] = 0 - - if (A.bloodbag) - data["hasblood"] = 1 - var/blood[0] - blood["volume"] = A.bloodbag.reagents.total_volume - if (A.bloodbag.reagents.reagent_list.len) - for (var/datum/reagent/blood/Blood in A.bloodbag.reagents.reagent_list) - blood["type"] = Blood.data["blood_type"] - else - blood["type"] = "N/A" - data["blood"] = blood; - else - data["hasblood"] = 0 - - var/program[0] - program["autotransfuse"] = A.checkprogram("AUTO_TRANSFUSE") - program["transfuseactive"] = A.checkprogram("TRANSFUSE_ACTIVE") - program["autoair"] = A.checkprogram("AUTO_AIR") - program["airactive"] = A.checkprogram("AIR_ACTIVE") - program["purge"] = A.checkprogram("PURGE") - program["emagged"] = A.emagged - data["program"] = program; - - else if (screen == 2) - if (data["table"] == 1) - screen = 1 - return - - var/obj/machinery/optable/lifesupport/B = table - data["log"] = B.internallog; - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "operating_computer.tmpl", "Operating Computer", 540, 680) - // when the ui is first opened this is the data it will use - ui.set_initial_data(data) - // open the new ui window - ui.open() - // auto update every Master Controller tick - ui.set_auto_update(1) - -/obj/machinery/computer/operating/advanced/Topic(href, href_list) - if(..()) - return - - if (istype(table, /obj/machinery/optable/lifesupport)) - var/obj/machinery/optable/lifesupport/A = table - if (href_list["toggle_lifesupport"]) - A.toggleactive() - return 1 - if (href_list["eject_advanced"]) - A.eject(href_list["eject_advanced"]) - return 1 - if (href_list["toggle_program"]) - A.toggleprogram(null, href_list["toggle_program"]) - return 1 - if (href_list["select_screen"]) - screen = text2num(href_list["select_screen"]) - return 1 - if (href_list["clear_log"]) - A.clearlog() - return 1 - return 1 + src.updateDialog() \ No newline at end of file diff --git a/code/game/machinery/optableadv.dm b/code/game/machinery/optableadv.dm deleted file mode 100644 index 33ef2f780da..00000000000 --- a/code/game/machinery/optableadv.dm +++ /dev/null @@ -1,450 +0,0 @@ -#define AUTO_TRANSFUSE 1 -#define AUTO_AIR 2 -#define TRANSFUSE_ACTIVE 4 -#define AIR_ACTIVE 8 -#define PURGE 16 - -/* - * The more advanced life support table - */ -/obj/machinery/optable/lifesupport - name = "life support operating table" - desc = "A more advanced version of the standard operating table." - icon_state = "table3-idle" - modify_state = "table3" - flags = OPENCONTAINER - idle_power_usage = 3 - active_power_usage = 8 - - var/movable = 0 //For buckling! - var/buckled = 0 //Is the patient hooked up to the machine properly? - var/active = 0 //Is the machine active, and providing lifesupport? - var/expired = 0 //Have we alerted the folks about a dead patient yet? - var/program = 0 //Bitfield for containing the programmable settings. - var/obj/item/reagent_containers/blood/bloodbag //Stores the bloodbag that you can add to the machine, for IV dripping shenanigans. - var/obj/item/tank/airsupply //Stores the airtank used for anesthesia. - var/obj/item/clothing/mask/breath/medical/airmask //Stores the medical mask used for anesthesia. - var/requiredchems = list( - "peridaxon" = 0.06, - "cryoxadone" = 0.2) //Details what chemicals (use ids, not names) it keeps track of, and the minimum quantities required for operation. Each time process() is called, the associated amount of that chemical is removed from storage. - //Cryoxadone will last you around 10 minutes, Clonexadone around 30. (Provided you use the standard, 60 unit beaker.) - var/list/internallog = list() //A log of everything that has happened on the table. Has two keys per entry: "time" and "message". - - component_types = list( - /obj/item/circuitboard/optableadv, - /obj/item/clothing/mask/breath/medical, - /obj/item/reagent_containers/glass/beaker/large = 2 - - ) - - -/obj/machinery/optable/lifesupport/proc/onlifesupport() - return 0 - - -/obj/machinery/optable/lifesupport/Initialize() - ..() - -/obj/machinery/optable/lifesupport/attackby(obj/item/W as obj, mob/living/carbon/user as mob) - . = ..() - if (.) - return - - if (istype(W, /obj/item/reagent_containers/blood)) - if (!bloodbag) - user.drop_item() - bloodbag = W - W.loc = src - to_chat(user, "You load [W] into [src], and hook it up to the machine.") - return - else - to_chat(user, "There is already a bloodbag in [src]!") - return - - if (W.is_open_container()) - return 0 - - if (istype(W, /obj/item/tank)) - if (!airsupply) - user.drop_item() - airsupply = W - W.loc = src - to_chat(user, "You load [W] into [src], and hook it up the machine.") - return - else - to_chat(user, "There is already [airsupply] in [src]!") - return - - if (istype(W, /obj/item/card/emag)) - if (!emagged) - emagged = 1 - to_chat(user, "You run [W] through [src], hear the machine quietly whirr. A new option has been unlocked.") - return - else - to_chat(user, "[src] is already emagged!") - return - -/obj/machinery/optable/lifesupport/process(mob/living/carbon/patient as mob) - ..() - - if (active) - if ((stat & NOPOWER) || (stat & BROKEN)) - //Safety catch number 2: immediate failure of life support, upon power failure or machine damage. - toggleactive(1) - return - - //A safety catch. - if (!victim || !buckled) - toggleactive() - if (program & TRANSFUSE_ACTIVE) - toggleprogram(TRANSFUSE_ACTIVE) - if (program & AIR_ACTIVE) - toggleprogram(AIR_ACTIVE) - return - - var/id = checkrequiredchems() - if (!id) - toggleactive(1) - return - else - reagents.remove_reagent(id, requiredchems[id]) - - if (victim.stat == 2 && !expired) - broadcastalert("ALERT! Patient death detected!") - addtolog("Patient death detected.") - expired = 1 - - var/bloodvolume = round(victim.vessel.get_reagent_amount("blood")) - if ((program & AUTO_TRANSFUSE) && bloodbag && bloodbag.reagents.total_volume) - if (bloodvolume < BLOOD_VOLUME_SAFE && !(program & TRANSFUSE_ACTIVE)) - toggleprogram(TRANSFUSE_ACTIVE) - else if (bloodvolume >= BLOOD_VOLUME_SAFE && (program & TRANSFUSE_ACTIVE)) - toggleprogram(TRANSFUSE_ACTIVE) - - if (program & TRANSFUSE_ACTIVE) - if (!bloodbag || !bloodbag.reagents.total_volume) - toggleprogram(TRANSFUSE_ACTIVE) - else - bloodbag.reagents.trans_to(victim, 4) - - if ((program & AUTO_AIR) && airsupply && airsupply.air_contents.return_pressure() > 10) - if (!(program & AIR_ACTIVE)) - toggleprogram(AIR_ACTIVE) - - if ((program & AIR_ACTIVE) && (!airsupply || airsupply.air_contents.return_pressure() < 10)) - toggleprogram(AIR_ACTIVE) - - if (program & PURGE) - var/T = get_turf(src) - new /obj/effect/gibspawner/human(T) - spark(T, 5) - playsound(T, "sparks", 50, 1) - to_chat(victim, "You feel the machine wrestle away at your flesh with its claws, leaving you as a husk of your former self...") - victim.set_species("Skeleton") - -/obj/machinery/optable/lifesupport/update_icon() - if (panel_open) - icon_state = "[modify_state]-open" - else if (victim && active) - icon_state = victim.pulse ? "[modify_state]-lifeactive" : "[modify_state]-lifeidle" - else if (victim) - icon_state = victim.pulse ? "[modify_state]-active" : "[modify_state]-idle" - else - icon_state = "[modify_state]-idle" - - -/obj/machinery/optable/lifesupport/check_table(mob/living/carbon/patient as mob) - if (victim) - to_chat(usr, "The table is already occupied!") - return 0 - - return 1 - -/obj/machinery/optable/lifesupport/onlifesupport() - return active - -/obj/machinery/optable/lifesupport/RefreshParts() - // Adjust reagent container volume to match combined volume of the inserted beakers - var/T = 0 - for(var/obj/item/reagent_containers/glass/G in component_parts) - T += G.reagents.maximum_volume - create_reagents(T) - // Transfer all reagents from the beakers to internal reagent container - for(var/obj/item/reagent_containers/glass/G in component_parts) - G.reagents.trans_to_obj(src, G.reagents.total_volume) - -/obj/machinery/optable/lifesupport/proc/broadcastalert(var/message as text) - playsound(loc, 'sound/machines/chime.ogg', 75, 1) - visible_message("\icon[src][src] pings: [message]") - -/obj/machinery/optable/lifesupport/proc/checkrequiredchems() - for (var/id in requiredchems) - if (reagents.has_reagent(id, requiredchems[id])) - return id - - return 0 - -/obj/machinery/optable/lifesupport/proc/addtolog(var/log as text) - var/time = worldtime2text() - internallog.Add(list(list("time" = time, "message" = log))) - -/obj/machinery/optable/lifesupport/proc/clearlog() - if (internallog.len) - internallog = list() - -/obj/machinery/optable/lifesupport/proc/eject(var/item as text) - switch (item) - if ("airsupply") - if (airsupply) - if (program & AIR_ACTIVE) - broadcastalert("ERROR: Internal air supply still connected. Aborting!") - return - else - airsupply.loc = loc - airsupply = null - broadcastalert("Internal air supply ejected.") - addtolog("Internal air supply ejected.") - return - if ("bloodbag") - if (bloodbag) - if (program & TRANSFUSE_ACTIVE) - broadcastalert("ERROR: Transfusion processes still underway. Aborting!") - return - else - bloodbag.loc = loc - bloodbag = null - broadcastalert("Internal blood supply ejected.") - addtolog("Internal blood supply ejected.") - return - if ("chems") - if (reagents.total_volume) - if (active) - broadcastalert("ERROR: Life support systems enabled, unable to flush chemicals. Aborting!") - return - else - broadcastalert("Stored chemicals flushed.") - addtolog("Stored chemicals flushed.") - reagents.clear_reagents() - -/obj/machinery/optable/lifesupport/proc/buckle(mob/living/carbon/human/patient as mob, mob/living/carbon/human/user as mob) - if (!victim) - to_chat(user, "No patient to buckle in!") - return - - if (patient == user) - to_chat(user, "You cannot do this yourself!") - return - - if (active) - to_chat(user, "You cannot do this while lifesupport is enabled!") - return - - if (!buckled) - if (patient.wear_mask) - to_chat(user, "You need to remove their [patient.wear_mask] first!") - return - else if (patient.back) - to_chat(user, "You need to remove their [patient.back] first!") - return - - switch (buckled) - if (0) - user.visible_message("[user] buckles \the [victim] into \the [src], linking them up to the required tubing and straps.", "You fit \the [victim] into \the [src]'s restraints, and hook them up to the life-support machine.") - if (!patient.sleeping && !patient.stat) - to_chat(patient, "[user] buckles you into \the [src] and hooks you up to the lifesupport machinery.") - buckled = 1 - patient.buckled = src - patient.update_canmove() - patient.equip_to_slot(airmask, slot_wear_mask) - addtolog("Restraints activated.") - return - if (1) - user.visible_message("[user] unbuckles \the [victim] from \the [src], disconnecting them from the tubing and straps.", "You remove \the [victim]'s restraints, and unhook them from the life-support machine.") - if (!patient.sleeping && !patient.stat) - to_chat(patient, "[user] unbuckles you from \the [src] and disconnects you from the lifesupport machinery.") - buckled = 0 - patient.buckled = null - patient.anchored = initial(patient.anchored) - patient.update_canmove() - patient.u_equip(airmask) - airmask.loc = src - addtolog("Restraints deactivated.") - return - -/obj/machinery/optable/lifesupport/verb/bucklepatient() - set name = "Buckle Patient In" - set category = "Object" - set src in oview(1) - - if(usr.stat || !ishuman(usr) || usr.restrained()) - return - - buckle(victim, usr) - -/obj/machinery/optable/lifesupport/proc/toggleactive(var/override = 0) - if (!victim) - broadcastalert("ERROR: No patient detected. Aborting!") - return - - if (!buckled) - broadcastalert("ERROR: Patient not linked to the machinery. Aborting!") - return - - switch (active) - if (0) - if (stat & BROKEN) - broadcastalert("ERROR: Machine damaged. Aborting!") - return - - if (stat & NOPOWER) - broadcastalert("ERROR: Machine not powered. Aborting!") - return - - if (victim.stat == DEAD) - broadcastalert("ERROR: No life signs detected from the patient. Unable to enable life support systems.") - return - - if (checkrequiredchems()) - active = 1 - broadcastalert("Patient detected. Life support systems enabled.") - addtolog("Life support systems enabled.") - return - else - broadcastalert("ERROR: Required chemicals not detected in the machine. Aborting!") - return - if (1) - if ((program & AUTO_TRANSFUSE) && (program & TRANSFUSE_ACTIVE)) - toggleprogram(TRANSFUSE_ACTIVE) - else if (program & TRANSFUSE_ACTIVE) - if (!override) - broadcastalert("ERROR: Transfusion processes still underway. Aborting!") - return - else - toggleprogram(TRANSFUSE_ACTIVE) - - if ((program & AUTO_AIR) && (program & AIR_ACTIVE)) - toggleprogram(AIR_ACTIVE) - else if (program & AIR_ACTIVE) - if (!override) - broadcastalert("ERROR: Internal air supply still connected. Aborting!") - return - else - toggleprogram(AIR_ACTIVE) - - active = 0 - - if (override) - broadcastalert("ERROR: Not enough chemicals to sustain lifesupport functionality! Shutting down lifesupport systems!") - addtolog("Emergency shutdown of life support systems.") - else - broadcastalert("Life support systems disabled.") - addtolog("Life support systems disabled.") - - return - -/obj/machinery/optable/lifesupport/proc/toggleprogram(setting, var/textsetting = null) - if (textsetting) - switch (textsetting) - if ("AUTO_TRANSFUSE") - setting = AUTO_TRANSFUSE - if ("AUTO_AIR") - setting = AUTO_AIR - if ("TRANSFUSE_ACTIVE") - setting = TRANSFUSE_ACTIVE - if ("AIR_ACTIVE") - setting = AIR_ACTIVE - if ("PURGE") - setting = PURGE - - if (program & setting) - switch (setting) - if (TRANSFUSE_ACTIVE) - broadcastalert("Transfusion processes deactivated.") - addtolog("Transfusion processes deactivated.") - program &= ~setting - return - if (AIR_ACTIVE) - victim.u_equip(airsupply) - airsupply.loc = src - broadcastalert("Internal air supply deactivated.") - addtolog("Internal air supply deactivated.") - program &= ~setting - return - if (PURGE) - if (!emagged) - return - else - program &= ~setting - return - else - var/textname - if (setting == AUTO_TRANSFUSE) - textname = "Automatic transfusion control" - else if (setting == AUTO_AIR) - textname = "Automatic air supply control" - else - textname = "Unknown program" - addtolog("[textname] deactivated.") - program &= ~setting - else - switch (setting) - if (TRANSFUSE_ACTIVE) - if (bloodbag && bloodbag.reagents.total_volume) - broadcastalert("Transfusion processes activated.") - addtolog("Transfusion processes activated.") - program |= setting - return - else - broadcastalert("Bloodbag empty or not connected!") - return - if (AIR_ACTIVE) - if (airsupply && airsupply.air_contents.return_pressure() > 10) - victim.equip_to_slot(airsupply, slot_back) - victim.internal = airsupply - broadcastalert("Internal air supply activated.") - addtolog("Internal air supply activated.") - program |= setting - return - else - broadcastalert("Air supply empty or not connected!") - return - if (PURGE) - if (!emagged) - return - else - program |= setting - else - var/textname - if (setting == AUTO_TRANSFUSE) - textname = "Automatic transfusion control" - else if (setting == AUTO_AIR) - textname = "Automatic air supply control" - else - textname = "Unknown program" - addtolog("[textname] activated.") - program |= setting - -/obj/machinery/optable/lifesupport/proc/checkprogram(var/textsetting as text) - var/setting - switch (textsetting) - if ("AUTO_TRANSFUSE") - setting = AUTO_TRANSFUSE - if ("AUTO_AIR") - setting = AUTO_AIR - if ("TRANSFUSE_ACTIVE") - setting = TRANSFUSE_ACTIVE - if ("AIR_ACTIVE") - setting = AIR_ACTIVE - if ("PURGE") - setting = PURGE - - if (program & setting) - return 1 - else - return 0 - -#undef AUTO_TRANSFUSE -#undef AUTO_AIR -#undef TRANSFUSE_ACTIVE -#undef AIR_ACTIVE -#undef PURGE diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index a5887df5e5a..93050cd1b67 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -225,7 +225,7 @@ BREATH ANALYZER user.show_message("Warning: Blood Level CRITICAL: [blood_percent]% [blood_volume]cl. Type: [blood_type]") else user.show_message("Blood Level Normal: [blood_percent]% [blood_volume]cl. Type: [blood_type]") - user.show_message("Subject's pulse: [H.get_pulse(GETPULSE_TOOL)] bpm.") + user.show_message("Subject's pulse: [H.get_pulse(GETPULSE_TOOL)] bpm.") /obj/item/device/healthanalyzer/verb/toggle_mode() set name = "Switch Verbosity" diff --git a/code/game/objects/items/weapons/circuitboards/computer/computer.dm b/code/game/objects/items/weapons/circuitboards/computer/computer.dm index c6a8b45bdb7..e01dee5002e 100644 --- a/code/game/objects/items/weapons/circuitboards/computer/computer.dm +++ b/code/game/objects/items/weapons/circuitboards/computer/computer.dm @@ -129,11 +129,6 @@ build_path = /obj/machinery/computer/operating origin_tech = list(TECH_DATA = 2, TECH_BIO = 2) -/obj/item/circuitboard/advoperating - name = T_BOARD("life support table console") - build_path = /obj/machinery/computer/operating/advanced - origin_tech = list(TECH_DATA = 4, TECH_BIO = 4) - /obj/item/circuitboard/curefab name = T_BOARD("cure fabricator") build_path = /obj/machinery/computer/curer diff --git a/code/game/objects/items/weapons/circuitboards/machinery/miscboards.dm b/code/game/objects/items/weapons/circuitboards/machinery/miscboards.dm index ea445f3df7c..9b8963eebe0 100644 --- a/code/game/objects/items/weapons/circuitboards/machinery/miscboards.dm +++ b/code/game/objects/items/weapons/circuitboards/machinery/miscboards.dm @@ -73,20 +73,6 @@ req_components = list( "/obj/item/stock_parts/scanning_module" = 1) -/obj/item/circuitboard/optableadv - name = T_BOARD("Advanced Operation Table") - desc = "The circuitboard for a advanced operating table." - build_path = "/obj/machinery/optable/lifesupport" - origin_tech = list(TECH_BIO = 4, TECH_ENGINEERING = 5) - board_type = "machine" - req_components = list( - "/obj/item/stock_parts/scanning_module" = 1, - "/obj/item/stock_parts/capacitor" = 1, - "/obj/item/device/healthanalyzer" = 1, - "/obj/item/stock_parts/scanning_module/adv" = 1, - "/obj/item/clothing/mask/breath/medical" = 1, - "/obj/item/reagent_containers/glass/beaker/large" = 2) - /obj/item/circuitboard/smartfridge name = T_BOARD("Smart Fridge") desc = "The circuitboard for a smart fridge." diff --git a/code/modules/item_worth/worths_list.dm b/code/modules/item_worth/worths_list.dm index 601b219b744..8837e4fc703 100644 --- a/code/modules/item_worth/worths_list.dm +++ b/code/modules/item_worth/worths_list.dm @@ -631,7 +631,7 @@ var/list/worths = list( /obj/item/organ/internal/heart = 1200, /obj/item/organ/internal/brain/golem = 3000, /obj/item/organ/internal/brain = 1200, - /obj/item/organ/internal/pariah_brain = 5, + /obj/item/organ/pariah_brain = 5, /obj/item/organ/vaurca/neuralsocket = 1500, /obj/item/organ/stack/vox = 5000, /obj/item/organ = 400, diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm index 67576e5fb22..b58b0cb4d79 100644 --- a/code/modules/mob/living/carbon/brain/brain_item.dm +++ b/code/modules/mob/living/carbon/brain/brain_item.dm @@ -1,24 +1,4 @@ -/obj/item/organ/internal/brain - name = "brain" - health = 400 //They need to live awhile longer than other organs. Is this even used by organ code anymore? - desc = "A piece of juicy meat found in a person's head." - organ_tag = BP_BRAIN - parent_organ = BP_HEAD - vital = 1 - icon_state = "brain" - force = 1.0 - w_class = 2.0 - throwforce = 1.0 - throw_speed = 3 - throw_range = 5 - origin_tech = list(TECH_BIO = 3) - attack_verb = list("attacked", "slapped", "whacked") - var/mob/living/carbon/brain/brainmob = null - var/list/datum/brain_trauma/traumas = list() - var/lobotomized = 0 - var/can_lobotomize = 1 - -/obj/item/organ/internal/pariah_brain +/obj/item/organ/pariah_brain name = "brain remnants" desc = "Did someone tread on this? It looks useless for cloning or cyborgification." organ_tag = "brain" @@ -132,15 +112,6 @@ to_chat(user, "The brain has already been operated on!") ..() -/obj/item/organ/internal/brain/process() - ..() - - if(!owner) - return - - if(lobotomized && (owner.getBrainLoss() < 40)) //lobotomized brains cannot be healed with chemistry. Part of the brain is irrevocably missing. Can be fixed magically with cloning, ofc. - owner.setBrainLoss(40) - /obj/item/organ/internal/brain/slime name = "slime core" desc = "A complex, organic knot of jelly and crystalline particles." diff --git a/code/modules/mob/living/carbon/breathe.dm b/code/modules/mob/living/carbon/breathe.dm index 7b0f98dd57c..b5069338843 100644 --- a/code/modules/mob/living/carbon/breathe.dm +++ b/code/modules/mob/living/carbon/breathe.dm @@ -21,7 +21,6 @@ return from.trans_to_holder(target,amount,multiplier,copy) //complete transfer /mob/living/carbon/proc/breathe(var/volume_needed = BREATH_VOLUME) - //if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell)) return if(species && (species.flags & NO_BREATHE)) return volume_needed *= (species?.breath_vol_mul || 1) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 87050a02a44..bd8eb71ec38 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -372,26 +372,6 @@ return -//generates realistic-ish pulse output based on preset levels -/mob/living/carbon/proc/get_pulse(var/method) //method 0 is for hands, 1 is for machines, more accurate - var/temp = 0 //see setup.dm:694 - switch(src.pulse) - if(PULSE_NONE) - return "0" - if(PULSE_SLOW) - temp = rand(40, 60) - return num2text(method ? temp : temp + rand(-10, 10)) - if(PULSE_NORM) - temp = rand(60, 90) - return num2text(method ? temp : temp + rand(-10, 10)) - if(PULSE_FAST) - temp = rand(90, 120) - return num2text(method ? temp : temp + rand(-10, 10)) - if(PULSE_2FAST) - temp = rand(120, 160) - return num2text(method ? temp : temp + rand(-10, 10)) - if(PULSE_THREADY) - return method ? ">250" : "extremely weak and fast, patient's artery feels like a thread" // output for machines^ ^^^^^^^output for people^^^^^^^^^ /mob/living/carbon/verb/mob_sleep() diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index 3a28ff86e4f..b3eef18f5db 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -21,8 +21,6 @@ var/datum/reagents/metabolism/touching = null var/datum/reagents/metabolism/breathing = null - var/pulse = PULSE_NORM //current pulse level - //these two help govern taste. The first is the last time a taste message was shown to the plaer. //the second is the message in question. var/last_taste_time = 0 diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 9639b96429e..bb8a03107cb 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -228,7 +228,7 @@ spawn (0) user.visible_message("[user] checks [src]'s pulse.", "You check [src]'s pulse.") if (do_mob(user, src, 15)) - if(pulse == PULSE_NONE) + if(is_pulse_present() == PULSE_NONE) to_chat(user, "[T.He] [T.has] no pulse[src.client ? "" : " and [T.his] soul has departed"]...") else to_chat(user, "[T.He] [T.has] a pulse!") diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index a71be51665e..3e8237f98e6 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1064,15 +1064,38 @@ ..() +/mob/living/carbon/human/handle_breath(datum/gas_mixture/breath) + if(status_flags & GODMODE) + return + + if(!species.has_organ[BP_LUNGS]) + return + + var/species_organ = species.breathing_organ + if(!species_organ) + return + + var/obj/item/organ/internal/lungs/L = internal_organs_by_name[species_organ] + + if(!L) + losebreath += 15 //No lungs, how do you breathe? + adjustOxyLoss(15) + failed_last_breath = TRUE + else + failed_last_breath = L.handle_breath(breath) + + return !failed_last_breath + /mob/living/carbon/human/proc/is_lung_ruptured() - var/obj/item/organ/internal/lungs/L = internal_organs_by_name[BP_LUNGS] + var/species_organ = species.breathing_organ + var/obj/item/organ/internal/lungs/L = internal_organs_by_name[species_organ] return L && L.is_bruised() /mob/living/carbon/human/proc/rupture_lung() - var/obj/item/organ/internal/lungs/L = internal_organs_by_name[BP_LUNGS] - + var/species_organ = species.breathing_organ + var/obj/item/organ/internal/lungs/L = internal_organs_by_name[species_organ] if(L && !L.is_bruised()) - src.custom_pain("You feel a stabbing pain in your chest!", 1) + custom_pain("You feel a stabbing pain in your chest!", 1) L.bruise() //returns 1 if made bloody, returns 0 otherwise @@ -1161,7 +1184,7 @@ usr.visible_message("[usr] begins counting their pulse.",\ "You begin counting your pulse.") - if(src.pulse) + if(is_pulse_present()) to_chat(usr, "[self ? "You have a" : "[src] has a"] pulse! Counting...") else to_chat(usr, "[src] has no pulse!") //it is REALLY UNLIKELY that a dead person would check his own pulse) @@ -1564,13 +1587,6 @@ /mob/living/carbon/human/get_metabolism(metabolism) return ..() * (species ? species.metabolism_mod : 1) - -/mob/living/carbon/human/proc/isonlifesupport() - if (buckled && istype(buckled, /obj/machinery/optable/lifesupport)) - var/obj/machinery/optable/lifesupport/A = buckled - return A.onlifesupport() - else - return 0 /mob/living/carbon/human/is_clumsy() if(CLUMSY in mutations) return TRUE @@ -1582,3 +1598,34 @@ return TRUE return FALSE + +/mob/living/carbon/human/proc/get_pulse(var/method) //method 0 is for hands, 1 is for machines, more accurate + var/temp = 0 //see setup.dm:694 + var/obj/item/organ/internal/heart/heart = internal_organs_by_name[BP_HEART] + if(heart) + switch(heart.pulse) + if(PULSE_NONE) + return "0" + if(PULSE_SLOW) + temp = rand(40, 60) + return num2text(method ? temp : temp + rand(-10, 10)) + if(PULSE_NORM) + temp = rand(60, 90) + return num2text(method ? temp : temp + rand(-10, 10)) + if(PULSE_FAST) + temp = rand(90, 120) + return num2text(method ? temp : temp + rand(-10, 10)) + if(PULSE_2FAST) + temp = rand(120, 160) + return num2text(method ? temp : temp + rand(-10, 10)) + if(PULSE_THREADY) + return method ? ">250" : "extremely weak and fast, patient's artery feels like a thread" + else + return "0" + +/mob/living/carbon/human/proc/is_pulse_present() + var/obj/item/organ/internal/heart/heart = internal_organs_by_name[BP_HEART] + if(heart) + return heart.pulse + else + return FALSE diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm index ddaacf2ac01..113479689a5 100644 --- a/code/modules/mob/living/carbon/human/human_organs.dm +++ b/code/modules/mob/living/carbon/human/human_organs.dm @@ -52,7 +52,7 @@ //Moving around with fractured ribs won't do you any good if (E.is_broken() && E.internal_organs && E.internal_organs.len && prob(15)) var/obj/item/organ/I = pick(E.internal_organs) - custom_pain("You feel broken bones moving in your [E.name]!", 1) + custom_pain("Pain jolts through your broken [E.name]!", 50) I.take_damage(rand(3,5)) //Moving makes open wounds get infected much faster diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 4c4e3285c10..d75194b66bf 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -1,8 +1,6 @@ //This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 //NOTE: Breathing happens once per FOUR TICKS, unless the last breath fails. In which case it happens once per ONE TICK! So oxyloss healing is done once per 4 ticks while oxyloss damage is applied once per tick! -#define HUMAN_MAX_OXYLOSS 1 //Defines how much oxyloss humans can get per tick. A tile with no air at all (such as space) applies this value, otherwise it's a percentage of it. -#define HUMAN_CRIT_MAX_OXYLOSS ( 2.0 / 6) //The amount of damage you'll get when in critical condition. We want this to be a 5 minute deal = 300s. There are 50HP to get through, so (1/6)*last_tick_duration per second. Breaths however only happen every 4 ticks. last_tick_duration = ~2.0 on average #define HEAT_DAMAGE_LEVEL_1 2 //Amount of damage applied when your body temperature just passes the 360.15k safety point #define HEAT_DAMAGE_LEVEL_2 4 //Amount of damage applied when your body temperature passes the 400K point @@ -31,7 +29,6 @@ var/pressure_alert = 0 var/temperature_alert = 0 var/in_stasis = 0 - var/heartbeat = 0 /mob/living/carbon/human/Life() set background = BACKGROUND_ENABLED @@ -77,10 +74,6 @@ handle_medical_side_effects() - handle_heartbeat() - - handle_brain_damage() - //Handles regenerating stamina if we have sufficient air and no oxyloss handle_stamina() @@ -97,8 +90,6 @@ //Update our name based on whether our face is obscured/disfigured name = get_visible_name() - pulse = handle_pulse() - if(mind && mind.vampire) handle_vampire() @@ -388,234 +379,6 @@ return breath -/mob/living/carbon/human/handle_breath(datum/gas_mixture/breath) - if(status_flags & GODMODE) - return - - //exposure to extreme pressures can rupture lungs - if(breath && (breath.total_moles/(species?.breath_vol_mul || 1) < BREATH_MOLES / 5 || breath.total_moles/(species?.breath_vol_mul || 1) > BREATH_MOLES * 5)) - if(!is_lung_ruptured() && prob(5)) - rupture_lung() - - //check if we actually need to process breath - if(!breath || (breath.total_moles == 0)) - failed_last_breath = 1 - if(health > config.health_threshold_crit) - adjustOxyLoss(HUMAN_MAX_OXYLOSS) - else - adjustOxyLoss(HUMAN_CRIT_MAX_OXYLOSS) - - oxygen_alert = max(oxygen_alert, 1) - return 0 - - var/safe_pressure_min = species.breath_pressure // Minimum safe partial pressure of breathable gas in kPa - - // Lung damage increases the minimum safe pressure. - var/handle_lungs = 0 - var/obj/item/organ/L = null - if (species.breathing_organ) - L = internal_organs_by_name[species.breathing_organ] - handle_lungs = TRUE - - if (handle_lungs) - if(!L) - safe_pressure_min = INFINITY //No lungs, how are you breathing? - else if(L.is_broken()) - safe_pressure_min *= 1.5 - else if(L.is_bruised()) - safe_pressure_min *= 1.25 - - var/safe_exhaled_max = 10 - var/safe_toxins_max = 0.2 - var/SA_para_min = 1 - var/SA_sleep_min = 5 - var/inhaled_gas_used = 0 - - var/breath_pressure = (breath.total_moles*R_IDEAL_GAS_EQUATION*breath.temperature)/(BREATH_VOLUME * species.breath_vol_mul) - - var/inhaling - var/poison - var/exhaling - - var/breath_type - var/poison_type - var/exhale_type - - var/failed_inhale = 0 - var/failed_exhale = 0 - - if(species.breath_type) - breath_type = species.breath_type - else - breath_type = "oxygen" - - inhaling = breath.gas[breath_type] - - if(species.poison_type) - poison_type = species.poison_type - else - poison_type = "phoron" - poison = breath.gas[poison_type] - - if(species.exhale_type) - exhale_type = species.exhale_type - exhaling = breath.gas[exhale_type] - else - exhaling = 0 - - var/inhale_pp = (inhaling/breath.total_moles)*breath_pressure - var/toxins_pp = (poison/breath.total_moles)*breath_pressure - var/exhaled_pp = (exhaling/breath.total_moles)*breath_pressure - - // Not enough to breathe - if(inhale_pp < safe_pressure_min) - if(prob(20)) - spawn(0) emote("gasp") - - var/ratio = inhale_pp/safe_pressure_min - // Don't fuck them up too fast (space only does HUMAN_MAX_OXYLOSS after all!) - adjustOxyLoss(max(HUMAN_MAX_OXYLOSS*(1-ratio), 0)) - failed_inhale = 1 - - oxygen_alert = max(oxygen_alert, 1) - else - // We're in safe limits - oxygen_alert = 0 - - inhaled_gas_used = inhaling/6 * (species?.breath_eff_mul || 1) - - breath.adjust_gas(breath_type, -inhaled_gas_used, update = 0) //update afterwards - - if(exhale_type) - breath.adjust_gas_temp(exhale_type, inhaled_gas_used, bodytemperature, update = 0) //update afterwards - - // Too much exhaled gas in the air - if(exhaled_pp > safe_exhaled_max) - if (!co2_alert|| prob(15)) - var/word = pick("extremely dizzy","short of breath","faint","confused") - to_chat(src, "You feel [word].") - - adjustOxyLoss(HUMAN_MAX_OXYLOSS) - co2_alert = 1 - failed_exhale = 1 - - else if(exhaled_pp > safe_exhaled_max * 0.7) - if (!co2_alert || prob(1)) - var/word = pick("dizzy","short of breath","faint","momentarily confused") - to_chat(src, "You feel [word].") - - //scale linearly from 0 to 1 between safe_exhaled_max and safe_exhaled_max*0.7 - var/ratio = 1.0 - (safe_exhaled_max - exhaled_pp)/(safe_exhaled_max*0.3) - - //give them some oxyloss, up to the limit - we don't want people falling unconcious due to CO2 alone until they're pretty close to safe_exhaled_max. - if (getOxyLoss() < 50*ratio) - adjustOxyLoss(HUMAN_MAX_OXYLOSS) - co2_alert = 1 - failed_exhale = 1 - - else if(exhaled_pp > safe_exhaled_max * 0.6) - if (prob(0.3)) - var/word = pick("a little dizzy","short of breath") - to_chat(src, "You feel [word].") - - else - co2_alert = 0 - - // Too much poison in the air. - if(toxins_pp > safe_toxins_max) - var/ratio = (poison/safe_toxins_max) * 10 - if(reagents) - reagents.add_reagent("toxin", Clamp(ratio, MIN_TOXIN_DAMAGE, MAX_TOXIN_DAMAGE)) - breath.adjust_gas(poison_type, -poison/6, update = 0) //update after - phoron_alert = max(phoron_alert, 1) - else - phoron_alert = 0 - - // If there's some other shit in the air lets deal with it here. - if(breath.gas["sleeping_agent"]) - var/SA_pp = (breath.gas["sleeping_agent"] / breath.total_moles) * breath_pressure - - // Enough to make us paralysed for a bit - if(SA_pp > SA_para_min) - - // 3 gives them one second to wake up and run away a bit! - Paralyse(3) - - // Enough to make us sleep as well - if(SA_pp > SA_sleep_min) - Sleeping(10) - - // There is sleeping gas in their lungs, but only a little, so give them a bit of a warning - else if(SA_pp > 0.15) - if(prob(20)) - spawn(0) emote(pick("giggle", "laugh")) - breath.adjust_gas("sleeping_agent", -breath.gas["sleeping_agent"]/6, update = 0) //update after - - // Were we able to breathe? - if (failed_inhale || failed_exhale) - failed_last_breath = 1 - else - failed_last_breath = 0 - if(disabilities & ASTHMA) - adjustOxyLoss(rand(-5,0)) - else - adjustOxyLoss(-5) - - - // Hot air hurts :( - if((breath.temperature < species.cold_level_1 || breath.temperature > species.heat_level_1) && !(COLD_RESISTANCE in mutations)) - - if(breath.temperature <= species.cold_level_1) - if(prob(20)) - to_chat(src, "You feel your face freezing and icicles forming in your lungs!") - else if(breath.temperature >= species.heat_level_1) - if(prob(20)) - to_chat(src, "You feel your face burning and a searing heat in your lungs!") - - if(breath.temperature >= species.heat_level_1) - if(breath.temperature < species.heat_level_2) - apply_damage(HEAT_GAS_DAMAGE_LEVEL_1, BURN, BP_HEAD, used_weapon = "Excessive Heat") - fire_alert = max(fire_alert, 2) - else if(breath.temperature < species.heat_level_3) - apply_damage(HEAT_GAS_DAMAGE_LEVEL_2, BURN, BP_HEAD, used_weapon = "Excessive Heat") - fire_alert = max(fire_alert, 2) - else - apply_damage(HEAT_GAS_DAMAGE_LEVEL_3, BURN, BP_HEAD, used_weapon = "Excessive Heat") - fire_alert = max(fire_alert, 2) - - else if(breath.temperature <= species.cold_level_1) - if(breath.temperature > species.cold_level_2) - apply_damage(COLD_GAS_DAMAGE_LEVEL_1, BURN, BP_HEAD, used_weapon = "Excessive Cold") - fire_alert = max(fire_alert, 1) - else if(breath.temperature > species.cold_level_3) - apply_damage(COLD_GAS_DAMAGE_LEVEL_2, BURN, BP_HEAD, used_weapon = "Excessive Cold") - fire_alert = max(fire_alert, 1) - else - apply_damage(COLD_GAS_DAMAGE_LEVEL_3, BURN, BP_HEAD, used_weapon = "Excessive Cold") - fire_alert = max(fire_alert, 1) - - //breathing in hot/cold air also heats/cools you a bit - var/temp_adj = breath.temperature - bodytemperature - if (temp_adj < 0) - temp_adj /= (BODYTEMP_COLD_DIVISOR * 5) //don't raise temperature as much as if we were directly exposed - else - temp_adj /= (BODYTEMP_HEAT_DIVISOR * 5) //don't raise temperature as much as if we were directly exposed - - var/relative_density = breath.total_moles / (MOLES_CELLSTANDARD * BREATH_PERCENTAGE) - temp_adj *= relative_density - - if (temp_adj > BODYTEMP_HEATING_MAX) temp_adj = BODYTEMP_HEATING_MAX - if (temp_adj < BODYTEMP_COOLING_MAX) temp_adj = BODYTEMP_COOLING_MAX - bodytemperature += temp_adj - - else if(breath.temperature >= species.heat_discomfort_level) - species.get_environment_discomfort(src,"heat") - else if(breath.temperature <= species.cold_discomfort_level) - species.get_environment_discomfort(src,"cold") - - breath.update_values() - return 1 - /mob/living/carbon/human/handle_environment(datum/gas_mixture/environment) if(!environment) return @@ -983,7 +746,7 @@ else //ALIVE. LIGHTS ARE ON updatehealth() //TODO - if(health <= config.health_threshold_dead || (species.has_organ[BP_BRAIN] && !has_brain() && !isonlifesupport())) + if(health <= config.health_threshold_dead || (species.has_organ[BP_BRAIN] && !has_brain())) death() blinded = 1 silent = 0 @@ -1384,63 +1147,6 @@ if(shock_stage >= 150) Weaken(20) -/mob/living/carbon/human/proc/handle_pulse() - if(life_tick % 5) return pulse //update pulse every 5 life ticks (~1 tick/sec, depending on server load) - - if(species && species.flags & NO_BLOOD) - return PULSE_NONE //No blood, no pulse. - - if(stat == DEAD) - return PULSE_NONE //that's it, you're dead, nothing can influence your pulse - - var/temp = PULSE_NORM - - if(round(vessel.get_reagent_amount("blood")) <= BLOOD_VOLUME_BAD) //how much blood do we have - temp = PULSE_THREADY //not enough :( - - if(status_flags & FAKEDEATH) - temp = PULSE_NONE //pretend that we're dead. unlike actual death, can be inflienced by meds - - //handles different chems' influence on pulse - for(var/datum/reagent/R in reagents.reagent_list) - if(R.id in bradycardics) - if(temp <= PULSE_THREADY && temp >= PULSE_NORM) - temp-- - if(R.id in tachycardics) - if(temp <= PULSE_FAST && temp >= PULSE_NONE) - temp++ - if(R.id in heartstopper) //To avoid using fakedeath - var/obj/item/organ/internal/heart/H = internal_organs_by_name[BP_HEART] - if(rand(0,6) == 3) - H.take_damage(5) - if(R.id in cheartstopper) //Conditional heart-stoppage - if(R.volume >= R.overdose) - var/obj/item/organ/internal/heart/H = internal_organs_by_name[BP_HEART] - if(rand(0,6) == 3) - H.take_damage(5) - - return temp - -/mob/living/carbon/human/proc/handle_heartbeat() - if(pulse == PULSE_NONE || !species.has_organ[BP_HEART]) - return - - var/obj/item/organ/internal/heart/H = internal_organs_by_name[BP_HEART] - - if(!H || H.robotic >=2 ) - return - - if(pulse >= PULSE_2FAST || shock_stage >= 10 || istype(get_turf(src), /turf/space)) - //PULSE_THREADY - maximum value for pulse, currently it 5. - //High pulse value corresponds to a fast rate of heartbeat. - //Divided by 2, otherwise it is too slow. - var/rate = (PULSE_THREADY - pulse)/2 - - if(heartbeat >= rate) - heartbeat = 0 - src << sound('sound/effects/singlebeat.ogg',0,0,0,50) - else - heartbeat++ /* Called by life(), instead of having the individual hud items update icons each tick and check for status changes @@ -1749,15 +1455,4 @@ damageoverlay.cut_overlay(last_oxy_overlay) last_oxy_overlay = null -//////////////// -//BRAIN DAMAGE// -//////////////// -/mob/living/carbon/human/proc/handle_brain_damage() - for(var/T in get_traumas()) - var/datum/brain_trauma/BT = T - if(!BT.suppressed) - BT.on_life() - -#undef HUMAN_MAX_OXYLOSS -#undef HUMAN_CRIT_MAX_OXYLOSS diff --git a/code/modules/mob/living/carbon/human/species/outsider/vox.dm b/code/modules/mob/living/carbon/human/species/outsider/vox.dm index 8c536c1aede..7d5ec0c69f2 100644 --- a/code/modules/mob/living/carbon/human/species/outsider/vox.dm +++ b/code/modules/mob/living/carbon/human/species/outsider/vox.dm @@ -109,7 +109,7 @@ BP_LUNGS = /obj/item/organ/internal/lungs/vox, BP_LIVER = /obj/item/organ/internal/liver/vox, BP_KIDNEYS = /obj/item/organ/internal/kidneys/vox, - BP_BRAIN = /obj/item/organ/internal/pariah_brain, + BP_BRAIN = /obj/item/organ/pariah_brain, BP_EYES = /obj/item/organ/internal/eyes ) spawn_flags = IS_RESTRICTED diff --git a/code/modules/organs/blood.dm b/code/modules/organs/blood.dm index 92908785cb9..db2ffb5a381 100644 --- a/code/modules/organs/blood.dm +++ b/code/modules/organs/blood.dm @@ -9,7 +9,6 @@ var/const/BLOOD_VOLUME_BAD = 224 var/const/BLOOD_VOLUME_SURVIVE = 122 /mob/living/carbon/human/var/datum/reagents/vessel //Container for blood and BLOOD ONLY. Do not transfer other chems here. -/mob/living/carbon/human/var/var/pale = 0 //Should affect how mob sprite is drawn, but currently doesn't. //Initializes blood vessels /mob/living/carbon/human/proc/make_blood() @@ -43,140 +42,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122 ) B.color = B.data["blood_colour"] -// Takes care blood loss and regeneration -/mob/living/carbon/human/handle_blood() - if(in_stasis) - return - - if(species && species.flags & NO_BLOOD) - return - - if(stat != DEAD && bodytemperature >= 170) //Dead or cryosleep people do not pump the blood. - var/blood_volume = round(vessel.get_reagent_amount("blood")) - - //Blood regeneration if there is some space - if(blood_volume < BLOOD_VOLUME_NORMAL && blood_volume) - var/datum/reagent/blood/B = locate() in vessel.reagent_list //Grab some blood - if(B) // Make sure there's some blood at all - if(weakref && B.data["donor"] != weakref) //If it's not theirs, then we look for theirs - donor is a weakref here, but it should be safe to just directly compare it. - for(var/datum/reagent/blood/D in vessel.reagent_list) - if(weakref && D.data["donor"] == weakref) - B = D - break - - B.volume += 0.1 // regenerate blood VERY slowly - if(blood_volume <= BLOOD_VOLUME_SAFE) //We loose nutrition and hydration very slowly if our blood is too low - adjustNutritionLoss(2) - adjustHydrationLoss(1) - if(CE_BLOODRESTORE in chem_effects) - B.volume += chem_effects[CE_BLOODRESTORE] - - //The heartfix to end all heartfixes - if(species && species.has_organ[BP_HEART]) - var/obj/item/organ/internal/heart/heart = internal_organs_by_name[BP_HEART] - // Before we do that, we check for lifesupport. - var/onlifesupport = 0 - if (buckled && istype(buckled, /obj/machinery/optable/lifesupport)) - var/obj/machinery/optable/lifesupport/A = buckled - onlifesupport = A.onlifesupport() - - - if (!onlifesupport) - if(!heart) - blood_volume = 0 - else if (heart.is_damaged()) - blood_volume = min(BLOOD_VOLUME_SAFE - 1,blood_volume) - blood_volume = (BLOOD_VOLUME_SURVIVE + (BLOOD_VOLUME_NORMAL-BLOOD_VOLUME_SURVIVE) * max(1 - heart.damage/heart.min_broken_damage,0)) * (blood_volume/BLOOD_VOLUME_NORMAL) - - //Effects of bloodloss - if(blood_volume < BLOOD_VOLUME_SAFE && oxyloss < 100 * (1 - blood_volume/BLOOD_VOLUME_NORMAL)) - oxyloss += 3 - - switch(blood_volume) - if(BLOOD_VOLUME_SAFE to 10000) - if(pale) - pale = 0 - update_body() - if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE) - if(!pale) - pale = 1 - update_body() - var/word = pick("dizzy","woosey","faint") - to_chat(src, "You feel [word]...") - if(prob(1)) - var/word = pick("dizzy","woosey","faint") - to_chat(src, "You feel [word]...") - if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY) - if(!pale) - pale = 1 - update_body() - eye_blurry = max(eye_blurry,6) - oxyloss += 1 - if(prob(15)) - Paralyse(rand(1,3)) - var/word = pick("dizzy","woosey","faint") - to_chat(src, "You feel extremely [word]...") - if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD) - oxyloss += 3 - toxloss += 3 - if(prob(15)) - var/word = pick("dizzy","woosey","faint") - to_chat(src, "You feel extremely [word]...") - if(0 to BLOOD_VOLUME_SURVIVE) - // There currently is a strange bug here. If the mob is not below -100 health - // when death() is called, apparently they will be just fine, and this way it'll - // spam deathgasp. Adjusting toxloss ensures the mob will stay dead. - toxloss += 300 // just to be safe! - death() - - //Bleeding out - var/blood_max = 0 - var/open_wound - var/list/do_spray = list() - for(var/obj/item/organ/external/temp in organs) - if(!(temp.status & ORGAN_BLEEDING) || temp.status & ORGAN_ROBOT) - continue - for(var/datum/wound/W in temp.wounds) - if(W.bleeding()) - open_wound = TRUE - if(temp.applied_pressure) - if(ishuman(temp.applied_pressure)) - var/mob/living/carbon/human/H = temp.applied_pressure - H.bloody_hands(src, 0) - var/min_eff_damage = max(0, W.damage - 10) / 6 - blood_max += max(min_eff_damage, W.damage - 30) / 40 - else - blood_max += ((W.damage / 40) * species.bleed_mod) - if(temp.status & ORGAN_ARTERY_CUT) - var/bleed_amount = Floor(vessel.total_volume / (temp.applied_pressure || !open_wound ? 450 : 300)) - if(bleed_amount) - if(open_wound) - blood_max += bleed_amount - do_spray += temp.name - else - blood_max += W.damage / 40 - if (temp.open) - blood_max += 2 * species.bleed_mod //Yer stomach is cut open - - if(world.time >= next_blood_squirt && istype(loc, /turf) && do_spray.len) - visible_message("Blood squirts from \the [src]'s [pick(do_spray)]!", "Blood is squirting out of your [pick(do_spray)]!") - eye_blurry = 2 - Stun(1) - next_blood_squirt = world.time + 100 - var/turf/sprayloc = get_turf(src) - blood_max -= drip(Ceiling(blood_max/3), sprayloc) - if(blood_max > 0) - blood_max -= blood_squirt(blood_max, sprayloc) - if(blood_max > 0) - drip(blood_max, get_turf(src)) - else - drip(blood_max) - -/mob/living/carbon/human - var/next_blood_squirt = 0 - //Makes a blood drop, leaking amt units of blood from the mob - /mob/living/carbon/human/proc/drip(var/amt as num, var/tar = src, var/spraydir) if(species && species.flags & NO_BLOOD) //TODO: Make drips come from the reagents instead. diff --git a/code/modules/organs/internal/brain.dm b/code/modules/organs/internal/brain.dm index e69de29bb2d..ad4f348cc58 100644 --- a/code/modules/organs/internal/brain.dm +++ b/code/modules/organs/internal/brain.dm @@ -0,0 +1,74 @@ +/obj/item/organ/internal/brain + name = "brain" + health = 400 //They need to live awhile longer than other organs. Is this even used by organ code anymore? + desc = "A piece of juicy meat found in a person's head." + organ_tag = BP_BRAIN + parent_organ = BP_HEAD + vital = 1 + icon_state = "brain" + force = 1.0 + w_class = 2.0 + throwforce = 1.0 + throw_speed = 3 + throw_range = 5 + origin_tech = list(TECH_BIO = 3) + attack_verb = list("attacked", "slapped", "whacked") + var/mob/living/carbon/brain/brainmob = null + var/list/datum/brain_trauma/traumas = list() + var/lobotomized = 0 + var/can_lobotomize = 1 + +/obj/item/organ/internal/brain/process() + ..() + + if(!owner) + return + + if(lobotomized && (owner.getBrainLoss() < 40)) //lobotomized brains cannot be healed with chemistry. Part of the brain is irrevocably missing. Can be fixed magically with cloning, ofc. + owner.setBrainLoss(40) + + for(var/T in owner.get_traumas()) + var/datum/brain_trauma/BT = T + if(!BT.suppressed) + BT.on_life() + + var/blood_volume = round(owner.vessel.get_reagent_amount("blood")) + switch(blood_volume) + if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE) + var/word = pick("dizzy","woosey","faint") + to_chat(owner, "You feel [word]...") + if(prob(1)) + word = pick("dizzy","woosey","faint") + to_chat(owner, "You feel [word]...") + if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY) + owner.eye_blurry = max(owner.eye_blurry,6) + owner.oxyloss += 1 + if(prob(15)) + owner.Paralyse(rand(1,3)) + var/word = pick("dizzy","woosey","faint") + to_chat(owner, "You feel extremely [word]...") + if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD) + owner.oxyloss += 3 + owner.toxloss += 3 + if(prob(15)) + var/word = pick("dizzy","woosey","faint") + to_chat(owner, "You feel extremely [word]...") + if(0 to BLOOD_VOLUME_SURVIVE) + // There currently is a strange bug here. If the mob is not below -100 health + // when death() is called, apparently they will be just fine, and this way it'll + // spam deathgasp. Adjusting toxloss ensures the mob will stay dead. + owner.toxloss += 300 // just to be safe! + owner.death() + + if(owner.species.has_organ[BP_HEART]) //This is where the bad times start if you have no heart. + var/obj/item/organ/internal/heart/H = owner.internal_organs_by_name[BP_HEART] + if(!istype(H)) + var/damprob + owner.eye_blurry = max(owner.eye_blurry,6) + damprob = owner.chem_effects[CE_STABLE] ? 80 : 100 + if(prob(10)) + to_chat(owner, "You jerk and gasp for breath, yet you still feel like you're suffocating!") + owner.emote("jerks and gasps!") + if(prob(damprob)) + owner.adjustOxyLoss(15) + diff --git a/code/modules/organs/internal/heart.dm b/code/modules/organs/internal/heart.dm index 0ab28e6d085..76e92cdc7ce 100644 --- a/code/modules/organs/internal/heart.dm +++ b/code/modules/organs/internal/heart.dm @@ -6,10 +6,149 @@ dead_icon = "heart-off" robotic_name = "circulatory pump" robotic_sprite = "heart-prosthetic" + var/pulse = PULSE_NORM //current pulse level + var/heartbeat = 0 + var/next_blood_squirt = 0 /obj/item/organ/internal/heart/process() - //Check if we're on lifesupport, and whether or not organs should be processing. - if(owner && owner.isonlifesupport()) - return 1 - else - return 0 \ No newline at end of file + if(owner) + handle_pulse() + if(pulse) + handle_heartbeat() + handle_blood() + ..() + +/obj/item/organ/internal/heart/proc/handle_pulse() + if((species && species.flags & NO_BLOOD)) //No heart, no pulse, buddy. + pulse = PULSE_NONE + + var/temp = PULSE_NORM + + if(round(owner.vessel.get_reagent_amount("blood")) <= BLOOD_VOLUME_BAD) //how much blood do we have + temp = PULSE_THREADY //not enough :( + + if(owner.status_flags & FAKEDEATH) + temp = PULSE_NONE //pretend that we're dead. unlike actual death, can be inflienced by meds + + //handles different chems' influence on pulse + for(var/datum/reagent/R in owner.reagents.reagent_list) + if(R.id in bradycardics) + if(temp <= PULSE_THREADY && temp >= PULSE_NORM) + temp-- + if(R.id in tachycardics) + if(temp <= PULSE_FAST && temp >= PULSE_NONE) + temp++ + if(R.id in heartstopper) //To avoid using fakedeath + if(rand(0,6) == 3) + take_internal_damage(5) + if(R.id in cheartstopper) //Conditional heart-stoppage + if(R.volume >= R.overdose) + if(rand(0,6) == 3) + take_internal_damage(5) + + pulse = temp + +/obj/item/organ/internal/heart/proc/handle_heartbeat() + if(pulse == PULSE_NONE || !owner.species.has_organ[BP_HEART]) + return + + if(!src || status & ORGAN_ROBOT) + return + + if(pulse >= PULSE_2FAST || owner.shock_stage >= 10 || istype(get_turf(src), /turf/space)) + //PULSE_THREADY - maximum value for pulse, currently it 5. + //High pulse value corresponds to a fast rate of heartbeat. + //Divided by 2, otherwise it is too slow. + var/rate = (PULSE_THREADY - pulse) / 2 + + if(heartbeat >= rate) + heartbeat = 0 + sound_to(owner, sound('sound/effects/singlebeat.ogg', 0, 0, 0, 50)) + else + heartbeat++ + +/obj/item/organ/internal/heart/proc/handle_blood() + if(owner.in_stasis) + return + + if(owner.species && owner.species.flags & NO_BLOOD) + return + + if(owner.stat == DEAD && owner.bodytemperature < 170) //Dead or cryosleep people do not pump the blood. + return + + if(pulse != PULSE_NONE || BP_IS_ROBOTIC(src)) + var/blood_volume = round(owner.vessel.get_reagent_amount("blood")) + + //Blood regeneration if there is some space + if(blood_volume < BLOOD_VOLUME_NORMAL && blood_volume) + var/datum/reagent/blood/B = locate() in owner.vessel.reagent_list //Grab some blood + if(B) // Make sure there's some blood at all + if(weakref && B.data["donor"] != weakref) //If it's not theirs, then we look for theirs - donor is a weakref here, but it should be safe to just directly compare it. + for(var/datum/reagent/blood/D in owner.vessel.reagent_list) + if(weakref && D.data["donor"] == weakref) + B = D + break + + B.volume += 0.1 // regenerate blood VERY slowly + if(blood_volume <= BLOOD_VOLUME_SAFE) //We loose nutrition and hydration very slowly if our blood is too low + owner.adjustNutritionLoss(2) + owner.adjustHydrationLoss(1) + if(CE_BLOODRESTORE in owner.chem_effects) + B.volume += owner.chem_effects[CE_BLOODRESTORE] + + //Effects of bloodloss + if(blood_volume < BLOOD_VOLUME_SAFE && owner.oxyloss < 100 * (1 - blood_volume/BLOOD_VOLUME_NORMAL)) + owner.oxyloss += 3 + + //Bleeding out + var/blood_max = 0 + var/open_wound + var/list/do_spray = list() + for(var/obj/item/organ/external/temp in owner.organs) + if((temp.status & ORGAN_BLEEDING) && !BP_IS_ROBOTIC(temp)) + for(var/datum/wound/W in temp.wounds) + if(W.bleeding()) + open_wound = TRUE + if(temp.applied_pressure) + if(ishuman(temp.applied_pressure)) + var/mob/living/carbon/human/H = temp.applied_pressure + H.bloody_hands(src, 0) + var/min_eff_damage = max(0, W.damage - 10) / 6 + blood_max += max(min_eff_damage, W.damage - 30) / 40 + else + blood_max += ((W.damage / 40) * species.bleed_mod) + + if(temp.status & ORGAN_ARTERY_CUT) + var/bleed_amount = Floor(owner.vessel.total_volume / (temp.applied_pressure || !open_wound ? 450 : 300)) + if(bleed_amount) + if(open_wound) + blood_max += bleed_amount + do_spray += "[temp.name]" + else + owner.vessel.remove_reagent("blood", bleed_amount) + + switch(pulse) + if(PULSE_SLOW) + blood_max *= 0.8 + if(PULSE_FAST) + blood_max *= 1.25 + if(PULSE_2FAST, PULSE_THREADY) + blood_max *= 1.5 + + if(CE_STABLE in owner.chem_effects) + blood_max *= 0.8 + + if(world.time >= next_blood_squirt && istype(owner.loc, /turf) && do_spray.len) + owner.visible_message("Blood squirts from \the [owner]'s [pick(do_spray)]!", "Blood is squirting out of your [pick(do_spray)]!") + owner.eye_blurry = 2 + owner.Stun(1) + next_blood_squirt = world.time + 100 + var/turf/sprayloc = get_turf(src) + blood_max -= owner.drip(Ceiling(blood_max/3), sprayloc) + if(blood_max > 0) + blood_max -= owner.blood_squirt(blood_max, sprayloc) + if(blood_max > 0) + owner.drip(blood_max, get_turf(src)) + else + owner.drip(blood_max) \ No newline at end of file diff --git a/code/modules/organs/internal/lungs.dm b/code/modules/organs/internal/lungs.dm index 7629f998c5f..ac82af879ec 100644 --- a/code/modules/organs/internal/lungs.dm +++ b/code/modules/organs/internal/lungs.dm @@ -1,3 +1,6 @@ +#define HUMAN_MAX_OXYLOSS 1 //Defines how much oxyloss humans can get per tick. A tile with no air at all (such as space) applies this value, otherwise it's a percentage of it. +#define HUMAN_CRIT_MAX_OXYLOSS ( 2.0 / 6) //The amount of damage you'll get when in critical condition. We want this to be a 5 minute deal = 300s. There are 50HP to get through, so (1/6)*last_tick_duration per second. Breaths however only happen every 4 ticks. last_tick_duration = ~2.0 on average + /obj/item/organ/internal/lungs name = "lungs" icon_state = "lungs" @@ -30,4 +33,233 @@ if(prob(4)) to_chat(owner, span("warning", "It feels hard to breathe...")) if (owner.losebreath < 5) - owner.losebreath = min(owner.losebreath + 1, 5) // it's still not good, but it's much better than an untreated collapsed lung \ No newline at end of file + owner.losebreath = min(owner.losebreath + 1, 5) // it's still not good, but it's much better than an untreated collapsed lung + +/obj/item/organ/internal/lungs/proc/handle_breath(datum/gas_mixture/breath) + if(!owner) + return 1 + + //exposure to extreme pressures can rupture lungs + if(breath && (breath.total_moles/(owner.species?.breath_vol_mul || 1) < BREATH_MOLES / 5 || breath.total_moles/(owner.species?.breath_vol_mul || 1) > BREATH_MOLES * 5)) + if(!is_bruised() && prob(5)) + bruise() + + //check if we actually need to process breath + if(!breath || (breath.total_moles == 0)) + owner.failed_last_breath = 1 + if(owner.health > config.health_threshold_crit) + owner.adjustOxyLoss(HUMAN_MAX_OXYLOSS) + else + owner.adjustOxyLoss(HUMAN_CRIT_MAX_OXYLOSS) + + owner.oxygen_alert = max(owner.oxygen_alert, 1) + return 0 + + var/safe_pressure_min = owner.species.breath_pressure // Minimum safe partial pressure of breathable gas in kPa + + if(is_broken()) + safe_pressure_min *= 1.5 + else if(is_bruised()) + safe_pressure_min *= 1.25 + + var/safe_exhaled_max = 10 + var/safe_toxins_max = 0.2 + var/SA_para_min = 1 + var/SA_sleep_min = 5 + var/inhaled_gas_used = 0 + + var/breath_pressure = (breath.total_moles*R_IDEAL_GAS_EQUATION*breath.temperature)/(BREATH_VOLUME * owner.species.breath_vol_mul) + + var/inhaling + var/poison + var/exhaling + + var/breath_type + var/poison_type + var/exhale_type + + var/failed_inhale = 0 + var/failed_exhale = 0 + + if(owner.species.breath_type) + breath_type = species.breath_type + else + breath_type = "oxygen" + + inhaling = breath.gas[breath_type] + + if(owner.species.poison_type) + poison_type = species.poison_type + else + poison_type = "phoron" + poison = breath.gas[poison_type] + + if(owner.species.exhale_type) + exhale_type = species.exhale_type + exhaling = breath.gas[exhale_type] + else + exhaling = 0 + + var/inhale_pp = (inhaling/breath.total_moles)*breath_pressure + var/toxins_pp = (poison/breath.total_moles)*breath_pressure + var/exhaled_pp = (exhaling/breath.total_moles)*breath_pressure + + // Not enough to breathe + if(inhale_pp < safe_pressure_min) + if(prob(20)) + spawn(0) + owner.emote("gasp") + + var/ratio = inhale_pp/safe_pressure_min + // Don't fuck them up too fast (space only does HUMAN_MAX_OXYLOSS after all!) + owner.adjustOxyLoss(max(HUMAN_MAX_OXYLOSS*(1-ratio), 0)) + failed_inhale = 1 + + owner.oxygen_alert = max(owner.oxygen_alert, 1) + else + // We're in safe limits + owner.oxygen_alert = 0 + + inhaled_gas_used = inhaling/6 * (owner.species?.breath_eff_mul || 1) + + breath.adjust_gas(breath_type, -inhaled_gas_used, update = 0) //update afterwards + + if(exhale_type) + breath.adjust_gas_temp(exhale_type, inhaled_gas_used, owner.bodytemperature, update = 0) //update afterwards + + // Too much exhaled gas in the air + if(exhaled_pp > safe_exhaled_max) + if (!owner.co2_alert|| prob(15)) + var/word = pick("extremely dizzy","short of breath","faint","confused") + to_chat(owner, "You feel [word].") + + owner.adjustOxyLoss(HUMAN_MAX_OXYLOSS) + owner.co2_alert = 1 + failed_exhale = 1 + + else if(exhaled_pp > safe_exhaled_max * 0.7) + if (!owner.co2_alert || prob(1)) + var/word = pick("dizzy","short of breath","faint","momentarily confused") + to_chat(owner, "You feel [word].") + + //scale linearly from 0 to 1 between safe_exhaled_max and safe_exhaled_max*0.7 + var/ratio = 1.0 - (safe_exhaled_max - exhaled_pp)/(safe_exhaled_max*0.3) + + //give them some oxyloss, up to the limit - we don't want people falling unconcious due to CO2 alone until they're pretty close to safe_exhaled_max. + if (owner.getOxyLoss() < 50*ratio) + owner.adjustOxyLoss(HUMAN_MAX_OXYLOSS) + owner.co2_alert = 1 + failed_exhale = 1 + + else if(exhaled_pp > safe_exhaled_max * 0.6) + if (prob(0.3)) + var/word = pick("a little dizzy","short of breath") + to_chat(owner, "You feel [word].") + + else + owner.co2_alert = 0 + + // Too much poison in the air. + if(toxins_pp > safe_toxins_max) + var/ratio = (poison/safe_toxins_max) * 10 + if(reagents) + reagents.add_reagent("toxin", Clamp(ratio, MIN_TOXIN_DAMAGE, MAX_TOXIN_DAMAGE)) + breath.adjust_gas(poison_type, -poison/6, update = 0) //update after + owner.phoron_alert = max(owner.phoron_alert, 1) + else + owner.phoron_alert = 0 + + // If there's some other shit in the air lets deal with it here. + if(breath.gas["sleeping_agent"]) + var/SA_pp = (breath.gas["sleeping_agent"] / breath.total_moles) * breath_pressure + + // Enough to make us paralysed for a bit + if(SA_pp > SA_para_min) + + // 3 gives them one second to wake up and run away a bit! + owner.Paralyse(3) + + // Enough to make us sleep as well + if(SA_pp > SA_sleep_min) + owner.Sleeping(10) + + // There is sleeping gas in their lungs, but only a little, so give them a bit of a warning + else if(SA_pp > 0.15) + if(prob(20)) + spawn(0) + owner.emote(pick("giggle", "laugh")) + breath.adjust_gas("sleeping_agent", -breath.gas["sleeping_agent"]/6, update = 0) //update after + + // Were we able to breathe? + if (failed_inhale || failed_exhale) + owner.failed_last_breath = 1 + else + owner.failed_last_breath = 0 + if(owner.disabilities & ASTHMA) + owner.adjustOxyLoss(rand(-5,0)) + else + owner.adjustOxyLoss(-5) + + + // Hot air hurts :( + handle_temperature_effects(breath) + + breath.update_values() + + var/failed_breath = failed_inhale || failed_exhale + + return failed_breath + +/obj/item/organ/internal/lungs/proc/handle_temperature_effects(datum/gas_mixture/breath) + if((breath.temperature < species.cold_level_1 || breath.temperature > species.heat_level_1) && !(COLD_RESISTANCE in owner.mutations)) + + if(breath.temperature <= owner.species.cold_level_1) + if(prob(20)) + to_chat(owner, "You feel your face freezing and icicles forming in your lungs!") + else if(breath.temperature >= owner.species.heat_level_1) + if(prob(20)) + to_chat(owner, "You feel your face burning and a searing heat in your lungs!") + + if(breath.temperature >= owner.species.heat_level_1) + if(breath.temperature < owner.species.heat_level_2) + owner.apply_damage(HEAT_GAS_DAMAGE_LEVEL_1, BURN, BP_HEAD, used_weapon = "Excessive Heat") + owner.fire_alert = max(owner.fire_alert, 2) + else if(breath.temperature < species.heat_level_3) + owner.apply_damage(HEAT_GAS_DAMAGE_LEVEL_2, BURN, BP_HEAD, used_weapon = "Excessive Heat") + owner.fire_alert = max(owner.fire_alert, 2) + else + owner.apply_damage(HEAT_GAS_DAMAGE_LEVEL_3, BURN, BP_HEAD, used_weapon = "Excessive Heat") + owner.fire_alert = max(owner.fire_alert, 2) + + else if(breath.temperature <= owner.species.cold_level_1) + if(breath.temperature > species.cold_level_2) + owner.apply_damage(COLD_GAS_DAMAGE_LEVEL_1, BURN, BP_HEAD, used_weapon = "Excessive Cold") + owner.fire_alert = max(owner.fire_alert, 1) + else if(breath.temperature > species.cold_level_3) + owner.apply_damage(COLD_GAS_DAMAGE_LEVEL_2, BURN, BP_HEAD, used_weapon = "Excessive Cold") + owner.fire_alert = max(owner.fire_alert, 1) + else + owner.apply_damage(COLD_GAS_DAMAGE_LEVEL_3, BURN, BP_HEAD, used_weapon = "Excessive Cold") + owner.fire_alert = max(owner.fire_alert, 1) + + //breathing in hot/cold air also heats/cools you a bit + var/temp_adj = breath.temperature - owner.bodytemperature + if (temp_adj < 0) + temp_adj /= (BODYTEMP_COLD_DIVISOR * 5) //don't raise temperature as much as if we were directly exposed + else + temp_adj /= (BODYTEMP_HEAT_DIVISOR * 5) //don't raise temperature as much as if we were directly exposed + + var/relative_density = breath.total_moles / (MOLES_CELLSTANDARD * BREATH_PERCENTAGE) + temp_adj *= relative_density + + if (temp_adj > BODYTEMP_HEATING_MAX) temp_adj = BODYTEMP_HEATING_MAX + if (temp_adj < BODYTEMP_COOLING_MAX) temp_adj = BODYTEMP_COOLING_MAX + owner.bodytemperature += temp_adj + + else if(breath.temperature >= owner.species.heat_discomfort_level) + owner.species.get_environment_discomfort(src,"heat") + else if(breath.temperature <= owner.species.cold_discomfort_level) + owner.species.get_environment_discomfort(src,"cold") + +#undef HUMAN_MAX_OXYLOSS +#undef HUMAN_CRIT_MAX_OXYLOSS \ No newline at end of file diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index 3d08d05e052..71b1c58ffe9 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -363,9 +363,6 @@ owner.update_action_buttons() owner = null - if(!owner.isonlifesupport()) - owner.death() - /obj/item/organ/proc/replaced(var/mob/living/carbon/human/target,var/obj/item/organ/external/affected) if(!istype(target)) return diff --git a/code/modules/research/designs/circuit_designs.dm b/code/modules/research/designs/circuit_designs.dm index 51bd7a1f4da..5a439d4afc4 100644 --- a/code/modules/research/designs/circuit_designs.dm +++ b/code/modules/research/designs/circuit_designs.dm @@ -73,12 +73,6 @@ build_path = /obj/item/circuitboard/operating sort_string = "FACAA" -/datum/design/circuit/operatingadv - name = "life support console" - id = "operatingadv" - build_path = /obj/item/circuitboard/advoperating - sort_string = "FACAB" - /datum/design/circuit/pandemic name = "PanD.E.M.I.C. 2200" id = "pandemic" @@ -281,15 +275,6 @@ build_path = /obj/item/circuitboard/optable sort_string = "HACAH" - -/datum/design/circuit/optable - name = "advanced operation table scanning board" - id = "advoptable_board" - req_tech = list(TECH_BIO = 4, TECH_ENGINEERING = 5) - build_path = /obj/item/circuitboard/optableadv - sort_string = "HACAI" - - /datum/design/circuit/smartfridge name = "smart fridge board" id = "fridge_board" diff --git a/html/changelogs/mattatlas-fromtheashesofcalamity.yml b/html/changelogs/mattatlas-fromtheashesofcalamity.yml new file mode 100644 index 00000000000..94e751a1ad5 --- /dev/null +++ b/html/changelogs/mattatlas-fromtheashesofcalamity.yml @@ -0,0 +1,48 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +# balance +# admin +# backend +# security +# refactor +################################# + +# Your name. +author: MattAtlas + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - experiment: "Several backend changes regarding human processing." + - rscadd: "Your heart now handles your blood! If you have no heart, well... you're not gonna bleed, but you're gonna die fast." + - bugfix: "Fixed a few runtimes." + - bugfix: "Fixed a few issues with arterial bleeding." + - tweak: "Some pain messages have been tweaked." + - rscadd: "You should now lose more or less blood depending on your pulse." + - tweak: "Losing your lungs and your heart is now more severe. Don't lose either one or you'll have a really hard time living." + - rscadd: "Removed advanced operating tables. They didn't work." \ No newline at end of file diff --git a/nano/templates/operating_computer.tmpl b/nano/templates/operating_computer.tmpl deleted file mode 100644 index df67237b4aa..00000000000 --- a/nano/templates/operating_computer.tmpl +++ /dev/null @@ -1,260 +0,0 @@ - -{{if !data.table}} -
-






No connected table detected! -
-{{else}} - {{if data.screen == 1}} -
-

Patient Information:

- - {{if data.patientgeneral && data.patienthealth}} - -
-
- Name: -
-
- {{:data.patientgeneral.Name}} -
-
-
-
- Age: -
-
- {{:data.patientgeneral.Age}} -
-
-
-
- Blood Type: -
-
- {{:data.patientgeneral.BloodType}} -
-
- -
-
- Health: -
-
- {{:data.patienthealth.Health}} -
-
-
-
- Brute Damage: -
-
- {{:data.patienthealth.Brute}} -
-
-
-
- Toxins Damage: -
-
- {{:data.patienthealth.Toxins}} -
-
-
-
- Burn Damage: -
-
- {{:data.patienthealth.Burn}} -
-
-
-
- Suffocation Damage: -
-
- {{:data.patienthealth.Suffocation}} -
-
-
-
- Status: -
-
- {{:data.patienthealth.Status}} -
-
-
-
- Heartbeat Rate: -
-
- {{:data.patienthealth.Heartrate}} bpm -
-
- {{if data.table == 2}} -
-
- Blood Level: -
-
- {{:data.patienthealth.BloodLevel}} cl -
-
- {{/if}} - {{else}} -
- No Patient Detected! -
- {{/if}} -
- - {{if data.table == 2}} -
-

Life Support Systems Detected

-

Machine Information:

- -
-
- Restraints: -
-
- {{:data.buckled ? 'Active' : 'Inactive'}} -
-
- -
-
- Life Support Systems: -
-
- {{:data.lifesupport ? 'Enabled' : 'Disabled'}} -
-
- {{:helper.link(data.lifesupport ? 'Disable Life Support' : 'Enable Life Support', data.lifesupport ? 'close' : 'check', {'toggle_lifesupport' : 1}, null)}} -
-
- -
-
- Stored Chemicals -
-
- {{:helper.link('Flush Chemicals', 'eject', {'eject_advanced' : 'chems'}, data.hasreagents ? null : 'disabled', 'floatRight')}} -
-
- - {{if data.hasreagents}} -
-
-
- {{for data.loadedreagents}} - {{:value.volume}} units of {{:value.name}}
- {{/for}} -
-
-
- {{else}} -
- No chemicals stored! -
- {{/if}} - -
-
- Internal Air Tank -
-
- {{:helper.link('Eject Air Tank', 'eject', {'eject_advanced' : 'airsupply'}, data.hasair ? null : 'disabled', 'floatRight')}} -
-
- - {{if data.hasair}} -
-
-
- Tank Internal Pressure: {{:data.air.internalpressure}} kPa
- Tank Release Pressure: {{:data.air.releasepressure}} kPa -
-
-
- {{else}} -
- No air tank detected! -
- {{/if}} - -
-
- Internal Blood Supply -
-
- {{:helper.link('Eject Blood Bag', 'eject', {'eject_advanced' : 'bloodbag'}, data.hasblood ? null : 'disabled', 'floatRight')}} -
-
- - {{if data.hasblood}} -
-
-
- Stored Volume: {{:data.blood.volume}}
- Blood Type: {{:data.blood.type}} -
-
-
- {{else}} -
- No blood bag detected! -
- {{/if}} - -

Programming Information:

- -
-
-
Transfusion Control:
-
{{:helper.link(data.program.autotransfuse ? 'Automated' : 'Manually Controlled', 'refresh', {'toggle_program' : 'AUTO_TRANSFUSE'}, null)}}
-
-
-
Transfusion:
-
{{:helper.link(data.program.transfuseactive ? 'Activated' : 'Deactivated', 'refresh', {'toggle_program' : 'TRANSFUSE_ACTIVE'}, data.program.autotransfuse ? 'disabled' : null)}}
-
-
-
Air Control:
-
{{:helper.link(data.program.autoair ? 'Automated' : 'Manually Controlled', 'refresh', {'toggle_program' : 'AUTO_AIR'}, null)}}
-
-
-
Air Status:
-
{{:helper.link(data.program.airactive ? 'Activated' : 'Deactivated', 'refresh', {'toggle_program' : 'AIR_ACTIVE'}, data.program.autoair ? 'disabled' : null)}}
-
- {{if data.program.emagged}} -
-
Blood Syphons:
-
{{:helper.link(data.program.purge ? 'Activated' : 'Deactivated', 'refresh', {'toggle_program' : 'PURGE'})}}
-
- {{/if}} -
- - {{:helper.link('Show Logs', 'gear', {'select_screen' : '2'})}} -
- {{/if}} - {{else data.screen == 2}} - {{:helper.link('Main Menu', 'gear', {'select_screen' : '1'})}} - {{:helper.link('Clear Log', 'gear', {'clear_log' : '1'})}} - - {{if data.log}} - - - - - - {{for data.log}} - - {{/for}} - -
Timestamp:Message:
{{:value.time}}{{:value.message}}
- {{/if}} - {{/if}} -{{/if}} \ No newline at end of file