From d581ebe76762dc7d8d1719dc8976881782756d25 Mon Sep 17 00:00:00 2001 From: cib Date: Mon, 24 Dec 2012 18:25:48 +0100 Subject: [PATCH] IV drips now can take blood as well as give it. This makes blood donations much easier. --- code/game/machinery/iv_drip.dm | 85 ++++++++++++++++++-- code/modules/mob/living/carbon/human/life.dm | 22 +++-- 2 files changed, 94 insertions(+), 13 deletions(-) diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm index 3faf3bebaf2..7ba6b06923a 100644 --- a/code/game/machinery/iv_drip.dm +++ b/code/game/machinery/iv_drip.dm @@ -4,7 +4,9 @@ anchored = 0 density = 1 + /obj/machinery/iv_drip/var/mob/living/carbon/human/attached = null +/obj/machinery/iv_drip/var/mode = "give" // mode can be "give" or "take" /obj/machinery/iv_drip/var/obj/item/weapon/reagent_containers/beaker = null /obj/machinery/iv_drip/update_icon() @@ -68,7 +70,8 @@ set background = 1 ..() - if(src.attached && src.beaker && src.beaker.volume > 0) + + if(src.attached) if(!(get_dist(src, src.attached) <= 1)) visible_message("The needle is ripped out of [src.attached], doesn't that hurt?") src.attached:apply_damage(3, BRUTE, pick("r_arm", "l_arm")) @@ -76,12 +79,64 @@ src.update_icon() return - var/transfer_amount = REAGENTS_METABOLISM - if(istype(src.beaker, /obj/item/weapon/reagent_containers/blood)) - // speed up transfer on blood packs - transfer_amount = 4 - src.beaker.reagents.trans_to(src.attached, transfer_amount) - update_icon() + if(src.attached && src.beaker) + // Give blood + if(mode == "give" && src.beaker.volume > 0) + var/transfer_amount = REAGENTS_METABOLISM + if(istype(src.beaker, /obj/item/weapon/reagent_containers/blood)) + // speed up transfer on blood packs + transfer_amount = 4 + src.beaker.reagents.trans_to(src.attached, transfer_amount) + update_icon() + + // Take blood + else if(mode == "take") + var/amount = beaker.reagents.maximum_volume - beaker.reagents.total_volume + // If the beaker is full, ping + if(amount == 0) + if(prob(5)) visible_message("\The [src] pings.") + return + + var/mob/living/carbon/human/T = attached + + if(!istype(T)) return + var/datum/reagent/B = new /datum/reagent/blood + if(!T.dna) + return + if(NOCLONE in T.mutations) + return + // If the human is losing too much blood, beep. + if(T.vessel.get_reagent_amount("blood") < BLOOD_VOLUME_SAFE) if(prob(5)) + visible_message("\The [src] beeps loudly.") + if(T.vessel.get_reagent_amount("blood") < amount) + return + B.holder = beaker + B.volume = amount + //set reagent data + B.data["donor"] = T + + if(T.virus2) + B.data["virus2"] = T.virus2.getcopy() + + B.data["blood_DNA"] = copytext(T.dna.unique_enzymes,1,0) + if(T.resistances && T.resistances.len) + B.data["resistances"] = T.resistances.Copy() + + B.data["blood_type"] = copytext(T.dna.b_type,1,0) + + var/list/temp_chem = list() + for(var/datum/reagent/R in T.reagents.reagent_list) + temp_chem += R.name + temp_chem[R.name] = R.volume + B.data["trace_chem"] = list2params(temp_chem) + B.data["antibodies"] = T.antibodies + + T.vessel.remove_reagent("blood",amount) // Removes blood if human + + beaker.reagents.reagent_list += B + beaker.reagents.update_total() + beaker.on_reagent_change() + beaker.reagents.handle_reactions() /obj/machinery/iv_drip/attack_hand(mob/user as mob) if(src.beaker) @@ -91,6 +146,22 @@ else return ..() + +/obj/machinery/iv_drip/verb/toggle_mode() + set name = "Toggle Mode" + set src in view(1) + + if(!istype(usr, /mob/living)) + usr << "\red You can't do that." + return + + if(mode == "give") + mode = "take" + usr << "The IV drip is now taking blood." + if(mode == "take") + mode = "give" + usr << "The IV drip is now giving blood." + /obj/machinery/iv_drip/examine() set src in view() ..() diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 07df4849d87..77162b1e558 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -21,6 +21,11 @@ #define COLD_GAS_DAMAGE_LEVEL_2 2 //Amount of damage applied when the current breath's temperature passes the 200K point #define COLD_GAS_DAMAGE_LEVEL_3 4 //Amount of damage applied when the current breath's temperature passes the 120K point +var/const/BLOOD_VOLUME_SAFE = 501 +var/const/BLOOD_VOLUME_OKAY = 336 +var/const/BLOOD_VOLUME_BAD = 224 +var/const/BLOOD_VOLUME_SURVIVE = 122 + /mob/living/carbon/human var/oxygen_alert = 0 var/toxins_alert = 0 @@ -152,11 +157,11 @@ switch(blood_volume) - if(501 to 10000) + if(BLOOD_VOLUME_SAFE to 10000) if(pale) pale = 0 update_body() - if(336 to 500) + if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE) if(!pale) pale = 1 update_body() @@ -168,7 +173,7 @@ if(oxyloss < 20) // hint that they're getting close to suffocation oxyloss += 3 - if(224 to 335) + if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY) if(!pale) pale = 1 update_body() @@ -180,13 +185,13 @@ Paralyse(rand(1,3)) var/word = pick("dizzy","woosey","faint") src << "\red You feel extremely [word]" - if(122 to 244) + if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD) oxyloss += 5 toxloss += 5 if(prob(15)) var/word = pick("dizzy","woosey","faint") src << "\red You feel extremely [word]" - if(0 to 122) + 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. @@ -1411,8 +1416,13 @@ if(0 to 20) healths.icon_state = "health5" else healths.icon_state = "health6" + var/adjusted_nutrition = nutrition + // With not enough blood, make it seem as though hungry, since eating will + // help regenerate blood + if(vessel.get_reagent_amount("blood") < BLOOD_VOLUME_SAFE) + adjusted_nutrition = min(200, nutrition) if(nutrition_icon) - switch(nutrition) + switch(adjusted_nutrition) if(450 to INFINITY) nutrition_icon.icon_state = "nutrition0" if(350 to 450) nutrition_icon.icon_state = "nutrition1" if(250 to 350) nutrition_icon.icon_state = "nutrition2"