Merge branch 'master' into BREATHE

This commit is contained in:
Werner
2019-12-21 14:45:17 +01:00
committed by GitHub
336 changed files with 11622 additions and 9853 deletions
+5 -6
View File
@@ -9,13 +9,12 @@
if(vessel)
return
vessel = new/datum/reagents(DEFAULT_BLOOD_SPECIES + 40)
vessel.my_atom = src
vessel = new/datum/reagents(species.blood_volume, src)
if(species && species.flags & NO_BLOOD) //We want the var for safety but we can do without the actual blood.
return
vessel.add_reagent("blood", DEFAULT_BLOOD_SPECIES)
vessel.add_reagent("blood", species.blood_volume)
fixblood()
//Resets blood data
@@ -209,7 +208,7 @@
var/list/chems = list()
chems = params2list(injected.data["trace_chem"])
for(var/C in chems)
src.reagents.add_reagent(C, (text2num(chems[C]) / DEFAULT_BLOOD_SPECIES) * amount)//adds trace chemicals to owner's blood
src.reagents.add_reagent(C, (text2num(chems[C]) / species.blood_volume) * amount)//adds trace chemicals to owner's blood
reagents.update_total()
//Transfers blood from reagents to vessel, respecting blood types compatability.
@@ -249,8 +248,8 @@ proc/blood_incompatible(donor,receiver,donor_species,receiver_species)
if(donor_species != receiver_species)
return 1
var/donor_antigen = copytext(donor,1,lentext(donor))
var/receiver_antigen = copytext(receiver,1,lentext(receiver))
var/donor_antigen = copytext(donor,1,length(donor))
var/receiver_antigen = copytext(receiver,1,length(receiver))
var/donor_rh = (findtext(donor,"+")>0)
var/receiver_rh = (findtext(receiver,"+")>0)
+16 -1
View File
@@ -44,9 +44,24 @@
if((status & ORGAN_DEAD) && dead_icon)
icon_state = dead_icon
/obj/item/organ/internal/proc/surgical_fix() //to be used for scarring -mattatlas
/obj/item/organ/internal/proc/surgical_fix(mob/user)
if(damage > min_broken_damage)
var/scarring = damage/max_damage
scarring = 1 - 0.3 * scarring ** 2 // Between ~15 and 30 percent loss
var/new_max_dam = Floor(scarring * max_damage)
if(new_max_dam < max_damage)
to_chat(user, "<span class='warning'>Not every part of [src] could be saved, some dead tissue had to be removed, making it more suspectable to damage in the future.</span>")
set_max_damage(new_max_dam)
heal_damage(damage)
/obj/item/organ/internal/proc/get_scarring_level()
. = (initial(max_damage) - max_damage)/initial(max_damage)
/obj/item/organ/internal/proc/get_scarring_results()
var/scar_level = get_scarring_level()
if(scar_level > 0.01)
. += "[get_wound_severity(get_scarring_level())] scarring"
/obj/item/organ/internal/is_usable()
return ..() && !is_broken()
+156 -10
View File
@@ -28,6 +28,57 @@
var/healed_threshold = 1
var/oxygen_reserve = 6
/obj/item/organ/internal/brain/Initialize(mapload)
. = ..()
if(species)
set_max_damage(species.total_health)
else
set_max_damage(200)
if(!mapload)
addtimer(CALLBACK(src, .proc/clear_screen), 5)
/obj/item/organ/internal/brain/Destroy()
if(brainmob)
qdel(brainmob)
brainmob = null
return ..()
/obj/item/organ/internal/brain/removed(var/mob/living/user)
for(var/X in traumas)
var/datum/brain_trauma/BT = X
BT.on_lose(TRUE)
BT.owner = null
var/mob/living/simple_animal/borer/borer = owner.has_brain_worms()
if(borer)
borer.detatch() //Should remove borer if the brain is removed - RR
var/obj/item/organ/internal/brain/B = src
if(istype(B) && istype(owner))
B.transfer_identity(owner)
..()
/obj/item/organ/internal/brain/replaced(var/mob/living/target)
if(target.key)
target.ghostize()
if(brainmob)
if(brainmob.mind)
brainmob.mind.transfer_to(target)
else
target.key = brainmob.key
for(var/X in traumas)
var/datum/brain_trauma/BT = X
BT.owner = owner
BT.on_gain()
..()
/obj/item/organ/internal/brain/can_recover()
return ~status & ORGAN_DEAD
@@ -41,15 +92,6 @@
..()
damage_threshold_value = round(max_damage / damage_threshold_count)
/obj/item/organ/internal/brain/Initialize(mapload)
. = ..()
if(species)
set_max_damage(species.total_health)
else
set_max_damage(200)
if(!mapload)
addtimer(CALLBACK(src, .proc/clear_screen), 5)
/obj/item/organ/internal/brain/process()
if(owner)
if(damage > max_damage / 2 && healed_threshold)
@@ -157,4 +199,108 @@
if(is_broken())
if(!owner.lying)
to_chat(owner, "<span class='danger'>You black out!</span>")
owner.Paralyse(10)
owner.Paralyse(10)
/obj/item/organ/internal/brain/surgical_fix(mob/user)
var/blood_volume = owner.get_blood_oxygenation()
if(blood_volume < BLOOD_VOLUME_SURVIVE)
to_chat(user, "<span class='danger'>Parts of [src] didn't survive the procedure due to lack of air supply!</span>")
set_max_damage(Floor(max_damage - 0.25*damage))
heal_damage(damage)
/obj/item/organ/internal/brain/get_scarring_level()
. = (species.total_health - max_damage)/species.total_health
////////////////////////////////////TRAUMAS////////////////////////////////////////
/obj/item/organ/internal/brain/proc/has_trauma_type(brain_trauma_type, consider_permanent = FALSE)
for(var/X in traumas)
var/datum/brain_trauma/BT = X
if(istype(BT, brain_trauma_type) && (consider_permanent || !BT.permanent))
return BT
//Add a specific trauma
/obj/item/organ/internal/brain/proc/gain_trauma(datum/brain_trauma/trauma, permanent = FALSE, list/arguments)
var/trauma_type
if(ispath(trauma))
trauma_type = trauma
traumas += new trauma_type(arglist(list(src, permanent) + arguments))
else
traumas += trauma
trauma.permanent = permanent
//Add a random trauma of a certain subtype
/obj/item/organ/internal/brain/proc/gain_trauma_type(brain_trauma_type = /datum/brain_trauma, permanent = FALSE)
var/list/datum/brain_trauma/possible_traumas = list()
for(var/T in subtypesof(brain_trauma_type))
var/datum/brain_trauma/BT = T
if(initial(BT.can_gain))
possible_traumas += BT
var/trauma_type = pick(possible_traumas)
traumas += new trauma_type(src, permanent)
//Cure a random trauma of a certain subtype
/obj/item/organ/internal/brain/proc/cure_trauma_type(brain_trauma_type, cure_permanent = FALSE)
var/datum/brain_trauma/trauma = has_trauma_type(brain_trauma_type)
if(trauma && (cure_permanent || !trauma.permanent))
qdel(trauma)
/obj/item/organ/internal/brain/proc/cure_all_traumas(cure_permanent = FALSE, cure_type = "")
for(var/X in traumas)
var/datum/brain_trauma/trauma = X
if(trauma.cure_type == cure_type || cure_type == CURE_ADMIN)
if(cure_permanent || !trauma.permanent)
qdel(trauma)
if(cure_type != CURE_ADMIN)
break
//Miscellaneous
/obj/item/organ/internal/brain/proc/clear_screen()
if (brainmob && brainmob.client)
brainmob.client.screen.Cut()
/obj/item/organ/internal/brain/proc/transfer_identity(var/mob/living/carbon/H)
brainmob = new(src)
brainmob.name = H.real_name
brainmob.real_name = H.real_name
brainmob.dna = H.dna.Clone()
brainmob.timeofhostdeath = H.timeofdeath
if(H.mind)
H.mind.transfer_to(brainmob)
to_chat(brainmob, "<span class='notice'>You feel slightly disoriented. That's normal when you're just a [initial(src.name)].</span>")
callHook("debrain", list(brainmob))
/obj/item/organ/internal/brain/examine(mob/user) // -- TLE
..(user)
if(brainmob && brainmob.client)//if thar be a brain inside... the brain.
to_chat(user, "You can feel the small spark of life still left in this one.")
else
to_chat(user, "This one seems particularly lifeless. Perhaps it will regain some of its luster later..")
/obj/item/organ/internal/brain/proc/lobotomize(mob/user as mob)
lobotomized = 1
if(owner)
to_chat(owner, "<span class='danger'>As part of your brain is drilled out, you feel your past self, your memories, your very being slip away...</span>")
to_chat(owner, "<b>Your brain has been surgically altered to remove your memory recall. Your ability to recall your former life has been surgically removed from your brain, and while your brain is in this state you remember nothing that ever came before this moment.</b>")
else if(brainmob)
to_chat(brainmob, "<span class='danger'>As part of your brain is drilled out, you feel your past self, your memories, your very being slip away...</span>")
to_chat(brainmob, "<b>Your brain has been surgically altered to remove your memory recall. Your ability to recall your former life has been surgically removed from your brain, and while your brain is in this state you remember nothing that ever came before this moment.</b>")
return
/obj/item/organ/internal/brain/attackby(obj/item/W as obj, mob/user as mob)
if(istype(W,/obj/item/surgicaldrill))
if(!can_lobotomize)
return
if(!lobotomized)
user.visible_message("<span class='danger'>[user] drills [src] deftly with [W] into the brain!</span>")
lobotomize(user)
else
to_chat(user, "<span class='notice'>The brain has already been operated on!</span>")
..()
+1 -1
View File
@@ -119,7 +119,7 @@
var/blood_volume = round(owner.vessel.get_reagent_amount("blood"))
//Blood regeneration if there is some space
if(blood_volume < DEFAULT_BLOOD_SPECIES && blood_volume)
if(blood_volume < species.blood_volume && 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.
+18 -1
View File
@@ -1,3 +1,5 @@
#define PUKE_ACTION_NAME "Empty Stomach"
/obj/item/organ/internal/stomach
name = "stomach"
desc = "Gross. This is hard to stomach."
@@ -18,6 +20,8 @@
ingested = new /datum/reagents/metabolism(240, owner, CHEM_INGEST)
if(!ingested.my_atom)
ingested.my_atom = src
if(species.gluttonous)
action_button_name = PUKE_ACTION_NAME
/obj/item/organ/internal/stomach/removed()
. = ..()
@@ -29,6 +33,18 @@
ingested.my_atom = owner
ingested.parent = owner
/obj/item/organ/internal/stomach/refresh_action_button()
. = ..()
if(.)
action.button_icon_state = "puke"
if(action.button) action.button.UpdateIcon()
/obj/item/organ/internal/stomach/attack_self(mob/user)
. = ..()
if(. && action_button_name == PUKE_ACTION_NAME && owner && !owner.incapacitated())
owner.vomit(deliberate = TRUE)
refresh_action_button()
/obj/item/organ/internal/stomach/proc/can_eat_atom(var/atom/movable/food)
return !isnull(get_devour_time(food))
@@ -113,4 +129,5 @@
if(prob(vomit_probability))
owner.vomit()
#undef STOMACH_VOLUME
#undef STOMACH_VOLUME
#undef PUKE_ACTION_NAME
+3 -9
View File
@@ -305,12 +305,8 @@
/obj/item/organ/proc/robotize() //Being used to make robutt hearts, etc
robotic = 2
src.status &= ~ORGAN_BROKEN
src.status &= ~ORGAN_BLEEDING
src.status &= ~ORGAN_SPLINTED
src.status &= ~ORGAN_CUT_AWAY
src.status |= ORGAN_ROBOT
src.status |= ORGAN_ASSISTED
status = ORGAN_ROBOT
status |= ORGAN_ASSISTED
if(robotic_name)
name = robotic_name
if(robotic_sprite)
@@ -318,10 +314,8 @@
/obj/item/organ/proc/mechassist() //Used to add things like pacemakers, etc
robotize()
src.status &= ~ORGAN_ROBOT
status = ORGAN_ASSISTED
robotic = 1
min_bruised_damage = 15
min_broken_damage = 35
if(!robotize_type)
name = initial(name)
icon_state = initial(icon_state)
+20 -3
View File
@@ -86,6 +86,8 @@
var/atom/movable/applied_pressure //Pressure applied to wounds. It'll make them bleed less, generally.
var/image/hud_damage_image
/obj/item/organ/external/proc/invalidate_marking_cache()
cached_markings = null
@@ -250,6 +252,8 @@
brute *= brute_mod
burn *= burn_mod
var/laser = (damage_flags & DAM_LASER)
add_pain(0.6*burn + 0.4*brute)
if(status & ORGAN_BROKEN && prob(40) && brute)
@@ -303,7 +307,10 @@
if(burn > 0 && can_inflict)
//Inflict all burn damage we can
createwound(BURN, min(burn,can_inflict))
if(laser)
createwound(LASER, min(burn, can_inflict))
else
createwound(BURN, min(burn,can_inflict))
//How much burn damage is left to inflict
spillover += max(0, burn - can_inflict)
@@ -464,7 +471,8 @@ This function completely restores a damaged organ to perfect condition.
/obj/item/organ/external/proc/createwound(var/type = CUT, var/damage)
if(damage == 0) return
if(damage <= 0) return
//moved this before the open_wound check so that having many small wounds for example doesn't somehow protect you from taking internal damage (because of the return)
//Possibly trigger an internal wound, too.
@@ -478,6 +486,15 @@ This function completely restores a damaged organ to perfect condition.
if(internal_damage)
owner.custom_pain("You feel something rip in your [name]!", 25)
//Burn damage can cause fluid loss due to blistering and cook-off
if((type in list(BURN, LASER)) && (damage > 5 || damage + burn_dam >= 15) && !BP_IS_ROBOTIC(src))
var/fluid_loss_severity
switch(type)
if(BURN) fluid_loss_severity = FLUIDLOSS_WIDE_BURN
if(LASER) fluid_loss_severity = FLUIDLOSS_CONC_BURN
var/fluid_loss = (damage/(owner.maxHealth - config.health_threshold_dead)) * DEFAULT_BLOOD_AMOUNT * fluid_loss_severity
owner.remove_blood_simple(fluid_loss)
// first check whether we can widen an existing wound
if(wounds.len > 0 && prob(max(50+(number_wounds-1)*10,90)))
if((type == CUT || type == BRUISE) && damage >= 5)
@@ -981,7 +998,7 @@ Note that amputating the affected organ does in fact remove the infection from t
W.germ_level = 0
return rval
/obj/item/organ/external/proc/clamp()
/obj/item/organ/external/proc/clamp_organ()
var/rval = 0
src.status &= ~ORGAN_BLEEDING
for(var/datum/wound/W in wounds)
+39 -3
View File
@@ -113,6 +113,7 @@
add_overlay(finished_icon) //So when it's not on your body, it has icons
mob_icon.Blend(finished_icon, ICON_OVERLAY) //So when it's on your body, it has icons
/obj/item/organ/external/var/icon_cache_key
/obj/item/organ/external/proc/get_icon(var/skeletal)
var/gender = "f"
@@ -158,18 +159,19 @@
mob_icon.Blend(rgb(s_tone, s_tone, s_tone), ICON_ADD)
else
mob_icon.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT)
apply_markings()
if(body_hair && hair_color)
var/list/limb_icon_cache = SSicon_cache.body_hair_cache
if(body_hair)
var/list/limb_icon_cache = SSicon_cache.limb_icons_cache
var/cache_key = "[body_hair]-[icon_name]-[hair_color]"
if(!limb_icon_cache[cache_key])
var/icon/I = icon(species.icobase, "[icon_name]_[body_hair]")
I.Blend(hair_color, ICON_ADD)
limb_icon_cache[cache_key] = I
mob_icon.Blend(limb_icon_cache[cache_key], ICON_OVERLAY)
icon_cache_key = cache_key
icon = mob_icon
@@ -217,3 +219,37 @@
LAZYADD(cached_markings, genetic_markings)
if (LAZYLEN(temporary_markings))
LAZYADD(cached_markings, temporary_markings)
// Global scope, used in code below.
var/list/flesh_hud_colours = list("#00ff00","#aaff00","#ffff00","#ffaa00","#ff0000","#aa0000","#660000")
var/list/robot_hud_colours = list("#ffffff","#cccccc","#aaaaaa","#888888","#666666","#444444","#222222","#000000")
/obj/item/organ/external/proc/get_damage_hud_image()
// Generate the greyscale base icon and cache it for later.
// icon_cache_key is set by any get_icon() calls that are made.
// This looks convoluted, but it's this way to avoid icon proc calls.
var/list/limb_icon_cache = SSicon_cache.limb_icons_cache
if(!hud_damage_image)
var/cache_key = "dambase-[icon_cache_key]"
if(!icon_cache_key || !limb_icon_cache[cache_key])
limb_icon_cache[cache_key] = icon(get_icon(), null, SOUTH)
var/image/temp = image(limb_icon_cache[cache_key])
if(species)
// Calculate the required colour matrix.
var/r = 0.30 * species.health_hud_intensity
var/g = 0.59 * species.health_hud_intensity
var/b = 0.11 * species.health_hud_intensity
temp.color = list(r, r, r, g, g, g, b, b, b)
hud_damage_image = image(null)
hud_damage_image.overlays += temp
// Calculate the required color index.
var/dam_state = min(1,((brute_dam+burn_dam)/max(1,max_damage)))
var/min_dam_state = min(1,(get_pain()/max(1,max_damage)))
if(min_dam_state && dam_state < min_dam_state)
dam_state = min_dam_state
// Apply colour and return product.
var/list/hud_colours = !BP_IS_ROBOTIC(src) ? flesh_hud_colours : robot_hud_colours
hud_damage_image.color = hud_colours[max(1,min(Ceiling(dam_state*hud_colours.len),hud_colours.len))]
return hud_damage_image