From 28f9496713bd6866169d20ccadd8a23113789297 Mon Sep 17 00:00:00 2001 From: KasparoVy Date: Thu, 19 Jan 2017 22:13:16 -0500 Subject: [PATCH 1/4] Adds Colourblindness for Vulpkanin&Tajara, Refactors Darksight, tidying up, etc. Adds colourblindness for Vulpkanin and Tajara that can be turned on by a preference in character creation. By default, Vulpkanin and Tajara still see in full colour, however their darksight is reduced to Human levels unless they choose the 'unaugmented' eyes option. Refactors darksight so it's tied to the eye organ. Refactors noir glasses. You can now visually distinguish mechanical/mechassisted organs from their organic counterparts due to their names and icons. Resolves issue w/ Colour-vision after Cloning/Lesser-to-greater Formswapping. Cloned Vulpkanin and Tajara get unaugmented vision (colourblind and darksight) by default since the cloners can't administer the eye-augmentation surgery. Same goes for swapping from lesser to greater form as a Changeling. The monkey-forms of Vulpkanin and Tajara now have almost the same organs as their greater forms, meaning they get the same colourblindness but excellent darksight. --- code/__DEFINES/misc.dm | 13 +---- code/__HELPERS/AnimationLibrary.dm | 2 +- code/modules/client/client procs.dm | 3 + code/modules/client/preference/preferences.dm | 16 ++++-- code/modules/clothing/glasses/glasses.dm | 34 +---------- code/modules/mob/living/carbon/carbon.dm | 2 +- code/modules/mob/living/carbon/human/human.dm | 18 +++--- .../mob/living/carbon/human/inventory.dm | 2 + .../living/carbon/human/species/abductor.dm | 10 +++- .../mob/living/carbon/human/species/apollo.dm | 9 ++- .../mob/living/carbon/human/species/golem.dm | 3 +- .../mob/living/carbon/human/species/monkey.dm | 21 +++++++ .../living/carbon/human/species/plasmaman.dm | 2 + .../mob/living/carbon/human/species/shadow.dm | 4 +- .../living/carbon/human/species/skeleton.dm | 2 +- .../living/carbon/human/species/species.dm | 18 ++++-- .../living/carbon/human/species/station.dm | 53 ++++++++++++------ code/modules/mob/login.dm | 2 + code/modules/mob/mob_helpers.dm | 26 +++++++-- code/modules/mob/new_player/new_player.dm | 2 +- .../designs/mechfabricator_designs.dm | 2 +- code/modules/surgery/organs/helpers.dm | 1 - code/modules/surgery/organs/organ.dm | 28 ++++----- code/modules/surgery/organs/organ_internal.dm | 44 +++++++++++++-- .../surgery/organs/subtypes/abductor.dm | 4 ++ code/modules/surgery/organs/subtypes/diona.dm | 44 ++------------- code/modules/surgery/organs/subtypes/drask.dm | 26 +-------- code/modules/surgery/organs/subtypes/grey.dm | 5 ++ .../surgery/organs/subtypes/machine.dm | 20 ++----- .../surgery/organs/subtypes/nucleation.dm | 7 +-- .../modules/surgery/organs/subtypes/shadow.dm | 4 ++ .../surgery/organs/subtypes/tajaran.dm | 9 +++ .../modules/surgery/organs/subtypes/unathi.dm | 5 ++ .../surgery/organs/subtypes/vulpkanin.dm | 9 +++ code/modules/surgery/organs/subtypes/wryn.dm | 4 ++ code/modules/surgery/organs_internal.dm | 4 +- icons/obj/surgery.dmi | Bin 31763 -> 31898 bytes paradise.dme | 2 + 38 files changed, 258 insertions(+), 202 deletions(-) create mode 100644 code/modules/surgery/organs/subtypes/abductor.dm create mode 100644 code/modules/surgery/organs/subtypes/shadow.dm diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 5e9815b7758..09ea7bf366f 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -250,16 +250,9 @@ #define MAP_MAXZ 6 //Matricies -#define MATRIX_DEFAULT list(1, 0, 0, 0,\ - 0, 1, 0, 0,\ - 0, 0, 1, 0,\ - 0, 0, 0, 1) - -#define MATRIX_GREYSCALE list(0.33, 0.33, 0.33, 0,\ - 0.33, 0.33, 0.33, 0,\ - 0.33, 0.33, 0.33, 0,\ - 0.00, 0.00, 0.00, 1,\ - 0.00, 0.00, 0.00, 0) +#define MATRIX_GREYSCALE list(0.33, 0.33, 0.33,\ + 0.33, 0.33, 0.33,\ + 0.33, 0.33, 0.33) //Gun trigger guards #define TRIGGER_GUARD_ALLOW_ALL -1 #define TRIGGER_GUARD_NONE 0 diff --git a/code/__HELPERS/AnimationLibrary.dm b/code/__HELPERS/AnimationLibrary.dm index fcabe2e0a78..fd79fe197f2 100644 --- a/code/__HELPERS/AnimationLibrary.dm +++ b/code/__HELPERS/AnimationLibrary.dm @@ -7,7 +7,7 @@ /proc/animate_fade_grayscale(var/atom/A, var/time = 5) if(!istype(A) && !istype(A, /client)) return - A.color = MATRIX_DEFAULT + A.color = null animate(A, color = MATRIX_GREYSCALE, time = time, easing = SINE_EASING) /proc/animate_melt_pixel(var/atom/A) diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 6e1fe9126fd..3e2e1f54e0c 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -621,3 +621,6 @@ if(lang.flags & RESTRICTED) message += " (RESTRICTED)" to_chat(world, "[message]") + +/client/proc/colour_transition(var/list/colour_to = null, var/time = 10) //Call this with no parameters to reset to default. + animate(src, color=colour_to, time=time, easing=SINE_EASING) diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm index ba51996f4e7..4ec7516a409 100644 --- a/code/modules/client/preference/preferences.dm +++ b/code/modules/client/preference/preferences.dm @@ -282,6 +282,8 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts dat += "Species: [species]
" if(species == "Vox") dat += "N2 Tank: [speciesprefs ? "Large N2 Tank" : "Specialized N2 Tank"]
" + else if(species in list("Vulpkanin", "Tajaran")) + dat += "Colour Vision: [speciesprefs ? "Unaugmented" : "Surgically Corrected"]
" dat += "Secondary Language: [language]
" dat += "Blood Type: [b_type]
" if(species in list("Human", "Drask", "Vox")) @@ -1337,9 +1339,13 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts //Reset prosthetics. organ_data = list() rlimb_data = list() - if("speciesprefs")//oldvox code - speciesprefs = !speciesprefs - + if("speciesprefs") + if(species == "Vox") //oldvox code + speciesprefs = !speciesprefs //Starts 0, so if someone clicks the button up top there, this won't be 0 anymore. If they click it again, it'll go back to 0. + else if(species in list("Vulpkanin", "Tajaran")) //Species that can be colourblind. + var/list/vision_options = list("Surgically Corrected", "Unaugmented") //Surgically corrected eyes (default option) see in full colour but have 2 darksight. Unaugmented eyes are colourblind but have 8 darksight. + speciesprefs = input("Please select your vision preference. \nOverridden by mech. assisted or mechanical eyes. \nSurgically Corrected: Full colour, low darksight. \n Unaugmented: Colourblind, full darksight.", "Character Generation", 0) in vision_options + speciesprefs = (speciesprefs != "Surgically Corrected") //Ensure the default option (surgically corrected) returns 0. I would've set up the vision_options list such that Surgically Corrected = 0, but input() didn't care for it. if("language") // var/languages_available var/list/new_languages = list("None") @@ -2020,8 +2026,6 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts return 1 /datum/preferences/proc/copy_to(mob/living/carbon/human/character) - var/datum/species/S = all_species[species] - character.change_species(species) // Yell at me if this causes everything to melt if(be_random_name) real_name = random_name(gender,species) @@ -2173,7 +2177,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts character.dna.SetSEState(MUTEBLOCK,1,1) character.disabilities |= MUTE - S.handle_dna(character) + character.species.handle_dna(character) if(character.dna.dirtySE) character.dna.UpdateSE() diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm index 4fde338ba54..5b38adc6a82 100644 --- a/code/modules/clothing/glasses/glasses.dm +++ b/code/modules/clothing/glasses/glasses.dm @@ -232,8 +232,6 @@ name = "noir sunglasses" desc = "Somehow these seem even more out-of-date than normal sunglasses." actions_types = list(/datum/action/item_action/noir) - var/noir_mode = 0 - color_view = MATRIX_GREYSCALE /obj/item/clothing/glasses/sunglasses/noir/attack_self() toggle_noir() @@ -243,36 +241,8 @@ return 1 /obj/item/clothing/glasses/sunglasses/noir/proc/toggle_noir() - var/list/difference = difflist(usr.client.color, color_view) - - if(!noir_mode) - if(color_view && usr.client && (!usr.client.color || difference)) - animate(usr.client, color = color_view, time = 10) - noir_mode = 1 - else - if(usr.client && usr.client.color && !difference) - animate(usr.client, color = initial(usr.client.color), time = 10) - noir_mode = 0 - -/obj/item/clothing/glasses/sunglasses/noir/equipped(mob/user, slot) - var/list/difference = difflist(user.client.color, color_view) - - if(slot == slot_glasses) - if(noir_mode) - if(color_view && user.client && (!user.client.color || difference.len)) - animate(user.client, color = color_view, time = 10) - else - if(user.client && user.client.color && !difference.len) - animate(user.client, color = initial(user.client.color), time = 10) - ..(user, slot) - -/obj/item/clothing/glasses/sunglasses/noir/dropped(mob/living/carbon/human/user) - var/list/difference = difflist(user.client.color, color_view) - - if(istype(user) && user.glasses == src) - if(user.client && user.client.color && !difference.len) - animate(user.client, color = initial(user.client.color), time = 10) - ..(user) + color_view = color_view ? null : MATRIX_GREYSCALE //Toggles between null and grayscale, with null being the default option. + usr.update_client_colour() /obj/item/clothing/glasses/sunglasses/yeah name = "agreeable glasses" diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 827f0ded62e..1ec1695352a 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -309,7 +309,7 @@ Stun(2) var/obj/item/organ/internal/eyes/E = get_int_organ(/obj/item/organ/internal/eyes) - if(!E) + if(!E || (E && E.weld_proof)) return switch(damage) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index ae88df869d9..c2e2f090bb2 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -721,8 +721,6 @@ if(istype(id)) return id - - /mob/living/carbon/human/update_sight() if(!client) return @@ -1533,12 +1531,6 @@ if(species.default_language) add_language(species.default_language) - see_in_dark = species.darksight - if(see_in_dark > 2) - see_invisible = SEE_INVISIBLE_LEVEL_ONE - else - see_invisible = SEE_INVISIBLE_LIVING - hunger_drain = species.hunger_drain digestion_ratio = species.digestion_ratio @@ -1608,8 +1600,17 @@ dna.real_name = real_name species.handle_post_spawn(src) + + see_in_dark = species.get_resultant_darksight(src) + if(see_in_dark > 2) + see_invisible = SEE_INVISIBLE_LEVEL_ONE + else + see_invisible = SEE_INVISIBLE_LIVING + species.handle_dna(src) //Give them whatever special dna business they got. + update_client_colour(0) + spawn(0) overlays.Cut() update_mutantrace(1) @@ -1632,7 +1633,6 @@ return null return species.default_language ? all_languages[species.default_language] : null - /mob/living/carbon/human/proc/bloody_doodle() set category = "IC" set name = "Write in blood" diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 4e90d763e9e..c375d718e3d 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -119,6 +119,7 @@ if(G.vision_flags || G.darkness_view || G.invis_override || G.invis_view) update_sight() update_inv_glasses() + update_client_colour() else if(I == head) head = null if(I.flags & BLOCKHAIR || I.flags & BLOCKHEADHAIR) @@ -271,6 +272,7 @@ if(G.vision_flags || G.darkness_view || G.invis_override || G.invis_view) update_sight() update_inv_glasses(redraw_mob) + update_client_colour() if(slot_gloves) gloves = W update_inv_gloves(redraw_mob) diff --git a/code/modules/mob/living/carbon/human/species/abductor.dm b/code/modules/mob/living/carbon/human/species/abductor.dm index 3bcade9f00d..4690529524f 100644 --- a/code/modules/mob/living/carbon/human/species/abductor.dm +++ b/code/modules/mob/living/carbon/human/species/abductor.dm @@ -7,8 +7,16 @@ language = "Abductor Mindlink" default_language = "Abductor Mindlink" unarmed_type = /datum/unarmed_attack/punch - darksight = 3 eyes = "blank_eyes" + has_organ = list( + "heart" = /obj/item/organ/internal/heart, + "lungs" = /obj/item/organ/internal/lungs, + "liver" = /obj/item/organ/internal/liver, + "kidneys" = /obj/item/organ/internal/kidneys, + "brain" = /obj/item/organ/internal/brain, + "appendix" = /obj/item/organ/internal/appendix, + "eyes" = /obj/item/organ/internal/eyes/abductor //3 darksight. + ) flags = HAS_LIPS | NO_BLOOD | NO_BREATHE diff --git a/code/modules/mob/living/carbon/human/species/apollo.dm b/code/modules/mob/living/carbon/human/species/apollo.dm index faeecdfcc5f..476f1aa9049 100644 --- a/code/modules/mob/living/carbon/human/species/apollo.dm +++ b/code/modules/mob/living/carbon/human/species/apollo.dm @@ -9,7 +9,6 @@ punchdamagelow = 0 punchdamagehigh = 1 //primitive = /mob/living/carbon/monkey/wryn - darksight = 3 slowdown = 1 warning_low_pressure = -300 hazard_low_pressure = 1 @@ -32,7 +31,7 @@ has_organ = list( "heart" = /obj/item/organ/internal/heart, "brain" = /obj/item/organ/internal/brain, - "eyes" = /obj/item/organ/internal/eyes, + "eyes" = /obj/item/organ/internal/eyes/wryn, //3 darksight. "appendix" = /obj/item/organ/internal/appendix, "antennae" = /obj/item/organ/internal/wryn/hivenode ) @@ -89,7 +88,7 @@ name_plural = "Nucleations" icobase = 'icons/mob/human_races/r_nucleation.dmi' unarmed_type = /datum/unarmed_attack/punch - blurb = "A sub-race of unforunates who have been exposed to too much supermatter radiation. As a result, \ + blurb = "A sub-race of unfortunates who have been exposed to too much supermatter radiation. As a result, \ supermatter crystal clusters have begun to grow across their bodies. Research to find a cure for this ailment \ has been slow, and so this is a common fate for veteran engineers. The supermatter crystals produce oxygen, \ negating the need for the individual to breathe. Their massive change in biology, however, renders most medicines \ @@ -109,8 +108,8 @@ reagent_tag = PROCESS_ORG has_organ = list( "heart" = /obj/item/organ/internal/heart, - "crystalized brain" = /obj/item/organ/internal/brain/crystal, - "eyes" = /obj/item/organ/internal/eyes/luminescent_crystal, + "crystallized brain" = /obj/item/organ/internal/brain/crystal, + "eyes" = /obj/item/organ/internal/eyes/luminescent_crystal, //Standard darksight of 2. "strange crystal" = /obj/item/organ/internal/nucleation/strange_crystal, "resonant crystal" = /obj/item/organ/internal/nucleation/resonant_crystal ) diff --git a/code/modules/mob/living/carbon/human/species/golem.dm b/code/modules/mob/living/carbon/human/species/golem.dm index 1bb4ba8e214..a2f2eb30467 100644 --- a/code/modules/mob/living/carbon/human/species/golem.dm +++ b/code/modules/mob/living/carbon/human/species/golem.dm @@ -40,7 +40,8 @@ has_organ = list( "brain" = /obj/item/organ/internal/brain/golem - ) + ) //Has standard darksight of 2. + suicide_messages = list( "is crumbling into dust!", "is smashing their body apart!") diff --git a/code/modules/mob/living/carbon/human/species/monkey.dm b/code/modules/mob/living/carbon/human/species/monkey.dm index dffc73d4e1d..34f4e16bfdf 100644 --- a/code/modules/mob/living/carbon/human/species/monkey.dm +++ b/code/modules/mob/living/carbon/human/species/monkey.dm @@ -26,6 +26,7 @@ tail = "chimptail" bodyflags = FEET_PADDED | HAS_TAIL reagent_tag = PROCESS_ORG + //Has standard darksight of 2. //unarmed_types = list(/datum/unarmed_attack/bite, /datum/unarmed_attack/claws) //inherent_verbs = list(/mob/living/proc/ventcrawl) @@ -106,6 +107,16 @@ tail = "farwatail" reagent_tag = PROCESS_ORG + has_organ = list( + "heart" = /obj/item/organ/internal/heart, + "lungs" = /obj/item/organ/internal/lungs, + "liver" = /obj/item/organ/internal/liver/tajaran, + "kidneys" = /obj/item/organ/internal/kidneys, + "brain" = /obj/item/organ/internal/brain, + "appendix" = /obj/item/organ/internal/appendix, + "eyes" = /obj/item/organ/internal/eyes/tajaran //Tajara monkey-forms are uniquely colourblind and have excellent darksight. + ) + /datum/species/monkey/vulpkanin name = "Wolpin" @@ -121,6 +132,16 @@ tail = "wolpintail" reagent_tag = PROCESS_ORG + has_organ = list( + "heart" = /obj/item/organ/internal/heart, + "lungs" = /obj/item/organ/internal/lungs, + "liver" = /obj/item/organ/internal/liver/vulpkanin, + "kidneys" = /obj/item/organ/internal/kidneys, + "brain" = /obj/item/organ/internal/brain, + "appendix" = /obj/item/organ/internal/appendix, + "eyes" = /obj/item/organ/internal/eyes/vulpkanin //Vulpkanin monkey-forms are uniquely colourblind and have excellent darksight. + ) + /datum/species/monkey/skrell name = "Neara" diff --git a/code/modules/mob/living/carbon/human/species/plasmaman.dm b/code/modules/mob/living/carbon/human/species/plasmaman.dm index 1a79374407c..d0d9d10fd94 100644 --- a/code/modules/mob/living/carbon/human/species/plasmaman.dm +++ b/code/modules/mob/living/carbon/human/species/plasmaman.dm @@ -20,6 +20,8 @@ heat_level_2 = 400 // Heat damage level 2 above this point. heat_level_3 = 500 // Heat damage level 3 above this point. + //Has default darksight of 2. + suicide_messages = list( "is twisting their own neck!", "is letting some O2 in!", diff --git a/code/modules/mob/living/carbon/human/species/shadow.dm b/code/modules/mob/living/carbon/human/species/shadow.dm index ca26348d188..35f008af802 100644 --- a/code/modules/mob/living/carbon/human/species/shadow.dm +++ b/code/modules/mob/living/carbon/human/species/shadow.dm @@ -7,12 +7,12 @@ default_language = "Galactic Common" unarmed_type = /datum/unarmed_attack/claws - darksight = 8 blood_color = "#CCCCCC" flesh_color = "#AAAAAA" has_organ = list( - "brain" = /obj/item/organ/internal/brain + "brain" = /obj/item/organ/internal/brain, + "eyes" = /obj/item/organ/internal/eyes/shadow //8 darksight. ) flags = NO_BLOOD | NO_BREATHE | RADIMMUNE diff --git a/code/modules/mob/living/carbon/human/species/skeleton.dm b/code/modules/mob/living/carbon/human/species/skeleton.dm index 4a3b087e93d..d09c8dd1699 100644 --- a/code/modules/mob/living/carbon/human/species/skeleton.dm +++ b/code/modules/mob/living/carbon/human/species/skeleton.dm @@ -41,7 +41,7 @@ "is twisting their skull off!") has_organ = list( "brain" = /obj/item/organ/internal/brain/golem, - ) + ) //Has default darksight of 2. /datum/species/skeleton/handle_reagents(var/mob/living/carbon/human/H, var/datum/reagent/R) // Crazylemon is still silly diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index e2238057533..73c557c9c58 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -49,7 +49,6 @@ var/siemens_coeff = 1 //base electrocution coefficient var/invis_sight = SEE_INVISIBLE_LIVING - var/darksight = 2 var/hazard_high_pressure = HAZARD_HIGH_PRESSURE // Dangerously high pressure. var/warning_high_pressure = WARNING_HIGH_PRESSURE // High pressure warning. var/warning_low_pressure = WARNING_LOW_PRESSURE // Low pressure warning. @@ -586,12 +585,23 @@ It'll return null if the organ doesn't correspond, so include null checks when u return null return has_organ[organ_slot] +/datum/species/proc/get_resultant_darksight(mob/living/carbon/human/H) //Returns default value of 2 if the mob doesn't have eyes, otherwise it grabs the eyes darksight. + var/resultant_darksight = 2 + var/obj/item/organ/internal/eyes/eyes = H.get_int_organ(/obj/item/organ/internal/eyes) + if(eyes && eyes.dark_view) + resultant_darksight = eyes.dark_view + return resultant_darksight /datum/species/proc/update_sight(mob/living/carbon/human/H) H.sight = initial(H.sight) - H.see_in_dark = darksight + H.see_in_dark = get_resultant_darksight(H) H.see_invisible = invis_sight + if(H.see_in_dark > 2) //Preliminary see_invisible handling as per set_species() in code\modules\mob\living\carbon\human\human.dm. + H.see_invisible = SEE_INVISIBLE_LEVEL_ONE + else + H.see_invisible = SEE_INVISIBLE_LIVING + if(H.client.eye != H) var/atom/A = H.client.eye if(A.update_remote_sight(H)) //returns 1 if we override all other sight updates. @@ -642,7 +652,7 @@ It'll return null if the organ doesn't correspond, so include null checks when u if(rig.visor && rig.visor.vision && rig.visor.active && rig.visor.vision.glasses) var/obj/item/clothing/glasses/G = rig.visor.vision.glasses if(istype(G)) - H.see_in_dark = (G.darkness_view ? G.darkness_view : darksight) // Otherwise we keep our darkness view with togglable nightvision. + H.see_in_dark = (G.darkness_view ? G.darkness_view : get_resultant_darksight(H)) // Otherwise we keep our darkness view with togglable nightvision. if(G.vision_flags) // MESONS H.sight |= G.vision_flags @@ -652,7 +662,7 @@ It'll return null if the organ doesn't correspond, so include null checks when u H.see_in_dark = max(lesser_darkview_bonus, H.see_in_dark) if(H.vision_type) - H.see_in_dark = max(H.see_in_dark, H.vision_type.see_in_dark, darksight) + H.see_in_dark = max(H.see_in_dark, H.vision_type.see_in_dark, get_resultant_darksight(H)) H.see_invisible = H.vision_type.see_invisible if(H.vision_type.light_sensitive) H.weakeyes = 1 diff --git a/code/modules/mob/living/carbon/human/species/station.dm b/code/modules/mob/living/carbon/human/species/station.dm index 5bde6ce8e5b..4ae52431e9a 100644 --- a/code/modules/mob/living/carbon/human/species/station.dm +++ b/code/modules/mob/living/carbon/human/species/station.dm @@ -18,6 +18,7 @@ worlds tumultous at best." reagent_tag = PROCESS_ORG + //Has standard darksight of 2. /datum/species/unathi name = "Unathi" @@ -30,7 +31,6 @@ tail = "sogtail" unarmed_type = /datum/unarmed_attack/claws primitive_form = "Stok" - darksight = 3 blurb = "A heavily reptillian species, Unathi (or 'Sinta as they call themselves) hail from the \ Uuosa-Eso system, which roughly translates to 'burning mother'.

Coming from a harsh, radioactive \ @@ -66,7 +66,7 @@ "kidneys" = /obj/item/organ/internal/kidneys, "brain" = /obj/item/organ/internal/brain, "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes, + "eyes" = /obj/item/organ/internal/eyes/unathi //3 darksight. ) allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/simple_animal/lizard, /mob/living/simple_animal/chick, /mob/living/simple_animal/chicken, @@ -91,7 +91,6 @@ language = "Siik'tajr" tail = "tajtail" unarmed_type = /datum/unarmed_attack/claws - darksight = 8 blurb = "The Tajaran race is a species of feline-like bipeds hailing from the planet of Ahdomai in the \ S'randarr system. They have been brought up into the space age by the Humans and Skrell, and have been \ @@ -126,7 +125,8 @@ "kidneys" = /obj/item/organ/internal/kidneys, "brain" = /obj/item/organ/internal/brain, "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes, + "eyes" = /obj/item/organ/internal/eyes/tajaran /*Most Tajara are surgically augmented at birth for full colour vision, although it cost them their darksight (darksight = 2) unless they choose otherwise in character creation (darksight = 8 but colourblind). + However, this organ define is for unaugmented eyes so cloned Tajara are colourblind but have excellent darksight.*/ ) allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/simple_animal/chick, /mob/living/simple_animal/butterfly, /mob/living/simple_animal/parrot, @@ -138,6 +138,15 @@ "is twisting their own neck!", "is holding their breath!") +/datum/species/tajaran/equip(var/mob/living/carbon/human/H) //Handles colourblindness preferences. Should only happen if the client is in a mob otherwise it won't work. + var/sight_pref = H.client.prefs.speciesprefs + if(!sight_pref) + var/obj/item/organ/internal/eyes/tajaran/tajeyes = H.get_int_organ(/obj/item/organ/internal/eyes) + if(tajeyes && !tajeyes.robotic) //To avoid overriding the properties of cybernetic/mechassisted eyes, apply the colour matrix and darksight modifier only if the organ is organic. Robotic/mechassisted eyes currently do this, too, as is necessary. + tajeyes.colourmatrix = null //For individuals who recieved the modification, they lose much of their darksight and gain full colour vision. + tajeyes.dark_view = 2 //If they didn't, they would have their unique colour-vision and full darksight. See code\modules\surgery\organs\subtypes\tajaran.dm + H.update_client_colour(0) + /datum/species/tajaran/handle_death(var/mob/living/carbon/human/H) H.stop_tail_wagging(1) @@ -152,7 +161,6 @@ primitive_form = "Wolpin" tail = "vulptail" unarmed_type = /datum/unarmed_attack/claws - darksight = 8 blurb = "Vulpkanin are a species of sharp-witted canine-pideds residing on the planet Altam just barely within the \ dual-star Vazzend system. Their politically de-centralized society and independent natures have led them to become a species and \ @@ -176,7 +184,8 @@ "kidneys" = /obj/item/organ/internal/kidneys, "brain" = /obj/item/organ/internal/brain, "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes, + "eyes" = /obj/item/organ/internal/eyes/vulpkanin /*Most Vulpkanin are surgically augmented at birth for full colour vision, although it cost them their darksight (darksight = 2) unless they choose otherwise in character creation (darksight = 8 but colourblind). + However, this organ define is for unaugmented eyes so cloned Vulpkanin are colourblind but have excellent darksight.*/ ) allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/simple_animal/lizard, /mob/living/simple_animal/chick, /mob/living/simple_animal/chicken, @@ -188,6 +197,15 @@ "is twisting their own neck!", "is holding their breath!") +/datum/species/vulpkanin/equip(var/mob/living/carbon/human/H) //Handles colourblindness preferences. Should only happen if the client is in a mob otherwise it won't work. + var/sight_pref = H.client.prefs.speciesprefs + if(!sight_pref) + var/obj/item/organ/internal/eyes/vulpkanin/vulpeyes = H.get_int_organ(/obj/item/organ/internal/eyes) + if(vulpeyes && !vulpeyes.robotic) //To avoid overriding the properties of cybernetic/mechassisted eyes, apply the colour matrix and darksight modifier only if the organ is organic. Robotic/mechassisted eyes currently do this, too, as is necessary. + vulpeyes.colourmatrix = null //For individuals who recieved the modification, they lose much of their darksight and gain full colour vision. + vulpeyes.dark_view = 2 //If they didn't, they would have their unique colour-vision and full darksight. See code\modules\surgery\organs\subtypes\vulpkanin.dm + H.update_client_colour(0) + /datum/species/vulpkanin/handle_death(var/mob/living/carbon/human/H) H.stop_tail_wagging(1) @@ -226,7 +244,7 @@ "kidneys" = /obj/item/organ/internal/kidneys, "brain" = /obj/item/organ/internal/brain, "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes, + "eyes" = /obj/item/organ/internal/eyes //Default darksight of 2. ) suicide_messages = list( @@ -315,7 +333,7 @@ "kidneys" = /obj/item/organ/internal/kidneys, "brain" = /obj/item/organ/internal/brain, "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes, + "eyes" = /obj/item/organ/internal/eyes, //Default darksight of 2. "stack" = /obj/item/organ/internal/stack/vox //Not the same as the cortical stack implant Vox Raiders spawn with. The cortical stack implant is used ) //for determining the success of the heist game-mode's 'leave nobody behind' objective, while this is just an organ. @@ -439,7 +457,7 @@ "liver" = /obj/item/organ/internal/liver, "kidneys" = /obj/item/organ/internal/kidneys, "brain" = /obj/item/organ/internal/brain, - "eyes" = /obj/item/organ/internal/eyes, + "eyes" = /obj/item/organ/internal/eyes, //Default darksight of 2. "stack" = /obj/item/organ/internal/stack/vox //Not the same as the cortical stack implant Vox Raiders spawn with. The cortical stack implant is used ) //for determining the success of the heist game-mode's 'leave nobody behind' objective, while this is just an organ. @@ -478,7 +496,7 @@ "kidneys" = /obj/item/organ/internal/kidneys, "brain" = /obj/item/organ/internal/brain, "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes, + "eyes" = /obj/item/organ/internal/eyes //Default darksight of 2. ) allowed_consumed_mobs = list(/mob/living/simple_animal/diona) @@ -517,6 +535,7 @@ exotic_blood = "water" //ventcrawler = 1 //ventcrawling commented out butt_sprite = "slime" + //Has default darksight of 2. has_organ = list( "brain" = /obj/item/organ/internal/brain/slime @@ -685,7 +704,6 @@ default_language = "Galactic Common" language = "Psionic Communication" unarmed_type = /datum/unarmed_attack/punch - darksight = 5 // BOOSTED from 2 eyes = "grey_eyes_s" butt_sprite = "grey" @@ -696,7 +714,7 @@ "kidneys" = /obj/item/organ/internal/kidneys, "brain" = /obj/item/organ/internal/brain/grey, "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes, + "eyes" = /obj/item/organ/internal/eyes/grey //5 darksight. ) brute_mod = 1.25 //greys are fragile @@ -771,13 +789,13 @@ has_organ = list( "nutrient channel" = /obj/item/organ/internal/liver/diona, "neural strata" = /obj/item/organ/internal/heart/diona, - "receptor node" = /obj/item/organ/internal/diona_receptor, + "receptor node" = /obj/item/organ/internal/eyes/diona, //Default darksight of 2. "gas bladder" = /obj/item/organ/internal/brain/diona, "polyp segment" = /obj/item/organ/internal/kidneys/diona, "anchoring ligament" = /obj/item/organ/internal/appendix/diona ) - vision_organ = /obj/item/organ/internal/diona_receptor + vision_organ = /obj/item/organ/internal/eyes/diona has_limbs = list( "chest" = list("path" = /obj/item/organ/external/chest/diona), "groin" = list("path" = /obj/item/organ/external/groin/diona), @@ -878,10 +896,10 @@ has_organ = list( "brain" = /obj/item/organ/internal/brain/mmi_holder/posibrain, "cell" = /obj/item/organ/internal/cell, - "optics" = /obj/item/organ/internal/optical_sensor + "optics" = /obj/item/organ/internal/eyes/optical_sensor //Default darksight of 2. ) - vision_organ = /obj/item/organ/internal/optical_sensor + vision_organ = /obj/item/organ/internal/eyes/optical_sensor has_limbs = list( "chest" = list("path" = /obj/item/organ/external/chest/ipc), "groin" = list("path" = /obj/item/organ/external/groin/ipc), @@ -927,7 +945,6 @@ language = "Orluum" unarmed_type = /datum/unarmed_attack/punch eyes = "drask_eyes_s" - darksight = 5 speech_sounds = list('sound/voice/DraskTalk.ogg') speech_chance = 20 @@ -977,7 +994,7 @@ "heart" = /obj/item/organ/internal/heart/drask, "lungs" = /obj/item/organ/internal/lungs/drask, "metabolic strainer" = /obj/item/organ/internal/liver/drask, - "eyes" = /obj/item/organ/internal/eyes/drask, + "eyes" = /obj/item/organ/internal/eyes/drask, //5 darksight. "brain" = /obj/item/organ/internal/brain/drask ) diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index 8cc51882ebf..27197474c00 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -72,6 +72,8 @@ for(var/datum/alternate_appearance/AA in viewing_alternate_appearances) AA.display_to(list(src)) + update_client_colour(0) + callHook("mob_login", list("client" = client, "mob" = src)) // Calling update_interface() in /mob/Login() causes the Cyborg to immediately be ghosted; because of winget(). diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 0b04647d094..e07fb765ce7 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -22,6 +22,24 @@ return 0 return 1 +/mob/proc/get_screen_colour() + +/mob/proc/update_client_colour(var/time = 10) //Update the mob's client.color with an animation the specified time in length. + if(!client) + return + client.colour_transition(get_screen_colour(), time = time) + +/mob/living/carbon/human/get_screen_colour() //Fetch the colour matrix from wherever (e.g. eyes) so it can be compared to client.color. + . = ..() + if(.) + return . + var/obj/item/clothing/glasses/worn_glasses = glasses + var/obj/item/organ/internal/eyes/eyes = get_int_organ(/obj/item/organ/internal/eyes) + if(istype(worn_glasses) && worn_glasses.color_view) //Check to see if they got those magic glasses and they're augmenting the colour of what the wearer sees. If they're not, color_view should be null. + return worn_glasses.color_view + else if(eyes && eyes.colourmatrix) //If they're not, check to see if their eyes got one of them there colour matrices. + return eyes.colourmatrix + /proc/isloyal(A) //Checks to see if the person contains a mindshield implant, then checks that the implant is actually inside of them for(var/obj/item/weapon/implant/loyalty/L in A) if(L && L.implanted) @@ -291,10 +309,10 @@ proc/muffledspeech(phrase) /mob/proc/abiotic(var/full_body = 0) - if(full_body && ((src.l_hand && !(src.l_hand.flags & ABSTRACT)) || (src.r_hand && !(src.r_hand.flags & ABSTRACT)) || (src.back || src.wear_mask))) + if(full_body && ((l_hand && !(l_hand.flags & ABSTRACT)) || (r_hand && !(r_hand.flags & ABSTRACT)) || (back || wear_mask))) return 1 - if((src.l_hand && !(src.l_hand.flags & ABSTRACT)) || (src.r_hand && !(src.r_hand.flags & ABSTRACT))) + if((l_hand && !(l_hand.flags & ABSTRACT)) || (r_hand && !(r_hand.flags & ABSTRACT))) return 1 return 0 @@ -586,8 +604,8 @@ var/list/intents = list(I_HELP,I_DISARM,I_GRAB,I_HARM) if(5) newletter="glor" newphrase+="[newletter]";counter-=1 - return newphrase - + return newphrase + /mob/proc/get_preference(toggleflag) if(!client) return FALSE diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index bccd7990de9..2233c617b6e 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -483,7 +483,7 @@ close_spawn_windows() check_prefs_are_sane() - var/mob/living/carbon/human/new_character = new(loc) + var/mob/living/carbon/human/new_character = new(loc, client.prefs.species) new_character.lastarea = get_area(loc) if(ticker.random_players || appearance_isbanned(new_character)) diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm index 702afa68f2f..46e5a478c88 100644 --- a/code/modules/research/designs/mechfabricator_designs.dm +++ b/code/modules/research/designs/mechfabricator_designs.dm @@ -1100,7 +1100,7 @@ name = "IPC Optical Sensor" id = "ipc_optics" build_type = MECHFAB - build_path = /obj/item/organ/internal/optical_sensor + build_path = /obj/item/organ/internal/eyes/optical_sensor materials = list(MAT_METAL=1000, MAT_GLASS=2500) construction_time = 200 category = list("Misc") diff --git a/code/modules/surgery/organs/helpers.dm b/code/modules/surgery/organs/helpers.dm index a61537f1985..24ae966cd14 100644 --- a/code/modules/surgery/organs/helpers.dm +++ b/code/modules/surgery/organs/helpers.dm @@ -13,7 +13,6 @@ /mob/living/carbon/get_int_organ(typepath) return (locate(typepath) in internal_organs) - /mob/living/carbon/get_organs_zone(zone, var/subzones = 0) var/list/returnorg = list() if(subzones) diff --git a/code/modules/surgery/organs/organ.dm b/code/modules/surgery/organs/organ.dm index 66436d22b64..f2da2d0a949 100644 --- a/code/modules/surgery/organs/organ.dm +++ b/code/modules/surgery/organs/organ.dm @@ -228,10 +228,10 @@ var/list/organ_cache = list() /obj/item/organ/proc/take_damage(amount, var/silent=0) if(tough) return - if(src.status & ORGAN_ROBOT) - src.damage = between(0, src.damage + (amount * 0.8), max_damage) + if(status & ORGAN_ROBOT) + damage = between(0, damage + (amount * 0.8), max_damage) else - src.damage = between(0, src.damage + amount, max_damage) + damage = between(0, damage + amount, max_damage) //only show this if the organ is not robotic if(owner && parent_organ && amount > 0) @@ -241,18 +241,18 @@ var/list/organ_cache = list() /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_ATTACHABLE - src.status &= ~ORGAN_DESTROYED - src.status |= ORGAN_ROBOT - src.status |= ORGAN_ASSISTED + status &= ~ORGAN_BROKEN + status &= ~ORGAN_BLEEDING + status &= ~ORGAN_SPLINTED + status &= ~ORGAN_CUT_AWAY + status &= ~ORGAN_ATTACHABLE + status &= ~ORGAN_DESTROYED + status |= ORGAN_ROBOT + status |= ORGAN_ASSISTED /obj/item/organ/proc/mechassist() //Used to add things like pacemakers, etc - robotize() - src.status &= ~ORGAN_ROBOT + robotize(1) //Skip the icon/name setting that occurs in robotize to avoid having to reset the icon file. + status &= ~ORGAN_ROBOT robotic = 1 min_bruised_damage = 15 min_broken_damage = 35 @@ -325,7 +325,7 @@ var/list/organ_cache = list() affected.internal_organs |= src if(!target.get_int_organ(src)) target.internal_organs += src - src.loc = target + loc = target if(robotic) status |= ORGAN_ROBOT diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index 5dd4d570ee2..79d1ed5faae 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -201,7 +201,7 @@ /obj/item/organ/internal/heart/prepare_eat() var/obj/S = ..() - S.icon_state = "heart-off" + S.icon_state = dead_icon return S /obj/item/organ/internal/heart/cursed @@ -343,16 +343,17 @@ parent_organ = "head" slot = "eyes" var/list/eye_colour = list(0,0,0) + var/list/colourmatrix = null + var/dark_view = 2 //Default dark_view for Humans. + var/weld_proof = null //If set, the eyes will not take damage during welding. eg. IPC optical sensors do not take damage when they weld things while all other eyes will. /obj/item/organ/internal/eyes/proc/update_colour() dna.write_eyes_attributes(src) -/obj/item/organ/internal/eyes/insert(mob/living/carbon/M, special = 0) +/obj/item/organ/internal/eyes/insert(mob/living/carbon/human/M, special = 0) ..() if(istype(M) && eye_colour) - var/mob/living/carbon/human/H = M - // Apply our eye colour to the target. - H.update_body() + M.update_body() //Apply our eye colour to the target. /obj/item/organ/internal/eyes/surgeryize() if(!owner) @@ -362,6 +363,38 @@ owner.SetEyeBlurry(0) owner.SetEyeBlind(0) +/obj/item/organ/internal/robotize(var/icon_bypass) //If icon bypass isn't null, skip the processing here and go straight to the parent call. + if(!icon_bypass && !(status & ORGAN_ROBOT)) //Don't override the icons for the already-mechanical IPC organs. + var/list/states = icon_states('icons/obj/surgery.dmi') //Insensitive to specially-defined icon files for species like the Drask or whomever else. Everyone gets the same robotic heart. + if(slot == "heart" && ("[slot]-prosthetic-on" in states) && ("[slot]-prosthetic-off" in states)) //Give the robotic heart its robotic heart icons if they exist. + var/obj/item/organ/internal/heart/H = src + H.icon = icon('icons/obj/surgery.dmi') + H.icon_base = "[slot]-prosthetic" + H.dead_icon = "[slot]-prosthetic-off" + H.update_icon() + else if("[slot]-prosthetic" in states) //Give the robotic organ its robotic organ icons if they exist. + icon = icon('icons/obj/surgery.dmi') + icon_state = "[slot]-prosthetic" + name = "mechanical [slot]" + ..() //Go apply all the organ flags/robotic statuses. + +/obj/item/organ/internal/eyes/robotize() + colourmatrix = null + dark_view = 2 + ..() //Make sure the organ's got the robotic status indicators before updating the client colour. + owner.update_client_colour(0) //Since both mechassisted and mechanical eyes give dark_view of 2 and full colour vision atm, just having this here is fine as mechassist() will call it anyway. + +/obj/item/organ/internal/mechassist() + ..() //Go back, call robotize(), adjust the robotic status indicators and the organ damage parameters. + var/list/states = icon_states(icon) //Sensitive to specially-defined icon files since the organs are not fully synthetic. + if(slot == "heart" && ("[organ_tag]-assisted-on" in states) && ("[organ_tag]-assisted-off" in states)) //Give the mechassisted heart its mechassisted heart icons if they exist. + var/obj/item/organ/internal/heart/H = src + H.icon_base = "[organ_tag]-assisted" + H.dead_icon = "[organ_tag]-assisted-off" + H.update_icon() + else if("[organ_tag]-assisted" in states) //Give the mechassisted organ its mechassisted organ icons if they exist. + icon_state = "[organ_tag]-assisted" + name = "mechanically assisted [initial(name)]" //Avoid setting the organ's name to something like "mechanically assisted mechanical eyes". /obj/item/organ/internal/liver name = "liver" @@ -372,7 +405,6 @@ var/alcohol_intensity = 1 /obj/item/organ/internal/liver/process() - ..() if(!owner) diff --git a/code/modules/surgery/organs/subtypes/abductor.dm b/code/modules/surgery/organs/subtypes/abductor.dm new file mode 100644 index 00000000000..6fd234bc501 --- /dev/null +++ b/code/modules/surgery/organs/subtypes/abductor.dm @@ -0,0 +1,4 @@ +/obj/item/organ/internal/eyes/abductor + name = "abductor eyeballs" + dark_view = 3 + species = "Abductor" diff --git a/code/modules/surgery/organs/subtypes/diona.dm b/code/modules/surgery/organs/subtypes/diona.dm index a4b0d8fb92b..729a87d2819 100644 --- a/code/modules/surgery/organs/subtypes/diona.dm +++ b/code/modules/surgery/organs/subtypes/diona.dm @@ -116,74 +116,42 @@ /obj/item/organ/diona/process() return -/obj/item/organ/internal/heart/diona +/obj/item/organ/internal/heart/diona // Turns into a nymph instantly, no transplanting possible. name = "neural strata" icon = 'icons/obj/objects.dmi' icon_state = "nymph" - organ_tag = "heart" // Turns into a nymph instantly, no transplanting possible. - origin_tech = "biotech=3" - parent_organ = "chest" - slot = "heart" species = "Diona" -/obj/item/organ/internal/brain/diona +/obj/item/organ/internal/brain/diona // Turns into a nymph instantly, no transplanting possible. name = "gas bladder" - parent_organ = "head" icon = 'icons/obj/objects.dmi' icon_state = "nymph" - organ_tag = "brain" // Turns into a nymph instantly, no transplanting possible. - origin_tech = "biotech=3" - slot = "brain" species = "Diona" -/obj/item/organ/internal/kidneys/diona +/obj/item/organ/internal/kidneys/diona // Turns into a nymph instantly, no transplanting possible. name = "polyp segment" icon = 'icons/obj/objects.dmi' icon_state = "nymph" - organ_tag = "kidneys" // Turns into a nymph instantly, no transplanting possible. - origin_tech = "biotech=3" - parent_organ = "groin" - slot = "kidneys" species = "Diona" -/obj/item/organ/internal/appendix/diona +/obj/item/organ/internal/appendix/diona // Turns into a nymph instantly, no transplanting possible. name = "anchoring ligament" icon = 'icons/obj/objects.dmi' icon_state = "nymph" - organ_tag = "appendix" // Turns into a nymph instantly, no transplanting possible. - origin_tech = "biotech=3" - parent_organ = "groin" - slot = "appendix" species = "Diona" -/obj/item/organ/internal/diona_receptor +/obj/item/organ/internal/eyes/diona // Turns into a nymph instantly, no transplanting possible. name = "receptor node" - organ_tag = "eyes" icon = 'icons/mob/alien.dmi' icon_state = "claw" - origin_tech = "biotech=3" - parent_organ = "head" - slot = "eyes" species = "Diona" -/obj/item/organ/internal/diona_receptor/surgeryize() - if(!owner) - return - owner.CureNearsighted() - owner.CureBlind() - owner.SetEyeBlurry(0) - owner.SetEyeBlind(0) - - //TODO:Make absorb rads on insert -/obj/item/organ/internal/liver/diona +/obj/item/organ/internal/liver/diona // Turns into a nymph instantly, no transplanting possible. name = "nutrient vessel" - parent_organ = "chest" - organ_tag = "liver" icon = 'icons/mob/alien.dmi' icon_state = "claw" - slot = "liver" alcohol_intensity = 0.5 species = "Diona" diff --git a/code/modules/surgery/organs/subtypes/drask.dm b/code/modules/surgery/organs/subtypes/drask.dm index b3b260a28a0..6e1e6662d0a 100644 --- a/code/modules/surgery/organs/subtypes/drask.dm +++ b/code/modules/surgery/organs/subtypes/drask.dm @@ -9,51 +9,29 @@ /obj/item/organ/internal/heart/drask name = "drask heart" icon = 'icons/obj/surgery_drask.dmi' - icon_state = "heart-on" - dead_icon = "heart-off" - organ_tag = "heart" parent_organ = "head" - slot = "heart" species = "Drask" /obj/item/organ/internal/lungs/drask - name = "lungs" icon = 'icons/obj/surgery_drask.dmi' - icon_state = "lungs" - gender = PLURAL - organ_tag = "lungs" - parent_organ = "chest" - slot = "lungs" species = "Drask" /obj/item/organ/internal/liver/drask name = "metabolic strainer" icon = 'icons/obj/surgery_drask.dmi' - icon_state = "kidneys" - gender = PLURAL - organ_tag = "kidneys" - parent_organ = "groin" - slot = "kidneys" alcohol_intensity = 0.8 species = "Drask" /obj/item/organ/internal/brain/drask - name = "brain" icon = 'icons/obj/surgery_drask.dmi' icon_state = "brain2" - organ_tag = "brain" - slot = "brain" mmi_icon = 'icons/obj/surgery_drask.dmi' mmi_icon_state = "mmi_full" species = "Drask" /obj/item/organ/internal/eyes/drask - name = "eyes" + name = "drask eyeballs" icon = 'icons/obj/surgery_drask.dmi' - icon_state = "eyes" - gender = PLURAL - organ_tag = "eyes" - parent_organ = "head" - slot = "eyes" desc = "Drask eyes. They look even stranger disembodied" + dark_view = 5 species = "Drask" diff --git a/code/modules/surgery/organs/subtypes/grey.dm b/code/modules/surgery/organs/subtypes/grey.dm index a47ab801d6f..6c06da373b7 100644 --- a/code/modules/surgery/organs/subtypes/grey.dm +++ b/code/modules/surgery/organs/subtypes/grey.dm @@ -14,3 +14,8 @@ /obj/item/organ/internal/brain/grey/remove(var/mob/living/carbon/M, var/special = 0) . = ..() M.remove_language("Psionic Communication") + +/obj/item/organ/internal/eyes/grey + name = "grey eyeballs" + dark_view = 5 + species = "Grey" diff --git a/code/modules/surgery/organs/subtypes/machine.dm b/code/modules/surgery/organs/subtypes/machine.dm index 0f402a42e5d..b3bb3f61e07 100644 --- a/code/modules/surgery/organs/subtypes/machine.dm +++ b/code/modules/surgery/organs/subtypes/machine.dm @@ -117,37 +117,26 @@ robotize() ..() -/obj/item/organ/internal/optical_sensor +/obj/item/organ/internal/eyes/optical_sensor name = "optical sensor" - organ_tag = "eyes" - parent_organ = "head" icon = 'icons/obj/robot_component.dmi' icon_state = "camera" - slot = "eyes" status = ORGAN_ROBOT species = "Machine" // dead_icon = "camera_broken" + weld_proof = 1 -/obj/item/organ/internal/optical_sensor/New() +/obj/item/organ/internal/eyes/optical_sensor/New() robotize() ..() -/obj/item/organ/internal/optical_sensor/remove(var/mob/living/user,special = 0) +/obj/item/organ/internal/eyes/optical_sensor/remove(var/mob/living/user,special = 0) if(!special) to_chat(owner, "Error 404:Optical Sensors not found.") . = ..() -/obj/item/organ/internal/optical_sensor/surgeryize() - if(!owner) - return - owner.CureNearsighted() - owner.CureBlind() - owner.SetEyeBlurry(0) - owner.SetEyeBlind(0) - - // Used for an MMI or posibrain being installed into a human. /obj/item/organ/internal/brain/mmi_holder name = "brain" @@ -160,7 +149,6 @@ species = "Machine" var/obj/item/device/mmi/stored_mmi - /obj/item/organ/internal/brain/mmi_holder/Destroy() if(stored_mmi) qdel(stored_mmi) diff --git a/code/modules/surgery/organs/subtypes/nucleation.dm b/code/modules/surgery/organs/subtypes/nucleation.dm index d234b666ae3..4223834501d 100644 --- a/code/modules/surgery/organs/subtypes/nucleation.dm +++ b/code/modules/surgery/organs/subtypes/nucleation.dm @@ -26,8 +26,6 @@ icon_state = "crystal-eyes" organ_tag = "luminescent eyes" light_color = "#1C1C00" - parent_organ = "head" - slot = "eyes" species = "Nucleation" /obj/item/organ/internal/eyes/luminescent_crystal/New() @@ -35,8 +33,7 @@ ..() /obj/item/organ/internal/brain/crystal - name = "crystalized brain" + name = "crystallized brain" icon_state = "crystal-brain" - organ_tag = "crystalized brain" - slot = "brain" + organ_tag = "crystallized brain" species = "Nucleation" diff --git a/code/modules/surgery/organs/subtypes/shadow.dm b/code/modules/surgery/organs/subtypes/shadow.dm new file mode 100644 index 00000000000..f81fc54bfb1 --- /dev/null +++ b/code/modules/surgery/organs/subtypes/shadow.dm @@ -0,0 +1,4 @@ +/obj/item/organ/internal/eyes/shadow + name = "dark orbs" + dark_view = 8 + species = "Shadow" diff --git a/code/modules/surgery/organs/subtypes/tajaran.dm b/code/modules/surgery/organs/subtypes/tajaran.dm index e37686a05ca..f65070feb6c 100644 --- a/code/modules/surgery/organs/subtypes/tajaran.dm +++ b/code/modules/surgery/organs/subtypes/tajaran.dm @@ -1,3 +1,12 @@ /obj/item/organ/internal/liver/tajaran alcohol_intensity = 1.4 species = "Tajaran" + +/obj/item/organ/internal/eyes/tajaran /*Most Tajara are surgically augmented at birth for full colour vision, although it cost them their darksight (darksight = 2) unless they choose otherwise in character creation (darksight = 8 but colourblind). + However, this organ define is for unaugmented eyes so cloned Tajara are colourblind but have excellent darksight.*/ + name = "tajaran eyeballs" + species = "Tajaran" + dark_view = 8 + colourmatrix = list(0.4,0.2,0.4,\ + 0.4,0.6,0.0,\ + 0.2,0.2,0.6) //Slightly less richness of hues or saturation of colours than Vulpkanin eyes. Pastel colour scheme, blues slightly green-shifted, reds slightly blue-shifted, greens yellow-shifted. diff --git a/code/modules/surgery/organs/subtypes/unathi.dm b/code/modules/surgery/organs/subtypes/unathi.dm index a769bce7a02..0fb45319ce5 100644 --- a/code/modules/surgery/organs/subtypes/unathi.dm +++ b/code/modules/surgery/organs/subtypes/unathi.dm @@ -1,3 +1,8 @@ /obj/item/organ/internal/liver/unathi alcohol_intensity = 0.8 species = "Unathi" + +/obj/item/organ/internal/eyes/unathi + name = "unathi eyeballs" + dark_view = 3 + species = "Unathi" diff --git a/code/modules/surgery/organs/subtypes/vulpkanin.dm b/code/modules/surgery/organs/subtypes/vulpkanin.dm index ca47ac83ddd..39ee9463425 100644 --- a/code/modules/surgery/organs/subtypes/vulpkanin.dm +++ b/code/modules/surgery/organs/subtypes/vulpkanin.dm @@ -1,3 +1,12 @@ /obj/item/organ/internal/liver/vulpkanin alcohol_intensity = 1.4 species = "Vulpkanin" + +/obj/item/organ/internal/eyes/vulpkanin /*Most Vulpkanin are surgically augmented at birth for full colour vision, although it cost them their darksight (darksight = 2) unless they choose otherwise in character creation (darksight = 8 but colourblind). + However, this organ define is for unaugmented eyes so cloned Vulpkanin are colourblind but have excellent darksight.*/ + name = "vulpkanin eyeballs" + species = "Vulpkanin" + dark_view = 8 + colourmatrix = list(0.5,0.4,0.1,\ + 0.5,0.4,0.1,\ + 0.0,0.2,0.8) //Seeing in tones of blues and yellows, blind to greens. More richness of hue and saturation of colour than Tajara. diff --git a/code/modules/surgery/organs/subtypes/wryn.dm b/code/modules/surgery/organs/subtypes/wryn.dm index f51adb6054e..ee1a12fd1ab 100644 --- a/code/modules/surgery/organs/subtypes/wryn.dm +++ b/code/modules/surgery/organs/subtypes/wryn.dm @@ -7,3 +7,7 @@ parent_organ = "head" slot = "hivenode" species = "Wryn" + +/obj/item/organ/internal/eyes/wryn + dark_view = 3 + species = "Wryn" diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm index f86cf41bcd0..73416045624 100644 --- a/code/modules/surgery/organs_internal.dm +++ b/code/modules/surgery/organs_internal.dm @@ -182,7 +182,7 @@ H.custom_pain("The pain in your [affected.name] is living hell!", 1) else if(istype(tool, /obj/item/weapon/reagent_containers/food/snacks/organ)) - to_chat(user, "[tool] was biten by someone! It's too damaged to use!") + to_chat(user, "[tool] was bitten by someone! It's too damaged to use!") return -1 ..() @@ -244,6 +244,8 @@ thing.forceMove(get_turf(target)) else user.put_in_hands(thing) + + target.update_icons() else user.visible_message("[user] can't seem to extract anything from [target]'s [parse_zone(target_zone)]!", "You can't extract anything from [target]'s [parse_zone(target_zone)]!") diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index 88161a20b5c2e7c031a5ab2afdee7c9e2421fdbc..db3343f1ca25a0e2671e4a37bd38bbfd5c016be1 100644 GIT binary patch literal 31898 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 Date: Fri, 20 Jan 2017 22:36:45 -0500 Subject: [PATCH 2/4] Changes Colourblindness from a Preference to a Disability For Vulpkanin and Tajara, it gives them their species-specific colourblindness but their excellent darksight, too. Otherwise it gives noir vision. You can choose this disability at character creation. It is off by default. You can turn it off via genetics and mutadone. Fixes Cling Transform&Lesser/Greater form & Darksight bugs Transforming to an identity will now, with 100% reliability, give you the exact appearance as that ability bar the body_accessory and the secondary hair/facial hair colours. Same thing with going from lesser form to an identity that was not the one you lesser formed with. Fixes the darksight bug from the last commit, happened 'cause typo. Woops. Eye Transplantation Applies Eye-dependent Genes Transplanting colourblind Vulpkanin/Tajara eyes into a Human gives the Human the dark_view and unique colourblindness of said Vulpkanin eyes. Removing colourblind eyes will take the disability with it, meaning the person will have colour vision/low darksight. --- code/__DEFINES/genetics.dm | 11 ++++-- code/__DEFINES/misc.dm | 10 ++++++ code/_globalvars/genetics.dm | 1 + code/game/dna/dna2.dm | 1 + code/game/dna/dna2_domutcheck.dm | 4 ++- code/game/dna/genes/disabilities.dm | 35 ++++++++++++++++++- code/game/dna/genes/gene.dm | 3 ++ .../gamemodes/changeling/powers/humanform.dm | 15 ++++---- .../gamemodes/changeling/powers/lesserform.dm | 7 +++- .../gamemodes/changeling/powers/transform.dm | 13 ++++--- code/game/gamemodes/setupgame.dm | 3 ++ code/modules/client/preference/preferences.dm | 14 ++++---- .../mob/living/carbon/human/species/monkey.dm | 31 ++++++++++++---- .../living/carbon/human/species/station.dm | 28 +++------------ code/modules/mob/transform_procs.dm | 1 - code/modules/surgery/organs/organ_internal.dm | 14 ++++++++ .../surgery/organs/subtypes/tajaran.dm | 9 ++--- .../surgery/organs/subtypes/vulpkanin.dm | 9 ++--- 18 files changed, 141 insertions(+), 68 deletions(-) diff --git a/code/__DEFINES/genetics.dm b/code/__DEFINES/genetics.dm index 11393957fc1..822179bf4cd 100644 --- a/code/__DEFINES/genetics.dm +++ b/code/__DEFINES/genetics.dm @@ -12,6 +12,7 @@ #define DISABILITY_FLAG_DEAF 8 #define DISABILITY_FLAG_BLIND 16 #define DISABILITY_FLAG_MUTE 32 +#define DISABILITY_FLAG_COLOURBLIND 64 /////////////////////////////////////// // MUTATIONS @@ -84,8 +85,9 @@ #define TOURETTES 8 #define NERVOUS 16 #define BLIND 32 -#define MUTE 64 -#define DEAF 128 +#define COLOURBLIND 64 +#define MUTE 128 +#define DEAF 256 //Nutrition levels for humans. No idea where else to put it #define NUTRITION_LEVEL_FAT 600 @@ -113,4 +115,7 @@ #define GENETIC_DAMAGE_STAGE_3 35 #define CLONER_FRESH_CLONE "fresh" -#define CLONER_MATURE_CLONE "mature" \ No newline at end of file +#define CLONER_MATURE_CLONE "mature" + +//Gene properties +#define GENE_EYE_DEPENDENT 1 diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 09ea7bf366f..bf19a447232 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -253,6 +253,16 @@ #define MATRIX_GREYSCALE list(0.33, 0.33, 0.33,\ 0.33, 0.33, 0.33,\ 0.33, 0.33, 0.33) + +#define MATRIX_VULP_CBLIND list(0.5,0.4,0.1,\ + 0.5,0.4,0.1,\ + 0.0,0.2,0.8) + +#define MATRIX_TAJ_CBLIND list(0.4,0.2,0.4,\ + 0.4,0.6,0.0,\ + 0.2,0.2,0.6) + + //Gun trigger guards #define TRIGGER_GUARD_ALLOW_ALL -1 #define TRIGGER_GUARD_NONE 0 diff --git a/code/_globalvars/genetics.dm b/code/_globalvars/genetics.dm index 73b2b7304f6..116aa0797cb 100644 --- a/code/_globalvars/genetics.dm +++ b/code/_globalvars/genetics.dm @@ -1,5 +1,6 @@ /////////// var/BLINDBLOCK = 0 +var/COLOURBLINDBLOCK = 0 var/DEAFBLOCK = 0 var/HULKBLOCK = 0 var/TELEBLOCK = 0 diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm index 82f7ffb2e93..2967dafe5ae 100644 --- a/code/game/dna/dna2.dm +++ b/code/game/dna/dna2.dm @@ -65,6 +65,7 @@ var/global/list/assigned_gene_blocks[DNA_SE_LENGTH] var/global/list/assigned_blocks[DNA_SE_LENGTH] var/global/list/datum/dna/gene/dna_genes[0] +var/global/list/datum/dna/gene/eye_dependent_genes[0] var/global/list/good_blocks[0] var/global/list/bad_blocks[0] diff --git a/code/game/dna/dna2_domutcheck.dm b/code/game/dna/dna2_domutcheck.dm index 6175d547d63..61ecb735459 100644 --- a/code/game/dna/dna2_domutcheck.dm +++ b/code/game/dna/dna2_domutcheck.dm @@ -44,7 +44,7 @@ var/mob/living/carbon/human/H = M defaultgenes = H.species.default_genes - if((gene in defaultgenes) && gene_active) + if((gene in defaultgenes) && gene_active && !gene.update) //Unless we want to update them with current information they depend on. return // Prior state @@ -65,3 +65,5 @@ gene.deactivate(M,connected,flags) if(M) M.active_genes -= gene.type + else if(gene.update && gene_active && (gene.type in M.active_genes)) //Update the gene. It should already be in the list of active genes. Updating is only useful if it's active. + gene.activate(M,connected,flags) diff --git a/code/game/dna/genes/disabilities.dm b/code/game/dna/genes/disabilities.dm index 4cfa6f45750..28c9c1c76b6 100644 --- a/code/game/dna/genes/disabilities.dm +++ b/code/game/dna/genes/disabilities.dm @@ -115,6 +115,40 @@ /datum/dna/gene/disability/blindness/New() block=BLINDBLOCK +/datum/dna/gene/disability/colourblindness + name="Colourblindness" + activation_message="Your perception of colour warps and distorts." + deactivation_message ="Your perception of colour returns to normal." + instability = -GENE_INSTABILITY_MODERATE + disability = COLOURBLIND + flags = GENE_EYE_DEPENDENT + update = 1 + +/datum/dna/gene/disability/colourblindness/New() + block=COLOURBLINDBLOCK + +/datum/dna/gene/disability/colourblindness/activate(var/mob/M, var/connected, var/flags) + ..(M,connected,flags) + var/mob/living/carbon/human/H = M + if(istype(M)) + var/obj/item/organ/internal/eyes/eyes = H.get_int_organ(/obj/item/organ/internal/eyes) + if(eyes && !eyes.robotic) //To avoid overriding the properties of cybernetic/mechassisted eyes, apply the colour matrix and darksight modifier only if the organ is organic. Robotic/mechassisted eyes currently do this, too, as is necessary. + var/list/cblind_properties = (eyes.colourblind_special) ? eyes.colourblind_special : null //If the mob's species has its own colourblindness parameters, gather them. + eyes.colourmatrix = (cblind_properties && cblind_properties["colour_matrix"]) ? cblind_properties["colour_matrix"] : MATRIX_GREYSCALE //If the mob's species has its own colourblindness colour matrix parameter, use it. + eyes.dark_view = (cblind_properties && cblind_properties["darkview"]) ? cblind_properties["darkview"] : eyes.dark_view //If the mob's species has its own colourblindness dark view parameter, use it. + H.update_client_colour() + +/datum/dna/gene/disability/colourblindness/deactivate(var/mob/M, var/connected, var/flags) + ..(M,connected,flags) + var/mob/living/carbon/human/H = M + if(istype(M)) + var/obj/item/organ/internal/eyes/eyes = H.get_int_organ(/obj/item/organ/internal/eyes) + if(eyes && !eyes.robotic) //To avoid overriding the properties of cybernetic/mechassisted eyes, apply the colour matrix and darksight modifier only if the organ is organic. Robotic/mechassisted eyes currently do this, too, as is necessary. + var/list/cblind_properties = (eyes.colourblind_special) ? eyes.colourblind_special : null //If the mob's species has its own colourblindness parameters, gather them. + eyes.colourmatrix = null //The only time a mob will have this set is if they're colourblind, so it's fine to null this out. + eyes.dark_view = (cblind_properties && cblind_properties["darkview"]) ? initial(eyes.dark_view) : eyes.dark_view //If the mob's species has its own colourblindness dark view parameter, set the mob's dark_view back to normal. + H.update_client_colour() + /datum/dna/gene/disability/deaf name="Deafness" activation_message="It's kinda quiet." @@ -139,7 +173,6 @@ /datum/dna/gene/disability/nearsighted/New() block=GLASSESBLOCK - /datum/dna/gene/disability/lisp name = "Lisp" desc = "I wonder wath thith doeth." diff --git a/code/game/dna/genes/gene.dm b/code/game/dna/genes/gene.dm index f74d0c7d2a0..63992e16a5f 100644 --- a/code/game/dna/genes/gene.dm +++ b/code/game/dna/genes/gene.dm @@ -26,6 +26,9 @@ // Chance of the gene to cause adverse effects when active var/instability=0 + // Whether the gene needs to be updated regardless of whether the mob has it or not. Useful for colour vision modifiers. + var/update=0 + /* * Is the gene active in this mob's DNA? */ diff --git a/code/game/gamemodes/changeling/powers/humanform.dm b/code/game/gamemodes/changeling/powers/humanform.dm index e587a7db0ab..aa333a865b5 100644 --- a/code/game/gamemodes/changeling/powers/humanform.dm +++ b/code/game/gamemodes/changeling/powers/humanform.dm @@ -24,15 +24,18 @@ if(!user) return 0 to_chat(user, "We transform our appearance.") - user.dna.SetSEState(MONKEYBLOCK,0) - domutcheck(user, null) // Do a pre-mutcheck to cleanly switch from monkey form. - user.dna = chosen_dna + user.dna.SetSEState(MONKEYBLOCK,0,1) + genemutcheck(user,MONKEYBLOCK,null,MUTCHK_FORCED) user.real_name = chosen_dna.real_name - user.flavor_text = "" if(ishuman(user)) - user.set_species() + user.set_species(chosen_dna.species) + user.dna = chosen_dna.Clone() + domutcheck(user, null, MUTCHK_FORCED) + user.flavor_text = "" + user.dna.UpdateSE() + user.dna.UpdateUI() + user.sync_organ_dna(1) user.UpdateAppearance() - domutcheck(user, null) changeling.purchasedpowers -= src //O.mind.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/lesserform(null) diff --git a/code/game/gamemodes/changeling/powers/lesserform.dm b/code/game/gamemodes/changeling/powers/lesserform.dm index e5040af282f..7316d635acf 100644 --- a/code/game/gamemodes/changeling/powers/lesserform.dm +++ b/code/game/gamemodes/changeling/powers/lesserform.dm @@ -21,13 +21,18 @@ to_chat(H, "We cannot perform this ability in this form!") return + var/datum/dna/DNA = changeling.GetDNA(user.dna.real_name) + user.dna = DNA ? DNA.Clone() : user.dna + H.visible_message("[H] transforms!") changeling.geneticdamage = 30 to_chat(H, "Our genes cry out!") var/list/implants = list() //Try to preserve implants. for(var/obj/item/weapon/implant/W in H) implants += W - H.monkeyize() + + user.dna.SetSEState(MONKEYBLOCK,1,1) + genemutcheck(user,MONKEYBLOCK,null,MUTCHK_FORCED) changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/humanform(null) feedback_add_details("changeling_powers","LF") return 1 \ No newline at end of file diff --git a/code/game/gamemodes/changeling/powers/transform.dm b/code/game/gamemodes/changeling/powers/transform.dm index f1ff51a42a2..5ca928c77c7 100644 --- a/code/game/gamemodes/changeling/powers/transform.dm +++ b/code/game/gamemodes/changeling/powers/transform.dm @@ -14,14 +14,17 @@ if(!chosen_dna) return - user.dna = chosen_dna.Clone() user.real_name = chosen_dna.real_name - user.flavor_text = "" if(ishuman(user)) - user.set_species() + user.set_species(chosen_dna.species) + user.dna = chosen_dna.Clone() + domutcheck(user, null, MUTCHK_FORCED) //Ensures species that get powers by the species proc handle_dna keep them + user.flavor_text = "" + user.dna.UpdateSE() + user.dna.UpdateUI() + user.sync_organ_dna(1) user.UpdateAppearance() - domutcheck(user, null) - + user.changeling_update_languages(changeling.absorbed_languages) feedback_add_details("changeling_powers","TR") diff --git a/code/game/gamemodes/setupgame.dm b/code/game/gamemodes/setupgame.dm index c177e85f870..e55d99c4c9e 100644 --- a/code/game/gamemodes/setupgame.dm +++ b/code/game/gamemodes/setupgame.dm @@ -35,6 +35,7 @@ // Standard muts BLINDBLOCK = getAssignedBlock("BLIND", numsToAssign) + COLOURBLINDBLOCK = getAssignedBlock("COLOURBLIND", numsToAssign) DEAFBLOCK = getAssignedBlock("DEAF", numsToAssign) HULKBLOCK = getAssignedBlock("HULK", numsToAssign, DNA_HARD_BOUNDS, good=1) TELEBLOCK = getAssignedBlock("TELE", numsToAssign, DNA_HARD_BOUNDS, good=1) @@ -115,6 +116,8 @@ if(G.block in blocks_assigned) warning("DNA2: Gene [G.name] trying to use already-assigned block [G.block] (used by [english_list(blocks_assigned[G.block])])") dna_genes.Add(G) + if(G.flags & GENE_EYE_DEPENDENT) + eye_dependent_genes.Add(G) var/list/assignedToBlock[0] if(blocks_assigned[G.block]) assignedToBlock=blocks_assigned[G.block] diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm index 4ec7516a409..8a2bec6a7ef 100644 --- a/code/modules/client/preference/preferences.dm +++ b/code/modules/client/preference/preferences.dm @@ -282,8 +282,6 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts dat += "Species: [species]
" if(species == "Vox") dat += "N2 Tank: [speciesprefs ? "Large N2 Tank" : "Specialized N2 Tank"]
" - else if(species in list("Vulpkanin", "Tajaran")) - dat += "Colour Vision: [speciesprefs ? "Unaugmented" : "Surgically Corrected"]
" dat += "Secondary Language: [language]
" dat += "Blood Type: [b_type]
" if(species in list("Human", "Drask", "Vox")) @@ -817,6 +815,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts HTML += ShowDisabilityState(user,DISABILITY_FLAG_EPILEPTIC,"Seizures") HTML += ShowDisabilityState(user,DISABILITY_FLAG_DEAF,"Deaf") HTML += ShowDisabilityState(user,DISABILITY_FLAG_BLIND,"Blind") + HTML += ShowDisabilityState(user,DISABILITY_FLAG_COLOURBLIND,"Colourblind") HTML += ShowDisabilityState(user,DISABILITY_FLAG_MUTE,"Mute") @@ -1340,12 +1339,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts organ_data = list() rlimb_data = list() if("speciesprefs") - if(species == "Vox") //oldvox code - speciesprefs = !speciesprefs //Starts 0, so if someone clicks the button up top there, this won't be 0 anymore. If they click it again, it'll go back to 0. - else if(species in list("Vulpkanin", "Tajaran")) //Species that can be colourblind. - var/list/vision_options = list("Surgically Corrected", "Unaugmented") //Surgically corrected eyes (default option) see in full colour but have 2 darksight. Unaugmented eyes are colourblind but have 8 darksight. - speciesprefs = input("Please select your vision preference. \nOverridden by mech. assisted or mechanical eyes. \nSurgically Corrected: Full colour, low darksight. \n Unaugmented: Colourblind, full darksight.", "Character Generation", 0) in vision_options - speciesprefs = (speciesprefs != "Surgically Corrected") //Ensure the default option (surgically corrected) returns 0. I would've set up the vision_options list such that Surgically Corrected = 0, but input() didn't care for it. + speciesprefs = !speciesprefs //Starts 0, so if someone clicks the button up top there, this won't be 0 anymore. If they click it again, it'll go back to 0. if("language") // var/languages_available var/list/new_languages = list("None") @@ -2173,6 +2167,10 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts character.dna.SetSEState(BLINDBLOCK,1,1) character.disabilities |= BLIND + if(disabilities & DISABILITY_FLAG_COLOURBLIND) + character.dna.SetSEState(COLOURBLINDBLOCK,1,1) + character.disabilities |= COLOURBLIND + if(disabilities & DISABILITY_FLAG_MUTE) character.dna.SetSEState(MUTEBLOCK,1,1) character.disabilities |= MUTE diff --git a/code/modules/mob/living/carbon/human/species/monkey.dm b/code/modules/mob/living/carbon/human/species/monkey.dm index 34f4e16bfdf..0108d693c18 100644 --- a/code/modules/mob/living/carbon/human/species/monkey.dm +++ b/code/modules/mob/living/carbon/human/species/monkey.dm @@ -54,8 +54,9 @@ ..() /datum/species/monkey/handle_dna(var/mob/living/carbon/human/H) - H.dna.SetSEState(MONKEYBLOCK,1) - genemutcheck(H, MONKEYBLOCK) + if(!is_type_in_list(/datum/dna/gene/monkey, H.active_genes)) //Only activate the monkey gene if it isn't already. + H.dna.SetSEState(MONKEYBLOCK,1,1) + genemutcheck(H,MONKEYBLOCK,null,MUTCHK_FORCED) /datum/species/monkey/handle_can_equip(obj/item/I, slot, disable_warning = 0, mob/living/carbon/human/user) switch(slot) @@ -106,7 +107,6 @@ base_color = "#000000" tail = "farwatail" reagent_tag = PROCESS_ORG - has_organ = list( "heart" = /obj/item/organ/internal/heart, "lungs" = /obj/item/organ/internal/lungs, @@ -114,8 +114,18 @@ "kidneys" = /obj/item/organ/internal/kidneys, "brain" = /obj/item/organ/internal/brain, "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes/tajaran //Tajara monkey-forms are uniquely colourblind and have excellent darksight. + "eyes" = /obj/item/organ/internal/eyes/tajaran //Tajara monkey-forms are uniquely colourblind and have excellent darksight, which is why they need the same organ as the Tajara. ) + default_genes = list(COLOURBLIND) + +/datum/species/monkey/tajaran/handle_dna(var/mob/living/carbon/C, var/remove) + if(!remove) + C.dna.SetSEState(COLOURBLINDBLOCK,1,1) + genemutcheck(C,COLOURBLINDBLOCK,null,MUTCHK_FORCED) + else + C.dna.SetSEState(COLOURBLINDBLOCK,0,1) + genemutcheck(C,COLOURBLINDBLOCK,null,MUTCHK_FORCED) + ..() /datum/species/monkey/vulpkanin @@ -131,7 +141,6 @@ base_color = "#000000" tail = "wolpintail" reagent_tag = PROCESS_ORG - has_organ = list( "heart" = /obj/item/organ/internal/heart, "lungs" = /obj/item/organ/internal/lungs, @@ -139,8 +148,18 @@ "kidneys" = /obj/item/organ/internal/kidneys, "brain" = /obj/item/organ/internal/brain, "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes/vulpkanin //Vulpkanin monkey-forms are uniquely colourblind and have excellent darksight. + "eyes" = /obj/item/organ/internal/eyes/vulpkanin //Vulpkanin monkey-forms are uniquely colourblind and have excellent darksight, which is why they need the same organ as the Vulpkanin. ) + default_genes = list(COLOURBLIND) + +/datum/species/monkey/vulpkanin/handle_dna(var/mob/living/carbon/C, var/remove) + if(!remove) + C.dna.SetSEState(COLOURBLINDBLOCK,1,1) + genemutcheck(C,COLOURBLINDBLOCK,null,MUTCHK_FORCED) + else + C.dna.SetSEState(COLOURBLINDBLOCK,0,1) + genemutcheck(C,COLOURBLINDBLOCK,null,MUTCHK_FORCED) + ..() /datum/species/monkey/skrell diff --git a/code/modules/mob/living/carbon/human/species/station.dm b/code/modules/mob/living/carbon/human/species/station.dm index 4ae52431e9a..f7635e2a9c4 100644 --- a/code/modules/mob/living/carbon/human/species/station.dm +++ b/code/modules/mob/living/carbon/human/species/station.dm @@ -125,8 +125,8 @@ "kidneys" = /obj/item/organ/internal/kidneys, "brain" = /obj/item/organ/internal/brain, "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes/tajaran /*Most Tajara are surgically augmented at birth for full colour vision, although it cost them their darksight (darksight = 2) unless they choose otherwise in character creation (darksight = 8 but colourblind). - However, this organ define is for unaugmented eyes so cloned Tajara are colourblind but have excellent darksight.*/ + "eyes" = /obj/item/organ/internal/eyes/tajaran /*Most Tajara see in full colour as a result of genetic augmentation, although it cost them their darksight (darksight = 2) + unless they choose otherwise by selecting the colourblind disability in character creation (darksight = 8 but colourblind).*/ ) allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/simple_animal/chick, /mob/living/simple_animal/butterfly, /mob/living/simple_animal/parrot, @@ -138,15 +138,6 @@ "is twisting their own neck!", "is holding their breath!") -/datum/species/tajaran/equip(var/mob/living/carbon/human/H) //Handles colourblindness preferences. Should only happen if the client is in a mob otherwise it won't work. - var/sight_pref = H.client.prefs.speciesprefs - if(!sight_pref) - var/obj/item/organ/internal/eyes/tajaran/tajeyes = H.get_int_organ(/obj/item/organ/internal/eyes) - if(tajeyes && !tajeyes.robotic) //To avoid overriding the properties of cybernetic/mechassisted eyes, apply the colour matrix and darksight modifier only if the organ is organic. Robotic/mechassisted eyes currently do this, too, as is necessary. - tajeyes.colourmatrix = null //For individuals who recieved the modification, they lose much of their darksight and gain full colour vision. - tajeyes.dark_view = 2 //If they didn't, they would have their unique colour-vision and full darksight. See code\modules\surgery\organs\subtypes\tajaran.dm - H.update_client_colour(0) - /datum/species/tajaran/handle_death(var/mob/living/carbon/human/H) H.stop_tail_wagging(1) @@ -184,8 +175,8 @@ "kidneys" = /obj/item/organ/internal/kidneys, "brain" = /obj/item/organ/internal/brain, "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes/vulpkanin /*Most Vulpkanin are surgically augmented at birth for full colour vision, although it cost them their darksight (darksight = 2) unless they choose otherwise in character creation (darksight = 8 but colourblind). - However, this organ define is for unaugmented eyes so cloned Vulpkanin are colourblind but have excellent darksight.*/ + "eyes" = /obj/item/organ/internal/eyes/vulpkanin /*Most Vulpkanin see in full colour as a result of genetic augmentation, although it cost them their darksight (darksight = 2) + unless they choose otherwise by selecting the colourblind disability in character creation (darksight = 8 but colourblind).*/ ) allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/simple_animal/lizard, /mob/living/simple_animal/chick, /mob/living/simple_animal/chicken, @@ -197,15 +188,6 @@ "is twisting their own neck!", "is holding their breath!") -/datum/species/vulpkanin/equip(var/mob/living/carbon/human/H) //Handles colourblindness preferences. Should only happen if the client is in a mob otherwise it won't work. - var/sight_pref = H.client.prefs.speciesprefs - if(!sight_pref) - var/obj/item/organ/internal/eyes/vulpkanin/vulpeyes = H.get_int_organ(/obj/item/organ/internal/eyes) - if(vulpeyes && !vulpeyes.robotic) //To avoid overriding the properties of cybernetic/mechassisted eyes, apply the colour matrix and darksight modifier only if the organ is organic. Robotic/mechassisted eyes currently do this, too, as is necessary. - vulpeyes.colourmatrix = null //For individuals who recieved the modification, they lose much of their darksight and gain full colour vision. - vulpeyes.dark_view = 2 //If they didn't, they would have their unique colour-vision and full darksight. See code\modules\surgery\organs\subtypes\vulpkanin.dm - H.update_client_colour(0) - /datum/species/vulpkanin/handle_death(var/mob/living/carbon/human/H) H.stop_tail_wagging(1) @@ -732,11 +714,9 @@ /datum/species/grey/handle_dna(var/mob/living/carbon/C, var/remove) if(!remove) C.dna.SetSEState(REMOTETALKBLOCK,1,1) - C.mutations |= REMOTE_TALK genemutcheck(C,REMOTETALKBLOCK,null,MUTCHK_FORCED) else C.dna.SetSEState(REMOTETALKBLOCK,0,1) - C.mutations -= REMOTE_TALK genemutcheck(C,REMOTETALKBLOCK,null,MUTCHK_FORCED) ..() diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 8adc505102b..a484324560d 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -1,7 +1,6 @@ /mob/living/carbon/human/proc/monkeyize() var/mob/H = src H.dna.SetSEState(MONKEYBLOCK,1) - domutcheck(H, null) /mob/new_player/AIize() spawning = 1 diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index 79d1ed5faae..514d836bfc3 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -344,6 +344,7 @@ slot = "eyes" var/list/eye_colour = list(0,0,0) var/list/colourmatrix = null + var/list/colourblind_special = list("colour_matrix" = null, "darkview" = null) //Special colourblindness parameters. var/dark_view = 2 //Default dark_view for Humans. var/weld_proof = null //If set, the eyes will not take damage during welding. eg. IPC optical sensors do not take damage when they weld things while all other eyes will. @@ -355,6 +356,19 @@ if(istype(M) && eye_colour) M.update_body() //Apply our eye colour to the target. + for(var/datum/dna/gene/G in eye_dependent_genes) //Handle the application of the eye-dependent genes from the eye to the new host mob if the genes are active. + if(dna && dna.GetSEState(G.block)) //If the eye-dependent gene in the eye's DNA is active, activate it on the human and genemutcheck to apply its effects. + M.dna.SetSEState(G.block,1,1) + genemutcheck(M,G.block,null,MUTCHK_FORCED) + +/obj/item/organ/internal/eyes/remove(mob/living/carbon/human/M, special = 0) + for(var/datum/dna/gene/G in eye_dependent_genes) //Handle the removal of the eye-dependent genes from the eye to the new host mob if the genes are active. + if(G.type in M.active_genes) //If there's an active eye-dependent gene on the mob, turn it off. + dna = M.dna.Clone() //Preserve the eye-dependent genes by ensuring the genome on the eyes remains intact. + M.dna.SetSEState(G.block,0,1) + genemutcheck(M,G.block,null,MUTCHK_FORCED) + .=..() + /obj/item/organ/internal/eyes/surgeryize() if(!owner) return diff --git a/code/modules/surgery/organs/subtypes/tajaran.dm b/code/modules/surgery/organs/subtypes/tajaran.dm index f65070feb6c..7feacd4fbc4 100644 --- a/code/modules/surgery/organs/subtypes/tajaran.dm +++ b/code/modules/surgery/organs/subtypes/tajaran.dm @@ -2,11 +2,8 @@ alcohol_intensity = 1.4 species = "Tajaran" -/obj/item/organ/internal/eyes/tajaran /*Most Tajara are surgically augmented at birth for full colour vision, although it cost them their darksight (darksight = 2) unless they choose otherwise in character creation (darksight = 8 but colourblind). - However, this organ define is for unaugmented eyes so cloned Tajara are colourblind but have excellent darksight.*/ +/obj/item/organ/internal/eyes/tajaran /*Most Tajara see in full colour as a result of genetic augmentation, although it cost them their darksight (darksight = 2) + unless they choose otherwise by selecting the colourblind disability in character creation (darksight = 8 but colourblind).*/ name = "tajaran eyeballs" species = "Tajaran" - dark_view = 8 - colourmatrix = list(0.4,0.2,0.4,\ - 0.4,0.6,0.0,\ - 0.2,0.2,0.6) //Slightly less richness of hues or saturation of colours than Vulpkanin eyes. Pastel colour scheme, blues slightly green-shifted, reds slightly blue-shifted, greens yellow-shifted. + colourblind_special = list("colour_matrix" = MATRIX_TAJ_CBLIND, "darkview" = 8) //The colour matrix and darksight parameters that the mob will recieve when they get the disability. diff --git a/code/modules/surgery/organs/subtypes/vulpkanin.dm b/code/modules/surgery/organs/subtypes/vulpkanin.dm index 39ee9463425..27172e50215 100644 --- a/code/modules/surgery/organs/subtypes/vulpkanin.dm +++ b/code/modules/surgery/organs/subtypes/vulpkanin.dm @@ -2,11 +2,8 @@ alcohol_intensity = 1.4 species = "Vulpkanin" -/obj/item/organ/internal/eyes/vulpkanin /*Most Vulpkanin are surgically augmented at birth for full colour vision, although it cost them their darksight (darksight = 2) unless they choose otherwise in character creation (darksight = 8 but colourblind). - However, this organ define is for unaugmented eyes so cloned Vulpkanin are colourblind but have excellent darksight.*/ +/obj/item/organ/internal/eyes/vulpkanin /*Most Vulpkanin see in full colour as a result of genetic augmentation, although it cost them their darksight (darksight = 2) + unless they choose otherwise by selecting the colourblind disability in character creation (darksight = 8 but colourblind).*/ name = "vulpkanin eyeballs" species = "Vulpkanin" - dark_view = 8 - colourmatrix = list(0.5,0.4,0.1,\ - 0.5,0.4,0.1,\ - 0.0,0.2,0.8) //Seeing in tones of blues and yellows, blind to greens. More richness of hue and saturation of colour than Tajara. + colourblind_special = list("colour_matrix" = MATRIX_VULP_CBLIND, "darkview" = 8) //The colour matrix and darksight parameters that the mob will recieve when they get the disability. From d73413b04662b6e0f2a0d0622943a865a734c351 Mon Sep 17 00:00:00 2001 From: KasparoVy Date: Mon, 23 Jan 2017 05:51:46 -0500 Subject: [PATCH 3/4] Uses the Disabilities system more correctly Allows eyes to track eye-dependent disabilities when removed from the mob. Farwas and Wolpins are now incurably colourblind (non-genetics based), so going lesser-form and back won't wipe your colourblindness. Eyes being straight-up deleted (as per how set_species() handles setting up the organs required for the species we're changing to) no longer wipes colourblindness. Now with more helper procs, less unnecessary commenting, random changes and other cleanliness-related tweaks. --- code/__DEFINES/genetics.dm | 3 -- code/game/dna/dna2.dm | 1 - code/game/dna/dna2_domutcheck.dm | 4 +-- code/game/dna/genes/disabilities.dm | 32 +++++-------------- code/game/dna/genes/gene.dm | 3 -- .../gamemodes/changeling/powers/humanform.dm | 8 ++--- .../gamemodes/changeling/powers/lesserform.dm | 5 +-- .../gamemodes/changeling/powers/transform.dm | 2 +- code/game/gamemodes/setupgame.dm | 2 -- code/game/machinery/adv_med.dm | 3 ++ code/game/objects/items/devices/flashlight.dm | 17 +++++----- code/modules/client/preference/preferences.dm | 5 +-- .../mob/living/carbon/human/species/monkey.dm | 24 ++------------ .../living/carbon/human/species/species.dm | 4 +-- code/modules/mob/mob_helpers.dm | 9 +++--- code/modules/mob/new_player/new_player.dm | 2 +- code/modules/mob/transform_procs.dm | 1 + code/modules/surgery/organs/helpers.dm | 1 + code/modules/surgery/organs/organ_internal.dm | 32 ++++++++++++------- .../surgery/organs/subtypes/tajaran.dm | 9 +++++- .../surgery/organs/subtypes/vulpkanin.dm | 9 +++++- nano/templates/adv_med.tmpl | 7 ++-- 22 files changed, 84 insertions(+), 99 deletions(-) diff --git a/code/__DEFINES/genetics.dm b/code/__DEFINES/genetics.dm index 822179bf4cd..8e7be007d12 100644 --- a/code/__DEFINES/genetics.dm +++ b/code/__DEFINES/genetics.dm @@ -116,6 +116,3 @@ #define CLONER_FRESH_CLONE "fresh" #define CLONER_MATURE_CLONE "mature" - -//Gene properties -#define GENE_EYE_DEPENDENT 1 diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm index 2967dafe5ae..82f7ffb2e93 100644 --- a/code/game/dna/dna2.dm +++ b/code/game/dna/dna2.dm @@ -65,7 +65,6 @@ var/global/list/assigned_gene_blocks[DNA_SE_LENGTH] var/global/list/assigned_blocks[DNA_SE_LENGTH] var/global/list/datum/dna/gene/dna_genes[0] -var/global/list/datum/dna/gene/eye_dependent_genes[0] var/global/list/good_blocks[0] var/global/list/bad_blocks[0] diff --git a/code/game/dna/dna2_domutcheck.dm b/code/game/dna/dna2_domutcheck.dm index 61ecb735459..6175d547d63 100644 --- a/code/game/dna/dna2_domutcheck.dm +++ b/code/game/dna/dna2_domutcheck.dm @@ -44,7 +44,7 @@ var/mob/living/carbon/human/H = M defaultgenes = H.species.default_genes - if((gene in defaultgenes) && gene_active && !gene.update) //Unless we want to update them with current information they depend on. + if((gene in defaultgenes) && gene_active) return // Prior state @@ -65,5 +65,3 @@ gene.deactivate(M,connected,flags) if(M) M.active_genes -= gene.type - else if(gene.update && gene_active && (gene.type in M.active_genes)) //Update the gene. It should already be in the list of active genes. Updating is only useful if it's active. - gene.activate(M,connected,flags) diff --git a/code/game/dna/genes/disabilities.dm b/code/game/dna/genes/disabilities.dm index 28c9c1c76b6..aaea991d5cf 100644 --- a/code/game/dna/genes/disabilities.dm +++ b/code/game/dna/genes/disabilities.dm @@ -116,38 +116,22 @@ block=BLINDBLOCK /datum/dna/gene/disability/colourblindness - name="Colourblindness" - activation_message="Your perception of colour warps and distorts." - deactivation_message ="Your perception of colour returns to normal." + name = "Colourblindness" + activation_message = "You feel a peculiar prickling in your eyes while your perception of colour changes." + deactivation_message ="Your eyes tingle unsettlingly, though everything seems to become alot more colourful." instability = -GENE_INSTABILITY_MODERATE disability = COLOURBLIND - flags = GENE_EYE_DEPENDENT - update = 1 /datum/dna/gene/disability/colourblindness/New() block=COLOURBLINDBLOCK /datum/dna/gene/disability/colourblindness/activate(var/mob/M, var/connected, var/flags) - ..(M,connected,flags) - var/mob/living/carbon/human/H = M - if(istype(M)) - var/obj/item/organ/internal/eyes/eyes = H.get_int_organ(/obj/item/organ/internal/eyes) - if(eyes && !eyes.robotic) //To avoid overriding the properties of cybernetic/mechassisted eyes, apply the colour matrix and darksight modifier only if the organ is organic. Robotic/mechassisted eyes currently do this, too, as is necessary. - var/list/cblind_properties = (eyes.colourblind_special) ? eyes.colourblind_special : null //If the mob's species has its own colourblindness parameters, gather them. - eyes.colourmatrix = (cblind_properties && cblind_properties["colour_matrix"]) ? cblind_properties["colour_matrix"] : MATRIX_GREYSCALE //If the mob's species has its own colourblindness colour matrix parameter, use it. - eyes.dark_view = (cblind_properties && cblind_properties["darkview"]) ? cblind_properties["darkview"] : eyes.dark_view //If the mob's species has its own colourblindness dark view parameter, use it. - H.update_client_colour() + ..() + M.update_client_colour() //Handle the activation of the colourblindness on the mob. /datum/dna/gene/disability/colourblindness/deactivate(var/mob/M, var/connected, var/flags) - ..(M,connected,flags) - var/mob/living/carbon/human/H = M - if(istype(M)) - var/obj/item/organ/internal/eyes/eyes = H.get_int_organ(/obj/item/organ/internal/eyes) - if(eyes && !eyes.robotic) //To avoid overriding the properties of cybernetic/mechassisted eyes, apply the colour matrix and darksight modifier only if the organ is organic. Robotic/mechassisted eyes currently do this, too, as is necessary. - var/list/cblind_properties = (eyes.colourblind_special) ? eyes.colourblind_special : null //If the mob's species has its own colourblindness parameters, gather them. - eyes.colourmatrix = null //The only time a mob will have this set is if they're colourblind, so it's fine to null this out. - eyes.dark_view = (cblind_properties && cblind_properties["darkview"]) ? initial(eyes.dark_view) : eyes.dark_view //If the mob's species has its own colourblindness dark view parameter, set the mob's dark_view back to normal. - H.update_client_colour() + ..() + M.update_client_colour() //Handle the deactivation of the colourblindness on the mob. /datum/dna/gene/disability/deaf name="Deafness" @@ -160,7 +144,7 @@ block=DEAFBLOCK /datum/dna/gene/disability/deaf/activate(var/mob/M, var/connected, var/flags) - ..(M,connected,flags) + ..() M.EarDeaf(1) /datum/dna/gene/disability/nearsighted diff --git a/code/game/dna/genes/gene.dm b/code/game/dna/genes/gene.dm index 63992e16a5f..f74d0c7d2a0 100644 --- a/code/game/dna/genes/gene.dm +++ b/code/game/dna/genes/gene.dm @@ -26,9 +26,6 @@ // Chance of the gene to cause adverse effects when active var/instability=0 - // Whether the gene needs to be updated regardless of whether the mob has it or not. Useful for colour vision modifiers. - var/update=0 - /* * Is the gene active in this mob's DNA? */ diff --git a/code/game/gamemodes/changeling/powers/humanform.dm b/code/game/gamemodes/changeling/powers/humanform.dm index aa333a865b5..fb3012cd274 100644 --- a/code/game/gamemodes/changeling/powers/humanform.dm +++ b/code/game/gamemodes/changeling/powers/humanform.dm @@ -26,11 +26,11 @@ to_chat(user, "We transform our appearance.") user.dna.SetSEState(MONKEYBLOCK,0,1) genemutcheck(user,MONKEYBLOCK,null,MUTCHK_FORCED) - user.real_name = chosen_dna.real_name - if(ishuman(user)) - user.set_species(chosen_dna.species) user.dna = chosen_dna.Clone() - domutcheck(user, null, MUTCHK_FORCED) + user.real_name = chosen_dna.real_name + if(istype(user)) + user.set_species(chosen_dna.species) + domutcheck(user,null,MUTCHK_FORCED) user.flavor_text = "" user.dna.UpdateSE() user.dna.UpdateUI() diff --git a/code/game/gamemodes/changeling/powers/lesserform.dm b/code/game/gamemodes/changeling/powers/lesserform.dm index 7316d635acf..9901768f1e5 100644 --- a/code/game/gamemodes/changeling/powers/lesserform.dm +++ b/code/game/gamemodes/changeling/powers/lesserform.dm @@ -23,16 +23,13 @@ var/datum/dna/DNA = changeling.GetDNA(user.dna.real_name) user.dna = DNA ? DNA.Clone() : user.dna - H.visible_message("[H] transforms!") changeling.geneticdamage = 30 to_chat(H, "Our genes cry out!") var/list/implants = list() //Try to preserve implants. for(var/obj/item/weapon/implant/W in H) implants += W - - user.dna.SetSEState(MONKEYBLOCK,1,1) - genemutcheck(user,MONKEYBLOCK,null,MUTCHK_FORCED) + H.monkeyize() changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/humanform(null) feedback_add_details("changeling_powers","LF") return 1 \ No newline at end of file diff --git a/code/game/gamemodes/changeling/powers/transform.dm b/code/game/gamemodes/changeling/powers/transform.dm index 5ca928c77c7..b7c8abefd1d 100644 --- a/code/game/gamemodes/changeling/powers/transform.dm +++ b/code/game/gamemodes/changeling/powers/transform.dm @@ -14,10 +14,10 @@ if(!chosen_dna) return + user.dna = chosen_dna.Clone() user.real_name = chosen_dna.real_name if(ishuman(user)) user.set_species(chosen_dna.species) - user.dna = chosen_dna.Clone() domutcheck(user, null, MUTCHK_FORCED) //Ensures species that get powers by the species proc handle_dna keep them user.flavor_text = "" user.dna.UpdateSE() diff --git a/code/game/gamemodes/setupgame.dm b/code/game/gamemodes/setupgame.dm index e55d99c4c9e..c785c511304 100644 --- a/code/game/gamemodes/setupgame.dm +++ b/code/game/gamemodes/setupgame.dm @@ -116,8 +116,6 @@ if(G.block in blocks_assigned) warning("DNA2: Gene [G.name] trying to use already-assigned block [G.block] (used by [english_list(blocks_assigned[G.block])])") dna_genes.Add(G) - if(G.flags & GENE_EYE_DEPENDENT) - eye_dependent_genes.Add(G) var/list/assignedToBlock[0] if(blocks_assigned[G.block]) assignedToBlock=blocks_assigned[G.block] diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index f7b793b6033..4f9e357cd61 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -453,6 +453,7 @@ occupantData["intOrgan"] = intOrganData occupantData["blind"] = (H.disabilities & BLIND) + occupantData["colourblind"] = (H.disabilities & COLOURBLIND) occupantData["nearsighted"] = (H.disabilities & NEARSIGHTED) data["occupant"] = occupantData @@ -639,6 +640,8 @@ dat += "" if(occupant.disabilities & BLIND) dat += "Cataracts detected.
" + if(occupant.disabilities & COLOURBLIND) + dat += "Photoreceptor abnormalities detected.
" if(occupant.disabilities & NEARSIGHTED) dat += "Retinal misalignment detected.
" else diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 7806982a627..d8f17ac4335 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -54,8 +54,8 @@ return var/mob/living/carbon/human/H = M //mob has protective eyewear - if(istype(M, /mob/living/carbon/human) && ((H.head && H.head.flags & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) || (H.glasses && H.glasses.flags & GLASSESCOVERSEYES))) - to_chat(user, "You're going to need to remove that [(H.head && H.head.flags & HEADCOVERSEYES) ? "helmet" : (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) ? "mask": "glasses"] first.") + if(istype(H) && ((H.head && H.head.flags & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) || (H.glasses && H.glasses.flags & GLASSESCOVERSEYES))) + to_chat(user, "You're going to need to remove that [(H.head && H.head.flags & HEADCOVERSEYES) ? "helmet" : (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) ? "mask" : "glasses"] first.") return if(M == user) //they're using it on themselves @@ -70,12 +70,13 @@ user.visible_message("[user] directs [src] to [M]'s eyes.", \ "You direct [src] to [M]'s eyes.") - if(istype(M, /mob/living/carbon/human)) //robots and aliens are unaffected - if(M.stat == DEAD || M.disabilities & BLIND) //mob is dead or fully blind - to_chat(user, "[M] pupils does not react to the light!") - else if(XRAY in M.mutations) //mob has X-RAY vision - to_chat(user, "[M] pupils give an eerie glow!") - else //they're okay! + if(istype(H)) //robots and aliens are unaffected + var/obj/item/organ/internal/eyes/eyes = H.get_int_organ(/obj/item/organ/internal/eyes) + if(M.stat == DEAD || !eyes || M.disabilities & BLIND) //mob is dead or fully blind + to_chat(user, "[M]'s pupils are unresponsive to the light!") + else if((XRAY in M.mutations) || (eyes.colourblind_darkview && eyes.colourblind_darkview == eyes.dark_view)) //The mob's either got the X-RAY vision or has a tapetum lucidum (extreme nightvision). + to_chat(user, "[M]'s pupils glow eerily!") + else //they're okay! if(M.flash_eyes(visual = 1)) to_chat(user, "[M]'s pupils narrow.") else diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm index 8a2bec6a7ef..fda5f7bedfb 100644 --- a/code/modules/client/preference/preferences.dm +++ b/code/modules/client/preference/preferences.dm @@ -2020,6 +2020,8 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts return 1 /datum/preferences/proc/copy_to(mob/living/carbon/human/character) + var/datum/species/S = all_species[species] + character.change_species(species) // Yell at me if this causes everything to melt if(be_random_name) real_name = random_name(gender,species) @@ -2169,13 +2171,12 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if(disabilities & DISABILITY_FLAG_COLOURBLIND) character.dna.SetSEState(COLOURBLINDBLOCK,1,1) - character.disabilities |= COLOURBLIND if(disabilities & DISABILITY_FLAG_MUTE) character.dna.SetSEState(MUTEBLOCK,1,1) character.disabilities |= MUTE - character.species.handle_dna(character) + S.handle_dna(character) if(character.dna.dirtySE) character.dna.UpdateSE() diff --git a/code/modules/mob/living/carbon/human/species/monkey.dm b/code/modules/mob/living/carbon/human/species/monkey.dm index 0108d693c18..c4c705829b4 100644 --- a/code/modules/mob/living/carbon/human/species/monkey.dm +++ b/code/modules/mob/living/carbon/human/species/monkey.dm @@ -114,18 +114,8 @@ "kidneys" = /obj/item/organ/internal/kidneys, "brain" = /obj/item/organ/internal/brain, "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes/tajaran //Tajara monkey-forms are uniquely colourblind and have excellent darksight, which is why they need the same organ as the Tajara. + "eyes" = /obj/item/organ/internal/eyes/tajaran/farwa //Tajara monkey-forms are uniquely colourblind and have excellent darksight, which is why they need a subtype of their greater-form's organ.. ) - default_genes = list(COLOURBLIND) - -/datum/species/monkey/tajaran/handle_dna(var/mob/living/carbon/C, var/remove) - if(!remove) - C.dna.SetSEState(COLOURBLINDBLOCK,1,1) - genemutcheck(C,COLOURBLINDBLOCK,null,MUTCHK_FORCED) - else - C.dna.SetSEState(COLOURBLINDBLOCK,0,1) - genemutcheck(C,COLOURBLINDBLOCK,null,MUTCHK_FORCED) - ..() /datum/species/monkey/vulpkanin @@ -148,18 +138,8 @@ "kidneys" = /obj/item/organ/internal/kidneys, "brain" = /obj/item/organ/internal/brain, "appendix" = /obj/item/organ/internal/appendix, - "eyes" = /obj/item/organ/internal/eyes/vulpkanin //Vulpkanin monkey-forms are uniquely colourblind and have excellent darksight, which is why they need the same organ as the Vulpkanin. + "eyes" = /obj/item/organ/internal/eyes/vulpkanin/wolpin //Vulpkanin monkey-forms are uniquely colourblind and have excellent darksight, which is why they need a subtype of their greater-form's organ.. ) - default_genes = list(COLOURBLIND) - -/datum/species/monkey/vulpkanin/handle_dna(var/mob/living/carbon/C, var/remove) - if(!remove) - C.dna.SetSEState(COLOURBLINDBLOCK,1,1) - genemutcheck(C,COLOURBLINDBLOCK,null,MUTCHK_FORCED) - else - C.dna.SetSEState(COLOURBLINDBLOCK,0,1) - genemutcheck(C,COLOURBLINDBLOCK,null,MUTCHK_FORCED) - ..() /datum/species/monkey/skrell diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 73c557c9c58..7ac64189ce8 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -588,8 +588,8 @@ It'll return null if the organ doesn't correspond, so include null checks when u /datum/species/proc/get_resultant_darksight(mob/living/carbon/human/H) //Returns default value of 2 if the mob doesn't have eyes, otherwise it grabs the eyes darksight. var/resultant_darksight = 2 var/obj/item/organ/internal/eyes/eyes = H.get_int_organ(/obj/item/organ/internal/eyes) - if(eyes && eyes.dark_view) - resultant_darksight = eyes.dark_view + if(eyes) + resultant_darksight = eyes.get_dark_view() return resultant_darksight /datum/species/proc/update_sight(mob/living/carbon/human/H) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index e07fb765ce7..93c79aeebfc 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -25,20 +25,21 @@ /mob/proc/get_screen_colour() /mob/proc/update_client_colour(var/time = 10) //Update the mob's client.color with an animation the specified time in length. - if(!client) + if(!client) //No client_colour without client. If the player logs back in they'll be back through here anyway. return - client.colour_transition(get_screen_colour(), time = time) + client.colour_transition(get_screen_colour(), time = time) //Get the colour matrix we're going to transition to depending on relevance (magic glasses first, eyes second). /mob/living/carbon/human/get_screen_colour() //Fetch the colour matrix from wherever (e.g. eyes) so it can be compared to client.color. . = ..() if(.) return . + var/obj/item/clothing/glasses/worn_glasses = glasses var/obj/item/organ/internal/eyes/eyes = get_int_organ(/obj/item/organ/internal/eyes) if(istype(worn_glasses) && worn_glasses.color_view) //Check to see if they got those magic glasses and they're augmenting the colour of what the wearer sees. If they're not, color_view should be null. return worn_glasses.color_view - else if(eyes && eyes.colourmatrix) //If they're not, check to see if their eyes got one of them there colour matrices. - return eyes.colourmatrix + else if(eyes) //If they're not, check to see if their eyes got one of them there colour matrices. Will be null if eyes are robotic/the mob isn't colourblind and they have no default colour matrix. + return eyes.get_colourmatrix() /proc/isloyal(A) //Checks to see if the person contains a mindshield implant, then checks that the implant is actually inside of them for(var/obj/item/weapon/implant/loyalty/L in A) diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 2233c617b6e..bccd7990de9 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -483,7 +483,7 @@ close_spawn_windows() check_prefs_are_sane() - var/mob/living/carbon/human/new_character = new(loc, client.prefs.species) + var/mob/living/carbon/human/new_character = new(loc) new_character.lastarea = get_area(loc) if(ticker.random_players || appearance_isbanned(new_character)) diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index a484324560d..8adc505102b 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -1,6 +1,7 @@ /mob/living/carbon/human/proc/monkeyize() var/mob/H = src H.dna.SetSEState(MONKEYBLOCK,1) + domutcheck(H, null) /mob/new_player/AIize() spawning = 1 diff --git a/code/modules/surgery/organs/helpers.dm b/code/modules/surgery/organs/helpers.dm index 24ae966cd14..a61537f1985 100644 --- a/code/modules/surgery/organs/helpers.dm +++ b/code/modules/surgery/organs/helpers.dm @@ -13,6 +13,7 @@ /mob/living/carbon/get_int_organ(typepath) return (locate(typepath) in internal_organs) + /mob/living/carbon/get_organs_zone(zone, var/subzones = 0) var/list/returnorg = list() if(subzones) diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index 514d836bfc3..c6a81e04481 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -344,30 +344,40 @@ slot = "eyes" var/list/eye_colour = list(0,0,0) var/list/colourmatrix = null - var/list/colourblind_special = list("colour_matrix" = null, "darkview" = null) //Special colourblindness parameters. + var/list/colourblind_matrix = null //Special colourblindness parameters. + var/colourblind_darkview = null + var/dependent_disabilities = null //Gets set by eye-dependent disabilities such as colourblindness so the eyes can transfer the disability during transplantation. var/dark_view = 2 //Default dark_view for Humans. var/weld_proof = null //If set, the eyes will not take damage during welding. eg. IPC optical sensors do not take damage when they weld things while all other eyes will. /obj/item/organ/internal/eyes/proc/update_colour() dna.write_eyes_attributes(src) +/obj/item/organ/internal/eyes/proc/get_colourmatrix() //Returns a colour matrix if the eyes are organic. + return !robotic && owner.disabilities & COLOURBLIND ? (colourblind_matrix ? colourblind_matrix : MATRIX_GREYSCALE) : colourmatrix //Returns special colourmatrix if colourblind and it exists and greyscale if it doesn't, otherwise returns current velue. + +/obj/item/organ/internal/eyes/proc/get_dark_view() //Returns dark_view (if the eyes are organic) for see_invisible handling in species.dm to be autoprocessed by life(). + return !robotic && colourblind_darkview && owner.disabilities & COLOURBLIND ? colourblind_darkview : dark_view //Returns special darkview value if colourblind and it exists, otherwise returns current velue. + /obj/item/organ/internal/eyes/insert(mob/living/carbon/human/M, special = 0) ..() if(istype(M) && eye_colour) M.update_body() //Apply our eye colour to the target. - for(var/datum/dna/gene/G in eye_dependent_genes) //Handle the application of the eye-dependent genes from the eye to the new host mob if the genes are active. - if(dna && dna.GetSEState(G.block)) //If the eye-dependent gene in the eye's DNA is active, activate it on the human and genemutcheck to apply its effects. - M.dna.SetSEState(G.block,1,1) - genemutcheck(M,G.block,null,MUTCHK_FORCED) + if(!(M.disabilities & COLOURBLIND) && (dependent_disabilities & COLOURBLIND)) //If the eyes are colourblind and we're not, carry over the gene. + dependent_disabilities &= ~COLOURBLIND + M.dna.SetSEState(COLOURBLINDBLOCK,1,1) + genemutcheck(M,COLOURBLINDBLOCK,null,MUTCHK_FORCED) + else + M.update_client_colour() //If we're here, that means the mob acquired the colourblindness gene while they didn't have eyes. Better handle it. /obj/item/organ/internal/eyes/remove(mob/living/carbon/human/M, special = 0) - for(var/datum/dna/gene/G in eye_dependent_genes) //Handle the removal of the eye-dependent genes from the eye to the new host mob if the genes are active. - if(G.type in M.active_genes) //If there's an active eye-dependent gene on the mob, turn it off. - dna = M.dna.Clone() //Preserve the eye-dependent genes by ensuring the genome on the eyes remains intact. - M.dna.SetSEState(G.block,0,1) - genemutcheck(M,G.block,null,MUTCHK_FORCED) - .=..() + if(!special && (M.disabilities & COLOURBLIND)) //If special is set, that means these eyes are getting deleted (i.e. during set_species()) + if(!(dependent_disabilities & COLOURBLIND)) //We only want to change COLOURBLINDBLOCK and such it the eyes are being surgically removed. + dependent_disabilities |= COLOURBLIND + M.dna.SetSEState(COLOURBLINDBLOCK,0,1) + genemutcheck(M,COLOURBLINDBLOCK,null,MUTCHK_FORCED) + . = ..() /obj/item/organ/internal/eyes/surgeryize() if(!owner) diff --git a/code/modules/surgery/organs/subtypes/tajaran.dm b/code/modules/surgery/organs/subtypes/tajaran.dm index 7feacd4fbc4..746abd6e601 100644 --- a/code/modules/surgery/organs/subtypes/tajaran.dm +++ b/code/modules/surgery/organs/subtypes/tajaran.dm @@ -6,4 +6,11 @@ unless they choose otherwise by selecting the colourblind disability in character creation (darksight = 8 but colourblind).*/ name = "tajaran eyeballs" species = "Tajaran" - colourblind_special = list("colour_matrix" = MATRIX_TAJ_CBLIND, "darkview" = 8) //The colour matrix and darksight parameters that the mob will recieve when they get the disability. + colourblind_matrix = MATRIX_TAJ_CBLIND //The colour matrix and darksight parameters that the mob will recieve when they get the disability. + colourblind_darkview = 8 + +/obj/item/organ/internal/eyes/tajaran/farwa //Being the lesser form of Tajara, Farwas have an utterly incurable version of their colourblindness. + name = "farwa eyeballs" + species = "Farwa" + colourmatrix = MATRIX_TAJ_CBLIND + dark_view = 8 diff --git a/code/modules/surgery/organs/subtypes/vulpkanin.dm b/code/modules/surgery/organs/subtypes/vulpkanin.dm index 27172e50215..af3d9deab09 100644 --- a/code/modules/surgery/organs/subtypes/vulpkanin.dm +++ b/code/modules/surgery/organs/subtypes/vulpkanin.dm @@ -6,4 +6,11 @@ unless they choose otherwise by selecting the colourblind disability in character creation (darksight = 8 but colourblind).*/ name = "vulpkanin eyeballs" species = "Vulpkanin" - colourblind_special = list("colour_matrix" = MATRIX_VULP_CBLIND, "darkview" = 8) //The colour matrix and darksight parameters that the mob will recieve when they get the disability. + colourblind_matrix = MATRIX_VULP_CBLIND //The colour matrix and darksight parameters that the mob will recieve when they get the disability. + colourblind_darkview = 8 + +/obj/item/organ/internal/eyes/vulpkanin/wolpin //Being the lesser form of Vulpkanin, Wolpins have an utterly incurable version of their colourblindness. + name = "wolpin eyeballs" + species = "Wolpin" + colourmatrix = MATRIX_VULP_CBLIND + dark_view = 8 diff --git a/nano/templates/adv_med.tmpl b/nano/templates/adv_med.tmpl index 51b74a12fda..e88db47456a 100644 --- a/nano/templates/adv_med.tmpl +++ b/nano/templates/adv_med.tmpl @@ -52,10 +52,13 @@ Used In File(s): \code\game\machinery\adv_med.dm Large growth detected in frontal lobe, possibly cancerous. Surgical removal is recommended.
{{/if}} {{if data.occupant.blind}} - Pupils unresponsive.
+ Cataracts detected.
+ {{/if}} + {{if data.occupant.colourblind}} + Photoreceptor abnormalities detected.
{{/if}} {{if data.occupant.nearsighted}} - Retinal misalignment detected
+ Retinal misalignment detected.
{{/if}}
From 8be26937983c45883a06427fc6756dece48fdb15 Mon Sep 17 00:00:00 2001 From: KasparoVy Date: Fri, 27 Jan 2017 19:15:38 -0500 Subject: [PATCH 4/4] Minor Tweaks & Fixes - Updated the flashlight eye-shine check with the new get_dark_view() helper proc - Removed a useless check on the handle_dna() for monkeys - Increases reliability of the monkeyize() proc and fixes issues where calling it wouldn't turn a mob into a monkey on the spot. - Increases readability/maintainability of the get_colourmatrix() and get_dark_view() procs. --- .../gamemodes/changeling/powers/lesserform.dm | 3 +-- code/game/objects/items/devices/flashlight.dm | 2 +- .../mob/living/carbon/human/species/monkey.dm | 5 ++--- code/modules/mob/transform_procs.dm | 2 +- code/modules/surgery/organs/organ_internal.dm | 18 ++++++++++++------ 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/code/game/gamemodes/changeling/powers/lesserform.dm b/code/game/gamemodes/changeling/powers/lesserform.dm index 9901768f1e5..8ba1e53cb10 100644 --- a/code/game/gamemodes/changeling/powers/lesserform.dm +++ b/code/game/gamemodes/changeling/powers/lesserform.dm @@ -21,8 +21,7 @@ to_chat(H, "We cannot perform this ability in this form!") return - var/datum/dna/DNA = changeling.GetDNA(user.dna.real_name) - user.dna = DNA ? DNA.Clone() : user.dna + user.dna = user.dna.Clone() H.visible_message("[H] transforms!") changeling.geneticdamage = 30 to_chat(H, "Our genes cry out!") diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index d8f17ac4335..216c37e7a51 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -74,7 +74,7 @@ var/obj/item/organ/internal/eyes/eyes = H.get_int_organ(/obj/item/organ/internal/eyes) if(M.stat == DEAD || !eyes || M.disabilities & BLIND) //mob is dead or fully blind to_chat(user, "[M]'s pupils are unresponsive to the light!") - else if((XRAY in M.mutations) || (eyes.colourblind_darkview && eyes.colourblind_darkview == eyes.dark_view)) //The mob's either got the X-RAY vision or has a tapetum lucidum (extreme nightvision). + else if((XRAY in M.mutations) || (eyes.colourblind_darkview && eyes.colourblind_darkview == eyes.get_dark_view())) //The mob's either got the X-RAY vision or has a tapetum lucidum (extreme nightvision, i.e. Vulp/Tajara with COLOURBLIND & their monkey forms). to_chat(user, "[M]'s pupils glow eerily!") else //they're okay! if(M.flash_eyes(visual = 1)) diff --git a/code/modules/mob/living/carbon/human/species/monkey.dm b/code/modules/mob/living/carbon/human/species/monkey.dm index c4c705829b4..6e29d658cfe 100644 --- a/code/modules/mob/living/carbon/human/species/monkey.dm +++ b/code/modules/mob/living/carbon/human/species/monkey.dm @@ -54,9 +54,8 @@ ..() /datum/species/monkey/handle_dna(var/mob/living/carbon/human/H) - if(!is_type_in_list(/datum/dna/gene/monkey, H.active_genes)) //Only activate the monkey gene if it isn't already. - H.dna.SetSEState(MONKEYBLOCK,1,1) - genemutcheck(H,MONKEYBLOCK,null,MUTCHK_FORCED) + H.dna.SetSEState(MONKEYBLOCK,1) + genemutcheck(H,MONKEYBLOCK,null,MUTCHK_FORCED) /datum/species/monkey/handle_can_equip(obj/item/I, slot, disable_warning = 0, mob/living/carbon/human/user) switch(slot) diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 8adc505102b..f7fb545d495 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -1,7 +1,7 @@ /mob/living/carbon/human/proc/monkeyize() var/mob/H = src H.dna.SetSEState(MONKEYBLOCK,1) - domutcheck(H, null) + genemutcheck(H,MONKEYBLOCK,null,MUTCHK_FORCED) /mob/new_player/AIize() spawning = 1 diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index c6a81e04481..b951b8c0774 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -344,7 +344,7 @@ slot = "eyes" var/list/eye_colour = list(0,0,0) var/list/colourmatrix = null - var/list/colourblind_matrix = null //Special colourblindness parameters. + var/list/colourblind_matrix = MATRIX_GREYSCALE //Special colourblindness parameters. By default, it's black-and-white. var/colourblind_darkview = null var/dependent_disabilities = null //Gets set by eye-dependent disabilities such as colourblindness so the eyes can transfer the disability during transplantation. var/dark_view = 2 //Default dark_view for Humans. @@ -353,11 +353,17 @@ /obj/item/organ/internal/eyes/proc/update_colour() dna.write_eyes_attributes(src) -/obj/item/organ/internal/eyes/proc/get_colourmatrix() //Returns a colour matrix if the eyes are organic. - return !robotic && owner.disabilities & COLOURBLIND ? (colourblind_matrix ? colourblind_matrix : MATRIX_GREYSCALE) : colourmatrix //Returns special colourmatrix if colourblind and it exists and greyscale if it doesn't, otherwise returns current velue. +/obj/item/organ/internal/eyes/proc/get_colourmatrix() //Returns a special colour matrix if the eyes are organic and the mob is colourblind, otherwise it uses the current one. + if(!robotic && owner.disabilities & COLOURBLIND) + return colourblind_matrix + else + return colourmatrix /obj/item/organ/internal/eyes/proc/get_dark_view() //Returns dark_view (if the eyes are organic) for see_invisible handling in species.dm to be autoprocessed by life(). - return !robotic && colourblind_darkview && owner.disabilities & COLOURBLIND ? colourblind_darkview : dark_view //Returns special darkview value if colourblind and it exists, otherwise returns current velue. + if(!robotic && colourblind_darkview && owner.disabilities & COLOURBLIND) //Returns special darkview value if colourblind and it exists, otherwise reuse current. + return colourblind_darkview + else + return dark_view /obj/item/organ/internal/eyes/insert(mob/living/carbon/human/M, special = 0) ..() @@ -366,7 +372,7 @@ if(!(M.disabilities & COLOURBLIND) && (dependent_disabilities & COLOURBLIND)) //If the eyes are colourblind and we're not, carry over the gene. dependent_disabilities &= ~COLOURBLIND - M.dna.SetSEState(COLOURBLINDBLOCK,1,1) + M.dna.SetSEState(COLOURBLINDBLOCK,1) genemutcheck(M,COLOURBLINDBLOCK,null,MUTCHK_FORCED) else M.update_client_colour() //If we're here, that means the mob acquired the colourblindness gene while they didn't have eyes. Better handle it. @@ -375,7 +381,7 @@ if(!special && (M.disabilities & COLOURBLIND)) //If special is set, that means these eyes are getting deleted (i.e. during set_species()) if(!(dependent_disabilities & COLOURBLIND)) //We only want to change COLOURBLINDBLOCK and such it the eyes are being surgically removed. dependent_disabilities |= COLOURBLIND - M.dna.SetSEState(COLOURBLINDBLOCK,0,1) + M.dna.SetSEState(COLOURBLINDBLOCK,0) genemutcheck(M,COLOURBLINDBLOCK,null,MUTCHK_FORCED) . = ..()