This commit is contained in:
shellspeed1
2019-10-14 18:46:06 -07:00
parent 345e69a718
commit 470ec5d62b
114 changed files with 2124 additions and 592 deletions
+1 -1
View File
@@ -458,7 +458,7 @@
SSblackbox.record_feedback("nested tally", "admin_secrets_fun_used", 1, list("Mass Braindamage"))
for(var/mob/living/carbon/human/H in GLOB.player_list)
to_chat(H, "<span class='boldannounce'>You suddenly feel stupid.</span>")
H.adjustBrainLoss(60, 80)
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 60, 80)
message_admins("[key_name_admin(usr)] made everybody retarded")
if("eagles")//SCRAW
+1 -1
View File
@@ -1752,7 +1752,7 @@
if(DEAD)
status = "<font color='red'><b>Dead</b></font>"
health_description = "Status = [status]"
health_description += "<BR>Oxy: [L.getOxyLoss()] - Tox: [L.getToxLoss()] - Fire: [L.getFireLoss()] - Brute: [L.getBruteLoss()] - Clone: [L.getCloneLoss()] - Brain: [L.getBrainLoss()] - Stamina: [L.getStaminaLoss()]"
health_description += "<BR>Oxy: [L.getOxyLoss()] - Tox: [L.getToxLoss()] - Fire: [L.getFireLoss()] - Brute: [L.getBruteLoss()] - Clone: [L.getCloneLoss()] - Brain: [L.getOrganLoss(ORGAN_SLOT_BRAIN)] - Stamina: [L.getStaminaLoss()]"
else
health_description = "This mob type has no health to speak of."
+1 -1
View File
@@ -1264,7 +1264,7 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
target.electrocution_animation(40)
to_chat(target, "<span class='userdanger'>The gods have punished you for your sins!</span>")
if(ADMIN_PUNISHMENT_BRAINDAMAGE)
target.adjustBrainLoss(199, 199)
target.adjustOrganLoss(ORGAN_SLOT_BRAIN, 199, 199)
if(ADMIN_PUNISHMENT_GIB)
target.gib(FALSE)
if(ADMIN_PUNISHMENT_BSA)
@@ -151,7 +151,7 @@
if(2)
to_chat(H, "<span class='warning'>You hear an annoying buzz in your head.</span>")
H.confused += 15
H.adjustBrainLoss(10, 160)
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10, 160)
if(3)
H.hallucination += 60
@@ -83,7 +83,7 @@
if(istype(C))
var/obj/item/organ/brain/B = C.getorganslot(ORGAN_SLOT_BRAIN)
if(B && (B.decoy_override != initial(B.decoy_override)))
B.vital = TRUE
B.organ_flags |= ORGAN_VITAL
B.decoy_override = FALSE
remove_changeling_powers()
. = ..()
@@ -340,7 +340,7 @@
if(istype(C))
var/obj/item/organ/brain/B = C.getorganslot(ORGAN_SLOT_BRAIN)
if(B)
B.vital = FALSE
B.organ_flags &= ~ORGAN_VITAL
B.decoy_override = TRUE
update_changeling_icons_added()
return
@@ -35,7 +35,7 @@
B = new C.dna.species.mutant_brain()
else
B = new()
B.vital = FALSE
B.organ_flags &= ~ORGAN_VITAL
B.decoy_override = TRUE
B.Insert(C)
if(ishuman(user))
@@ -50,7 +50,7 @@
to_chat(user, "<span class='userdanger'>The helmet tries to drive a spike through your head as you scramble to remove it!</span>")
user.emote("scream")
user.apply_damage(30, BRUTE, BODY_ZONE_HEAD)
user.adjustBrainLoss(30)
user.adjustOrganLoss(ORGAN_SLOT_BRAIN, 30)
addtimer(CALLBACK(user, /mob/living.proc/dropItemToGround, src, TRUE), 1) //equipped happens before putting stuff on(but not before picking items up), 1). thus, we need to wait for it to be on before forcing it off.
/obj/item/clothing/head/helmet/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
@@ -80,6 +80,7 @@
desc = "Still it beats furiously, emanating an aura of utter hate."
icon = 'icons/obj/surgery.dmi'
icon_state = "demon_heart-on"
decay_factor = 0
/obj/item/organ/heart/demon/update_icon()
return //always beating visually
@@ -144,6 +144,13 @@
else
O.forceMove(src)
return TRUE
///Really simple proc, just moves the object "O" into the hands of mob "M" if able, done so I could modify the proc a little for the organ fridge
/obj/machinery/smartfridge/proc/dispense(obj/item/O, var/mob/M)
if(!M.put_in_hands(O))
O.forceMove(drop_location())
adjust_item_drop_location(O)
/obj/machinery/smartfridge/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
@@ -197,9 +204,7 @@
if(desired == 1 && Adjacent(usr) && !issilicon(usr))
for(var/obj/item/O in src)
if(O.name == params["name"])
if(!usr.put_in_hands(O))
O.forceMove(drop_location())
adjust_item_drop_location(O)
dispense(O, usr)
break
if (visible_contents)
update_icon()
@@ -209,8 +214,7 @@
if(desired <= 0)
break
if(O.name == params["name"])
O.forceMove(drop_location())
adjust_item_drop_location(O)
dispense(O, usr)
desired--
if (visible_contents)
update_icon()
@@ -378,6 +382,44 @@
/obj/machinery/smartfridge/extract/preloaded
initial_contents = list(/obj/item/slime_scanner = 2)
// ------------------------- You think you're better than Chem, huh?
// Organ Surgery Smartfridge
// ------------------------- Just wait till Tamiorgans
/obj/machinery/smartfridge/organ
name = "smart organ storage"
desc = "A refrigerated storage unit for organ storage."
max_n_of_items = 20 //vastly lower to prevent processing too long
var/repair_rate = 0
/obj/machinery/smartfridge/organ/accept_check(obj/item/O)
if(istype(O, /obj/item/organ))
return TRUE
return FALSE
/obj/machinery/smartfridge/organ/load(obj/item/O)
. = ..()
if(!.) //if the item loads, clear can_decompose
return
var/obj/item/organ/organ = O
organ.organ_flags |= ORGAN_FROZEN
/obj/machinery/smartfridge/organ/RefreshParts()
for(var/obj/item/stock_parts/matter_bin/B in component_parts)
max_n_of_items = 20 * B.rating
repair_rate = max(0, STANDARD_ORGAN_HEALING * (B.rating - 1))
/obj/machinery/smartfridge/organ/process()
for(var/organ in contents)
var/obj/item/organ/O = organ
if(!istype(O))
return
O.applyOrganDamage(-repair_rate)
/obj/machinery/smartfridge/organ/Exited(obj/item/organ/AM, atom/newLoc)
. = ..()
if(istype(AM))
AM.organ_flags &= ~ORGAN_FROZEN
// -----------------------------
// Chemistry Medical Smartfridge
// -----------------------------
@@ -399,7 +441,7 @@
return TRUE
if(!O.reagents || !O.reagents.reagent_list.len) // other empty containers not accepted
return FALSE
if(istype(O, /obj/item/reagent_containers/syringe) || istype(O, /obj/item/reagent_containers/glass/bottle) || istype(O, /obj/item/reagent_containers/glass/beaker) || istype(O, /obj/item/reagent_containers/spray) || istype(O, /obj/item/reagent_containers/medspray)|| istype(O, /obj/item/reagent_containers/chem_pack))
if(istype(O, /obj/item/reagent_containers/syringe) || istype(O, /obj/item/reagent_containers/glass/bottle) || istype(O, /obj/item/reagent_containers/glass/beaker) || istype(O, /obj/item/reagent_containers/spray) || istype(O, /obj/item/reagent_containers/medspray))
return TRUE
return FALSE
@@ -69,7 +69,7 @@ Chaplain
B.name = "Guys Gone Wild"
if("lol", "wtf", "gay", "penis", "ass", "poo", "badmin", "shitmin", "deadmin", "cock", "cocks", "meme", "memes")
B.name = pick("Woodys Got Wood: The Aftermath", "War of the Cocks", "Sweet Bro and Hella Jef: Expanded Edition")
H.adjustBrainLoss(100) // starts off retarded as fuck
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 100) // starts off retarded as fuck
if("science")
B.name = pick("Principle of Relativity", "Quantum Enigma: Physics Encounters Consciousness", "Programming the Universe", "Quantum Physics and Theology", "String Theory for Dummies", "How To: Build Your Own Warp Drive", "The Mysteries of Bluespace", "Playing God: Collector's Edition")
else
+2 -2
View File
@@ -50,8 +50,8 @@
if(U.job in list("Curator")) // the curator is both faster, and more accurate than normal crew members at research
speed = 100
correctness = 100
correctness -= U.getBrainLoss() *0.5 //Brain damage makes researching hard.
speed += U.getBrainLoss() * 3
correctness -= U.getOrganLoss(ORGAN_SLOT_BRAIN) *0.5 //Brain damage makes researching hard.
speed += U.getOrganLoss(ORGAN_SLOT_BRAIN) * 3
if(do_after(user, speed, 0, user))
var/usedName = devilName
if(!prob(correctness))
+3 -1
View File
@@ -57,13 +57,14 @@
newbrain.brainmob = null
brainmob.forceMove(src)
brainmob.container = src
if(!newbrain.damaged_brain) // the brain organ hasn't been beaten to death.
if(!(newbrain.organ_flags & ORGAN_FAILING)) // the brain organ hasn't been beaten to death.
brainmob.stat = CONSCIOUS //we manually revive the brain mob
GLOB.dead_mob_list -= brainmob
GLOB.alive_mob_list += brainmob
brainmob.reset_perspective()
brain = newbrain
brain.organ_flags |= ORGAN_FROZEN
name = "Man-Machine Interface: [brainmob.real_name]"
update_icon()
@@ -100,6 +101,7 @@
user.put_in_hands(brain) //puts brain in the user's hand or otherwise drops it on the user's turf
else
brain.forceMove(get_turf(src))
brain.organ_flags &= ~ORGAN_FROZEN
brain = null //No more brain in here
+141 -14
View File
@@ -7,11 +7,19 @@
layer = ABOVE_MOB_LAYER
zone = BODY_ZONE_HEAD
slot = ORGAN_SLOT_BRAIN
vital = TRUE
organ_flags = ORGAN_VITAL
attack_verb = list("attacked", "slapped", "whacked")
///The brain's organ variables are significantly more different than the other organs, with half the decay rate for balance reasons, and twice the maxHealth
decay_factor = STANDARD_ORGAN_DECAY / 4 //30 minutes of decaying to result in a fully damaged brain, since a fast decay rate would be unfun gameplay-wise
maxHealth = BRAIN_DAMAGE_DEATH
low_threshold = 45
high_threshold = 120
var/mob/living/brain/brainmob = null
var/damaged_brain = FALSE //whether the brain organ is damaged.
var/brain_death = FALSE //if the brainmob was intentionally killed by attacking the brain after removal, or by severe braindamage
var/decoy_override = FALSE //I apologize to the security players, and myself, who abused this, but this is going to go.
//two variables necessary for calculating whether we get a brain trauma or not
var/damage_delta = 0
var/list/datum/brain_trauma/traumas = list()
@@ -34,7 +42,7 @@
if(brainmob.mind)
brainmob.mind.transfer_to(C)
else
C.key = brainmob.key
brainmob.transfer_ckey(C)
QDEL_NULL(brainmob)
@@ -90,22 +98,89 @@
if(brainmob)
O.attack(brainmob, user) //Oh noooeeeee
/obj/item/organ/brain/examine(mob/user)
..()
if(istype(O, /obj/item/organ_storage)) //BUG_PROBABLE_CAUSE
return //Borg organ bags shouldn't be killing brains
if(brainmob)
if(brainmob.client)
if(brainmob.health <= HEALTH_THRESHOLD_DEAD)
to_chat(user, "It's lifeless and severely damaged.")
if((organ_flags & ORGAN_FAILING) && O.is_drainable() && O.reagents.has_reagent("neurine")) //Neurine fixes dead brains
. = TRUE //don't do attack animation.
var/cached_Bdamage = brainmob?.health
var/datum/reagent/medicine/neurine/N = reagents.has_reagent("neurine")
var/datum/reagent/medicine/mannitol/M1 = reagents.has_reagent("mannitol")
if(O.reagents.has_reagent("mannitol"))//Just a quick way to bolster the effects if someone mixes up a batch.
N.volume *= (M1.volume*0.5)
if(!O.reagents.has_reagent("neurine", 10))
to_chat(user, "<span class='warning'>There's not enough neurine in [O] to restore [src]!</span>")
return
user.visible_message("<span class='notice'>[user] starts to pour the contents of [O] onto [src].</span>", "<span class='notice'>You start to slowly pour the contents of [O] onto [src].</span>")
if(!do_after(user, 60, TRUE, src))
to_chat(user, "<span class='warning'>You failed to pour [O] onto [src]!</span>")
return
user.visible_message("<span class='notice'>[user] pours the contents of [O] onto [src], causing it to reform its original shape and turn a slightly brighter shade of pink.</span>", "<span class='notice'>You pour the contents of [O] onto [src], causing it to reform its original shape and turn a slightly brighter shade of pink.</span>")
setOrganDamage((damage - (0.10 * maxHealth)*(N.volume/10))) //heals a small amount, and by using "setorgandamage", we clear the failing variable if that was up
O.reagents.clear_reagents()
if(cached_Bdamage <= HEALTH_THRESHOLD_DEAD) //Fixing dead brains yeilds a trauma
if((cached_Bdamage <= HEALTH_THRESHOLD_DEAD) && (brainmob.health > HEALTH_THRESHOLD_DEAD))
if(prob(80))
gain_trauma_type(BRAIN_TRAUMA_MILD)
else if(prob(50))
gain_trauma_type(BRAIN_TRAUMA_SEVERE)
else
gain_trauma_type(BRAIN_TRAUMA_SPECIAL)
return
if((organ_flags & ORGAN_FAILING) && O.is_drainable() && O.reagents.has_reagent("mannitol")) //attempt to heal the brain
. = TRUE //don't do attack animation.
var/datum/reagent/medicine/mannitol/M = reagents.has_reagent("mannitol")
if(brain_death || brainmob?.health <= HEALTH_THRESHOLD_DEAD) //if the brain is fucked anyway, do nothing
to_chat(user, "<span class='warning'>[src] is far too damaged, you'll have to use neurine on it!</span>")
return
if(!O.reagents.has_reagent("mannitol", 10))
to_chat(user, "<span class='warning'>There's not enough mannitol in [O] to restore [src]!</span>")
return
user.visible_message("<span class='notice'>[user] starts to pour the contents of [O] onto [src].</span>", "<span class='notice'>You start to slowly pour the contents of [O] onto [src].</span>")
if(!do_after(user, 60, TRUE, src))
to_chat(user, "<span class='warning'>You failed to pour [O] onto [src]!</span>")
return
user.visible_message("<span class='notice'>[user] pours the contents of [O] onto [src], causing it to reform its original shape and turn a slightly brighter shade of pink.</span>", "<span class='notice'>You pour the contents of [O] onto [src], causing it to reform its original shape and turn a slightly brighter shade of pink.</span>")
setOrganDamage((damage - (0.05 * maxHealth)*(M.volume/10))) //heals a small amount, and by using "setorgandamage", we clear the failing variable if that was up
O.reagents.clear_reagents()
return
/obj/item/organ/brain/examine(mob/user)//BUG_PROBABLE_CAUSE to_chats changed to . +=
. = ..()
if(user.suiciding)
. += "<span class='info'>It's started turning slightly grey. They must not have been able to handle the stress of it all.</span>"
else if(brainmob)
if(brainmob.get_ghost(FALSE, TRUE))
if(brain_death || brainmob.health <= HEALTH_THRESHOLD_DEAD)
. += "<span class='info'>It's lifeless and severely damaged, only the strongest of chems will save it.</span>"
else if(organ_flags & ORGAN_FAILING)
. += "<span class='info'>It seems to still have a bit of energy within it, but it's rather damaged... You may be able to restore it with some <b>mannitol</b>.</span>"
else
to_chat(user, "You can feel the small spark of life still left in this one.")
. += "<span class='info'>You can feel the small spark of life still left in this one.</span>"
else if(organ_flags & ORGAN_FAILING)
. += "<span class='info'>It seems particularly lifeless and is rather damaged... You may be able to restore it with some <b>mannitol</b> incase it becomes functional again later.</span>"
else
to_chat(user, "This one seems particularly lifeless. Perhaps it will regain some of its luster later.")
. += "<span class='info'>This one seems particularly lifeless. Perhaps it will regain some of its luster later.</span>"
else
if(decoy_override)
to_chat(user, "This one seems particularly lifeless. Perhaps it will regain some of its luster later.")
if(organ_flags & ORGAN_FAILING)
. += "<span class='info'>It seems particularly lifeless and is rather damaged... You may be able to restore it with some <b>mannitol</b> incase it becomes functional again later.</span>"
else
. += "<span class='info'>This one seems particularly lifeless. Perhaps it will regain some of its luster later.</span>"
else
to_chat(user, "This one is completely devoid of life.")
. += "<span class='info'>This one is completely devoid of life.</span>"
/obj/item/organ/brain/attack(mob/living/carbon/C, mob/user)
if(!istype(C))
@@ -141,7 +216,7 @@
Insert(C)
else
..()
/* TO BE REMOVED, KEPT IN CASE OF BUGS
/obj/item/organ/brain/proc/get_brain_damage()
var/brain_damage_threshold = max_integrity * BRAIN_DAMAGE_INTEGRITY_MULTIPLIER
var/offset_integrity = obj_integrity - (max_integrity - brain_damage_threshold)
@@ -165,6 +240,54 @@
else if(adjusted_amount <= -DAMAGE_PRECISION)
obj_integrity = min(max_integrity, obj_integrity-adjusted_amount)
. = adjusted_amount
*/
/obj/item/organ/brain/on_life()
if(damage >= BRAIN_DAMAGE_DEATH) //rip
to_chat(owner, "<span class='userdanger'>The last spark of life in your brain fizzles out...</span>")
owner.death()
brain_death = TRUE
/obj/item/organ/brain/on_death()
if(damage <= BRAIN_DAMAGE_DEATH) //rip
brain_death = FALSE
applyOrganDamage(maxHealth * decay_factor)
/obj/item/organ/brain/applyOrganDamage(var/d, var/maximum = maxHealth)
..()
/obj/item/organ/brain/check_damage_thresholds(mob/M)
. = ..()
//if we're not more injured than before, return without gambling for a trauma
if(damage <= prev_damage)
return
damage_delta = damage - prev_damage
if(damage > BRAIN_DAMAGE_MILD)
if(prob(damage_delta * (1 + max(0, (damage - BRAIN_DAMAGE_MILD)/100)))) //Base chance is the hit damage; for every point of damage past the threshold the chance is increased by 1% //learn how to do your bloody math properly goddamnit
gain_trauma_type(BRAIN_TRAUMA_MILD)
if(damage > BRAIN_DAMAGE_SEVERE)
if(prob(damage_delta * (1 + max(0, (damage - BRAIN_DAMAGE_SEVERE)/100)))) //Base chance is the hit damage; for every point of damage past the threshold the chance is increased by 1%
if(prob(20))
gain_trauma_type(BRAIN_TRAUMA_SPECIAL)
else
gain_trauma_type(BRAIN_TRAUMA_SEVERE)
if (owner)
if(owner.stat < UNCONSCIOUS) //conscious or soft-crit
var/brain_message
if(prev_damage < BRAIN_DAMAGE_MILD && damage >= BRAIN_DAMAGE_MILD)
brain_message = "<span class='warning'>You feel lightheaded.</span>"
else if(prev_damage < BRAIN_DAMAGE_SEVERE && damage >= BRAIN_DAMAGE_SEVERE)
brain_message = "<span class='warning'>You feel less in control of your thoughts.</span>"
else if(prev_damage < (BRAIN_DAMAGE_DEATH - 20) && damage >= (BRAIN_DAMAGE_DEATH - 20))
brain_message = "<span class='warning'>You can feel your mind flickering on and off...</span>"
if(.)
. += "\n[brain_message]"
else
return brain_message
/obj/item/organ/brain/Destroy() //copypasted from MMIs.
if(brainmob)
@@ -200,6 +323,10 @@
return FALSE
if(!resilience)
resilience = initial(trauma.resilience)
if(!owner)
return FALSE
if(owner.stat == DEAD)
return FALSE
var/resilience_tier_count = 0
for(var/X in traumas)
+1 -1
View File
@@ -20,7 +20,7 @@
else if(istype(loc, /obj/item/organ/brain))
BR = loc
if(BR)
BR.damaged_brain = 1 //beaten to a pulp
BR.brain_death = TRUE
/mob/living/brain/proc/handle_emp_damage()
if(emp_damage)
@@ -22,6 +22,7 @@
return S
/obj/item/organ/body_egg/alien_embryo/on_life()
.=..()
switch(stage)
if(2, 3)
if(prob(2))
+1 -1
View File
@@ -814,7 +814,7 @@
reagents.clear_reagents()
var/obj/item/organ/brain/B = getorgan(/obj/item/organ/brain)
if(B)
B.damaged_brain = FALSE
B.brain_death = FALSE
for(var/thing in diseases)
var/datum/disease/D = thing
if(D.severity != DISEASE_SEVERITY_POSITIVE)
@@ -405,16 +405,16 @@
if(istype(ears) && (deafen_pwr || damage_pwr))
var/ear_damage = damage_pwr * effect_amount
var/deaf = max(ears.deaf, deafen_pwr * effect_amount)
var/deaf = deafen_pwr * effect_amount
adjustEarDamage(ear_damage,deaf)
if(ears.ear_damage >= 15)
if(ears.damage >= 15)
to_chat(src, "<span class='warning'>Your ears start to ring badly!</span>")
if(prob(ears.ear_damage - 5))
if(prob(ears.damage - 5))
to_chat(src, "<span class='userdanger'>You can't hear anything!</span>")
ears.ear_damage = min(ears.ear_damage, UNHEALING_EAR_DAMAGE)
ears.damage = min(ears.damage, ears.maxHealth)
// you need earmuffs, inacusiate, or replacement
else if(ears.ear_damage >= 5)
else if(ears.damage >= 5)
to_chat(src, "<span class='warning'>Your ears start to ring!</span>")
SEND_SOUND(src, sound('sound/weapons/flash_ring.ogg',0,1,0,250))
return effect_amount //how soundbanged we are
+49 -6
View File
@@ -47,7 +47,6 @@
adjustArousalLoss(damage * hit_percent)
return TRUE
//These procs fetch a cumulative total damage from all bodyparts
/mob/living/carbon/getBruteLoss()
var/amount = 0
@@ -63,7 +62,6 @@
amount += BP.burn_dam
return amount
/mob/living/carbon/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE)
if(!forced && (status_flags & GODMODE))
return FALSE
@@ -113,6 +111,50 @@
return
adjustStaminaLoss(diff, updating, forced)
/** adjustOrganLoss
* inputs: slot (organ slot, like ORGAN_SLOT_HEART), amount (damage to be done), and maximum (currently an arbitrarily large number, can be set so as to limit damage)
* outputs:
* description: If an organ exists in the slot requested, and we are capable of taking damage (we don't have GODMODE on), call the damage proc on that organ.
*/
/mob/living/carbon/adjustOrganLoss(slot, amount, maximum)
var/obj/item/organ/O = getorganslot(slot)
if(O && !(status_flags & GODMODE))
if(!maximum)
maximum = O.maxHealth
O.applyOrganDamage(amount, maximum)
O.onDamage(amount, maximum)
/** setOrganLoss
* inputs: slot (organ slot, like ORGAN_SLOT_HEART), amount(damage to be set to)
* outputs:
* description: If an organ exists in the slot requested, and we are capable of taking damage (we don't have GODMODE on), call the set damage proc on that organ, which can
* set or clear the failing variable on that organ, making it either cease or start functions again, unlike adjustOrganLoss.
*/
/mob/living/carbon/setOrganLoss(slot, amount)
var/obj/item/organ/O = getorganslot(slot)
if(O && !(status_flags & GODMODE))
O.setOrganDamage(amount)
O.onSetDamage(amount)
/** getOrganLoss
* inputs: slot (organ slot, like ORGAN_SLOT_HEART)
* outputs: organ damage
* description: If an organ exists in the slot requested, return the amount of damage that organ has
*/
/mob/living/carbon/getOrganLoss(slot)
var/obj/item/organ/O = getorganslot(slot)
if(O)
return O.damage
/mob/living/carbon/proc/adjustAllOrganLoss(amount, maximum)
for(var/obj/item/organ/O in internal_organs)
if(O && !(status_flags & GODMODE))
continue
if(!maximum)
maximum = O.maxHealth
O.applyOrganDamage(amount, maximum)
O.onDamage(amount, maximum)
////////////////////////////////////////////
//Returns a list of damaged bodyparts
@@ -213,24 +255,25 @@
update_damage_overlays()
update_stamina()
/mob/living/carbon/getBrainLoss()
/* TO_REMOVE
/mob/living/carbon/getOrganLoss(ORGAN_SLOT_BRAIN)
. = 0
var/obj/item/organ/brain/B = getorganslot(ORGAN_SLOT_BRAIN)
if(B)
. = B.get_brain_damage()
//Some sources of brain damage shouldn't be deadly
/mob/living/carbon/adjustBrainLoss(amount, maximum = BRAIN_DAMAGE_DEATH)
/mob/living/carbon/adjustOrganLoss(ORGAN_SLOT_BRAIN, amount, maximum = BRAIN_DAMAGE_DEATH)
if(status_flags & GODMODE)
return FALSE
var/prev_brainloss = getBrainLoss()
var/prev_brainloss = getOrganLoss(ORGAN_SLOT_BRAIN)
var/obj/item/organ/brain/B = getorganslot(ORGAN_SLOT_BRAIN)
if(!B)
return
B.adjust_brain_damage(amount, maximum)
if(amount <= 0) //cut this early
return
var/brainloss = getBrainLoss()
var/brainloss = getOrganLoss(ORGAN_SLOT_BRAIN)
if(brainloss > BRAIN_DAMAGE_MILD)
if(prob(amount * ((2 * (100 + brainloss - BRAIN_DAMAGE_MILD)) / 100))) //Base chance is the hit damage; for every point of damage past the threshold the chance is increased by 2%
gain_trauma_type(BRAIN_TRAUMA_MILD)
@@ -348,10 +348,15 @@
if(temp)
var/update = 0
var/dmg = rand(M.force/2, M.force)
var/atom/throw_target = get_edge_target_turf(src, M.dir)
switch(M.damtype)
if("brute")
if(M.force > 20)
Unconscious(20)
if(M.force > 35) // durand and other heavy mechas
Knockdown(50)
src.throw_at(throw_target, rand(1,5), 7)
else if(M.force >= 20 && !IsKnockdown()) // lightweight mechas like gygax
Knockdown(30)
src.throw_at(throw_target, rand(1,3), 7)
update |= temp.receive_damage(dmg, 0)
playsound(src, 'sound/weapons/punch4.ogg', 50, 1)
if("fire")
@@ -746,9 +751,54 @@
if(0 to NUTRITION_LEVEL_STARVING)
to_send += "<span class='danger'>You're starving!</span>\n"
//TODO: Convert these messages into vague messages, thereby encouraging actual dignosis.
//Compiles then shows the list of damaged organs and broken organs
var/list/broken = list()
var/list/damaged = list()
var/broken_message
var/damaged_message
var/broken_plural
var/damaged_plural
//Sets organs into their proper list
for(var/O in internal_organs)
var/obj/item/organ/organ = O
if(organ.organ_flags & ORGAN_FAILING)
if(broken.len)
broken += ", "
broken += organ.name
else if(organ.damage > organ.low_threshold)
if(damaged.len)
damaged += ", "
damaged += organ.name
//Checks to enforce proper grammar, inserts words as necessary into the list
if(broken.len)
if(broken.len > 1)
broken.Insert(broken.len, "and ")
broken_plural = TRUE
else
var/holder = broken[1] //our one and only element
if(holder[lentext(holder)] == "s")
broken_plural = TRUE
//Put the items in that list into a string of text
for(var/B in broken)
broken_message += B
to_chat(src, "<span class='warning'> Your [broken_message] [broken_plural ? "are" : "is"] non-functional!</span>")
if(damaged.len)
if(damaged.len > 1)
damaged.Insert(damaged.len, "and ")
damaged_plural = TRUE
else
var/holder = damaged[1]
if(holder[lentext(holder)] == "s")
damaged_plural = TRUE
for(var/D in damaged)
damaged_message += D
to_chat(src, "<span class='info'>Your [damaged_message] [damaged_plural ? "are" : "is"] hurt.</span>")
if(roundstart_quirks.len)
to_send += "<span class='notice'>You have these quirks: [get_trait_string()].</span>\n"
to_chat(src, to_send)
else
if(wear_suit)
+1 -1
View File
@@ -71,7 +71,7 @@
else if(eye_blurry) //blurry eyes heal slowly
adjust_blurriness(-1)
if (getBrainLoss() >= 30) //Citadel change to make memes more often.
if (getOrganLoss(ORGAN_SLOT_BRAIN) >= 30) //Citadel change to make memes more often.
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "brain_damage", /datum/mood_event/brain_damage)
if(prob(3))
if(prob(25))
+235 -33
View File
@@ -1,6 +1,7 @@
// This code handles different species in the game.
GLOBAL_LIST_EMPTY(roundstart_races)
GLOBAL_LIST_EMPTY(roundstart_race_names)
/datum/species
var/id // if the game needs to manually check your race to do something not included in a proc here, it will use this
@@ -8,13 +9,35 @@ GLOBAL_LIST_EMPTY(roundstart_races)
var/name // this is the fluff name. these will be left generic (such as 'Lizardperson' for the lizard race) so servers can change them to whatever
var/default_color = "#FFF" // if alien colors are disabled, this is the color that will be used by that race
var/sexes = 1 // whether or not the race has sexual characteristics. at the moment this is only 0 for skeletons and shadows
var/sexes = 1 // whether or not the race has sexual characteristics. at the moment this is only 0 for skeletons and shadows
var/list/offset_features = list(OFFSET_UNIFORM = list(0,0), OFFSET_ID = list(0,0), OFFSET_GLOVES = list(0,0), OFFSET_GLASSES = list(0,0), OFFSET_EARS = list(0,0), OFFSET_SHOES = list(0,0), OFFSET_S_STORE = list(0,0), OFFSET_FACEMASK = list(0,0), OFFSET_HEAD = list(0,0), OFFSET_FACE = list(0,0), OFFSET_BELT = list(0,0), OFFSET_BACK = list(0,0), OFFSET_SUIT = list(0,0), OFFSET_NECK = list(0,0))
//Species Icon Drawing Offsets - Pixel X, Pixel Y, Aka X = Horizontal and Y = Vertical, from bottom left corner
var/list/offset_features = list(
OFFSET_UNIFORM = list(0,0),
OFFSET_ID = list(0,0),
OFFSET_GLOVES = list(0,0),
OFFSET_GLASSES = list(0,0),
OFFSET_EARS = list(0,0),
OFFSET_SHOES = list(0,0),
OFFSET_S_STORE = list(0,0),
OFFSET_FACEMASK = list(0,0),
OFFSET_HEAD = list(0,0),
OFFSET_EYES = list(0,0),
OFFSET_LIPS = list(0,0),
OFFSET_BELT = list(0,0),
OFFSET_BACK = list(0,0),
OFFSET_HAIR = list(0,0),
OFFSET_FHAIR = list(0,0),
OFFSET_SUIT = list(0,0),
OFFSET_NECK = list(0,0),
OFFSET_MUTPARTS = list(0,0)
)
var/hair_color // this allows races to have specific hair colors... if null, it uses the H's hair/facial hair colors. if "mutcolor", it uses the H's mutant_color
var/hair_alpha = 255 // the alpha used by the hair. 255 is completely solid, 0 is transparent.
var/horn_color //specific horn colors, because why not?
var/use_skintones = 0 // does it use skintones or not? (spoiler alert this is only used by humans)
var/exotic_blood = "" // If your race wants to bleed something other than bog standard blood, change this to reagent id.
var/exotic_bloodtype = "" //If your race uses a non standard bloodtype (A+, O-, AB-, etc)
@@ -79,7 +102,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
var/fixed_mut_color3 = ""
var/whitelisted = 0 //Is this species restricted to certain players?
var/whitelist = list() //List the ckeys that can use this species, if it's whitelisted.: list("John Doe", "poopface666", "SeeALiggerPullTheTrigger") Spaces & capitalization can be included or ignored entirely for each key as it checks for both.
var/should_draw_citadel = FALSE
///////////
// PROCS //
@@ -98,6 +121,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
var/datum/species/S = new I
if(S.check_roundstart_eligible())
GLOB.roundstart_races += S.id
GLOB.roundstart_race_names["[S.name]"] = S.id
qdel(S)
if(!GLOB.roundstart_races.len)
GLOB.roundstart_races += "human"
@@ -129,10 +153,10 @@ GLOBAL_LIST_EMPTY(roundstart_races)
return
//Please override this locally if you want to define when what species qualifies for what rank if human authority is enforced.
/datum/species/proc/qualifies_for_rank(rank, list/features)
if(rank in GLOB.command_positions)
return 0
return 1
/datum/species/proc/qualifies_for_rank(rank, list/features) //SPECIES JOB RESTRICTIONS
//if(rank in GLOB.command_positions) Left as an example: The format qualifies for rank takes.
// return 0 //It returns false when it runs the proc so they don't get jobs from the global list.
return 1 //It returns 1 to say they are a-okay to continue.
//Will regenerate missing organs
/datum/species/proc/regenerate_organs(mob/living/carbon/C,datum/species/old_species,replace_current=TRUE)
@@ -260,7 +284,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
C.hud_used.update_locked_slots()
// this needs to be FIRST because qdel calls update_body which checks if we have DIGITIGRADE legs or not and if not then removes DIGITIGRADE from species_traits
if(("legs" in C.dna.species.mutant_bodyparts) && C.dna.features["legs"] == "Digitigrade Legs")
if(("legs" in C.dna.species.mutant_bodyparts) && (C.dna.features["legs"] == "Digitigrade" || C.dna.features["legs"] == "Avian"))
species_traits += DIGITIGRADE
if(DIGITIGRADE in species_traits)
C.Digitigrade_Leg_Swap(FALSE)
@@ -294,8 +318,6 @@ GLOBAL_LIST_EMPTY(roundstart_races)
for(var/datum/disease/A in C.diseases)
A.cure(FALSE)
SEND_SIGNAL(C, COMSIG_SPECIES_GAIN, src, old_species)
//CITADEL EDIT
if(NOAROUSAL in species_traits)
C.canbearoused = FALSE
@@ -306,6 +328,11 @@ GLOBAL_LIST_EMPTY(roundstart_races)
var/mob/living/carbon/human/H = C
if(NOGENITALS in H.dna.species.species_traits)
H.give_genitals(TRUE) //call the clean up proc to delete anything on the mob then return.
if("meat_type" in default_features) //I can't believe it's come to the meat
H.type_of_meat = GLOB.meat_types[H.dna.features["meat_type"]]
SEND_SIGNAL(C, COMSIG_SPECIES_GAIN, src, old_species)
// EDIT ENDS
@@ -317,6 +344,11 @@ GLOBAL_LIST_EMPTY(roundstart_races)
for(var/X in inherent_traits)
REMOVE_TRAIT(C, X, SPECIES_TRAIT)
if("meat_type" in default_features)
C.type_of_meat = GLOB.meat_types[C.dna.features["meat_type"]]
else
C.type_of_meat = initial(meat)
SEND_SIGNAL(C, COMSIG_SPECIES_LOSS, src)
/datum/species/proc/handle_hair(mob/living/carbon/human/H, forced_colour)
@@ -389,6 +421,10 @@ GLOBAL_LIST_EMPTY(roundstart_races)
facial_overlay.alpha = hair_alpha
if(OFFSET_FHAIR in H.dna.species.offset_features)
facial_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FHAIR][1]
facial_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FHAIR][2]
standing += facial_overlay
if(H.head)
@@ -446,9 +482,11 @@ GLOBAL_LIST_EMPTY(roundstart_races)
else
hair_overlay.color = forced_colour
hair_overlay.alpha = hair_alpha
if(OFFSET_FACE in H.dna.species.offset_features)
hair_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FACE][1]
hair_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FACE][2]
if(OFFSET_HAIR in H.dna.species.offset_features)
hair_overlay.pixel_x += H.dna.species.offset_features[OFFSET_HAIR][1]
hair_overlay.pixel_y += H.dna.species.offset_features[OFFSET_HAIR][2]
if(hair_overlay.icon)
standing += hair_overlay
@@ -469,9 +507,11 @@ GLOBAL_LIST_EMPTY(roundstart_races)
if(H.lip_style && (LIPS in species_traits))
var/mutable_appearance/lip_overlay = mutable_appearance('icons/mob/human_face.dmi', "lips_[H.lip_style]", -BODY_LAYER)
lip_overlay.color = H.lip_color
if(OFFSET_FACE in H.dna.species.offset_features)
lip_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FACE][1]
lip_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FACE][2]
if(OFFSET_LIPS in H.dna.species.offset_features)
lip_overlay.pixel_x += H.dna.species.offset_features[OFFSET_LIPS][1]
lip_overlay.pixel_y += H.dna.species.offset_features[OFFSET_LIPS][2]
standing += lip_overlay
// eyes
@@ -484,9 +524,11 @@ GLOBAL_LIST_EMPTY(roundstart_races)
eye_overlay = mutable_appearance('icons/mob/human_face.dmi', "eyes", -BODY_LAYER)
if((EYECOLOR in species_traits) && has_eyes)
eye_overlay.color = "#" + H.eye_color
if(OFFSET_FACE in H.dna.species.offset_features)
eye_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FACE][1]
eye_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FACE][2]
if(OFFSET_EYES in H.dna.species.offset_features)
eye_overlay.pixel_x += H.dna.species.offset_features[OFFSET_EYES][1]
eye_overlay.pixel_y += H.dna.species.offset_features[OFFSET_EYES][2]
standing += eye_overlay
//Underwear, Undershirts & Socks
@@ -529,7 +571,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
var/digilegs = (DIGITIGRADE in species_traits) ? "_d" : ""
var/mutable_appearance/MA = mutable_appearance(S.icon, "[S.icon_state][digilegs]", -BODY_LAYER)
if(UNDIE_COLORABLE(S))
MA.color = "[H.socks_color]"
MA.color = "#[H.socks_color]"
standing += MA
if(standing.len)
@@ -612,6 +654,10 @@ GLOBAL_LIST_EMPTY(roundstart_races)
else if ("wings" in mutant_bodyparts)
bodyparts_to_add -= "wings_open"
if("insect_fluff" in mutant_bodyparts)
if(!H.dna.features["insect_fluff"] || H.dna.features["insect_fluff"] == "None" || H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT))
bodyparts_to_add -= "insect_fluff"
//CITADEL EDIT
//Race specific bodyparts:
//Xenos
@@ -715,12 +761,14 @@ GLOBAL_LIST_EMPTY(roundstart_races)
S = GLOB.wings_list[H.dna.features["wings"]]
if("wingsopen")
S = GLOB.wings_open_list[H.dna.features["wings"]]
if("deco_wings")
S = GLOB.deco_wings_list[H.dna.features["deco_wings"]]
if("legs")
S = GLOB.legs_list[H.dna.features["legs"]]
if("moth_wings")
S = GLOB.moth_wings_list[H.dna.features["moth_wings"]]
if("moth_markings")
S = GLOB.moth_markings_list[H.dna.features["moth_markings"]]
if("insect_wings")
S = GLOB.insect_wings_list[H.dna.features["insect_wings"]]
if("insect_fluff")
S = GLOB.insect_fluffs_list[H.dna.features["insect_fluff"]]
if("caps")
S = GLOB.caps_list[H.dna.features["caps"]]
if("ipc_screen")
@@ -817,6 +865,8 @@ GLOBAL_LIST_EMPTY(roundstart_races)
accessory_overlay.color = "#[H.facial_hair_color]"
if(EYECOLOR)
accessory_overlay.color = "#[H.eye_color]"
if(HORNCOLOR)
accessory_overlay.color = "#[H.horn_color]"
else
accessory_overlay.color = forced_colour
else
@@ -833,6 +883,11 @@ GLOBAL_LIST_EMPTY(roundstart_races)
for(var/index=1, index<=husklist.len, index++)
husklist[index] = husklist[index]/255
accessory_overlay.color = husklist
if(OFFSET_MUTPARTS in H.dna.species.offset_features)
accessory_overlay.pixel_x += H.dna.species.offset_features[OFFSET_MUTPARTS][1]
accessory_overlay.pixel_y += H.dna.species.offset_features[OFFSET_MUTPARTS][2]
standing += accessory_overlay
if(S.hasinner)
@@ -845,6 +900,10 @@ GLOBAL_LIST_EMPTY(roundstart_races)
if(S.center)
inner_accessory_overlay = center_image(inner_accessory_overlay, S.dimension_x, S.dimension_y)
if(OFFSET_MUTPARTS in H.dna.species.offset_features)
inner_accessory_overlay.pixel_x += H.dna.species.offset_features[OFFSET_MUTPARTS][1]
inner_accessory_overlay.pixel_y += H.dna.species.offset_features[OFFSET_MUTPARTS][2]
standing += inner_accessory_overlay
if(S.extra) //apply the extra overlay, if there is one
@@ -882,6 +941,14 @@ GLOBAL_LIST_EMPTY(roundstart_races)
extra_accessory_overlay.color = "#[H.facial_hair_color]"
if(EYECOLOR)
extra_accessory_overlay.color = "#[H.eye_color]"
if(HORNCOLOR)
extra_accessory_overlay.color = "#[H.horn_color]"
if(OFFSET_MUTPARTS in H.dna.species.offset_features)
extra_accessory_overlay.pixel_x += H.dna.species.offset_features[OFFSET_MUTPARTS][1]
extra_accessory_overlay.pixel_y += H.dna.species.offset_features[OFFSET_MUTPARTS][2]
standing += extra_accessory_overlay
if(S.extra2) //apply the extra overlay, if there is one
@@ -914,6 +981,13 @@ GLOBAL_LIST_EMPTY(roundstart_races)
extra2_accessory_overlay.color = "#[H.dna.features["mcolor"]]"
else
extra2_accessory_overlay.color = "#[H.hair_color]"
if(HORNCOLOR)
extra2_accessory_overlay.color = "#[H.horn_color]"
if(OFFSET_MUTPARTS in H.dna.species.offset_features)
extra2_accessory_overlay.pixel_x += H.dna.species.offset_features[OFFSET_MUTPARTS][1]
extra2_accessory_overlay.pixel_y += H.dna.species.offset_features[OFFSET_MUTPARTS][2]
standing += extra2_accessory_overlay
@@ -1198,9 +1272,14 @@ GLOBAL_LIST_EMPTY(roundstart_races)
if(mood && mood.sanity > SANITY_DISTURBED)
hunger_rate *= max(0.5, 1 - 0.002 * mood.sanity) //0.85 to 0.75
if(H.satiety > 0)
// Whether we cap off our satiety or move it towards 0
if(H.satiety > MAX_SATIETY)
H.satiety = MAX_SATIETY
else if(H.satiety > 0)
H.satiety--
if(H.satiety < 0)
else if(H.satiety < -MAX_SATIETY)
H.satiety = -MAX_SATIETY
else if(H.satiety < 0)
H.satiety++
if(prob(round(-H.satiety/40)))
H.Jitter(5)
@@ -1316,9 +1395,9 @@ GLOBAL_LIST_EMPTY(roundstart_races)
if(!istype(J) && istype(C))
J = C.jetpack
if(istype(J) && J.full_speed && J.allow_thrust(0.01, H)) //Prevents stacking
. -= 2
. -= 0.4
else if(istype(T) && T.allow_thrust(0.01, H))
. -= 2
. -= 0.4
if(!ignoreslow && gravity)
if(H.wear_suit)
@@ -1685,7 +1764,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
if(BODY_ZONE_HEAD)
if(!I.is_sharp() && armor_block < 50)
if(prob(I.force))
H.adjustBrainLoss(20)
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 20)
if(H.stat == CONSCIOUS)
H.visible_message("<span class='danger'>[H] has been knocked senseless!</span>", \
"<span class='userdanger'>[H] has been knocked senseless!</span>")
@@ -1694,11 +1773,11 @@ GLOBAL_LIST_EMPTY(roundstart_races)
if(prob(10))
H.gain_trauma(/datum/brain_trauma/mild/concussion)
else
H.adjustBrainLoss(I.force * 0.2)
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, I.force * 0.2)
if(H.stat == CONSCIOUS && H != user && prob(I.force + ((100 - H.health) * 0.5))) // rev deconversion through blunt trauma.
var/datum/antagonist/rev/rev = H.mind.has_antag_datum(/datum/antagonist/rev)
var/datum/antagonist/gang/gang = H.mind.has_antag_datum(/datum/antagonist/gang/)
var/datum/antagonist/gang/gang = H.mind.has_antag_datum(/datum/antagonist/gang && !/datum/antagonist/gang/boss)
if(rev)
rev.remove_revolutionary(FALSE, user)
if(gang)
@@ -1734,6 +1813,130 @@ GLOBAL_LIST_EMPTY(roundstart_races)
H.forcesay(GLOB.hit_appends) //forcesay checks stat already.
return TRUE
/datum/species/proc/alt_spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style)
if(!istype(M))
return TRUE
CHECK_DNA_AND_SPECIES(M)
CHECK_DNA_AND_SPECIES(H)
if(!istype(M)) //sanity check for drones.
return TRUE
if(M.mind)
attacker_style = M.mind.martial_art
if((M != H) && M.a_intent != INTENT_HELP && H.check_shields(M, 0, M.name, attack_type = UNARMED_ATTACK))
log_combat(M, H, "attempted to touch")
H.visible_message("<span class='warning'>[M] attempted to touch [H]!</span>")
return TRUE
switch(M.a_intent)
if(INTENT_HELP)
if(M == H)
althelp(M, H, attacker_style)
return TRUE
return FALSE
if(INTENT_DISARM)
altdisarm(M, H, attacker_style)
return TRUE
return FALSE
/datum/species/proc/althelp(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style)
if(user == target && istype(user))
if(user.getStaminaLoss() >= STAMINA_SOFTCRIT)
to_chat(user, "<span class='warning'>You're too exhausted for that.</span>")
return
if(!user.resting)
to_chat(user, "<span class='notice'>You can only force yourself up if you're on the ground.</span>")
return
user.visible_message("<span class='notice'>[user] forces [p_them()]self up to [p_their()] feet!</span>", "<span class='notice'>You force yourself up to your feet!</span>")
user.resting = 0
user.update_canmove()
user.adjustStaminaLossBuffered(user.stambuffer) //Rewards good stamina management by making it easier to instantly get up from resting
playsound(user, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
/datum/species/proc/altdisarm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style)
if(user.getStaminaLoss() >= STAMINA_SOFTCRIT)
to_chat(user, "<span class='warning'>You're too exhausted.</span>")
return FALSE
if(target.check_block())
target.visible_message("<span class='warning'>[target] blocks [user]'s shoving attempt!</span>")
return FALSE
if(attacker_style && attacker_style.disarm_act(user,target))
return TRUE
if(user.resting)
return FALSE
else
if(user == target)
return
user.do_attack_animation(target, ATTACK_EFFECT_DISARM)
user.adjustStaminaLossBuffered(4)
playsound(target, 'sound/weapons/thudswoosh.ogg', 50, TRUE, -1)
if(target.w_uniform)
target.w_uniform.add_fingerprint(user)
SEND_SIGNAL(target, COMSIG_HUMAN_DISARM_HIT, user, user.zone_selected)
if(!target.resting)
target.adjustStaminaLoss(5)
if(target.is_shove_knockdown_blocked())
return
var/turf/target_oldturf = target.loc
var/shove_dir = get_dir(user.loc, target_oldturf)
var/turf/target_shove_turf = get_step(target.loc, shove_dir)
var/mob/living/carbon/human/target_collateral_human
var/shove_blocked = FALSE //Used to check if a shove is blocked so that if it is knockdown logic can be applied
//Thank you based whoneedsspace
target_collateral_human = locate(/mob/living/carbon/human) in target_shove_turf.contents
if(target_collateral_human && !target_collateral_human.resting)
shove_blocked = TRUE
else
target_collateral_human = null
target.Move(target_shove_turf, shove_dir)
if(get_turf(target) == target_oldturf)
shove_blocked = TRUE
if(shove_blocked && !target.buckled)
var/directional_blocked = !target.Adjacent(target_shove_turf)
var/targetatrest = target.resting
if((directional_blocked || !(target_collateral_human || target_shove_turf.shove_act(target, user))) && !targetatrest)
target.Knockdown(SHOVE_KNOCKDOWN_SOLID)
user.visible_message("<span class='danger'>[user.name] shoves [target.name], knocking them down!</span>",
"<span class='danger'>You shove [target.name], knocking them down!</span>", null, COMBAT_MESSAGE_RANGE)
log_combat(user, target, "shoved", "knocking them down")
else if(target_collateral_human && !targetatrest)
target.Knockdown(SHOVE_KNOCKDOWN_HUMAN)
target_collateral_human.Knockdown(SHOVE_KNOCKDOWN_COLLATERAL)
user.visible_message("<span class='danger'>[user.name] shoves [target.name] into [target_collateral_human.name]!</span>",
"<span class='danger'>You shove [target.name] into [target_collateral_human.name]!</span>", null, COMBAT_MESSAGE_RANGE)
log_combat(user, target, "shoved", "into [target_collateral_human.name]")
else
user.visible_message("<span class='danger'>[user.name] shoves [target.name]!</span>",
"<span class='danger'>You shove [target.name]!</span>", null, COMBAT_MESSAGE_RANGE)
var/target_held_item = target.get_active_held_item()
var/knocked_item = FALSE
if(!is_type_in_typecache(target_held_item, GLOB.shove_disarming_types))
target_held_item = null
if(!target.has_movespeed_modifier(SHOVE_SLOWDOWN_ID))
target.add_movespeed_modifier(SHOVE_SLOWDOWN_ID, multiplicative_slowdown = SHOVE_SLOWDOWN_STRENGTH)
if(target_held_item)
target.visible_message("<span class='danger'>[target.name]'s grip on \the [target_held_item] loosens!</span>",
"<span class='danger'>Your grip on \the [target_held_item] loosens!</span>", null, COMBAT_MESSAGE_RANGE)
addtimer(CALLBACK(target, /mob/living/carbon/human/proc/clear_shove_slowdown), SHOVE_SLOWDOWN_LENGTH)
else if(target_held_item)
target.dropItemToGround(target_held_item)
knocked_item = TRUE
target.visible_message("<span class='danger'>[target.name] drops \the [target_held_item]!!</span>",
"<span class='danger'>You drop \the [target_held_item]!!</span>", null, COMBAT_MESSAGE_RANGE)
var/append_message = ""
if(target_held_item)
if(knocked_item)
append_message = "causing them to drop [target_held_item]"
else
append_message = "loosening their grip on [target_held_item]"
log_combat(user, target, "shoved", append_message)
/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H)
var/hit_percent = (100-(blocked+armor))/100
hit_percent = (hit_percent * (100-H.physiology.damage_resistance))/100
@@ -1783,14 +1986,13 @@ GLOBAL_LIST_EMPTY(roundstart_races)
if(CLONE)
H.adjustCloneLoss(damage * hit_percent * H.physiology.clone_mod)
if(STAMINA)
H.stamdamageoverlaytemp = 20
if(BP)
if(damage > 0 ? BP.receive_damage(0, 0, damage * hit_percent * H.physiology.stamina_mod) : BP.heal_damage(0, 0, abs(damage * hit_percent * H.physiology.stamina_mod), only_robotic = FALSE, only_organic = FALSE))
H.update_stamina()
else
H.adjustStaminaLoss(damage * hit_percent * H.physiology.stamina_mod)
if(BRAIN)
H.adjustBrainLoss(damage * hit_percent * H.physiology.brain_mod)
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, damage * hit_percent * H.physiology.brain_mod)
if(AROUSAL) //Citadel edit - arousal
H.adjustArousalLoss(damage * hit_percent)
return 1
@@ -64,7 +64,7 @@
/obj/item/organ/brain/dullahan
decoy_override = TRUE
vital = FALSE
organ_flags = 0
/obj/item/organ/tongue/dullahan
zone = "abstract"
@@ -102,6 +102,7 @@
color = "#1C1C1C"
var/respawn_progress = 0
var/obj/item/light_eater/blade
decay_factor = 0
/obj/item/organ/heart/nightmare/attack(mob/M, mob/living/carbon/user, obj/target)
@@ -122,10 +123,8 @@
if(special != HEART_SPECIAL_SHADOWIFY)
blade = new/obj/item/light_eater
M.put_in_hands(blade)
START_PROCESSING(SSobj, src)
/obj/item/organ/heart/nightmare/Remove(mob/living/carbon/M, special = 0)
STOP_PROCESSING(SSobj, src)
respawn_progress = 0
if(blade && special != HEART_SPECIAL_SHADOWIFY)
QDEL_NULL(blade)
@@ -138,9 +137,8 @@
/obj/item/organ/heart/nightmare/update_icon()
return //always beating visually
/obj/item/organ/heart/nightmare/process()
if(QDELETED(owner) || owner.stat != DEAD)
respawn_progress = 0
/obj/item/organ/heart/nightmare/on_death()
if(!owner)
return
var/turf/T = get_turf(owner)
if(istype(T))
+38 -20
View File
@@ -9,9 +9,10 @@
stamdamageoverlaytemp = 0
update_damage_hud()
if(!IsInStasis())
if(stat != DEAD) //Reagent processing needs to come before breathing, to prevent edge cases.
handle_organs()
//Reagent processing needs to come before breathing, to prevent edge cases.
handle_organs()
. = ..()
@@ -49,8 +50,22 @@
//Start of a breath chain, calls breathe()
/mob/living/carbon/handle_breathing(times_fired)
if((times_fired % 4) == 2 || failed_last_breath)
breathe() //Breathe per 4 ticks, unless suffocating
var/next_breath = 4
var/obj/item/organ/lungs/L = getorganslot(ORGAN_SLOT_LUNGS)
var/obj/item/organ/heart/H = getorganslot(ORGAN_SLOT_HEART)
if(L)
if(L.damage > L.high_threshold)
next_breath--
if(H)
if(H.damage > H.high_threshold)
next_breath--
if((times_fired % next_breath) == 0 || failed_last_breath)
breathe() //Breathe per 4 ticks if healthy, down to 2 if our lungs or heart are damaged, unless suffocating
if(failed_last_breath)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "suffocation", /datum/mood_event/suffocation)
else
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "suffocation")
else
if(istype(loc, /obj/))
var/obj/location_as_object = loc
@@ -58,6 +73,7 @@
//Second link in a breath chain, calls check_breath()
/mob/living/carbon/proc/breathe()
var/obj/item/organ/lungs = getorganslot(ORGAN_SLOT_LUNGS)
if(reagents.has_reagent("lexorin"))
return
if(istype(loc, /obj/machinery/atmospherics/components/unary/cryo_cell))
@@ -76,7 +92,7 @@
var/datum/gas_mixture/breath
if(!getorganslot(ORGAN_SLOT_BREATHING_TUBE))
if(health <= HEALTH_THRESHOLD_FULLCRIT || (pulledby && pulledby.grab_state >= GRAB_KILL))
if(health <= HEALTH_THRESHOLD_FULLCRIT || (pulledby && pulledby.grab_state >= GRAB_KILL) || lungs.organ_flags & ORGAN_FAILING)
losebreath++ //You can't breath at all when in critical or when being choked, so you're going to miss a breath
else if(health <= crit_threshold)
@@ -128,7 +144,7 @@
if((status_flags & GODMODE))
return
var/lungs = getorganslot(ORGAN_SLOT_LUNGS)
var/obj/item/organ/lungs = getorganslot(ORGAN_SLOT_LUNGS)
if(!lungs)
adjustOxyLoss(2)
@@ -368,9 +384,18 @@
. |= BP.on_life()
/mob/living/carbon/proc/handle_organs()
for(var/V in internal_organs)
var/obj/item/organ/O = V
O.on_life()
if(stat != DEAD)
for(var/V in internal_organs)
var/obj/item/organ/O = V
if(O)
O.on_life()
else
for(var/V in internal_organs)
var/obj/item/organ/O = V
if(O)
O.on_death() //Needed so organs decay while inside the body.
/mob/living/carbon/handle_diseases()
for(var/thing in diseases)
@@ -615,7 +640,7 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
to_chat(src, "<span class='warning'>Maybe you should lie down for a bit...</span>")
if(drunkenness >= 91)
adjustBrainLoss(0.4, 60)
adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.4, 60)
if(prob(20) && !stat)
if(SSshuttle.emergency.mode == SHUTTLE_DOCKED && is_station_level(z)) //QoL mainly
to_chat(src, "<span class='warning'>You're so tired... but you can't miss that shuttle...</span>")
@@ -649,8 +674,8 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
if((!dna && !liver) || (NOLIVER in dna.species.species_traits))
return
if(liver)
if(liver.damage >= liver.maxHealth)
liver.failing = TRUE
if(liver.damage < liver.maxHealth)
liver.organ_flags |= ORGAN_FAILING
liver_failure()
else
liver_failure()
@@ -689,13 +714,6 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
var/datum/brain_trauma/BT = T
BT.on_life()
if(getBrainLoss() >= BRAIN_DAMAGE_DEATH) //rip
to_chat(src, "<span class='userdanger'>The last spark of life in your brain fizzles out...<span>")
death()
var/obj/item/organ/brain/B = getorganslot(ORGAN_SLOT_BRAIN)
if(B)
B.damaged_brain = TRUE
/////////////////////////////////////
//MONKEYS WITH TOO MUCH CHOLOESTROL//
/////////////////////////////////////
@@ -704,7 +722,7 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
if(!needs_heart())
return FALSE
var/obj/item/organ/heart/heart = getorganslot(ORGAN_SLOT_HEART)
if(!heart || heart.synthetic)
if(!heart || (heart.organ_flags & ORGAN_SYNTHETIC))
return FALSE
return TRUE
+5 -12
View File
@@ -25,8 +25,6 @@
adjustCloneLoss(damage * hit_percent)
if(STAMINA)
adjustStaminaLoss(damage * hit_percent)
if(BRAIN)
adjustBrainLoss(damage * hit_percent)
return 1
/mob/living/proc/apply_damage_type(damage = 0, damagetype = BRUTE) //like apply damage except it always uses the damage procs
@@ -43,8 +41,6 @@
return adjustCloneLoss(damage)
if(STAMINA)
return adjustStaminaLoss(damage)
if(BRAIN)
return adjustBrainLoss(damage)
/mob/living/proc/get_damage_amount(damagetype = BRUTE)
switch(damagetype)
@@ -60,9 +56,6 @@
return getCloneLoss()
if(STAMINA)
return getStaminaLoss()
if(BRAIN)
return getBrainLoss()
/mob/living/proc/apply_damages(brute = 0, burn = 0, tox = 0, oxy = 0, clone = 0, def_zone = null, blocked = FALSE, stamina = 0, brain = 0)
if(blocked >= 100)
@@ -218,13 +211,13 @@
updatehealth()
return amount
/mob/living/proc/getBrainLoss()
. = 0
/mob/living/proc/adjustBrainLoss(amount, maximum = BRAIN_DAMAGE_DEATH)
/mob/living/proc/adjustOrganLoss(slot, amount, maximum)
return
/mob/living/proc/setBrainLoss(amount)
/mob/living/proc/setOrganLoss(slot, amount, maximum)
return
/mob/living/proc/getOrganLoss(slot)
return
/mob/living/proc/getStaminaLoss()
+1 -1
View File
@@ -255,7 +255,7 @@
H.Knockdown(20)
else
message_param = "<span class='userdanger'>bumps [user.p_their()] head on the ground</span> trying to motion towards %t."
H.adjustBrainLoss(5)
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5)
..()
/datum/emote/living/pout
+7 -1
View File
@@ -473,7 +473,6 @@
setToxLoss(0, 0) //zero as second argument not automatically call updatehealth().
setOxyLoss(0, 0)
setCloneLoss(0, 0)
setBrainLoss(0)
setStaminaLoss(0, 0)
SetUnconscious(0, FALSE)
set_disgust(0)
@@ -500,6 +499,13 @@
QDEL_LIST_ASSOC_VAL(mood.mood_events)
mood.sanity = SANITY_GREAT
mood.update_mood()
//Heal all organs
if(iscarbon(src))
var/mob/living/carbon/C = src
if(C.internal_organs)
for(var/organ in C.internal_organs)
var/obj/item/organ/O = organ
O.setOrganDamage(0)
//proc called by revive(), to check if we can actually ressuscitate the mob (we don't want to revive him and have him instantly die again)
@@ -35,8 +35,8 @@
/mob/living/silicon/setStaminaLoss(amount, updating_stamina = 1)
return FALSE
/mob/living/silicon/adjustBrainLoss(amount)
/mob/living/silicon/adjustOrganLoss(slot, amount, maximum = 500)
return FALSE
/mob/living/silicon/setBrainLoss(amount)
/mob/living/silicon/setOrganLoss(slot, amount)
return FALSE
@@ -84,7 +84,7 @@
/mob/living/silicon/pai/adjustStaminaLoss(amount)
take_holo_damage(amount & 0.25)
/mob/living/silicon/pai/adjustBrainLoss(amount)
/mob/living/silicon/pai/adjustOrganLoss(slot, amount, maximum = 500) //I kept this in, unlike tg
Knockdown(amount * 0.2)
/mob/living/silicon/pai/getBruteLoss()
@@ -102,18 +102,12 @@
/mob/living/silicon/pai/getCloneLoss()
return FALSE
/mob/living/silicon/pai/getBrainLoss()
return FALSE
/mob/living/silicon/pai/getStaminaLoss()
return FALSE
/mob/living/silicon/pai/setCloneLoss()
return FALSE
/mob/living/silicon/pai/setBrainLoss()
return FALSE
/mob/living/silicon/pai/setStaminaLoss()
return FALSE
+3 -3
View File
@@ -43,7 +43,7 @@
.=..()
if ((from.pH > 12.5) || (from.pH < 1.5))
to_chat(src, "<span class='warning'>You taste chemical burns!</span>")
T.adjustTongueLoss(src, 4)
T.applyOrganDamage(5)
if(istype(T, /obj/item/organ/tongue/cybernetic))
to_chat(src, "<span class='notice'>Your tongue moves on it's own in response to the liquid.</span>")
say("The pH is appropriately [round(from.pH, 1)].")
@@ -52,13 +52,13 @@
switch(from.pH)
if(11.5 to INFINITY)
to_chat(src, "<span class='warning'>You taste a strong alkaline flavour!</span>")
T.adjustTongueLoss(src, 1)
T.applyOrganDamage(1)
if(8.5 to 11.5)
to_chat(src, "<span class='notice'>You taste a sort of soapy tone in the mixture.</span>")
if(2.5 to 5.5)
to_chat(src, "<span class='notice'>You taste a sort of acid tone in the mixture.</span>")
if(-INFINITY to 2.5)
to_chat(src, "<span class='warning'>You taste a strong acidic flavour!</span>")
T.adjustTongueLoss(src, 1)
T.applyOrganDamage(1)
#undef DEFAULT_TASTE_SENSITIVITY
+2 -2
View File
@@ -75,7 +75,7 @@
O.setOxyLoss(getOxyLoss(), 0)
O.setCloneLoss(getCloneLoss(), 0)
O.adjustFireLoss(getFireLoss(), 0)
O.setBrainLoss(getBrainLoss(), 0)
O.setOrganLoss(ORGAN_SLOT_BRAIN, getOrganLoss(ORGAN_SLOT_BRAIN), 0)
O.adjustStaminaLoss(getStaminaLoss(), 0)//CIT CHANGE - makes monkey transformations inherit stamina
O.updatehealth()
O.radiation = radiation
@@ -236,7 +236,7 @@
O.setOxyLoss(getOxyLoss(), 0)
O.setCloneLoss(getCloneLoss(), 0)
O.adjustFireLoss(getFireLoss(), 0)
O.setBrainLoss(getBrainLoss(), 0)
O.setOrganLoss(ORGAN_SLOT_BRAIN, getOrganLoss(ORGAN_SLOT_BRAIN), 0)
O.adjustStaminaLoss(getStaminaLoss(), 0)//CIT CHANGE - makes monkey transformations inherit stamina
O.updatehealth()
O.radiation = radiation
@@ -5,5 +5,5 @@
. = ..()
if(ishuman(target))
var/mob/living/carbon/human/M = target
M.adjustBrainLoss(20)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 20)
M.hallucination += 30
+5 -1
View File
@@ -550,6 +550,10 @@
if (multiplier == 0)
fermiEnd()
return
for(var/P in C.required_catalysts)
if(!has_reagent(P))
fermiEnd()
return
for(var/P in cached_results)
targetVol = cached_results[P]*multiplier
@@ -676,7 +680,7 @@
STOP_PROCESSING(SSprocessing, src)
return 0
C.FermiCreate(src)//proc that calls when step is done
C.FermiCreate(src, addChemAmmount, purity)//proc that calls when step is done
//Apply pH changes and thermal output of reaction to beaker
chem_temp = round(cached_temp + (C.ThermicConstant * addChemAmmount))
@@ -1373,6 +1373,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
/datum/reagent/consumable/ethanol/neurotoxin
name = "Neurotoxin"
id = "neurotoxin"
description = "A strong neurotoxin that puts the subject into a death-like state."
color = "#2E2E61" // rgb: 46, 46, 97
boozepwr = 50
@@ -1382,6 +1383,10 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_icon_state = "neurotoxinglass"
glass_name = "Neurotoxin"
glass_desc = "A drink that is guaranteed to knock you silly."
//SplitChem = TRUE
impure_chem = "neuroweak"
inverse_chem_val = 0.5 //Clear conversion
inverse_chem = "neuroweak"
/datum/reagent/consumable/ethanol/neurotoxin/proc/pickt()
return (pick(TRAIT_PARALYSIS_L_ARM,TRAIT_PARALYSIS_R_ARM,TRAIT_PARALYSIS_R_LEG,TRAIT_PARALYSIS_L_LEG))
@@ -1389,18 +1394,18 @@ All effects don't start immediately, but rather get worse over time; the rate is
/datum/reagent/consumable/ethanol/neurotoxin/on_mob_life(mob/living/carbon/M)
M.set_drugginess(50)
M.dizziness +=2
M.adjustBrainLoss(1*REM, 150)
if(prob(20))
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1*REM, 150)
if(prob(20) && !holder.has_reagent("neuroweak"))
M.adjustStaminaLoss(10)
M.drop_all_held_items()
to_chat(M, "<span class='notice'>You cant feel your hands!</span>")
if(current_cycle > 5)
if(prob(20))
if(prob(20) && !holder.has_reagent("neuroweak"))
var/t = pickt()
ADD_TRAIT(M, t, type)
M.adjustStaminaLoss(10)
if(current_cycle > 30)
M.adjustBrainLoss(2*REM)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2*REM)
if(current_cycle > 50 && prob(15))
if(!M.undergoing_cardiac_arrest() && M.can_heartattack())
M.set_heartattack(TRUE)
@@ -1417,6 +1422,25 @@ All effects don't start immediately, but rather get worse over time; the rate is
M.adjustStaminaLoss(10)
..()
/datum/reagent/consumable/ethanol/neuroweak
name = "Neuro-Smash"
id = "neuroweak"
description = "A mostly safe alcoholic drink for the true daredevils. Counteracts Neurotoxins."
boozepwr = 60
pH = 8
/datum/reagent/consumable/ethanol/neuroweak/on_mob_life(mob/living/carbon/M)
if(holder.has_reagent("neurotoxin"))
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1*REM, 150)
M.reagents.remove_reagent("neurotoxin", 1.5 * REAGENTS_METABOLISM, FALSE)
if(holder.has_reagent("fentanyl"))
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1*REM, 150)
M.reagents.remove_reagent("fentanyl", 0.75 * REAGENTS_METABOLISM, FALSE)
else
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, -0.5*REM, 150)
M.dizziness +=2
..()
/datum/reagent/consumable/ethanol/hippies_delight
name = "Hippie's Delight"
id = "hippiesdelight"
@@ -2122,6 +2146,29 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_name = "Planet Cracker"
glass_desc = "Although historians believe the drink was originally created to commemorate the end of an important conflict in man's past, its origins have largely been forgotten and it is today seen more as a general symbol of human supremacy."
/datum/reagent/consumable/ethanol/commander_and_chief
name = "Commander and Chief"
id = "commander_and_chief"
description = "A cocktail for the captain on the go."
color = "#ffffc9"
boozepwr = 50
quality = DRINK_FANTASTIC
taste_description = "Tastes like...duty and responsibility?"
glass_icon_state = "commander_and_chief"
glass_name = "Commander and Chief"
glass_desc = "The gems of this majestic chalice represent the departments and their Heads."
/datum/reagent/consumable/ethanol/commander_and_chief/on_mob_life(mob/living/carbon/M)
if(M.mind && HAS_TRAIT(M.mind, TRAIT_CAPTAIN_METABOLISM))
M.heal_bodypart_damage(2,2,2)
M.adjustBruteLoss(-3.5,0)
M.adjustOxyLoss(-3.5,0)
M.adjustFireLoss(-3.5,0)
M.adjustToxLoss(-3.5,0)
M.radiation = max(M.radiation - 25, 0)
. = 1
return ..()
/datum/reagent/consumable/ethanol/fruit_wine
name = "Fruit Wine"
id = "fruit_wine"
@@ -80,14 +80,14 @@
. = 1
/datum/reagent/drug/crank/overdose_process(mob/living/M)
M.adjustBrainLoss(2*REM)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2*REM)
M.adjustToxLoss(2*REM, 0)
M.adjustBruteLoss(2*REM, 0)
..()
. = 1
/datum/reagent/drug/crank/addiction_act_stage1(mob/living/M)
M.adjustBrainLoss(5*REM)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5*REM)
..()
/datum/reagent/drug/crank/addiction_act_stage2(mob/living/M)
@@ -101,7 +101,7 @@
. = 1
/datum/reagent/drug/crank/addiction_act_stage4(mob/living/M)
M.adjustBrainLoss(3*REM)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3*REM)
M.adjustToxLoss(5*REM, 0)
M.adjustBruteLoss(5*REM, 0)
..()
@@ -125,13 +125,13 @@
..()
/datum/reagent/drug/krokodil/overdose_process(mob/living/M)
M.adjustBrainLoss(0.25*REM)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.25*REM)
M.adjustToxLoss(0.25*REM, 0)
..()
. = 1
/datum/reagent/drug/krokodil/addiction_act_stage1(mob/living/M)
M.adjustBrainLoss(2*REM)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2*REM)
M.adjustToxLoss(2*REM, 0)
..()
. = 1
@@ -192,7 +192,7 @@
if(jitter)
M.Jitter(2)
if(brain_damage)
M.adjustBrainLoss(rand(1,4))
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, rand(1,4))
M.heal_overall_damage(2, 2)
if(prob(5))
M.emote(pick("twitch", "shiver"))
@@ -210,7 +210,7 @@
M.drop_all_held_items()
..()
M.adjustToxLoss(1, 0)
M.adjustBrainLoss(pick(0.5, 0.6, 0.7, 0.8, 0.9, 1))
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, pick(0.5, 0.6, 0.7, 0.8, 0.9, 1))
. = 1
/datum/reagent/drug/methamphetamine/addiction_act_stage1(mob/living/M)
@@ -289,7 +289,7 @@
if(prob(5))
to_chat(M, "<span class='notice'>[high_message]</span>")
M.adjustStaminaLoss(-5, 0)
M.adjustBrainLoss(4)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 4)
M.hallucination += 5
if(M.canmove && !ismovableatom(M.loc))
step(M, pick(GLOB.cardinals))
@@ -314,7 +314,7 @@
for(var/i = 0, i < 8, i++)
step(M, pick(GLOB.cardinals))
M.Jitter(5)
M.adjustBrainLoss(10)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10)
if(prob(20))
M.emote(pick("twitch","drool","moan"))
..()
@@ -326,7 +326,7 @@
step(M, pick(GLOB.cardinals))
M.Jitter(10)
M.Dizzy(10)
M.adjustBrainLoss(10)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10)
if(prob(30))
M.emote(pick("twitch","drool","moan"))
..()
@@ -338,7 +338,7 @@
step(M, pick(GLOB.cardinals))
M.Jitter(15)
M.Dizzy(15)
M.adjustBrainLoss(10)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10)
if(prob(40))
M.emote(pick("twitch","drool","moan"))
..()
@@ -351,7 +351,7 @@
M.Jitter(50)
M.Dizzy(50)
M.adjustToxLoss(5, 0)
M.adjustBrainLoss(10)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10)
if(prob(50))
M.emote(pick("twitch","drool","moan"))
..()
@@ -401,7 +401,7 @@
M.jitteriness = 0
M.confused = 0
M.disgust = 0
M.adjustBrainLoss(0.2)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.2)
..()
. = 1
@@ -418,7 +418,7 @@
if(3)
M.emote("frown")
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "happiness_drug", /datum/mood_event/happiness_drug_bad_od)
M.adjustBrainLoss(0.5)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.5)
..()
. = 1
@@ -490,7 +490,7 @@
H.dna.species.punchdamagehigh *= 0.2
/datum/reagent/drug/skooma/on_mob_life(mob/living/carbon/M)
M.adjustBrainLoss(1*REM)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1*REM)
M.adjustToxLoss(1*REM)
if(prob(10))
M.adjust_blurriness(2)
@@ -522,7 +522,7 @@
M.Dizzy(50)
M.adjust_blurriness(10)
if(prob(50)) //This proc will be called about 200 times and the adjustbrainloss() below only has to be called 40 times to kill. This will make surviving skooma addiction pretty rare without mannitol usage.
M.adjustBrainLoss(5)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5)
if(prob(40))
M.emote(pick("twitch","drool","moan"))
..()
@@ -684,7 +684,7 @@
. = 1
if(prob(20))
M.losebreath += 4
M.adjustBrainLoss(2*REM, 150)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2*REM, 150)
M.adjustToxLoss(3*REM,0)
M.adjustStaminaLoss(10*REM,0)
M.blur_eyes(5)
@@ -44,7 +44,7 @@
M.heal_bodypart_damage(5,5)
M.adjustToxLoss(-5, 0, TRUE)
M.hallucination = 0
M.setBrainLoss(0)
M.setOrganLoss(ORGAN_SLOT_BRAIN, 0)
REMOVE_TRAITS_NOT_IN(M, list(SPECIES_TRAIT, ROUNDSTART_TRAIT, ORGAN_TRAIT))
M.set_blurriness(0)
M.set_blindness(0)
@@ -64,6 +64,10 @@
if(M.blood_volume < (BLOOD_VOLUME_NORMAL*M.blood_ratio))
M.blood_volume = (BLOOD_VOLUME_NORMAL*M.blood_ratio)
for(var/organ in M.internal_organs)
var/obj/item/organ/O = organ
O.setOrganDamage(0)
for(var/thing in M.diseases)
var/datum/disease/D = thing
if(D.severity == DISEASE_SEVERITY_POSITIVE)
@@ -852,10 +856,16 @@
if(M.notify_ghost_cloning(source = M))
spawn (100) //so the ghost has time to re-enter
return
else
M.adjustOxyLoss(-20, 0)
M.adjustToxLoss(-20, 0)
var/mob/living/carbon/H = M
for(var/organ in H.internal_organs)
var/obj/item/organ/O = organ
O.setOrganDamage(0)
M.updatehealth()
if(M.revive())
M.emote("gasp")
log_combat(M, M, "revived", src)
@@ -875,7 +885,7 @@
pH = 10.4
/datum/reagent/medicine/mannitol/on_mob_life(mob/living/carbon/C)
C.adjustBrainLoss(-2*REM)
C.adjustOrganLoss(ORGAN_SLOT_BRAIN, -2*REM)
if(prob(10))
C.cure_trauma_type(resilience = TRAUMA_RESILIENCE_BASIC)
..()
@@ -1130,7 +1140,7 @@
M.adjustFireLoss(-5*REM, 0)
M.adjustOxyLoss(-15, 0)
M.adjustToxLoss(-5*REM, 0)
M.adjustBrainLoss(-15*REM)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, -15*REM)
M.adjustCloneLoss(-3*REM, 0)
M.adjustStaminaLoss(-20*REM,0)
..()
@@ -1175,9 +1185,9 @@
M.adjustFireLoss(-3 * REM, 0)
M.adjustOxyLoss(-15 * REM, 0)
M.adjustToxLoss(-3 * REM, 0, TRUE) //Heals TOXINLOVERS
M.adjustBrainLoss(2 * REM, 150) //This does, after all, come from ambrosia, and the most powerful ambrosia in existence, at that!
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2 * REM, 150) //This does, after all, come from ambrosia, and the most powerful ambrosia in existence, at that!
M.adjustCloneLoss(-1 * REM, 0)
M.adjustStaminaLoss(-30 * REM, 0)
M.adjustStaminaLoss(-13 * REM, 0)
M.jitteriness = min(max(0, M.jitteriness + 3), 30)
M.druggy = min(max(0, M.druggy + 10), 15) //See above
..()
@@ -1207,7 +1217,7 @@
if (M.hallucination >= 5)
M.hallucination -= 5
if(prob(20))
M.adjustBrainLoss(1*REM, 50)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1*REM, 50)
M.adjustStaminaLoss(2.5*REM, 0)
..()
return TRUE
@@ -3,6 +3,7 @@
name = "Blood"
id = "blood"
color = "#C80000" // rgb: 200, 0, 0
description = "Blood from a human, or otherwise."
metabolization_rate = 5 //fast rate so it disappears fast.
taste_description = "iron"
taste_mult = 1.3
@@ -200,22 +201,20 @@
pH = 7.5 //God is alkaline
/datum/reagent/water/holywater/on_mob_metabolize(mob/living/L)
..()
. = ..()
ADD_TRAIT(L, TRAIT_HOLY, id)
if(is_servant_of_ratvar(L))
to_chat(L, "<span class='userdanger'>A fog spreads through your mind, purging the Justiciar's influence!</span>")
else if(iscultist(L))
to_chat(L, "<span class='userdanger'>A fog spreads through your mind, weakening your connection to the veil and purging Nar-sie's influence</span>")
/datum/reagent/water/holywater/on_mob_end_metabolize(mob/living/L)
REMOVE_TRAIT(L, TRAIT_HOLY, id)
..()
/datum/reagent/water/holywater/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
if(is_servant_of_ratvar(M))
to_chat(M, "<span class='userdanger'>A fog spreads through your mind, purging the Justiciar's influence!</span>")
..()
/datum/reagent/water/holywater/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
if(iscultist(M))
to_chat(M, "<span class='userdanger'>A fog spreads through your mind, weakening your connection to the veil and purging Nar-sie's influence</span>")
..()
if(iscultist(L))
for(var/datum/action/innate/cult/blood_magic/BM in L.actions)
BM.holy_dispel = FALSE
return ..()
/datum/reagent/water/holywater/on_mob_life(mob/living/carbon/M)
if(!data)
@@ -224,9 +223,11 @@
M.jitteriness = min(M.jitteriness+4,10)
if(iscultist(M))
for(var/datum/action/innate/cult/blood_magic/BM in M.actions)
to_chat(M, "<span class='cultlarge'>Your blood rites falter as holy water scours your body!</span>")
for(var/datum/action/innate/cult/blood_spell/BS in BM.spells)
qdel(BS)
if(!BM.holy_dispel)
BM.holy_dispel = TRUE
to_chat(M, "<span class='cultlarge'>Your blood rites falter as holy water scours your body!</span>")
for(var/datum/action/innate/cult/blood_spell/BS in BM.spells)
qdel(BS)
if(data >= 25) // 10 units, 45 seconds @ metabolism 0.4 units & tick rate 1.8 sec
if(!M.stuttering)
M.stuttering = 1
@@ -296,7 +297,7 @@
if(ishuman(M) && M.blood_volume < (BLOOD_VOLUME_NORMAL*M.blood_ratio))
M.blood_volume += 3
else // Will deal about 90 damage when 50 units are thrown
M.adjustBrainLoss(3, 150)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3, 150)
M.adjustToxLoss(2, 0)
M.adjustFireLoss(2, 0)
M.adjustOxyLoss(2, 0)
@@ -315,7 +316,7 @@
M.IgniteMob() //Only problem with igniting people is currently the commonly availible fire suits make you immune to being on fire
M.adjustToxLoss(1, 0)
M.adjustFireLoss(1, 0) //Hence the other damages... ain't I a bastard?
M.adjustBrainLoss(5, 150)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5, 150)
holder.remove_reagent(id, 1)
pH = 0.1
@@ -536,12 +537,12 @@
race = /datum/species/fly
mutationtext = "<span class='danger'>The pain subsides. You feel... buzzy.</span>"
/datum/reagent/mutationtoxin/moth
name = "Moth Mutation Toxin"
/datum/reagent/mutationtoxin/insect
name = "Insect Mutation Toxin"
id = "mothmutationtoxin"
description = "A glowing toxin."
color = "#5EFF3B" //RGB: 94, 255, 59
race = /datum/species/moth
race = /datum/species/insect
mutationtext = "<span class='danger'>The pain subsides. You feel... attracted to light.</span>"
/datum/reagent/mutationtoxin/pod
@@ -805,7 +806,7 @@
step(M, pick(GLOB.cardinals))
if(prob(5))
M.emote(pick("twitch","drool","moan"))
M.adjustBrainLoss(1)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1)
..()
/datum/reagent/sulfur
@@ -1172,7 +1173,7 @@
/datum/reagent/impedrezene/on_mob_life(mob/living/carbon/M)
M.jitteriness = max(M.jitteriness-5,0)
if(prob(80))
M.adjustBrainLoss(2*REM)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2*REM)
if(prob(50))
M.drowsyness = max(M.drowsyness, 3)
if(prob(10))
@@ -1222,7 +1223,7 @@
description = "A perfluoronated sulfonic acid that forms a foam when mixed with water."
color = "#9E6B38" // rgb: 158, 107, 56
taste_description = "metal"
pH = 13
pH = 11
/datum/reagent/foaming_agent// Metal foaming agent. This is lithium hydride. Add other recipes (e.g. LiH + H2O -> LiOH + H2) eventually.
name = "Foaming agent"
@@ -1231,7 +1232,7 @@
reagent_state = SOLID
color = "#664B63" // rgb: 102, 75, 99
taste_description = "metal"
pH = 12.5
pH = 11.5
/datum/reagent/smart_foaming_agent //Smart foaming agent. Functions similarly to metal foam, but conforms to walls.
name = "Smart foaming agent"
@@ -1445,9 +1446,6 @@
color = "#FFFFFF" // white
random_color_list = list("#FFFFFF") //doesn't actually change appearance at all
//////////////////////////////////Hydroponics stuff///////////////////////////////
/datum/reagent/plantnutriment
@@ -1489,16 +1487,8 @@
tox_prob = 15
pH = 1
// GOON OTHERS
/datum/reagent/oil
name = "Oil"
id = "oil"
@@ -1530,20 +1520,6 @@
taste_description = "metal"
pH = 4.5
/datum/reagent/carpet
name = "Carpet"
id = "carpet"
description = "For those that need a more creative way to roll out a red carpet."
reagent_state = LIQUID
color = "#b51d05"
taste_description = "carpet" // Your tounge feels furry.
/datum/reagent/carpet/reaction_turf(turf/T, reac_volume)
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
var/turf/open/floor/F = T
F.PlaceOnTop(/turf/open/floor/carpet)
..()
/datum/reagent/bromine
name = "Bromine"
id = "bromine"
@@ -1676,7 +1652,7 @@
reagent_state = LIQUID
color = "#FFFFD6" // very very light yellow
taste_description = "alkali" //who put ACID for NaOH ????
pH = 13
pH = 11.9
/datum/reagent/drying_agent
name = "Drying agent"
@@ -1697,6 +1673,143 @@
qdel(O)
new /obj/item/clothing/shoes/galoshes/dry(t_loc)
// Liquid Carpets
/datum/reagent/carpet
name = "Liquid Carpet"
id = "carpet"
description = "For those that need a more creative way to roll out a carpet."
reagent_state = LIQUID
color = "#b51d05"
taste_description = "carpet" // Your tounge feels furry.
/datum/reagent/carpet/reaction_turf(turf/T, reac_volume)
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
var/turf/open/floor/F = T
F.PlaceOnTop(/turf/open/floor/carpet)
..()
/datum/reagent/carpet/black
name = "Liquid Black Carpet"
id = "blackcarpet"
color = "#363636"
/datum/reagent/carpet/black/reaction_turf(turf/T, reac_volume)
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
var/turf/open/floor/F = T
F.PlaceOnTop(/turf/open/floor/carpet/black)
..()
/datum/reagent/carpet/blackred
name = "Liquid Red Black Carpet"
id = "blackredcarpet"
color = "#342125"
/datum/reagent/carpet/blackred/reaction_turf(turf/T, reac_volume)
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
var/turf/open/floor/F = T
F.PlaceOnTop(/turf/open/floor/carpet/blackred)
..()
/datum/reagent/carpet/monochrome
name = "Liquid Monochrome Carpet"
id = "monochromecarpet"
color = "#b4b4b4"
/datum/reagent/carpet/monochrome/reaction_turf(turf/T, reac_volume)
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
var/turf/open/floor/F = T
F.PlaceOnTop(/turf/open/floor/carpet/monochrome)
..()
/datum/reagent/carpet/blue
name = "Liquid Blue Carpet"
id = "bluecarpet"
color = "#1256ff"
/datum/reagent/carpet/blue/reaction_turf(turf/T, reac_volume)
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
var/turf/open/floor/F = T
F.PlaceOnTop(/turf/open/floor/carpet/blue)
..()
/datum/reagent/carpet/cyan
name = "Liquid Cyan Carpet"
id = "cyancarpet"
color = "#3acfb9"
/datum/reagent/carpet/cyan/reaction_turf(turf/T, reac_volume)
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
var/turf/open/floor/F = T
F.PlaceOnTop(/turf/open/floor/carpet/cyan)
..()
/datum/reagent/carpet/green
name = "Liquid Green Carpet"
id = "greencarpet"
color = "#619b62"
/datum/reagent/carpet/green/reaction_turf(turf/T, reac_volume)
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
var/turf/open/floor/F = T
F.PlaceOnTop(/turf/open/floor/carpet/green)
..()
/datum/reagent/carpet/orange
name = "Liquid Orange Carpet"
id = "orangecarpet"
color = "#cc7900"
/datum/reagent/carpet/orange/reaction_turf(turf/T, reac_volume)
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
var/turf/open/floor/F = T
F.PlaceOnTop(/turf/open/floor/carpet/orange)
..()
/datum/reagent/carpet/purple
name = "Liquid Purple Carpet"
id = "purplecarpet"
color = "#6d3392"
/datum/reagent/carpet/purple/reaction_turf(turf/T, reac_volume)
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
var/turf/open/floor/F = T
F.PlaceOnTop(/turf/open/floor/carpet/purple)
..()
/datum/reagent/carpet/red
name = "Liquid Red Carpet"
id = "redcarpet"
color = "#871515"
/datum/reagent/carpet/red/reaction_turf(turf/T, reac_volume)
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
var/turf/open/floor/F = T
F.PlaceOnTop(/turf/open/floor/carpet/red)
..()
/datum/reagent/carpet/royalblack
name = "Liquid Royal Black Carpet"
id = "royalblackcarpet"
color = "#483d05"
/datum/reagent/carpet/royalblack/reaction_turf(turf/T, reac_volume)
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
var/turf/open/floor/F = T
F.PlaceOnTop(/turf/open/floor/carpet/royalblack)
..()
/datum/reagent/carpet/royalblue
name = "Liquid Royal Blue Carpet"
id = "royalbluecarpet"
color = "#24227e"
/datum/reagent/carpet/royalblue/reaction_turf(turf/T, reac_volume)
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
var/turf/open/floor/F = T
F.PlaceOnTop(/turf/open/floor/carpet/royalblue)
..()
// Virology virus food chems.
/datum/reagent/toxin/mutagen/mutagenvirusfood
@@ -2003,7 +2116,7 @@
can_synth = FALSE
var/datum/dna/original_dna
var/reagent_ticks = 0
invisible = TRUE
chemical_flags = REAGENT_INVISIBLE
/datum/reagent/changeling_string/on_mob_metabolize(mob/living/carbon/C)
if(C && C.dna && data["desired_dna"])
@@ -2031,3 +2144,25 @@
/datum/reagent/changeling_string/Destroy()
qdel(original_dna)
return ..()
/datum/reagent/mustardgrind
name = "Mustardgrind"
id = "mustardgrind"
description = "A powerd that is mixed with water and enzymes to make mustard."
color = "#BCC740" //RGB: 188, 199, 64
taste_description = "plant dust"
/datum/reagent/pax/catnip
name = "catnip"
id = "catnip"
taste_description = "grass"
description = "A colorless liquid that makes people more peaceful and felines more happy."
metabolization_rate = 1.75 * REAGENTS_METABOLISM
/datum/reagent/pax/catnip/on_mob_life(mob/living/carbon/M)
if(prob(20))
M.emote("nya")
if(prob(20))
to_chat(M, "<span class = 'notice'>[pick("Headpats feel nice.", "The feeling of a hairball...", "Backrubs would be nice.", "Whats behind those doors?")]</span>")
M.adjustArousalLoss(2)
..()
@@ -313,25 +313,6 @@
. = 1
..()
/datum/reagent/toxin/chloralhydratedelayed //sedates half as quickly and does not cause toxloss. same name/desc so it doesn't give away sleepypens
name = "Chloral Hydrate"
id = "chloralhydratedelayed"
description = "A powerful sedative that induces confusion and drowsiness before putting its target to sleep."
reagent_state = SOLID
color = "#000067" // rgb: 0, 0, 103
toxpwr = 0
metabolization_rate = 1 * REAGENTS_METABOLISM
/datum/reagent/toxin/chloralhydratedelayed/on_mob_life(mob/living/carbon/M)
switch(current_cycle)
if(10 to 20)
M.confused += 1
M.drowsyness += 1
M.adjustStaminaLoss(7.5)
if(20 to INFINITY)
M.Sleeping(40, 0)
..()
/datum/reagent/toxin/fakebeer //disguised as normal beer for use by emagged brobots
name = "Beer"
id = "fakebeer"
@@ -389,12 +370,12 @@
id = "tirizene"
description = "A nonlethal poison that causes extreme fatigue and weakness in its victim."
color = "#6E2828"
data = 13
data = 15
toxpwr = 0
/datum/reagent/toxin/staminatoxin/on_mob_life(mob/living/carbon/M)
M.adjustStaminaLoss(REM * data, 0)
data = max(data - 1, 3)
data = max(data - 1, 5)
..()
. = 1
@@ -490,7 +471,7 @@
toxpwr = 0
/datum/reagent/toxin/fentanyl/on_mob_life(mob/living/carbon/M)
M.adjustBrainLoss(3*REM, 150)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3*REM, 150)
if(M.toxloss <= 60)
M.adjustToxLoss(1*REM, 0)
if(current_cycle >= 18)
@@ -969,3 +950,20 @@
to_chat(M, "<span class='warning'>Your missing arm aches from wherever you left it.</span>")
M.emote("sigh")
return ..()
/datum/reagent/toxin/brainhurtingjuice //oof ouch
name = "Brain Hurting Juice"
id = "brainhurtingjuice"
color = "#AAAAAA77" //RGBA: 170, 170, 170, 77
toxpwr = 0
taste_description = "brain hurting"
metabolization_rate = 5
/datum/reagent/toxin/brainhurtingjuice/on_mob_life(mob/living/carbon/M)
if(prob(50))
M.gain_trauma_type(BRAIN_TRAUMA_MILD)
else if(prob(50))
M.gain_trauma_type(BRAIN_TRAUMA_SEVERE)
else
M.gain_trauma_type(BRAIN_TRAUMA_SPECIAL)
..()
@@ -68,6 +68,42 @@
results = list("synthflesh" = 3)
required_reagents = list("blood" = 1, "carbon" = 1, "styptic_powder" = 1)
/datum/chemical_reaction/synthtissue
name = "Synthtissue"
id = "synthtissue"
results = list("synthtissue" = 0.05)
required_reagents = list("synthflesh" = 0.01)
required_catalysts = list("nutriment" = 0.1)
//FermiChem vars:
OptimalTempMin = 305 // Lower area of bell curve for determining heat based rate reactions
OptimalTempMax = 315 // Upper end for above
ExplodeTemp = 1050 // Temperature at which reaction explodes
OptimalpHMin = 8.5 // Lowest value of pH determining pH a 1 value for pH based rate reactions (Plateu phase)
OptimalpHMax = 9.5 // Higest value for above
ReactpHLim = 2 // How far out pH wil react, giving impurity place (Exponential phase)
CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst)
CurveSharpT = 1 // How sharp the temperature exponential curve is (to the power of value)
CurveSharppH = 2.5 // How sharp the pH exponential curve is (to the power of value)
ThermicConstant = 0.01 // Temperature change per 1u produced
HIonRelease = 0.015 // pH change per 1u reaction (inverse for some reason)
RateUpLim = 0.05 // Optimal/max rate possible if all conditions are perfect
FermiChem = TRUE // If the chemical uses the Fermichem reaction mechanics
PurityMin = 0
/datum/chemical_reaction/synthtissue/FermiCreate(datum/reagents/holder, added_volume, added_purity)
var/datum/reagent/synthtissue/St = holder.has_reagent("synthtissue")
var/datum/reagent/N = holder.has_reagent("nutriment")
if(!St)
return
if(holder.chem_temp > 320)
var/temp_ratio = 1-(330 - holder.chem_temp)/10
holder.remove_reagent(src.id, added_volume*temp_ratio)
if(St.purity < 1)
St.volume *= St.purity
St.purity = 1
N.volume -= 0.002
St.data["grown_volume"] = St.data["grown_volume"] + added_volume
/datum/chemical_reaction/styptic_powder
name = "Styptic Powder"
id = "styptic_powder"
@@ -534,6 +534,17 @@
category = list("Medical Designs")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
/datum/design/cybernetic_heart_u
name = "Upgraded Cybernetic Heart"
desc = "An upgraded cybernetic heart"
id = "cybernetic_heart_u"
build_type = PROTOLATHE | MECHFAB
construction_time = 50
materials = list(MAT_METAL = 500, MAT_GLASS = 500, MAT_SILVER = 500)
build_path = /obj/item/organ/heart/cybernetic/upgraded
category = list("Misc", "Medical Designs")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
/datum/design/cybernetic_liver_u
name = "Upgraded Cybernetic Liver"
desc = "An upgraded cybernetic liver"
@@ -712,6 +723,28 @@
category = list("Medical Designs")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
/datum/design/cybernetic_ears
name = "Cybernetic Ears"
desc = "A pair of cybernetic ears."
id = "cybernetic_ears"
build_type = PROTOLATHE | MECHFAB
construction_time = 30
materials = list(MAT_METAL = 250, MAT_GLASS = 400)
build_path = /obj/item/organ/ears/cybernetic
category = list("Misc", "Medical Designs")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
/datum/design/cybernetic_ears_u
name = "Upgraded Cybernetic Ears"
desc = "A pair of upgraded cybernetic ears."
id = "cybernetic_ears_u"
build_type = PROTOLATHE | MECHFAB
construction_time = 40
materials = list(MAT_METAL = 500, MAT_GLASS = 500, MAT_SILVER = 500)
build_path = /obj/item/organ/ears/cybernetic/upgraded
category = list("Misc", "Medical Designs")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
/////////////////////
///Surgery Designs///
/////////////////////
@@ -72,14 +72,16 @@
/datum/nanite_program/brain_heal/check_conditions()
if(iscarbon(host_mob))
var/mob/living/carbon/C = host_mob
if(length(C.get_traumas()))
return ..()
if(host_mob.getBrainLoss())
for(var/X in C.get_traumas())
var/datum/brain_trauma/BT = X
if(BT.resilience <= TRAUMA_RESILIENCE_BASIC)
return ..()
if(host_mob.getOrganLoss(ORGAN_SLOT_BRAIN))
return ..()
return FALSE
/datum/nanite_program/brain_heal/active_effect()
host_mob.adjustBrainLoss(-1, TRUE)
host_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1, TRUE)
if(iscarbon(host_mob) && prob(10))
var/mob/living/carbon/C = host_mob
C.cure_trauma_type(resilience = TRAUMA_RESILIENCE_BASIC)
@@ -193,14 +195,16 @@
/datum/nanite_program/brain_heal_advanced/check_conditions()
if(iscarbon(host_mob))
var/mob/living/carbon/C = host_mob
if(length(C.get_traumas()))
return ..()
if(host_mob.getBrainLoss())
for(var/X in C.get_traumas())
var/datum/brain_trauma/BT = X
if(BT.resilience <= TRAUMA_RESILIENCE_LOBOTOMY)
return ..()
if(host_mob.getOrganLoss(ORGAN_SLOT_BRAIN))
return ..()
return FALSE
/datum/nanite_program/brain_heal_advanced/active_effect()
host_mob.adjustBrainLoss(-2, TRUE)
host_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, -2, TRUE)
if(iscarbon(host_mob) && prob(10))
var/mob/living/carbon/C = host_mob
C.cure_trauma_type(resilience = TRAUMA_RESILIENCE_LOBOTOMY)
@@ -232,7 +236,7 @@
if(!C.getorgan(/obj/item/organ/heart)) //what are we even shocking
return FALSE
var/obj/item/organ/brain/BR = C.getorgan(/obj/item/organ/brain)
if(QDELETED(BR) || BR.damaged_brain)
if(QDELETED(BR) || BR.brain_death || (BR.organ_flags & ORGAN_FAILING) || C.suiciding)
return FALSE
if(C.get_ghost())
return FALSE
@@ -252,7 +256,7 @@
SEND_SIGNAL(C, COMSIG_LIVING_MINOR_SHOCK)
var/tplus = world.time - C.timeofdeath
if(tplus > 600)
C.adjustBrainLoss( max(0, ((1800 - tplus) / 1800 * 150)), 150)
C.adjustOrganLoss(ORGAN_SLOT_BRAIN, max(0, ((1800 - tplus) / 1800 * 150)), 150)
log_game("[C] has been successfully defibrillated by nanites.")
else
playsound(C, 'sound/machines/defib_failed.ogg', 50, 0)
@@ -59,7 +59,7 @@
/datum/nanite_program/brain_decay/active_effect()
if(prob(4))
host_mob.hallucination = min(15, host_mob.hallucination)
host_mob.adjustBrainLoss(1)
host_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1)
//Generic brain-affecting programs can also decay into this
/datum/nanite_program/brain_misfire
+10 -2
View File
@@ -526,10 +526,18 @@
display_name = "Cybernetic Organs"
description = "We have the technology to rebuild him."
prereq_ids = list("adv_biotech")
design_ids = list("cybernetic_heart", "cybernetic_liver", "cybernetic_liver_u", "cybernetic_lungs", "cybernetic_lungs_u", "cybernetic_tongue")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
design_ids = list("cybernetic_ears", "cybernetic_heart", "cybernetic_liver", "cybernetic_lungs", "cybernetic_tongue")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000)
export_price = 5000
/datum/techweb_node/cyber_organs_upgraded
id = "cyber_organs_upgraded"
display_name = "Upgraded Cybernetic Organs"
description = "We have the technology to upgrade him."
prereq_ids = list("cyber_organs")
design_ids = list("cybernetic_ears_u", "cybernetic_heart_u", "cybernetic_liver_u", "cybernetic_lungs_u")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500)
/datum/techweb_node/cyber_implants
id = "cyber_implants"
display_name = "Cybernetic Implants"
@@ -119,7 +119,7 @@ Consuming extracts:
M.adjustToxLoss(-5, forced=1) //To heal slimepeople.
M.adjustOxyLoss(-5)
M.adjustCloneLoss(-5)
M.adjustBrainLoss(-5)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, -5)
/obj/item/slimecross/consuming/blue
colour = "blue"
@@ -12,7 +12,7 @@
/datum/surgery_step/clamp_bleeders,
/datum/surgery_step/brainwash,
/datum/surgery_step/close)
species = list(/mob/living/carbon/human)
possible_locs = list(BODY_ZONE_HEAD)
/datum/surgery/advanced/brainwashing/can_start(mob/user, mob/living/carbon/target)
@@ -56,7 +56,7 @@
display_results(user, target, "<span class='warning'>You screw up, bruising the brain tissue!</span>",
"<span class='warning'>[user] screws up, causing brain damage!</span>",
"[user] completes the surgery on [target]'s brain.")
target.adjustBrainLoss(40)
target.adjustOrganLoss(ORGAN_SLOT_BRAIN, 40)
else
user.visible_message("<span class='warning'>[user] suddenly notices that the brain [user.p_they()] [user.p_were()] working on is not there anymore.", "<span class='warning'>You suddenly notice that the brain you were working on is not there anymore.</span>")
return FALSE
+3 -2
View File
@@ -51,11 +51,12 @@
return TRUE
/datum/surgery_step/lobotomize/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(target.getorganslot(ORGAN_SLOT_BRAIN))
var/obj/item/organ/brain/B = target.getorganslot(ORGAN_SLOT_BRAIN)
if(B)
display_results(user, target, "<span class='warning'>You remove the wrong part, causing more damage!</span>",
"[user] successfully lobotomizes [target]!",
"[user] completes the surgery on [target]'s brain.")
target.adjustBrainLoss(80)
B.applyOrganDamage(80)
switch(rand(1,3))
if(1)
target.gain_trauma_type(BRAIN_TRAUMA_MILD, TRAUMA_RESILIENCE_MAGIC)
+2 -2
View File
@@ -63,7 +63,7 @@
user.visible_message("...[target] wakes up, alive and aware!", "<span class='notice'><b>IT'S ALIVE!</b></span>")
target.visible_message("...[target] wakes up, alive and aware!")
target.emote("gasp")
target.adjustBrainLoss(50, 199) //MAD SCIENCE
target.adjustOrganLoss(ORGAN_SLOT_BRAIN, 50, 199) //MAD SCIENCE
return TRUE
else
user.visible_message("...[target.p_they()] convulses, then lies still.")
@@ -75,5 +75,5 @@
"[user] send a powerful shock to [target]'s brain with [tool], but [target.p_they()] doesn't react.",
"[user] send a powerful shock to [target]'s brain with [tool], but [target.p_they()] doesn't react.")
playsound(get_turf(target), 'sound/magic/lightningbolt.ogg', 50, 1)
target.adjustBrainLoss(15, 199)
target.adjustOrganLoss(ORGAN_SLOT_BRAIN, 15, 199)
return FALSE
+2 -2
View File
@@ -31,7 +31,7 @@
"[user] completes the surgery on [target]'s brain.")
if(target.mind && target.mind.has_antag_datum(/datum/antagonist/brainwashed))
target.mind.remove_antag_datum(/datum/antagonist/brainwashed)
target.adjustBrainLoss(-60)
target.setOrganLoss(ORGAN_SLOT_BRAIN, target.getOrganLoss(ORGAN_SLOT_BRAIN) - 60) //we set damage in this case in order to clear the "failing" flag
target.cure_all_traumas(TRAUMA_RESILIENCE_SURGERY)
return TRUE
@@ -40,7 +40,7 @@
display_results(user, target, "<span class='warning'>You screw up, causing more damage!</span>",
"<span class='warning'>[user] screws up, causing brain damage!</span>",
"[user] completes the surgery on [target]'s brain.")
target.adjustBrainLoss(60)
target.adjustOrganLoss(ORGAN_SLOT_BRAIN, 60)
target.gain_trauma_type(BRAIN_TRAUMA_SEVERE, TRAUMA_RESILIENCE_LOBOTOMY)
else
user.visible_message("<span class='warning'>[user] suddenly notices that the brain [user.p_they()] [user.p_were()] working on is not there anymore.", "<span class='warning'>You suddenly notice that the brain you were working on is not there anymore.</span>")
+77
View File
@@ -0,0 +1,77 @@
/datum/surgery/coronary_bypass
name = "Coronary Bypass"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/saw, /datum/surgery_step/clamp_bleeders,
/datum/surgery_step/incise_heart, /datum/surgery_step/coronary_bypass, /datum/surgery_step/close)
possible_locs = list(BODY_ZONE_CHEST)
/datum/surgery/coronary_bypass/can_start(mob/user, mob/living/carbon/target)
var/obj/item/organ/heart/H = target.getorganslot(ORGAN_SLOT_HEART)
if(H)
if(H.damage > 60 && !H.operated)
return TRUE
return FALSE
//an incision but with greater bleed, and a 90% base success chance
/datum/surgery_step/incise_heart
name = "incise heart"
implements = list(/obj/item/scalpel = 90, /obj/item/melee/transforming/energy/sword = 45, /obj/item/kitchen/knife = 45,
/obj/item/shard = 25)
time = 16
/datum/surgery_step/incise_heart/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
display_results(user, target, "<span class='notice'>You begin to make an incision in [target]'s heart...</span>",
"[user] begins to make an incision in [target]'s heart.",
"[user] begins to make an incision in [target]'s heart.")
/datum/surgery_step/incise_heart/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(ishuman(target))
var/mob/living/carbon/human/H = target
if (!(NOBLOOD in H.dna.species.species_traits))
display_results(user, target, "<span class='notice'>Blood pools around the incision in [H]'s heart.</span>",
"Blood pools around the incision in [H]'s heart.",
"")
H.bleed_rate += 10
H.adjustBruteLoss(10)
return TRUE
/datum/surgery_step/incise_heart/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(ishuman(target))
var/mob/living/carbon/human/H = target
display_results(user, target, "<span class='warning'>You screw up, cutting too deeply into the heart!</span>",
"<span class='warning'>[user] screws up, causing blood to spurt out of [H]'s chest!</span>",
"<span class='warning'>[user] screws up, causing blood to spurt out of [H]'s chest!</span>")
H.bleed_rate += 20
H.adjustOrganLoss(ORGAN_SLOT_HEART, 10)
H.adjustBruteLoss(10)
//grafts a coronary bypass onto the individual's heart, success chance is 90% base again
/datum/surgery_step/coronary_bypass
name = "graft coronary bypass"
implements = list(/obj/item/hemostat = 90, TOOL_WIRECUTTER = 35, /obj/item/stack/packageWrap = 15, /obj/item/stack/cable_coil = 5)
time = 90
/datum/surgery_step/coronary_bypass/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
display_results(user, target, "<span class='notice'>You begin to graft a bypass onto [target]'s heart...</span>",
"[user] begins to graft something onto [target]'s heart!",
"[user] begins to graft something onto [target]'s heart!")
/datum/surgery_step/coronary_bypass/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
target.setOrganLoss(ORGAN_SLOT_HEART, 60)
var/obj/item/organ/heart/heart = target.getorganslot(ORGAN_SLOT_HEART)
if(heart) //slightly worrying if we lost our heart mid-operation, but that's life
heart.operated = TRUE
display_results(user, target, "<span class='notice'>You successfully graft a bypass onto [target]'s heart.</span>",
"[user] finishes grafting something onto [target]'s heart.",
"[user] finishes grafting something onto [target]'s heart.")
return TRUE
/datum/surgery_step/coronary_bypass/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(ishuman(target))
var/mob/living/carbon/human/H = target
display_results(user, target, "<span class='warning'>You screw up in attaching the graft, and it tears off, tearing part of the heart!</span>",
"<span class='warning'>[user] screws up, causing blood to spurt out of [H]'s chest profusely!</span>",
"<span class='warning'>[user] screws up, causing blood to spurt out of [H]'s chest profusely!</span>")
H.adjustOrganLoss(ORGAN_SLOT_HEART, 20)
H.bleed_rate += 30
return FALSE
+1 -1
View File
@@ -37,7 +37,7 @@
display_results(user, target, "<span class='warning'>You accidentally stab [target] right in the brain!</span>",
"<span class='warning'>[user] accidentally stabs [target] right in the brain!</span>",
"<span class='warning'>[user] accidentally stabs [target] right in the brain!</span>")
target.adjustBrainLoss(70)
target.adjustOrganLoss(ORGAN_SLOT_BRAIN, 70)
else
display_results(user, target, "<span class='warning'>You accidentally stab [target] right in the brain! Or would have, if [target] had a brain.</span>",
"<span class='warning'>[user] accidentally stabs [target] right in the brain! Or would have, if [target] had a brain.</span>",
+70
View File
@@ -0,0 +1,70 @@
//Organ reconstruction, limited to the chest region as most organs in the head have their own repair method (eyes/brain). We require synthflesh for these
//steps since fixing internal organs aren't as simple as mending exterior flesh, though in the future it would be neat to add more chems to the viable list.
//TBD: Add heart damage, have heart reconstruction seperate from organ reconstruction, and find a better name for this. I can imagine people getting it confused with manipulation.
/datum/surgery/graft_synthtissue
name = "Graft synthtissue"
species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_GROIN, BODY_ZONE_PRECISE_EYES)
steps = list(
/datum/surgery_step/incise,
/datum/surgery_step/retract_skin,
/datum/surgery_step/saw,
/datum/surgery_step/clamp_bleeders,
/datum/surgery_step/incise,
/datum/surgery_step/graft_synthtissue,
/datum/surgery_step/close
)
//repair organs
/datum/surgery_step/graft_synthtissue
name = "graft synthtissue"
implements = list(/obj/item/hemostat = 100, TOOL_SCREWDRIVER = 35, /obj/item/pen = 15)
repeatable = TRUE
time = 75
chems_needed = list("synthtissue")
var/obj/item/organ/chosen_organ
var/health_restored = 10
/datum/surgery_step/graft_synthtissue/preop(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(implement_type in implements)
var/list/organs = target.getorganszone(target_zone)
if(!organs.len)
to_chat(user, "<span class='notice'>There are no targetable organs in [target]'s [parse_zone(target_zone)]!</span>")
return -1
else
for(var/obj/item/organ/O in organs)
O.on_find(user)
organs -= O
organs[O.name] = O
chosen_organ = input("Target which organ?", "Surgery", null, null) as null|anything in organs
chosen_organ = organs[chosen_organ]
if(!chosen_organ)
return -1
if(!target.reagents.has_reagent("synthtissue"))
to_chat(user, "<span class='notice'>There's no synthtissue available for use on [chosen_organ]</span>")
return -1
var/datum/reagent/synthtissue/Sf = locate(/datum/reagent/synthtissue) in target.reagents.reagent_list
if(Sf.volume < 10)
to_chat(user, "<span class='notice'>There's not enough synthtissue to perform the operation! There needs to be at least 10u.</span>")
return -1
if((chosen_organ.organ_flags & ORGAN_FAILING) && !(Sf.data["grown_volume"] >= 115))
to_chat(user, "<span class='notice'>[chosen_organ] is too damaged to graft onto!</span>")
return -1
if(health_restored != 10)
health_restored = 10
health_restored += (Sf.data["grown_volume"]/10)
user.visible_message("[user] begins to graft synthtissue onto [chosen_organ].</span>")
target.reagents.remove_reagent("synthtissue", 10)
/datum/surgery_step/graft_synthtissue/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("[user] successfully repairs part of [chosen_organ].", "<span class='notice'>You succeed in repairing parts of [chosen_organ].</span>")
chosen_organ.applyOrganDamage(health_restored)
/datum/surgery_step/graft_synthtissue/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("<span class='warning'>[user] accidentally damages part of [chosen_organ]!</span>", "<span class='warning'>You damage [chosen_organ]! Apply more synthtissue if it's run out.</span>")
chosen_organ.applyOrganDamage(10)
return FALSE
+46
View File
@@ -0,0 +1,46 @@
/datum/surgery/lobectomy
name = "Lobectomy" //not to be confused with lobotomy
steps = list(/datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/saw, /datum/surgery_step/clamp_bleeders,
/datum/surgery_step/lobectomy, /datum/surgery_step/close)
possible_locs = list(BODY_ZONE_CHEST)
/datum/surgery/lobectomy/can_start(mob/user, mob/living/carbon/target)
var/obj/item/organ/lungs/L = target.getorganslot(ORGAN_SLOT_LUNGS)
if(L)
if(L.damage > 60 && !L.operated)
return TRUE
return FALSE
//lobectomy, removes the most damaged lung lobe with a 95% base success chance
/datum/surgery_step/lobectomy
name = "excise damaged lung node"
implements = list(/obj/item/scalpel = 95, /obj/item/melee/transforming/energy/sword = 65, /obj/item/kitchen/knife = 45,
/obj/item/shard = 35)
time = 42
/datum/surgery_step/lobectomy/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
display_results(user, target, "<span class='notice'>You begin to make an incision in [target]'s lungs...</span>",
"[user] begins to make an incision in [target].",
"[user] begins to make an incision in [target].")
/datum/surgery_step/lobectomy/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(ishuman(target))
var/mob/living/carbon/human/H = target
var/obj/item/organ/lungs/L = H.getorganslot(ORGAN_SLOT_LUNGS)
L.operated = TRUE
H.setOrganLoss(ORGAN_SLOT_LUNGS, 60)
display_results(user, target, "<span class='notice'>You successfully excise [H]'s most damaged lobe.</span>",
"Successfully removes a piece of [H]'s lungs.",
"")
return TRUE
/datum/surgery_step/lobectomy/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(ishuman(target))
var/mob/living/carbon/human/H = target
display_results(user, target, "<span class='warning'>You screw up, failing to excise [H]'s damaged lobe!</span>",
"<span class='warning'>[user] screws up!</span>",
"<span class='warning'>[user] screws up!</span>")
H.losebreath += 4
H.adjustOrganLoss(ORGAN_SLOT_LUNGS, 10)
return FALSE
+18 -2
View File
@@ -3,7 +3,23 @@
icon_state = "appendix"
zone = BODY_ZONE_PRECISE_GROIN
slot = ORGAN_SLOT_APPENDIX
var/inflamed = 0
healing_factor = STANDARD_ORGAN_HEALING
decay_factor = STANDARD_ORGAN_DECAY
now_failing = "<span class='warning'>An explosion of pain erupts in your lower right abdomen!</span>"
now_fixed = "<span class='info'>The pain in your abdomen has subsided.</span>"
var/inflamed
/obj/item/organ/appendix/on_life()
..()
if(!(organ_flags & ORGAN_FAILING))
return
var/mob/living/carbon/M = owner
if(M)
M.adjustToxLoss(4, TRUE, TRUE) //forced to ensure people don't use it to gain tox as slime person
/obj/item/organ/appendix/update_icon()
if(inflamed)
@@ -16,7 +32,7 @@
/obj/item/organ/appendix/Remove(mob/living/carbon/M, special = 0)
for(var/datum/disease/appendicitis/A in M.diseases)
A.cure()
inflamed = 1
inflamed = TRUE
update_icon()
..()
+3 -2
View File
@@ -121,7 +121,7 @@
playsound(get_turf(owner), 'sound/mecha/mechmove03.ogg', 50, 1)
/obj/item/organ/cyberimp/arm/ui_action_click()
if(crit_fail || (!holder && !contents.len))
if(crit_fail || (organ_flags & ORGAN_FAILING) || (!holder && !contents.len))
to_chat(owner, "<span class='warning'>The implant doesn't respond. It seems to be broken...</span>")
return
@@ -145,7 +145,7 @@
. = ..()
if(. & EMP_PROTECT_SELF)
return
if(prob(30/severity) && owner && !crit_fail)
if(prob(30/severity) && owner && !(organ_flags & ORGAN_FAILING))
Retract()
owner.visible_message("<span class='danger'>A loud bang comes from [owner]\'s [zone == BODY_ZONE_R_ARM ? "right" : "left"] arm!</span>")
playsound(get_turf(owner), 'sound/weapons/flashbang.ogg', 100, 1)
@@ -154,6 +154,7 @@
owner.IgniteMob()
owner.adjustFireLoss(25)
crit_fail = 1
organ_flags |= ORGAN_FAILING
/obj/item/organ/cyberimp/arm/gun/laser
@@ -144,7 +144,7 @@
/obj/item/organ/cyberimp/chest/thrusters/proc/toggle(silent = FALSE)
if(!on)
if(crit_fail)
if(crit_fail || (organ_flags & ORGAN_FAILING))
if(!silent)
to_chat(owner, "<span class='warning'>Your thrusters set seems to be broken!</span>")
return 0
@@ -4,6 +4,7 @@
name = "cybernetic implant"
desc = "A state-of-the-art implant that improves a baseline's functionality."
status = ORGAN_ROBOTIC
organ_flags = ORGAN_SYNTHETIC
var/implant_color = "#FFFFFF"
var/implant_overlay
var/syndicate_implant = FALSE //Makes the implant invisible to health analyzers and medical HUDs.
@@ -102,7 +103,7 @@
/obj/item/organ/cyberimp/brain/anti_stun/on_life()
..()
if(crit_fail)
if(crit_fail || !(organ_flags & ORGAN_FAILING))
return
owner.adjustStaminaLoss(-3.5) //Citadel edit, makes it more useful in Stamina based combat
if(owner.AmountStun() > STUN_SET_AMOUNT)
@@ -112,13 +113,15 @@
/obj/item/organ/cyberimp/brain/anti_stun/emp_act(severity)
. = ..()
if(crit_fail || . & EMP_PROTECT_SELF)
if(crit_fail || (organ_flags & ORGAN_FAILING) || . & EMP_PROTECT_SELF)
return
crit_fail = TRUE
organ_flags |= ORGAN_FAILING
addtimer(CALLBACK(src, .proc/reboot), 90 / severity)
/obj/item/organ/cyberimp/brain/anti_stun/proc/reboot()
crit_fail = FALSE
organ_flags &= ~ORGAN_FAILING
//[[[[MOUTH]]]]
+39 -3
View File
@@ -6,6 +6,14 @@
slot = ORGAN_SLOT_EARS
gender = PLURAL
healing_factor = STANDARD_ORGAN_HEALING
decay_factor = STANDARD_ORGAN_DECAY
low_threshold_passed = "<span class='info'>Your ears begin to resonate with an internal ring sometimes.</span>"
now_failing = "<span class='warning'>You are unable to hear at all!</span>"
now_fixed = "<span class='info'>Noise slowly begins filling your ears once more.</span>"
low_threshold_cleared = "<span class='info'>The ringing in your ears has died down.</span>"
// `deaf` measures "ticks" of deafness. While > 0, the person is unable
// to hear anything.
var/deaf = 0
@@ -23,17 +31,26 @@
/obj/item/organ/ears/on_life()
if(!iscarbon(owner))
return
..()
var/mob/living/carbon/C = owner
if((damage < maxHealth) && (organ_flags & ORGAN_FAILING)) //ear damage can be repaired from the failing condition
organ_flags &= ~ORGAN_FAILING
// genetic deafness prevents the body from using the ears, even if healthy
if(HAS_TRAIT(C, TRAIT_DEAF))
deaf = max(deaf, 1)
else if(ear_damage < UNHEALING_EAR_DAMAGE) // if higher than UNHEALING_EAR_DAMAGE, no natural healing occurs.
ear_damage = max(ear_damage - 0.05, 0)
else if(!(organ_flags & ORGAN_FAILING)) // if this organ is failing, do not clear deaf stacks.
deaf = max(deaf - 1, 0)
if(prob(damage / 20) && (damage > low_threshold))
adjustEarDamage(0, 4)
SEND_SOUND(C, sound('sound/weapons/flash_ring.ogg'))
to_chat(C, "<span class='warning'>The ringing in your ears grows louder, blocking out any external noises for a moment.</span>")
else if((organ_flags & ORGAN_FAILING) && (deaf == 0))
deaf = 1 //stop being not deaf you deaf idiot
/obj/item/organ/ears/proc/restoreEars()
deaf = 0
ear_damage = 0
organ_flags &= ~ORGAN_FAILING
var/mob/living/carbon/C = owner
@@ -99,4 +116,23 @@
name = "tin ears"
desc = "The robust ears of a bronze golem. "
damage_multiplier = 0.1 //STRONK
bang_protect = 1 //Fear me weaklings.
bang_protect = 1 //Fear me weaklings.
/obj/item/organ/ears/cybernetic
name = "cybernetic ears"
icon_state = "ears-c"
desc = "a basic cybernetic designed to mimic the operation of ears."
damage_multiplier = 0.9
organ_flags = ORGAN_SYNTHETIC
/obj/item/organ/ears/cybernetic/upgraded
name = "upgraded cybernetic ears"
icon_state = "ears-c-u"
desc = "an advanced cybernetic ear, surpassing the performance of organic ears"
damage_multiplier = 0.5
/obj/item/organ/ears/cybernetic/emp_act(severity)
. = ..()
if(. & EMP_PROTECT_SELF)
return
damage += 40/severity
+54 -5
View File
@@ -6,6 +6,19 @@
slot = ORGAN_SLOT_EYES
gender = PLURAL
healing_factor = STANDARD_ORGAN_HEALING
decay_factor = STANDARD_ORGAN_DECAY
maxHealth = 0.5 * STANDARD_ORGAN_THRESHOLD //half the normal health max since we go blind at 30, a permanent blindness at 50 therefore makes sense unless medicine is administered
high_threshold = 0.3 * STANDARD_ORGAN_THRESHOLD //threshold at 30
low_threshold = 0.15 * STANDARD_ORGAN_THRESHOLD //threshold at 15
low_threshold_passed = "<span class='info'>Distant objects become somewhat less tangible.</span>"
high_threshold_passed = "<span class='info'>Everything starts to look a lot less clear.</span>"
now_failing = "<span class='warning'>Darkness envelopes you, as your eyes go blind!</span>"
now_fixed = "<span class='info'>Color and shapes are once again perceivable.</span>"
high_threshold_cleared = "<span class='info'>Your vision functions passably once more.</span>"
low_threshold_cleared = "<span class='info'>Your vision is cleared of any ailment.</span>"
var/sight_flags = 0
var/see_in_dark = 2
var/eye_damage = 0
@@ -15,9 +28,12 @@
var/flash_protect = 0
var/see_invisible = SEE_INVISIBLE_LIVING
var/lighting_alpha
var/damaged = FALSE //damaged indicates that our eyes are undergoing some level of negative effect
/obj/item/organ/eyes/Insert(mob/living/carbon/M, special = FALSE, drop_if_replaced = FALSE)
..()
if(damage == initial(damage))
clear_eye_trauma()
if(ishuman(owner))
var/mob/living/carbon/human/HMN = owner
old_eye_color = HMN.eye_color
@@ -32,7 +48,9 @@
M.update_tint()
owner.update_sight()
/obj/item/organ/eyes/Remove(mob/living/carbon/M, special = 0)
clear_eye_trauma()
..()
if(ishuman(M) && eye_color)
var/mob/living/carbon/human/HMN = M
@@ -41,6 +59,34 @@
M.update_tint()
M.update_sight()
/obj/item/organ/eyes/on_life()
..()
var/mob/living/carbon/C = owner
//since we can repair fully damaged eyes, check if healing has occurred
if((organ_flags & ORGAN_FAILING) && (damage < maxHealth))
organ_flags &= ~ORGAN_FAILING
C.cure_blind(EYE_DAMAGE)
//various degrees of "oh fuck my eyes", from "point a laser at your eye" to "staring at the Sun" intensities
if(damage > 20)
damaged = TRUE
if(organ_flags & ORGAN_FAILING)
C.become_blind(EYE_DAMAGE)
else if(damage > 30)
C.overlay_fullscreen("eye_damage", /obj/screen/fullscreen/impaired, 2)
else
C.overlay_fullscreen("eye_damage", /obj/screen/fullscreen/impaired, 1)
//called once since we don't want to keep clearing the screen of eye damage for people who are below 20 damage
else if(damaged)
damaged = FALSE
C.clear_fullscreen("eye_damage")
return
/obj/item/organ/eyes/proc/clear_eye_trauma()
var/mob/living/carbon/C = owner
C.clear_fullscreen("eye_damage")
C.cure_blind(EYE_DAMAGE)
damaged = FALSE
/obj/item/organ/eyes/night_vision
name = "shadow eyes"
desc = "A spooky set of eyes that can see in the dark."
@@ -71,6 +117,7 @@
/obj/item/organ/eyes/night_vision/zombie
name = "undead eyes"
desc = "Somewhat counterintuitively, these half-rotten eyes actually have superior vision to those of a living human."
sight_flags = SEE_MOBS
/obj/item/organ/eyes/night_vision/nightmare
name = "burning red eyes"
@@ -88,15 +135,17 @@
icon_state = "cybernetic_eyeballs"
desc = "Your vision is augmented."
status = ORGAN_ROBOTIC
organ_flags = ORGAN_SYNTHETIC
/obj/item/organ/eyes/robotic/emp_act(severity)
. = ..()
if(!owner || . & EMP_PROTECT_SELF)
return
if(prob(10 * severity))
return
to_chat(owner, "<span class='warning'>Static obfuscates your vision!</span>")
owner.flash_act(visual = 1)
if(severity == EMP_HEAVY)
owner.adjustOrganLoss(ORGAN_SLOT_EYES, 20)
/obj/item/organ/eyes/robotic/xray
name = "\improper X-ray eyes"
@@ -137,7 +186,7 @@
M.become_blind("flashlight_eyes")
/obj/item/organ/eyes/robotic/flashlight/Remove(var/mob/living/carbon/M, var/special = 0)
/obj/item/organ/eyes/robotic/flashlight/Remove(var/mob/living/carbon/M, special = FALSE)
eye.on = FALSE
eye.update_brightness(M)
eye.forceMove(src)
@@ -321,7 +370,7 @@
if(!istype(parent))
return INITIALIZE_HINT_QDEL
/obj/item/organ/eyes/moth
name = "moth eyes"
/obj/item/organ/eyes/insect
name = "insect eyes"
desc = "These eyes seem to have increased sensitivity to bright light, with no improvement to low light vision."
flash_protect = -1
+53 -3
View File
@@ -4,12 +4,24 @@
icon_state = "heart-on"
zone = BODY_ZONE_CHEST
slot = ORGAN_SLOT_HEART
healing_factor = STANDARD_ORGAN_HEALING
decay_factor = 4 * STANDARD_ORGAN_DECAY //designed to fail about 5 minutes after death
low_threshold_passed = "<span class='info'>Prickles of pain appear then die out from within your chest...</span>"
high_threshold_passed = "<span class='warning'>Something inside your chest hurts, and the pain isn't subsiding. You notice yourself breathing far faster than before.</span>"
now_fixed = "<span class='info'>Your heart begins to beat again.</span>"
high_threshold_cleared = "<span class='info'>The pain in your chest has died down, and your breathing becomes more relaxed.</span>"
// Heart attack code is in code/modules/mob/living/carbon/human/life.dm
var/beating = 1
var/icon_base = "heart"
attack_verb = list("beat", "thumped")
var/beat = BEAT_NONE//is this mob having a heatbeat sound played? if so, which?
var/failed = FALSE //to prevent constantly running failing code
var/operated = FALSE //whether the heart's been operated on to fix some of its damages
/obj/item/organ/heart/update_icon()
if(beating)
icon_state = "[icon_base]-on"
@@ -50,6 +62,7 @@
/obj/item/organ/heart/on_life()
if(owner.client && beating)
failed = FALSE
var/sound/slowbeat = sound('sound/health/slowbeat.ogg', repeat = TRUE)
var/sound/fastbeat = sound('sound/health/fastbeat.ogg', repeat = TRUE)
var/mob/living/carbon/H = owner
@@ -70,11 +83,18 @@
H.stop_sound_channel(CHANNEL_HEARTBEAT)
beat = BEAT_NONE
if(organ_flags & ORGAN_FAILING) //heart broke, stopped beating, death imminent
if(owner.stat == CONSCIOUS)
owner.visible_message("<span class='userdanger'>[owner] clutches at [owner.p_their()] chest as if [owner.p_their()] heart is stopping!</span>")
owner.set_heartattack(TRUE)
failed = TRUE
/obj/item/organ/heart/cursed
name = "cursed heart"
desc = "A heart that, when inserted, will force you to pump it manually."
icon_state = "cursedheart-off"
icon_base = "cursedheart"
decay_factor = 0
actions_types = list(/datum/action/item_action/organ_action/cursed_heart)
var/last_pump = 0
var/add_colour = TRUE //So we're not constantly recreating colour datums
@@ -153,18 +173,48 @@
name = "cybernetic heart"
desc = "An electronic device designed to mimic the functions of an organic human heart. Offers no benefit over an organic heart other than being easy to make."
icon_state = "heart-c"
synthetic = TRUE
organ_flags = ORGAN_SYNTHETIC
/obj/item/organ/heart/cybernetic/emp_act()
/obj/item/organ/heart/cybernetic/emp_act(severity)
. = ..()
if(. & EMP_PROTECT_SELF)
return
Stop()
addtimer(CALLBACK(src, .proc/Restart), 20/severity SECONDS)
damage += 100/severity
/obj/item/organ/heart/cybernetic/upgraded
name = "upgraded cybernetic heart"
desc = "An electronic device designed to mimic the functions of an organic human heart. Also holds an emergency dose of epinephrine, used automatically after facing severe trauma. This upgraded model can regenerate its dose after use."
icon_state = "heart-c-u"
maxHealth = 2 * STANDARD_ORGAN_THRESHOLD
//I put it on upgraded for now.
var/dose_available = TRUE
var/rid = /datum/reagent/medicine/epinephrine
var/ramount = 10
obj/item/organ/heart/cybernetic/upgraded/on_life()
. = ..()
if(dose_available && owner.health <= owner.crit_threshold && !owner.reagents.has_reagent(rid))
owner.reagents.add_reagent(rid, ramount)
used_dose()
if(ramount < 10) //eats your nutrition to regen epinephrine
var/regen_amount = owner.nutrition/2000
owner.nutrition -= regen_amount
ramount += regen_amount
/obj/item/organ/heart/cybernetic/upgraded/proc/used_dose()
. = ..()
addtimer(VARSET_CALLBACK(src, dose_available, TRUE), 5 MINUTES)
ramount = 0
/obj/item/organ/heart/freedom
name = "heart of freedom"
desc = "This heart pumps with the passion to give... something freedom."
synthetic = TRUE //the power of freedom prevents heart attacks
organ_flags = ORGAN_SYNTHETIC //the power of freedom prevents heart attacks
var/min_next_adrenaline = 0
/obj/item/organ/heart/freedom/on_life()
+10 -6
View File
@@ -10,10 +10,13 @@
zone = BODY_ZONE_CHEST
slot = ORGAN_SLOT_LIVER
desc = "Pairing suggestion: chianti and fava beans."
var/damage = 0 //liver damage, 0 is no damage, damage=maxHealth causes liver failure
maxHealth = STANDARD_ORGAN_THRESHOLD
healing_factor = STANDARD_ORGAN_HEALING
decay_factor = STANDARD_ORGAN_DECAY
var/alcohol_tolerance = ALCOHOL_RATE//affects how much damage the liver takes from alcohol
var/failing //is this liver failing?
var/maxHealth = LIVER_DEFAULT_HEALTH
var/toxTolerance = LIVER_DEFAULT_TOX_TOLERANCE//maximum amount of toxins the liver can just shrug off
var/toxLethality = LIVER_DEFAULT_TOX_LETHALITY//affects how much damage toxins do to the liver
var/filterToxins = TRUE //whether to filter toxins
@@ -24,7 +27,7 @@
var/mob/living/carbon/C = owner
if(istype(C))
if(!failing)//can't process reagents with a failing liver
if(!(organ_flags & ORGAN_FAILING))//can't process reagents with a failing liver
//slowly heal liver damage
damage = max(0, damage - 0.1)
@@ -69,7 +72,7 @@
if(moveCalc == cachedmoveCalc)//reduce calculations
return
if(prob(5))
to_chat(owner, "<span class='notice'>You feel a stange ache in your side, almost like a sitch. This pain is affecting your movements and making you feel lightheaded.</span>")
to_chat(owner, "<span class='notice'>You feel a stange ache in your side, almost like a stitch. This pain is affecting your movements and making you feel lightheaded.</span>")
var/mob/living/carbon/human/H = owner
H.add_movespeed_modifier(LIVER_SWELLING_MOVE_MODIFY, TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = moveCalc)
H.AdjustBloodVol(moveCalc/3)
@@ -97,14 +100,15 @@
name = "cybernetic liver"
icon_state = "liver-c"
desc = "An electronic device designed to mimic the functions of a human liver. It has no benefits over an organic liver, but is easy to produce."
synthetic = TRUE
organ_flags = ORGAN_SYNTHETIC
maxHealth = 1.1 * STANDARD_ORGAN_THRESHOLD
/obj/item/organ/liver/cybernetic/upgraded
name = "upgraded cybernetic liver"
icon_state = "liver-c-u"
desc = "An upgraded version of the cybernetic liver, designed to improve upon organic livers. It is resistant to alcohol poisoning and is very robust at filtering toxins."
alcohol_tolerance = 0.001
maxHealth = 200 //double the health of a normal liver
maxHealth = 2 * STANDARD_ORGAN_THRESHOLD
toxTolerance = 15 //can shrug off up to 15u of toxins
toxLethality = 0.008 //20% less damage than a normal liver
+73 -31
View File
@@ -8,6 +8,19 @@
gender = PLURAL
w_class = WEIGHT_CLASS_NORMAL
var/failed = FALSE
var/operated = FALSE //whether we can still have our damages fixed through surgery
//health
maxHealth = LUNGS_MAX_HEALTH
healing_factor = STANDARD_ORGAN_HEALING
decay_factor = STANDARD_ORGAN_DECAY
high_threshold_passed = "<span class='warning'>You feel some sort of constriction around your chest as your breathing becomes shallow and rapid.</span>"
now_fixed = "<span class='warning'>Your lungs seem to once again be able to hold air.</span>"
high_threshold_cleared = "<span class='info'>The constriction around your chest loosens as your breathing calms down.</span>"
//Breath damage
var/safe_oxygen_min = 16 // Minimum safe partial pressure of O2, in kPa
@@ -56,36 +69,35 @@
var/crit_stabilizing_reagent = "epinephrine"
//health
var/maxHealth = LUNGS_MAX_HEALTH
var/damage = 0
//TODO: lung health affects lung function
/obj/item/organ/lungs/proc/adjustLungLoss(damage_mod, mob/living/carbon/M) //damage might be too low atm.
/obj/item/organ/lungs/onDamage(damage_mod) //damage might be too low atm.
var/cached_damage = damage
if (maxHealth == INFINITY)
return
if(damage+damage_mod < 0)
damage = 0
if(cached_damage+damage_mod < 0)
cached_damage = 0
return
damage += damage_mod
if ((damage / maxHealth) > 1)
to_chat(M, "<span class='userdanger'>You feel your lungs collapse within your chest as you gasp for air, unable to inflate them anymore!</span>")
M.emote("gasp")
cached_damage += damage_mod
if ((cached_damage/ maxHealth) > 1)
to_chat(owner, "<span class='userdanger'>You feel your lungs collapse within your chest as you gasp for air, unable to inflate them anymore!</span>")
owner.emote("gasp")
SSblackbox.record_feedback("tally", "fermi_chem", 1, "Lungs lost")
qdel(src)
else if ((damage / maxHealth) > 0.75)
to_chat(M, "<span class='warning'>It's getting really hard to breathe!!</span>")
M.emote("gasp")
M.Dizzy(3)
else if ((damage / maxHealth) > 0.5)
M.Dizzy(2)
to_chat(M, "<span class='notice'>Your chest is really starting to hurt.</span>")
M.emote("cough")
else if ((damage / maxHealth) > 0.2)
to_chat(M, "<span class='notice'>You feel an ache within your chest.</span>")
M.emote("cough")
M.Dizzy(1)
//qdel(src) - Handled elsewhere for now.
else if ((cached_damage / maxHealth) > 0.75)
to_chat(owner, "<span class='warning'>It's getting really hard to breathe!!</span>")
owner.emote("gasp")
owner.Dizzy(3)
else if ((cached_damage / maxHealth) > 0.5)
owner.Dizzy(2)
to_chat(owner, "<span class='notice'>Your chest is really starting to hurt.</span>")
owner.emote("cough")
else if ((cached_damage / maxHealth) > 0.2)
to_chat(owner, "<span class='notice'>You feel an ache within your chest.</span>")
owner.emote("cough")
owner.Dizzy(1)
/obj/item/organ/lungs/proc/check_breath(datum/gas_mixture/breath, mob/living/carbon/human/H)
//TODO: add lung damage = less oxygen gains
@@ -289,7 +301,7 @@
H.hallucination += 10
H.reagents.add_reagent("bz_metabolites",5)
if(prob(33))
H.adjustBrainLoss(3, 150)
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3, 150)
else if(bz_pp > 0.01)
H.hallucination += 5
@@ -405,13 +417,13 @@
var/cold_modifier = H.dna.species.coldmod
if(breath_temperature < cold_level_3_threshold)
H.apply_damage_type(cold_level_3_damage*cold_modifier, cold_damage_type)
adjustLungLoss((cold_level_3_damage*cold_modifier*2), H)
H.adjustOrganLoss(ORGAN_SLOT_LUNGS, (cold_level_3_damage*cold_modifier*2))
if(breath_temperature > cold_level_3_threshold && breath_temperature < cold_level_2_threshold)
H.apply_damage_type(cold_level_2_damage*cold_modifier, cold_damage_type)
adjustLungLoss((cold_level_2_damage*cold_modifier*2), H)
H.adjustOrganLoss(ORGAN_SLOT_LUNGS, (cold_level_2_damage*cold_modifier*2))
if(breath_temperature > cold_level_2_threshold && breath_temperature < cold_level_1_threshold)
H.apply_damage_type(cold_level_1_damage*cold_modifier, cold_damage_type)
adjustLungLoss((cold_level_1_damage*cold_modifier*2), H)
H.adjustOrganLoss(ORGAN_SLOT_LUNGS, (cold_level_1_damage*cold_modifier*2))
if(breath_temperature < cold_level_1_threshold)
if(prob(20))
to_chat(H, "<span class='warning'>You feel [cold_message] in your [name]!</span>")
@@ -420,17 +432,29 @@
var/heat_modifier = H.dna.species.heatmod
if(breath_temperature > heat_level_1_threshold && breath_temperature < heat_level_2_threshold)
H.apply_damage_type(heat_level_1_damage*heat_modifier, heat_damage_type)
adjustLungLoss((heat_level_1_damage*heat_modifier*2), H)
H.adjustOrganLoss(ORGAN_SLOT_LUNGS, (heat_level_1_damage*heat_modifier*2))
if(breath_temperature > heat_level_2_threshold && breath_temperature < heat_level_3_threshold)
H.apply_damage_type(heat_level_2_damage*heat_modifier, heat_damage_type)
adjustLungLoss((heat_level_2_damage*heat_modifier*2), H)
H.adjustOrganLoss(ORGAN_SLOT_LUNGS, (heat_level_2_damage*heat_modifier*2))
if(breath_temperature > heat_level_3_threshold)
H.apply_damage_type(heat_level_3_damage*heat_modifier, heat_damage_type)
adjustLungLoss((heat_level_3_damage*heat_modifier*2), H)
H.adjustOrganLoss(ORGAN_SLOT_LUNGS, (heat_level_3_damage*heat_modifier*2))
if(breath_temperature > heat_level_1_threshold)
if(prob(20))
to_chat(H, "<span class='warning'>You feel [hot_message] in your [name]!</span>")
/obj/item/organ/lungs/on_life()
..()
if((!failed) && ((organ_flags & ORGAN_FAILING)))
if(owner.stat == CONSCIOUS)
owner.visible_message("<span class='danger'>[owner] grabs [owner.p_their()] throat, struggling for breath!</span>", \
"<span class='userdanger'>You suddenly feel like you can't breathe!</span>")
failed = TRUE
else if(!(organ_flags & ORGAN_FAILING))
failed = FALSE
return
/obj/item/organ/lungs/prepare_eat()
var/obj/S = ..()
S.reagents.add_reagent("salbutamol", 5)
@@ -451,14 +475,16 @@
name = "cybernetic lungs"
desc = "A cybernetic version of the lungs found in traditional humanoid entities. It functions the same as an organic lung and is merely meant as a replacement."
icon_state = "lungs-c"
synthetic = TRUE
organ_flags = ORGAN_SYNTHETIC
maxHealth = 400
safe_oxygen_min = 13
/obj/item/organ/lungs/cybernetic/emp_act()
. = ..()
if(. & EMP_PROTECT_SELF)
return
owner.losebreath = 20
owner.adjustOrganLoss(ORGAN_SLOT_LUNGS, 25)
/obj/item/organ/lungs/cybernetic/upgraded
@@ -495,8 +521,24 @@
safe_toxins_max = 0 //We breathe this to gain POWER.
cold_level_1_threshold = 285 // Remember when slimes used to be succeptable to cold? Well....
cold_level_2_threshold = 260
cold_level_3_threshold = 230
maxHealth = 250
/obj/item/organ/lungs/slime/check_breath(datum/gas_mixture/breath, mob/living/carbon/human/H)
. = ..()
if (breath && breath.gases[/datum/gas/plasma])
var/plasma_pp = breath.get_breath_partial_pressure(breath.gases[/datum/gas/plasma])
owner.blood_volume += (0.2 * plasma_pp) // 10/s when breathing literally nothing but plasma, which will suffocate you.
/obj/item/organ/lungs/yamerol
name = "Yamerol lungs"
desc = "A temporary pair of lungs made from self assembling yamerol molecules."
maxHealth = 200
color = "#68e83a"
/obj/item/organ/lungs/yamerol/on_life()
..()
damage += 2 //Yamerol lungs are temporary
+122 -13
View File
@@ -1,3 +1,6 @@
#define STANDARD_ORGAN_THRESHOLD 100
#define STANDARD_ORGAN_HEALING 0.001
/obj/item/organ
name = "organ"
icon = 'icons/obj/surgery.dmi'
@@ -8,11 +11,23 @@
var/zone = BODY_ZONE_CHEST
var/slot
// DO NOT add slots with matching names to different zones - it will break internal_organs_slot list!
var/vital = 0
//Was this organ implanted/inserted/etc, if true will not be removed during species change.
var/external = FALSE
var/synthetic = FALSE // To distinguish between organic and synthetic organs
var/organ_flags = 0
var/maxHealth = STANDARD_ORGAN_THRESHOLD
var/damage = 0 //total damage this organ has sustained
///Healing factor and decay factor function on % of maxhealth, and do not work by applying a static number per tick
var/healing_factor = 0 //fraction of maxhealth healed per on_life(), set to 0 for generic organs
var/decay_factor = 0 //same as above but when without a living owner, set to 0 for generic organs
var/high_threshold = STANDARD_ORGAN_THRESHOLD * 0.45 //when severe organ damage occurs
var/low_threshold = STANDARD_ORGAN_THRESHOLD * 0.1 //when minor organ damage occurs
///Organ variables for determining what we alert the owner with when they pass/clear the damage thresholds
var/prev_damage = 0
var/low_threshold_passed
var/high_threshold_passed
var/now_failing
var/now_fixed
var/high_threshold_cleared
var/low_threshold_cleared
/obj/item/organ/proc/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
if(!iscarbon(M) || owner == M)
@@ -33,31 +48,53 @@
for(var/X in actions)
var/datum/action/A = X
A.Grant(M)
STOP_PROCESSING(SSobj, src)
//Special is for instant replacement like autosurgeons
/obj/item/organ/proc/Remove(mob/living/carbon/M, special = 0)
/obj/item/organ/proc/Remove(mob/living/carbon/M, special = FALSE)
owner = null
if(M)
M.internal_organs -= src
if(M.internal_organs_slot[slot] == src)
M.internal_organs_slot.Remove(slot)
if(vital && !special && !(M.status_flags & GODMODE))
if((organ_flags & ORGAN_VITAL) && !special && !(M.status_flags & GODMODE))
M.death()
for(var/X in actions)
var/datum/action/A = X
A.Remove(M)
START_PROCESSING(SSobj, src)
/obj/item/organ/proc/on_find(mob/living/finder)
return
/obj/item/organ/proc/on_life()
return
/obj/item/organ/process()
on_death() //Kinda hate doing it like this, but I really don't want to call process directly.
/obj/item/organ/proc/on_death() //runs decay when outside of a person
if(organ_flags & (ORGAN_SYNTHETIC | ORGAN_FROZEN | ORGAN_NO_SPOIL))
return
applyOrganDamage(maxHealth * decay_factor)
/obj/item/organ/proc/on_life() //repair organ damage if the organ is not failing
if(!(organ_flags & ORGAN_FAILING))
///Damage decrements by a percent of its maxhealth
var/healing_amount = -(maxHealth * healing_factor)
///Damage decrements again by a percent of its maxhealth, up to a total of 4 extra times depending on the owner's health
healing_amount -= owner.satiety > 0 ? 4 * healing_factor * owner.satiety / MAX_SATIETY : 0
applyOrganDamage(healing_amount) //to FERMI_TWEAK
//Make it so each threshold is stuck.
/obj/item/organ/examine(mob/user)
..()
if(status == ORGAN_ROBOTIC && crit_fail)
to_chat(user, "<span class='warning'>[src] seems to be broken!</span>")
. = ..()
if(!organ_flags & ORGAN_FAILING)
if(status == ORGAN_ROBOTIC)
. += "<span class='warning'>[src] seems to be broken!</span>"
return
. += "<span class='warning'>[src] has decayed for too long, and has turned a sickly color! It doesn't look like it will work anymore!</span>"
return
if(damage > high_threshold)
. += "<span class='warning'>[src] is starting to look discolored.</span>"
/obj/item/organ/proc/prepare_eat()
@@ -78,6 +115,10 @@
foodtype = RAW | MEAT | GROSS
/obj/item/organ/Initialize()
. = ..()
START_PROCESSING(SSobj, src)
/obj/item/organ/Destroy()
if(owner)
// The special flag is important, because otherwise mobs can die
@@ -100,13 +141,64 @@
/obj/item/organ/item_action_slot_check(slot,mob/user)
return //so we don't grant the organ's action to mobs who pick up the organ.
///Adjusts an organ's damage by the amount "d", up to a maximum amount, which is by default max damage
/obj/item/organ/proc/applyOrganDamage(var/d, var/maximum = maxHealth) //use for damaging effects
if(!d) //Micro-optimization.
return
if(maximum < damage)
return
damage = CLAMP(damage + d, 0, maximum)
var/mess = check_damage_thresholds(owner)
prev_damage = damage
if(mess && owner)
to_chat(owner, mess)
///SETS an organ's damage to the amount "d", and in doing so clears or sets the failing flag, good for when you have an effect that should fix an organ if broken
/obj/item/organ/proc/setOrganDamage(var/d) //use mostly for admin heals
applyOrganDamage(d - damage)
/** check_damage_thresholds
* input: M (a mob, the owner of the organ we call the proc on)
* output: returns a message should get displayed.
* description: By checking our current damage against our previous damage, we can decide whether we've passed an organ threshold.
* If we have, send the corresponding threshold message to the owner, if such a message exists.
*/
/obj/item/organ/proc/check_damage_thresholds(var/M)
if(damage == prev_damage)
return
var/delta = damage - prev_damage
if(delta > 0)
if(damage >= maxHealth)
organ_flags |= ORGAN_FAILING
return now_failing
if(damage > high_threshold && prev_damage <= high_threshold)
return high_threshold_passed
if(damage > low_threshold && prev_damage <= low_threshold)
return low_threshold_passed
else
organ_flags &= ~ORGAN_FAILING
if(prev_damage > low_threshold && damage <= low_threshold)
return low_threshold_cleared
if(prev_damage > high_threshold && damage <= high_threshold)
return high_threshold_cleared
if(prev_damage == maxHealth)
return now_fixed
//Runs some code on the organ when damage is taken/healed
/obj/item/organ/proc/onDamage(var/d, var/maximum = maxHealth)
return
//Runs some code on the organ when damage is taken/healed
/obj/item/organ/proc/onSetDamage(var/d, var/maximum = maxHealth)
return
//Looking for brains?
//Try code/modules/mob/living/carbon/brain/brain_item.dm
/mob/living/proc/regenerate_organs()
return 0
/mob/living/carbon/regenerate_organs()
/mob/living/carbon/regenerate_organs(only_one = FALSE)
var/breathes = TRUE
var/blooded = TRUE
if(dna && dna.species)
@@ -125,6 +217,8 @@
else
LI = new()
LI.Insert(src)
if(only_one)
return TRUE
if(has_stomach && !getorganslot(ORGAN_SLOT_STOMACH))
var/obj/item/organ/stomach/S
@@ -134,14 +228,20 @@
else
S = new()
S.Insert(src)
if(only_one)
return TRUE
if(breathes && !getorganslot(ORGAN_SLOT_LUNGS))
var/obj/item/organ/lungs/L = new()
L.Insert(src)
if(only_one)
return TRUE
if(blooded && !getorganslot(ORGAN_SLOT_HEART))
var/obj/item/organ/heart/H = new()
H.Insert(src)
if(only_one)
return TRUE
if(!getorganslot(ORGAN_SLOT_TONGUE))
var/obj/item/organ/tongue/T
@@ -153,7 +253,10 @@
// if they have no mutant tongues, give them a regular one
T.Insert(src)
else
if(only_one)
return TRUE
else if (!only_one)
var/obj/item/organ/tongue/oT = getorganslot(ORGAN_SLOT_TONGUE)
if(oT.name == "fluffy tongue")
var/obj/item/organ/tongue/T
@@ -174,6 +277,8 @@
else
E = new()
E.Insert(src)
if(only_one)
return TRUE
if(!getorganslot(ORGAN_SLOT_EARS))
var/obj/item/organ/ears/ears
@@ -183,9 +288,13 @@
ears = new
ears.Insert(src)
if(only_one)
return TRUE
if(!getorganslot(ORGAN_SLOT_TAIL))
var/obj/item/organ/tail/tail
if(dna && dna.species && dna.species.mutanttail)
tail = new dna.species.mutanttail
tail.Insert(src)
if(only_one)
return TRUE
+33 -4
View File
@@ -8,12 +8,41 @@
desc = "Onaka ga suite imasu."
var/disgust_metabolism = 1
/obj/item/organ/stomach/on_life()
var/mob/living/carbon/human/H = owner
healing_factor = STANDARD_ORGAN_HEALING
decay_factor = STANDARD_ORGAN_DECAY
if(istype(H))
H.dna.species.handle_digestion(H)
low_threshold_passed = "<span class='info'>Your stomach flashes with pain before subsiding. Food doesn't seem like a good idea right now.</span>"
high_threshold_passed = "<span class='warning'>Your stomach flares up with constant pain- you can hardly stomach the idea of food right now!</span>"
high_threshold_cleared = "<span class='info'>The pain in your stomach dies down for now, but food still seems unappealing.</span>"
low_threshold_cleared = "<span class='info'>The last bouts of pain in your stomach have died out.</span>"
/obj/item/organ/stomach/on_life()
var/datum/reagent/consumable/nutriment/Nutri
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
if(!(organ_flags & ORGAN_FAILING))
H.dna.species.handle_digestion(H)
handle_disgust(H)
Nutri = locate(/datum/reagent/consumable/nutriment) in H.reagents.reagent_list
if(Nutri)
if(prob((damage/40) * Nutri.volume * Nutri.volume))
H.vomit(damage)
to_chat(H, "<span class='warning'>Your stomach reels in pain as you're incapable of holding down all that food!</span>")
else if(Nutri && damage > high_threshold)
if(prob((damage/10) * Nutri.volume * Nutri.volume))
H.vomit(damage)
to_chat(H, "<span class='warning'>Your stomach reels in pain as you're incapable of holding down all that food!</span>")
else if(iscarbon(owner))
var/mob/living/carbon/C = owner
Nutri = locate(/datum/reagent/consumable/nutriment) in C.reagents.reagent_list
if(damage < low_threshold)
return
/obj/item/organ/stomach/proc/handle_disgust(mob/living/carbon/human/H)
if(H.disgust)
+35 -18
View File
@@ -10,8 +10,7 @@
var/list/languages_possible
var/say_mod = null
var/taste_sensitivity = 15 // lower is more sensitive.
var/maxHealth = TONGUE_MAX_HEALTH
var/damage = 0
maxHealth = TONGUE_MAX_HEALTH
var/modifies_speech = FALSE
var/static/list/languages_possible_base = typecacheof(list(
/datum/language/common,
@@ -31,27 +30,34 @@
/obj/item/organ/tongue/proc/handle_speech(datum/source, list/speech_args)
/obj/item/organ/tongue/proc/adjustTongueLoss(mob/living/carbon/M, damage_mod)
if (maxHealth == "alien")
return
if (maxHealth == "bone")
var/target = M.get_bodypart(BODY_ZONE_HEAD)
M.apply_damage(damage_mod, BURN, target)
to_chat(M, "<span class='userdanger'>The drink burns your skull! Oof, your bones!</span>")
return
if(damage+damage_mod < 0)
damage = 0
/obj/item/organ/tongue/emp_act(severity)
. = ..()
if(. & EMP_PROTECT_SELF)
return
if(organ_flags & ORGAN_SYNTHETIC)
var/errormessage = list("Runtime in tongue.dm, line 39: Undefined operation \"zapzap ow my tongue\"", "afhsjifksahgjkaslfhashfjsak", "-1.#IND", "Graham's number", "inside you all along", "awaiting at least 1 approving review before merging this taste request")
owner.say("The pH is appropriately [pick(errormessage)].")
/obj/item/organ/tongue/applyOrganDamage(var/d, var/maximum = maxHealth)
if(!d) //Micro-optimization.
return
if(maximum < damage)
return
damage = CLAMP(damage + d, 0, maximum)
var/mess = check_damage_thresholds(owner)
prev_damage = damage
if(mess && owner)
to_chat(owner, mess)
damage += damage_mod
if ((damage / maxHealth) > 1)
to_chat(M, "<span class='userdanger'>Your tongue is singed beyond recognition, and disintegrates!</span>")
to_chat(owner, "<span class='userdanger'>Your tongue is singed beyond recognition, and disintegrates!</span>")
SSblackbox.record_feedback("tally", "fermi_chem", 1, "Tongues lost to Fermi")
qdel(src)
else if ((damage / maxHealth) > 0.85)
to_chat(M, "<span class='warning'>Your tongue feels like it's about to fall out!.</span>")
to_chat(owner, "<span class='warning'>Your tongue feels like it's about to fall out!.</span>")
else if ((damage / maxHealth) > 0.5)
to_chat(M, "<span class='notice'>Your tongue is really starting to hurt.</span>")
to_chat(owner, "<span class='notice'>Your tongue is really starting to hurt.</span>")
/obj/item/organ/tongue/Insert(mob/living/carbon/M, special = 0)
@@ -168,7 +174,7 @@
icon_state = "tonguexeno"
say_mod = "hisses"
taste_sensitivity = 10 // LIZARDS ARE ALIENS CONFIRMED
maxHealth = "alien" //Their blood is acid, so, no, though a tongueless xeno might be funny
maxHealth = 500 //They've a little mouth for a tongue, so it's pretty rhobust
modifies_speech = TRUE // not really, they just hiss
var/static/list/languages_possible_alien = typecacheof(list(
/datum/language/xenocommon,
@@ -189,9 +195,10 @@
desc = "Apparently skeletons alter the sounds they produce through oscillation of their teeth, hence their characteristic rattling."
icon_state = "tonguebone"
say_mod = "rattles"
organ_flags = ORGAN_NO_SPOIL
attack_verb = list("bitten", "chattered", "chomped", "enamelled", "boned")
taste_sensitivity = 101 // skeletons cannot taste anything
maxHealth = "bone" //Take brute damage instead
maxHealth = 75 //Take brute damage instead
modifies_speech = TRUE
var/chattering = FALSE
var/phomeme_type = "sans"
@@ -201,6 +208,14 @@
. = ..()
phomeme_type = pick(phomeme_types)
/obj/item/organ/tongue/bone/applyOrganDamage(var/d, var/maximum = maxHealth)
if(!owner)
return
var/target = owner.get_bodypart(BODY_ZONE_HEAD)
owner.apply_damage(d, BURN, target)
to_chat(owner, "<span class='userdanger'>You feel your skull burning! Oof, your bones!</span>")
return
/obj/item/organ/tongue/bone/handle_speech(datum/source, list/speech_args)
if (chattering)
chatter(speech_args[SPEECH_MESSAGE], phomeme_type, source)
@@ -262,6 +277,7 @@
icon_state = "tonguecybernetic"
taste_sensitivity = 10
maxHealth = 60 //It's robotic!
organ_flags = ORGAN_SYNTHETIC
/obj/item/organ/tongue/cybernetic/handle_speech(datum/source, list/speech_args)
speech_args[SPEECH_SPANS] |= SPAN_ROBOT
@@ -271,3 +287,4 @@
say_mod = "beeps"
desc = "A voice synthesizer used by IPCs to smoothly interface with organic lifeforms."
electronics_magic = FALSE
organ_flags = ORGAN_SYNTHETIC
+4 -5
View File
@@ -26,12 +26,14 @@
zone = BODY_ZONE_HEAD
slot = ORGAN_SLOT_ADAMANTINE_RESONATOR
icon_state = "adamantine_resonator"
decay_factor = 0
/obj/item/organ/vocal_cords/adamantine
name = "adamantine vocal cords"
desc = "When adamantine resonates, it causes all nearby pieces of adamantine to resonate as well. Adamantine golems use this to broadcast messages to nearby golems."
actions_types = list(/datum/action/item_action/organ_action/use/adamantine_vocal_cords)
icon_state = "adamantine_cords"
decay_factor = 0
/datum/action/item_action/organ_action/use/adamantine_vocal_cords/Trigger()
if(!IsAvailable())
@@ -62,6 +64,7 @@
var/cooldown_mod = 1
var/base_multiplier = 1
spans = list("colossus","yell")
decay_factor = 0
/datum/action/item_action/organ_action/colossus
name = "Voice of God"
@@ -623,10 +626,6 @@
/datum/action/item_action/organ_action/velvet
name = "Velvet chords"
var/obj/item/organ/vocal_cords/velvet/cords = null
//icon_icon = 'icons/mob/screen_alert.dmi'
//button_icon_state = "velvet_chords"
//icon = 'icons/mob/screen_alert.dmi'
//icon_state = "in_love"
/datum/action/item_action/organ_action/velvet/New()
..()
@@ -991,7 +990,7 @@
if (HAS_TRAIT(H, TRAIT_DEAF))//How the heck you managed to get here I have no idea, but just in case!
speaktrigger += "I can barely hear you! "
//And the brain damage. And the brain damage. And the brain damage. And the brain damage. And the brain damage.
switch(H.getBrainLoss())
switch(H.getOrganLoss(ORGAN_SLOT_BRAIN))
if(20 to 40)
speaktrigger += "I have a mild head ache, "
if(40 to 80)
+2 -2
View File
@@ -75,7 +75,7 @@
H.adjustStaminaLoss(40)
var/head_slot = H.get_item_by_slot(SLOT_HEAD)
if(!head_slot || !(istype(head_slot,/obj/item/clothing/head/helmet) || istype(head_slot,/obj/item/clothing/head/hardhat)))
H.adjustBrainLoss(3)
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3)
H.updatehealth()
visible_message("<span class='danger'>[src] crashes into [A], sending [H] flying!</span>")
playsound(src, 'sound/effects/bang.ogg', 50, 1)
@@ -201,7 +201,7 @@
H.adjustStaminaLoss(10)
var/head_slot = H.get_item_by_slot(SLOT_HEAD)
if(!head_slot || !(istype(head_slot,/obj/item/clothing/head/helmet) || istype(head_slot,/obj/item/clothing/head/hardhat)))
H.adjustBrainLoss(1)
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1)
H.updatehealth()
visible_message("<span class='danger'>[src] crashes into [A], sending [H] flying!</span>")
playsound(src, 'sound/effects/bang.ogg', 50, 1)
+1 -1
View File
@@ -73,5 +73,5 @@
user.adjustFireLoss(-hp_gained, 0)
user.adjustCloneLoss(-hp_gained, 0)
user.updatehealth()
user.adjustBrainLoss(-hp_gained) // Zom Bee gibbers "BRAAAAISNSs!1!"
user.adjustOrganLoss(ORGAN_SLOT_BRAIN, -hp_gained) // Zom Bee gibbers "BRAAAAISNSs!1!"
user.nutrition = min(user.nutrition + hp_gained, NUTRITION_LEVEL_FULL)