Merge pull request #2885 from Crazylemon64/blood-n-guts

Organ Germiness Adjustments
This commit is contained in:
Fox McCloud
2015-12-20 22:18:31 -05:00
11 changed files with 195 additions and 104 deletions
+11
View File
@@ -534,6 +534,17 @@ Turf and target are seperate in case you want to teleport some distance from a t
loc = loc.loc
return loc
/*
Returns 1 if the chain up to the area contains the given typepath
0 otherwise
*/
/atom/proc/is_found_within(var/typepath)
var/atom/A = src
while(A.loc)
if(istype(A.loc, typepath))
return 1
A = A.loc
return 0
// the on-close client verb
// called when a browser popup window is closed after registering with proc/onclose()
+1 -1
View File
@@ -889,7 +889,7 @@
product_ads = "Go save some lives!;The best stuff for your medbay.;Only the finest tools.;Natural chemicals!;This stuff saves lives.;Don't you want some?;Ping!"
req_access_txt = "5"
products = list(/obj/item/weapon/reagent_containers/glass/bottle/charcoal = 4,/obj/item/weapon/reagent_containers/glass/bottle/morphine = 4,/obj/item/weapon/reagent_containers/glass/bottle/ether = 4,/obj/item/weapon/reagent_containers/glass/bottle/epinephrine = 4,
/obj/item/weapon/reagent_containers/glass/bottle/toxin = 4,/obj/item/weapon/reagent_containers/syringe/antiviral = 4,/obj/item/weapon/reagent_containers/syringe/insulin = 4,
/obj/item/weapon/reagent_containers/glass/bottle/toxin = 4,/obj/item/weapon/reagent_containers/syringe/antiviral = 6,/obj/item/weapon/reagent_containers/syringe/insulin = 4,
/obj/item/weapon/reagent_containers/syringe = 12,/obj/item/device/healthanalyzer = 5,/obj/item/device/healthupgrade = 5,/obj/item/weapon/reagent_containers/glass/beaker = 4,
/obj/item/weapon/reagent_containers/dropper = 2,/obj/item/stack/medical/advanced/bruise_pack = 3, /obj/item/stack/medical/advanced/ointment = 3,
/obj/item/stack/medical/bruise_pack = 3,/obj/item/stack/medical/splint = 2, /obj/item/device/sensor_device = 2)
+110 -88
View File
@@ -12,91 +12,112 @@
var/alien = 0
var/syndiemmi = 0 //Whether or not this is a Syndicate MMI
var/mob/living/carbon/brain/brainmob = null//The current occupant.
var/obj/item/organ/brain/held_brain = null // This is so MMI's aren't brainscrubber 9000's
var/mob/living/silicon/robot/robot = null//Appears unused.
var/obj/mecha/mecha = null//This does not appear to be used outside of reference in mecha.dm.
// I'm using this for mechs giving MMIs HUDs now
attackby(var/obj/item/O as obj, var/mob/user as mob, params)
if(istype(O, /obj/item/organ/brain/crystal ))
user << "<span class='warning'> This brain is too malformed to be able to use with the [src].</span>"
/obj/item/device/mmi/attackby(var/obj/item/O as obj, var/mob/user as mob, params)
if(istype(O, /obj/item/organ/brain/crystal ))
user << "<span class='warning'> This brain is too malformed to be able to use with the [src].</span>"
return
if(istype(O,/obj/item/organ/brain) && !brainmob) //Time to stick a brain in it --NEO
var/obj/item/organ/brain/B = O
if(!B.brainmob)
user << "<span class='warning'>You aren't sure where this brain came from, but you're pretty sure it's a useless brain.</span>"
return
if(istype(O,/obj/item/organ/brain) && !brainmob) //Time to stick a brain in it --NEO
if(!O:brainmob)
user << "\red You aren't sure where this brain came from, but you're pretty sure it's a useless brain."
return
for(var/mob/V in viewers(src, null))
V.show_message(text("\blue [user] sticks \a [O] into \the [src]."))
brainmob = O:brainmob
O:brainmob = null
brainmob.loc = src
brainmob.container = src
brainmob.stat = 0
respawnable_list -= brainmob
dead_mob_list -= brainmob//Update dem lists
living_mob_list += brainmob
user.drop_item()
if(istype(O,/obj/item/organ/brain/xeno))
name = "Man-Machine Interface: Alien - [brainmob.real_name]"
icon = 'icons/mob/alien.dmi'
icon_state = "AlienMMI"
alien = 1
else
name = "Man-Machine Interface: [brainmob.real_name]"
icon_state = "mmi_full"
alien = 0
qdel(O)
feedback_inc("cyborg_mmis_filled",1)
if(held_brain)
user << "<span class='userdanger'>Somehow, this MMI still has a brain in it. Report this to the bug tracker.</span>"
log_to_dd("[user] tried to stick a [O] into [src] in [get_area(src)], but the held brain variable wasn't cleared")
return
if(brainmob)
O.attack(brainmob, user)//Oh noooeeeee
// Brainmobs can take damage, but they can't actually die. Maybe should fix.
if(B.status & ORGAN_DEAD) // As it stood, a brain would never become unviable for MMI usage. Perhaps we should keep it that way?
user << "<span class='warning'>This [B] is dead</span>"
return
..()
for(var/mob/V in viewers(src, null))
V.show_message("<span class='notice'>[user] sticks \a [O] into \the [src].</span>")
brainmob = B.brainmob
B.brainmob = null
brainmob.loc = src
brainmob.container = src
brainmob.stat = CONSCIOUS
respawnable_list -= brainmob
dead_mob_list -= brainmob//Update dem lists
living_mob_list += brainmob
attack_self(mob/user as mob)
if(!brainmob)
user << "\red You upend the MMI, but there's nothing in it."
user.drop_item()
B.forceMove(src)
held_brain = B
if(istype(O,/obj/item/organ/brain/xeno)) // I'm not sure how well this will work now, since I don't think you can actually get xeno brains
name = "Man-Machine Interface: Alien - [brainmob.real_name]"
icon = 'icons/mob/alien.dmi'
icon_state = "AlienMMI"
alien = 1
else
user << "<span class='notice'>You unlock and upend the MMI, spilling the brain onto the floor.</span>"
if(alien)
var/obj/item/organ/brain/xeno/brain = new(user.loc)
dropbrain(brain,get_turf(user))
else
var/obj/item/organ/brain/brain = new(user.loc)
dropbrain(brain,get_turf(user))
icon = 'icons/obj/assemblies.dmi'
icon_state = "mmi_empty"
name = "Man-Machine Interface"
proc
transfer_identity(var/mob/living/carbon/human/H)//Same deal as the regular brain proc. Used for human-->robot people.
brainmob = new(src)
brainmob.name = H.real_name
brainmob.real_name = H.real_name
brainmob.dna = H.dna.Clone()
brainmob.container = src
name = "Man-Machine Interface: [brainmob.real_name]"
icon_state = "mmi_full"
return
alien = 0
feedback_inc("cyborg_mmis_filled",1)
return
if(brainmob)
O.attack(brainmob, user)//Oh noooeeeee
// Brainmobs can take damage, but they can't actually die. Maybe should fix.
return
..()
/obj/item/device/mmi/attack_self(mob/user as mob)
if(!brainmob)
user << "<span class='warning'>You upend the MMI, but there's nothing in it.</span>"
else
user << "<span class='notice'>You unlock and upend the MMI, spilling the brain onto the floor.</span>"
dropbrain(get_turf(user))
icon = 'icons/obj/assemblies.dmi'
icon_state = "mmi_empty"
name = "Man-Machine Interface"
/obj/item/device/mmi/proc/transfer_identity(var/mob/living/carbon/human/H)//Same deal as the regular brain proc. Used for human-->robot people.
brainmob = new(src)
brainmob.name = H.real_name
brainmob.real_name = H.real_name
brainmob.dna = H.dna.Clone()
brainmob.container = src
if(!istype(H.species) || isnull(H.species.return_organ("brain"))) // Diona/buggy people
held_brain = new(src)
else // We have a species, and it has a brain
var/brain_path = H.species.return_organ("brain")
if(!ispath(brain_path, /obj/item/organ/brain))
brain_path = /obj/item/organ/brain
held_brain = new brain_path(src) // Slime people will keep their slimy brains this way
held_brain.dna = brainmob.dna.Clone()
held_brain.name = "\the [brainmob.name]'s [initial(held_brain.name)]"
name = "Man-Machine Interface: [brainmob.real_name]"
icon_state = "mmi_full"
return
//I made this proc as a way to have a brainmob be transferred to any created brain, and to solve the
//problem i was having with alien/nonalien brain drops.
dropbrain(var/obj/item/organ/brain/brain, var/turf/dropspot)
brainmob.container = null//Reset brainmob mmi var.
brainmob.loc = brain//Throw mob into brain.
respawnable_list += brainmob
living_mob_list -= brainmob//Get outta here
brain.brainmob = brainmob//Set the brain to use the brainmob
brain.brainmob.cancel_camera()
brainmob = null//Set mmi brainmob var to null
/obj/item/device/mmi/proc/dropbrain(var/turf/dropspot)
if(isnull(held_brain))
log_to_dd("[src] at [loc] attempted to drop brain without a contained brain in [get_area(src)].")
brainmob << "<span class='userdanger'>Your MMI did not contain a brain! We'll make a new one for you, but you'd best report this to the bugtracker!</span>"
held_brain = new(dropspot) // Let's not ruin someone's round because of something dumb -- Crazylemon
held_brain.dna = brainmob.dna.Clone()
held_brain.name = "\the [brainmob.name]'s [initial(held_brain.name)]"
brainmob.container = null//Reset brainmob mmi var.
brainmob.loc = held_brain//Throw mob into brain.
respawnable_list += brainmob
living_mob_list -= brainmob//Get outta here
held_brain.brainmob = brainmob//Set the brain to use the brainmob
held_brain.brainmob.cancel_camera()
brainmob = null//Set mmi brainmob var to null
held_brain.forceMove(dropspot)
held_brain = null
/obj/item/device/mmi/radio_enabled
@@ -106,25 +127,23 @@
var/obj/item/device/radio/radio = null//Let's give it a radio.
New()
..()
radio = new(src)//Spawns a radio inside the MMI.
radio.broadcasting = 1//So it's broadcasting from the start.
/obj/item/device/mmi/radio_enabled/New()
..()
radio = new(src)//Spawns a radio inside the MMI.
radio.broadcasting = 1//So it's broadcasting from the start.
verb//Allows the brain to toggle the radio functions.
/obj/item/device/mmi/radio_enabled/verb/Toggle_Listening()
set name = "Toggle Listening"
set desc = "Toggle listening channel on or off."
set category = "MMI"
set src = usr.loc
set popup_menu = 0
Toggle_Listening()
set name = "Toggle Listening"
set desc = "Toggle listening channel on or off."
set category = "MMI"
set src = usr.loc
set popup_menu = 0
if(brainmob.stat)
brainmob << "Can't do that while incapacitated or dead."
if(brainmob.stat)
brainmob << "Can't do that while incapacitated or dead."
radio.listening = radio.listening==1 ? 0 : 1
brainmob << "\blue Radio is [radio.listening==1 ? "now" : "no longer"] receiving broadcast."
radio.listening = radio.listening==1 ? 0 : 1
brainmob << "<span class='notice'>Radio is [radio.listening==1 ? "now" : "no longer"] receiving broadcast.</span>"
/obj/item/device/mmi/emp_act(severity)
if(!brainmob)
@@ -153,6 +172,9 @@
if(brainmob)
qdel(brainmob)
brainmob = null
if(held_brain)
qdel(held_brain)
held_brain = null
return ..()
/obj/item/device/mmi/syndie
@@ -54,19 +54,24 @@
else if (response == "Never for this round")
C.prefs.be_special ^= BE_PAI
// This should not ever happen, but let's be safe
/obj/item/device/mmi/posibrain/dropbrain(var/turf/dropspot)
log_to_dd("[src] at [loc] attempted to drop brain without a contained brain.")
return
/obj/item/device/mmi/posibrain/transfer_identity(var/mob/living/carbon/H)
name = "positronic brain ([H])"
brainmob.name = H.real_name
brainmob.real_name = H.real_name
brainmob.dna = H.dna
if(isnull(brainmob.dna))
brainmob.dna = H.dna.Clone()
brainmob.name = brainmob.dna.real_name
brainmob.real_name = brainmob.name
brainmob.timeofhostdeath = H.timeofdeath
brainmob.stat = 0
brainmob.stat = CONSCIOUS
if(brainmob.mind)
brainmob.mind.assigned_role = "Positronic Brain"
if(H.mind)
H.mind.transfer_to(brainmob)
brainmob << "\blue You feel slightly disoriented. That's normal when you're just a metal cube."
brainmob << "<span class='notice'>You feel slightly disoriented. That's normal when you're just a metal cube.</span>"
icon_state = "posibrain-occupied"
return
@@ -118,6 +118,7 @@
"l_foot" = list("path" = /obj/item/organ/external/foot),
"r_foot" = list("path" = /obj/item/organ/external/foot/right)
)
var/cyborg_type = "Cyborg"
/datum/species/New()
//If the species has eyes, they are the default vision organ
@@ -593,3 +594,12 @@
H.bodytemp.icon_state = "temp0"
return 1
/*
Returns the path corresponding to the corresponding organ
It'll return null if the organ doesn't correspond, so include null checks when using this!
*/
/datum/species/proc/return_organ(var/organ_slot)
if(!(organ_slot in has_organ))
return null
return has_organ[organ_slot]
+1 -1
View File
@@ -161,7 +161,7 @@
O.job = "Cyborg"
O.notify_ai(1)
if(O.mind.assigned_role == "Cyborg")
if(O.mind && O.mind.assigned_role == "Cyborg")
if(O.mind.role_alt_title == "Android")
O.mmi = new /obj/item/device/mmi/posibrain(O)
else if(O.mind.role_alt_title == "Robot")
+39 -7
View File
@@ -23,6 +23,8 @@ var/list/organ_cache = list()
germ_level = 0
var/datum/dna/dna
var/datum/species/species
var/needs_preservation_update = 1
var/is_in_freezer = 0
/obj/item/organ/Destroy()
if(!owner)
@@ -106,8 +108,7 @@ var/list/organ_cache = list()
if(status & ORGAN_DEAD)
return
// Don't process if we're in a freezer, an MMI or a stasis bag. //TODO: ambient temperature?
if(istype(loc,/obj/item/device/mmi) || istype(loc,/obj/item/bodybag/cryobag) || istype(loc,/obj/structure/closet/crate/freezer))
if(is_preserved())
return
//Process infections
@@ -121,8 +122,11 @@ var/list/organ_cache = list()
if(B && prob(40))
reagents.remove_reagent("blood",0.1)
blood_splatter(src,B,1)
germ_level += rand(2,6)
// Maybe scale it down a bit, have it REALLY kick in once past the basic infection threshold
// Another mercy for surgeons preparing transplant organs
germ_level++
if(germ_level >= INFECTION_LEVEL_ONE)
germ_level += rand(2,6)
if(germ_level >= INFECTION_LEVEL_TWO)
germ_level += rand(2,6)
if(germ_level >= INFECTION_LEVEL_THREE)
@@ -140,6 +144,32 @@ var/list/organ_cache = list()
if(damage >= max_damage)
die()
/obj/item/organ/proc/is_preserved()
if(istype(loc,/obj/item/device/mmi))
germ_level = max(0, germ_level - 1) // So a brain can slowly recover from being left out of an MMI
return 1
if(is_found_within(/obj/item/bodybag/cryobag))
return 1
if(is_found_within(/obj/structure/closet/crate/freezer))
return 1
if(istype(loc,/turf))
if(needs_preservation_update)
// I don't want to loop through everything in the tile constantly, especially since it'll be a pile of organs
// if the virologist releases gibbingtons again or something
// There's probably a much less silly way of doing this, but BYOND native algorithms are stupidly naive
is_in_freezer = 0
for(var/obj/structure/closet/crate/freezer/F in loc.contents)
if(F.opened)
is_in_freezer = 1 // on the same tile, close enough, should keep organs much fresher on avg
break
needs_preservation_update = 0
spawn(100) // (100 / 10) once every 10 seconds
needs_preservation_update = 1
return is_in_freezer // I'd like static varibles, please
// You can do your cool location temperature organ preserving effects here!
return 0
/obj/item/organ/examine(mob/user)
..(user)
if(status & ORGAN_DEAD)
@@ -175,6 +205,7 @@ var/list/organ_cache = list()
/obj/item/organ/proc/rejuvenate()
damage = 0
germ_level = 0
/obj/item/organ/proc/is_damaged()
return damage > 0
@@ -189,15 +220,16 @@ var/list/organ_cache = list()
/obj/item/organ/proc/handle_antibiotics()
var/antibiotics = owner.reagents.get_reagent_amount("spaceacillin")
if (!germ_level || antibiotics < 5)
if (!germ_level || antibiotics <= 0.4)
return
if (germ_level < INFECTION_LEVEL_ONE)
germ_level = 0 //cure instantly
else if (germ_level < INFECTION_LEVEL_TWO)
germ_level -= 6 //at germ_level == 500, this should cure the infection in a minute
germ_level -= 24 //at germ_level == 500, this should cure the infection in 15 seconds
else
germ_level -= 2 //at germ_level == 1000, this will cure the infection in 5 minutes
germ_level -= 8 // at germ_level == 1000, this will cure the infection in 1 minute, 15 seconds
// Let's not drag this on, medbay has only so much antibiotics
//Adds autopsy data for used_weapon.
/obj/item/organ/proc/add_autopsy_data(var/used_weapon, var/damage)
+5 -1
View File
@@ -79,24 +79,28 @@
switch(stage)
if(0)
if(istype(W,/obj/item/weapon/scalpel))
spread_germs_to_organ(src,user)
user.visible_message("<span class='danger'><b>[user]</b> cuts [src] open with [W]!")
stage++
return
if(1)
if(istype(W,/obj/item/weapon/retractor))
spread_germs_to_organ(src,user)
user.visible_message("<span class='danger'><b>[user]</b> cracks [src] open like an egg with [W]!")
stage++
return
if(2)
if(istype(W,/obj/item/weapon/hemostat))
spread_germs_to_organ(src,user)
if(contents.len)
var/obj/item/removing = pick(contents)
removing.loc = get_turf(user.loc)
var/obj/item/organ/O = removing
if(istype(O))
O.status |= ORGAN_CUT_AWAY
spread_germs_to_organ(O,user) // This wouldn't be any cleaner than the actual surgery
O.removed(user)
else if(!(user.l_hand && user.r_hand))
if(!(user.l_hand && user.r_hand))
user.put_in_hands(removing)
user.visible_message("<span class='danger'><b>[user]</b> extracts [removing] from [src] with [W]!")
else
+2
View File
@@ -137,6 +137,8 @@
/obj/item/organ/external/head/removed()
if(owner)
if(!istype(dna))
dna = owner.dna.Clone()
name = "[dna.real_name]'s head"
owner.unEquip(owner.glasses)
owner.unEquip(owner.head)
+5
View File
@@ -136,6 +136,7 @@
for(var/obj/item/organ/I in affected.internal_organs)
if(I && I.damage > 0)
if(I.robotic < 2)
spread_germs_to_organ(I, user)
user.visible_message("[user] starts treating damage to [target]'s [I.name] with [tool_name].", \
"You start treating damage to [target]'s [I.name] with [tool_name]." )
@@ -238,6 +239,7 @@
var/obj/item/organ/I = target.op_stage.organ_ref
if(I && istype(I))
spread_germs_to_organ(I, user)
I.status |= ORGAN_CUT_AWAY
fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
@@ -297,6 +299,7 @@
if(target.op_stage.current_organ)
var/obj/item/organ/O = target.op_stage.organ_ref
if(O && istype(O))
spread_germs_to_organ(O, user)
O.removed(user)
fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
@@ -376,6 +379,7 @@
var/obj/item/organ/O = tool
if(istype(O))
O.replaced(target,affected)
spread_germs_to_organ(O, user)
fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
user.visible_message("\red [user]'s hand slips, damaging \the [tool]!", \
@@ -433,6 +437,7 @@
var/obj/item/organ/I = target.op_stage.organ_ref
if(I && istype(I))
I.status &= ~ORGAN_CUT_AWAY
spread_germs_to_organ(I, user)
fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/obj/item/organ/external/affected = target.get_organ(target_zone)
+1 -1
View File
@@ -66,7 +66,7 @@
/datum/surgery_step/proc/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
return null
/proc/spread_germs_to_organ(obj/item/organ/external/E, mob/living/carbon/human/user)
/proc/spread_germs_to_organ(obj/item/organ/E, mob/living/carbon/human/user)
if(!istype(user) || !istype(E)) return
var/germ_level = user.germ_level