From d71573e7499742b8b3317581d218efecb5dbde80 Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Fri, 18 Dec 2015 18:23:58 +1030 Subject: [PATCH] Further work on properly integrating, updating and fixing prosthetic options. WIP Allowed heads/bodies to be prosthetic. Removed IPC. Refactored some flags. --- code/ZAS/Phoron.dm | 10 +- code/__defines/chemistry.dm | 1 - code/__defines/species_languages.dm | 6 +- code/_helpers/mobs.dm | 26 +- code/datums/datacore.dm | 6 +- code/datums/disease.dm | 2 +- .../datums/diseases/advance/symptoms/vomit.dm | 33 +-- code/datums/diseases/appendicitis.dm | 10 +- code/game/atoms.dm | 2 +- code/game/dna/dna2_helpers.dm | 9 +- .../gamemodes/changeling/powers/absorb.dm | 4 +- .../gamemodes/changeling/powers/revive.dm | 2 +- code/game/gamemodes/cult/runes.dm | 4 +- code/game/jobs/job/silicon.dm | 2 +- code/game/machinery/adv_med.dm | 4 +- code/game/machinery/bioprinter.dm | 4 +- code/game/machinery/cloning.dm | 2 +- code/game/machinery/computer/cloning.dm | 6 +- code/game/machinery/doors/airlock.dm | 2 +- code/game/machinery/iv_drip.dm | 4 +- code/game/machinery/suit_storage_unit.dm | 6 +- .../objects/effects/decals/Cleanable/misc.dm | 8 +- code/game/objects/items.dm | 2 +- .../objects/items/weapons/material/shards.dm | 8 +- code/game/objects/items/weapons/tools.dm | 11 +- code/game/objects/structures/morgue.dm | 2 +- code/modules/admin/admin_verbs.dm | 7 +- .../preference_setup/general/01_basic.dm | 2 +- .../preference_setup/general/03_body.dm | 79 +++++- code/modules/client/preferences.dm | 10 +- .../clothing/under/accessories/accessory.dm | 8 +- code/modules/mob/language/station.dm | 10 +- code/modules/mob/living/carbon/brain/MMI.dm | 2 +- .../mob/living/carbon/brain/brain_item.dm | 21 +- code/modules/mob/living/carbon/breathe.dm | 2 +- code/modules/mob/living/carbon/carbon.dm | 8 + .../mob/living/carbon/carbon_powers.dm | 24 +- .../mob/living/carbon/human/appearance.dm | 34 ++- code/modules/mob/living/carbon/human/death.dm | 4 +- code/modules/mob/living/carbon/human/emote.dm | 2 +- .../mob/living/carbon/human/examine.dm | 31 ++- code/modules/mob/living/carbon/human/human.dm | 90 +++---- .../mob/living/carbon/human/human_damage.dm | 54 ++-- .../mob/living/carbon/human/human_defense.dm | 4 +- .../mob/living/carbon/human/human_defines.dm | 1 + .../mob/living/carbon/human/human_movement.dm | 4 +- .../mob/living/carbon/human/human_organs.dm | 7 +- .../mob/living/carbon/human/inventory.dm | 1 - code/modules/mob/living/carbon/human/life.dm | 97 ++++--- .../carbon/human/species/outsider/shadow.dm | 2 +- .../carbon/human/species/outsider/vox.dm | 16 +- .../living/carbon/human/species/species.dm | 21 +- .../carbon/human/species/station/golem.dm | 2 +- .../carbon/human/species/station/monkey.dm | 16 +- .../carbon/human/species/station/slime.dm | 2 +- .../carbon/human/species/station/station.dm | 100 ++----- .../human/species/xenomorphs/alien_species.dm | 18 +- .../mob/living/carbon/human/unarmed_attack.dm | 13 +- .../mob/living/carbon/human/update_icons.dm | 4 +- .../mob/living/carbon/metroid/powers.dm | 2 +- code/modules/mob/living/carbon/shock.dm | 2 +- code/modules/mob/living/living.dm | 48 ++++ code/modules/mob/living/living_defines.dm | 1 + .../mob/living/silicon/robot/drone/drone.dm | 2 +- .../modules/mob/living/silicon/robot/robot.dm | 8 +- .../simple_animal/borer/borer_powers.dm | 2 +- code/modules/mob/mob_defines.dm | 1 - code/modules/mob/mob_grab_specials.dm | 2 +- .../mob/new_player/preferences_setup.dm | 73 ++++-- code/modules/mob/transform_procs.dm | 4 +- code/modules/organs/blood.dm | 18 +- code/modules/organs/misc.dm | 13 +- code/modules/organs/organ.dm | 78 +++--- code/modules/organs/organ_external.dm | 246 ++++++++++++------ code/modules/organs/organ_icon.dm | 8 +- code/modules/organs/organ_internal.dm | 9 +- code/modules/organs/pain.dm | 20 +- code/modules/organs/robolimbs.dm | 1 - code/modules/organs/subtypes/diona.dm | 16 -- code/modules/organs/subtypes/machine.dm | 145 +++-------- code/modules/power/cable.dm | 12 +- code/modules/projectiles/projectile/change.dm | 6 +- .../Chemistry-Reagents-Core.dm | 6 +- .../Chemistry-Reagents-Dispenser.dm | 2 +- .../Chemistry-Reagents-Food-Drinks.dm | 9 +- .../Chemistry-Reagents-Medicine.dm | 2 +- .../Chemistry-Reagents-Toxins.dm | 5 + .../reagents/reagent_containers/syringes.dm | 2 +- code/modules/surgery/bones.dm | 1 - code/modules/surgery/generic.dm | 7 +- code/modules/surgery/organs_internal.dm | 6 +- code/modules/surgery/robotics.dm | 8 +- code/modules/virus2/admin.dm | 2 +- code/modules/virus2/disease2.dm | 4 +- code/modules/virus2/helpers.dm | 2 +- code/modules/virus2/items_devices.dm | 2 +- icons/mob/human_races/cyberlimbs/bishop.dmi | Bin 950 -> 1442 bytes .../human_races/cyberlimbs/hesphaistos.dmi | Bin 935 -> 1431 bytes icons/mob/human_races/cyberlimbs/ipc.dmi | Bin 1716 -> 1717 bytes icons/mob/human_races/cyberlimbs/xion.dmi | Bin 901 -> 1397 bytes icons/mob/human_races/cyberlimbs/zenghu.dmi | Bin 849 -> 1362 bytes icons/mob/human_races/r_machine.dmi | Bin 2120 -> 0 bytes 102 files changed, 925 insertions(+), 722 deletions(-) delete mode 100644 icons/mob/human_races/r_machine.dmi diff --git a/code/ZAS/Phoron.dm b/code/ZAS/Phoron.dm index ff03f947e1..cffa28a1fc 100644 --- a/code/ZAS/Phoron.dm +++ b/code/ZAS/Phoron.dm @@ -116,10 +116,6 @@ obj/var/contaminated = 0 /mob/living/carbon/human/proc/burn_eyes() - //The proc that handles eye burning. - if(!species.has_organ["eyes"]) - return - var/obj/item/organ/eyes/E = internal_organs_by_name["eyes"] if(E) if(prob(20)) src << "Your eyes burn!" @@ -143,15 +139,15 @@ obj/var/contaminated = 0 //Checks if the suit is adequately sealed. var/coverage = 0 for(var/obj/item/protection in list(wear_suit, gloves, shoes)) - if(!protection) + if(!protection) continue if(vsc.plc.PHORONGUARD_ONLY && !(protection.flags & PHORONGUARD)) return 0 coverage |= protection.body_parts_covered - + if(vsc.plc.PHORONGUARD_ONLY) return 1 - + return BIT_TEST_ALL(coverage, UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS) /mob/living/carbon/human/proc/suit_contamination() diff --git a/code/__defines/chemistry.dm b/code/__defines/chemistry.dm index 31bdcc9469..3c1be97566 100644 --- a/code/__defines/chemistry.dm +++ b/code/__defines/chemistry.dm @@ -23,7 +23,6 @@ #define IS_UNATHI 4 #define IS_TAJARA 5 #define IS_XENOS 6 -#define IS_MACHINE 7 #define CE_STABLE "stable" // Inaprovaline #define CE_ANTIBIOTIC "antibiotic" // Spaceacilin diff --git a/code/__defines/species_languages.dm b/code/__defines/species_languages.dm index e204cdb977..9dc9ecd0fd 100644 --- a/code/__defines/species_languages.dm +++ b/code/__defines/species_languages.dm @@ -1,12 +1,10 @@ // Species flags. -#define NO_BLOOD 0x1 // Vessel var is not filled with blood, cannot bleed out. -#define NO_BREATHE 0x2 // Cannot suffocate or take oxygen loss. +#define NO_MINOR_CUT 0x1 // Can step on broken glass with no ill-effects. Either thick skin (diona/vox), cut resistant (slimes) or incorporeal (shadows) +#define IS_PLANT 0x2 // Is a treeperson. #define NO_SCAN 0x4 // Cannot be scanned in a DNA machine/genome-stolen. #define NO_PAIN 0x8 // Cannot suffer halloss/recieves deceptive health indicator. #define NO_SLIP 0x10 // Cannot fall over. #define NO_POISON 0x20 // Cannot not suffer toxloss. -#define IS_PLANT 0x40 // Is a treeperson. -#define NO_MINOR_CUT 0x80 // Can step on broken glass with no ill-effects. Either thick skin (diona/vox), cut resistant (slimes) or incorporeal (shadows) // unused: 0x8000 - higher than this will overflow // Species spawn flags diff --git a/code/_helpers/mobs.dm b/code/_helpers/mobs.dm index 6e2a7fae36..96b50fc6c5 100644 --- a/code/_helpers/mobs.dm +++ b/code/_helpers/mobs.dm @@ -29,10 +29,13 @@ proc/random_hair_style(gender, species = "Human") var/list/valid_hairstyles = list() for(var/hairstyle in hair_styles_list) var/datum/sprite_accessory/S = hair_styles_list[hairstyle] - if(gender == MALE && S.gender == FEMALE) - continue - if(gender == FEMALE && S.gender == MALE) - continue + + if(gender != NEUTER) + if(gender == MALE && S.gender == FEMALE) + continue + if(gender == FEMALE && S.gender == MALE) + continue + if( !(species in S.species_allowed)) continue valid_hairstyles[hairstyle] = hair_styles_list[hairstyle] @@ -48,10 +51,13 @@ proc/random_facial_hair_style(gender, species = "Human") var/list/valid_facialhairstyles = list() for(var/facialhairstyle in facial_hair_styles_list) var/datum/sprite_accessory/S = facial_hair_styles_list[facialhairstyle] - if(gender == MALE && S.gender == FEMALE) - continue - if(gender == FEMALE && S.gender == MALE) - continue + + if(gender != NEUTER) + if(gender == MALE && S.gender == FEMALE) + continue + if(gender == FEMALE && S.gender == MALE) + continue + if( !(species in S.species_allowed)) continue @@ -61,12 +67,12 @@ proc/random_facial_hair_style(gender, species = "Human") f_style = pick(valid_facialhairstyles) return f_style - + proc/sanitize_name(name, species = "Human") var/datum/species/current_species if(species) current_species = all_species[species] - + return current_species ? current_species.sanitize_name(name) : sanitizeName(name) proc/random_name(gender, species = "Human") diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index 5c86505da7..f748fdd53e 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -222,6 +222,7 @@ locked += L return +// TODO. proc/get_id_photo(var/mob/living/carbon/human/H, var/assigned_role) var/icon/preview_icon = null @@ -258,7 +259,10 @@ proc/get_id_photo(var/mob/living/carbon/human/H, var/assigned_role) if(!H.species || H.species.flags & HAS_SKIN_COLOR) preview_icon.Blend(rgb(H.r_skin, H.g_skin, H.b_skin), ICON_ADD) - var/icon/eyes_s = new/icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = H.species ? H.species.eyes : "eyes_s") + var/use_eye_icon = "eyes_s" + var/obj/item/organ/external/head/temp_head = H.get_organ("head") + if(temp_head) use_eye_icon = temp_head.eye_icon + var/icon/eyes_s = new/icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = use_eye_icon) if (H.species.flags & HAS_EYE_COLOR) eyes_s.Blend(rgb(H.r_eyes, H.g_eyes, H.b_eyes), ICON_ADD) diff --git a/code/datums/disease.dm b/code/datums/disease.dm index 606acdef99..453cd0d8bd 100644 --- a/code/datums/disease.dm +++ b/code/datums/disease.dm @@ -57,7 +57,7 @@ var/list/diseases = typesof(/datum/disease) - /datum/disease // Some species are immune to viruses entirely. if(affected_mob && istype(affected_mob, /mob/living/carbon/human)) var/mob/living/carbon/human/H = affected_mob - if(H.species.virus_immune) + if(H.species.get_virus_immune(H)) cure() return age++ diff --git a/code/datums/diseases/advance/symptoms/vomit.dm b/code/datums/diseases/advance/symptoms/vomit.dm index 1f62065ef9..ecfd2deb81 100644 --- a/code/datums/diseases/advance/symptoms/vomit.dm +++ b/code/datums/diseases/advance/symptoms/vomit.dm @@ -27,29 +27,15 @@ Bonus stage_speed = 0 transmittable = 1 level = 3 + var/bloodvomit /datum/symptom/vomit/Activate(var/datum/disease/advance/A) ..() if(prob(SYMPTOM_ACTIVATION_PROB / 2)) var/mob/living/M = A.affected_mob - switch(A.stage) - if(1, 2, 3, 4) - M << "[pick("You feel nauseous.", "You feel like you're going to throw up!")]" - else - Vomit(M) - + spawn M.vomit(M, bloodvomit) return -/datum/symptom/vomit/proc/Vomit(var/mob/living/M) - - M.visible_message("[M] vomits on the floor!") - - M.nutrition -= 20 - M.adjustToxLoss(-3) - - var/turf/pos = get_turf(M) - pos.add_vomit_floor(M) - playsound(pos, 'sound/effects/splat.ogg', 50, 1) /* ////////////////////////////////////// @@ -78,17 +64,4 @@ Bonus stage_speed = -1 transmittable = 1 level = 4 - -/datum/symptom/vomit/blood/Vomit(var/mob/living/M) - - M.Stun(1) - M.visible_message("[M] vomits on the floor!") - - // They lose blood and health. - var/brute_dam = M.getBruteLoss() - if(brute_dam < 50) - M.adjustBruteLoss(3) - - var/turf/simulated/pos = get_turf(M) - pos.add_blood_floor(M) - playsound(pos, 'sound/effects/splat.ogg', 50, 1) \ No newline at end of file + bloodvomit = 1 diff --git a/code/datums/diseases/appendicitis.dm b/code/datums/diseases/appendicitis.dm index b4f2b1a38a..d6f05d33ef 100644 --- a/code/datums/diseases/appendicitis.dm +++ b/code/datums/diseases/appendicitis.dm @@ -33,13 +33,9 @@ affected_mob.adjustToxLoss(1) if(stage > 2) if(prob(1)) - if (affected_mob.nutrition > 100) - var/mob/living/carbon/human/H = affected_mob - H.vomit() - else - affected_mob << "You gag as you want to throw up, but there's nothing in your stomach!" - affected_mob.Weaken(10) - affected_mob.adjustToxLoss(3) + var/mob/living/carbon/human/H = affected_mob + spawn H.vomit() + if(stage > 3) if(prob(1) && ishuman(affected_mob)) var/mob/living/carbon/human/H = affected_mob diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 1a9d246215..f219e1d6c7 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -400,7 +400,7 @@ its easier to just keep the beam vertical. M.dna.real_name = M.real_name M.check_dna() if (M.species) - blood_color = M.species.blood_color + blood_color = M.species.get_blood_colour(M) . = 1 return 1 diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm index ce6320cd88..98acc1d335 100644 --- a/code/game/dna/dna2_helpers.dm +++ b/code/game/dna/dna2_helpers.dm @@ -150,10 +150,11 @@ H.s_tone = 35 - dna.GetUIValueRange(DNA_UI_SKIN_TONE, 220) // Value can be negative. - if (dna.GetUIState(DNA_UI_GENDER)) - H.gender = FEMALE - else - H.gender = MALE + if(H.gender != NEUTER) + if (dna.GetUIState(DNA_UI_GENDER)) + H.gender = FEMALE + else + H.gender = MALE //Hair var/hair = dna.GetUIValueRange(DNA_UI_HAIR_STYLE,hair_styles_list.len) diff --git a/code/game/gamemodes/changeling/powers/absorb.dm b/code/game/gamemodes/changeling/powers/absorb.dm index 7d5a42e7e8..0c13276f12 100644 --- a/code/game/gamemodes/changeling/powers/absorb.dm +++ b/code/game/gamemodes/changeling/powers/absorb.dm @@ -19,8 +19,8 @@ return var/mob/living/carbon/human/T = G.affecting - if(!istype(T)) - src << "[T] is not compatible with our biology." + if(!istype(T) || T.isSynthetic()) + src << "\The [T] is not compatible with our biology." return if(T.species.flags & NO_SCAN) diff --git a/code/game/gamemodes/changeling/powers/revive.dm b/code/game/gamemodes/changeling/powers/revive.dm index 465088a06a..f67df60f2a 100644 --- a/code/game/gamemodes/changeling/powers/revive.dm +++ b/code/game/gamemodes/changeling/powers/revive.dm @@ -23,7 +23,7 @@ C.radiation = 0 C.heal_overall_damage(C.getBruteLoss(), C.getFireLoss()) C.reagents.clear_reagents() - C.restore_all_organs() //Covers things like fractures and other things not covered by the above. + C.restore_all_organs(ignore_prosthetic_prefs=1) //Covers things like fractures and other things not covered by the above. if(ishuman(C)) var/mob/living/carbon/human/H = src H.restore_blood() diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index aafcd791e5..760a2d4833 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -162,8 +162,8 @@ var/list/sacrificed = list() target.adjustBrainLoss(rand(1,5)) initial_message = 1 - if (target.species && (target.species.flags & NO_PAIN)) - target.visible_message("The markings below [target] glow a bloody red.") + if (!target.can_feel_pain()) + target.visible_message("The markings below \the [target] glow a bloody red.") else target.visible_message("[target] writhes in pain as the markings below \him glow a bloody red.", "AAAAAAHHHH!", "You hear an anguished scream.") diff --git a/code/game/jobs/job/silicon.dm b/code/game/jobs/job/silicon.dm index 6cec7149e9..b64508499c 100644 --- a/code/game/jobs/job/silicon.dm +++ b/code/game/jobs/job/silicon.dm @@ -40,7 +40,7 @@ supervisors = "your laws and the AI" //Nodrak selection_color = "#ddffdd" minimal_player_age = 1 - alt_titles = list("Android", "Robot") + alt_titles = list("Robot", "Drone") account_allowed = 0 economic_modifier = 0 diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index af922271d9..64393c2bc4 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -399,9 +399,9 @@ for(var/obj/item/organ/i in occ["internal_organs"]) var/mech = "" - if(i.robotic == 1) + if(i.status & ORGAN_ASSISTED) mech = "Assisted:" - if(i.robotic == 2) + if(i.status & ORGAN_ROBOT) mech = "Mechanical:" var/infection = "None" diff --git a/code/game/machinery/bioprinter.dm b/code/game/machinery/bioprinter.dm index 23d00318ea..0bb7dd1935 100644 --- a/code/game/machinery/bioprinter.dm +++ b/code/game/machinery/bioprinter.dm @@ -41,7 +41,7 @@ var/obj/item/organ/O = new new_organ(get_turf(src)) if(prints_prosthetics) - O.robotic = 2 + O.robotize() else if(loaded_dna) visible_message("The printer injects the stored DNA into the biomass..") O.transplant_data = list() @@ -80,5 +80,5 @@ user << "\The [src] processes \the [W]. Levels of stored matter now: [stored_matter]" qdel(W) return - + return..() \ No newline at end of file diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index a2b2b63325..d3c152fa25 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -16,7 +16,7 @@ //They need a brain! if(istype(M, /mob/living/carbon/human)) var/mob/living/carbon/human/H = M - if(H.species.has_organ["brain"] && !H.has_brain()) + if(!H.has_brain()) continue if(M.ckey == find_key) selected = M diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index 857832d2f5..83b6f2ce86 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -353,11 +353,15 @@ if (!subject.has_brain()) if(istype(subject, /mob/living/carbon/human)) var/mob/living/carbon/human/H = subject - if(H.species.has_organ["brain"]) + if(H.should_have_organ("brain")) scantemp = "Error: No signs of intelligence detected." else scantemp = "Error: No signs of intelligence detected." return + + if(subject.isSynthetic()) + scantemp = "Error: Subject is not organic." + return if (subject.suiciding == 1) scantemp = "Error: Subject's brain is not responding to scanning stimuli." return diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index d32c7e45ee..c2758a7ffd 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -943,7 +943,7 @@ About the new airlock wires panel: /mob/living/carbon/airlock_crush(var/crush_damage) . = ..() - if (!(species && (species.flags & NO_PAIN))) + if(can_feel_pain()) emote("scream") /mob/living/silicon/robot/airlock_crush(var/crush_damage) diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm index c1b160c94b..0fec7a9c1b 100644 --- a/code/game/machinery/iv_drip.dm +++ b/code/game/machinery/iv_drip.dm @@ -106,7 +106,7 @@ if(NOCLONE in T.mutations) return - if(T.species.flags & NO_BLOOD) + if(!T.should_have_organ("heart")) return // If the human is losing too much blood, beep. @@ -165,4 +165,4 @@ /obj/machinery/iv_drip/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) if(height && istype(mover) && mover.checkpass(PASSTABLE)) //allow bullets, beams, thrown objects, mice, drones, and the like through. return 1 - return ..() + return ..() diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index 703760ddf0..d3fe17a068 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -333,16 +333,14 @@ OCCUPANT.apply_effect(50, IRRADIATE) var/obj/item/organ/diona/nutrients/rad_organ = locate() in OCCUPANT.internal_organs if (!rad_organ) + if (OCCUPANT.can_feel_pain()) + OCCUPANT.emote("scream") if(src.issuperUV) var/burndamage = rand(28,35) OCCUPANT.take_organ_damage(0,burndamage) - if (!(OCCUPANT.species && (OCCUPANT.species.flags & NO_PAIN))) - OCCUPANT.emote("scream") else var/burndamage = rand(6,10) OCCUPANT.take_organ_damage(0,burndamage) - if (!(OCCUPANT.species && (OCCUPANT.species.flags & NO_PAIN))) - OCCUPANT.emote("scream") if(i==3) //End of the cycle if(!src.issuperUV) if(src.HELMET) diff --git a/code/game/objects/effects/decals/Cleanable/misc.dm b/code/game/objects/effects/decals/Cleanable/misc.dm index c70a5ab9fc..250e8f350e 100644 --- a/code/game/objects/effects/decals/Cleanable/misc.dm +++ b/code/game/objects/effects/decals/Cleanable/misc.dm @@ -102,10 +102,10 @@ random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4") var/list/viruses = list() - Destroy() - for(var/datum/disease/D in viruses) - D.cure(0) - ..() +/obj/effect/decal/cleanable/vomit/Destroy() + for(var/datum/disease/D in viruses) + D.cure(0) + return ..() /obj/effect/decal/cleanable/tomato_smudge name = "tomato smudge" diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 25320136b9..eeed37b9e7 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -465,7 +465,7 @@ var/list/global/slot_flags_enumeration = list( eyes.damage += rand(3,4) if(eyes.damage >= eyes.min_bruised_damage) if(M.stat != 2) - if(eyes.robotic <= 1) //robot eyes bleeding might be a bit silly + if(!(eyes.status & ORGAN_ROBOT)) //robot eyes bleeding might be a bit silly M << "Your eyes start to bleed profusely!" if(prob(50)) if(M.stat != 2) diff --git a/code/game/objects/items/weapons/material/shards.dm b/code/game/objects/items/weapons/material/shards.dm index 65bb1d4ebc..bb4b80c1b8 100644 --- a/code/game/objects/items/weapons/material/shards.dm +++ b/code/game/objects/items/weapons/material/shards.dm @@ -64,10 +64,10 @@ ..() if(isliving(AM)) var/mob/M = AM - + if(M.buckled) //wheelchairs, office chairs, rollerbeds return - + M << "You step on \the [src]!" playsound(src.loc, 'sound/effects/glass_step.ogg', 50, 1) // not sure how to handle metal shards with sounds if(ishuman(M)) @@ -78,7 +78,7 @@ if( H.shoes || ( H.wear_suit && (H.wear_suit.body_parts_covered & FEET) ) ) return - + var/list/check = list("l_foot", "r_foot") while(check.len) var/picked = pick(check) @@ -89,7 +89,7 @@ if(affecting.take_damage(5, 0)) H.UpdateDamageIcon() H.updatehealth() - if(!(H.species.flags & NO_PAIN)) + if(affecting.can_feel_pain()) H.Weaken(3) return check -= picked diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm index 282e7bece6..0e1f0dadc3 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -422,14 +422,18 @@ icon_state = "red_crowbar" item_state = "crowbar_red" +/obj/item/weapon/weldingtool/attack(var/atom/A, var/mob/living/user, var/def_zone) + if(ishuman(A) && user.a_intent == I_HELP) + return + return ..() + /obj/item/weapon/weldingtool/afterattack(var/mob/M, var/mob/user) if(ishuman(M)) var/mob/living/carbon/human/H = M var/obj/item/organ/external/S = H.organs_by_name[user.zone_sel.selecting] - if (!S) return - if(!(S.status & ORGAN_ROBOT) || user.a_intent != I_HELP) + if(!S || !(S.status & ORGAN_ROBOT) || user.a_intent != I_HELP) return ..() if(S.brute_dam) @@ -438,10 +442,9 @@ user.visible_message("\The [user] patches some dents on \the [M]'s [S.name] with \the [src].") else if(S.open != 2) user << "The damage is far too severe to patch over externally." - return 1 else if(S.open != 2) user << "Nothing to fix!" - + return else return ..() diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 9f8eed2eb5..949cbc1ff6 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -324,7 +324,7 @@ M.emote("scream") else var/mob/living/carbon/C = M - if (!(C.species && (C.species.flags & NO_PAIN))) + if (C.can_feel_pain()) C.emote("scream") //Logging for this causes runtimes resulting in the cremator locking up. Commenting it out until that's figured out. diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index e959c1991b..19302f8d30 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -880,12 +880,15 @@ var/list/admin_verbs_mentor = list( if(new_fstyle) M.f_style = new_fstyle - var/new_gender = alert(usr, "Please select gender.", "Character Generation", "Male", "Female") + var/new_gender = alert(usr, "Please select gender.", "Character Generation", "Male", "Female", "Neuter") if (new_gender) if(new_gender == "Male") M.gender = MALE - else + else if (new_gender == "Female") M.gender = FEMALE + else + M.gender = NEUTER + M.update_hair() M.update_body() M.check_dna(M) diff --git a/code/modules/client/preference_setup/general/01_basic.dm b/code/modules/client/preference_setup/general/01_basic.dm index 440cf90e59..0f993b0fca 100644 --- a/code/modules/client/preference_setup/general/01_basic.dm +++ b/code/modules/client/preference_setup/general/01_basic.dm @@ -1,7 +1,7 @@ /datum/category_item/player_setup_item/general/basic name = "Basic" sort_order = 1 - var/list/valid_player_genders = list(MALE, FEMALE) + var/list/valid_player_genders = list(MALE, FEMALE, NEUTER, PLURAL) /datum/category_item/player_setup_item/general/basic/load_character(var/savefile/S) S["real_name"] >> pref.real_name diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm index 07530881fe..720a3d3c07 100644 --- a/code/modules/client/preference_setup/general/03_body.dm +++ b/code/modules/client/preference_setup/general/03_body.dm @@ -75,8 +75,8 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O /datum/category_item/player_setup_item/general/body/content(var/mob/user) pref.update_preview_icon() if(pref.preview_icon_front && pref.preview_icon_side) - user << browse_rsc(pref.preview_icon_front, "previewicon.png") - user << browse_rsc(pref.preview_icon_side, "previewicon2.png") + user << browse_rsc(pref.preview_icon_front, "preview_icon.png") + user << browse_rsc(pref.preview_icon_side, "preview_icon2.png") var/mob_species = all_species[pref.species] . += "
Body " @@ -87,7 +87,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O if(has_flag(mob_species, HAS_SKIN_TONE)) . += "Skin Tone: [-pref.s_tone + 35]/220
" . += "Needs Glasses: [pref.disabilities & NEARSIGHTED ? "Yes" : "No"]
" - . += "Limbs: Adjust
" + . += "Limbs: Adjust Reset
" . += "Internal Organs: Adjust
" //display limbs below @@ -96,6 +96,13 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O var/status = pref.organ_data[name] var/organ_name = null switch(name) + + if("torso") + organ_name = "torso" + if("groin") + organ_name = "groin" + if("head") + organ_name = "head" if("l_arm") organ_name = "left arm" if("r_arm") @@ -116,6 +123,8 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O organ_name = "heart" if("eyes") organ_name = "eyes" + if("brain") + organ_name = "brain" if(status == "cyborg") ++ind @@ -136,7 +145,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O ++ind if(ind > 1) . += ", " - . += "\tMechanical [organ_name]" + . += "\tSynthetic [organ_name]" else if(status == "assisted") ++ind if(ind > 1) @@ -148,6 +157,8 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O . += "\tSurgically altered [organ_name]" if("eyes") . += "\tRetinal overlayed [organ_name]" + if("brain") + . += "\tAssisted-interface [organ_name]" else . += "\tMechanically assisted [organ_name]" if(!ind) @@ -155,7 +166,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O else . += "

" - . += "
Preview
" + . += "
Preview
" . += "
" . += "Hair
" @@ -252,6 +263,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O pref.b_hair = 0//hex2num(copytext(new_hair, 6, 8)) pref.s_tone = 0 + reset_limbs() // Safety for species with incompatible manufacturers; easier than trying to do it case by case. return TOPIC_REFRESH else if(href_list["hair_color"]) @@ -334,8 +346,12 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O pref.f_style = new_f_style return TOPIC_REFRESH + else if(href_list["reset_limbs"]) + reset_limbs() + return TOPIC_REFRESH + else if(href_list["limbs"]) - var/limb_name = input(user, "Which limb do you want to change?") as null|anything in list("Left Leg","Right Leg","Left Arm","Right Arm","Left Foot","Right Foot","Left Hand","Right Hand") + var/limb_name = input(user, "Which limb do you want to change?") as null|anything in list("Left Leg","Right Leg","Left Arm","Right Arm","Left Foot","Right Foot","Left Hand","Right Hand","Full Body") if(!limb_name && !CanUseTopic(user)) return TOPIC_NOACTION var/limb = null @@ -366,6 +382,9 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O if("Right Hand") limb = "r_hand" third_limb = "r_arm" + if("Full Body") + limb = "torso" + var/new_state = input(user, "What state do you wish the limb to be in?") as null|anything in list("Normal","Amputated","Prothesis") if(!new_state && !CanUseTopic(user)) return TOPIC_NOACTION @@ -378,6 +397,10 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O pref.organ_data[third_limb] = null pref.rlimb_data[third_limb] = null if("Amputated") + + if(limb == "torso") + return + pref.organ_data[limb] = "amputated" pref.rlimb_data[limb] = null if(second_limb) @@ -397,17 +420,31 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O var/choice = input(user, "Which manufacturer do you wish to use for this limb?") as null|anything in usable_manufacturers if(!choice) return + pref.rlimb_data[limb] = choice pref.organ_data[limb] = "cyborg" + if(second_limb) pref.rlimb_data[second_limb] = choice pref.organ_data[second_limb] = "cyborg" if(third_limb && pref.organ_data[third_limb] == "amputated") pref.organ_data[third_limb] = null + + if(limb == "torso") + for(var/other_limb in list("l_foot","r_foot","l_hand","r_hand","l_leg","r_leg","l_arm","r_arm","groin","head")) + if(pref.organ_data[other_limb]) + continue + pref.organ_data[other_limb] = "cyborg" + pref.rlimb_data[other_limb] = choice + if(!pref.organ_data["brain"]) + pref.organ_data["brain"] = "assisted" + for(var/internal_organ in list("heart","eyes")) + pref.organ_data[internal_organ] = "mechanical" + return TOPIC_REFRESH else if(href_list["organs"]) - var/organ_name = input(user, "Which internal function do you want to change?") as null|anything in list("Heart", "Eyes") + var/organ_name = input(user, "Which internal function do you want to change?") as null|anything in list("Heart", "Eyes", "Brain") if(!organ_name) return var/organ = null @@ -416,12 +453,20 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O organ = "heart" if("Eyes") organ = "eyes" + if("Brain") + if(pref.organ_data["head"] != "cyborg") + user << "You may only select an assisted or synthetic brain if you have a full prosthetic body." + return + organ = "brain" var/new_state = input(user, "What state do you wish the organ to be in?") as null|anything in list("Normal","Assisted","Mechanical") if(!new_state) return switch(new_state) if("Normal") + if(pref.organ_data["torso"] == "cyborg") + user << "A character with a synthetic body may only use synthetic organs." + return pref.organ_data[organ] = null if("Assisted") pref.organ_data[organ] = "assisted" @@ -436,6 +481,18 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O return ..() +/datum/category_item/player_setup_item/general/body/proc/reset_limbs() + + for(var/organ in pref.organ_data) + pref.organ_data[organ] = null + while(null in pref.organ_data) + pref.organ_data -= null + + for(var/organ in pref.rlimb_data) + pref.rlimb_data[organ] = null + while(null in pref.rlimb_data) + pref.rlimb_data -= null + /datum/category_item/player_setup_item/general/body/proc/SetSpecies(mob/user) if(!pref.species_preview || !(pref.species_preview in all_species)) pref.species_preview = "Human" @@ -455,10 +512,10 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O dat += "
Often present on human stations." if(current_species.spawn_flags & IS_WHITELISTED) dat += "
Whitelist restricted." - if(current_species.flags & NO_BLOOD) - dat += "
Does not have blood." - if(current_species.flags & NO_BREATHE) - dat += "
Does not breathe." + if(!current_species.has_organ["heart"]) + dat += "
Does not have a circulatory system." + if(!current_species.has_organ["lungs"]) + dat += "
Does not have a respiratory system." if(current_species.flags & NO_SCAN) dat += "
Does not have DNA." if(current_species.flags & NO_PAIN) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 6bc9b88845..b4060b221f 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -310,6 +310,8 @@ datum/preferences var/status = organ_data[name] var/obj/item/organ/external/O = character.organs_by_name[name] + if(name == "torso" && !O) + O = character.organs_by_name["chest"] if(O) O.status = 0 if(status == "amputated") @@ -334,20 +336,14 @@ datum/preferences I.robotize() character.underwear = underwear - character.undershirt = undershirt - character.socks = socks if(backbag > 4 || backbag < 1) backbag = 1 //Same as above character.backbag = backbag - //Debugging report to track down a bug, which randomly assigned the plural gender to people. - if(character.gender in list(PLURAL, NEUTER)) - if(isliving(src)) //Ghosts get neuter by default - message_admins("[character] ([character.ckey]) has spawned with their gender as plural or neuter. Please notify coders.") - character.gender = MALE + character.update_body() /datum/preferences/proc/open_load_dialog(mob/user) var/dat = "" diff --git a/code/modules/clothing/under/accessories/accessory.dm b/code/modules/clothing/under/accessories/accessory.dm index 5610a23f63..f57b9c9be2 100644 --- a/code/modules/clothing/under/accessories/accessory.dm +++ b/code/modules/clothing/under/accessories/accessory.dm @@ -99,10 +99,9 @@ var/sound = "heartbeat" var/sound_strength = "cannot hear" var/heartbeat = 0 - if(M.species && M.species.has_organ["heart"]) - var/obj/item/organ/heart/heart = M.internal_organs_by_name["heart"] - if(heart && !heart.robotic) - heartbeat = 1 + var/obj/item/organ/heart/heart = M.internal_organs_by_name["heart"] + if(heart && !(heart.status & ORGAN_ROBOT)) + heartbeat = 1 if(M.stat == DEAD || (M.status_flags&FAKEDEATH)) sound_strength = "cannot hear" sound = "anything" @@ -112,7 +111,6 @@ sound_strength = "hear" sound = "no heartbeat" if(heartbeat) - var/obj/item/organ/heart/heart = M.internal_organs_by_name["heart"] if(heart.is_bruised() || M.getOxyLoss() > 50) sound = "[pick("odd noises in","weak")] heartbeat" else diff --git a/code/modules/mob/language/station.dm b/code/modules/mob/language/station.dm index cc477f0ee7..d237f36b09 100644 --- a/code/modules/mob/language/station.dm +++ b/code/modules/mob/language/station.dm @@ -96,13 +96,13 @@ /datum/language/machine name = "Encoded Audio Language" - desc = "A language of encoded tones that allow for IPCs to communicate auditorily between each other in a manner that allows for easier transfer of information." - speech_verb = "beeps" - ask_verb = "beeps" - exclaim_verb = "loudly beeps" + desc = "A efficient language of encoded tones developed by synthetics and cyborgs." + speech_verb = "whistles" + ask_verb = "chirps" + exclaim_verb = "whistles loudly" colour = "changeling" key = "6" - flags = RESTRICTED | NO_STUTTER + flags = NO_STUTTER syllables = list("beep","beep","beep","beep","beep","boop","boop","boop","bop","bop","dee","dee","doo","doo","hiss","hss","buzz","buzz","bzz","ksssh","keey","wurr","wahh","tzzz") space_chance = 10 diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm index 07004f9754..03de410f5e 100644 --- a/code/modules/mob/living/carbon/brain/MMI.dm +++ b/code/modules/mob/living/carbon/brain/MMI.dm @@ -60,7 +60,7 @@ brainobj = O brainobj.loc = src - name = "Man-Machine Interface: [brainmob.real_name]" + name = "man-machine interface ([brainmob.real_name])" icon_state = "mmi_full" locked = 1 diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm index 543c3d339f..fc1e7778ad 100644 --- a/code/modules/mob/living/carbon/brain/brain_item.dm +++ b/code/modules/mob/living/carbon/brain/brain_item.dm @@ -15,6 +15,25 @@ attack_verb = list("attacked", "slapped", "whacked") var/mob/living/carbon/brain/brainmob = null + +/obj/item/organ/brain/robotize() + replace_self_with(/obj/item/organ/mmi_holder/posibrain) + +/obj/item/organ/brain/mechassist() + replace_self_with(/obj/item/organ/mmi_holder) + +/obj/item/organ/brain/proc/replace_self_with(replace_path) + if(!owner) + new replace_path(src.loc) + qdel(src) + return + owner.internal_organs_by_name[organ_tag] = new replace_path(owner, 1) + owner.internal_organs -= src + while(null in owner.internal_organs_by_name) + owner.internal_organs_by_name -= null + while(null in owner.internal_organs) + owner.internal_organs -= null + /obj/item/organ/pariah_brain name = "brain remnants" desc = "Did someone tread on this? It looks useless for cloning or cyborgification." @@ -93,13 +112,11 @@ /obj/item/organ/brain/slime name = "slime core" desc = "A complex, organic knot of jelly and crystalline particles." - robotic = 2 icon = 'icons/mob/slimes.dmi' icon_state = "green slime extract" /obj/item/organ/brain/golem name = "chem" desc = "A tightly furled roll of paper, covered with indecipherable runes." - robotic = 2 icon = 'icons/obj/wizard.dmi' icon_state = "scroll" diff --git a/code/modules/mob/living/carbon/breathe.dm b/code/modules/mob/living/carbon/breathe.dm index 20f86d4dde..fa87736f26 100644 --- a/code/modules/mob/living/carbon/breathe.dm +++ b/code/modules/mob/living/carbon/breathe.dm @@ -7,7 +7,7 @@ /mob/living/carbon/proc/breathe() //if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell)) return - if(species && (species.flags & NO_BREATHE) || does_not_breathe) return + if(!should_have_organ("lungs") || does_not_breathe) return var/datum/gas_mixture/breath = null diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index fd6fd0f658..f0b09f88d6 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -472,3 +472,11 @@ if(!species) return null return species.default_language ? all_languages[species.default_language] : null + +/mob/living/carbon/proc/should_have_organ(var/organ_check) + return 0 + +/mob/living/carbon/proc/can_feel_pain(var/check_organ) + if(isSynthetic()) + return 0 + return !(species.flags & NO_PAIN) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/carbon_powers.dm b/code/modules/mob/living/carbon/carbon_powers.dm index 65fcbc7b17..f1360504ef 100644 --- a/code/modules/mob/living/carbon/carbon_powers.dm +++ b/code/modules/mob/living/carbon/carbon_powers.dm @@ -8,7 +8,7 @@ var/mob/living/simple_animal/borer/B = has_brain_worms() if(B && B.host_brain) - src << "\red You withdraw your probosci, releasing control of [B.host_brain]" + src << "You withdraw your probosci, releasing control of [B.host_brain]" B.detatch() @@ -17,7 +17,7 @@ verbs -= /mob/living/carbon/proc/spawn_larvae else - src << "\red ERROR NO BORER OR BRAINMOB DETECTED IN THIS MOB, THIS IS A BUG !" + src << "ERROR NO BORER OR BRAINMOB DETECTED IN THIS MOB, THIS IS A BUG !" //Brain slug proc for tormenting the host. /mob/living/carbon/proc/punish_host() @@ -31,13 +31,12 @@ return if(B.host_brain.ckey) - src << "\red You send a punishing spike of psychic agony lancing into your host's brain." - - if (species && (species.flags & NO_PAIN)) - B.host_brain << "\red You feel a strange sensation as a foreign influence prods your mind." - src << "\red It doesn't seem to be as effective as you hoped." + src << "You send a punishing spike of psychic agony lancing into your host's brain." + if (!can_feel_pain()) + B.host_brain << "You feel a strange sensation as a foreign influence prods your mind." + src << "It doesn't seem to be as effective as you hoped." else - B.host_brain << "\red Horrific, burning agony lances through you, ripping a soundless scream from your trapped mind!" + B.host_brain << "Horrific, burning agony lances through you, ripping a soundless scream from your trapped mind!" /mob/living/carbon/proc/spawn_larvae() set category = "Abilities" @@ -50,15 +49,14 @@ return if(B.chemicals >= 100) - src << "\red Your host twitches and quivers as you rapidly excrete a larva from your sluglike body." - visible_message("\red [src] heaves violently, expelling a rush of vomit and a wriggling, sluglike creature!") + src << "Your host twitches and quivers as you rapidly excrete a larva from your sluglike body." + visible_message("\The [src] heaves violently, expelling a rush of vomit and a wriggling, sluglike creature!") B.chemicals -= 100 B.has_reproduced = 1 - new /obj/effect/decal/cleanable/vomit(get_turf(src)) - playsound(loc, 'sound/effects/splat.ogg', 50, 1) + vomit(1) new /mob/living/simple_animal/borer(get_turf(src)) else - src << "You do not have enough chemicals stored to reproduce." + src << "You do not have enough chemicals stored to reproduce." return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index 5f9d7e827c..cf404df6ff 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -157,30 +157,44 @@ return valid_species /mob/living/carbon/human/proc/generate_valid_hairstyles(var/check_gender = 1) + + var/use_species = species.get_bodytype() + var/obj/item/organ/external/head/H = get_organ("head") + if(H) use_species = H.species.get_bodytype() + var/list/valid_hairstyles = new() for(var/hairstyle in hair_styles_list) var/datum/sprite_accessory/S = hair_styles_list[hairstyle] - if(check_gender && gender == MALE && S.gender == FEMALE) - continue - if(check_gender && gender == FEMALE && S.gender == MALE) - continue - if(!(species.get_bodytype() in S.species_allowed)) + if(check_gender && gender != NEUTER) + if(gender == MALE && S.gender == FEMALE) + continue + else if(gender == FEMALE && S.gender == MALE) + continue + + if(!(use_species in S.species_allowed)) continue valid_hairstyles += hairstyle return valid_hairstyles /mob/living/carbon/human/proc/generate_valid_facial_hairstyles() + + var/use_species = species.get_bodytype() + var/obj/item/organ/external/head/H = get_organ("head") + if(H) use_species = H.species.get_bodytype() + var/list/valid_facial_hairstyles = new() for(var/facialhairstyle in facial_hair_styles_list) var/datum/sprite_accessory/S = facial_hair_styles_list[facialhairstyle] - if(gender == MALE && S.gender == FEMALE) - continue - if(gender == FEMALE && S.gender == MALE) - continue - if(!(species.get_bodytype() in S.species_allowed)) + if(gender != NEUTER) + if(gender == MALE && S.gender == FEMALE) + continue + else if(gender == FEMALE && S.gender == MALE) + continue + + if(!(use_species in S.species_allowed)) continue valid_facial_hairstyles += facialhairstyle diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index ff7255523d..a01a8f4ee8 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -15,7 +15,7 @@ I.throw_at(get_edge_target_turf(src,pick(alldirs)), rand(1,3), round(30/I.w_class)) ..(species.gibbed_anim) - gibs(loc, viruses, dna, null, species.flesh_color, species.blood_color) + gibs(loc, viruses, dna, null, species.get_flesh_colour(src), species.get_blood_colour(src)) /mob/living/carbon/human/dust() if(species) @@ -68,7 +68,7 @@ if(wearing_rig) wearing_rig.notify_ai("Warning: user death event. Mobility control passed to integrated intelligence system.") - return ..(gibbed,species.death_message) + return ..(gibbed,species.get_death_message(src)) /mob/living/carbon/human/proc/ChangeToHusk() if(HUSK in mutations) return diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index c1abe448f3..6509943754 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -207,7 +207,7 @@ m_type = 2 if ("deathgasp") - message = "[species.death_message]" + message = "[species.get_death_message()]" m_type = 1 if ("giggle") diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 07619bff1f..650a72014e 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -38,9 +38,21 @@ CRASH("Gender datum was null; key was '[(skipjumpsuit && skipface) ? PLURAL : gender]'") msg += "[src.name]" - if(species.name != "Human") - msg += ", a [species.name]" - msg += "!\n" + + + var/is_synth = isSynthetic() + if(is_synth) + var/use_gender = "a synthetic" + if(gender == MALE) + use_gender = "an android" + else if(gender == FEMALE) + use_gender = "a gynoid" + + msg += ", [use_gender]!" + + else if(species.name != "Human") + msg += ", \a [species.name]!" + msg += "
" //uniform if(w_uniform && !skipjumpsuit) @@ -230,11 +242,12 @@ if(getBrainLoss() >= 60) msg += "[T.He] [T.has] a stupid expression on [T.his] face.\n" - if(species.show_ssd && (!species.has_organ["brain"] || has_brain()) && stat != DEAD) + var/ssd_msg = species.get_ssd(src) + if(ssd_msg && (!should_have_organ("brain") || has_brain()) && stat != DEAD) if(!key) - msg += "[T.He] [T.is] [species.show_ssd]. It doesn't look like [T.he] [T.is] waking up anytime soon.\n" + msg += "[T.He] [T.is] [ssd_msg]. It doesn't look like [T.he] [T.is] waking up anytime soon.\n" else if(!client) - msg += "[T.He] [T.is] [species.show_ssd].\n" + msg += "[T.He] [T.is] [ssd_msg].\n" var/list/wound_flavor_text = list() var/list/is_destroyed = list() @@ -261,12 +274,12 @@ is_destroyed["[temp.name]"] = 1 wound_flavor_text["[temp.name]"] = "[T.He] [T.is] missing [T.his] [temp.name].\n" continue - if(temp.status & ORGAN_ROBOT) + if(!is_synth && temp.status & ORGAN_ROBOT) if(!(temp.brute_dam + temp.burn_dam)) - wound_flavor_text["[temp.name]"] = "[T.He] [T.has] a robot [temp.name]!\n" + wound_flavor_text["[temp.name]"] = "[T.He] [T.has] a [temp.name]!\n" continue else - wound_flavor_text["[temp.name]"] = "[T.He] [T.has] a robot [temp.name]. It has[temp.get_wounds_desc()]!\n" + wound_flavor_text["[temp.name]"] = "[T.He] [T.has] a [temp.name]. It has[temp.get_wounds_desc()]!\n" else if(temp.wounds.len > 0 || temp.open) if(temp.is_stump() && temp.parent_organ && organs_by_name[temp.parent_organ]) var/obj/item/organ/external/parent = organs_by_name[temp.parent_organ] diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index eef1b95245..68662204a3 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -654,18 +654,12 @@ ///eyecheck() ///Returns a number between -1 to 2 /mob/living/carbon/human/eyecheck() + + var/obj/item/organ/I = internal_organs_by_name["eyes"] + if(!I || I.status & (ORGAN_CUT_AWAY|ORGAN_DESTROYED)) + return 2 + var/number = 0 - - if(!species.has_organ["eyes"]) //No eyes, can't hurt them. - return 2 - - if(internal_organs_by_name["eyes"]) // Eyes are fucked, not a 'weak point'. - var/obj/item/organ/I = internal_organs_by_name["eyes"] - if(I.status & ORGAN_CUT_AWAY) - return 2 - else - return 2 - if(istype(src.head, /obj/item/clothing/head/welding)) if(!src.head:up) number += 2 @@ -690,8 +684,6 @@ //Used by various things that knock people out by applying blunt trauma to the head. //Checks that the species has a "head" (brain containing organ) and that hit_zone refers to it. /mob/living/carbon/human/proc/headcheck(var/target_zone, var/brain_tag = "brain") - if(!species.has_organ[brain_tag]) - return 0 var/obj/item/organ/affecting = internal_organs_by_name[brain_tag] @@ -745,38 +737,16 @@ xylophone=0 return -/mob/living/carbon/human/proc/check_has_mouth() +/mob/living/proc/check_has_mouth() + return 1 + +/mob/living/carbon/human/check_has_mouth() // Todo, check stomach organ when implemented. var/obj/item/organ/external/head/H = get_organ("head") if(!H || !H.can_intake_reagents) return 0 return 1 -/mob/living/carbon/human/proc/vomit() - - if(!check_has_mouth()) - return - - if(!lastpuke) - lastpuke = 1 - src << "You feel nauseous..." - spawn(150) //15 seconds until second warning - src << "You feel like you are about to throw up!" - spawn(100) //and you have 10 more for mad dash to the bucket - Stun(5) - - src.visible_message("[src] throws up!","You throw up!") - playsound(loc, 'sound/effects/splat.ogg', 50, 1) - - var/turf/location = loc - if (istype(location, /turf/simulated)) - location.add_vomit_floor(src, 1) - - nutrition -= 40 - adjustToxLoss(-3) - spawn(350) //wait 35 seconds before next volley - lastpuke = 0 - /mob/living/carbon/human/proc/morph() set name = "Morph" set category = "Superpower" @@ -846,12 +816,14 @@ if(new_style) f_style = new_style - var/new_gender = alert(usr, "Please select gender.", "Character Generation", "Male", "Female") + var/new_gender = alert(usr, "Please select gender.", "Character Generation", "Male", "Female", "Neutral") if (new_gender) if(new_gender == "Male") gender = MALE - else + else if(new_gender == "Female") gender = FEMALE + else + gender = NEUTER regenerate_icons() check_dna() @@ -936,13 +908,12 @@ /mob/living/carbon/human/revive() - if(species && !(species.flags & NO_BLOOD)) + if(should_have_organ("heart")) vessel.add_reagent("blood",560-vessel.total_volume) fixblood() - // Fix up all organs. - // This will ignore any prosthetics in the prefs currently. - species.create_organs(src) + species.create_organs(src) // Reset our organs/limbs. + restore_all_organs() // Reapply robotics/amputated status from preferences. if(!client || !key) //Don't boot out anyone already in the mob. for (var/obj/item/organ/brain/H in world) @@ -1057,7 +1028,7 @@ for(var/obj/item/O in organ.implants) if(!istype(O,/obj/item/weapon/implant) && prob(5)) //Moving with things stuck in you could be bad. // All kinds of embedded objects cause bleeding. - if(species.flags & NO_PAIN) + if(!can_feel_pain(organ.limb_name)) src << "You feel [O] moving inside your [organ.name]." else var/msg = pick( \ @@ -1067,7 +1038,7 @@ src << msg organ.take_damage(rand(1,3), 0, 0) - if(!(organ.status & ORGAN_ROBOT) && !(species.flags & NO_BLOOD)) //There is no blood in protheses. + if(!(organ.status & ORGAN_ROBOT) && !should_have_organ("heart")) //There is no blood in protheses. organ.status |= ORGAN_BLEEDING src.adjustToxLoss(rand(1,3)) @@ -1302,11 +1273,15 @@ /mob/living/carbon/human/getDNA() if(species.flags & NO_SCAN) return null + if(isSynthetic()) + return ..() /mob/living/carbon/human/setDNA() if(species.flags & NO_SCAN) return + if(isSynthetic()) + return ..() /mob/living/carbon/human/has_brain() @@ -1423,3 +1398,24 @@ pulling_punches = !pulling_punches src << "You are now [pulling_punches ? "pulling your punches" : "not pulling your punches"]." return + +/mob/living/carbon/human/should_have_organ(var/organ_check) + + var/obj/item/organ/external/affecting + if(organ_check in list("heart","lungs")) + affecting = organs_by_name["chest"] + else if(organ_check in list("liver","kidneys")) + affecting = organs_by_name["groin"] + + if(affecting && (affecting.status & ORGAN_ROBOT)) + return 0 + return (species && species.has_organ[organ_check]) + +/mob/living/carbon/human/can_feel_pain(var/obj/item/organ/check_organ) + if(isSynthetic()) + return 0 + if(check_organ) + if(!istype(check_organ)) + return 0 + return check_organ.can_feel_pain() + return !(species.flags & NO_PAIN) diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index 377581d09b..517bc79a41 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -13,7 +13,7 @@ total_brute += O.brute_dam total_burn += O.burn_dam - var/oxy_l = ((species.flags & NO_BREATHE) ? 0 : getOxyLoss()) + var/oxy_l = getOxyLoss() var/tox_l = ((species.flags & NO_POISON) ? 0 : getToxLoss()) var/clone_l = getCloneLoss() @@ -28,7 +28,7 @@ if(status_flags & GODMODE) return 0 //godmode - if(species && species.has_organ["brain"]) + if(should_have_organ("brain")) var/obj/item/organ/brain/sponge = internal_organs_by_name["brain"] if(sponge) sponge.take_damage(amount) @@ -42,7 +42,7 @@ if(status_flags & GODMODE) return 0 //godmode - if(species && species.has_organ["brain"]) + if(should_have_organ("brain")) var/obj/item/organ/brain/sponge = internal_organs_by_name["brain"] if(sponge) sponge.damage = min(max(amount, 0),(maxHealth*2)) @@ -56,7 +56,7 @@ if(status_flags & GODMODE) return 0 //godmode - if(species && species.has_organ["brain"]) + if(should_have_organ("brain")) var/obj/item/organ/brain/sponge = internal_organs_by_name["brain"] if(sponge) brainloss = min(sponge.damage,maxHealth*2) @@ -142,12 +142,12 @@ ..() /mob/living/carbon/human/getCloneLoss() - if(species.flags & (NO_SCAN)) + if((species.flags & NO_SCAN) || isSynthetic()) cloneloss = 0 return ..() /mob/living/carbon/human/setCloneLoss(var/amount) - if(species.flags & (NO_SCAN)) + if((species.flags & NO_SCAN) || isSynthetic()) cloneloss = 0 else ..() @@ -155,7 +155,7 @@ /mob/living/carbon/human/adjustCloneLoss(var/amount) ..() - if(species.flags & (NO_SCAN)) + if((species.flags & NO_SCAN) || isSynthetic()) cloneloss = 0 return @@ -189,37 +189,37 @@ // Defined here solely to take species flags into account without having to recast at mob/living level. /mob/living/carbon/human/getOxyLoss() - if(species.flags & NO_BREATHE) + if(!should_have_organ("lungs")) oxyloss = 0 return ..() /mob/living/carbon/human/adjustOxyLoss(var/amount) - if(species.flags & NO_BREATHE) + if(!should_have_organ("lungs")) oxyloss = 0 else amount = amount*species.oxy_mod ..(amount) /mob/living/carbon/human/setOxyLoss(var/amount) - if(species.flags & NO_BREATHE) + if(!should_have_organ("lungs")) oxyloss = 0 else ..() /mob/living/carbon/human/getToxLoss() - if(species.flags & NO_POISON) + if((species.flags & NO_POISON) || isSynthetic()) toxloss = 0 return ..() /mob/living/carbon/human/adjustToxLoss(var/amount) - if(species.flags & NO_POISON) + if((species.flags & NO_POISON) || isSynthetic()) toxloss = 0 else amount = amount*species.toxins_mod ..(amount) /mob/living/carbon/human/setToxLoss(var/amount) - if(species.flags & NO_POISON) + if((species.flags & NO_POISON) || isSynthetic()) toxloss = 0 else ..() @@ -321,7 +321,7 @@ In most cases it makes more sense to use apply_damage() instead! And make sure t This function restores the subjects blood to max. */ /mob/living/carbon/human/proc/restore_blood() - if(!(species.flags & NO_BLOOD)) + if(should_have_organ("heart")) var/blood_volume = vessel.get_reagent_amount("blood") vessel.add_reagent("blood",560.0-blood_volume) @@ -329,9 +329,9 @@ This function restores the subjects blood to max. /* This function restores all organs. */ -/mob/living/carbon/human/restore_all_organs() +/mob/living/carbon/human/restore_all_organs(var/ignore_prosthetic_prefs) for(var/obj/item/organ/external/current_organ in organs) - current_organ.rejuvenate() + current_organ.rejuvenate(ignore_prosthetic_prefs) /mob/living/carbon/human/proc/HealDamage(zone, brute, burn) var/obj/item/organ/external/E = get_organ(zone) @@ -354,14 +354,19 @@ This function restores all organs. if(Debug2) world.log << "## DEBUG: human/apply_damage() was called on [src], with [damage] damage, and an armor value of [blocked]." - //visible_message("Hit debug. [damage] | [damagetype] | [def_zone] | [blocked] | [sharp] | [used_weapon]") + var/obj/item/organ/external/organ = null + if(isorgan(def_zone)) + organ = def_zone + else + if(!def_zone) def_zone = ran_zone(def_zone) + organ = get_organ(check_zone(def_zone)) //Handle other types of damage if((damagetype != BRUTE) && (damagetype != BURN)) - if(damagetype == HALLOSS && !(species && (species.flags & NO_PAIN))) - if ((damage > 25 && prob(20)) || (damage > 50 && prob(60))) - emote("scream") - + if(damagetype == HALLOSS) + if((damage > 25 && prob(20)) || (damage > 50 && prob(60))) + if(organ && organ.can_feel_pain()) + emote("scream") ..(damage, damagetype, def_zone, blocked) return 1 @@ -371,12 +376,7 @@ This function restores all organs. if(blocked >= 100) return 0 - var/obj/item/organ/external/organ = null - if(isorgan(def_zone)) - organ = def_zone - else - if(!def_zone) def_zone = ran_zone(def_zone) - organ = get_organ(check_zone(def_zone)) + if(!organ) return 0 if(blocked) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index e34a4de79e..b516852074 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -61,7 +61,7 @@ emp_act emote("me", 1, "drops what they were holding, their [affected.name] malfunctioning!") else var/emote_scream = pick("screams in pain and ", "lets out a sharp cry and ", "cries out and ") - emote("me", 1, "[(species && species.flags & NO_PAIN) ? "" : emote_scream ]drops what they were holding in their [affected.name]!") + emote("me", 1, "[affected.can_feel_pain() ? "" : emote_scream]drops what they were holding in their [affected.name]!") ..(stun_amount, agony_amount, def_zone) @@ -223,7 +223,7 @@ emp_act //Harder to score a stun but if you do it lasts a bit longer if(prob(effective_force)) apply_effect(20, PARALYZE, armor) - visible_message("[src] [species.knockout_message]") + visible_message("[src] [species.get_knockout_message(src)]") else //Easier to score a stun but lasts less time if(prob(effective_force + 10)) diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 7ed171a1f1..f116ae17f0 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -83,6 +83,7 @@ var/list/flavor_texts = list() var/gunshot_residue var/pulling_punches // Are you trying not to hurt your opponent? + var/full_prosthetic // We are a robutt. mob_bump_flag = HUMAN mob_push_flags = ~HEAVY diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index ca81defe0f..c8011cb059 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -16,7 +16,7 @@ var/health_deficiency = (100 - health) if(health_deficiency >= 40) tally += (health_deficiency / 25) - if (!(species && (species.flags & NO_PAIN))) + if(can_feel_pain()) if(halloss >= 10) tally += (halloss / 10) //halloss shouldn't slow you down if you can't even feel it var/hungry = (500 - nutrition)/5 // So overeat would be 100 and default level would be 80 @@ -42,7 +42,7 @@ var/obj/item/organ/external/E = get_organ(organ_name) if(!E || (E.status & ORGAN_DESTROYED)) tally += 4 - if(E.status & ORGAN_SPLINTED) + else if(E.status & ORGAN_SPLINTED) tally += 0.5 else if(E.status & ORGAN_BROKEN) tally += 1.5 diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm index d69f6e57cc..cab9b5a1c2 100644 --- a/code/modules/mob/living/carbon/human/human_organs.dm +++ b/code/modules/mob/living/carbon/human/human_organs.dm @@ -68,6 +68,7 @@ if (istype(buckled, /obj/structure/bed)) return + var/limb_pain for(var/limb_tag in list("l_leg","r_leg","l_foot","r_foot")) var/obj/item/organ/external/E = organs_by_name[limb_tag] if(!E || (E.status & (ORGAN_DESTROYED|ORGAN_DEAD))) @@ -88,6 +89,8 @@ else if (E.is_dislocated()) stance_damage += 0.5 + if(E) limb_pain = E.can_feel_pain() + // Canes and crutches help you stand (if the latter is ever added) // One cane mitigates a broken leg+foot, or a missing foot. // Two canes are needed for a lost leg. If you are missing both legs, canes aren't gonna help you. @@ -99,7 +102,7 @@ // standing is poor if(stance_damage >= 4 || (stance_damage >= 2 && prob(5))) if(!(lying || resting)) - if(species && !(species.flags & NO_PAIN)) + if(limb_pain) emote("scream") custom_emote(1, "collapses!") Weaken(5) //can't emote while weakened, apparently. @@ -145,7 +148,7 @@ drop_from_inventory(r_hand) var/emote_scream = pick("screams in pain and ", "lets out a sharp cry and ", "cries out and ") - emote("me", 1, "[(species.flags & NO_PAIN) ? "" : emote_scream ]drops what they were holding in their [E.name]!") + emote("me", 1, "[(E.can_feel_pain()) ? "" : emote_scream ]drops what they were holding in their [E.name]!") else if(E.is_malfunctioning()) switch(E.body_part) diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index ae66cf3fe0..c3d0568b80 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -40,7 +40,6 @@ This saves us from having to call add_fingerprint() any time something is put in /mob/living/carbon/human/proc/has_organ(name) var/obj/item/organ/external/O = organs_by_name[name] - return (O && !(O.status & ORGAN_DESTROYED) && !O.is_stump()) /mob/living/carbon/human/proc/has_organ_for_slot(slot) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 97327c4bbd..8e77023fe7 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -254,6 +254,12 @@ radiation = Clamp(radiation,0,100) if (radiation) + + // TODO. + if(isSynthetic()) + radiation = 0 + return + var/obj/item/organ/diona/nutrients/rad_organ = locate() in internal_organs if(rad_organ && !rad_organ.is_broken()) var/rads = radiation/25 @@ -365,7 +371,7 @@ var/safe_pressure_min = 16 // Minimum safe partial pressure of breathable gas in kPa // Lung damage increases the minimum safe pressure. - if(species.has_organ["lungs"]) + if(should_have_organ("lungs")) var/obj/item/organ/lungs/L = internal_organs_by_name["lungs"] if(isnull(L)) safe_pressure_min = INFINITY //No lungs, how are you breathing? @@ -831,6 +837,7 @@ return min(1,thermal_protection) /mob/living/carbon/human/handle_chemicals_in_body() + if(in_stasis) return @@ -838,43 +845,48 @@ chem_effects.Cut() analgesic = 0 - if(touching) touching.metabolize() - if(ingested) ingested.metabolize() - if(bloodstr) bloodstr.metabolize() + if(!isSynthetic()) - if(CE_PAINKILLER in chem_effects) - analgesic = chem_effects[CE_PAINKILLER] + if(touching) touching.metabolize() + if(ingested) ingested.metabolize() + if(bloodstr) bloodstr.metabolize() - var/total_phoronloss = 0 - for(var/obj/item/I in src) - if(I.contaminated) - total_phoronloss += vsc.plc.CONTAMINATION_LOSS - if(!(status_flags & GODMODE)) adjustToxLoss(total_phoronloss) + if(CE_PAINKILLER in chem_effects) + analgesic = chem_effects[CE_PAINKILLER] + + var/total_phoronloss = 0 + for(var/obj/item/I in src) + if(I.contaminated) + total_phoronloss += vsc.plc.CONTAMINATION_LOSS + if(!(status_flags & GODMODE)) adjustToxLoss(total_phoronloss) if(status_flags & GODMODE) return 0 //godmode var/obj/item/organ/diona/node/light_organ = locate() in internal_organs - if(light_organ && !light_organ.is_broken()) - var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing - if(isturf(loc)) //else, there's considered to be no light - var/turf/T = loc - var/atom/movable/lighting_overlay/L = locate(/atom/movable/lighting_overlay) in T - if(L) - light_amount = min(10,L.lum_r + L.lum_g + L.lum_b) - 5 //hardcapped so it's not abused by having a ton of flashlights - else - light_amount = 5 - nutrition += light_amount - traumatic_shock -= light_amount - if(species.flags & IS_PLANT) - if(nutrition > 450) - nutrition = 450 - if(light_amount >= 3) //if there's enough light, heal - adjustBruteLoss(-(round(light_amount/2))) - adjustFireLoss(-(round(light_amount/2))) - adjustToxLoss(-(light_amount)) - adjustOxyLoss(-(light_amount)) - //TODO: heal wounds, heal broken limbs. + if(!isSynthetic()) + if(light_organ && !light_organ.is_broken()) + var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing + if(isturf(loc)) //else, there's considered to be no light + var/turf/T = loc + var/atom/movable/lighting_overlay/L = locate(/atom/movable/lighting_overlay) in T + if(L) + light_amount = min(10,L.lum_r + L.lum_g + L.lum_b) - 5 //hardcapped so it's not abused by having a ton of flashlights + else + light_amount = 5 + nutrition += light_amount + traumatic_shock -= light_amount + + if(species.flags & IS_PLANT) + if(nutrition > 450) + nutrition = 450 + + if(light_amount >= 3) //if there's enough light, heal + adjustBruteLoss(-(round(light_amount/2))) + adjustFireLoss(-(round(light_amount/2))) + adjustToxLoss(-(light_amount)) + adjustOxyLoss(-(light_amount)) + //TODO: heal wounds, heal broken limbs. if(species.light_dam) var/light_amount = 0 @@ -901,13 +913,14 @@ if(overeatduration > 1) overeatduration -= 2 //doubled the unfat rate - if(species.flags & IS_PLANT && (!light_organ || light_organ.is_broken())) + if(!isSynthetic() && (species.flags & IS_PLANT) && (!light_organ || light_organ.is_broken())) if(nutrition < 200) take_overall_damage(2,0) traumatic_shock++ // TODO: stomach and bloodstream organ. - handle_trace_chems() + if(!isSynthetic()) + handle_trace_chems() updatehealth() @@ -920,7 +933,7 @@ if(status_flags & GODMODE) return 0 //SSD check, if a logged player is awake put them back to sleep! - if(species.show_ssd && !client && !teleop) + if(species.get_ssd(src) && !client && !teleop) Sleeping(2) if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP blinded = 1 @@ -928,7 +941,7 @@ else //ALIVE. LIGHTS ARE ON updatehealth() //TODO - if(health <= config.health_threshold_dead || (species.has_organ["brain"] && !has_brain())) + if(health <= config.health_threshold_dead || (should_have_organ("brain") && !has_brain())) death() blinded = 1 silent = 0 @@ -1248,7 +1261,7 @@ if(2) healths.icon_state = "health7" else //switch(health - halloss) - switch(100 - ((species.flags & NO_PAIN) ? 0 : traumatic_shock)) + switch(100 - (!can_feel_pain() ? 0 : traumatic_shock)) if(100 to INFINITY) healths.icon_state = "health0" if(80 to 100) healths.icon_state = "health1" if(60 to 80) healths.icon_state = "health2" @@ -1410,7 +1423,7 @@ // Puke if toxloss is too high if(!stat) if (getToxLoss() >= 45 && nutrition > 20) - vomit() + spawn vomit() //0.1% chance of playing a scary sound to someone who's in complete darkness if(isturf(loc) && rand(1,1000) == 1) @@ -1484,7 +1497,7 @@ /mob/living/carbon/human/handle_shock() ..() if(status_flags & GODMODE) return 0 //godmode - if(species && species.flags & NO_PAIN) return + if(!can_feel_pain()) return if(health < config.health_threshold_softcrit)// health 0 makes you immediately collapse shock_stage = max(shock_stage, 61) @@ -1535,7 +1548,7 @@ /mob/living/carbon/human/proc/handle_pulse() if(life_tick % 5) return pulse //update pulse every 5 life ticks (~1 tick/sec, depending on server load) - if(species && species.flags & NO_BLOOD) + if(!internal_organs_by_name["heart"]) return PULSE_NONE //No blood, no pulse. if(stat == DEAD) @@ -1566,12 +1579,12 @@ return temp /mob/living/carbon/human/proc/handle_heartbeat() - if(pulse == PULSE_NONE || !species.has_organ["heart"]) + if(pulse == PULSE_NONE) return var/obj/item/organ/heart/H = internal_organs_by_name["heart"] - if(!H || H.robotic >=2 ) + if(!H || (H.status & ORGAN_ROBOT)) return if(pulse >= PULSE_2FAST || shock_stage >= 10 || istype(get_turf(src), /turf/space)) @@ -1734,7 +1747,7 @@ return slurring /mob/living/carbon/human/handle_stunned() - if(species.flags & NO_PAIN) + if(!can_feel_pain()) stunned = 0 return 0 if(..()) diff --git a/code/modules/mob/living/carbon/human/species/outsider/shadow.dm b/code/modules/mob/living/carbon/human/species/outsider/shadow.dm index 87fe13fb1d..8820ffaf5b 100644 --- a/code/modules/mob/living/carbon/human/species/outsider/shadow.dm +++ b/code/modules/mob/living/carbon/human/species/outsider/shadow.dm @@ -18,7 +18,7 @@ remains_type = /obj/effect/decal/cleanable/ash death_message = "dissolves into ash..." - flags = NO_BLOOD | NO_SCAN | NO_SLIP | NO_POISON | NO_MINOR_CUT + flags = NO_SCAN | NO_SLIP | NO_POISON | NO_MINOR_CUT spawn_flags = IS_RESTRICTED /datum/species/shadow/handle_death(var/mob/living/carbon/human/H) diff --git a/code/modules/mob/living/carbon/human/species/outsider/vox.dm b/code/modules/mob/living/carbon/human/species/outsider/vox.dm index fa7dda8f57..c1c335a22d 100644 --- a/code/modules/mob/living/carbon/human/species/outsider/vox.dm +++ b/code/modules/mob/living/carbon/human/species/outsider/vox.dm @@ -25,7 +25,6 @@ cold_level_2 = 50 cold_level_3 = 0 - eyes = "vox_eyes_s" gluttonous = 2 breath_type = "nitrogen" @@ -45,6 +44,21 @@ /mob/living/carbon/human/proc/leap ) + has_limbs = list( + "chest" = list("path" = /obj/item/organ/external/chest), + "groin" = list("path" = /obj/item/organ/external/groin), + "head" = list("path" = /obj/item/organ/external/head/vox), + "l_arm" = list("path" = /obj/item/organ/external/arm), + "r_arm" = list("path" = /obj/item/organ/external/arm/right), + "l_leg" = list("path" = /obj/item/organ/external/leg), + "r_leg" = list("path" = /obj/item/organ/external/leg/right), + "l_hand" = list("path" = /obj/item/organ/external/hand), + "r_hand" = list("path" = /obj/item/organ/external/hand/right), + "l_foot" = list("path" = /obj/item/organ/external/foot), + "r_foot" = list("path" = /obj/item/organ/external/foot/right) + ) + + has_organ = list( "heart" = /obj/item/organ/heart, "lungs" = /obj/item/organ/lungs, diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index d6e32722b1..c0722fbca9 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -19,7 +19,6 @@ var/blood_mask = 'icons/mob/human_races/masks/blood_human.dmi' var/prone_icon // If set, draws this from icobase when mob is prone. - var/eyes = "eyes_s" // Icon for eyes. var/blood_color = "#A10808" // Red. var/flesh_color = "#FFC896" // Pink. var/base_color // Used by changelings. Should also be used for icon previes.. @@ -85,7 +84,7 @@ var/warning_low_pressure = WARNING_LOW_PRESSURE // Low pressure warning. var/hazard_low_pressure = HAZARD_LOW_PRESSURE // Dangerously low pressure. var/light_dam // If set, mob will be damaged in light over this value and heal in light below its negative. - var/body_temperature = 310.15 // Non-IS_SYNTHETIC species will try to stabilize at this temperature. + var/body_temperature = 310.15 // Species will try to stabilize at this temperature. // (also affects temperature processing) var/heat_discomfort_level = 315 // Aesthetic messages about feeling warm. @@ -177,6 +176,24 @@ /datum/species/proc/get_bodytype() return name +/datum/species/proc/get_knockout_message(var/mob/living/carbon/human/H) + return ((H && H.isSynthetic()) ? "encounters a hardware fault and suddenly reboots!" : knockout_message) + +/datum/species/proc/get_death_message(var/mob/living/carbon/human/H) + return ((H && H.isSynthetic()) ? "gives one shrill beep before falling lifeless." : death_message) + +/datum/species/proc/get_ssd(var/mob/living/carbon/human/H) + return ((H && H.isSynthetic()) ? "flashing a 'system offline' glyph on their monitor" : show_ssd) + +/datum/species/proc/get_blood_colour(var/mob/living/carbon/human/H) + return ((H && H.isSynthetic()) ? "#1F181F" : blood_color) + +/datum/species/proc/get_virus_immune(var/mob/living/carbon/human/H) + return ((H && H.isSynthetic()) ? 1 : virus_immune) + +/datum/species/proc/get_flesh_colour(var/mob/living/carbon/human/H) + return ((H && H.isSynthetic()) ? "#575757" : flesh_color) + /datum/species/proc/get_environment_discomfort(var/mob/living/carbon/human/H, var/msg_type) if(!prob(5)) diff --git a/code/modules/mob/living/carbon/human/species/station/golem.dm b/code/modules/mob/living/carbon/human/species/station/golem.dm index fae7d834e5..7faf868ac2 100644 --- a/code/modules/mob/living/carbon/human/species/station/golem.dm +++ b/code/modules/mob/living/carbon/human/species/station/golem.dm @@ -7,7 +7,7 @@ language = "Sol Common" //todo? unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/punch) - flags = NO_BREATHE | NO_PAIN | NO_BLOOD | NO_SCAN | NO_POISON | NO_MINOR_CUT + flags = NO_PAIN | NO_SCAN | NO_POISON | NO_MINOR_CUT spawn_flags = IS_RESTRICTED siemens_coefficient = 0 diff --git a/code/modules/mob/living/carbon/human/species/station/monkey.dm b/code/modules/mob/living/carbon/human/species/station/monkey.dm index d9d8347550..77a5f942f0 100644 --- a/code/modules/mob/living/carbon/human/species/station/monkey.dm +++ b/code/modules/mob/living/carbon/human/species/station/monkey.dm @@ -15,8 +15,6 @@ has_fine_manipulation = 0 show_ssd = null - eyes = "blank_eyes" - gibbed_anim = "gibbed-m" dusted_anim = "dust-m" death_message = "lets out a faint chimper as it collapses and stops moving..." @@ -40,6 +38,20 @@ pass_flags = PASSTABLE + has_limbs = list( + "chest" = list("path" = /obj/item/organ/external/chest), + "groin" = list("path" = /obj/item/organ/external/groin), + "head" = list("path" = /obj/item/organ/external/head/no_eyes), + "l_arm" = list("path" = /obj/item/organ/external/arm), + "r_arm" = list("path" = /obj/item/organ/external/arm/right), + "l_leg" = list("path" = /obj/item/organ/external/leg), + "r_leg" = list("path" = /obj/item/organ/external/leg/right), + "l_hand" = list("path" = /obj/item/organ/external/hand), + "r_hand" = list("path" = /obj/item/organ/external/hand/right), + "l_foot" = list("path" = /obj/item/organ/external/foot), + "r_foot" = list("path" = /obj/item/organ/external/foot/right) + ) + /datum/species/monkey/handle_npc(var/mob/living/carbon/human/H) if(H.stat != CONSCIOUS) return diff --git a/code/modules/mob/living/carbon/human/species/station/slime.dm b/code/modules/mob/living/carbon/human/species/station/slime.dm index 38db954932..96a926b14e 100644 --- a/code/modules/mob/living/carbon/human/species/station/slime.dm +++ b/code/modules/mob/living/carbon/human/species/station/slime.dm @@ -8,7 +8,7 @@ language = null //todo? unarmed_types = list(/datum/unarmed_attack/slime_glomp) - flags = NO_SCAN | NO_SLIP | NO_BREATHE | NO_MINOR_CUT + flags = NO_SCAN | NO_SLIP | NO_MINOR_CUT spawn_flags = IS_RESTRICTED siemens_coefficient = 3 //conductive darksight = 3 diff --git a/code/modules/mob/living/carbon/human/species/station/station.dm b/code/modules/mob/living/carbon/human/species/station/station.dm index e5b3ae6b0f..5fecc7c79b 100644 --- a/code/modules/mob/living/carbon/human/species/station/station.dm +++ b/code/modules/mob/living/carbon/human/species/station/station.dm @@ -131,7 +131,6 @@ name_plural = "Skrell" icobase = 'icons/mob/human_races/r_skrell.dmi' deform = 'icons/mob/human_races/r_def_skrell.dmi' - eyes = "skrell_eyes_s" primitive_form = "Neaera" unarmed_types = list(/datum/unarmed_attack/punch) blurb = "An amphibious species, Skrell come from the star system known as Qerr'Vallis, which translates to 'Star of \ @@ -152,6 +151,20 @@ reagent_tag = IS_SKRELL + has_limbs = list( + "chest" = list("path" = /obj/item/organ/external/chest), + "groin" = list("path" = /obj/item/organ/external/groin), + "head" = list("path" = /obj/item/organ/external/head/skrell), + "l_arm" = list("path" = /obj/item/organ/external/arm), + "r_arm" = list("path" = /obj/item/organ/external/arm/right), + "l_leg" = list("path" = /obj/item/organ/external/leg), + "r_leg" = list("path" = /obj/item/organ/external/leg/right), + "l_hand" = list("path" = /obj/item/organ/external/hand), + "r_hand" = list("path" = /obj/item/organ/external/hand/right), + "l_foot" = list("path" = /obj/item/organ/external/foot), + "r_foot" = list("path" = /obj/item/organ/external/foot/right) + ) + /datum/species/diona name = "Diona" name_plural = "Dionaea" @@ -164,7 +177,6 @@ rarity_value = 3 hud_type = /datum/hud_data/diona siemens_coefficient = 0.3 - eyes = "blank_eyes" show_ssd = "completely quiescent" num_alternate_languages = 1 name_language = "Rootspeak" @@ -189,7 +201,7 @@ has_limbs = list( "chest" = list("path" = /obj/item/organ/external/diona/chest), "groin" = list("path" = /obj/item/organ/external/diona/groin), - "head" = list("path" = /obj/item/organ/external/diona/head), + "head" = list("path" = /obj/item/organ/external/head/no_eyes/diona), "l_arm" = list("path" = /obj/item/organ/external/diona/arm), "r_arm" = list("path" = /obj/item/organ/external/diona/arm/right), "l_leg" = list("path" = /obj/item/organ/external/diona/leg), @@ -217,7 +229,7 @@ body_temperature = T0C + 15 //make the plant people have a bit lower body temperature, why not - flags = NO_BREATHE | NO_SCAN | IS_PLANT | NO_BLOOD | NO_PAIN | NO_SLIP | NO_MINOR_CUT + flags = NO_SCAN | IS_PLANT | NO_PAIN | NO_SLIP | NO_MINOR_CUT spawn_flags = CAN_JOIN | IS_WHITELISTED blood_color = "#004400" @@ -254,82 +266,4 @@ else qdel(D) - H.visible_message("[H] splits apart with a wet slithering noise!") - -/datum/species/machine - name = "Machine" - name_plural = "machines" - - blurb = "Positronic intelligence really took off in the 26th century, and it is not uncommon to see independant, free-willed \ - robots on many human stations, particularly in fringe systems where standards are slightly lax and public opinion less relevant \ - to corporate operations. IPCs (Integrated Positronic Chassis) are a loose category of self-willed robots with a humanoid form, \ - generally self-owned after being 'born' into servitude; they are reliable and dedicated workers, albeit more than slightly \ - inhuman in outlook and perspective." - - icobase = 'icons/mob/human_races/r_machine.dmi' - deform = 'icons/mob/human_races/r_machine.dmi' - - language = "Encoded Audio Language" - unarmed_types = list(/datum/unarmed_attack/punch) - rarity_value = 2 - num_alternate_languages = 1 // potentially could be 2? - name_language = "Encoded Audio Language" - - eyes = "blank_eyes" - brute_mod = 1.875 // 100% * 1.875 * 0.8 (robolimbs) ~= 150% - burn_mod = 1.875 // So they take 50% extra damage from brute/burn overall. - show_ssd = "flashing a 'system offline' glyph on their monitor" - death_message = "gives one shrill beep before falling lifeless." - knockout_message = "encounters a hardware fault and suddenly reboots!" - - warning_low_pressure = 50 - hazard_low_pressure = 0 - - cold_level_1 = 50 - cold_level_2 = -1 - cold_level_3 = -1 - - heat_level_1 = 500 // Gives them about 25 seconds in space before taking damage - heat_level_2 = 1000 - heat_level_3 = 2000 - - passive_temp_gain = 10 // This should cause IPCs to stabilize at ~80 C in a 20 C environment. - - flags = NO_BREATHE | NO_SCAN | NO_BLOOD | NO_PAIN | NO_POISON - spawn_flags = CAN_JOIN | IS_WHITELISTED - - blood_color = "#1F181F" - flesh_color = "#575757" - virus_immune = 1 - reagent_tag = IS_MACHINE - - has_organ = list( - "brain" = /obj/item/organ/mmi_holder/posibrain, - "cell" = /obj/item/organ/cell, - "optics" = /obj/item/organ/optical_sensor - ) - - vision_organ = "optics" - - has_limbs = list( - "chest" = list("path" = /obj/item/organ/external/chest/ipc), - "groin" = list("path" = /obj/item/organ/external/groin/ipc), - "head" = list("path" = /obj/item/organ/external/head/ipc), - "l_arm" = list("path" = /obj/item/organ/external/arm/ipc), - "r_arm" = list("path" = /obj/item/organ/external/arm/right/ipc), - "l_leg" = list("path" = /obj/item/organ/external/leg/ipc), - "r_leg" = list("path" = /obj/item/organ/external/leg/right/ipc), - "l_hand" = list("path" = /obj/item/organ/external/hand/ipc), - "r_hand" = list("path" = /obj/item/organ/external/hand/right/ipc), - "l_foot" = list("path" = /obj/item/organ/external/foot/ipc), - "r_foot" = list("path" = /obj/item/organ/external/foot/right/ipc) - ) - -/datum/species/machine/handle_death(var/mob/living/carbon/human/H) - ..() - H.h_style = "" - spawn(100) - if(H) H.update_hair() - -/datum/species/machine/sanitize_name(var/name) - return sanitizeName(name, allow_numbers = 1) + H.visible_message("\The [H] splits apart with a wet slithering noise!") diff --git a/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm b/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm index 1c5e88ce59..5f6ab38fad 100644 --- a/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm +++ b/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm @@ -13,8 +13,6 @@ siemens_coefficient = 0 gluttonous = 3 - eyes = "blank_eyes" - brute_mod = 0.5 // Hardened carapace. burn_mod = 2 // Weak to fire. @@ -25,7 +23,7 @@ cold_level_2 = -1 cold_level_3 = -1 - flags = NO_BREATHE | NO_SCAN | NO_PAIN | NO_SLIP | NO_POISON | NO_MINOR_CUT + flags = NO_SCAN | NO_PAIN | NO_SLIP | NO_POISON | NO_MINOR_CUT spawn_flags = IS_RESTRICTED reagent_tag = IS_XENOS @@ -62,6 +60,20 @@ var/weeds_heal_rate = 1 // Health regen on weeds. var/weeds_plasma_rate = 5 // Plasma regen on weeds. + has_limbs = list( + "chest" = list("path" = /obj/item/organ/external/chest), + "groin" = list("path" = /obj/item/organ/external/groin), + "head" = list("path" = /obj/item/organ/external/head/no_eyes), + "l_arm" = list("path" = /obj/item/organ/external/arm), + "r_arm" = list("path" = /obj/item/organ/external/arm/right), + "l_leg" = list("path" = /obj/item/organ/external/leg), + "r_leg" = list("path" = /obj/item/organ/external/leg/right), + "l_hand" = list("path" = /obj/item/organ/external/hand), + "r_hand" = list("path" = /obj/item/organ/external/hand/right), + "l_foot" = list("path" = /obj/item/organ/external/foot), + "r_foot" = list("path" = /obj/item/organ/external/foot/right) + ) + /datum/species/xenos/get_bodytype() return "Xenomorph" diff --git a/code/modules/mob/living/carbon/human/unarmed_attack.dm b/code/modules/mob/living/carbon/human/unarmed_attack.dm index 92a6089e9f..f6ecb54ce5 100644 --- a/code/modules/mob/living/carbon/human/unarmed_attack.dm +++ b/code/modules/mob/living/carbon/human/unarmed_attack.dm @@ -54,7 +54,7 @@ var/global/list/sparring_attack_cache = list() if("l_arm", "l_hand") if (target.l_hand) // Disarm left hand - //Urist McAssistant dropped the macguffin with a scream just sounds odd. Plus it doesn't work with NO_PAIN + //Urist McAssistant dropped the macguffin with a scream just sounds odd. target.visible_message("\The [target.l_hand] was knocked right out of [target]'s grasp!") target.drop_l_hand() if("r_arm", "r_hand") @@ -94,10 +94,13 @@ var/global/list/sparring_attack_cache = list() /datum/unarmed_attack/proc/handle_eye_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target) var/obj/item/organ/eyes/eyes = target.internal_organs_by_name["eyes"] - eyes.take_damage(rand(3,4), 1) - - user.visible_message("[user] presses \his [eye_attack_text] into [target]'s [eyes.name]!") - target << "You experience[(target.species.flags & NO_PAIN)? "" : " immense pain as you feel" ] [eye_attack_text_victim] being pressed into your [eyes.name][(target.species.flags & NO_PAIN)? "." : "!"]" + if(eyes) + eyes.take_damage(rand(3,4), 1) + user.visible_message("[user] presses \his [eye_attack_text] into [target]'s [eyes.name]!") + var/eye_pain = eyes.can_feel_pain() + target << "You experience[(eye_pain) ? "" : " immense pain as you feel" ] [eye_attack_text_victim] being pressed into your [eyes.name][(eye_pain)? "." : "!"]" + return + user.visible_message("[user] attempts to press \his [eye_attack_text] into [target]'s eyes, but they don't have any!") /datum/unarmed_attack/bite attack_verb = list("bit") diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 8fab931887..cc112b18d9 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -209,11 +209,11 @@ var/global/list/damage_icon_parts = list() O.update_icon() if(O.damage_state == "00") continue var/icon/DI - var/cache_index = "[O.damage_state]/[O.icon_name]/[species.blood_color]/[species.get_bodytype()]" + var/cache_index = "[O.damage_state]/[O.icon_name]/[O.species.get_blood_colour()]/[species.get_bodytype()]" if(damage_icon_parts[cache_index] == null) DI = new /icon(species.damage_overlays, O.damage_state) // the damage icon for whole human DI.Blend(new /icon(species.damage_mask, O.icon_name), ICON_MULTIPLY) // mask with this organ's pixels - DI.Blend(species.blood_color, ICON_MULTIPLY) + DI.Blend(O.species.get_blood_colour(), ICON_MULTIPLY) damage_icon_parts[cache_index] = DI else DI = damage_icon_parts[cache_index] diff --git a/code/modules/mob/living/carbon/metroid/powers.dm b/code/modules/mob/living/carbon/metroid/powers.dm index 8b8e875aec..2e1cc29595 100644 --- a/code/modules/mob/living/carbon/metroid/powers.dm +++ b/code/modules/mob/living/carbon/metroid/powers.dm @@ -63,7 +63,7 @@ H.custom_pain(painMes) else if (istype(M, /mob/living/carbon)) var/mob/living/carbon/C = M - if (!(C.species && (C.species.flags & NO_PAIN))) + if (C.can_feel_pain()) M << "[painMes]" gain_nutrition(rand(20,25)) diff --git a/code/modules/mob/living/carbon/shock.dm b/code/modules/mob/living/carbon/shock.dm index be31d28034..92eccc66df 100644 --- a/code/modules/mob/living/carbon/shock.dm +++ b/code/modules/mob/living/carbon/shock.dm @@ -3,7 +3,7 @@ // proc to find out in how much pain the mob is at the moment /mob/living/carbon/proc/updateshock() - if (species && (species.flags & NO_PAIN)) + if (!can_feel_pain()) src.traumatic_shock = 0 return 0 diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index ef7a33fd40..f575c6303d 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -813,3 +813,51 @@ default behaviour is: ear_damage = damage if(deaf >= 0) ear_deaf = deaf + +/mob/living/proc/vomit(var/skip_wait, var/blood_vomit) + + if(isSynthetic()) + src << "A sudden, dizzying wave of internal feedback rushes over you!" + src.Weaken(5) + return + + if(!check_has_mouth()) + return + + if(!lastpuke) + + if (nutrition <= 100) + src << "You gag as you want to throw up, but there's nothing in your stomach!" + src.Weaken(10) + src.adjustToxLoss(3) + return + + lastpuke = 1 + src << "You feel nauseous..." + + if(!skip_wait) + sleep(150) //15 seconds until second warning + src << "You feel like you are about to throw up!" + sleep(100) //and you have 10 more for mad dash to the bucket + + Stun(5) + src.visible_message("[src] throws up!","You throw up!") + playsound(loc, 'sound/effects/splat.ogg', 50, 1) + + var/turf/simulated/T = get_turf(src) + if(istype(T)) + if(blood_vomit) + T.add_blood_floor(src) + else + T.add_vomit_floor(src, 1) + + if(blood_vomit) + if(getBruteLoss() < 50) + adjustBruteLoss(3) + else + nutrition -= 40 + adjustToxLoss(-3) + + sleep(350) + lastpuke = 0 + diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 5a671afe99..c547211ecf 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -43,3 +43,4 @@ var/fire_stacks var/failed_last_breath = 0 //This is used to determine if the mob failed a breath. If they did fail a brath, they will attempt to breathe each tick, otherwise just once per 4 ticks. + var/lastpuke = 0 diff --git a/code/modules/mob/living/silicon/robot/drone/drone.dm b/code/modules/mob/living/silicon/robot/drone/drone.dm index 6b38a7c465..14434bfe6e 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone.dm @@ -30,7 +30,7 @@ var/list/mob_hat_cache = list() universal_understand = 1 gender = NEUTER pass_flags = PASSTABLE - braintype = "Robot" + braintype = "Drone" lawupdate = 0 density = 1 req_access = list(access_engine, access_robotics) diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 8507053e23..293a55b222 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -247,7 +247,7 @@ if((crisis && security_level == SEC_LEVEL_RED) || crisis_override) //Leaving this in until it's balanced appropriately. src << "\red Crisis mode active. Combat module available." modules+="Combat" - modtype = input("Please, select a module!", "Robot", null, null) as null|anything in modules + modtype = input("Please, select a module!", "Robot module", null, null) as null|anything in modules if(module) return @@ -267,9 +267,9 @@ modtype = prefix if(istype(mmi, /obj/item/device/mmi/digital/posibrain)) - braintype = "Android" - else if(istype(mmi, /obj/item/device/mmi/digital/robot)) braintype = "Robot" + else if(istype(mmi, /obj/item/device/mmi/digital/robot)) + braintype = "Drone" else braintype = "Cyborg" @@ -911,7 +911,7 @@ if(!(icontype in module_sprites)) icontype = module_sprites[1] else - icontype = input("Select an icon! [triesleft ? "You have [triesleft] more chance\s." : "This is your last try."]", "Robot", icontype, null) in module_sprites + icontype = input("Select an icon! [triesleft ? "You have [triesleft] more chance\s." : "This is your last try."]", "Robot Icon", icontype, null) in module_sprites icon_state = module_sprites[icontype] updateicon() diff --git a/code/modules/mob/living/simple_animal/borer/borer_powers.dm b/code/modules/mob/living/simple_animal/borer/borer_powers.dm index 88be25cc24..05bf7e8eef 100644 --- a/code/modules/mob/living/simple_animal/borer/borer_powers.dm +++ b/code/modules/mob/living/simple_animal/borer/borer_powers.dm @@ -77,7 +77,7 @@ if(!E || (E.status & ORGAN_DESTROYED)) src << "\The [H] does not have a head!" - if(!H.species.has_organ["brain"]) + if(!H.should_have_organ("brain")) src << "\The [H] does not seem to have an ear canal to breach." return diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 7885d3e8f7..9503800189 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -87,7 +87,6 @@ var/canmove = 1 //Allows mobs to move through dense areas without restriction. For instance, in space or out of holder objects. var/incorporeal_move = 0 //0 is off, 1 is normal, 2 is for ninjas. - var/lastpuke = 0 var/unacidable = 0 var/list/pinned = list() // List of things pinning this creature to walls (see living_defense.dm) var/list/embedded = list() // Embedded items, since simple mobs don't have organs. diff --git a/code/modules/mob/mob_grab_specials.dm b/code/modules/mob/mob_grab_specials.dm index 44303241db..fb51bc1572 100644 --- a/code/modules/mob/mob_grab_specials.dm +++ b/code/modules/mob/mob_grab_specials.dm @@ -99,7 +99,7 @@ if(!armor && target.headcheck("head") && prob(damage)) target.apply_effect(20, PARALYZE) - target.visible_message("[target] [target.species.knockout_message]") + target.visible_message("[target] [target.species.get_knockout_message(target)]") playsound(attacker.loc, "swing_hit", 25, 1, -1) attacker.attack_log += text("\[[time_stamp()]\] Headbutted [target.name] ([target.ckey])") diff --git a/code/modules/mob/new_player/preferences_setup.dm b/code/modules/mob/new_player/preferences_setup.dm index a3f81168b7..d20fe8bee2 100644 --- a/code/modules/mob/new_player/preferences_setup.dm +++ b/code/modules/mob/new_player/preferences_setup.dm @@ -3,8 +3,18 @@ datum/preferences proc/randomize_appearance_for(var/mob/living/carbon/human/H) gender = pick(MALE, FEMALE) s_tone = random_skin_tone() - h_style = random_hair_style(gender, species) - f_style = random_facial_hair_style(gender, species) + + var/use_head_species + var/obj/item/organ/external/head/temp_head = H.get_organ("head") + if(temp_head) + use_head_species = temp_head.species.get_bodytype() + else + use_head_species = H.species.get_bodytype() + + if(use_head_species) + h_style = random_hair_style(gender, species) + f_style = random_facial_hair_style(gender, species) + randomize_hair_color("hair") randomize_hair_color("facial") randomize_eyes_color() @@ -191,37 +201,58 @@ datum/preferences else icobase = 'icons/mob/human_races/r_human.dmi' - preview_icon = new /icon(icobase, "torso_[g]") - preview_icon.Blend(new /icon(icobase, "groin_[g]"), ICON_OVERLAY) - preview_icon.Blend(new /icon(icobase, "head_[g]"), ICON_OVERLAY) - - for(var/name in list("r_arm","r_hand","r_leg","r_foot","l_leg","l_foot","l_arm","l_hand")) - if(organ_data[name] == "amputated") continue + preview_icon = new /icon(icobase, "") + for(var/name in list("torso", "groin", "head", "r_arm","r_hand","r_leg","r_foot","l_leg","l_foot","l_arm","l_hand")) + if(organ_data[name] == "amputated") + continue if(organ_data[name] == "cyborg") var/datum/robolimb/R if(rlimb_data[name]) R = all_robolimbs[rlimb_data[name]] if(!R) R = basic_robolimb - preview_icon.Blend(icon(R.icon, "[name]"), ICON_OVERLAY) // This doesn't check gendered_icon. Not an issue while only limbs can be robotic. + if(name in list("torso", "groin", "head")) + preview_icon.Blend(icon(R.icon, "[name]_[g]"), ICON_OVERLAY) + else + preview_icon.Blend(icon(R.icon, "[name]"), ICON_OVERLAY) continue - preview_icon.Blend(new /icon(icobase, "[name]"), ICON_OVERLAY) + var/icon/limb_icon + if(name in list("torso", "groin", "head")) + limb_icon = new /icon(icobase, "[name]_[g]") + else + limb_icon = new /icon(icobase, "[name]") + // Skin color + if(current_species && (current_species.appearance_flags & HAS_SKIN_COLOR)) + limb_icon.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD) + // Skin tone + if(current_species && (current_species.appearance_flags & HAS_SKIN_TONE)) + if (s_tone >= 0) + limb_icon.Blend(rgb(s_tone, s_tone, s_tone), ICON_ADD) + else + limb_icon.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT) + preview_icon.Blend(limb_icon, ICON_OVERLAY) //Tail if(current_species && (current_species.tail)) var/icon/temp = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[current_species.tail]_s") + if(current_species && (current_species.appearance_flags & HAS_SKIN_COLOR)) + temp.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD) + if(current_species && (current_species.appearance_flags & HAS_SKIN_TONE)) + if (s_tone >= 0) + temp.Blend(rgb(s_tone, s_tone, s_tone), ICON_ADD) + else + temp.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT) preview_icon.Blend(temp, ICON_OVERLAY) - // Skin color - if(current_species && (current_species.appearance_flags & HAS_SKIN_COLOR)) - preview_icon.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD) + // This is absolute garbage but whatever. It will do until this entire file can be rewritten without crashes. + var/use_eye_icon = "eyes_s" + var/list/use_eye_data = current_species.has_limbs["head"] + if(islist(use_eye_data)) + var/use_eye_path = use_eye_data["path"] + var/obj/item/organ/external/head/temp_head = new use_eye_path () + if(istype(temp_head)) + use_eye_icon = temp_head.eye_icon + qdel(temp_head) - // Skin tone - if(current_species && (current_species.appearance_flags & HAS_SKIN_TONE)) - if (s_tone >= 0) - preview_icon.Blend(rgb(s_tone, s_tone, s_tone), ICON_ADD) - else - preview_icon.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT) - - var/icon/eyes_s = new/icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = current_species ? current_species.eyes : "eyes_s") + var/icon/eyes_s = new/icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = use_eye_icon) if ((current_species && (current_species.appearance_flags & HAS_EYE_COLOR))) eyes_s.Blend(rgb(r_eyes, g_eyes, b_eyes), ICON_ADD) diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 10b9d0ebbf..f200766179 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -145,9 +145,9 @@ O.loc = loc O.job = "Cyborg" if(O.mind.assigned_role == "Cyborg") - if(O.mind.role_alt_title == "Android") + if(O.mind.role_alt_title == "Robot") O.mmi = new /obj/item/device/mmi/digital/posibrain(O) - else if(O.mind.role_alt_title == "Robot") + else if(O.mind.role_alt_title == "Drone") O.mmi = new /obj/item/device/mmi/digital/robot(O) else O.mmi = new /obj/item/device/mmi(O) diff --git a/code/modules/organs/blood.dm b/code/modules/organs/blood.dm index ebc490601d..74d2cebce0 100644 --- a/code/modules/organs/blood.dm +++ b/code/modules/organs/blood.dm @@ -19,7 +19,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122 vessel = new/datum/reagents(600) vessel.my_atom = src - if(species && species.flags & NO_BLOOD) //We want the var for safety but we can do without the actual blood. + if(!should_have_organ("heart")) //We want the var for safety but we can do without the actual blood. return vessel.add_reagent("blood",560) @@ -30,7 +30,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122 /mob/living/carbon/human/proc/fixblood() for(var/datum/reagent/blood/B in vessel.reagent_list) if(B.id == "blood") - B.data = list( "donor"=src,"viruses"=null,"species"=species.name,"blood_DNA"=dna.unique_enzymes,"blood_colour"= species.blood_color,"blood_type"=dna.b_type, \ + B.data = list( "donor"=src,"viruses"=null,"species"=species.name,"blood_DNA"=dna.unique_enzymes,"blood_colour"= species.get_blood_colour(src),"blood_type"=dna.b_type, \ "resistances"=null,"trace_chem"=null, "virus2" = null, "antibodies" = list()) B.color = B.data["blood_colour"] @@ -39,7 +39,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122 if(in_stasis) return - if(species && species.flags & NO_BLOOD) + if(!should_have_organ("heart")) return if(stat != DEAD && bodytemperature >= 170) //Dead or cryosleep people do not pump the blood. @@ -62,7 +62,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122 // Damaged heart virtually reduces the blood volume, as the blood isn't // being pumped properly anymore. - if(species && species.has_organ["heart"]) + if(species && should_have_organ("heart")) var/obj/item/organ/heart/heart = internal_organs_by_name["heart"] if(!heart) @@ -126,7 +126,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122 //Bleeding out var/blood_max = 0 for(var/obj/item/organ/external/temp in organs) - if(!(temp.status & ORGAN_BLEEDING) || temp.status & ORGAN_ROBOT) + if(!(temp.status & ORGAN_BLEEDING) || (temp.status & ORGAN_ROBOT)) continue for(var/datum/wound/W in temp.wounds) if(W.bleeding()) blood_max += W.damage / 40 @@ -137,7 +137,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122 //Makes a blood drop, leaking amt units of blood from the mob /mob/living/carbon/human/proc/drip(var/amt as num) - if(species && species.flags & NO_BLOOD) //TODO: Make drips come from the reagents instead. + if(!should_have_organ("heart")) //TODO: Make drips come from the reagents instead. return if(!amt) @@ -175,7 +175,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122 // Putting this here due to return shenanigans. if(istype(src,/mob/living/carbon/human)) var/mob/living/carbon/human/H = src - B.data["blood_colour"] = H.species.blood_color + B.data["blood_colour"] = H.species.get_blood_colour(H) B.color = B.data["blood_colour"] var/list/temp_chem = list() @@ -188,7 +188,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122 //For humans, blood does not appear from blue, it comes from vessels. /mob/living/carbon/human/take_blood(obj/item/weapon/reagent_containers/container, var/amount) - if(species && species.flags & NO_BLOOD) + if(!should_have_organ("heart")) return null if(vessel.get_reagent_amount("blood") < amount) @@ -216,7 +216,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122 //Transfers blood from reagents to vessel, respecting blood types compatability. /mob/living/carbon/human/inject_blood(var/datum/reagent/blood/injected, var/amount) - if(species.flags & NO_BLOOD) + if(should_have_organ("heart")) reagents.add_reagent("blood", amount, injected.data) reagents.update_total() return diff --git a/code/modules/organs/misc.dm b/code/modules/organs/misc.dm index a330e307a3..0ba128c1a6 100644 --- a/code/modules/organs/misc.dm +++ b/code/modules/organs/misc.dm @@ -46,7 +46,8 @@ /obj/item/organ/stack name = "cortical stack" parent_organ = "head" - robotic = 2 + icon_state = "brain-prosthetic" + organ_tag = "stack" vital = 1 var/backup_time = 0 var/datum/mind/backup @@ -56,15 +57,5 @@ backup_time = world.time if(owner.mind) backup = owner.mind -/obj/item/organ/stack/vox - /obj/item/organ/stack/vox/stack - -/obj/item/organ/stack - name = "cortical stack" - icon_state = "brain-prosthetic" - organ_tag = "stack" - robotic = 2 - -/obj/item/organ/stack/vox name = "vox cortical stack" diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index 5165108635..63c57acb21 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -3,33 +3,37 @@ var/list/organ_cache = list() /obj/item/organ name = "organ" icon = 'icons/obj/surgery.dmi' + germ_level = 0 + + // Strings. + var/organ_tag = "organ" + var/parent_organ = "chest" + + // Appearance. var/dead_icon - var/mob/living/carbon/human/owner = null + + // Status tracking. var/status = 0 var/vital //Lose a vital limb, die immediately. var/damage = 0 // amount of damage to the organ - var/min_bruised_damage = 10 - var/min_broken_damage = 30 - var/max_damage - var/organ_tag = "organ" - - var/parent_organ = "chest" - var/robotic = 0 //For being a robot - var/rejecting // Is this organ already being rejected? - + // Reference data. + var/mob/living/carbon/human/owner = null var/list/transplant_data var/list/datum/autopsy_data/autopsy_data = list() var/list/trace_chemicals = list() // traces of chemicals in the organ, - // links chemical IDs to number of ticks for which they'll stay in the blood - germ_level = 0 var/datum/dna/dna var/datum/species/species + // Damage vars. + var/min_bruised_damage = 10 + var/min_broken_damage = 30 + var/max_damage + var/rejecting // Is this organ already being rejected? + /obj/item/organ/Destroy() if(!owner) return ..() - if(istype(owner, /mob/living/carbon)) if((owner.internal_organs) && (src in owner.internal_organs)) owner.internal_organs -= src @@ -42,7 +46,7 @@ var/list/organ_cache = list() owner.organs_by_name -= src if(src in owner.contents) owner.contents -= src - + owner = null return ..() /obj/item/organ/proc/update_health() @@ -189,8 +193,25 @@ var/list/organ_cache = list() /obj/item/organ/proc/receive_chem(chemical as obj) return 0 -/obj/item/organ/proc/rejuvenate() +/obj/item/organ/proc/rejuvenate(var/ignore_prosthetic_prefs) damage = 0 + status = 0 + if(!ignore_prosthetic_prefs && owner && owner.client && owner.client.prefs && owner.client.prefs.real_name == owner.real_name) + var/status = owner.client.prefs.organ_data[organ_tag] + if(status == "assisted") + mechassist() + else if(status == "mechanical") + robotize() + +/obj/item/organ/proc/remove_rejuv() + if(owner) + owner.internal_organs -= src + owner.internal_organs_by_name[organ_tag] = null + while(null in owner.internal_organs) + owner.internal_organs -= null + while(null in owner.internal_organs_by_name) + owner.internal_organs_by_name -= null + qdel(src) /obj/item/organ/proc/is_damaged() return damage > 0 @@ -241,19 +262,13 @@ var/list/organ_cache = list() owner.custom_pain("Something inside your [parent.name] hurts a lot.", 1) /obj/item/organ/proc/robotize() //Being used to make robutt hearts, etc - robotic = 2 - src.status &= ~ORGAN_BROKEN - src.status &= ~ORGAN_BLEEDING - src.status &= ~ORGAN_SPLINTED - src.status &= ~ORGAN_CUT_AWAY - src.status &= ~ORGAN_DESTROYED - src.status |= ORGAN_ROBOT - src.status |= ORGAN_ASSISTED + status = 0 + status |= ORGAN_ASSISTED + status |= ORGAN_ROBOT /obj/item/organ/proc/mechassist() //Used to add things like pacemakers, etc - robotize() - src.status &= ~ORGAN_ROBOT - robotic = 1 + status = 0 + status |= ORGAN_ASSISTED min_bruised_damage = 15 min_broken_damage = 35 @@ -320,8 +335,6 @@ var/list/organ_cache = list() target.internal_organs |= src affected.internal_organs |= src target.internal_organs_by_name[organ_tag] = src - if(robotic) - status |= ORGAN_ROBOT /obj/item/organ/eyes/replaced(var/mob/living/carbon/human/target) @@ -335,10 +348,10 @@ var/list/organ_cache = list() /obj/item/organ/proc/bitten(mob/user) - if(robotic) + if(status & ORGAN_ROBOT) return - user << "\blue You take an experimental bite out of \the [src]." + user << "You take an experimental bite out of \the [src]." var/datum/reagent/blood/B = locate(/datum/reagent/blood) in reagents.reagent_list blood_splatter(src,B,1) @@ -361,6 +374,9 @@ var/list/organ_cache = list() /obj/item/organ/attack_self(mob/user as mob) // Convert it to an edible form, yum yum. - if(!robotic && user.a_intent == "help" && user.zone_sel.selecting == "mouth") + if((status & ORGAN_ROBOT) && user.a_intent == "help" && user.zone_sel.selecting == "mouth") bitten(user) return + +/obj/item/organ/proc/can_feel_pain() + return !(status & (ORGAN_ROBOT|ORGAN_DESTROYED)) && !(species.flags & NO_PAIN) diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 1e2f7d1e52..ed9d32f122 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -14,49 +14,57 @@ dir = SOUTH organ_tag = "limb" - var/brute_mod = 1 - var/burn_mod = 1 + // Strings + var/limb_name + // Damage vars. + var/brute_mod = 1 // Multiplier for incoming brute damage. + var/burn_mod = 1 // As above for burn. + var/damage_state = "00" // Modifier used for generating the on-mob damage overlay for this limb. + var/brute_dam = 0 // Actual current brute damage. + var/burn_dam = 0 // Actual current burn damage. + var/last_dam = -1 + + // Appearance vars. var/icon_name = null var/body_part = null var/icon_position = 0 var/model var/force_icon - var/damage_state = "00" - var/brute_dam = 0 - var/burn_dam = 0 - var/max_size = 0 - var/last_dam = -1 var/icon/mob_icon var/gendered_icon = 0 - var/limb_name - var/disfigured = 0 - var/cannot_amputate - var/cannot_break var/s_tone var/list/s_col var/list/h_col + var/body_hair + + // Wound and structural data. + var/wound_update_accuracy = 1 // how often wounds should be updated, a higher number means less often var/list/wounds = list() var/number_wounds = 0 // cache the number of wounds, which is NOT wounds.len! - var/perma_injury = 0 var/obj/item/organ/external/parent var/list/obj/item/organ/external/children var/list/internal_organs = list() // Internal organs of this body part - var/damage_msg = "\red You feel an intense pain" var/broken_description - var/open = 0 - var/stage = 0 - var/cavity = 0 var/sabotaged = 0 // If a prosthetic limb is emagged, it will detonate when it fails. - var/encased // Needs to be opened with a saw to access the organs. var/list/implants = list() - var/wound_update_accuracy = 1 // how often wounds should be updated, a higher number means less often + + // Joint/state stuff. + var/can_grasp //It would be more appropriate if these two were named "affects_grasp" and "affects_stand" at this point + var/can_stand + var/disfigured = 0 + var/cannot_amputate + var/cannot_break var/joint = "joint" // Descriptive string used in dislocation. var/amputation_point // Descriptive string used in amputation. var/dislocated = 0 // If you target a joint, you can dislocate the limb, causing temporary damage to the organ. - var/can_grasp //It would be more appropriate if these two were named "affects_grasp" and "affects_stand" at this point - var/can_stand - var/body_hair + var/encased // Needs to be opened with a saw to access the organs. + + // Surgery vars. + var/open = 0 + var/stage = 0 + var/cavity = 0 + /obj/item/organ/external/Destroy() if(parent && parent.children) @@ -188,12 +196,6 @@ parent.children = list() parent.children.Add(src) -/obj/item/organ/external/robotize() - ..() - //robit limbs take reduced damage - brute_mod = 0.8 - burn_mod = 0.8 - /**************************************************** DAMAGE PROCS ****************************************************/ @@ -219,7 +221,7 @@ brute -= brute / 2 if(status & ORGAN_BROKEN && prob(40) && brute) - if (!(owner.species && (owner.species.flags & NO_PAIN))) + if(!((species.flags & NO_PAIN) || (status & ORGAN_ROBOT))) owner.emote("scream") //getting hit on broken hand hurts if(used_weapon) add_autopsy_data("[used_weapon]", brute + burn) @@ -316,7 +318,6 @@ if(internal) status &= ~ORGAN_BROKEN - perma_injury = 0 /*if((brute || burn) && children && children.len && (owner.species.flags & REGENERATES_LIMBS)) var/obj/item/organ/external/stump/S = locate() in children @@ -333,13 +334,10 @@ /* This function completely restores a damaged organ to perfect condition. */ -/obj/item/organ/external/rejuvenate() +/obj/item/organ/external/rejuvenate(var/ignore_prosthetic_prefs) damage_state = "00" - if(status & 128) //Robotic organs stay robotic. Fix because right click rejuvinate makes IPC's organs organic. - status = 128 - else - status = 0 - perma_injury = 0 + + status = 0 brute_dam = 0 burn_dam = 0 germ_level = 0 @@ -348,16 +346,44 @@ This function completely restores a damaged organ to perfect condition. // handle internal organs for(var/obj/item/organ/current_organ in internal_organs) - current_organ.rejuvenate() + current_organ.rejuvenate(ignore_prosthetic_prefs) // remove embedded objects and drop them on the floor for(var/obj/implanted_object in implants) if(!istype(implanted_object,/obj/item/weapon/implant)) // We don't want to remove REAL implants. Just shrapnel etc. - implanted_object.loc = owner.loc + implanted_object.loc = get_turf(src) implants -= implanted_object - owner.updatehealth() + if(owner && !ignore_prosthetic_prefs) + if(owner.client && owner.client.prefs && owner.client.prefs.real_name == owner.real_name) + var/status = owner.client.prefs.organ_data[limb_name] + if(status == "amputated") + remove_rejuv() + else if(status == "cyborg") + var/robodata = owner.client.prefs.rlimb_data[limb_name] + if(robodata) + robotize(robodata) + else + robotize() + owner.updatehealth() +/obj/item/organ/external/remove_rejuv() + if(owner) + owner.organs -= src + owner.organs_by_name[limb_name] = null + while(null in owner.organs) + owner.organs -= null + while(null in owner.organs_by_name) + owner.organs_by_name -= null + if(children && children.len) + for(var/obj/item/organ/external/E in children) + E.remove_rejuv() + children.Cut() + + for(var/obj/item/organ/O in contents) + O.remove_rejuv() + + qdel(src) /obj/item/organ/external/proc/createwound(var/type = CUT, var/damage) if(damage == 0) return @@ -384,13 +410,13 @@ This function completely restores a damaged organ to perfect condition. W.open_wound(damage) if(prob(25)) if(status & ORGAN_ROBOT) - owner.visible_message("\red The damage to [owner.name]'s [name] worsens.",\ - "\red The damage to your [name] worsens.",\ - "You hear the screech of abused metal.") + owner.visible_message("The damage to [owner.name]'s [name] worsens.",\ + "The damage to your [name] worsens.",\ + "You hear the screech of abused metal.") else - owner.visible_message("\red The wound on [owner.name]'s [name] widens with a nasty ripping noise.",\ - "\red The wound on your [name] widens with a nasty ripping noise.",\ - "You hear a nasty ripping noise, as if flesh is being torn apart.") + owner.visible_message("The wound on [owner.name]'s [name] widens with a nasty ripping noise.",\ + "The wound on your [name] widens with a nasty ripping noise.",\ + "You hear a nasty ripping noise, as if flesh is being torn apart.") return //Creating wound @@ -451,9 +477,6 @@ This function completely restores a damaged organ to perfect condition. if(trace_chemicals[chemID] <= 0) trace_chemicals.Remove(chemID) - if(!(status & ORGAN_BROKEN)) - perma_injury = 0 - //Infections update_germs() else @@ -629,7 +652,7 @@ Note that amputating the affected organ does in fact remove the infection from t else if(W.damage_type == BURN) burn_dam += W.damage - if(!(status & ORGAN_ROBOT) && W.bleeding() && (H && !(H.species.flags & NO_BLOOD))) + if(!(status & ORGAN_ROBOT) && W.bleeding() && (H && H.should_have_organ("heart"))) W.bleed_timer-- status |= ORGAN_BLEEDING @@ -638,7 +661,7 @@ Note that amputating the affected organ does in fact remove the infection from t number_wounds += W.amount //things tend to bleed if they are CUT OPEN - if (open && !clamped && (H && !(H.species.flags & NO_BLOOD))) + if (open && !clamped && (H && H.should_have_organ("heart"))) status |= ORGAN_BLEEDING //Bone fractures @@ -687,7 +710,7 @@ Note that amputating the affected organ does in fact remove the infection from t ****************************************************/ //Handles dismemberment -/obj/item/organ/external/proc/droplimb(var/clean, var/disintegrate, var/ignore_children) +/obj/item/organ/external/proc/droplimb(var/clean, var/disintegrate, var/ignore_children, var/silent) if(cannot_amputate || !owner) return @@ -762,12 +785,18 @@ Note that amputating the affected organ does in fact remove the infection from t I.loc = get_turf(src) qdel(src) if(DROPLIMB_BLUNT) - var/obj/effect/decal/cleanable/blood/gibs/gore = new victim.species.single_gib_type(get_turf(victim)) - if(victim.species.flesh_color) - gore.fleshcolor = victim.species.flesh_color - if(victim.species.blood_color) - gore.basecolor = victim.species.blood_color - gore.update_icon() + var/obj/effect/decal/cleanable/blood/gibs/gore + if(status & ORGAN_ROBOT) + gore = new /obj/effect/decal/cleanable/blood/gibs/robot(get_turf(victim)) + else + gore = new victim.species.single_gib_type(get_turf(victim)) + if(species) + if(species.get_flesh_colour()) + gore.fleshcolor = species.get_flesh_colour() + if(species.get_blood_colour()) + gore.basecolor = species.get_blood_colour() + gore.update_icon() + gore.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30) for(var/obj/item/organ/I in internal_organs) @@ -849,15 +878,14 @@ Note that amputating the affected organ does in fact remove the infection from t if(owner) owner.visible_message(\ - "\red You hear a loud cracking sound coming from \the [owner].",\ - "\red Something feels like it shattered in your [name]!",\ - "You hear a sickening crack.") - if(owner.species && !(owner.species.flags & NO_PAIN)) + "You hear a loud cracking sound coming from \the [owner].",\ + "Something feels like it shattered in your [name]!",\ + "You hear a sickening crack.") + if(!(species.flags & NO_PAIN)) owner.emote("scream") status |= ORGAN_BROKEN broken_description = pick("broken","fracture","hairline fracture") - perma_injury = brute_dam // Fractures have a chance of getting you out of restraints if (prob(25)) @@ -891,26 +919,55 @@ Note that amputating the affected organ does in fact remove the infection from t status &= ~ORGAN_BROKEN return 1 -/obj/item/organ/external/robotize(var/company) +/obj/item/organ/external/robotize(var/company, var/ski) + + if(status & ORGAN_ROBOT) + return + ..() + brute_mod = 0.8 + burn_mod = 0.8 + + brute_mod = 0.8 + burn_mod = 0.8 if(company) model = company var/datum/robolimb/R = all_robolimbs[company] - if(species && (species.name in R.species_cannot_use)) + if(!R || (species && (species.name in R.species_cannot_use))) R = basic_robolimb if(R) force_icon = R.icon - name = "[R.company] [initial(name)]" - desc = "[R.desc]" + name = "robotic [initial(name)]" + desc = "[R.desc] It looks like it was produced by [R.company]." - dislocated = -1 //TODO, make robotic limbs a separate type, remove snowflake + dislocated = -1 cannot_break = 1 get_icon() unmutate() - for (var/obj/item/organ/external/T in children) - if(T) - T.robotize() + + for(var/obj/item/organ/external/T in children) + T.robotize(company, 1) + + if(owner) + + if(!skip_prosthetics) + owner.full_prosthetic = null // Will be rechecked next isSynthetic() call. + + for(var/obj/item/organ/thing in src.contents) + if(istype(thing)) + if(thing.vital) + continue + owner.internal_organs_by_name[thing.organ_tag] = null + owner.internal_organs.Remove(thing) + qdel(thing) + + while(null in owner.internal_organs) + owner.internal_organs -= null + while(null in owner.internal_organs_by_name) + owner.internal_organs -= null + + return 1 /obj/item/organ/external/proc/mutate() if(src.status & ORGAN_ROBOT) @@ -923,7 +980,7 @@ Note that amputating the affected organ does in fact remove the infection from t if(owner) owner.update_body() /obj/item/organ/external/proc/get_damage() //returns total damage - return max(brute_dam + burn_dam - perma_injury, perma_injury) //could use max_damage? + return (brute_dam+burn_dam) //could use max_damage? /obj/item/organ/external/proc/has_infected_wound() for(var/datum/wound/W in wounds) @@ -1012,13 +1069,13 @@ Note that amputating the affected organ does in fact remove the infection from t return if(owner) if(type == "brute") - owner.visible_message("\red You hear a sickening cracking sound coming from \the [owner]'s [name].", \ - "\red Your [name] becomes a mangled mess!", \ - "\red You hear a sickening crack.") + owner.visible_message("You hear a sickening cracking sound coming from \the [owner]'s [name].", \ + "Your [name] becomes a mangled mess!", \ + "You hear a sickening crack.") else - owner.visible_message("\red \The [owner]'s [name] melts away, turning into mangled mess!", \ - "\red Your [name] melts away!", \ - "\red You hear a sickening sizzle.") + owner.visible_message("\The [owner]'s [name] melts away, turning into mangled mess!", \ + "Your [name] melts away!", \ + "You hear a sickening sizzle.") disfigured = 1 /obj/item/organ/external/proc/get_wounds_desc() @@ -1098,6 +1155,12 @@ Note that amputating the affected organ does in fact remove the infection from t parent_organ = null encased = "ribcage" +/obj/item/organ/external/chest/robotize() + if(..()) + // Give them a new cell. + owner.internal_organs_by_name["cell"] = new /obj/item/organ/cell(owner,1) + + /obj/item/organ/external/groin name = "lower body" limb_name = "groin" @@ -1224,6 +1287,8 @@ Note that amputating the affected organ does in fact remove the infection from t gendered_icon = 1 encased = "skull" + var/eye_icon = "eyes_s" + /obj/item/organ/external/head/removed() if(owner) name = "[owner.real_name]'s head" @@ -1244,3 +1309,32 @@ Note that amputating the affected organ does in fact remove the infection from t disfigure("brute") if (burn_dam > 40) disfigure("burn") + +/obj/item/organ/external/head/skrell + eye_icon = "skrell_eyes_s" + +/obj/item/organ/external/head/resomi + eye_icon = "eyes_resomi" + +/obj/item/organ/external/head/vox + eye_icon = "vox_eyes_s" + +/obj/item/organ/external/head/no_eyes + eye_icon = "blank_eyes" + +/obj/item/organ/external/head/no_eyes/diona + max_damage = 50 + min_broken_damage = 25 + cannot_break = 1 + amputation_point = "branch" + joint = "structural ligament" + dislocated = -1 + vital = 0 + +/obj/item/organ/external/head/no_eyes/diona/removed() + var/mob/living/carbon/human/H = owner + ..() + if(!istype(H) || !H.organs || !H.organs.len) + H.death() + if(prob(50) && spawn_diona_nymph(get_turf(src))) + qdel(src) \ No newline at end of file diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm index bcc8de7694..4faa796107 100644 --- a/code/modules/organs/organ_icon.dm +++ b/code/modules/organs/organ_icon.dm @@ -53,10 +53,10 @@ var/global/list/limb_icon_cache = list() overlays.Cut() if(!owner || !owner.species) return - if(owner.species.has_organ["eyes"]) + if(owner.should_have_organ("eyes")) var/obj/item/organ/eyes/eyes = owner.internal_organs_by_name["eyes"] - if(species.eyes) - var/icon/eyes_icon = new/icon('icons/mob/human_face.dmi', species.eyes) + if(eye_icon) + var/icon/eyes_icon = new/icon('icons/mob/human_face.dmi', eye_icon) if(eyes) eyes_icon.Blend(rgb(eyes.eye_colour[1], eyes.eye_colour[2], eyes.eye_colour[3]), ICON_ADD) else @@ -91,7 +91,7 @@ var/global/list/limb_icon_cache = list() var/gender if(force_icon) - mob_icon = new /icon(force_icon, "[icon_name]") + mob_icon = new /icon(force_icon, "[icon_name][gendered_icon ? "_f" : ""]") else if(!dna) mob_icon = new /icon('icons/mob/human_races/r_human.dmi', "[icon_name][gendered_icon ? "_f" : ""]") diff --git a/code/modules/organs/organ_internal.dm b/code/modules/organs/organ_internal.dm index 39a8a142cf..cfd7ec78f7 100644 --- a/code/modules/organs/organ_internal.dm +++ b/code/modules/organs/organ_internal.dm @@ -70,6 +70,13 @@ parent_organ = "head" var/list/eye_colour = list(0,0,0) +/obj/item/organ/eyes/robotize() + ..() + name = "optical sensor" + icon = 'icons/obj/robot_component.dmi' + icon_state = "camera" + dead_icon = "camera_broken" + /obj/item/organ/eyes/proc/update_colour() if(!owner) return @@ -109,7 +116,7 @@ if (germ_level > INFECTION_LEVEL_ONE) if(prob(1)) - owner << "\red Your skin itches." + owner << "Your skin itches." if (germ_level > INFECTION_LEVEL_TWO) if(prob(1)) spawn owner.vomit() diff --git a/code/modules/organs/pain.dm b/code/modules/organs/pain.dm index e4e024be10..280ea53f49 100644 --- a/code/modules/organs/pain.dm +++ b/code/modules/organs/pain.dm @@ -8,9 +8,9 @@ mob/var/next_pain_time = 0 // partname is the name of a body part // amount is a num from 1 to 100 mob/living/carbon/proc/pain(var/partname, var/amount, var/force, var/burning = 0) - if(stat >= 1) + if(stat >= 1) return - if(species && (species.flags & NO_PAIN)) + if(!can_feel_pain()) return if(analgesic > 40) return @@ -25,13 +25,13 @@ mob/living/carbon/proc/pain(var/partname, var/amount, var/force, var/burning = 0 if(burning) switch(amount) if(1 to 10) - msg = "\red Your [partname] burns." + msg = "Your [partname] burns." if(11 to 90) flash_weak_pain() - msg = "\red Your [partname] burns badly!" + msg = "Your [partname] burns badly!" if(91 to 10000) flash_pain() - msg = "\red OH GOD! Your [partname] is on fire!" + msg = "OH GOD! Your [partname] is on fire!" else switch(amount) if(1 to 10) @@ -51,9 +51,9 @@ mob/living/carbon/proc/pain(var/partname, var/amount, var/force, var/burning = 0 // message is the custom message to be displayed // flash_strength is 0 for weak pain flash, 1 for strong pain flash mob/living/carbon/human/proc/custom_pain(var/message, var/flash_strength) - if(stat >= 1) + if(stat >= 1) return - if(species.flags & NO_PAIN) + if(!can_feel_pain()) return if(reagents.has_reagent("tramadol")) return @@ -61,9 +61,9 @@ mob/living/carbon/human/proc/custom_pain(var/message, var/flash_strength) return if(analgesic) return - var/msg = "\red [message]" + var/msg = "[message]" if(flash_strength >= 1) - msg = "\red [message]" + msg = "[message]" // Anti message spam checks if(msg && ((msg != last_pain_message) || (world.time >= next_pain_time))) @@ -74,7 +74,7 @@ mob/living/carbon/human/proc/custom_pain(var/message, var/flash_strength) mob/living/carbon/human/proc/handle_pain() // not when sleeping - if(species.flags & NO_PAIN) return + if(!can_feel_pain()) return if(stat >= 2) return if(analgesic > 70) diff --git a/code/modules/organs/robolimbs.dm b/code/modules/organs/robolimbs.dm index 774f7a5261..47ae475735 100644 --- a/code/modules/organs/robolimbs.dm +++ b/code/modules/organs/robolimbs.dm @@ -41,4 +41,3 @@ var/global/datum/robolimb/basic_robolimb company = "Morpheus Cyberkinetics" desc = "This limb is simple and functional; no effort has been made to make it look human." icon = 'icons/mob/human_races/cyberlimbs/ipc.dmi' - unavailable_at_chargen = 1 diff --git a/code/modules/organs/subtypes/diona.dm b/code/modules/organs/subtypes/diona.dm index edef9801c5..5d77383d2a 100644 --- a/code/modules/organs/subtypes/diona.dm +++ b/code/modules/organs/subtypes/diona.dm @@ -122,22 +122,6 @@ body_part = HAND_RIGHT parent_organ = "r_arm" -/obj/item/organ/external/diona/head - limb_name = "head" - icon_name = "head" - name = "head" - max_damage = 50 - min_broken_damage = 25 - w_class = 3 - body_part = HEAD - parent_organ = "chest" - -/obj/item/organ/external/diona/head/removed() - if(owner) - owner.u_equip(owner.head) - owner.u_equip(owner.l_ear) - ..() - //DIONA ORGANS. /obj/item/organ/external/diona/removed() var/mob/living/carbon/human/H = owner diff --git a/code/modules/organs/subtypes/machine.dm b/code/modules/organs/subtypes/machine.dm index fd94c2c759..3d551a3760 100644 --- a/code/modules/organs/subtypes/machine.dm +++ b/code/modules/organs/subtypes/machine.dm @@ -1,77 +1,3 @@ -// IPC limbs. -/obj/item/organ/external/head/ipc - dislocated = -1 - can_intake_reagents = 0 - vital = 0 - max_damage = 50 //made same as arm, since it is not vital - min_broken_damage = 30 - encased = null - -/obj/item/organ/external/head/ipc/New() - robotize("Morpheus Cyberkinetics") - ..() - -/obj/item/organ/external/chest/ipc - dislocated = -1 - encased = null -/obj/item/organ/external/chest/ipc/New() - robotize("Morpheus Cyberkinetics") - ..() - -/obj/item/organ/external/groin/ipc - dislocated = -1 -/obj/item/organ/external/groin/ipc/New() - robotize("Morpheus Cyberkinetics") - ..() - -/obj/item/organ/external/arm/ipc - dislocated = -1 -/obj/item/organ/external/arm/ipc/New() - robotize("Morpheus Cyberkinetics") - ..() - -/obj/item/organ/external/arm/right/ipc - dislocated = -1 -/obj/item/organ/external/arm/right/ipc/New() - robotize("Morpheus Cyberkinetics") - ..() - -/obj/item/organ/external/leg/ipc - dislocated = -1 -/obj/item/organ/external/leg/ipc/New() - robotize("Morpheus Cyberkinetics") - ..() - -/obj/item/organ/external/leg/right/ipc - dislocated = -1 -/obj/item/organ/external/leg/right/ipc/New() - robotize("Morpheus Cyberkinetics") - ..() - -/obj/item/organ/external/foot/ipc - dislocated = -1 -/obj/item/organ/external/foot/ipc/New() - robotize("Morpheus Cyberkinetics") - ..() - -/obj/item/organ/external/foot/right/ipc - dislocated = -1 -/obj/item/organ/external/foot/right/ipc/New() - robotize("Morpheus Cyberkinetics") - ..() - -/obj/item/organ/external/hand/ipc - dislocated = -1 -/obj/item/organ/external/hand/ipc/New() - robotize("Morpheus Cyberkinetics") - ..() - -/obj/item/organ/external/hand/right/ipc - dislocated = -1 -/obj/item/organ/external/hand/right/ipc/New() - robotize("Morpheus Cyberkinetics") - ..() - /obj/item/organ/cell name = "microbattery" desc = "A small, powerful cell for use in fully prosthetic bodies." @@ -92,34 +18,59 @@ owner.stat = 0 owner.visible_message("\The [owner] twitches visibly!") -/obj/item/organ/optical_sensor - name = "optical sensor" - organ_tag = "eyes" - parent_organ = "head" - icon = 'icons/obj/robot_component.dmi' - icon_state = "camera" - dead_icon = "camera_broken" - -/obj/item/organ/optical_sensor/New() - robotize() - ..() - // Used for an MMI or posibrain being installed into a human. /obj/item/organ/mmi_holder name = "brain" organ_tag = "brain" - parent_organ = "chest" + parent_organ = "head" vital = 1 var/obj/item/device/mmi/stored_mmi +/obj/item/organ/mmi_holder/Destroy() + stored_mmi = null + return ..() + +/obj/item/organ/mmi_holder/New() + ..() + if(!stored_mmi) + stored_mmi = new(src) + + spawn(1) + + if(!owner) + if(stored_mmi) + stored_mmi.loc = get_turf(src) + qdel(src) + return + + update_from_mmi() + if(stored_mmi.brainmob && owner && owner.stat == DEAD) + owner.stat = 0 + owner.visible_message("\The [owner] twitches visibly!") + /obj/item/organ/mmi_holder/proc/update_from_mmi() + if(!stored_mmi) return + + if(!stored_mmi.brainmob) + stored_mmi.brainmob = new(src) + + stored_mmi.brainmob.real_name = owner.name + stored_mmi.brainmob.name = stored_mmi.brainmob.real_name + + if(owner) + stored_mmi.name = "[initial(stored_mmi.name)] ([owner.name])" + name = stored_mmi.name desc = stored_mmi.desc icon = stored_mmi.icon icon_state = stored_mmi.icon_state +/obj/item/organ/mmi_holder/removed() + update_from_mmi() + return ..() + /obj/item/organ/mmi_holder/removed(var/mob/living/user) if(stored_mmi) @@ -133,25 +84,9 @@ holder_mob.drop_from_inventory(src) qdel(src) -/obj/item/organ/mmi_holder/New() - ..() - // This is very ghetto way of rebooting an IPC. TODO better way. - spawn(1) - if(owner && owner.stat == DEAD) - owner.stat = 0 - owner.visible_message("\The [owner] twitches visibly!") +/obj/item/organ/mmi_holder/posibrain + name = "positronic brain" /obj/item/organ/mmi_holder/posibrain/New() - robotize() stored_mmi = new /obj/item/device/mmi/digital/posibrain(src) ..() - spawn(1) - if(owner) - stored_mmi.name = "positronic brain ([owner.name])" - stored_mmi.brainmob.real_name = owner.name - stored_mmi.brainmob.name = stored_mmi.brainmob.real_name - stored_mmi.icon_state = "posibrain-occupied" - update_from_mmi() - else - stored_mmi.loc = get_turf(src) - qdel(src) \ No newline at end of file diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 25c8c4827f..12c48a7826 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -119,6 +119,7 @@ By design, d1 is the smallest direction and d2 is the highest // - Cable coil : merge cables // - Multitool : get the power currently passing through the cable // + /obj/structure/cable/attackby(obj/item/W, mob/user) var/turf/T = src.loc @@ -512,14 +513,18 @@ obj/structure/cable/proc/cableColor(var/colorC) /////////////////////////////////// //you can use wires to heal robotics +/obj/item/stack/cable_coil/attack(var/atom/A, var/mob/living/user, var/def_zone) + if(ishuman(A) && user.a_intent == I_HELP) + return + return ..() + /obj/item/stack/cable_coil/afterattack(var/mob/M, var/mob/user) if(ishuman(M)) var/mob/living/carbon/human/H = M var/obj/item/organ/external/S = H.organs_by_name[user.zone_sel.selecting] - if (!S) return - if(!(S.status & ORGAN_ROBOT) || user.a_intent != I_HELP) + if(!S || !(S.status & ORGAN_ROBOT) || user.a_intent != I_HELP) return ..() if(S.burn_dam) @@ -528,10 +533,9 @@ obj/structure/cable/proc/cableColor(var/colorC) user.visible_message("\The [user] repairs some burn damage on \the [M]'s [S.name] with \the [src].") else if(S.open != 2) user << "The damage is far too severe to patch over externally." - return 1 else if(S.open != 2) user << "Nothing to fix!" - + return else return ..() diff --git a/code/modules/projectiles/projectile/change.dm b/code/modules/projectiles/projectile/change.dm index c643e94dcc..45e8910b38 100644 --- a/code/modules/projectiles/projectile/change.dm +++ b/code/modules/projectiles/projectile/change.dm @@ -67,9 +67,13 @@ if(M.gender == MALE) H.gender = MALE H.name = pick(first_names_male) - else + else if(M.gender == FEMALE) H.gender = FEMALE H.name = pick(first_names_female) + else + H.gender = NEUTER + H.name = pick(first_names_female|first_names_male) + H.name += " [pick(last_names)]" H.real_name = H.name diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm index 4ed12a2846..f13c216945 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm @@ -70,8 +70,10 @@ infect_virus2(M, V.getcopy()) /datum/reagent/blood/affect_touch(var/mob/living/carbon/M, var/alien, var/removed) - if(alien == IS_MACHINE) - return + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.check_is_prosthetic()) + return if(data && data["viruses"]) for(var/datum/disease/D in data["viruses"]) if(D.spread_type == SPECIAL || D.spread_type == NON_CONTAGIOUS) diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm index 87897fd9a8..88f314c99d 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm @@ -328,7 +328,7 @@ if(affecting.take_damage(0, removed * power * 0.1)) H.UpdateDamageIcon() if(prob(100 * removed / meltdose)) // Applies disfigurement - if (!(H.species && (H.species.flags & NO_PAIN))) + if (affecting.can_feel_pain()) H.emote("scream") H.status_flags |= DISFIGURED else diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm index 0bfa1b4006..6c169852b9 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm @@ -233,12 +233,13 @@ M.adjustToxLoss(0.5 * removed) /datum/reagent/capsaicin/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed) - if(alien == IS_DIONA || alien == IS_MACHINE) + if(alien == IS_DIONA) return if(ishuman(M)) var/mob/living/carbon/human/H = M - if(H.species && (H.species.flags & (NO_PAIN))) + if(!H.can_feel_pain()) return + if(dose < 5 && (dose == metabolism || prob(5))) M << "Your insides feel uncomfortably hot!" if(dose >= 5) @@ -268,7 +269,7 @@ var/obj/item/safe_thing = null if(istype(M, /mob/living/carbon/human)) var/mob/living/carbon/human/H = M - if(H.species && (H.species.flags & NO_PAIN)) + if(!H.can_feel_pain()) return if(H.head) if(H.head.body_parts_covered & EYES) @@ -314,7 +315,7 @@ /datum/reagent/condensedcapsaicin/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed) if(ishuman(M)) var/mob/living/carbon/human/H = M - if(H.species && (H.species.flags & (NO_PAIN))) + if(!H.can_feel_pain()) return if(dose == metabolism) M << "You feel like your insides are burning!" diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm index 1c4abbdfe8..b392e789e0 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm @@ -274,7 +274,7 @@ var/mob/living/carbon/human/H = M for(var/obj/item/organ/I in H.internal_organs) - if((I.damage > 0) && (I.robotic != 2)) //Peridaxon heals only non-robotic organs + if((I.damage > 0) && !(I.status & ORGAN_ROBOT)) //Peridaxon heals only non-robotic organs I.damage = max(I.damage - removed, 0) /datum/reagent/ryetalyn diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm index d981734ec9..3de830f644 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm @@ -234,9 +234,14 @@ affect_blood(M, alien, removed) /datum/reagent/mutagen/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) + + if(M.isSynthetic()) + return + var/mob/living/carbon/human/H = M if(istype(H) && (H.species.flags & NO_SCAN)) return + if(M.dna) if(prob(removed * 0.1)) // Approx. one mutation per 10 injected/20 ingested/30 touching units randmuti(M) diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index 19ac8c62fb..75ef62894d 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -96,7 +96,7 @@ var/datum/reagent/B if(istype(T, /mob/living/carbon/human)) var/mob/living/carbon/human/H = T - if(H.species && H.species.flags & NO_BLOOD) + if(H.species && !H.should_have_organ("heart")) H.reagents.trans_to_obj(src, amount) else B = T.take_blood(src, amount) diff --git a/code/modules/surgery/bones.dm b/code/modules/surgery/bones.dm index 25addbd40a..823561b5d8 100644 --- a/code/modules/surgery/bones.dm +++ b/code/modules/surgery/bones.dm @@ -142,7 +142,6 @@ affected.status &= ~ORGAN_BROKEN affected.status &= ~ORGAN_SPLINTED affected.stage = 0 - affected.perma_injury = 0 fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/organ/external/affected = target.get_organ(target_zone) diff --git a/code/modules/surgery/generic.dm b/code/modules/surgery/generic.dm index d1becd0cbf..0fef3de54c 100644 --- a/code/modules/surgery/generic.dm +++ b/code/modules/surgery/generic.dm @@ -51,9 +51,6 @@ //Could be cleaner ... affected.open = 1 - if(istype(target) && !(target.species.flags & NO_BLOOD)) - affected.status |= ORGAN_BLEEDING - affected.createwound(CUT, 1) affected.clamp() spread_germs_to_organ(affected, user) @@ -91,7 +88,7 @@ "\blue You have constructed a prepared incision on and within [target]'s [affected.name] with \the [tool].",) affected.open = 1 - if(istype(target) && !(target.species.flags & NO_BLOOD)) + if(istype(target) && target.should_have_organ("heart")) affected.status |= ORGAN_BLEEDING affected.createwound(CUT, 1) @@ -133,7 +130,7 @@ "\blue You have made an incision on [target]'s [affected.name] with \the [tool].",) affected.open = 1 - if(istype(target) && !(target.species.flags & NO_BLOOD)) + if(istype(target) && target.should_have_organ("heart")) affected.status |= ORGAN_BLEEDING affected.createwound(CUT, 1) diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm index f0025b7429..e074cbcca5 100644 --- a/code/modules/surgery/organs_internal.dm +++ b/code/modules/surgery/organs_internal.dm @@ -91,7 +91,7 @@ for(var/obj/item/organ/I in affected.internal_organs) if(I && I.damage > 0) - if(I.robotic < 2) + if(!(I.status & ORGAN_ROBOT)) user.visible_message("[user] starts treating damage to [target]'s [I.name] with [tool_name].", \ "You start treating damage to [target]'s [I.name] with [tool_name]." ) @@ -111,7 +111,7 @@ for(var/obj/item/organ/I in affected.internal_organs) if(I && I.damage > 0) - if(I.robotic < 2) + if(!(I.status & ORGAN_ROBOT)) user.visible_message("[user] treats damage to [target]'s [I.name] with [tool_name].", \ "You treat damage to [target]'s [I.name] with [tool_name]." ) I.damage = 0 @@ -285,7 +285,7 @@ if(O.organ_tag == "limb") return 0 - else if(target.species.has_organ[O.organ_tag]) + else if(target.should_have_organ(O.organ_tag)) if(O.damage > (O.max_damage * 0.75)) user << "\The [O.organ_tag] [o_is] in no state to be transplanted." diff --git a/code/modules/surgery/robotics.dm b/code/modules/surgery/robotics.dm index 24bc848472..1ad2aec24f 100644 --- a/code/modules/surgery/robotics.dm +++ b/code/modules/surgery/robotics.dm @@ -212,7 +212,7 @@ if(!affected) return var/is_organ_damaged = 0 for(var/obj/item/organ/I in affected.internal_organs) - if(I.damage > 0 && I.robotic >= 2) + if(I.damage > 0 && (I.status & ORGAN_ROBOT)) is_organ_damaged = 1 break return affected.open == 2 && is_organ_damaged @@ -225,7 +225,7 @@ for(var/obj/item/organ/I in affected.internal_organs) if(I && I.damage > 0) - if(I.robotic >= 2) + if(I.status & ORGAN_ROBOT) user.visible_message("[user] starts mending the damage to [target]'s [I.name]'s mechanisms.", \ "You start mending the damage to [target]'s [I.name]'s mechanisms." ) @@ -241,7 +241,7 @@ for(var/obj/item/organ/I in affected.internal_organs) if(I && I.damage > 0) - if(I.robotic >= 2) + if(I.status & ORGAN_ROBOT) user.visible_message("[user] repairs [target]'s [I.name] with [tool].", \ "You repair [target]'s [I.name] with [tool]." ) I.damage = 0 @@ -393,7 +393,7 @@ user << "You have no idea what species this person is. Report this on the bug tracker." return SURGERY_FAILURE - if(!target.species.has_organ["brain"]) + if(!target.should_have_organ("brain")) user << "You're pretty sure [target.species.name_plural] don't normally have a brain." return SURGERY_FAILURE diff --git a/code/modules/virus2/admin.dm b/code/modules/virus2/admin.dm index dad0a30925..b36da37d6f 100644 --- a/code/modules/virus2/admin.dm +++ b/code/modules/virus2/admin.dm @@ -87,7 +87,7 @@ var/f = 1 for(var/k in all_species) var/datum/species/S = all_species[k] - if(S.virus_immune) + if(S.get_virus_immune()) continue if(!f) H += " | " else f = 0 diff --git a/code/modules/virus2/disease2.dm b/code/modules/virus2/disease2.dm index 81a57dd300..b6e56d231b 100644 --- a/code/modules/virus2/disease2.dm +++ b/code/modules/virus2/disease2.dm @@ -45,7 +45,7 @@ var/list/res = list() for (var/specie in all_species) var/datum/species/S = all_species[specie] - if(!S.virus_immune) + if(!S.get_virus_immune()) meat += S if(meat.len) var/num = rand(1,meat.len) @@ -71,7 +71,7 @@ // Some species are flat out immune to organic viruses. var/mob/living/carbon/human/H = mob - if(istype(H) && H.species.virus_immune) + if(istype(H) && H.species.get_virus_immune(H)) cure(mob) return diff --git a/code/modules/virus2/helpers.dm b/code/modules/virus2/helpers.dm index 1cd185a32b..4daae5c5e2 100644 --- a/code/modules/virus2/helpers.dm +++ b/code/modules/virus2/helpers.dm @@ -4,7 +4,7 @@ proc/infection_check(var/mob/living/carbon/M, var/vector = "Airborne") return 0 var/mob/living/carbon/human/H = M - if(istype(H) && H.species.virus_immune) + if(istype(H) && H.species.get_virus_immune(H)) return 0 var/protection = M.getarmor(null, "bio") //gets the full body bio armour value, weighted by body part coverage. diff --git a/code/modules/virus2/items_devices.dm b/code/modules/virus2/items_devices.dm index d318ca9f8a..69ede1d494 100644 --- a/code/modules/virus2/items_devices.dm +++ b/code/modules/virus2/items_devices.dm @@ -16,7 +16,7 @@ var/mob/living/carbon/C = M if (istype(C,/mob/living/carbon/human/)) var/mob/living/carbon/human/H = C - if(H.species.flags & NO_BLOOD) + if(!H.should_have_organ("heart")) report("Scan aborted: The target does not have blood.", user) return diff --git a/icons/mob/human_races/cyberlimbs/bishop.dmi b/icons/mob/human_races/cyberlimbs/bishop.dmi index 045c3a57249b655882152b59c2144fcae83e2a2c..ebc132f554fa1f0118f3e25323a07e59c1191e90 100644 GIT binary patch delta 1397 zcmY*Wdpy$%6yMZE9@&*gxOr4FkGiHO(k9n#wyxLcTKZ^}>{`ma(!BPQqMN)Q@$s6` zP-q%MF~)kh9@X*kW+A3Q?En^w)zQ(>+S%14D_V01$|r zpVa?Mi3?YWnHZ%gWz5ls$LRa-sC1d{zCFDyUGYj^GbKc&08@+pJYxVP`U|f$Qs7+` z!=$40pkrzw$O4x5N)Pc|fM=EZR1O)hbRyojvfU=vtSYLMsZZ2wcdG8rrs|>+t_9a< zzi>#LQ*?u5m@vU3VtApgJZVCo*WZjJ~_wlpNG}!~tAWM3q>4S!#*tYd3+Jj083Zc1*FyP#p{zQVYhnfwwJVDnOhdzYMhPt?Dfw#5tx63BtM;E-?!H1_g=2WNdg@ zq=^^^YmSpf^EHnY@yu2Kv5BUv6YtP0%o^BPB${mAyOro<8fV)cJyTPrAt5fJRs)%_ z0}(CpK;J3Hh0kY+ocaw@6yOzgSl7_JfuT?V?%WsHGzZ5S(`q0P@IOH$-QmAwJ9+q$fQWFtIIjc3R48Ui2kfz9 zbrL-)_azcnA1$WMO`Um3?PnpCZ5<@VQCC6S@vhzSuc|}bh%xg|-{Y|{kuaPJuM91i?5TW(D3g6#A==xouaEHmMa8T{8CsZJ&A4{Zu_Xq-O=6fN}R zzzf+r(?e3kPB%UE;^&=Lv2bb+o+Zn%sZ>F~E$_KiPwg?^;k8cMNL^Ndau%&^{qx9C ze+k3SwXkG_h&ugD@BpB-??zr)ibxpln^Z5V-=Q}dJu(hd``xwo|MnVk1+FCr=Q=E~ z8d<56PL_`!vYd4@fO|6}H#Hhjd8J>61FtTo5b;t&!B z*;XrZQPsUHhMXV=6b(%X)ic#g+vY50>sP3|5}ClM(A5bTSt6=NaYW~v wCp<>0zX+eWnk%zzg_1g0qOb4#YDGgB1st53kkntoncW(oQO*ue>@UXt3yE)(!vFvP delta 901 zcmV;01A6?T3$_O(iBL{Q4GJ0x0000DNk~Le0002M0002M2m=5B0A&K4H2?qrRFNe> zf5E}QwY9a%%F4sT!@Rt_udlCISXjWo!1QC=-~a#s0d!JMQvg8b*k%9#0FHW8Sad{X zb7OL8aCB*JZU6vyoKseCa&`CgQ*iP1Q`~Iik%5O8Mscr1uwB?md6pW&@>sYkjiI zfemEkOAcfN^UdsGAE_<-p`6iX1BHBZeZyf46c`W14IIWs8~B-Tu20fqpunT{UmOVu z<(tt@&!Gy>PYpsM`R$?s00000e*kc$R#Sjmkq2cwuoa?A2R1_@lY})=h6CFn<>A0~ zNO?H09p%|T>L&k$WSqKG{Jb6#8Nt*PX9MFj2R1NIeev^pNUIGL9bY7{0eLxI5mJ1n znPVhgyEzmB000000002^L!o~k>;KoY|7x53Qe^(I+CJ3(k7c)4=--F>fB&^6xi%YU ztI(%!*1Fe&oJaB2J0$g;#ar>5U3$spO?kz0_MDSr18G|A28O-kB%n;|eT7^H>12Lg z?FP=TkYfXBUhM`Xd0wG;y{`}e000000B*!?t$J=#`}b!5e{ubsPhFDY>5z+FQg_Pr zI(q-!?Ef#XpL?VGe!kq-f7f5>-`oBF#r1Pa^}lcazN5YdJwYa`|G&7tyyf~Sw_%^( zjGqkD6U3ZNEUqu_#woYqFuofb&=cg<>WnY0FCX?-_+f0I@(P)q@x}F}GiD6u-sQKoz@>@0ByzO$avH`n>dW&;?000000001h?J*ksz7fJLRU7=C_WrF^8~mR3 b{y+B%B()QTrkVi^00000NkvXXu0mjfE#0Pg diff --git a/icons/mob/human_races/cyberlimbs/hesphaistos.dmi b/icons/mob/human_races/cyberlimbs/hesphaistos.dmi index 5fbcd15861956af7ea2f167b7e7127212dfa8d89..225b18f5b9cf32ed5839d49c3ae5c441281d1383 100644 GIT binary patch delta 1386 zcmYjPc~H`M6vt~l8%#`Ab0iB|bv;nq%FJU)^PoT!C2NF6OC!Z&D@POgsU4K2iAOr7 zA(_(UMN%nVrEY4YWZ}sg+GU=ZBqa{~7HX#H{qeq^_jxm)&wFpaT-_2w)a4+Y-v$E< z0|*4NA;8}!7y{8yLCBPzmMV+c{*kK3mxXe6u(Y&PK_ZbzB9ZWTd~|d)27|G)vooWH zY*jThP6y*cAl@IwqE*EmRuT-zec5c#g*M8V9%mR7E>w?BR3pzD4gC50x%XNHddG&^ z8K;aY0-FMsXAxIorEvlVdf?t@LS;eHPUtDG3cmc9kQyFOsx^66nnE#fzj*w9@18Qd zT6zu7in^)yV8dVu+rl?H?w<$nZl5a)dIaM_8=eMB$9ZGat*o7Tlb;2E@6)}8X9ey{ zs6=wUcuaDbHo+Nh7s17E?si*;%|C-cw6Os`e-l&67t6)huJ1PXjWC1n+hg8906}gZ z`bKIa5oO-`4w?2f(8?xhurcUC3+FHwrrHkDDal)~vRyNA`iMZ@IAA*yclp#-PHdjO z`LI(jcWZ7=&1qU;EilyN=s4ti6%Kpl)W?0(k|I|IFFPd8Mlr?DtJ9r}YbgbI6pI)8 zR%+72r@`I!7M(DigTH^!&Fr1#oLFsftZ`0Wx}A@gA73NVMsrzRQHY3PeYqzmDX2e2 z!J}I^ZhWnB*f5ub-_m&pQO_ocG zWd3!z2YNMv@?x9F@4CG`EAHGSMtHl+;y|VCi4_=?ys?j+p*A@_A^yy%e1x;^4KyQmn!m@3ZJo=eS7|=#Sg&1x*RbEkj)%n%ehP4vXV76&Z>(%v`f0Un(%LV zTXqp4p4K^AtR2xIlYfNekEk0Z&Q)ocr#7g}u=GP8*%U&9bny#9*wzLkirG~M_aA}q znywIrm@;hI< zLxu~gBLweOYj~LIxJz&#c78!|_bm7RKCW7T8DzRZ*Zrpc^S?wVBDd-0uJOrP^go|^CVa;gp#~n^)%uGv!;L$O_9v&;OMLvV1k8O(VyCqb+)tex1=+c z;e`G(ibvYnK&d2A2WYZ2(x=Nc>qf@_9_W$zrlXGI8xnyqO%qE!lTZK!59J*R!m zZ+t@e%cUU8;-hVDY0~R_xiSpQoM1Ob0(ASJUJpWhuxR1^sZxLy(&O$kSG9#B3XXz`s?&Acw!@D`+)^ zNr;E*(Bv~VBAKq*JHu!GbfA^u;^m6>5`JFXipu-b)ME~%QS-#)m+i9iFe?~sJ ULB!W|h@pxK@WuJmVUA|~4=W~*Y5)KL delta 901 zcmbQvy_{XOGr-TCmrII^fq{Y7)59eQNFM-U4rU;k$~4CmNEuI5HLO2y;DC&b%+k$K zy+9Ghk|4ie28U-i(tw=4s*s2hm(=3qqRfJl%=|nChKf1CVFg8{-@gPGeEj-E%Uf6L z+?n&i8$t~(8b5fXbKXbuBtub8?+y#&Amhu%UJ7#_O*%3uL?L*khTTSu@Xl^y)y*p; zmH_Fs8iwYgN6cJSoKmd!3Jt7rON!$XY!h6%M#E0sbS}r?j=)fn`P1gdJGCVKn4+n@ zZf;c8~DwQoDru7^o(-LU1jI`BeFlkDrW3bpP^-Z!X}M9Yv0y-yUyb8EX5+W zN-O(!Xa0Ql>(iqj9J-O!7JA-q&V6_m{n|UQK0H(?IY=(fR`Og;aqa5Yue_tCx_eJD zln(fG_UqI&by`|QdR503@cubxem(rjS;K>~Go*LK++W`(5Wa7x-SaEg%kOvXse9UA zl?`+U5EN_=T+ZOmxp_`C`y{sd(hKgAWn2X!oq?~fop)AQdG$+XN1eq3izhifwa4bO z{}ouU0hoUPI9|;8(Hs@bDHs$cZ;*!uEq^k=QkG?mZ<@Q?9;(WXSo*x~ZWy9 zgXi6z{FS%lOyJq~G4c?T7#`HDY1;pu=b^*)vVWUD<@oQf-wu|k9k?i|SKUBCaP^WaC<3lTPc z;XYybkO+J*5d?}Uy4lkNZ9k%#FftGi&6y(e2FYKhsB#YONfv>#m3+CZ_;A(Y(+upK z7@6_I;+2;8BOD4Z_+ECXDLfog+$i(y#(NOY*CNIWVmzU!R6ptqi^2o7v6TQ#2fyou zV|`bCsitlEl`y)-uQnM|N@vw__R|z@Z!_BAQ;}q<^me|*_Sp%QA6rl}dLfsx`2B)! z34`|sSiKtjKWcvc++Fe<1ls0`wK?e;Q#4(Ck;FGuy{3HB^+D*+0=J`~SiaF}?u|meg_lZ`hBFkWR$SCsMv2)=b&}4eA;S%Rz=7*1<3|LYLMf#cQU}(t7(-f3T*Gusa?@66lr z>h9Bb4SAkxmP^I=@3JhnFfeFNEa=0m_?P}N2oX8@dSZSf{IB(Y;`+DdyCw~> zfXY-Cq>xtGk(Sp}S?l}L;Tm{gejye?2{^1~_R^`>|D|(6pD+uXng;Kz9E_EJJW=5&s5`#JvW}04+yU@Dv zO9RnHy3d#AH9gdtd^v#Sz^y2dQ$?vm^r zE&x8}pOF|8yu83&vs}NlTlv`I{&P8J&Iw8i-COXqGQ&Lh`0PS}L;uo$cK7jOEh73L zs_#Q03B3?11%9DyiQ6^0n)gA0m5}G1ECW>mLkrtXfKm(--R3-e58alzF*V2s1${M54~I9XKj;#MqH$eR1^0sg&}@Vc$pS{N~9U z@5vroB4~jm$ZS`8;)F(fTcF%x#F*S!5H(WdLVE~O*Yo2~=U8ETV;fc+CrY(0yv7xc zK?~@{Un~A@bcg5xgnHpx8itaG*=K%W?KgKo+5-}v!GIf*7D;$$r2p0DB*J`%yzhvu z+coG(CzqVQqXd6-egF5@}=SmybQv zJE896z61W@L@6^WN{51+q(_=+_9Api(b6$Y>G6)0z&PaguJL+LpuWcXG6VgourNFu zHxYWLy6H=D8Spl%&O2(ID>Is1Ue)R&T=8Zb>09C=9i1`;`On@lj~FQ1Ng!;J|1iY_ zkt@!ES3C!FpL+=7P^@vyo0CP|fpROn(Y>xcuM*)9>Dkfni$7mTCt4+WTaiWuf$}!S z9_OmuiI}XFk!pcYUz>zN6n<#beB>r?7FG@?*C?QML{P0;9qf+7U}jA#m2Dyz5dW4h zn(lx`qbx3Awl0(J%&;9KajEe!k65jji&q1K(4w6CPh~t{DM}*K*@z95&u_PrpcI>@ iYAw>ZvVUf~vUN>`xNhj~78Zd27{uD*Y#v&BCH)DoCmFf` delta 1643 zcmV-x29)`=4YUm(s00001bW%=J06^y0W&i*HpL$eSbVOxyV{&P5bZKvH004NLjnO>{!!Qg5 z;MqQfN%qpewM$6|8Ja5?gB9D5SRjk$`bpZMQ;9Y``1C-iHqW-}2h+TI{RS!tvw4{N z>8#a~JjX5Eu3AM%A@VmAb`0BCk##gze_HuOWna>2Bsar8UwDYDUJFDMf+vJ(VB znM9Et5m`_sVvJPqP(^UZM+U-_|Eb!vL-YCS3MZF_MqX2bCIA2hT1iAfRCt{2om*qu zC=i7;)1abKb(6SFVmtf)|K@_ceQ3;Ftc!!)^R;~`XqaPUWa$9vIsgCw007WFf5hDv zN3|~rH>454DQ)EphkVbG*}e2px0Aq}H1gaM~oikxCx5_MpqUq0}o<8k1jRz&OQ>vAUN@pFFB*@Hq<YMH%4qO>y(|C#0000000000004gt59EIW ze3S4{wdd{!9*6rDm=)f+z=0Pzsm=4$`K(@zb)4R<+I(KzgMxo(vZP&Je>gM}UF09u zFEu%cru>2i&f*g}EqJlWyB5#zpmc$)J8)kYnACIE-N0}@ z(S-V?wlmS_t~*M-O|;4YJyyN}#Qyw*s2B90)K*-_+^@#JAU^;A00000000000002s zwzzMDx1bqyeD2NN9$FW2f4YNNCYn#fp}GkCeu$f%p@zxL(h~kP8RQe#Ws_@8tZ78^ z?x)qpmJ5v8;ghR%Xf%A<9q)`LJUPr}c@LVitaj!(x?vCcY<$tcFA-|)`yZG+ST*oh z!Z-hCP$p6l1>@*nb`NfM8T0LDGS;Vk=;mKhx(X(Sqt|Mw-GXlTnKeOX6BuDn_Dby<&lrkm1qVDx=LHuR(y>HJXtzO@2 zrEi7R@&Et;0000000000;7S+{UE>C~?GEuz!~AG_n*rNf;~nqR3S-mT3^;nwvae{o zV72zOVS5=YTLvUif5Sb<_7Yp>Uq+44@F>H**@LeyFGh`&6zjv~A3EyH#oo|AUnFz` zQhZm#bo3|thqk}xv*)B5i~Yl?R6klv&*SgCO%|ONLJqQme`x48K7N<4rdxEXy|;#c zsF!-&LjV8(006KN)bQP=3uCq)`-fLSfAOb0{+`1>oRig>i2j_<-!uKgxp}RJ5KqYEoJ+ME z>gjO#xge1qe`{h$`~5xz@iG!(3MtCvRGz7XAni6W{9nAzI~!&|X`e6CdvT`$N_0pE zlFI{!A;bH6`JPK@*l@1~1B#QtC<-|6;gJ7{<++Q7e{mdTfw?dX{InUTOp`$IkpLYJ zx%_aHzhgz<`@1ag{k;hMG=GI@`VNW$`FPAdcswdUW?cf8XF3-?F}r-SzZ3^dFTD!Z zq-S$dv@u_H^XatalVj_K$vnRd0bA<}+I~G#jcpUym@)<|yPx@YtyH#wvp!n(V7PUK zS>Uphe^3|blE39=6gS;=Z4JzaLTYKg6KMR=K3o2$K7{Z{ZF@5mllV)xz)`;naCt#s z!vgc|NYw5%rYZlL!XmKc9;B4>SN4VDq32#V`P*LpR|W`HZZ^sg+59lM2<~qEw-x{Z z00000000000002+kw*T3*Lka)@0D!-X{{WXSAdu*hm3sgH002ovPDHLkV1jglA6fta diff --git a/icons/mob/human_races/cyberlimbs/xion.dmi b/icons/mob/human_races/cyberlimbs/xion.dmi index daf10298c217b113fa82934faed2049535e1d128..6c230675c3f84553a723a304fa9f02d07cab7f2b 100644 GIT binary patch delta 1346 zcmZ8hdpOez7~W7c93_>cB&2W-N1k!;7&UC=nBvK0r#Q4}VXo!ApHL|&LpViirx>}_ zTuwEO5Hspn*w|dlC2j7zxU}uid7hs0obQkCeZTjQ@BO~-kMEkY2x4^8!`)RKq5}be zKY{0s;L-k_i{6~&FrBOwAez>8?)0&Jp}m$$b!3WdUAu_h)a>WVJB4HX=7#@!R- zI5mLXD9RJOd}833=%6TEL<}w*4+6y%Wqo)FX|+&G86PA-as?$EZi!*K+B;M2v`NJr zl?yC7AzH2YWF2y0M(=jWawv^p@veds{wOCBsu2wzdn0kK+^K~GYlD#MF3=N5a_ z1e)EPQN;Od-oU6|7?(Uq@7u%s__R&`EWZN;Qqn=foxI|TW{X)@xVBpG{m%>@^UU8)T!E)TsCI7+n}?Si6<_>a`~o3)Y42W2cs){jJRegdK3OZ$n^oBy_j~AV z@ec~Ui69eO%EXl5%hG%bVROShZ__@6r3 z8c3hVWZL^fGbXIZP*Q3Vh6__QqV=3f%Y-w9AxO?nh3^L6$ckMj4Ru2ogZvtMm*DQu z<%kpBw1Z2Tc=NengUqXoT^yb$dMR0I$$Zskb9ipMsG?;dp|R@45*z3R--El*7t!*= z%7`pk3>@>te?DlS-hgEKUVr03L1*7jXb-W~OSAcd5C_H`+FM)4~KViVvj);zI zb=Ycu_WY$J;jV@8yWkFv!(;I4ggqW_@BKxn)5*?fFs$!P(Hz@Dl>RqwLFcQtcj&%( zB?0J+9eY>jAQr;C^4@Tp3^ZWd8Tjy8HiHq1N-2=yZ7^12RswPPY(BLxn3%_4dh35{ z<)}6vGCaD1lu~dxlkpEHL7t8U==DT^UgUh267ReFkASFY=RV4$0RFOG9#mP&HaH{P3&*ZITwePy;u=Tghl$f0x_$bI-+B$i z{h?(oUo06rwmzCAVao515sfGP);AyEzhQ4DSJZOB`Xvv@Ag!Ac(%BteeLNubA8THY A*8l(j delta 846 zcmV-U1F`(|3WWzHiBL{Q4GJ0x0000DNk~Le0002M0002M2m=5B0A&K4H2?qrMUf>& zf55=NE;(6n00001bW%=J06^y0W&i*Hj(SvBbVOxyV{&P5bZKvH004NLQ&wiFEu_#xG zi!&v&s2HS)i!-e#F*g;&Hbkh(Axc$Ie|$z_UJ4P05v8msJ|{Ju2*Zd`RTQ6=pI<_R zVfd6OE4cc(fCCu-Q1xbe6{Q==00071NklVA?*n}s}q%LM=cAj9?VD~FUu8u?a#!{{zB>WyBdOzwDW%dGua)=k}5n3iw#7b-5>sxB6FUvWyl*=NcYXo|Xvdn2C&_lFl>*q0_f4u*+Lx96Hz5)LN5zV!ckh`g)^(7dhu3!2a$l9Gc z=-%cMI3z6dc1K9g5ojxXZ5*4ai)B?88zH-H;1ak1?Zu%G000000000;rVX;QhT9K0 z0{A_@56%CLDSz}VAx@d!$L9aB?0m}nJ~sc4W$!@wZKsXyJ3+qV!{%?M|I000000001h6G|BHARj7Wz<;cS0sn)2 Y16#HY12mq>=>Px#07*qoM6N<$f&dbI*#H0l diff --git a/icons/mob/human_races/cyberlimbs/zenghu.dmi b/icons/mob/human_races/cyberlimbs/zenghu.dmi index a94eacc48a512f131f9f999ad93d7b764135fb2f..7ee24241b9faccd0a2ee27b65a245ddce179e596 100644 GIT binary patch delta 1335 zcmY*VdpOez82-(569;ufoH#hsqEpnNv|JC>IGbWw>EgIFp_prA_H#Qak0nEMv}JM` zlXP5?#6(3GWR%MuETVF0mW*w-ojHG;&iVfMzW4pU@AdHdBk8t|(}Fo(1>3^f1% z&_W${^9BHj0s=g!vLbVf4+koWYc6~zXklTYfLJURhr@Y!dExPRS65d{OG~4+5?93l z66=le0i0)s@d{FP341)&?QBd?bSNPP_IMEx$U~pgPi3nWH#`lE@ z{u;>3XYX|HFS4v5R@51X>UE><^-_xs-LuX|*XuuV%btfG)yYHDL2^}Xbc4#$?4V?@T&UP#ZnQSUFpG=Ndf53u)y*U_WJH9&B31WoWR=%c!MH8s4 zzr}S-m)}Z~J|sSj_hls|*61WAKYx~(1SajsukojP{R$Nc&Xj+V{e>!wmcAga%l#JD znRQM-%E!n>Wzpi66?IK!mT`$s8>;)9?smKGk3-V~VXis($mCmDTAbrmAbP&?hl)2l zq%2|>G*rpa$qIkmVE$U7U}9QN94Bfh%I`mBi-M(ByUl)WqKspp-~Oy4o+pLB)*MtH zLHCn(5OaKlcg?2Hy2McP#b$ajDXhqulXLvbrL7O>Z=tqqPmc@j1Wpposgk+IWj-LM2 zEsy7UVz}wWz^bRs z6@^tVRJzpM$X@yI^2DE0)|i1Z3#j10_GN2&sdvPJ$xd0_T3(Kq6=O>opbvNX!bU*+ zBqkm9r>1PByS_6B${y8F;rl3wR^Rhmy(8v8PsS=!1fs1N=l~C$X;s?LKF4}F#aU3i z^1AGE`-quavtjz?+E#GC?B1-|%~{76Fz@F^xKGby)i4rgXCM_jZtEN_Z%`@?%$+1l z?kaF_fa-9Pdc$%tc%#2!AN@8`j^K`({MVi~&9`~=^x`{>D@|hUL0R?|aBAe{(TD~9 zltH7ZDeJUveVT|UtCBK*>3ne=OBNd@NJNh)j7It692AIEqSd}**$P%EAC~G!;quP4 z^9~5*na$>nJ>7>Cdv#qWCESeksIB)U+P-m!2BG>t4)U{>Gq0+~Nw1}!j+}Es&;Gor z-gp_ZBp9tN?c;&9u)^gLkitK=D$+J7Q1RlK3{XE3mT(()Kn^D6iQuUQj7G4CVN3eg57iBL{Q4GJ0x0000DNk~Le0002M0002M1Oos70HE@5GynhqEs-TI zf55=N!^;e!00001bW%=J06^y0W&i*Hj(SvBbVOxyV{&P5bZKvH004NLQ&wiFEu_#xG zi!&v&s2HS)i!-e#F*g;&Hbkh(Axc$Ie|$z_UJ4P05v8msJ|{Ju2*Zd`RTQ6=pI<_R zVfd6OE4cc(fCCu-Q1xbe6{Q==0006wNklzI&#Y4gk zIr-J=8Byyg6O(0K8&M+bSwDRt7ASkyRF!ZAjh^*WPh!E|qdk6kjt^+`tlz<_T=5=n zD(XZ1000000D#0O#Vz(>XJIxwe}H-Lp;1?6vjg;|x5$kIf&5^TSW-wN?7!LaJ0mGh zZ|rgDhZ@~&mR@~G%d1akz`{GV+i}3Rk(STCoB>O}qT7J1kmnlt7ytkO004l#Sidjl z0iy065*xoC$OHc3cqwUGY5aa558Qj7>h1#?zaPj0{$kmEfc5xt9tf#3e=n{zq}<44 z^o%Wy5 zo2jZI&dl@sEDuEMbxo|~n7U2R@3TA*t&a~V{Q=}`v|iC2$*G<7%q%mz(R%h@!<>f5 z((S*eDsUH9U00000+X8(h w!d|iTh5CKw|9cPc;((YK`r*fc0UiDi?}SK|zN%-500000NkvXX1g=70f+!ep9smFU diff --git a/icons/mob/human_races/r_machine.dmi b/icons/mob/human_races/r_machine.dmi deleted file mode 100644 index 65f66c3238599dc86e3c0b902ee79973bee106ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2120 zcmZ8gXHXLe6HS8jCWst_2q?WsqERWqgepi$0tCWPL<9ng8ajw@1XNI|2MS0p3V0m7 zNKZtNj(|c`)TopIA=0D;o*?LR1JW1ONa;FIt+}0{}oS z1OfzjxXJ$?XB;=hVr_8d6beOERh3)KfcQ+b4hRH-rl#f_E;cd2?A1`w>uynwlCE3PmE3+S=M+Fc<^^K_Cz-D=P#7VPRoWngQT4YiMYs zwtsiaU)GA*0suHRHa1#XTdAqv-Q1S-^hODUk<84IBr%ZluhBy6(GCEk`S%2FL5ajU zhnV>Udj(w$2)RnU2>?XoB~Oe9b;CsXSA$tnKJAGPHJ7|kAX@P1_Xz%huF6$%U7ajF z5zNTRSPzb^Vr$!H1;?sEUlog@uYp*6s6OObc1QBfo1>#HPD{jxBoVQekC`A|H`HyQgwJ{Q_Qf_odS67Uw5& z4PcoPFX}_UqiT~+YQhRvt-kBNT=4wpzD5rUtr^-x$D}p(9M_7d319At#p>EC7Q((|s|b6`6bZ4iQieXK$7CJtb3Kuz9HK~@%nn~^5uTG!q*EZ9!u42| z{gIJiw$82fi9gq&xKY5+J{AHvSGH1c24GK1r`42r$FSOIzO@DM_4|ydAXWSfZT*Sr ztE1AxNUAyO1KHmnP^~pv<9_S!hVsgXui*IEd$L%6V|tl4YB$^=JicsqT_jB&*;@^_ z4HeW(UfF8S_Bw=Cn0vc0&+Pbj&EF#F)(K;@hl9y|ahSgH>x6q_Wv$-#ReSj#nU17O z-0)Tv=%~fuWV^it*Q}?fy*idym<#dsy0ep(4NF?DpwR870%vURd)?Bs%R9U^9*mbK zReX_~1RV?+=`WS-lsDEv`M%BRpTh}@Ok6*nqw~JQ&AUq=`zGer_?F zT#EVtH%iLzLYNC~sFfz*b?n?bTZ{8de3g6rAkpFB#GmTa9648mV7^bZ&$8#Q;L;~*rG*>q&<8ew5- z&v5odSL3^PNO$07Cs^#xcjE~KDSj6Qoi|G-WUyYi?{HigZ_t-3#oF6Wm;0ZjVjN=_ zvCYdp$K8RUj`0~hOAz7me^8M{I_-gN{8hT}rp=Pe9eeLxP|yMSpT~1)BaTx&_8IJ( zfx!oNJP~A$-7&wa!fMhJ8mEP4%$YVhyX{fm_1K6K5gh~E`@a&a!jjGX%siJ#mGY$h zdx`zEG#6Um= zUV1!@&vWg})~amkDuo#+Iw?OrTSHweeE)@>pWvBx%rbcZs8QnBTo|tVf%ALJ^L|xCJ?z{UWBQnj!f(fh zDLF+^)*hs$YE|Owc~dj~Jg`~yVDIm3Cbn=me1@+brNX4k6?xTV66~S|@3S~W%8V|1 ziyZ(L=eCO6D<`wr^ovR25j+#S*0+Zo4sX2}R<=JgO7bGVEBOlvbYc(?W_0f+mc3CkI_TM^*I9i znYnYMAHC`FanXAcdQW{X$E1jNyX_c~S#K7dU|QMG^kSM*76x973KL>FsKgvKVAPnh zWCN;aQ-R@S3IL^P4kz!MQh<2!t%=b!i54}gbj9<)THNc|?Z|^T^M*==A}ZARG;5Ya cbUpMH<(y`4Hg9%x;+Luy&CzDnCYR&>2bWpbb^rhX