diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm index 15a8ed20949..d6ab9543d76 100644 --- a/code/__DEFINES/flags.dm +++ b/code/__DEFINES/flags.dm @@ -68,6 +68,7 @@ #define MUTCOLORS_PARTSONLY 15 //Used if we want the mutant colour to be only used by mutant bodyparts. Don't combine this with MUTCOLORS, or it will be useless. #define NODISMEMBER 16 #define NOHUNGER 17 +#define NOCRITDAMAGE 18 /* These defines are used specifically with the atom/movable/languages bitmask. diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index aba4515d973..163a510dbe8 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -426,3 +426,5 @@ var/global/list/ghost_others_options = list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE // Shuttle return values #define SHUTTLE_ALREADY_DOCKED 7 + +#define CHECK_DNA_AND_SPECIES(C) if((!(C.dna)) || (!(C.dna.species))) return diff --git a/code/game/dna.dm b/code/datums/dna.dm similarity index 100% rename from code/game/dna.dm rename to code/datums/dna.dm diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm index 360311ad9c1..d741a28896e 100644 --- a/code/game/gamemodes/wizard/spellbook.dm +++ b/code/game/gamemodes/wizard/spellbook.dm @@ -370,7 +370,10 @@ /datum/spellbook_entry/item/cursed_heart name = "Cursed Heart" - desc = "A heart that has been revived by dark magicks, the user must concentrate to ensure the heart beats, but every beat heals them. It must beat every 6 seconds." + desc = "A heart that has been revived by dark magicks, the user must \ + concentrate to ensure the heart beats, but every beat heals them. It \ + must beat every 6 seconds. The heart is fickle, and will not work for a \ + lich." item_path = /obj/item/organ/heart/cursed/wizard log_name = "CH" cost = 1 diff --git a/code/modules/awaymissions/mission_code/challenge.dm b/code/modules/awaymissions/mission_code/challenge.dm index 724dcf434e3..2134e7db4cb 100644 --- a/code/modules/awaymissions/mission_code/challenge.dm +++ b/code/modules/awaymissions/mission_code/challenge.dm @@ -32,4 +32,9 @@ state = 2 /obj/machinery/power/emitter/energycannon/RefreshParts() - return \ No newline at end of file + return + +/obj/machinery/power/emitter/energycannon/magical + name = "wabbajack statue" + desc = "Who am I? What is my purpose in life? What do I mean by who am I?" + projectile_type = /obj/item/projectile/magic/change diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 54d8d66f29a..b1718b26f9a 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -33,9 +33,15 @@ set_species(dna.species.type) //initialise organs - internal_organs += new /obj/item/organ/appendix - internal_organs += new /obj/item/organ/lungs - internal_organs += new /obj/item/organ/heart + if(!(NOHUNGER in dna.species.specflags)) + internal_organs += new /obj/item/organ/appendix + + if(!(NOBREATH in dna.species.specflags)) + internal_organs += new /obj/item/organ/lungs + + if(!(NOBLOOD in dna.species.specflags)) + internal_organs += new /obj/item/organ/heart + internal_organs += new /obj/item/organ/brain //Note: Additional organs are generated/replaced on the dna.species level @@ -811,6 +817,8 @@ /mob/living/carbon/human/proc/do_cpr(mob/living/carbon/C) + CHECK_DNA_AND_SPECIES(C) + if(C.stat == DEAD) src << "[C.name] is dead!" return @@ -828,14 +836,27 @@ src << "You fail to perform CPR on [C]!" return 0 - if(C.health <= config.health_threshold_crit) - C.cpr_time = world.time + var/they_breathe = (!(NOBREATH in C.dna.species.specflags)) + var/they_lung = C.getorganslot("lungs") + + if(C.health > config.health_threshold_crit) + return + + src.visible_message("[src] performs CPR on [C.name]!", "You perform CPR on [C.name].") + C.cpr_time = world.time + add_logs(src, C, "CPRed") + + if(they_breathe && they_lung) var/suff = min(C.getOxyLoss(), 7) C.adjustOxyLoss(-suff) C.updatehealth() - src.visible_message("[src] performs CPR on [C.name]!", "You perform CPR on [C.name].") C << "You feel a breath of fresh air enter your lungs... It feels good..." - add_logs(src, C, "CPRed") + else if(they_breathe && !they_lung) + C << "You feel a breath of fresh air... \ + but you don't feel any better..." + else + C << "You feel a breath of fresh air... \ + which is a sensation you don't recognise..." /mob/living/carbon/human/generateStaticOverlay() var/image/staticOverlay = image(icon('icons/effects/effects.dmi', "static"), loc = src) @@ -985,14 +1006,32 @@ hud_used.healthdoll.icon_state = "healthdoll_DEAD" /mob/living/carbon/human/fully_heal(admin_revive = 0) + CHECK_DNA_AND_SPECIES(src) + if(admin_revive) regenerate_limbs() - if(!getorganslot("lungs")) - var/obj/item/organ/lungs/L = new() - L.Insert(src) - if(!getorganslot("tongue")) - var/obj/item/organ/tongue/T = new() - T.Insert(src) + + if(!(NOBREATH in dna.species.specflags) && !getorganslot("lungs")) + var/obj/item/organ/lungs/L = new() + L.Insert(src) + + if(!(NOBLOOD in dna.species.specflags) && !getorganslot("heart")) + var/obj/item/organ/heart/H = new() + H.Insert(src) + + if(!getorganslot("tongue")) + var/obj/item/organ/tongue/T + + for(var/tongue_type in dna.species.mutant_organs) + if(ispath(tongue_type, /obj/item/organ/tongue)) + T = new tongue_type() + T.Insert(src) + + // if they have no mutant tongues, give them a regular one + if(!T) + T = new() + T.Insert(src) + restore_blood() remove_all_embedded_objects() drunkenness = 0 diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 99d99f6b6d6..ad5a44c60b1 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -305,13 +305,25 @@ clear_alert("embeddedobject") /mob/living/carbon/human/proc/handle_heart() - if(!heart_attack) - return - else - if(losebreath < 3) - losebreath += 2 - adjustOxyLoss(5) - adjustBruteLoss(1) + CHECK_DNA_AND_SPECIES(src) + var/needs_heart = (!(NOBLOOD in dna.species.specflags)) + var/we_breath = (!(NOBREATH in dna.species.specflags)) + + if(heart_attack) + if(!needs_heart) + heart_attack = FALSE + else if(we_breath) + if(losebreath < 3) + losebreath += 2 + adjustOxyLoss(5) + adjustBruteLoss(1) + else + // even though we don't require oxygen, our blood still needs + // circulation, and without it, our tissues die and start + // gaining toxins + adjustBruteLoss(3) + if(src.reagents) + src.reagents.add_reagent("toxin", 2) /* Alcohol Poisoning Chart diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm index 047f46481c0..32a5b9c694f 100644 --- a/code/modules/mob/living/carbon/human/say.dm +++ b/code/modules/mob/living/carbon/human/say.dm @@ -48,7 +48,10 @@ return real_name /mob/living/carbon/human/IsVocal() - if(!getorganslot("lungs")) + CHECK_DNA_AND_SPECIES(src) + + // how do species that don't breathe talk? magic, that's what. + if(!(NOBREATH in dna.species.specflags) && !getorganslot("lungs")) return 0 if(mind) return !mind.miming diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index f4c7f3b2886..ce9096b4c34 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -129,6 +129,32 @@ C.regenerate_limbs() //if we don't handle dismemberment, we grow our missing limbs back if(exotic_blood) C.reagents.add_reagent(exotic_blood, 80) + + var/obj/item/organ/heart/heart = C.getorganslot("heart") + var/obj/item/organ/lungs/lungs = C.getorganslot("lungs") + var/obj/item/organ/appendix/appendix = C.getorganslot("appendix") + + if((NOBLOOD in specflags) && heart) + heart.Remove(C) + qdel(heart) + else if((!(NOBLOOD in specflags)) && (!heart)) + heart = new() + heart.Insert(C) + + if((NOBREATH in specflags) && lungs) + lungs.Remove(C) + qdel(lungs) + else if((!(NOBREATH in specflags)) && (!lungs)) + lungs = new() + lungs.Insert(C) + + if((NOHUNGER in specflags) && appendix) + appendix.Remove(C) + qdel(appendix) + else if((!(NOHUNGER in specflags)) && (!appendix)) + appendix = new() + appendix.Insert(C) + for(var/path in mutant_organs) var/obj/item/organ/I = new path() I.Insert(C) @@ -472,7 +498,13 @@ H.apply_overlay(BODY_FRONT_LAYER) /datum/species/proc/spec_life(mob/living/carbon/human/H) - return + if(NOBREATH in specflags) + H.setOxyLoss(0) + H.losebreath = 0 + + var/takes_crit_damage = (!(NOCRITDAMAGE in specflags)) + if((H.health < config.health_threshold_crit) && takes_crit_damage) + H.adjustBruteLoss(1) /datum/species/proc/spec_death(gibbed, mob/living/carbon/human/H) return @@ -885,6 +917,10 @@ ////////////////// /datum/species/proc/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H) + + CHECK_DNA_AND_SPECIES(M) + CHECK_DNA_AND_SPECIES(H) + if(!istype(M)) //sanity check for drones. return if((M != H) && M.a_intent != "help" && H.check_shields(0, M.name, attack_type = UNARMED_ATTACK)) @@ -902,7 +938,17 @@ add_logs(M, H, "shaked") return 1 else - M.do_cpr(H) + var/we_breathe = (!(NOBREATH in M.dna.species.specflags)) + var/we_lung = M.getorganslot("lungs") + + if(we_breathe && we_lung) + M.do_cpr(H) + else if(we_breathe && !we_lung) + M << "You have no lungs to breathe \ + with, so cannot peform CPR." + else + M << "You do not breathe, so \ + cannot perform CPR." if("grab") if(attacker_style && attacker_style.grab_act(M,H)) @@ -1155,7 +1201,8 @@ ///////////// /datum/species/proc/breathe(mob/living/carbon/human/H) - return + if(NOBREATH in specflags) + return TRUE /datum/species/proc/check_breath(datum/gas_mixture/breath, var/mob/living/carbon/human/H) if((H.status_flags & GODMODE)) @@ -1167,16 +1214,13 @@ if(H.reagents.has_reagent("epinephrine") && lungs) return if(H.health >= config.health_threshold_crit) - if(NOBREATH in specflags) - return 1 H.adjustOxyLoss(HUMAN_MAX_OXYLOSS) if(!lungs) H.adjustOxyLoss(1) - H.failed_last_breath = 1 - else + else if(!(NOCRITDAMAGE in specflags)) H.adjustOxyLoss(HUMAN_CRIT_MAX_OXYLOSS) - H.failed_last_breath = 1 + H.failed_last_breath = 1 H.throw_alert("oxy", /obj/screen/alert/oxy) return 0 diff --git a/code/modules/mob/living/carbon/human/species_types.dm b/code/modules/mob/living/carbon/human/species_types.dm index 98ce33f8a64..e0672de9cee 100644 --- a/code/modules/mob/living/carbon/human/species_types.dm +++ b/code/modules/mob/living/carbon/human/species_types.dm @@ -79,6 +79,14 @@ /datum/species/lizard/spec_death(gibbed, mob/living/carbon/human/H) if(H) H.endTailWag() + +/* + Lizard subspecies: ASHWALKERS +*/ +/datum/species/lizard/ashwalker + name = "Ash Walker" + id = "lizard" + specflags = list(MUTCOLORS,EYECOLOR,LIPS,NOBREATH,NOGUNS) /* PODPEOPLE */ diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index 5bfe942374d..966481e1b2d 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -89,14 +89,21 @@ toxpwr = 0 /datum/reagent/toxin/lexorin/on_mob_life(mob/living/M) - M.adjustOxyLoss(5, 0) + . = TRUE + var/mob/living/carbon/C if(iscarbon(M)) - var/mob/living/carbon/C = M - C.losebreath += 2 - if(prob(20)) - M.emote("gasp") + C = M + CHECK_DNA_AND_SPECIES(C) + if(NOBREATH in C.dna.species.specflags) + . = FALSE + + if(.) + M.adjustOxyLoss(5, 0) + if(C) + C.losebreath += 2 + if(prob(20)) + M.emote("gasp") ..() - . = 1 /datum/reagent/toxin/slimejelly name = "Slime Jelly" diff --git a/code/modules/ruins/lavaland_ruin_code.dm b/code/modules/ruins/lavaland_ruin_code.dm index 61a17593f7b..622e3c38a31 100644 --- a/code/modules/ruins/lavaland_ruin_code.dm +++ b/code/modules/ruins/lavaland_ruin_code.dm @@ -223,7 +223,7 @@ name = "ash walker egg" icon = 'icons/mob/lavaland/lavaland_monsters.dmi' icon_state = "large_egg" - mob_species = /datum/species/lizard + mob_species = /datum/species/lizard/ashwalker helmet = /obj/item/clothing/head/helmet/gladiator uniform = /obj/item/clothing/under/gladiator roundstart = FALSE @@ -237,8 +237,6 @@ new_spawn << "Drag corpses to your nest to feed the young, and spawn more Ash Walkers. Bring glory to the tribe!" if(ishuman(new_spawn)) var/mob/living/carbon/human/H = new_spawn - H.dna.species.specflags |= NOBREATH - H.dna.species.specflags |= NOGUNS H.underwear = "Nude" H.update_body() diff --git a/code/modules/spells/spell_types/lichdom.dm b/code/modules/spells/spell_types/lichdom.dm index c7efcd76349..f6a119c428a 100644 --- a/code/modules/spells/spell_types/lichdom.dm +++ b/code/modules/spells/spell_types/lichdom.dm @@ -1,6 +1,11 @@ /obj/effect/proc_holder/spell/targeted/lichdom name = "Bind Soul" - desc = "A dark necromantic pact that can forever bind your soul to an item of your choosing. So long as both your body and the item remain intact and on the same plane you can revive from death, though the time between reincarnations grows steadily with use." + desc = "A dark necromantic pact that can forever bind your soul to an \ + item of your choosing. So long as both your body and the item remain \ + intact and on the same plane you can revive from death, though the time \ + between reincarnations grows steadily with use, along with the weakness \ + that the new skeleton body will experience upon 'birth'. Note that \ + becoming a lich destroys all internal organs except the brain." school = "necromancy" charge_max = 10 clothes_req = 0 diff --git a/code/modules/surgery/bodyparts/bodyparts.dm b/code/modules/surgery/bodyparts/bodyparts.dm index 266add1b1c5..e92340bee3d 100644 --- a/code/modules/surgery/bodyparts/bodyparts.dm +++ b/code/modules/surgery/bodyparts/bodyparts.dm @@ -283,6 +283,10 @@ /obj/item/bodypart/l_arm name = "left arm" + desc = "Did you know that the word 'sinister' stems originally from the \ + Latin 'sinestra' (left hand), because the left hand was supposed to \ + be possessed by the devil? This arm appears to be possessed by no \ + one though." icon_state = "l_arm" max_damage = 50 body_zone ="l_arm" @@ -292,6 +296,8 @@ /obj/item/bodypart/r_arm name = "right arm" + desc = "Over 87% of humans are right handed. That figure is much lower \ + among humans missing their right arm." icon_state = "r_arm" max_damage = 50 body_zone = "r_arm" @@ -301,6 +307,8 @@ /obj/item/bodypart/l_leg name = "left leg" + desc = "Some athletes prefer to tie their left shoelaces first for good \ + luck. In this instance, it probably would not have helped." icon_state = "l_leg" max_damage = 50 body_zone = "l_leg" @@ -310,6 +318,10 @@ /obj/item/bodypart/r_leg name = "right leg" + desc = "You put your right leg in, your right leg out. In, out, in, out, \ + shake it all about. And apparently then it detaches.\n\ + The hokey pokey has certainly changed a lot since space colonisation." + // alternative spellings of 'pokey' are availible icon_state = "r_leg" max_damage = 50 body_zone = "r_leg" @@ -322,15 +334,9 @@ /obj/item/severedtail name = "tail" - desc = "A severed tail." + desc = "A severed tail. Somewhere, no doubt, a lizard hater is very \ + pleased with themselves." icon = 'icons/obj/surgery.dmi' icon_state = "severedtail" color = "#161" var/markings = "Smooth" - - - - - - - diff --git a/tgstation.dme b/tgstation.dme index d47f1928a1a..427b6b81017 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -156,6 +156,7 @@ #include "code\datums\browser.dm" #include "code\datums\datacore.dm" #include "code\datums\datumvars.dm" +#include "code\datums\dna.dm" #include "code\datums\dog_fashion.dm" #include "code\datums\hud.dm" #include "code\datums\martial.dm" @@ -251,7 +252,6 @@ #include "code\game\atoms_movable.dm" #include "code\game\communications.dm" #include "code\game\data_huds.dm" -#include "code\game\dna.dm" #include "code\game\say.dm" #include "code\game\shuttle_engines.dm" #include "code\game\skincmd.dm"