From 55504da79d0c5153fd8fcd90e9e1a66698c05daa Mon Sep 17 00:00:00 2001 From: Waterpig <49160555+Majkl-J@users.noreply.github.com> Date: Tue, 5 Aug 2025 20:09:38 -0400 Subject: [PATCH] Datumizes DNA blocks, makes DNA cleaner in general (#92061) Moves all the dna block handling onto singleton datums initialized inside global lists, to make the handling dna less of a copy-paste mess and make adding new blocks significantly easier. There is still some work to be done in the copypaste department but ultimately that falls under its own PR scope after the core refactor goes through. (Ill probably do those but it will also be easier for everyone else as the code is now significantly less of an eyesore) Both features and identities have been tested through and through, and seem to be working fine. Also removed the reliance on weird hardcoded lookup tables for length, and other similar things that just didn't make sense when I was passing through DNA code. There's a lot more that fall out of scope for this exact PR's goal however I've been told the maintainers will love me for doing this :cl: code: feature keys are no longer magical strings floating around the codebase and use proper defines refactor: DNA blocks are now handled with singleton datums. /:cl: --- code/__DEFINES/DNA.dm | 84 ++-- code/__DEFINES/~skyrat_defines/DNA.dm | 11 + code/__HELPERS/dna.dm | 2 - code/_globalvars/lists/mobs.dm | 18 + .../subsystem/sprite_accessories.dm | 24 +- .../markings_bodypart_overlay.dm | 4 +- code/datums/dna/blocks/dna_features_block.dm | 151 ++++++++ code/datums/dna/blocks/dna_identity_block.dm | 129 +++++++ code/datums/{ => dna}/dna.dm | 365 +++--------------- code/datums/dna/dna_block.dm | 69 ++++ .../quirks/neutral_quirks/heretochromatic.dm | 2 +- .../dna_infuser/organ_sets/fish_organs.dm | 10 +- .../dna_infuser/organ_sets/fox_organs.dm | 2 +- code/game/objects/structures/mirror.dm | 17 +- code/modules/admin/verbs/secrets.dm | 2 +- code/modules/antagonists/brother/brother.dm | 10 +- .../preferences/species_features/ethereal.dm | 2 +- .../preferences/species_features/felinid.dm | 4 +- .../preferences/species_features/lizard.dm | 14 +- .../preferences/species_features/monkey.dm | 2 +- .../preferences/species_features/moth.dm | 7 +- .../species_features/mushperson.dm | 2 +- .../preferences/species_features/mutants.dm | 2 +- .../preferences/species_features/pod.dm | 4 +- code/modules/hydroponics/grown/replicapod.dm | 8 +- .../mining_loot/megafauna/ash_drake.dm | 69 ++-- code/modules/mob/living/blood_types.dm | 4 +- .../mob/living/carbon/human/_species.dm | 6 +- code/modules/mob/living/carbon/human/dummy.dm | 34 +- .../carbon/human/species_types/ethereal.dm | 10 +- .../carbon/human/species_types/felinid.dm | 12 +- .../carbon/human/species_types/jellypeople.dm | 10 +- .../human/species_types/lizardpeople.dm | 8 +- .../carbon/human/species_types/mothmen.dm | 2 +- .../carbon/human/species_types/mushpeople.dm | 4 +- .../carbon/human/species_types/podpeople.dm | 4 +- .../carbon/human/species_types/snail.dm | 2 +- .../modules/mob/living/carbon/init_signals.dm | 10 +- .../reagents/drinks/alcohol_reagents.dm | 2 +- .../chemistry/reagents/other_reagents.dm | 6 +- .../research/xenobiology/xenobiology.dm | 4 +- code/modules/surgery/bodyparts/_bodyparts.dm | 2 +- .../surgery/organs/external/_visual_organs.dm | 25 +- .../modules/surgery/organs/external/spines.dm | 4 +- code/modules/surgery/organs/external/tails.dm | 22 +- .../organs/external/wings/moth_wings.dm | 4 +- .../surgery/organs/external/wings/wings.dm | 2 +- .../surgery/organs/internal/ears/_ears.dm | 4 +- .../internal/stomach/stomach_ethereal.dm | 2 +- code/modules/unit_tests/changeling.dm | 23 +- .../unit_tests/screenshot_humanoids.dm | 22 +- .../unit_tests/species_change_clothing.dm | 2 +- tgstation.dme | 5 +- 53 files changed, 667 insertions(+), 582 deletions(-) create mode 100644 code/datums/dna/blocks/dna_features_block.dm create mode 100644 code/datums/dna/blocks/dna_identity_block.dm rename code/datums/{ => dna}/dna.dm (56%) create mode 100644 code/datums/dna/dna_block.dm diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index fa90b1ee083..0287e3c31fb 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -44,68 +44,40 @@ //DNA - Because fuck you and your magic numbers being all over the codebase. #define DNA_BLOCK_SIZE 3 - #define DNA_BLOCK_SIZE_COLOR DEFAULT_HEX_COLOR_LEN -#define DNA_GENDER_BLOCK 1 -#define DNA_SKIN_TONE_BLOCK 2 -#define DNA_EYE_COLOR_LEFT_BLOCK 3 -#define DNA_EYE_COLOR_RIGHT_BLOCK 4 -#define DNA_HAIRSTYLE_BLOCK 5 -#define DNA_HAIR_COLOR_BLOCK 6 -#define DNA_FACIAL_HAIRSTYLE_BLOCK 7 -#define DNA_FACIAL_HAIR_COLOR_BLOCK 8 -#define DNA_HAIRSTYLE_GRADIENT_BLOCK 9 -#define DNA_HAIR_COLOR_GRADIENT_BLOCK 10 -#define DNA_FACIAL_HAIRSTYLE_GRADIENT_BLOCK 11 -#define DNA_FACIAL_HAIR_COLOR_GRADIENT_BLOCK 12 - -#define DNA_UNI_IDENTITY_BLOCKS 12 - -//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular_skyrat/modules/customization/_DEFINES/DNA.dm) -/* -/// This number needs to equal the total number of DNA blocks -#define DNA_MUTANT_COLOR_BLOCK 1 -#define DNA_ETHEREAL_COLOR_BLOCK 2 -#define DNA_LIZARD_MARKINGS_BLOCK 3 -#define DNA_TAIL_BLOCK 4 -#define DNA_LIZARD_TAIL_BLOCK 5 -#define DNA_SNOUT_BLOCK 6 -#define DNA_HORNS_BLOCK 7 -#define DNA_FRILLS_BLOCK 8 -#define DNA_SPINES_BLOCK 9 -#define DNA_EARS_BLOCK 10 -#define DNA_MOTH_WINGS_BLOCK 11 -#define DNA_MOTH_ANTENNAE_BLOCK 12 -#define DNA_MOTH_MARKINGS_BLOCK 13 -#define DNA_MUSHROOM_CAPS_BLOCK 14 -#define DNA_POD_HAIR_BLOCK 15 -#define DNA_FISH_TAIL_BLOCK 16 -*/ //SKYRAT EDIT REMOVAL END - -// Hey! Listen up if you're here because you're adding a species feature! -// -// You don't need to add a DNA block for EVERY species feature! -// You ONLY need DNA blocks if you intend to allow players to change it via GENETICS! -// (Which means having a DNA block for a feature tied to a mob without DNA is entirely pointless.) - -/// Total amount of DNA blocks, must be equal to the highest DNA block number -#define DNA_FEATURE_BLOCKS SSaccessories.dna_total_feature_blocks // SKYRAT EDIT CHANGE - ORIGINAL: #define DNA_FEATURE_BLOCKS 15 -// SKYRAT EDIT ADDITION START -#define DNA_MANDATORY_COLOR_BLOCKS 5 -#define DNA_MUTANT_COLOR_BLOCK 1 -#define DNA_MUTANT_COLOR_2_BLOCK 2 -#define DNA_MUTANT_COLOR_3_BLOCK 3 -#define DNA_ETHEREAL_COLOR_BLOCK 4 -#define DNA_SKIN_COLOR_BLOCK 5 -#define DNA_POD_HAIR_BLOCK 15 -#define DNA_FISH_TAIL_BLOCK 16 -// SKYRAT EDIT ADDITION END - #define DNA_SEQUENCE_LENGTH 4 #define DNA_MUTATION_BLOCKS 8 #define DNA_UNIQUE_ENZYMES_LEN 32 +//Features - No more magic strings +//These can't just simply use dna block paths like identities, because there's keys that aren't tied to blocks + +// Block tied +#define FEATURE_MUTANT_COLOR "mcolor" +#define FEATURE_ETHEREAL_COLOR "ethcolor" +#define FEATURE_EARS "ears" +#define FEATURE_TAIL "tail_cat" +#define FEATURE_TAIL_LIZARD "tail_lizard" +#define FEATURE_TAIL_FISH "tail_fish" +#define FEATURE_SNOUT "snout" +#define FEATURE_LIZARD_MARKINGS "marking_lizard" +#define FEATURE_HORNS "horns" +#define FEATURE_FRILLS "frills" +#define FEATURE_SPINES "spines" +#define FEATURE_MOTH_WINGS "moth_wings" +#define FEATURE_MOTH_ANTENNAE "moth_antennae" +#define FEATURE_MOTH_MARKINGS "moth_markings" +#define FEATURE_MUSH_CAP "caps" +#define FEATURE_POD_HAIR "pod_hair" + +// Other +#define FEATURE_WINGS "wings" +#define FEATURE_TAIL_MONKEY "tail_monkey" +#define FEATURE_TAIL_XENO "tail_xeno" +#define FEATURE_TAILSPINES "tailspines" // Different from regular spines, these appear on tails +#define FEATURE_LEGS "legs" + ///flag for the transfer_flag argument from dna/proc/copy_dna(). This one makes it so the SE is copied too. #define COPY_DNA_SE (1<<0) ///flag for the transfer_flag argument from dna/proc/copy_dna(). This one copies the species. diff --git a/code/__DEFINES/~skyrat_defines/DNA.dm b/code/__DEFINES/~skyrat_defines/DNA.dm index 35173909280..a0da77d5291 100644 --- a/code/__DEFINES/~skyrat_defines/DNA.dm +++ b/code/__DEFINES/~skyrat_defines/DNA.dm @@ -153,3 +153,14 @@ #define DNA_MARKING_COLOR_BLOCKS_PER_MARKING 1 #define DNA_BLOCKS_PER_MARKING_ZONE (MAXIMUM_MARKINGS_PER_LIMB * DNA_BLOCKS_PER_MARKING + 1) #define DNA_MARKING_BLOCKS_TOTAL_SIZE_PER_MARKING (DNA_BLOCK_SIZE + DNA_BLOCK_SIZE_COLOR * DNA_MARKING_COLOR_BLOCKS_PER_MARKING) + +/// Total amount of DNA blocks, must be equal to the highest DNA block number +#define DNA_FEATURE_BLOCKS SSaccessories.dna_total_feature_blocks +#define DNA_MANDATORY_COLOR_BLOCKS 5 +#define DNA_MUTANT_COLOR_BLOCK 1 +#define DNA_MUTANT_COLOR_2_BLOCK 2 +#define DNA_MUTANT_COLOR_3_BLOCK 3 +#define DNA_ETHEREAL_COLOR_BLOCK 4 +#define DNA_SKIN_COLOR_BLOCK 5 +#define DNA_POD_HAIR_BLOCK 15 +#define DNA_FISH_TAIL_BLOCK 16 diff --git a/code/__HELPERS/dna.dm b/code/__HELPERS/dna.dm index 17fd7e21b8e..ffa3c3a8768 100644 --- a/code/__HELPERS/dna.dm +++ b/code/__HELPERS/dna.dm @@ -12,7 +12,5 @@ #define GET_MUTATION_POWER(A) ((A.power_coeff < 0) ? 1 : A.power_coeff) #define GET_MUTATION_ENERGY(A) ((A.energy_coeff < 0) ? 1 : A.energy_coeff) -///Getter macro used to get the length of a identity block -#define GET_UI_BLOCK_LEN(blocknum) (GLOB.identity_block_lengths["[blocknum]"] || DNA_BLOCK_SIZE) ///Ditto, but for a feature. #define GET_UF_BLOCK_LEN(blocknum) (SSaccessories.features_block_lengths["[blocknum]"] || DNA_BLOCK_SIZE) //SKYRAT CHANGE EDIT - Customization ORIGINAL: #define GET_UF_BLOCK_LEN(blocknum) (GLOB.features_block_lengths["[blocknum]"] || DNA_BLOCK_SIZE) diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm index 498b497f1d5..0113a2c8db5 100644 --- a/code/_globalvars/lists/mobs.dm +++ b/code/_globalvars/lists/mobs.dm @@ -198,3 +198,21 @@ GLOBAL_LIST_INIT(construct_radial_images, list( if(mind) minds += mind return minds + +/// A keyed list of identity block singletons, in a key:value group of typepath:block +GLOBAL_LIST_INIT(dna_identity_blocks, init_identity_block_types()) + +/proc/init_identity_block_types() + . = list() + for(var/datum/dna_block/identity/block_path as anything in subtypesof(/datum/dna_block/identity)) + var/datum/dna_block/identity/new_block = new block_path() + .[block_path] = new_block + +/// A keyed list of feature block singletons, in a key:value group of typepath:block +GLOBAL_LIST_INIT(dna_feature_blocks, init_feature_block_types()) + +/proc/init_feature_block_types() + . = list() + for(var/datum/dna_block/feature/block_path as anything in subtypesof(/datum/dna_block/feature)) + var/datum/dna_block/feature/new_block = new block_path() + .[block_path] = new_block diff --git a/code/controllers/subsystem/sprite_accessories.dm b/code/controllers/subsystem/sprite_accessories.dm index b2f03725aea..052a1e9163e 100644 --- a/code/controllers/subsystem/sprite_accessories.dm +++ b/code/controllers/subsystem/sprite_accessories.dm @@ -11,6 +11,7 @@ SUBSYSTEM_DEF(accessories) // just 'accessories' for brevity name = "Sprite Accessories" flags = SS_NO_FIRE | SS_NO_INIT + // HOLY SHIT COMPACT THIS INTO ASSOCIATED LISTS SO WE STOP ADDING VARIABLES //Hairstyles var/list/hairstyles_list //! stores /datum/sprite_accessory/hair indexed by name var/list/hairstyles_male_list //! stores only hair names @@ -41,7 +42,6 @@ SUBSYSTEM_DEF(accessories) // just 'accessories' for brevity //Socks var/list/socks_list //! stores /datum/sprite_accessory/socks indexed by name - /* SKYRAT EDIT REMOVAL START - Customization - Moved to sprite_accessories var //Lizard Bits (all datum lists indexed by name) var/list/lizard_markings_list var/list/snouts_list @@ -61,18 +61,11 @@ SUBSYSTEM_DEF(accessories) // just 'accessories' for brevity var/list/wings_open_list var/list/moth_wings_list var/list/moth_antennae_list - */ //SKYRAT EDIT REMOVAL END var/list/moth_markings_list + var/list/caps_list var/list/pod_hair_list // SKYRAT EDIT ADDITION START - Customization - var/list/lizard_markings_list - var/list/tails_list_monkey - var/list/tails_list_xeno - var/list/tails_list_fish - var/list/caps_list - var/list/moth_wings_list - var/list/sprite_accessories = list() var/list/genetic_accessories = list() var/list/generic_accessories = list() @@ -124,19 +117,13 @@ SUBSYSTEM_DEF(accessories) // just 'accessories' for brevity // SKYRAT EDIT ADDITION END socks_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/socks)[DEFAULT_SPRITE_LIST] - - /* // SKYRAT EDIT START - Customization - socks_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/socks)[DEFAULT_SPRITE_LIST] - lizard_markings_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/lizard_markings, add_blank = TRUE)[DEFAULT_SPRITE_LIST] tails_list_felinid = init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/felinid, add_blank = TRUE)[DEFAULT_SPRITE_LIST] tails_list_lizard = init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/lizard)[DEFAULT_SPRITE_LIST] - */ tails_list_monkey = init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/monkey)[DEFAULT_SPRITE_LIST] tails_list_xeno = init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/xeno)[DEFAULT_SPRITE_LIST] //tails fo fish organ infusions, not for prefs. tails_list_fish = init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/fish)[DEFAULT_SPRITE_LIST] - /* snouts_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/snouts)[DEFAULT_SPRITE_LIST] horns_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/horns, add_blank = TRUE)[DEFAULT_SPRITE_LIST] ears_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/ears, add_blank = TRUE)[DEFAULT_SPRITE_LIST] @@ -145,17 +132,12 @@ SUBSYSTEM_DEF(accessories) // just 'accessories' for brevity frills_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/frills, add_blank = TRUE)[DEFAULT_SPRITE_LIST] spines_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/spines, add_blank = TRUE)[DEFAULT_SPRITE_LIST] tail_spines_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/tail_spines, add_blank = TRUE)[DEFAULT_SPRITE_LIST] - caps_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/caps)[DEFAULT_SPRITE_LIST] + caps_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/caps, add_blank = TRUE)[DEFAULT_SPRITE_LIST] // BUBBER EDIT CHANGE - ORIGINAL: caps_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/caps)[DEFAULT_SPRITE_LIST] moth_wings_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/moth_wings)[DEFAULT_SPRITE_LIST] moth_antennae_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/moth_antennae)[DEFAULT_SPRITE_LIST] - */ // SKYRAT EDIT END moth_markings_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/moth_markings, add_blank = TRUE)[DEFAULT_SPRITE_LIST] pod_hair_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/pod_hair)[DEFAULT_SPRITE_LIST] // SKYRAT EDIT ADDITION START - Customization - tails_list_monkey = init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/monkey)[DEFAULT_SPRITE_LIST] - caps_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/caps, add_blank = TRUE)[DEFAULT_SPRITE_LIST] - moth_wings_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/moth_wings)[DEFAULT_SPRITE_LIST] - features_block_lengths = list( "[DNA_MUTANT_COLOR_BLOCK]" = DNA_BLOCK_SIZE_COLOR, "[DNA_MUTANT_COLOR_2_BLOCK]" = DNA_BLOCK_SIZE_COLOR, diff --git a/code/datums/bodypart_overlays/markings_bodypart_overlay.dm b/code/datums/bodypart_overlays/markings_bodypart_overlay.dm index b51fb3098de..5cd5eb3cedc 100644 --- a/code/datums/bodypart_overlays/markings_bodypart_overlay.dm +++ b/code/datums/bodypart_overlays/markings_bodypart_overlay.dm @@ -43,13 +43,13 @@ return mutable_appearance(icon, gender_string + icon_state + "_" + limb.body_zone, layer = layer) /datum/bodypart_overlay/simple/body_marking/moth - dna_feature_key = "moth_markings" + dna_feature_key = FEATURE_MOTH_MARKINGS /datum/bodypart_overlay/simple/body_marking/moth/get_accessory(name) return SSaccessories.moth_markings_list[name] /datum/bodypart_overlay/simple/body_marking/lizard - dna_feature_key = "lizard_markings" + dna_feature_key = FEATURE_LIZARD_MARKINGS applies_to = list(/obj/item/bodypart/chest) /datum/bodypart_overlay/simple/body_marking/lizard/get_accessory(name) diff --git a/code/datums/dna/blocks/dna_features_block.dm b/code/datums/dna/blocks/dna_features_block.dm new file mode 100644 index 00000000000..ce66061e8de --- /dev/null +++ b/code/datums/dna/blocks/dna_features_block.dm @@ -0,0 +1,151 @@ +/datum/dna_block/feature/mutant_color + block_length = DNA_BLOCK_SIZE_COLOR + feature_key = FEATURE_MUTANT_COLOR + +/datum/dna_block/feature/mutant_color/create_unique_block(mob/living/carbon/human/target) + return sanitize_hexcolor(target.dna.features[feature_key], include_crunch = FALSE) + +/datum/dna_block/feature/mutant_color/apply_to_mob(mob/living/carbon/human/target, dna_hash) + target.dna.features[feature_key] = sanitize_hexcolor(get_block(dna_hash)) + +/datum/dna_block/feature/ethereal_color + block_length = DNA_BLOCK_SIZE_COLOR + feature_key = FEATURE_ETHEREAL_COLOR + +/datum/dna_block/feature/ethereal_color/create_unique_block(mob/living/carbon/human/target) + return sanitize_hexcolor(target.dna.features[FEATURE_ETHEREAL_COLOR], include_crunch = FALSE) + +/datum/dna_block/feature/ethereal_color/apply_to_mob(mob/living/carbon/human/target, dna_hash) + target.dna.features[feature_key] = sanitize_hexcolor(get_block(dna_hash)) + +/datum/dna_block/feature/ears + feature_key = FEATURE_EARS + +/datum/dna_block/feature/ears/create_unique_block(mob/living/carbon/human/target) + return construct_block(SSaccessories.ears_list.Find(target.dna.features[feature_key]), length(SSaccessories.ears_list)) + +/datum/dna_block/feature/ears/apply_to_mob(mob/living/carbon/human/target, dna_hash) + target.dna.features[feature_key] = SSaccessories.ears_list[deconstruct_block(get_block(dna_hash), length(SSaccessories.ears_list))] + +// One day, someone should consider merging all tails into one, this is stupid +// No I don't care that it will "Create situations where a felinid grows a lizard tail" that makes it more fun +/datum/dna_block/feature/tail + feature_key = FEATURE_TAIL + +/datum/dna_block/feature/tail/create_unique_block(mob/living/carbon/human/target) + return construct_block(SSaccessories.tails_list_felinid.Find(target.dna.features[feature_key]), length(SSaccessories.tails_list_felinid)) + +/datum/dna_block/feature/tail/apply_to_mob(mob/living/carbon/human/target, dna_hash) + target.dna.features[feature_key] = SSaccessories.tails_list_felinid[deconstruct_block(get_block(dna_hash), length(SSaccessories.tails_list_felinid))] + +/datum/dna_block/feature/tail_lizard + feature_key = FEATURE_TAIL_LIZARD + +/datum/dna_block/feature/tail_lizard/create_unique_block(mob/living/carbon/human/target) + return construct_block(SSaccessories.tails_list_lizard.Find(target.dna.features[feature_key]), length(SSaccessories.tails_list_lizard)) + +/datum/dna_block/feature/tail_lizard/apply_to_mob(mob/living/carbon/human/target, dna_hash) + target.dna.features[feature_key] = SSaccessories.tails_list_lizard[deconstruct_block(get_block(dna_hash), length(SSaccessories.tails_list_lizard))] + +/datum/dna_block/feature/tail_fish + feature_key = FEATURE_TAIL_FISH + +/datum/dna_block/feature/tail_fish/create_unique_block(mob/living/carbon/human/target) + return construct_block(SSaccessories.tails_list_fish.Find(target.dna.features[feature_key]), length(SSaccessories.tails_list_fish)) + +/datum/dna_block/feature/tail_fish/apply_to_mob(mob/living/carbon/human/target, dna_hash) + target.dna.features[feature_key] = SSaccessories.tails_list_fish[deconstruct_block(get_block(dna_hash), length(SSaccessories.tails_list_fish))] + +/datum/dna_block/feature/snout + feature_key = FEATURE_SNOUT + +/datum/dna_block/feature/snout/create_unique_block(mob/living/carbon/human/target) + return construct_block(SSaccessories.snouts_list.Find(target.dna.features[feature_key]), length(SSaccessories.snouts_list)) + +/datum/dna_block/feature/snout/apply_to_mob(mob/living/carbon/human/target, dna_hash) + target.dna.features[feature_key] = SSaccessories.snouts_list[deconstruct_block(get_block(dna_hash), length(SSaccessories.snouts_list))] + +/datum/dna_block/feature/lizard_marking + feature_key = FEATURE_LIZARD_MARKINGS + +/datum/dna_block/feature/lizard_marking/create_unique_block(mob/living/carbon/human/target) + return construct_block(SSaccessories.lizard_markings_list.Find(target.dna.features[feature_key]), length(SSaccessories.lizard_markings_list)) + +/datum/dna_block/feature/lizard_marking/apply_to_mob(mob/living/carbon/human/target, dna_hash) + target.dna.features[feature_key] = SSaccessories.lizard_markings_list[deconstruct_block(get_block(dna_hash), length(SSaccessories.lizard_markings_list))] + +/datum/dna_block/feature/horn + feature_key = FEATURE_HORNS + +/datum/dna_block/feature/horn/create_unique_block(mob/living/carbon/human/target) + return construct_block(SSaccessories.horns_list.Find(target.dna.features[feature_key]), length(SSaccessories.horns_list)) + +/datum/dna_block/feature/horn/apply_to_mob(mob/living/carbon/human/target, dna_hash) + target.dna.features[feature_key] = SSaccessories.horns_list[deconstruct_block(get_block(dna_hash), length(SSaccessories.horns_list))] + +/datum/dna_block/feature/frill + feature_key = FEATURE_FRILLS + +/datum/dna_block/feature/frill/create_unique_block(mob/living/carbon/human/target) + return construct_block(SSaccessories.frills_list.Find(target.dna.features[feature_key]), length(SSaccessories.frills_list)) + +/datum/dna_block/feature/frill/apply_to_mob(mob/living/carbon/human/target, dna_hash) + target.dna.features[feature_key] = SSaccessories.frills_list[deconstruct_block(get_block(dna_hash), length(SSaccessories.frills_list))] + +/datum/dna_block/feature/spine + feature_key = FEATURE_SPINES + +/datum/dna_block/feature/spine/create_unique_block(mob/living/carbon/human/target) + return construct_block(SSaccessories.spines_list.Find(target.dna.features[feature_key]), length(SSaccessories.spines_list)) + +/datum/dna_block/feature/spine/apply_to_mob(mob/living/carbon/human/target, dna_hash) + target.dna.features[feature_key] = SSaccessories.spines_list[deconstruct_block(get_block(dna_hash), length(SSaccessories.spines_list))] + +/datum/dna_block/feature/moth_wing + feature_key = FEATURE_MOTH_WINGS + +/datum/dna_block/feature/moth_wing/create_unique_block(mob/living/carbon/human/target) + if(target.dna.features[feature_key] == "Burnt Off") // Why is this snowflake check a thing. Please find a way to fix this later + return random_string(block_length, GLOB.hex_characters) + return construct_block(SSaccessories.moth_wings_list.Find(target.dna.features[feature_key]), length(SSaccessories.moth_wings_list)) + +/datum/dna_block/feature/moth_wing/apply_to_mob(mob/living/carbon/human/target, dna_hash) + target.dna.features[feature_key] = SSaccessories.moth_wings_list[deconstruct_block(get_block(dna_hash), length(SSaccessories.moth_wings_list))] + +/datum/dna_block/feature/moth_antenna + feature_key = FEATURE_MOTH_ANTENNAE + +/datum/dna_block/feature/moth_antenna/create_unique_block(mob/living/carbon/human/target) + if(target.dna.features[feature_key] == "Burnt Off") + return random_string(block_length, GLOB.hex_characters) + return construct_block(SSaccessories.moth_antennae_list.Find(target.dna.features[feature_key]), length(SSaccessories.moth_antennae_list)) + +/datum/dna_block/feature/moth_antenna/apply_to_mob(mob/living/carbon/human/target, dna_hash) + target.dna.features[feature_key] = SSaccessories.moth_antennae_list[deconstruct_block(get_block(dna_hash), length(SSaccessories.moth_antennae_list))] + +/datum/dna_block/feature/moth_marking + feature_key = FEATURE_MOTH_MARKINGS + +/datum/dna_block/feature/moth_marking/create_unique_block(mob/living/carbon/human/target) + return construct_block(SSaccessories.moth_markings_list.Find(target.dna.features[feature_key]), length(SSaccessories.moth_markings_list)) + +/datum/dna_block/feature/moth_marking/apply_to_mob(mob/living/carbon/human/target, dna_hash) + target.dna.features[feature_key] = SSaccessories.moth_markings_list[deconstruct_block(get_block(dna_hash), length(SSaccessories.moth_markings_list))] + +/datum/dna_block/feature/mush_cap + feature_key = FEATURE_MUSH_CAP + +/datum/dna_block/feature/mush_cap/create_unique_block(mob/living/carbon/human/target) + return construct_block(SSaccessories.caps_list.Find(target.dna.features[feature_key]), length(SSaccessories.caps_list)) + +/datum/dna_block/feature/mush_cap/apply_to_mob(mob/living/carbon/human/target, dna_hash) + target.dna.features[feature_key] = SSaccessories.caps_list[deconstruct_block(get_block(dna_hash), length(SSaccessories.caps_list))] + +/datum/dna_block/feature/pod_hair + feature_key = FEATURE_POD_HAIR + +/datum/dna_block/feature/pod_hair/create_unique_block(mob/living/carbon/human/target) + return construct_block(SSaccessories.pod_hair_list.Find(target.dna.features[feature_key]), length(SSaccessories.pod_hair_list)) + +/datum/dna_block/feature/pod_hair/apply_to_mob(mob/living/carbon/human/target, dna_hash) + target.dna.features[feature_key] = SSaccessories.pod_hair_list[deconstruct_block(get_block(dna_hash), length(SSaccessories.pod_hair_list))] diff --git a/code/datums/dna/blocks/dna_identity_block.dm b/code/datums/dna/blocks/dna_identity_block.dm new file mode 100644 index 00000000000..8b5a9a3c914 --- /dev/null +++ b/code/datums/dna/blocks/dna_identity_block.dm @@ -0,0 +1,129 @@ +/datum/dna_block/identity/gender + +/datum/dna_block/identity/gender/create_unique_block(mob/living/carbon/human/target) + //ignores TRAIT_AGENDER so that a "real" gender can be stored in the DNA if later use is needed + switch(target.gender) + if(MALE) + . = construct_block(G_MALE, GENDERS) + if(FEMALE) + . = construct_block(G_FEMALE, GENDERS) + if(NEUTER) + . = construct_block(G_NEUTER, GENDERS) + else + . = construct_block(G_PLURAL, GENDERS) + return . + +/datum/dna_block/identity/gender/apply_to_mob(mob/living/carbon/human/target, dna_hash) + //Always plural gender if agender + if(HAS_TRAIT(target, TRAIT_AGENDER)) + target.gender = PLURAL + return + switch(deconstruct_block(get_block(dna_hash), GENDERS)) + if(G_MALE) + target.gender = MALE + if(G_FEMALE) + target.gender = FEMALE + if(G_NEUTER) + target.gender = NEUTER + else + target.gender = PLURAL + +/datum/dna_block/identity/skin_tone + +/datum/dna_block/identity/skin_tone/create_unique_block(mob/living/carbon/human/target) + return construct_block(GLOB.skin_tones.Find(target.skin_tone), GLOB.skin_tones.len) + +/datum/dna_block/identity/skin_tone/apply_to_mob(mob/living/carbon/human/target, dna_hash) + target.skin_tone = GLOB.skin_tones[deconstruct_block(get_block(dna_hash), GLOB.skin_tones.len)] + +/// Holds both the left and right eye color at once +/datum/dna_block/identity/eye_colors + block_length = DNA_BLOCK_SIZE_COLOR * 2 // Left eye color, then right eye color + +/datum/dna_block/identity/eye_colors/create_unique_block(mob/living/carbon/human/target) + var/left = sanitize_hexcolor(target.eye_color_left, include_crunch = FALSE) + var/right = sanitize_hexcolor(target.eye_color_right, include_crunch = FALSE) + return left + right + +/datum/dna_block/identity/eye_colors/apply_to_mob(mob/living/carbon/human/target, dna_hash) + var/colors = get_block(dna_hash) + var/right_color_begin = DNA_BLOCK_SIZE_COLOR + 1 + target.set_eye_color(sanitize_hexcolor(copytext(colors, 1, right_color_begin)), sanitize_hexcolor(copytext(colors, right_color_begin, length(colors) + 1))) + +/datum/dna_block/identity/hair_style + +/datum/dna_block/identity/hair_style/create_unique_block(mob/living/carbon/human/target) + return construct_block(SSaccessories.hairstyles_list.Find(target.hairstyle), length(SSaccessories.hairstyles_list)) + +/datum/dna_block/identity/hair_style/apply_to_mob(mob/living/carbon/human/target, dna_hash) + if(HAS_TRAIT(target, TRAIT_BALD)) + target.set_hairstyle("Bald", update = FALSE) + return + var/style = SSaccessories.hairstyles_list[deconstruct_block(get_block(dna_hash), length(SSaccessories.hairstyles_list))] + target.set_hairstyle(style, update = FALSE) + +/datum/dna_block/identity/hair_color + block_length = DNA_BLOCK_SIZE_COLOR + +/datum/dna_block/identity/hair_color/create_unique_block(mob/living/carbon/human/target) + return sanitize_hexcolor(target.hair_color, include_crunch = FALSE) + +/datum/dna_block/identity/hair_color/apply_to_mob(mob/living/carbon/human/target, dna_hash) + target.set_haircolor(sanitize_hexcolor(get_block(dna_hash)), update = FALSE) + +/datum/dna_block/identity/facial_style + +/datum/dna_block/identity/facial_style/create_unique_block(mob/living/carbon/human/target) + return construct_block(SSaccessories.facial_hairstyles_list.Find(target.facial_hairstyle), length(SSaccessories.facial_hairstyles_list)) + +/datum/dna_block/identity/facial_style/apply_to_mob(mob/living/carbon/human/target, dna_hash) + if(HAS_TRAIT(src, TRAIT_SHAVED)) + target.set_facial_hairstyle("Shaved", update = FALSE) + return + var/style = SSaccessories.facial_hairstyles_list[deconstruct_block(get_block(dna_hash), length(SSaccessories.facial_hairstyles_list))] + target.set_facial_hairstyle(style, update = FALSE) + +/datum/dna_block/identity/facial_color + block_length = DNA_BLOCK_SIZE_COLOR + +/datum/dna_block/identity/facial_color/create_unique_block(mob/living/carbon/human/target) + return sanitize_hexcolor(target.facial_hair_color, include_crunch = FALSE) + +/datum/dna_block/identity/facial_color/apply_to_mob(mob/living/carbon/human/target, dna_hash) + target.set_facial_haircolor(sanitize_hexcolor(get_block(dna_hash)), update = FALSE) + +/datum/dna_block/identity/hair_gradient + +/datum/dna_block/identity/hair_gradient/create_unique_block(mob/living/carbon/human/target) + return construct_block(SSaccessories.hair_gradients_list.Find(target.grad_style[GRADIENT_HAIR_KEY]), length(SSaccessories.hair_gradients_list)) + +/datum/dna_block/identity/hair_gradient/apply_to_mob(mob/living/carbon/human/target, dna_hash) + var/gradient_style = SSaccessories.hair_gradients_list[deconstruct_block(get_block(dna_hash), length(SSaccessories.hair_gradients_list))] + target.set_hair_gradient_style(gradient_style, update = FALSE) + +/datum/dna_block/identity/hair_gradient_color + block_length = DNA_BLOCK_SIZE_COLOR + +/datum/dna_block/identity/hair_gradient_color/create_unique_block(mob/living/carbon/human/target) + return sanitize_hexcolor(target.grad_color[GRADIENT_HAIR_KEY], include_crunch = FALSE) + +/datum/dna_block/identity/hair_gradient_color/apply_to_mob(mob/living/carbon/human/target, dna_hash) + target.set_hair_gradient_color(sanitize_hexcolor(get_block(dna_hash)), update = FALSE) + +/datum/dna_block/identity/facial_gradient + +/datum/dna_block/identity/facial_gradient/create_unique_block(mob/living/carbon/human/target) + return construct_block(SSaccessories.facial_hair_gradients_list.Find(target.grad_style[GRADIENT_FACIAL_HAIR_KEY]), length(SSaccessories.facial_hair_gradients_list)) + +/datum/dna_block/identity/facial_gradient/apply_to_mob(mob/living/carbon/human/target, dna_hash) + var/gradient_style = SSaccessories.hair_gradients_list[deconstruct_block(get_block(dna_hash), length(SSaccessories.hair_gradients_list))] + target.set_facial_hair_gradient_style(gradient_style, update = FALSE) + +/datum/dna_block/identity/facial_gradient_color + block_length = DNA_BLOCK_SIZE_COLOR + +/datum/dna_block/identity/facial_gradient_color/create_unique_block(mob/living/carbon/human/target) + return sanitize_hexcolor(target.grad_color[GRADIENT_FACIAL_HAIR_KEY], include_crunch = FALSE) + +/datum/dna_block/identity/facial_gradient_color/apply_to_mob(mob/living/carbon/human/target, dna_hash) + target.set_facial_hair_gradient_color(sanitize_hexcolor(get_block(dna_hash)), update = FALSE) diff --git a/code/datums/dna.dm b/code/datums/dna/dna.dm similarity index 56% rename from code/datums/dna.dm rename to code/datums/dna/dna.dm index 8d67a68ff9f..d3f5bf4c915 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna/dna.dm @@ -1,76 +1,33 @@ -//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular_skyrat/modules/customization/code/datums/dna.dm) -/* -/** - * Some identity blocks (basically pieces of the unique_identity string variable of the dna datum, commonly abbreviated with ui) - * may have a length that differ from standard length of 3 ASCII characters. This list is necessary - * for these non-standard blocks to work, as well as the entire unique identity string. - * Should you add a new ui block which size differ from the standard (again, 3 ASCII characters), like for example, a color, - * please do not forget to also include it in this list in the following format: - * "[dna block number]" = dna block size, - * Failure to do that may result in bugs. Thanks. - */ -GLOBAL_LIST_INIT(identity_block_lengths, list( - "[DNA_HAIR_COLOR_BLOCK]" = DNA_BLOCK_SIZE_COLOR, - "[DNA_FACIAL_HAIR_COLOR_BLOCK]" = DNA_BLOCK_SIZE_COLOR, - "[DNA_EYE_COLOR_LEFT_BLOCK]" = DNA_BLOCK_SIZE_COLOR, - "[DNA_EYE_COLOR_RIGHT_BLOCK]" = DNA_BLOCK_SIZE_COLOR, - )) - -/** - * Some identity blocks (basically pieces of the unique_identity string variable of the dna datum, commonly abbreviated with ui) - * may have a length that differ from standard length of 3 ASCII characters. This list is necessary - * for these non-standard blocks to work, as well as the entire unique identity string. - * Should you add a new ui block which size differ from the standard (again, 3 ASCII characters), like for example, a color, - * please do not forget to also include it in this list in the following format: - * "[dna block number]" = dna block size, - * Failure to do that may result in bugs. Thanks. - */ -GLOBAL_LIST_INIT(identity_block_lengths, list( - "[DNA_HAIR_COLOR_BLOCK]" = DNA_BLOCK_SIZE_COLOR, - "[DNA_FACIAL_HAIR_COLOR_BLOCK]" = DNA_BLOCK_SIZE_COLOR, - "[DNA_EYE_COLOR_LEFT_BLOCK]" = DNA_BLOCK_SIZE_COLOR, - "[DNA_EYE_COLOR_RIGHT_BLOCK]" = DNA_BLOCK_SIZE_COLOR, - "[DNA_HAIR_COLOR_GRADIENT_BLOCK]" = DNA_BLOCK_SIZE_COLOR, - "[DNA_FACIAL_HAIR_COLOR_GRADIENT_BLOCK]" = DNA_BLOCK_SIZE_COLOR, - )) - -/** - * The same rules of the above also apply here, with the exception that this is for the unique_features string variable - * (commonly abbreviated with uf) and its blocks. Both ui and uf have a standard block length of 3 ASCII characters. - */ -GLOBAL_LIST_INIT(features_block_lengths, list( - "[DNA_MUTANT_COLOR_BLOCK]" = DNA_BLOCK_SIZE_COLOR, - "[DNA_ETHEREAL_COLOR_BLOCK]" = DNA_BLOCK_SIZE_COLOR, - )) - /** * A list of numbers that keeps track of where ui blocks start in the unique_identity string variable of the dna datum. * Commonly used by the datum/dna/set_uni_identity_block and datum/dna/get_uni_identity_block procs. */ GLOBAL_LIST_INIT(total_ui_len_by_block, populate_total_ui_len_by_block()) -*/ GLOBAL_LIST_INIT(standard_mutation_sources, list(MUTATION_SOURCE_ACTIVATED, MUTATION_SOURCE_MUTATOR, MUTATION_SOURCE_TIMED_INJECTOR)) -/* /proc/populate_total_ui_len_by_block() . = list() var/total_block_len = 1 - for(var/blocknumber in 1 to DNA_UNI_IDENTITY_BLOCKS) - . += total_block_len - total_block_len += GET_UI_BLOCK_LEN(blocknumber) + for(var/block_path in GLOB.dna_identity_blocks) + var/datum/dna_block/identity/block = GLOB.dna_identity_blocks[block_path] + .[block_path] += total_block_len + total_block_len += block.block_length +/* ///Ditto but for unique features. Used by the datum/dna/set_uni_feature_block and datum/dna/get_uni_feature_block procs. GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) /proc/populate_total_uf_len_by_block() . = list() var/total_block_len = 1 - for(var/blocknumber in 1 to DNA_FEATURE_BLOCKS) - . += total_block_len - total_block_len += GET_UF_BLOCK_LEN(blocknumber) + for(var/block_path in GLOB.dna_feature_blocks) + var/datum/dna_block/feature/block = GLOB.dna_feature_blocks[block_path] + .[block_path] += total_block_len + total_block_len += block.block_length */ //SKYRAT EDIT REMOVAL END + /////////////////////////// DNA DATUM /datum/dna ///An md5 hash of the dna holder's real name @@ -83,7 +40,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) var/datum/species/species = new /datum/species/human /// Assoc list of feature keys to their value /// Note if you set these manually, and do not update [unique_features] afterwards, it will likely be reset. - var/list/features = list("mcolor" = COLOR_WHITE) + var/list/features = list(FEATURE_MUTANT_COLOR = COLOR_WHITE) ///Stores the hashed values of the person's non-human features var/unique_features ///Stores the real name of the person who originally got this dna datum. Used primarily for changelings @@ -236,79 +193,20 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) /datum/dna/proc/generate_unique_identity() . = "" - var/list/L = new /list(DNA_UNI_IDENTITY_BLOCKS) - - //ignores TRAIT_AGENDER so that a "real" gender can be stored in the DNA if later use is needed - switch(holder.gender) - if(MALE) - L[DNA_GENDER_BLOCK] = construct_block(G_MALE, GENDERS) - if(FEMALE) - L[DNA_GENDER_BLOCK] = construct_block(G_FEMALE, GENDERS) - if(NEUTER) - L[DNA_GENDER_BLOCK] = construct_block(G_NEUTER, GENDERS) - else - L[DNA_GENDER_BLOCK] = construct_block(G_PLURAL, GENDERS) - if(ishuman(holder)) - var/mob/living/carbon/human/H = holder - if(length(SSaccessories.hairstyles_list) == 0 || length(SSaccessories.facial_hairstyles_list) == 0) - CRASH("SSaccessories lists are empty, this is bad!") - - L[DNA_HAIRSTYLE_BLOCK] = construct_block(SSaccessories.hairstyles_list.Find(H.hairstyle), length(SSaccessories.hairstyles_list)) - L[DNA_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.hair_color, include_crunch = FALSE) - L[DNA_FACIAL_HAIRSTYLE_BLOCK] = construct_block(SSaccessories.facial_hairstyles_list.Find(H.facial_hairstyle), length(SSaccessories.facial_hairstyles_list)) - L[DNA_FACIAL_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.facial_hair_color, include_crunch = FALSE) - L[DNA_SKIN_TONE_BLOCK] = construct_block(GLOB.skin_tones.Find(H.skin_tone), GLOB.skin_tones.len) - L[DNA_EYE_COLOR_LEFT_BLOCK] = sanitize_hexcolor(H.eye_color_left, include_crunch = FALSE) - L[DNA_EYE_COLOR_RIGHT_BLOCK] = sanitize_hexcolor(H.eye_color_right, include_crunch = FALSE) - L[DNA_HAIRSTYLE_GRADIENT_BLOCK] = construct_block(SSaccessories.hair_gradients_list.Find(H.grad_style[GRADIENT_HAIR_KEY]), length(SSaccessories.hair_gradients_list)) - L[DNA_HAIR_COLOR_GRADIENT_BLOCK] = sanitize_hexcolor(H.grad_color[GRADIENT_HAIR_KEY], include_crunch = FALSE) - L[DNA_FACIAL_HAIRSTYLE_GRADIENT_BLOCK] = construct_block(SSaccessories.facial_hair_gradients_list.Find(H.grad_style[GRADIENT_FACIAL_HAIR_KEY]), length(SSaccessories.facial_hair_gradients_list)) - L[DNA_FACIAL_HAIR_COLOR_GRADIENT_BLOCK] = sanitize_hexcolor(H.grad_color[GRADIENT_FACIAL_HAIR_KEY], include_crunch = FALSE) - - for(var/blocknum in 1 to DNA_UNI_IDENTITY_BLOCKS) - . += L[blocknum] || random_string(GET_UI_BLOCK_LEN(blocknum), GLOB.hex_characters) + for(var/block_type in GLOB.dna_identity_blocks) + var/datum/dna_block/identity/block = GLOB.dna_identity_blocks[block_type] + . += block.unique_block(holder) //SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular_skyrat/modules/customization/code/datums/dna.dm) /* /datum/dna/proc/generate_unique_features() . = "" - var/list/L = new /list(DNA_FEATURE_BLOCKS) - - if(features["mcolor"]) - L[DNA_MUTANT_COLOR_BLOCK] = sanitize_hexcolor(features["mcolor"], include_crunch = FALSE) - if(features["ethcolor"]) - L[DNA_ETHEREAL_COLOR_BLOCK] = sanitize_hexcolor(features["ethcolor"], include_crunch = FALSE) - if(features["lizard_markings"]) - L[DNA_LIZARD_MARKINGS_BLOCK] = construct_block(SSaccessories.lizard_markings_list.Find(features["lizard_markings"]), length(SSaccessories.lizard_markings_list)) - if(features["tail_cat"]) - L[DNA_TAIL_BLOCK] = construct_block(SSaccessories.tails_list_felinid.Find(features["tail_cat"]), length(SSaccessories.tails_list_felinid)) - if(features["tail_lizard"]) - L[DNA_LIZARD_TAIL_BLOCK] = construct_block(SSaccessories.tails_list_lizard.Find(features["tail_lizard"]), length(SSaccessories.tails_list_lizard)) - if(features["snout"]) - L[DNA_SNOUT_BLOCK] = construct_block(SSaccessories.snouts_list.Find(features["snout"]), length(SSaccessories.snouts_list)) - if(features["horns"]) - L[DNA_HORNS_BLOCK] = construct_block(SSaccessories.horns_list.Find(features["horns"]), length(SSaccessories.horns_list)) - if(features["frills"]) - L[DNA_FRILLS_BLOCK] = construct_block(SSaccessories.frills_list.Find(features["frills"]), length(SSaccessories.frills_list)) - if(features["spines"]) - L[DNA_SPINES_BLOCK] = construct_block(SSaccessories.spines_list.Find(features["spines"]), length(SSaccessories.spines_list)) - if(features["ears"]) - L[DNA_EARS_BLOCK] = construct_block(SSaccessories.ears_list.Find(features["ears"]), length(SSaccessories.ears_list)) - if(features["moth_wings"] != "Burnt Off") - L[DNA_MOTH_WINGS_BLOCK] = construct_block(SSaccessories.moth_wings_list.Find(features["moth_wings"]), length(SSaccessories.moth_wings_list)) - if(features["moth_antennae"] != "Burnt Off") - L[DNA_MOTH_ANTENNAE_BLOCK] = construct_block(SSaccessories.moth_antennae_list.Find(features["moth_antennae"]), length(SSaccessories.moth_antennae_list)) - if(features["moth_markings"]) - L[DNA_MOTH_MARKINGS_BLOCK] = construct_block(SSaccessories.moth_markings_list.Find(features["moth_markings"]), length(SSaccessories.moth_markings_list)) - if(features["caps"]) - L[DNA_MUSHROOM_CAPS_BLOCK] = construct_block(SSaccessories.caps_list.Find(features["caps"]), length(SSaccessories.caps_list)) - if(features["pod_hair"]) - L[DNA_POD_HAIR_BLOCK] = construct_block(SSaccessories.pod_hair_list.Find(features["pod_hair"]), length(SSaccessories.pod_hair_list)) - if(features["fish_tail"]) - L[DNA_FISH_TAIL_BLOCK] = construct_block(SSaccessories.tails_list_fish.Find(features["fish_tail"]), length(SSaccessories.tails_list_fish)) - - for(var/blocknum in 1 to DNA_FEATURE_BLOCKS) - . += L[blocknum] || random_string(GET_UI_BLOCK_LEN(blocknum), GLOB.hex_characters) + for(var/block_type in GLOB.dna_feature_blocks) + var/datum/dna_block/feature/block = GLOB.dna_feature_blocks[block_type] + if(isnull(features[block.feature_key])) + . += random_string(block.block_length, GLOB.hex_characters) + continue + . += block.unique_block(holder) */ //SKYRAT EDIT REMOVAL END @@ -370,98 +268,29 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) . += random_string(DNA_UNIQUE_ENZYMES_LEN, GLOB.hex_characters) return . -///Setter macro used to modify unique identity blocks. -/datum/dna/proc/set_uni_identity_block(blocknum, input) - var/precesing_blocks = copytext(unique_identity, 1, GLOB.total_ui_len_by_block[blocknum]) - var/succeeding_blocks = blocknum < GLOB.total_ui_len_by_block.len ? copytext(unique_identity, GLOB.total_ui_len_by_block[blocknum+1]) : "" - unique_identity = precesing_blocks + input + succeeding_blocks - ///Setter macro used to modify unique features blocks. /datum/dna/proc/set_uni_feature_block(blocknum, input) var/precesing_blocks = copytext(unique_features, 1, GLOB.total_uf_len_by_block[blocknum]) var/succeeding_blocks = blocknum < GLOB.total_uf_len_by_block.len ? copytext(unique_features, GLOB.total_uf_len_by_block[blocknum+1]) : "" unique_features = precesing_blocks + input + succeeding_blocks -/datum/dna/proc/update_ui_block(blocknumber) - if(!blocknumber) - CRASH("UI block index is null") +/datum/dna/proc/update_ui_block(blocktype) + if(isnull(blocktype)) + CRASH("UI block type is null") if(!ishuman(holder)) CRASH("Non-human mobs shouldn't have DNA") - var/mob/living/carbon/human/H = holder - switch(blocknumber) - if(DNA_HAIR_COLOR_BLOCK) - set_uni_identity_block(blocknumber, sanitize_hexcolor(H.hair_color, include_crunch = FALSE)) - if(DNA_FACIAL_HAIR_COLOR_BLOCK) - set_uni_identity_block(blocknumber, sanitize_hexcolor(H.facial_hair_color, include_crunch = FALSE)) - if(DNA_SKIN_TONE_BLOCK) - set_uni_identity_block(blocknumber, construct_block(GLOB.skin_tones.Find(H.skin_tone), GLOB.skin_tones.len)) - if(DNA_EYE_COLOR_LEFT_BLOCK) - set_uni_identity_block(blocknumber, sanitize_hexcolor(H.eye_color_left, include_crunch = FALSE)) - if(DNA_EYE_COLOR_RIGHT_BLOCK) - set_uni_identity_block(blocknumber, sanitize_hexcolor(H.eye_color_right, include_crunch = FALSE)) - if(DNA_GENDER_BLOCK) - switch(H.gender) - if(MALE) - set_uni_identity_block(blocknumber, construct_block(G_MALE, GENDERS)) - if(FEMALE) - set_uni_identity_block(blocknumber, construct_block(G_FEMALE, GENDERS)) - if(NEUTER) - set_uni_identity_block(blocknumber, construct_block(G_NEUTER, GENDERS)) - else - set_uni_identity_block(blocknumber, construct_block(G_PLURAL, GENDERS)) - if(DNA_FACIAL_HAIRSTYLE_BLOCK) - set_uni_identity_block(blocknumber, construct_block(SSaccessories.facial_hairstyles_list.Find(H.facial_hairstyle), length(SSaccessories.facial_hairstyles_list))) - if(DNA_HAIRSTYLE_BLOCK) - set_uni_identity_block(blocknumber, construct_block(SSaccessories.hairstyles_list.Find(H.hairstyle), length(SSaccessories.hairstyles_list))) - if(DNA_HAIRSTYLE_GRADIENT_BLOCK) - set_uni_identity_block(blocknumber, construct_block(SSaccessories.hair_gradients_list.Find(H.grad_style[GRADIENT_HAIR_KEY]), length(SSaccessories.hair_gradients_list))) - if(DNA_FACIAL_HAIRSTYLE_GRADIENT_BLOCK) - set_uni_identity_block(blocknumber, construct_block(SSaccessories.facial_hair_gradients_list.Find(H.grad_style[GRADIENT_FACIAL_HAIR_KEY]), length(SSaccessories.facial_hair_gradients_list))) - if(DNA_HAIR_COLOR_GRADIENT_BLOCK) - set_uni_identity_block(blocknumber, sanitize_hexcolor(H.grad_color[GRADIENT_HAIR_KEY], include_crunch = FALSE)) - if(DNA_FACIAL_HAIR_COLOR_GRADIENT_BLOCK) - set_uni_identity_block(blocknumber, sanitize_hexcolor(H.grad_color[GRADIENT_FACIAL_HAIR_KEY], include_crunch = FALSE)) + var/datum/dna_block/identity/block = GLOB.dna_identity_blocks[blocktype] + unique_identity = block.modified_hash(unique_identity, block.unique_block(holder)) //SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular_skyrat/modules/customization/code/datums/dna.dm) /* -/datum/dna/proc/update_uf_block(blocknumber) - if(!blocknumber) - CRASH("UF block index is null") +/datum/dna/proc/update_uf_block(blocktype) + if(!blocktype) + CRASH("UF block type is null") if(!ishuman(holder)) CRASH("Non-human mobs shouldn't have DNA") - switch(blocknumber) - if(DNA_MUTANT_COLOR_BLOCK) - set_uni_feature_block(blocknumber, sanitize_hexcolor(features["mcolor"], include_crunch = FALSE)) - if(DNA_ETHEREAL_COLOR_BLOCK) - set_uni_feature_block(blocknumber, sanitize_hexcolor(features["ethcolor"], include_crunch = FALSE)) - if(DNA_LIZARD_MARKINGS_BLOCK) - set_uni_feature_block(blocknumber, construct_block(SSaccessories.lizard_markings_list.Find(features["lizard_markings"]), length(SSaccessories.lizard_markings_list))) - if(DNA_TAIL_BLOCK) - set_uni_feature_block(blocknumber, construct_block(SSaccessories.tails_list_felinid.Find(features["tail_cat"]), length(SSaccessories.tails_list_felinid))) - if(DNA_LIZARD_TAIL_BLOCK) - set_uni_feature_block(blocknumber, construct_block(SSaccessories.tails_list_lizard.Find(features["tail_lizard"]), length(SSaccessories.tails_list_lizard))) - if(DNA_SNOUT_BLOCK) - set_uni_feature_block(blocknumber, construct_block(SSaccessories.snouts_list.Find(features["snout"]), length(SSaccessories.snouts_list))) - if(DNA_HORNS_BLOCK) - set_uni_feature_block(blocknumber, construct_block(SSaccessories.horns_list.Find(features["horns"]), length(SSaccessories.horns_list))) - if(DNA_FRILLS_BLOCK) - set_uni_feature_block(blocknumber, construct_block(SSaccessories.frills_list.Find(features["frills"]), length(SSaccessories.frills_list))) - if(DNA_SPINES_BLOCK) - set_uni_feature_block(blocknumber, construct_block(SSaccessories.spines_list.Find(features["spines"]), length(SSaccessories.spines_list))) - if(DNA_EARS_BLOCK) - set_uni_feature_block(blocknumber, construct_block(SSaccessories.ears_list.Find(features["ears"]), length(SSaccessories.ears_list))) - if(DNA_MOTH_WINGS_BLOCK) - set_uni_feature_block(blocknumber, construct_block(SSaccessories.moth_wings_list.Find(features["moth_wings"]), length(SSaccessories.moth_wings_list))) - if(DNA_MOTH_ANTENNAE_BLOCK) - set_uni_feature_block(blocknumber, construct_block(SSaccessories.moth_antennae_list.Find(features["moth_antennae"]), length(SSaccessories.moth_antennae_list))) - if(DNA_MOTH_MARKINGS_BLOCK) - set_uni_feature_block(blocknumber, construct_block(SSaccessories.moth_markings_list.Find(features["moth_markings"]), length(SSaccessories.moth_markings_list))) - if(DNA_MUSHROOM_CAPS_BLOCK) - set_uni_feature_block(blocknumber, construct_block(SSaccessories.caps_list.Find(features["caps"]), length(SSaccessories.caps_list))) - if(DNA_POD_HAIR_BLOCK) - set_uni_feature_block(blocknumber, construct_block(SSaccessories.pod_hair_list.Find(features["pod_hair"]), length(SSaccessories.pod_hair_list))) - if(DNA_FISH_TAIL_BLOCK) - set_uni_feature_block(blocknumber, construct_block(SSaccessories.tails_list_fish.Find(features["fish_tail"]), length(SSaccessories.tails_list_fish))) + var/datum/dna_block/feature/block = GLOB.dna_identity_blocks[blocktype] + unique_features = block.modified_hash(unique_features, block.unique_block(holder)) */ //SKYRAT EDIT REMOVAL END @@ -513,6 +342,8 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) /// Updates the UI, UE, and UF of the DNA according to the features, appearance, name, etc. of the DNA / holder. /datum/dna/proc/update_dna_identity() + if(!holder.has_dna()) + return unique_identity = generate_unique_identity() unique_enzymes = generate_unique_enzymes() unique_features = generate_unique_features() @@ -531,21 +362,16 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) generate_dna_blocks(mutation_blacklist = list(/datum/mutation/headless)) if(randomize_features) /* SKYRAT EDIT REMOVAL START - We don't really want this. We instead let get_mutant_bodyparts() handle the bodypart randomization on our end, to prevent getting any crazy cross-species features. - var/static/list/all_species_protoypes - if(isnull(all_species_protoypes)) - all_species_protoypes = list() - for(var/species_path in subtypesof(/datum/species)) - all_species_protoypes += new species_path() for(var/species_type in GLOB.species_prototypes) var/list/new_features = GLOB.species_prototypes[species_type].randomize_features() for(var/feature in new_features) - features[feature] = new_features[feature] + features[feature] = new_features[feature] SKYRAT REMOVAL END */ features = species.randomize_features() | features // SKYRAT EDIT CHANGE - Where applicable, replace features with the features generated by species/randomize_features() - Original: features["mcolor"] = "#[random_color()]" body_markings = species.get_random_body_markings(features) // SKYRAT EDIT ADDITION - features["mcolor"] = "#[random_color()]" + features[FEATURE_MUTANT_COLOR] = "#[random_color()]" mutant_bodyparts = species.get_mutant_bodyparts(features, existing_mutant_bodyparts = randomize_features ? list() : mutant_bodyparts) // SKYRAT EDIT ADDITION update_dna_identity() @@ -703,95 +529,32 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) dna.species = new rando_race() //proc used to update the mob's appearance after its dna UI has been changed -/mob/living/carbon/proc/updateappearance(icon_update=1, mutcolor_update=0, mutations_overlay_update=0) +//2025: Im unsure if dna is meant to be living, carbon, or human level.. there's contradicting stuff and bugfixes going back 8 years +//If youre reading this, and you know for sure, update this, or maybe remove the carbon part entirely +/mob/living/carbon/proc/updateappearance(icon_update = TRUE, mutcolor_update = FALSE, mutations_overlay_update = FALSE) if(!has_dna()) return - //Always plural gender if agender - if(HAS_TRAIT(src, TRAIT_AGENDER)) - gender = PLURAL - return - - switch(deconstruct_block(get_uni_identity_block(dna.unique_identity, DNA_GENDER_BLOCK), GENDERS)) - if(G_MALE) - gender = MALE - if(G_FEMALE) - gender = FEMALE - if(G_NEUTER) - gender = NEUTER - else - gender = PLURAL - //SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular_skyrat/modules/customization/code/datums/dna.dm) /* /mob/living/carbon/human/updateappearance(icon_update = TRUE, mutcolor_update = FALSE, mutations_overlay_update = FALSE) - ..() - var/structure = dna.unique_identity - skin_tone = GLOB.skin_tones[deconstruct_block(get_uni_identity_block(structure, DNA_SKIN_TONE_BLOCK), GLOB.skin_tones.len)] - set_eye_color(sanitize_hexcolor(get_uni_identity_block(structure, DNA_EYE_COLOR_LEFT_BLOCK)), sanitize_hexcolor(get_uni_identity_block(structure, DNA_EYE_COLOR_RIGHT_BLOCK))) - set_haircolor(sanitize_hexcolor(get_uni_identity_block(structure, DNA_HAIR_COLOR_BLOCK)), update = FALSE) - set_facial_haircolor(sanitize_hexcolor(get_uni_identity_block(structure, DNA_FACIAL_HAIR_COLOR_BLOCK)), update = FALSE) - set_hair_gradient_color(sanitize_hexcolor(get_uni_identity_block(structure, DNA_HAIR_COLOR_GRADIENT_BLOCK)), update = FALSE) - set_facial_hair_gradient_color(sanitize_hexcolor(get_uni_identity_block(structure, DNA_FACIAL_HAIR_COLOR_GRADIENT_BLOCK)), update = FALSE) - if(HAS_TRAIT(src, TRAIT_SHAVED)) - set_facial_hairstyle("Shaved", update = FALSE) - else - var/style = SSaccessories.facial_hairstyles_list[deconstruct_block(get_uni_identity_block(structure, DNA_FACIAL_HAIRSTYLE_BLOCK), length(SSaccessories.facial_hairstyles_list))] - var/gradient_style = SSaccessories.facial_hair_gradients_list[deconstruct_block(get_uni_identity_block(structure, DNA_FACIAL_HAIRSTYLE_GRADIENT_BLOCK), length(SSaccessories.facial_hair_gradients_list))] - set_facial_hairstyle(style, update = FALSE) - set_facial_hair_gradient_style(gradient_style, update = FALSE) - if(HAS_TRAIT(src, TRAIT_BALD)) - set_hairstyle("Bald", update = FALSE) - else - var/style = SSaccessories.hairstyles_list[deconstruct_block(get_uni_identity_block(structure, DNA_HAIRSTYLE_BLOCK), length(SSaccessories.hairstyles_list))] - var/gradient_style = SSaccessories.hair_gradients_list[deconstruct_block(get_uni_identity_block(structure, DNA_HAIRSTYLE_GRADIENT_BLOCK), length(SSaccessories.hair_gradients_list))] - set_hairstyle(style, update = FALSE) - set_hair_gradient_style(gradient_style, update = FALSE) - var/features = dna.unique_features - if(dna.features["mcolor"]) - dna.features["mcolor"] = sanitize_hexcolor(get_uni_feature_block(features, DNA_MUTANT_COLOR_BLOCK)) - if(dna.features["ethcolor"]) - dna.features["ethcolor"] = sanitize_hexcolor(get_uni_feature_block(features, DNA_ETHEREAL_COLOR_BLOCK)) - if(dna.features["lizard_markings"]) - dna.features["lizard_markings"] = SSaccessories.lizard_markings_list[deconstruct_block(get_uni_feature_block(features, DNA_LIZARD_MARKINGS_BLOCK), length(SSaccessories.lizard_markings_list))] - if(dna.features["snout"]) - dna.features["snout"] = SSaccessories.snouts_list[deconstruct_block(get_uni_feature_block(features, DNA_SNOUT_BLOCK), length(SSaccessories.snouts_list))] - if(dna.features["horns"]) - dna.features["horns"] = SSaccessories.horns_list[deconstruct_block(get_uni_feature_block(features, DNA_HORNS_BLOCK), length(SSaccessories.horns_list))] - if(dna.features["frills"]) - dna.features["frills"] = SSaccessories.frills_list[deconstruct_block(get_uni_feature_block(features, DNA_FRILLS_BLOCK), length(SSaccessories.frills_list))] - if(dna.features["spines"]) - dna.features["spines"] = SSaccessories.spines_list[deconstruct_block(get_uni_feature_block(features, DNA_SPINES_BLOCK), length(SSaccessories.spines_list))] - if(dna.features["tail_cat"]) - dna.features["tail_cat"] = SSaccessories.tails_list_felinid[deconstruct_block(get_uni_feature_block(features, DNA_TAIL_BLOCK), length(SSaccessories.tails_list_felinid))] - if(dna.features["tail_lizard"]) - dna.features["tail_lizard"] = SSaccessories.tails_list_lizard[deconstruct_block(get_uni_feature_block(features, DNA_LIZARD_TAIL_BLOCK), length(SSaccessories.tails_list_lizard))] - if(dna.features["ears"]) - dna.features["ears"] = SSaccessories.ears_list[deconstruct_block(get_uni_feature_block(features, DNA_EARS_BLOCK), length(SSaccessories.ears_list))] - if(dna.features["moth_wings"]) - var/genetic_value = SSaccessories.moth_wings_list[deconstruct_block(get_uni_feature_block(features, DNA_MOTH_WINGS_BLOCK), length(SSaccessories.moth_wings_list))] - dna.features["original_moth_wings"] = genetic_value - dna.features["moth_wings"] = genetic_value - if(dna.features["moth_antennae"]) - var/genetic_value = SSaccessories.moth_antennae_list[deconstruct_block(get_uni_feature_block(features, DNA_MOTH_ANTENNAE_BLOCK), length(SSaccessories.moth_antennae_list))] - dna.features["original_moth_antennae"] = genetic_value - dna.features["moth_antennae"] = genetic_value - if(dna.features["moth_markings"]) - dna.features["moth_markings"] = SSaccessories.moth_markings_list[deconstruct_block(get_uni_feature_block(features, DNA_MOTH_MARKINGS_BLOCK), length(SSaccessories.moth_markings_list))] - if(dna.features["caps"]) - dna.features["caps"] = SSaccessories.caps_list[deconstruct_block(get_uni_feature_block(features, DNA_MUSHROOM_CAPS_BLOCK), length(SSaccessories.caps_list))] - if(dna.features["pod_hair"]) - dna.features["pod_hair"] = SSaccessories.pod_hair_list[deconstruct_block(get_uni_feature_block(features, DNA_POD_HAIR_BLOCK), length(SSaccessories.pod_hair_list))] - if(dna.features["fish_tail"]) - dna.features["fish_tail"] = SSaccessories.tails_list_fish[deconstruct_block(get_uni_feature_block(features, DNA_FISH_TAIL_BLOCK), length(SSaccessories.tails_list_fish))] + . = ..() + for(var/block_type in GLOB.dna_identity_blocks) + var/datum/dna_block/identity/block_to_apply = GLOB.dna_identity_blocks[block_type] + block_to_apply.apply_to_mob(src, dna.unique_identity) + + for(var/block_type in GLOB.dna_feature_blocks) + var/datum/dna_block/feature/block_to_apply = GLOB.dna_feature_blocks[block_type] + if(dna.features[block_to_apply.feature_key]) + block_to_apply.apply_to_mob(src, dna.unique_features) for(var/obj/item/organ/organ in organs) - organ.mutate_feature(features, src) + organ.mutate_feature(dna.unique_features, src) if(icon_update) update_body(is_creating = mutcolor_update) - if(mutations_overlay_update) - update_mutations_overlay() + if(mutations_overlay_update) + update_mutations_overlay() */ //SKYRAT EDIT REMOVAL END @@ -910,15 +673,17 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) /mob/living/carbon/proc/random_mutate_unique_identity() if(!has_dna()) CRASH("[src] does not have DNA") - var/num = rand(1, DNA_UNI_IDENTITY_BLOCKS) - dna.set_uni_feature_block(num, random_string(GET_UI_BLOCK_LEN(num), GLOB.hex_characters)) - updateappearance(mutations_overlay_update=1) + var/mutblock_path = pick(GLOB.dna_identity_blocks) + var/datum/dna_block/identity/mutblock = GLOB.dna_identity_blocks[mutblock_path] + dna.unique_identity = mutblock.modified_hash(dna.unique_identity, random_string(mutblock.block_length, GLOB.hex_characters)) + updateappearance(mutations_overlay_update = TRUE) /mob/living/carbon/proc/random_mutate_unique_features() if(!has_dna()) CRASH("[src] does not have DNA") - var/num = rand(1, DNA_FEATURE_BLOCKS) - dna.set_uni_feature_block(num, random_string(GET_UF_BLOCK_LEN(num), GLOB.hex_characters)) + var/mutblock_path = pick(GLOB.dna_feature_blocks) + var/datum/dna_block/feature/mutblock = GLOB.dna_feature_blocks[mutblock_path] + dna.unique_features = mutblock.modified_hash(dna.unique_features, random_string(mutblock.block_length, GLOB.hex_characters)) updateappearance(mutcolor_update = TRUE, mutations_overlay_update = TRUE) /mob/living/carbon/proc/clean_dna() @@ -930,7 +695,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) clean_dna() random_mutate(candidates, difficulty) -/proc/scramble_dna(mob/living/carbon/M, ui=FALSE, se=FALSE, uf=FALSE, probability) +/proc/scramble_dna(mob/living/carbon/M, ui = FALSE, se = FALSE, uf = FALSE, probability = 100) if(!M.has_dna()) CRASH("[M] does not have DNA") if(HAS_TRAIT(M, TRAIT_NO_DNA_SCRAMBLE)) @@ -941,13 +706,15 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) M.dna.generate_dna_blocks() M.domutcheck() if(ui) - for(var/blocknum in 1 to DNA_UNI_IDENTITY_BLOCKS) + for(var/block_id in GLOB.dna_identity_blocks) + var/datum/dna_block/identity/block = GLOB.dna_identity_blocks[block_id] if(prob(probability)) - M.dna.set_uni_feature_block(blocknum, random_string(GET_UI_BLOCK_LEN(blocknum), GLOB.hex_characters)) + M.dna.unique_identity = block.modified_hash(M.dna.unique_identity, random_string(block.block_length, GLOB.hex_characters)) if(uf) - for(var/blocknum in 1 to DNA_FEATURE_BLOCKS) + for(var/block_id in GLOB.dna_feature_blocks) + var/datum/dna_block/feature/block = GLOB.dna_feature_blocks[block_id] if(prob(probability)) - M.dna.set_uni_feature_block(blocknum, random_string(GET_UF_BLOCK_LEN(blocknum), GLOB.hex_characters)) + M.dna.unique_identity = block.modified_hash(M.dna.unique_identity, random_string(block.block_length, GLOB.hex_characters)) if(ui || uf) M.updateappearance(mutcolor_update=uf, mutations_overlay_update=1) @@ -968,12 +735,6 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) value = values return value -/proc/get_uni_identity_block(identity, blocknum) - return copytext(identity, GLOB.total_ui_len_by_block[blocknum], LAZYACCESS(GLOB.total_ui_len_by_block, blocknum+1)) - -/proc/get_uni_feature_block(features, blocknum) - return copytext(features, GLOB.total_uf_len_by_block[blocknum], LAZYACCESS(GLOB.total_uf_len_by_block, blocknum+1)) - /////////////////////////// DNA HELPER-PROCS /mob/living/carbon/human/proc/something_horrible(ignore_stability) diff --git a/code/datums/dna/dna_block.dm b/code/datums/dna/dna_block.dm new file mode 100644 index 00000000000..f9205c2278e --- /dev/null +++ b/code/datums/dna/dna_block.dm @@ -0,0 +1,69 @@ +// This DNA block system is by no means perfect, and individual (Especially feature) blocks still contain a lot of copypaste +// It might be worth abstracting these, and compacting all SSaccessories vars that use dna_blocks into a single keyed list +// That's out of scope for me refactoring DNA, but to be considered for a future atomic change + +/// A singleton for handling block-unique functions called by the DNA datum. +/// +/// You don't need to add a DNA block for every feature. +/// Only add a new one if you want this feature to be changed via genetics. +/datum/dna_block + /// The length of this block when converted to ascii + var/block_length = DNA_BLOCK_SIZE + +/// Returns the unique block created from target. To be used for external calls. +/// +/// Does extra checks to make sure target is valid before calling the internal +/// `create_unique_block`, don't override this. +/datum/dna_block/proc/unique_block(mob/living/carbon/human/target) + SHOULD_NOT_OVERRIDE(TRUE) + if(!ishuman(target)) + CRASH("Non-human mobs shouldn't have DNA") + return create_unique_block(target) + +/// Actually creates the unique block from the inputted target. +/// Not used outside of the type, see `unique_block` instead. +/// +/// Children should always override this. +/datum/dna_block/proc/create_unique_block(mob/living/carbon/human/target) + PROTECTED_PROC(TRUE) + return null + +/// The position of this block's string in its hash type +/datum/dna_block/proc/position_in_hash() + return null + +/// Takes in the old hash and a string value to change this block to inside the hash. +/// +/// Returns a new hash with block's value updated +/datum/dna_block/proc/modified_hash(old_hash, value) + var/block_pos = position_in_hash() + if(isnull(block_pos)) + return old_hash + var/preceding_blocks = copytext(old_hash, 1, block_pos) + var/succeeding_blocks = copytext(old_hash, block_pos + block_length) + return (preceding_blocks + value + succeeding_blocks) + +/// Gets the block string from the hash inserted +/datum/dna_block/proc/get_block(from_hash) + if(isnull(from_hash)) + CRASH("Null hash provided for getting dna block string") + var/block_pos = position_in_hash() + return copytext(from_hash, block_pos, block_pos + block_length) + +/// Applies the DNA effects/appearance that this block's string encodes +/datum/dna_block/proc/apply_to_mob(mob/living/carbon/human/target, dna_hash) + return + +/// Blocks for unique identities (skin tones, hair style, and gender) +/datum/dna_block/identity + +/datum/dna_block/identity/position_in_hash() + return GLOB.total_ui_len_by_block[type] + +/// Blocks for unique features (mutant color, mutant bodyparts) +/datum/dna_block/feature + /// The feature key this block ties in to. + var/feature_key = null + +/datum/dna_block/feature/position_in_hash() + return GLOB.total_uf_len_by_block[type] diff --git a/code/datums/quirks/neutral_quirks/heretochromatic.dm b/code/datums/quirks/neutral_quirks/heretochromatic.dm index 96982b4089a..80cb2fef5f0 100644 --- a/code/datums/quirks/neutral_quirks/heretochromatic.dm +++ b/code/datums/quirks/neutral_quirks/heretochromatic.dm @@ -20,7 +20,7 @@ var/was_not_hetero = !human_holder.eye_color_heterochromatic human_holder.eye_color_heterochromatic = TRUE human_holder.eye_color_right = color - human_holder.dna.update_ui_block(DNA_EYE_COLOR_RIGHT_BLOCK) + human_holder.dna.update_ui_block(/datum/dna_block/identity/eye_colors) var/obj/item/organ/eyes/eyes_of_the_holder = quirk_holder.get_organ_by_type(/obj/item/organ/eyes) if(!eyes_of_the_holder) diff --git a/code/game/machinery/dna_infuser/organ_sets/fish_organs.dm b/code/game/machinery/dna_infuser/organ_sets/fish_organs.dm index 1a049412edd..dbe914a67e9 100644 --- a/code/game/machinery/dna_infuser/organ_sets/fish_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/fish_organs.dm @@ -220,7 +220,7 @@ greyscale_colors = FISH_ORGAN_COLOR bodypart_overlay = /datum/bodypart_overlay/mutant/tail/fish - dna_block = DNA_FISH_TAIL_BLOCK + dna_block = /datum/dna_block/feature/tail_fish wag_flags = NONE organ_traits = list(TRAIT_FLOPPING, TRAIT_SWIMMER) restyle_flags = EXTERNAL_RESTYLE_FLESH @@ -282,15 +282,15 @@ source.add_traits(list(TRAIT_OFF_BALANCE_TACKLER, TRAIT_NO_STAGGER, TRAIT_NO_THROW_HITPUSH), type) /datum/bodypart_overlay/mutant/tail/fish - feature_key = "fish_tail" + feature_key = FEATURE_TAIL_FISH color_source = ORGAN_COLOR_OVERRIDE /datum/bodypart_overlay/mutant/tail/fish/on_mob_insert(obj/item/organ/parent, mob/living/carbon/receiver) //Initialize the related dna feature block if we don't have any so it doesn't error out. //This isn't tied to any species, but I kinda want it to be mutable instead of having a fixed sprite accessory. - if(imprint_on_next_insertion && !receiver.dna.features["fish_tail"]) - receiver.dna.features["fish_tail"] = pick(SSaccessories.tails_list_fish) - receiver.dna.update_uf_block(DNA_FISH_TAIL_BLOCK) + if(imprint_on_next_insertion && !receiver.dna.features[FEATURE_TAIL_FISH]) + receiver.dna.features[FEATURE_TAIL_FISH] = pick(SSaccessories.tails_list_fish) + receiver.dna.update_uf_block(FEATURE_TAIL_FISH) return ..() diff --git a/code/game/machinery/dna_infuser/organ_sets/fox_organs.dm b/code/game/machinery/dna_infuser/organ_sets/fox_organs.dm index db9410cbf84..4df944427a8 100644 --- a/code/game/machinery/dna_infuser/organ_sets/fox_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/fox_organs.dm @@ -6,6 +6,6 @@ visual = TRUE damage_multiplier = 2 - //dna_block = DNA_EARS_BLOCK // Bubber edit - We don't use this + //dna_block = /datum/dna_block/feature/ears // Bubber edit - We don't use this bodypart_overlay = /datum/bodypart_overlay/mutant/cat_ears sprite_accessory_override = /datum/sprite_accessory/ears/fox diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index cc8a561acad..49979dd185c 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -199,15 +199,15 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/mirror/broken, 28) var/new_s_tone = tgui_input_list(race_changer, "Choose your skin tone", "Race change", GLOB.skin_tones) if(new_s_tone) race_changer.skin_tone = new_s_tone - race_changer.dna.update_ui_block(DNA_SKIN_TONE_BLOCK) + race_changer.dna.update_ui_block(/datum/dna_block/identity/skin_tone) else if(HAS_TRAIT(race_changer, TRAIT_MUTANT_COLORS) && !HAS_TRAIT(race_changer, TRAIT_FIXED_MUTANT_COLORS)) - var/new_mutantcolor = tgui_color_picker(race_changer, "Choose your skin color:", "Race change", race_changer.dna.features["mcolor"]) // BUBBERSTATION EDIT: TGUI COLOR PICKER + var/new_mutantcolor = tgui_color_picker(race_changer, "Choose your skin color:", "Race change", race_changer.dna.features[FEATURE_MUTANT_COLOR]) // BUBBERSTATION EDIT: TGUI COLOR PICKER if(new_mutantcolor) var/list/mutant_hsv = rgb2hsv(new_mutantcolor) if(mutant_hsv[3] >= 50) // mutantcolors must be bright - race_changer.dna.features["mcolor"] = sanitize_hexcolor(new_mutantcolor) - race_changer.dna.update_uf_block(DNA_MUTANT_COLOR_BLOCK) + race_changer.dna.features[FEATURE_MUTANT_COLOR] = sanitize_hexcolor(new_mutantcolor) + race_changer.dna.update_uf_block(FEATURE_MUTANT_COLOR) else to_chat(race_changer, span_notice("Invalid color. Your color is not bright enough.")) return TRUE @@ -241,7 +241,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/mirror/broken, 28) if(chosen_physique && chosen_physique != "Wizards Don't Need Gender") sexy.physique = (chosen_physique == "Warlock Physique") ? MALE : FEMALE - sexy.dna.update_ui_block(DNA_GENDER_BLOCK) + sexy.dna.update_ui_block(/datum/dna_block/identity/gender) sexy.update_body(is_creating = TRUE) // or else physique won't change properly sexy.update_mutations_overlay() //(hulk male/female) sexy.update_clothing(ITEM_SLOT_ICLOTHING) // update gender shaped clothing @@ -251,8 +251,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/mirror/broken, 28) if(isnull(new_eye_color)) return TRUE user.set_eye_color(sanitize_hexcolor(new_eye_color)) - user.dna.update_ui_block(DNA_EYE_COLOR_LEFT_BLOCK) - user.dna.update_ui_block(DNA_EYE_COLOR_RIGHT_BLOCK) + user.dna.update_ui_block(/datum/dna_block/identity/eye_colors) user.update_body() to_chat(user, span_notice("You gaze at your new eyes with your new eyes. Perfect!")) @@ -383,12 +382,12 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/mirror/broken, 28) if(new_hair_color) user.set_haircolor(sanitize_hexcolor(new_hair_color)) - user.dna.update_ui_block(DNA_HAIR_COLOR_BLOCK) + user.dna.update_ui_block(/datum/dna_block/identity/hair_color) if(user.physique == MALE) var/new_face_color = tgui_color_picker(user, "Choose your facial hair color", "Hair Color", user.facial_hair_color) // BUBBERSTATION EDIT: TGUI COLOR PICKER if(new_face_color) user.set_facial_haircolor(sanitize_hexcolor(new_face_color)) - user.dna.update_ui_block(DNA_FACIAL_HAIR_COLOR_BLOCK) + user.dna.update_ui_block(/datum/dna_block/identity/facial_color) /obj/structure/mirror/magic/attack_hand(mob/living/carbon/human/user) . = ..() diff --git a/code/modules/admin/verbs/secrets.dm b/code/modules/admin/verbs/secrets.dm index 84586ce3356..f9c9bdc50f6 100644 --- a/code/modules/admin/verbs/secrets.dm +++ b/code/modules/admin/verbs/secrets.dm @@ -578,7 +578,7 @@ ADMIN_VERB(secrets, R_NONE, "Secrets", "Abuse harder than you ever have before w SEND_SOUND(H, sound(SSstation.announcer.event_sounds[ANNOUNCER_ANIMES])) if(H.dna.species.id == SPECIES_HUMAN) - if(H.dna.features["tail_human"] == "None" || H.dna.features["ears"] == "None") + if(H.dna.features[FEATURE_TAIL] == "None" || H.dna.features[FEATURE_EARS] == "None") var/obj/item/organ/ears/cat/ears = new var/obj/item/organ/tail/cat/tail = new ears.Insert(H, movement_flags = DELETE_IF_REPLACED) diff --git a/code/modules/antagonists/brother/brother.dm b/code/modules/antagonists/brother/brother.dm index b539cfb2e0b..39b21d15f3f 100644 --- a/code/modules/antagonists/brother/brother.dm +++ b/code/modules/antagonists/brother/brother.dm @@ -133,14 +133,14 @@ var/mob/living/carbon/human/dummy/consistent/brother1 = new var/mob/living/carbon/human/dummy/consistent/brother2 = new - brother1.dna.features["ethcolor"] = GLOB.color_list_ethereal["Faint Red"] + brother1.dna.features[FEATURE_ETHEREAL_COLOR] = GLOB.color_list_ethereal["Faint Red"] brother1.set_species(/datum/species/ethereal) - brother2.dna.features["mcolor"] = "#E5CD99" // SKYRAT EDIT ADDITION - Customization - brother2.dna.mutant_bodyparts["moth_antennae"] = list(MUTANT_INDEX_NAME = "Plain", MUTANT_INDEX_COLOR_LIST = list("#FFFFFF", "#FFFFFF", "#FFFFFF")) // SKYRAT EDIT - Customization - ORIGINAL: brother2.dna.features["moth_antennae"] = "Plain" - brother2.dna.mutant_bodyparts["moth_markings"] = list(MUTANT_INDEX_NAME = "None", MUTANT_INDEX_COLOR_LIST = list("#FFFFFF", "#FFFFFF", "#FFFFFF")) // SKYRAT EDIT - Customization - ORIGINAL: brother2.dna.features["moth_markings"] = "None" - brother2.dna.mutant_bodyparts["wings"] = list(MUTANT_INDEX_NAME = "Moth (Plain)", MUTANT_INDEX_COLOR_LIST = list("#FFFFFF", "#FFFFFF", "#FFFFFF")) // SKYRAT EDIT - Customization - ORIGINAL: brother2.dna.features["moth_wings"] = "Plain" + brother2.dna.features[FEATURE_MUTANT_COLOR] = "#E5CD99" // SKYRAT EDIT ADDITION - Customization + brother2.dna.mutant_bodyparts[FEATURE_MOTH_ANTENNAE] = list(MUTANT_INDEX_NAME = "Plain", MUTANT_INDEX_COLOR_LIST = list("#FFFFFF", "#FFFFFF", "#FFFFFF")) // SKYRAT EDIT - Customization - ORIGINAL: brother2.dna.features[FEATURE_MOTH_ANTENNAE] = "Plain" + brother2.dna.mutant_bodyparts[FEATURE_MOTH_MARKINGS] = list(MUTANT_INDEX_NAME = "None", MUTANT_INDEX_COLOR_LIST = list("#FFFFFF", "#FFFFFF", "#FFFFFF")) // SKYRAT EDIT - Customization - ORIGINAL: brother2.dna.features[FEATURE_MOTH_MARKINGS] = "None" + brother2.dna.mutant_bodyparts[FEATURE_WINGS] = list(MUTANT_INDEX_NAME = "Moth (Plain)", MUTANT_INDEX_COLOR_LIST = list("#FFFFFF", "#FFFFFF", "#FFFFFF")) // SKYRAT EDIT - Customization - ORIGINAL: brother2.dna.features[FEATURE_MOTH_WINGS] = "Plain" brother2.set_species(/datum/species/moth) var/icon/brother1_icon = render_preview_outfit(/datum/outfit/job/quartermaster, brother1) diff --git a/code/modules/client/preferences/species_features/ethereal.dm b/code/modules/client/preferences/species_features/ethereal.dm index 244068bc8a9..fc93cf4008e 100644 --- a/code/modules/client/preferences/species_features/ethereal.dm +++ b/code/modules/client/preferences/species_features/ethereal.dm @@ -33,4 +33,4 @@ return icon /datum/preference/choiced/ethereal_color/apply_to_human(mob/living/carbon/human/target, value) - target.dna.features["ethcolor"] = GLOB.color_list_ethereal[value] + target.dna.features[FEATURE_ETHEREAL_COLOR] = GLOB.color_list_ethereal[value] diff --git a/code/modules/client/preferences/species_features/felinid.dm b/code/modules/client/preferences/species_features/felinid.dm index b9e923c420d..cfc6cd86f03 100644 --- a/code/modules/client/preferences/species_features/felinid.dm +++ b/code/modules/client/preferences/species_features/felinid.dm @@ -10,7 +10,7 @@ return assoc_to_keys_features(SSaccessories.tails_list_felinid) /datum/preference/choiced/tail_felinid/apply_to_human(mob/living/carbon/human/target, value) - target.dna.features["tail_cat"] = value + target.dna.features[FEATURE_TAIL] = value /datum/preference/choiced/tail_felinid/create_default_value() var/datum/sprite_accessory/tails/felinid/cat/tail = /datum/sprite_accessory/tails/felinid/cat @@ -27,7 +27,7 @@ return assoc_to_keys_features(SSaccessories.ears_list) /datum/preference/choiced/felinid_ears/apply_to_human(mob/living/carbon/human/target, value) - target.dna.features["ears"] = value + target.dna.features[FEATURE_EARS] = value /datum/preference/choiced/felinid_ears/create_default_value() return /datum/sprite_accessory/ears/cat::name diff --git a/code/modules/client/preferences/species_features/lizard.dm b/code/modules/client/preferences/species_features/lizard.dm index bbb23e1fe11..d379328074c 100644 --- a/code/modules/client/preferences/species_features/lizard.dm +++ b/code/modules/client/preferences/species_features/lizard.dm @@ -56,7 +56,7 @@ return final_icon /datum/preference/choiced/lizard_body_markings/apply_to_human(mob/living/carbon/human/target, value) - target.dna.features["lizard_markings"] = value + target.dna.features[FEATURE_LIZARD_MARKINGS] = value /datum/preference/choiced/lizard_frills savefile_key = "feature_lizard_frills" @@ -73,7 +73,7 @@ return generate_lizard_side_shot(SSaccessories.frills_list[value], "frills") /datum/preference/choiced/lizard_frills/apply_to_human(mob/living/carbon/human/target, value) - target.dna.features["frills"] = value + target.dna.features[FEATURE_FRILLS] = value /datum/preference/choiced/lizard_horns savefile_key = "feature_lizard_horns" @@ -90,7 +90,7 @@ return generate_lizard_side_shot(SSaccessories.horns_list[value], "horns") /datum/preference/choiced/lizard_horns/apply_to_human(mob/living/carbon/human/target, value) - target.dna.features["horns"] = value + target.dna.features[FEATURE_HORNS] = value /datum/preference/choiced/lizard_legs savefile_key = "feature_lizard_legs" @@ -101,7 +101,7 @@ return list(NORMAL_LEGS, DIGITIGRADE_LEGS) /datum/preference/choiced/lizard_legs/apply_to_human(mob/living/carbon/human/target, value) - target.dna.features["legs"] = value + target.dna.features[FEATURE_LEGS] = value // Hack to update the dummy in the preference menu // (Because digi legs are ONLY handled on species change) if(!isdummy(target) || target.dna.species.digitigrade_customization == DIGITIGRADE_NEVER) @@ -146,7 +146,7 @@ return generate_lizard_side_shot(SSaccessories.snouts_list[value], "snout", include_snout = FALSE) /datum/preference/choiced/lizard_snout/apply_to_human(mob/living/carbon/human/target, value) - target.dna.features["snout"] = value + target.dna.features[FEATURE_SNOUT] = value /datum/preference/choiced/lizard_spines savefile_key = "feature_lizard_spines" @@ -158,7 +158,7 @@ return assoc_to_keys_features(SSaccessories.spines_list) /datum/preference/choiced/lizard_spines/apply_to_human(mob/living/carbon/human/target, value) - target.dna.features["spines"] = value + target.dna.features[FEATURE_SPINES] = value /datum/preference/choiced/lizard_tail savefile_key = "feature_lizard_tail" @@ -170,7 +170,7 @@ return assoc_to_keys_features(SSaccessories.tails_list_lizard) /datum/preference/choiced/lizard_tail/apply_to_human(mob/living/carbon/human/target, value) - target.dna.features["tail_lizard"] = value + target.dna.features[FEATURE_TAIL_LIZARD] = value /datum/preference/choiced/lizard_tail/create_default_value() return /datum/sprite_accessory/tails/lizard/smooth::name diff --git a/code/modules/client/preferences/species_features/monkey.dm b/code/modules/client/preferences/species_features/monkey.dm index edc92240ed9..2cdf998f849 100644 --- a/code/modules/client/preferences/species_features/monkey.dm +++ b/code/modules/client/preferences/species_features/monkey.dm @@ -10,7 +10,7 @@ return assoc_to_keys_features(SSaccessories.tails_list_monkey) /datum/preference/choiced/monkey_tail/apply_to_human(mob/living/carbon/human/target, value) - target.dna.features["tail_monkey"] = value + target.dna.features[FEATURE_TAIL_MONKEY] = value /datum/preference/choiced/monkey_tail/create_default_value() var/datum/sprite_accessory/tails/monkey/default/tail = /datum/sprite_accessory/tails/monkey/default diff --git a/code/modules/client/preferences/species_features/moth.dm b/code/modules/client/preferences/species_features/moth.dm index e3a5f8c3fdb..fac5d42e6c0 100644 --- a/code/modules/client/preferences/species_features/moth.dm +++ b/code/modules/client/preferences/species_features/moth.dm @@ -28,7 +28,7 @@ return icon_with_antennae /datum/preference/choiced/moth_antennae/apply_to_human(mob/living/carbon/human/target, value) - target.dna.features["moth_antennae"] = value + target.dna.features[FEATURE_MOTH_ANTENNAE] = value /datum/preference/choiced/moth_markings savefile_key = "feature_moth_markings" @@ -78,7 +78,7 @@ return icon_with_markings /datum/preference/choiced/moth_markings/apply_to_human(mob/living/carbon/human/target, value) - target.dna.features["moth_markings"] = value + target.dna.features[FEATURE_MOTH_MARKINGS] = value /datum/preference/choiced/moth_wings savefile_key = "feature_moth_wings" @@ -96,6 +96,5 @@ return uni_icon(moth_wings.icon, "m_moth_wings_[moth_wings.icon_state]_BEHIND") /datum/preference/choiced/moth_wings/apply_to_human(mob/living/carbon/human/target, value) - target.dna.features["moth_wings"] = value - + target.dna.features[FEATURE_MOTH_WINGS] = value */ diff --git a/code/modules/client/preferences/species_features/mushperson.dm b/code/modules/client/preferences/species_features/mushperson.dm index b0f82571f6b..5eed4d3b4ef 100644 --- a/code/modules/client/preferences/species_features/mushperson.dm +++ b/code/modules/client/preferences/species_features/mushperson.dm @@ -9,5 +9,5 @@ return assoc_to_keys_features(SSaccessories.caps_list) /datum/preference/choiced/mushroom_cap/apply_to_human(mob/living/carbon/human/target, value) - target.dna.features["caps"] = value + target.dna.features[FEATURE_MUSH_CAP] = value */ diff --git a/code/modules/client/preferences/species_features/mutants.dm b/code/modules/client/preferences/species_features/mutants.dm index 12ae93d2d2d..194e3a5a759 100644 --- a/code/modules/client/preferences/species_features/mutants.dm +++ b/code/modules/client/preferences/species_features/mutants.dm @@ -17,7 +17,7 @@ return sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]") /datum/preference/color/mutant_color/apply_to_human(mob/living/carbon/human/target, value) - target.dna.features["mcolor"] = value + target.dna.features[FEATURE_MUTANT_COLOR] = value /datum/preference/color/mutant_color/is_valid(value) if (!..(value)) diff --git a/code/modules/client/preferences/species_features/pod.dm b/code/modules/client/preferences/species_features/pod.dm index 2a846b22842..866dc64c539 100644 --- a/code/modules/client/preferences/species_features/pod.dm +++ b/code/modules/client/preferences/species_features/pod.dm @@ -30,5 +30,5 @@ return pick(assoc_to_keys_features(SSaccessories.pod_hair_list)) /datum/preference/choiced/pod_hair/apply_to_human(mob/living/carbon/human/target, value) - target.dna.features["pod_hair"] = value -*/ // SKYRAT EDIT END + target.dna.features[FEATURE_POD_HAIR] = value +*/ diff --git a/code/modules/hydroponics/grown/replicapod.dm b/code/modules/hydroponics/grown/replicapod.dm index 5a655d06ef2..408eb2eb24b 100644 --- a/code/modules/hydroponics/grown/replicapod.dm +++ b/code/modules/hydroponics/grown/replicapod.dm @@ -199,11 +199,11 @@ podman.gender = blood_gender podman.faction |= factions - if(!features["mcolor"]) - features["mcolor"] = "#59CE00" + if(!features[FEATURE_MUTANT_COLOR]) + features[FEATURE_MUTANT_COLOR] = "#59CE00" /* SKYRAT EDIT REMOVAL START - if(!features["pod_hair"]) - features["pod_hair"] = pick(SSaccessories.pod_hair_list) + if(!features[FEATURE_POD_HAIR]) + features[FEATURE_POD_HAIR] = pick(SSaccessories.pod_hair_list) */ //SKYRAT EDIT REMOVAL END - Tricolor Pod Hair for(var/V in quirks) diff --git a/code/modules/mining/lavaland/mining_loot/megafauna/ash_drake.dm b/code/modules/mining/lavaland/mining_loot/megafauna/ash_drake.dm index cd4d355cb2f..3276ba3a128 100644 --- a/code/modules/mining/lavaland/mining_loot/megafauna/ash_drake.dm +++ b/code/modules/mining/lavaland/mining_loot/megafauna/ash_drake.dm @@ -171,50 +171,49 @@ if(1) to_chat(user, span_danger("Your appearance morphs to that of a very small humanoid ash dragon! You get to look like a freak without the cool abilities.")) - // BUBBER EDIT CHANGE BEGIN + // BUBBER EDIT CHANGE BEGIN // consumer.dna.features = list( - // "mcolor" = "#A02720", - // "tail_lizard" = "Dark Tiger", - // "tail_human" = "None", - // "snout" = "Sharp", - // "horns" = "Curled", - // "ears" = "None", - // "wings" = "None", - // "frills" = "None", - // "spines" = "Long", - // "lizard_markings" = "Dark Tiger Body", - // "legs" = DIGITIGRADE_LEGS, - consumer.dna.features["mcolor"] = "#A02720" + // FEATURE_MUTANT_COLOR = "#A02720", + // FEATURE_TAIL_LIZARD = "Dark Tiger", + // FEATURE_TAIL = "None", + // FEATURE_SNOUT = "Sharp", + // FEATURE_HORNS = "Curled", + // FEATURE_EARS = "None", + // FEATURE_WINGS = "None", + // FEATURE_FRILLS = "None", + // FEATURE_SPINES = "Long", + // FEATURE_LIZARD_MARKINGS = "Dark Tiger Body", + // FEATURE_LEGS = DIGITIGRADE_LEGS, + consumer.dna.features[FEATURE_MUTANT_COLOR] = "#A02720" consumer.dna.mutant_bodyparts["tail"] = list( - "name" = "Dark Tiger", - "color" = list(1 = "#A02720", 2 = "#A02720", 3 = "#A02720") + MUTANT_INDEX_NAME = "Dark Tiger", + MUTANT_INDEX_COLOR_LIST = list("#A02720", "#A02720", "#A02720") ) - consumer.dna.mutant_bodyparts["snout"] = list( - "name" = "Sharp", - "color" = list(1 = "#A02720", 2 = "#A02720", 3 = "#A02720") + consumer.dna.mutant_bodyparts[FEATURE_SNOUT] = list( + MUTANT_INDEX_NAME = "Sharp", + MUTANT_INDEX_COLOR_LIST = list("#A02720", "#A02720", "#A02720") ) - consumer.dna.mutant_bodyparts["horns"] = list( - "name" = "Curled", - "color" = list(1 = "#A02720", 2 = "#A02720", 3 = "#A02720") + consumer.dna.mutant_bodyparts[FEATURE_HORNS] = list( + MUTANT_INDEX_NAME = "Curled", + MUTANT_INDEX_COLOR_LIST = list("#A02720", "#A02720", "#A02720") ) - consumer.dna.mutant_bodyparts["ears"] = list( - "name" = "None", - "color" = list(1 = "#A02720", 2 = "#A02720", 3 = "#A02720") + consumer.dna.mutant_bodyparts[FEATURE_EARS] = list( + MUTANT_INDEX_NAME = "None", + MUTANT_INDEX_COLOR_LIST = list("#A02720", "#A02720", "#A02720") ) - consumer.dna.mutant_bodyparts["wings"] = list( - "name" = "None", - "color" = list(1 = "#A02720", 2 = "#A02720", 3 = "#A02720") + consumer.dna.mutant_bodyparts[FEATURE_WINGS] = list( + MUTANT_INDEX_NAME = "None", + MUTANT_INDEX_COLOR_LIST = list("#A02720", "#A02720", "#A02720") ) - consumer.dna.mutant_bodyparts["frills"] = list( - "name" = "None", - "color" = list(1 = "#A02720", 2 = "#A02720", 3 = "#A02720") + consumer.dna.mutant_bodyparts[FEATURE_FRILLS] = list( + MUTANT_INDEX_NAME = "None", + MUTANT_INDEX_COLOR_LIST = list("#A02720", "#A02720", "#A02720") ) - consumer.dna.mutant_bodyparts["spines"] = list( - "name" = "Long", - "color" = list(1 = "#A02720", 2 = "#A02720", 3 = "#A02720") + consumer.dna.mutant_bodyparts[FEATURE_SPINES] = list( + MUTANT_INDEX_NAME = "Long", + MUTANT_INDEX_COLOR_LIST = list("#A02720", "#A02720", "#A02720") ) - - consumer.dna.features["legs"] = DIGITIGRADE_LEGS + consumer.dna.features[FEATURE_LEGS] = DIGITIGRADE_LEGS //BUBBER EDIT CHANGE END consumer.set_eye_color("#FEE5A3") diff --git a/code/modules/mob/living/blood_types.dm b/code/modules/mob/living/blood_types.dm index 20f95d534dc..e46c1834954 100644 --- a/code/modules/mob/living/blood_types.dm +++ b/code/modules/mob/living/blood_types.dm @@ -350,9 +350,9 @@ // Ensures that lighter slimefolk look half-decent when wounded and bleeding /datum/blood_type/slime/get_wound_color(mob/living/carbon/victim) - return victim.dna?.features?["mcolor"] || get_color() + return victim.dna?.features?[FEATURE_MUTANT_COLOR] || get_color() /datum/blood_type/slime/get_damage_color(mob/living/carbon/victim) - return victim.dna?.features?["mcolor"] || get_color() + return victim.dna?.features?[FEATURE_MUTANT_COLOR] || get_color() /// Podpeople blood /datum/blood_type/water diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index 5e4b4197324..20d6f7d2b82 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -2096,7 +2096,7 @@ GLOBAL_LIST_EMPTY(features_by_species) // BUBBER EDIT BEGIN REMOVAL - We bake these into the species /* - if((new_species.digitigrade_customization == DIGITIGRADE_OPTIONAL && target.dna.features["legs"] == DIGITIGRADE_LEGS) || new_species.digitigrade_customization == DIGITIGRADE_FORCED) + if((new_species.digitigrade_customization == DIGITIGRADE_OPTIONAL && target.dna.features[FEATURE_LEGS] == DIGITIGRADE_LEGS) || new_species.digitigrade_customization == DIGITIGRADE_FORCED) final_bodypart_overrides[BODY_ZONE_R_LEG] = /obj/item/bodypart/leg/right/digitigrade final_bodypart_overrides[BODY_ZONE_L_LEG] = /obj/item/bodypart/leg/left/digitigrade */ // BUBBER EDIT END @@ -2149,7 +2149,7 @@ GLOBAL_LIST_EMPTY(features_by_species) ASSERT(!isnull(for_mob)) switch(hair_color_mode) if(USE_MUTANT_COLOR) - return for_mob.dna.features["mcolor"] + return for_mob.dna.features[FEATURE_MUTANT_COLOR] if(USE_FIXED_MUTANT_COLOR) return fixed_mut_color @@ -2166,7 +2166,7 @@ GLOBAL_LIST_EMPTY(features_by_species) continue var/datum/bodypart_overlay/simple/body_marking/overlay = new markings_type() - overlay.set_appearance(accessory_name, hooman.dna.features["mcolor"]) + overlay.set_appearance(accessory_name, hooman.dna.features[FEATURE_MUTANT_COLOR]) people_part.add_bodypart_overlay(overlay) qdel(markings) diff --git a/code/modules/mob/living/carbon/human/dummy.dm b/code/modules/mob/living/carbon/human/dummy.dm index f28087efd15..fb560f70fd7 100644 --- a/code/modules/mob/living/carbon/human/dummy.dm +++ b/code/modules/mob/living/carbon/human/dummy.dm @@ -105,24 +105,24 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy) return consistent_entry /proc/create_consistent_human_dna(mob/living/carbon/human/target) - target.dna.features["mcolor"] = COLOR_VIBRANT_LIME - target.dna.features["ethcolor"] = COLOR_WHITE + target.dna.features[FEATURE_MUTANT_COLOR] = COLOR_VIBRANT_LIME + target.dna.features[FEATURE_ETHEREAL_COLOR] = COLOR_WHITE /* SKYRAT EDIT START REMOVAL START - Customization - target.dna.features["lizard_markings"] = get_consistent_feature_entry(SSaccessories.lizard_markings_list) - target.dna.features["ears"] = get_consistent_feature_entry(SSaccessories.ears_list) - target.dna.features["frills"] = get_consistent_feature_entry(SSaccessories.frills_list) - target.dna.features["horns"] = get_consistent_feature_entry(SSaccessories.horns_list) - target.dna.features["moth_antennae"] = get_consistent_feature_entry(SSaccessories.moth_antennae_list) - target.dna.features["moth_markings"] = get_consistent_feature_entry(SSaccessories.moth_markings_list) - target.dna.features["moth_wings"] = get_consistent_feature_entry(SSaccessories.moth_wings_list) - target.dna.features["snout"] = get_consistent_feature_entry(SSaccessories.snouts_list) - target.dna.features["spines"] = get_consistent_feature_entry(SSaccessories.spines_list) - target.dna.features["tail_cat"] = get_consistent_feature_entry(SSaccessories.tails_list_felinid) // it's a lie - target.dna.features["tail_lizard"] = get_consistent_feature_entry(SSaccessories.tails_list_lizard) - target.dna.features["tail_monkey"] = get_consistent_feature_entry(SSaccessories.tails_list_monkey) - target.dna.features["fish_tail"] = get_consistent_feature_entry(SSaccessories.tails_list_fish) - target.dna.features["pod_hair"] = get_consistent_feature_entry(SSaccessories.pod_hair_list) - target.dna.features["caps"] = get_consistent_feature_entry(SSaccessories.caps_list) + target.dna.features[FEATURE_LIZARD_MARKINGS] = get_consistent_feature_entry(SSaccessories.lizard_markings_list) + target.dna.features[FEATURE_EARS] = get_consistent_feature_entry(SSaccessories.ears_list) + target.dna.features[FEATURE_FRILLS] = get_consistent_feature_entry(SSaccessories.frills_list) + target.dna.features[FEATURE_HORNS] = get_consistent_feature_entry(SSaccessories.horns_list) + target.dna.features[FEATURE_MOTH_ANTENNAE] = get_consistent_feature_entry(SSaccessories.moth_antennae_list) + target.dna.features[FEATURE_MOTH_MARKINGS] = get_consistent_feature_entry(SSaccessories.moth_markings_list) + target.dna.features[FEATURE_MOTH_WINGS] = get_consistent_feature_entry(SSaccessories.moth_wings_list) + target.dna.features[FEATURE_SNOUT] = get_consistent_feature_entry(SSaccessories.snouts_list) + target.dna.features[FEATURE_SPINES] = get_consistent_feature_entry(SSaccessories.spines_list) + target.dna.features[FEATURE_TAIL] = get_consistent_feature_entry(SSaccessories.tails_list_felinid) // it's a lie + target.dna.features[FEATURE_TAIL_LIZARD] = get_consistent_feature_entry(SSaccessories.tails_list_lizard) + target.dna.features[FEATURE_TAIL_MONKEY] = get_consistent_feature_entry(SSaccessories.tails_list_monkey) + target.dna.features[FEATURE_TAIL_FISH] = get_consistent_feature_entry(SSaccessories.tails_list_fish) + target.dna.features[FEATURE_POD_HAIR] = get_consistent_feature_entry(SSaccessories.pod_hair_list) + target.dna.features[FEATURE_MUSH_CAP] = get_consistent_feature_entry(SSaccessories.caps_list) */ // SKYRAT EDIT REMOVAL END target.dna.initialize_dna(newblood_type = get_blood_type(BLOOD_TYPE_O_MINUS), create_mutation_blocks = FALSE, randomize_features = FALSE) // UF and UI are nondeterministic, even though the features are the same some blocks will randomize slightly diff --git a/code/modules/mob/living/carbon/human/species_types/ethereal.dm b/code/modules/mob/living/carbon/human/species_types/ethereal.dm index 295a4bd7201..3f7cf201ee8 100644 --- a/code/modules/mob/living/carbon/human/species_types/ethereal.dm +++ b/code/modules/mob/living/carbon/human/species_types/ethereal.dm @@ -55,7 +55,7 @@ . = ..() if(!ishuman(new_ethereal)) return - default_color = new_ethereal.dna.features["ethcolor"] + default_color = new_ethereal.dna.features[FEATURE_ETHEREAL_COLOR] RegisterSignal(new_ethereal, COMSIG_ATOM_EMAG_ACT, PROC_REF(on_emag_act)) RegisterSignal(new_ethereal, COMSIG_ATOM_EMP_ACT, PROC_REF(on_emp_act)) RegisterSignal(new_ethereal, COMSIG_ATOM_SABOTEUR_ACT, PROC_REF(hit_by_saboteur)) @@ -84,7 +84,7 @@ /datum/species/ethereal/randomize_features() var/list/features = ..() - features["ethcolor"] = GLOB.color_list_ethereal[pick(GLOB.color_list_ethereal)] + features[FEATURE_ETHEREAL_COLOR] = GLOB.color_list_ethereal[pick(GLOB.color_list_ethereal)] return features /datum/species/ethereal/proc/refresh_light_color(mob/living/carbon/human/ethereal) @@ -95,7 +95,7 @@ var/healthpercent = max(ethereal.health, 0) / 100 if(!emageffect) var/static/list/skin_color = rgb2num("#eda495") - var/list/colors = rgb2num(ethereal.dna.features["ethcolor"]) + var/list/colors = rgb2num(ethereal.dna.features[FEATURE_ETHEREAL_COLOR]) var/list/built_color = list() for(var/i in 1 to 3) built_color += skin_color[i] + ((colors[i] - skin_color[i]) * healthpercent) @@ -334,5 +334,5 @@ /datum/species/ethereal/lustrous/on_species_gain(mob/living/carbon/new_lustrous, datum/species/old_species, pref_load, regenerate_icons) ..() - default_color = new_lustrous.dna.features["ethcolor"] - new_lustrous.dna.features["ethcolor"] = GLOB.color_list_lustrous[pick(GLOB.color_list_lustrous)] //Picks one of 5 lustrous-specific colors. + default_color = new_lustrous.dna.features[FEATURE_ETHEREAL_COLOR] + new_lustrous.dna.features[FEATURE_ETHEREAL_COLOR] = GLOB.color_list_lustrous[pick(GLOB.color_list_lustrous)] //Picks one of 5 lustrous-specific colors. diff --git a/code/modules/mob/living/carbon/human/species_types/felinid.dm b/code/modules/mob/living/carbon/human/species_types/felinid.dm index 5b9d9c04260..f270801bce7 100644 --- a/code/modules/mob/living/carbon/human/species_types/felinid.dm +++ b/code/modules/mob/living/carbon/human/species_types/felinid.dm @@ -30,14 +30,14 @@ if(ishuman(carbon_being)) var/mob/living/carbon/human/target_human = carbon_being if(!pref_load) //Hah! They got forcefully purrbation'd. Force default felinid parts on them if they have no mutant parts in those areas! - target_human.dna.features["tail_cat"] = "Cat" - if(target_human.dna.features["ears"] == "None") - target_human.dna.features["ears"] = "Cat" + target_human.dna.features[FEATURE_TAIL] = "Cat" + if(target_human.dna.features[FEATURE_EARS] == "None") + target_human.dna.features[FEATURE_EARS] = "Cat" /* SKYRAT EDIT -- START -- ORIGINAL - if(target_human.dna.features["ears"] == "None") + if(target_human.dna.features[FEATURE_EARS] == "None") mutantears = /obj/item/organ/ears else - var/obj/item/organ/ears/cat/ears = new(FALSE, target_human.dna.features["ears"]) + var/obj/item/organ/ears/cat/ears = new(FALSE, target_human.dna.features[FEATURE_EARS]) ears.Insert(target_human, movement_flags = DELETE_IF_REPLACED) */ if(target_human.dna.features["ears"] == "Cat") @@ -50,7 +50,7 @@ /datum/species/human/felinid/randomize_features(mob/living/carbon/human/human_mob) var/list/features = ..() - features["ears"] = pick("None", "Cat") + features[FEATURE_EARS] = pick("None", "Cat") return features /datum/species/human/felinid/get_laugh_sound(mob/living/carbon/human/felinid) diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm index ad340710bcb..42958260703 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -115,7 +115,7 @@ ) /datum/species/jelly/prepare_human_for_preview(mob/living/carbon/human/human) - human.dna.features["mcolor"] = COLOR_PINK + human.dna.features[FEATURE_MUTANT_COLOR] = COLOR_PINK human.hairstyle = "Bob Hair 2" human.hair_color = COLOR_PINK human.update_body(is_creating = TRUE) @@ -312,8 +312,8 @@ spare.underwear = "Nude" H.dna.copy_dna(spare.dna, COPY_DNA_SE|COPY_DNA_SPECIES|COPY_DNA_MUTATIONS) - spare.dna.features["mcolor"] = "#[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]" - spare.dna.update_uf_block(DNA_MUTANT_COLOR_BLOCK) + spare.dna.features[FEATURE_MUTANT_COLOR] = "#[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]" + spare.dna.update_uf_block(FEATURE_MUTANT_COLOR) spare.real_name = spare.dna.real_name spare.name = spare.dna.real_name spare.updateappearance(mutcolor_update=1) @@ -387,7 +387,7 @@ continue var/list/L = list() - L["htmlcolor"] = body.dna.features["mcolor"] + L["htmlcolor"] = body.dna.features[FEATURE_MUTANT_COLOR] L["area"] = get_area_name(body, TRUE) var/stat = "error" switch(body.stat) @@ -557,7 +557,7 @@ /datum/species/jelly/luminescent/proc/update_glow(mob/living/carbon/human/glowie, intensity) if(intensity) glow_intensity = intensity - glow.set_light_range_power_color(glow_intensity, glow_intensity, glowie.dna.features["mcolor"]) + glow.set_light_range_power_color(glow_intensity, glow_intensity, glowie.dna.features[FEATURE_MUTANT_COLOR]) /datum/action/innate/integrate_extract name = "Integrate Extract" diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm index 2fe4a902fd2..774479f1e6c 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -52,7 +52,7 @@ /* /datum/species/lizard/randomize_features() var/list/features = ..() - features["lizard_markings"] = pick(SSaccessories.lizard_markings_list) + features[FEATURE_LIZARD_MARKINGS] = pick(SSaccessories.lizard_markings_list) return features */ @@ -230,14 +230,14 @@ Lizard subspecies: SILVER SCALED and their tongue allows them to turn into a statue, for some reason." /datum/species/lizard/silverscale/on_species_gain(mob/living/carbon/human/new_silverscale, datum/species/old_species, pref_load, regenerate_icons) - old_mutcolor = new_silverscale.dna.features["mcolor"] - new_silverscale.dna.features["mcolor"] = "#eeeeee" + old_mutcolor = new_silverscale.dna.features[FEATURE_MUTANT_COLOR] + new_silverscale.dna.features[FEATURE_MUTANT_COLOR] = "#eeeeee" new_silverscale.add_eye_color("#0000a0", EYE_COLOR_SPECIES_PRIORITY) . = ..() new_silverscale.add_filter("silver_glint", 2, list("type" = "outline", "color" = "#ffffff63", "size" = 2)) /datum/species/lizard/silverscale/on_species_loss(mob/living/carbon/human/was_silverscale, datum/species/new_species, pref_load) - was_silverscale.dna.features["mcolor"] = old_mutcolor + was_silverscale.dna.features[FEATURE_MUTANT_COLOR] = old_mutcolor was_silverscale.remove_eye_color(EYE_COLOR_SPECIES_PRIORITY) was_silverscale.remove_filter("silver_glint") return ..() diff --git a/code/modules/mob/living/carbon/human/species_types/mothmen.dm b/code/modules/mob/living/carbon/human/species_types/mothmen.dm index e102e321599..1db98982320 100644 --- a/code/modules/mob/living/carbon/human/species_types/mothmen.dm +++ b/code/modules/mob/living/carbon/human/species_types/mothmen.dm @@ -43,7 +43,7 @@ /datum/species/moth/randomize_features() var/list/features = ..() - features["moth_markings"] = pick(SSaccessories.moth_wings_list) // SKYRAT EDIT CHANGE - ORIGINAL: features["moth_markings"] = pick(SSaccessories.moth_markings_list) + features[FEATURE_MOTH_MARKINGS] = pick(SSaccessories.moth_wings_list) // SKYRAT EDIT CHANGE - ORIGINAL: features[FEATURE_MOTH_MARKINGS] = pick(SSaccessories.moth_markings_list) return features /datum/species/moth/get_scream_sound(mob/living/carbon/human/moth) diff --git a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm index e664c1b352b..49e96055c37 100644 --- a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm @@ -61,7 +61,7 @@ preference = "feature_mushperson_cap" - //dna_block = DNA_MUSHROOM_CAPS_BLOCK // SKYRAT EDIT REMOVAL - Customization - We have our own system to handle DNA. + //dna_block = /datum/dna_block/feature/mush_cap // SKYRAT EDIT REMOVAL - Customization - We have our own system to handle DNA. restyle_flags = EXTERNAL_RESTYLE_PLANT bodypart_overlay = /datum/bodypart_overlay/mutant/mushroom_cap @@ -71,7 +71,7 @@ /// Bodypart overlay for the mushroom cap organ /datum/bodypart_overlay/mutant/mushroom_cap layers = EXTERNAL_ADJACENT - feature_key = "caps" + feature_key = FEATURE_MUSH_CAP dyable = TRUE /datum/bodypart_overlay/mutant/mushroom_cap/get_global_feature_list() diff --git a/code/modules/mob/living/carbon/human/species_types/podpeople.dm b/code/modules/mob/living/carbon/human/species_types/podpeople.dm index cc76f0716ec..34afa3e4f74 100644 --- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/podpeople.dm @@ -40,8 +40,8 @@ ) /datum/species/pod/prepare_human_for_preview(mob/living/carbon/human/human) - human.dna.features["mcolor"] = "#886600" - human.dna.features["pod_hair"] = "Rose" + human.dna.features[FEATURE_MUTANT_COLOR] = "#886600" + human.dna.features[FEATURE_POD_HAIR] = "Rose" human.update_body(is_creating = TRUE) /datum/species/pod/get_physical_attributes() diff --git a/code/modules/mob/living/carbon/human/species_types/snail.dm b/code/modules/mob/living/carbon/human/species_types/snail.dm index bfb2379f38c..a59d433731c 100644 --- a/code/modules/mob/living/carbon/human/species_types/snail.dm +++ b/code/modules/mob/living/carbon/human/species_types/snail.dm @@ -29,7 +29,7 @@ ) /datum/species/snail/prepare_human_for_preview(mob/living/carbon/human/human) - human.dna.features["mcolor"] = COLOR_BEIGE + human.dna.features[FEATURE_MUTANT_COLOR] = COLOR_BEIGE human.update_body(is_creating = TRUE) /datum/species/snail/get_physical_attributes() diff --git a/code/modules/mob/living/carbon/init_signals.dm b/code/modules/mob/living/carbon/init_signals.dm index e64410ab635..1f9f30093a5 100644 --- a/code/modules/mob/living/carbon/init_signals.dm +++ b/code/modules/mob/living/carbon/init_signals.dm @@ -31,14 +31,8 @@ /mob/living/carbon/proc/on_agender_trait_loss(datum/source) SIGNAL_HANDLER - //updates our gender to be whatever our DNA wants it to be - switch(deconstruct_block(get_uni_identity_block(dna.unique_identity, DNA_GENDER_BLOCK), 3) || pick(G_MALE, G_FEMALE)) - if(G_MALE) - gender = MALE - if(G_FEMALE) - gender = FEMALE - else - gender = PLURAL + var/datum/dna_block/identity/gender/to_update = GLOB.dna_identity_blocks[/datum/dna_block/identity/gender] + to_update.apply_to_mob(src, src.dna.unique_identity) /** * On gain of TRAIT_NOBREATH diff --git a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm index 42ab6224af1..1b1f8e59fb0 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm @@ -168,7 +168,7 @@ if(HAS_TRAIT(affected_human, TRAIT_USES_SKINTONES)) affected_human.skin_tone = "green" else if(HAS_TRAIT(affected_human, TRAIT_MUTANT_COLORS) && !HAS_TRAIT(affected_human, TRAIT_FIXED_MUTANT_COLORS)) //Code stolen from spraytan overdose - affected_human.dna.features["mcolor"] = "#a8e61d" + affected_human.dna.features[FEATURE_MUTANT_COLOR] = "#a8e61d" affected_human.update_body(is_creating = TRUE) /datum/reagent/consumable/ethanol/kahlua diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 34e1a605200..5316c47621a 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -596,7 +596,7 @@ exposed_human.skin_tone = "mixed3" //take current alien color and darken it slightly else if(HAS_TRAIT(exposed_human, TRAIT_MUTANT_COLORS) && !HAS_TRAIT(exposed_human, TRAIT_FIXED_MUTANT_COLORS)) - var/list/existing_color = rgb2num(exposed_human.dna.features["mcolor"]) + var/list/existing_color = rgb2num(exposed_human.dna.features[FEATURE_MUTANT_COLOR]) var/list/darkened_color = list() // Reduces each part of the color by 16 for(var/channel in existing_color) @@ -606,7 +606,7 @@ var/list/new_hsv = rgb2hsv(new_color) // Can't get too dark now if(new_hsv[3] >= 50) - exposed_human.dna.features["mcolor"] = new_color + exposed_human.dna.features[FEATURE_MUTANT_COLOR] = new_color exposed_human.update_body(is_creating = TRUE) if((methods & INGEST) && show_message) @@ -630,7 +630,7 @@ if(HAS_TRAIT(affected_human, TRAIT_USES_SKINTONES)) affected_human.skin_tone = "orange" else if(HAS_TRAIT(affected_human, TRAIT_MUTANT_COLORS) && !HAS_TRAIT(affected_human, TRAIT_FIXED_MUTANT_COLORS)) //Aliens with custom colors simply get turned orange - affected_human.dna.features["mcolor"] = "#ff8800" + affected_human.dna.features[FEATURE_MUTANT_COLOR] = "#ff8800" affected_human.update_body(is_creating = TRUE) if(SPT_PROB(3.5, seconds_per_tick)) if(affected_human.w_uniform) diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 50d9daae902..61c1b761541 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -606,8 +606,8 @@ /obj/item/slime_extract/rainbow/activate(mob/living/carbon/human/user, datum/species/jelly/luminescent/species, activation_type) switch(activation_type) if(SLIME_ACTIVATE_MINOR) - user.dna.features["mcolor"] = "#[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]" - user.dna.update_uf_block(DNA_MUTANT_COLOR_BLOCK) + user.dna.features[FEATURE_MUTANT_COLOR] = "#[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]" + user.dna.update_uf_block(FEATURE_MUTANT_COLOR) user.updateappearance(mutcolor_update=1) species.update_glow(user) to_chat(user, span_notice("You feel different...")) diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index b93895fa0ae..6fa25be8c73 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -1001,7 +1001,7 @@ if(owner_species.fixed_mut_color) species_color = owner_species.fixed_mut_color else - species_color = human_owner.dna.features["mcolor"] + species_color = human_owner.dna.features[FEATURE_MUTANT_COLOR] else skin_tone = "" species_color = "" diff --git a/code/modules/surgery/organs/external/_visual_organs.dm b/code/modules/surgery/organs/external/_visual_organs.dm index d5c34bc128e..6c92ba96646 100644 --- a/code/modules/surgery/organs/external/_visual_organs.dm +++ b/code/modules/surgery/organs/external/_visual_organs.dm @@ -10,7 +10,7 @@ Unlike normal organs, we're actually inside a persons limbs at all times /// The savefile_key of the preference this relates to. Used for the preferences UI. var/preference ///With what DNA block do we mutate in mutate_feature() ? For genetics - var/dna_block + var/datum/dna_block/dna_block ///Set to EXTERNAL_BEHIND, EXTERNAL_FRONT or EXTERNAL_ADJACENT if you want to draw one of those layers as the object sprite. FALSE to use your own ///This will not work if it doesn't have a limb to generate its icon with @@ -79,7 +79,8 @@ Unlike normal organs, we're actually inside a persons limbs at all times var/list/feature_list = bodypart_overlay.get_global_feature_list() - bodypart_overlay.set_appearance_from_name(feature_list[deconstruct_block(get_uni_feature_block(features, dna_block), feature_list.len)]) + var/datum/dna_block/feature/feature_block = GLOB.dna_feature_blocks[dna_block] + bodypart_overlay.set_appearance_from_name(feature_list[deconstruct_block(feature_block.get_block(features), feature_list.len)]) ///If you need to change an external_organ for simple one-offs, use this. Pass the accessory type : /datum/accessory/something /obj/item/organ/proc/simple_change_sprite(accessory_type) @@ -113,7 +114,7 @@ Unlike normal organs, we're actually inside a persons limbs at all times slot = ORGAN_SLOT_EXTERNAL_HORNS preference = "feature_lizard_horns" - //dna_block = DNA_HORNS_BLOCK // SKYRAT EDIT REMOVAL - Customization - We have our own system to handle DNA. + //dna_block = /datum/dna_block/feature/horn // SKYRAT EDIT REMOVAL - Customization - We have our own system to handle DNA. restyle_flags = EXTERNAL_RESTYLE_ENAMEL bodypart_overlay = /datum/bodypart_overlay/mutant/horns @@ -122,7 +123,7 @@ Unlike normal organs, we're actually inside a persons limbs at all times /datum/bodypart_overlay/mutant/horns layers = EXTERNAL_ADJACENT - feature_key = "horns" + feature_key = FEATURE_HORNS dyable = TRUE /datum/bodypart_overlay/mutant/horns/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner) @@ -146,7 +147,7 @@ Unlike normal organs, we're actually inside a persons limbs at all times slot = ORGAN_SLOT_EXTERNAL_FRILLS preference = "feature_lizard_frills" - //dna_block = DNA_FRILLS_BLOCK // SKYRAT EDIT REMOVAL - Customization - We have our own system to handle DNA. + //dna_block = /datum/dna_block/feature/frill // SKYRAT EDIT REMOVAL - Customization - We have our own system to handle DNA. restyle_flags = EXTERNAL_RESTYLE_FLESH bodypart_overlay = /datum/bodypart_overlay/mutant/frills @@ -155,7 +156,7 @@ Unlike normal organs, we're actually inside a persons limbs at all times /datum/bodypart_overlay/mutant/frills layers = EXTERNAL_ADJACENT - feature_key = "frills" + feature_key = FEATURE_FRILLS /datum/bodypart_overlay/mutant/frills/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner) var/mob/living/carbon/human/human = bodypart_owner.owner @@ -180,7 +181,7 @@ Unlike normal organs, we're actually inside a persons limbs at all times preference = "feature_lizard_snout" external_bodyshapes = BODYSHAPE_SNOUTED - //dna_block = DNA_SNOUT_BLOCK // SKYRAT EDIT REMOVAL - Customization - We have our own system to handle DNA. + //dna_block = /datum/dna_block/feature/snout // SKYRAT EDIT REMOVAL - Customization - We have our own system to handle DNA. restyle_flags = EXTERNAL_RESTYLE_FLESH bodypart_overlay = /datum/bodypart_overlay/mutant/snout @@ -189,7 +190,7 @@ Unlike normal organs, we're actually inside a persons limbs at all times /datum/bodypart_overlay/mutant/snout layers = EXTERNAL_ADJACENT - feature_key = "snout" + feature_key = FEATURE_SNOUT /datum/bodypart_overlay/mutant/snout/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner) var/mob/living/carbon/human/human = bodypart_owner.owner @@ -212,7 +213,7 @@ Unlike normal organs, we're actually inside a persons limbs at all times slot = ORGAN_SLOT_EXTERNAL_ANTENNAE preference = "feature_moth_antennae" - //dna_block = DNA_MOTH_ANTENNAE_BLOCK // SKYRAT EDIT REMOVAL - Customization - We have our own system to handle DNA. + //dna_block = /datum/dna_block/feature/moth_antenna // SKYRAT EDIT REMOVAL - Customization - We have our own system to handle DNA. restyle_flags = EXTERNAL_RESTYLE_FLESH bodypart_overlay = /datum/bodypart_overlay/mutant/antennae @@ -266,7 +267,7 @@ Unlike normal organs, we're actually inside a persons limbs at all times ///Moth antennae datum, with full burning functionality /datum/bodypart_overlay/mutant/antennae layers = EXTERNAL_FRONT | EXTERNAL_BEHIND - feature_key = "moth_antennae" + feature_key = FEATURE_MOTH_ANTENNAE dyable = TRUE ///Accessory datum of the burn sprite var/datum/sprite_accessory/burn_datum = /datum/sprite_accessory/moth_antennae/burnt_off @@ -308,7 +309,7 @@ Unlike normal organs, we're actually inside a persons limbs at all times preference = "feature_pod_hair" use_mob_sprite_as_obj_sprite = TRUE - dna_block = DNA_POD_HAIR_BLOCK + dna_block = /datum/dna_block/feature/pod_hair restyle_flags = EXTERNAL_RESTYLE_PLANT bodypart_overlay = /datum/bodypart_overlay/mutant/pod_hair @@ -318,7 +319,7 @@ Unlike normal organs, we're actually inside a persons limbs at all times ///Podperson bodypart overlay, with special coloring functionality to render the flowers in the inverse color /datum/bodypart_overlay/mutant/pod_hair layers = EXTERNAL_FRONT|EXTERNAL_ADJACENT - feature_key = "pod_hair" + feature_key = FEATURE_POD_HAIR dyable = TRUE ///This layer will be colored differently than the rest of the organ. So we can get differently colored flowers or something diff --git a/code/modules/surgery/organs/external/spines.dm b/code/modules/surgery/organs/external/spines.dm index 1dc7f51b421..1042de43384 100644 --- a/code/modules/surgery/organs/external/spines.dm +++ b/code/modules/surgery/organs/external/spines.dm @@ -9,7 +9,7 @@ preference = "feature_lizard_spines" - //dna_block = DNA_SPINES_BLOCK // SKYRAT EDIT REMOVAL - Customization - We have our own system to handle DNA. + //dna_block = /datum/dna_block/feature/spine // SKYRAT EDIT REMOVAL - Customization - We have our own system to handle DNA. restyle_flags = EXTERNAL_RESTYLE_FLESH bodypart_overlay = /datum/bodypart_overlay/mutant/spines @@ -31,7 +31,7 @@ ///Bodypart overlay for spines /datum/bodypart_overlay/mutant/spines layers = EXTERNAL_ADJACENT|EXTERNAL_BEHIND - feature_key = "spines" + feature_key = FEATURE_SPINES dyable = TRUE /datum/bodypart_overlay/mutant/spines/get_global_feature_list() diff --git a/code/modules/surgery/organs/external/tails.dm b/code/modules/surgery/organs/external/tails.dm index 29a8d8e9a8d..4a9426bff22 100644 --- a/code/modules/surgery/organs/external/tails.dm +++ b/code/modules/surgery/organs/external/tails.dm @@ -7,7 +7,7 @@ zone = BODY_ZONE_PRECISE_GROIN slot = ORGAN_SLOT_EXTERNAL_TAIL - //dna_block = DNA_TAIL_BLOCK // SKYRAT EDIT REMOVAL - Customization - We have our own system to handle DNA. + //dna_block = /datum/dna_block/feature/tail // SKYRAT EDIT REMOVAL - Customization - We have our own system to handle DNA. restyle_flags = EXTERNAL_RESTYLE_FLESH // defaults to cat, but the parent type shouldn't be created regardless @@ -66,11 +66,11 @@ tail_spines_overlay = new tail_spines_overlay.tail_spine_key = tail_spine_key // SKYRAT EDIT ADDITION START - if(!bodypart.owner.dna.mutant_bodyparts["spines"]) - bodypart.owner.dna.mutant_bodyparts["spines"] = list(MUTANT_INDEX_NAME = "None", MUTANT_INDEX_COLOR_LIST = list("#886600", "#886600", "#886600")) + if(!bodypart.owner.dna.mutant_bodyparts[FEATURE_SPINES]) + bodypart.owner.dna.mutant_bodyparts[FEATURE_SPINES] = list(MUTANT_INDEX_NAME = "None", MUTANT_INDEX_COLOR_LIST = list("#886600", "#886600", "#886600")) // SKYRAT EDIT ADDITION END - var/feature_name = bodypart.owner.dna.mutant_bodyparts["spines"][MUTANT_INDEX_NAME] // SKYRAT EDIT CHANGE - ORIGINAL: var/feature_name = bodypart.owner.dna.features["spines"] //tail spines don't live in DNA, but share feature names with regular spines - tail_spines_overlay.set_appearance_from_dna(bodypart.owner.dna, feature_name, feature_key = "spines") // SKYRAT EDIT CHANGE - ORIGINAL: tail_spines_overlay.set_appearance_from_name(feature_name) + var/feature_name = bodypart.owner.dna.mutant_bodyparts[FEATURE_SPINES][MUTANT_INDEX_NAME] // SKYRAT EDIT CHANGE - ORIGINAL: var/feature_name = bodypart.owner.dna.features[FEATURE_SPINES] //tail spines don't live in DNA, but share feature names with regular spines + tail_spines_overlay.set_appearance_from_dna(bodypart.owner.dna, feature_name, feature_key = FEATURE_SPINES) // SKYRAT EDIT CHANGE - ORIGINAL: tail_spines_overlay.set_appearance_from_name(feature_name) bodypart.add_bodypart_overlay(tail_spines_overlay) /// If we have a tail spines overlay, delete it @@ -181,7 +181,7 @@ ///Cat tail bodypart overlay /datum/bodypart_overlay/mutant/tail/cat - feature_key = "tail" // SKYRAT EDIT - Customization - ORIGINAL: feature_key = "tail_cat" + feature_key = "tail" // SKYRAT EDIT - Customization - ORIGINAL: feature_key = FEATURE_TAIL // color_source = ORGAN_COLOR_HAIR // SKYRAT EDIT REMOVAL /datum/bodypart_overlay/mutant/tail/cat/get_global_feature_list() @@ -197,7 +197,7 @@ ///Monkey tail bodypart overlay /datum/bodypart_overlay/mutant/tail/monkey color_source = NONE - feature_key = "tail" // SKYRAT EDIT - Customization - ORIGINAL: feature_key = "tail_monkey" + feature_key = "tail" // SKYRAT EDIT - Customization - ORIGINAL: feature_key = FEATURE_TAIL_MONKEY /datum/bodypart_overlay/mutant/tail/monkey/get_global_feature_list() return SSaccessories.tails_list_monkey @@ -240,7 +240,7 @@ ///Alien tail bodypart overlay /datum/bodypart_overlay/mutant/tail/xeno color_source = NONE - feature_key = "tail_xeno" + feature_key = FEATURE_TAIL_XENO imprint_on_next_insertion = FALSE /// We don't want to bother writing this in DNA, just use this appearance var/default_appearance = "Xeno" @@ -266,11 +266,11 @@ bodypart_overlay = /datum/bodypart_overlay/mutant/tail/lizard wag_flags = WAG_ABLE - //dna_block = DNA_LIZARD_TAIL_BLOCK // SKYRAT EDIT REMOVAL - Customization - We have our own system to handle DNA. + //dna_block = /datum/dna_block/feature/tail_lizard // SKYRAT EDIT REMOVAL - Customization - We have our own system to handle DNA. ///Lizard tail bodypart overlay datum /datum/bodypart_overlay/mutant/tail/lizard - feature_key = "tail" // SKYRAT EDIT - Customization - ORIGINAL: feature_key = "tail_lizard" + feature_key = "tail" // SKYRAT EDIT - Customization - ORIGINAL: feature_key = FEATURE_TAIL_LIZARD /datum/bodypart_overlay/mutant/tail/lizard/get_global_feature_list() return SSaccessories.sprite_accessories["tail"] // SKYRAT EDIT - Customization - ORIGINAL: return SSaccessories.tails_list_lizard @@ -282,7 +282,7 @@ ///Bodypart overlay for tail spines. Handled by the tail - has no actual organ associated. /datum/bodypart_overlay/mutant/tail_spines layers = EXTERNAL_ADJACENT|EXTERNAL_BEHIND - feature_key = "tailspines" + feature_key = FEATURE_TAILSPINES ///Spines wag when the tail does var/wagging = FALSE /// Key for tail spine states, depends on the shape of the tail. Defined in the tail sprite datum. diff --git a/code/modules/surgery/organs/external/wings/moth_wings.dm b/code/modules/surgery/organs/external/wings/moth_wings.dm index fa8c0240ae5..db0b63c0f86 100644 --- a/code/modules/surgery/organs/external/wings/moth_wings.dm +++ b/code/modules/surgery/organs/external/wings/moth_wings.dm @@ -7,7 +7,7 @@ preference = "feature_moth_wings" - //dna_block = DNA_MOTH_WINGS_BLOCK // SKYRAT EDIT REMOVAL + //dna_block = /datum/dna_block/feature/moth_wing // SKYRAT EDIT REMOVAL bodypart_overlay = /datum/bodypart_overlay/mutant/wings/moth restyle_flags = EXTERNAL_RESTYLE_FLESH @@ -101,7 +101,7 @@ ///Moth wing bodypart overlay, including burn functionality! /datum/bodypart_overlay/mutant/wings/moth - feature_key = "wings" // SKYRAT EDIT - Customization - ORIGINAL: feature_key = "moth_wings" + feature_key = FEATURE_WINGS // SKYRAT EDIT - Customization - ORIGINAL: feature_key = FEATURE_MOTH_WINGS layers = EXTERNAL_BEHIND | EXTERNAL_FRONT ///Accessory datum of the burn sprite var/datum/sprite_accessory/burn_datum = /datum/sprite_accessory/moth_wings/burnt_off diff --git a/code/modules/surgery/organs/external/wings/wings.dm b/code/modules/surgery/organs/external/wings/wings.dm index 3f243648526..0c42a9784ca 100644 --- a/code/modules/surgery/organs/external/wings/wings.dm +++ b/code/modules/surgery/organs/external/wings/wings.dm @@ -22,7 +22,7 @@ ///Bodypart overlay of default wings. Does not have any wing functionality /datum/bodypart_overlay/mutant/wings layers = ALL_EXTERNAL_OVERLAYS - feature_key = "wings" + feature_key = FEATURE_WINGS /datum/bodypart_overlay/mutant/wings/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner) var/mob/living/carbon/human/human = bodypart_owner.owner diff --git a/code/modules/surgery/organs/internal/ears/_ears.dm b/code/modules/surgery/organs/internal/ears/_ears.dm index 826851f5e17..14793289385 100644 --- a/code/modules/surgery/organs/internal/ears/_ears.dm +++ b/code/modules/surgery/organs/internal/ears/_ears.dm @@ -160,7 +160,7 @@ preference = "feature_human_ears" restyle_flags = EXTERNAL_RESTYLE_FLESH - //dna_block = DNA_EARS_BLOCK // SKYRAT EDIT REMOVAL - Customization - We have our own system to handle DNA. + //dna_block = /datum/dna_block/feature/ears // SKYRAT EDIT REMOVAL - Customization - We have our own system to handle DNA. bodypart_overlay = /datum/bodypart_overlay/mutant/cat_ears @@ -168,7 +168,7 @@ /datum/bodypart_overlay/mutant/cat_ears layers = EXTERNAL_FRONT | EXTERNAL_BEHIND color_source = ORGAN_COLOR_HAIR - feature_key = "ears" + feature_key = FEATURE_EARS dyable = TRUE /// Layer upon which we add the inner ears overlay diff --git a/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm b/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm index 603b9051526..d082bc02e48 100644 --- a/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm +++ b/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm @@ -103,7 +103,7 @@ var/mob/living/carbon/human/human = carbon if(human.dna?.species) //fixed_mut_color is also ethereal color (for some reason) - carbon.flash_lighting_fx(5, 7, human.dna.species.fixed_mut_color ? human.dna.species.fixed_mut_color : human.dna.features["mcolor"]) + carbon.flash_lighting_fx(5, 7, human.dna.species.fixed_mut_color ? human.dna.species.fixed_mut_color : human.dna.features[FEATURE_MUTANT_COLOR]) playsound(carbon, 'sound/effects/magic/lightningshock.ogg', 100, TRUE, extrarange = 5) carbon.cut_overlay(overcharge) diff --git a/code/modules/unit_tests/changeling.dm b/code/modules/unit_tests/changeling.dm index b9d06434bde..dfc97a4492b 100644 --- a/code/modules/unit_tests/changeling.dm +++ b/code/modules/unit_tests/changeling.dm @@ -26,7 +26,7 @@ TEST_ASSERT_EQUAL(victim.real_name, ling_name, "Victim real name did not change on being transformation stung.") TEST_ASSERT_EQUAL(victim.name, ling_name, "Victim name did not change on being transformation stung.") TEST_ASSERT_EQUAL(victim.dna.species.type, ling.dna.species.type, "Victim species did not change on being transformation stung.") - TEST_ASSERT_EQUAL(victim.dna.features["mcolor"], ling.dna.features["mcolor"], "Victim mcolor did not change on being transformation stung.") + TEST_ASSERT_EQUAL(victim.dna.features[FEATURE_MUTANT_COLOR], ling.dna.features[FEATURE_MUTANT_COLOR], "Victim mcolor did not change on being transformation stung.") // Check they actually look the same add_to_screenshot(ling, victim) @@ -37,7 +37,7 @@ TEST_ASSERT_EQUAL(victim.name, base_victim_name, "Victim name did not change back after transformation sting expired.") TEST_ASSERT_EQUAL(victim.real_name, base_victim_name, "Victim real name did not change back after transformation sting expired.") TEST_ASSERT_NOTEQUAL(victim.dna.species.type, ling.dna.species.type, "Victim species did not change back after transformation sting expired.") - TEST_ASSERT_NOTEQUAL(victim.dna.features["mcolor"], ling.dna.features["mcolor"], "Victim mcolor did not reset after transformation sting expired.") + TEST_ASSERT_NOTEQUAL(victim.dna.features[FEATURE_MUTANT_COLOR], ling.dna.features[FEATURE_MUTANT_COLOR], "Victim mcolor did not reset after transformation sting expired.") // Check they actually look different again add_to_screenshot(ling, victim, both_species = TRUE) @@ -74,17 +74,16 @@ // Because we use two consistent humans, we need to change some of the features to know they're actually updating to new values. // The more DNA features and random things we change, the more likely we are to catch something not updating correctly. // Yeah guess who/what this is, I dare you. - ling.dna.features["mcolor"] = "#886600" - ling.dna.mutant_bodyparts["tail"] = list(MUTANT_INDEX_NAME = "Smooth", MUTANT_INDEX_COLOR_LIST = list("#886600", "#886600", "#886600")) // SKYRAT EDIT CHANGE - ORIGINAL: ling.dna.features["tail_lizard"] = "Smooth" - ling.dna.mutant_bodyparts["snout"] = list(MUTANT_INDEX_NAME = "Sharp + Light", MUTANT_INDEX_COLOR_LIST = list("#886600", "#886600", "#886600")) // SKYRAT EDIT CHANGE - ORIGINAL: ling.dna.features["snout"] = "Sharp + Light" - ling.dna.mutant_bodyparts["horns"] = list(MUTANT_INDEX_NAME = "Curled", MUTANT_INDEX_COLOR_LIST = list("#292826", "#292826", "#8292826")) // SKYRAT EDIT CHANGE - ORIGINAL: ling.dna.features["horns"] = "Curved" - ling.dna.mutant_bodyparts["frills"] = list(MUTANT_INDEX_NAME = "Short", MUTANT_INDEX_COLOR_LIST = list("#886600", "#886600", "#886600")) // SKYRAT EDIT CHANGE - ORIGINAL: ling.dna.features["frills"] = "Sort" - ling.dna.mutant_bodyparts["spines"] = list(MUTANT_INDEX_NAME = "Long + Membrane", MUTANT_INDEX_COLOR_LIST = list("#886600", "#886600", "#886600")) // SKYRAT EDIT CHANGE - ORIGINAL: ling.dna.features["spines"] = "Long + Membrane" - ling.dna.body_markings["chest"] = list("Light Belly" = list("#886600", 0)) // SKYRAT EDIT CHANGE - ORIGINAL : ling.dna.features[lizard_markings] = list("Light Belly") - ling.dna.features["legs"] = DIGITIGRADE_LEGS + ling.dna.features[FEATURE_MUTANT_COLOR] = "#886600" + ling.dna.mutant_bodyparts["tail"] = list(MUTANT_INDEX_NAME = "Smooth", MUTANT_INDEX_COLOR_LIST = list("#886600", "#886600", "#886600")) // SKYRAT EDIT CHANGE - ORIGINAL: ling.dna.features[FEATURE_TAIL_LIZARD] = "Smooth" + ling.dna.mutant_bodyparts[FEATURE_SNOUT] = list(MUTANT_INDEX_NAME = "Sharp + Light", MUTANT_INDEX_COLOR_LIST = list("#886600", "#886600", "#886600")) // SKYRAT EDIT CHANGE - ORIGINAL: ling.dna.features[FEATURE_SNOUT] = "Sharp + Light" + ling.dna.mutant_bodyparts[FEATURE_HORNS] = list(MUTANT_INDEX_NAME = "Curled", MUTANT_INDEX_COLOR_LIST = list("#292826", "#292826", "#8292826")) // SKYRAT EDIT CHANGE - ORIGINAL: ling.dna.features[FEATURE_HORNS] = "Curled" + ling.dna.mutant_bodyparts[FEATURE_FRILLS] = list(MUTANT_INDEX_NAME = "Short", MUTANT_INDEX_COLOR_LIST = list("#886600", "#886600", "#886600")) // SKYRAT EDIT CHANGE - ORIGINAL: ling.dna.features[FEATURE_FRILLS] = "Short" + ling.dna.mutant_bodyparts[FEATURE_SPINES] = list(MUTANT_INDEX_NAME = "Long + Membrane", MUTANT_INDEX_COLOR_LIST = list("#886600", "#886600", "#886600")) // SKYRAT EDIT CHANGE - ORIGINAL: ling.dna.features[FEATURE_SPINES] = "Long + Membrane" + ling.dna.body_markings["chest"] = list("Light Belly" = list("#886600", 0)) // SKYRAT EDIT CHANGE - ORIGINAL : ling.dna.features[FEATURE_LIZARD_MARKINGS] = "Light Belly" + ling.dna.features[FEATURE_LEGS] = DIGITIGRADE_LEGS ling.set_eye_color(COLOR_WHITE) - ling.dna.update_ui_block(DNA_EYE_COLOR_LEFT_BLOCK) - ling.dna.update_ui_block(DNA_EYE_COLOR_RIGHT_BLOCK) + ling.dna.update_ui_block(/datum/dna_block/identity/eye_colors) ling.set_species(/datum/species/lizard) ling.real_name = ling_name diff --git a/code/modules/unit_tests/screenshot_humanoids.dm b/code/modules/unit_tests/screenshot_humanoids.dm index 9aa0c7c31d6..d7c1de26128 100644 --- a/code/modules/unit_tests/screenshot_humanoids.dm +++ b/code/modules/unit_tests/screenshot_humanoids.dm @@ -6,12 +6,12 @@ // Test lizards as their own thing so we can get more coverage on their features var/mob/living/carbon/human/lizard = allocate(/mob/living/carbon/human/dummy/consistent) - lizard.dna.features["mcolor"] = "#099" - lizard.dna.mutant_bodyparts["tail"] = list(MUTANT_INDEX_NAME = "Light Tiger", MUTANT_INDEX_COLOR_LIST = list("#009999", "#009999", "#009999")) // SKYRAT EDIT - Customization - ORIGINAL: lizard.dna.features["tail_lizard"] = "Light Tiger" - lizard.dna.mutant_bodyparts["snout"] = list(MUTANT_INDEX_NAME = "Sharp + Light", MUTANT_INDEX_COLOR_LIST = list("#009999", "#009999", "#009999")) // SKYRAT EDIT - Customization - ORIGINAL: lizard.dna.features["snout"] = "Sharp + Light" - lizard.dna.mutant_bodyparts["horns"] = list(MUTANT_INDEX_NAME = "Simple", MUTANT_INDEX_COLOR_LIST = list("#009999", "#009999", "#009999")) // SKYRAT EDIT - Customization - ORIGINAL: lizard.dna.features["horns"] = "Simple" - lizard.dna.mutant_bodyparts["frills"] = list(MUTANT_INDEX_NAME = "Aquatic", MUTANT_INDEX_COLOR_LIST = list("#009999", "#009999", "#009999")) // SKYRAT EDIT - Customization - ORIGINAL: lizard.dna.features["frills"] = "Aquatic" - lizard.dna.features["legs"] = "Normal Legs" + lizard.dna.features[FEATURE_MUTANT_COLOR] = "#099" + lizard.dna.mutant_bodyparts["tail"] = list(MUTANT_INDEX_NAME = "Light Tiger", MUTANT_INDEX_COLOR_LIST = list("#009999", "#009999", "#009999")) // SKYRAT EDIT - Customization - ORIGINAL: lizard.dna.features[FEATURE_TAIL_LIZARD] = "Light Tiger" + lizard.dna.mutant_bodyparts[FEATURE_SNOUT] = list(MUTANT_INDEX_NAME = "Sharp + Light", MUTANT_INDEX_COLOR_LIST = list("#009999", "#009999", "#009999")) // SKYRAT EDIT - Customization - ORIGINAL: lizard.dna.features[FEATURE_SNOUT] = "Sharp + Light" + lizard.dna.mutant_bodyparts[FEATURE_HORNS] = list(MUTANT_INDEX_NAME = "Simple", MUTANT_INDEX_COLOR_LIST = list("#009999", "#009999", "#009999")) // SKYRAT EDIT - Customization - ORIGINAL: lizard.dna.features[FEATURE_HORNS] = "Simple" + lizard.dna.mutant_bodyparts[FEATURE_FRILLS] = list(MUTANT_INDEX_NAME = "Aquatic", MUTANT_INDEX_COLOR_LIST = list("#009999", "#009999", "#009999")) // SKYRAT EDIT - Customization - ORIGINAL: lizard.dna.features[FEATURE_FRILLS] = "Aquatic" + lizard.dna.features[FEATURE_LEGS] = "Normal Legs" lizard.set_species(/datum/species/lizard) lizard.equipOutfit(/datum/outfit/job/engineer) test_screenshot("[/datum/species/lizard]", get_flat_icon_for_all_directions(lizard)) @@ -24,10 +24,10 @@ // let me have this var/mob/living/carbon/human/moth = allocate(/mob/living/carbon/human/dummy/consistent) - moth.dna.features["mcolor"] = "#E5CD99" // SKYRAT EDIT ADDITION - Customization - moth.dna.mutant_bodyparts["moth_antennae"] = list(MUTANT_INDEX_NAME = "Firewatch", MUTANT_INDEX_COLOR_LIST = list("#FFFFFF", "#FFFFFF", "#FFFFFF")) // SKYRAT EDIT - Customization - ORIGINAL: moth.dna.features["moth_antennae"] = "Firewatch" - moth.dna.mutant_bodyparts["moth_markings"] = list(MUTANT_INDEX_NAME = "None", MUTANT_INDEX_COLOR_LIST = list("#FFFFFF", "#FFFFFF", "#FFFFFF")) // SKYRAT EDIT - Customization - ORIGINAL: moth.dna.features["moth_markings"] = "None" - moth.dna.mutant_bodyparts["wings"] = list(MUTANT_INDEX_NAME = "Moth (Firewatch)", MUTANT_INDEX_COLOR_LIST = list("#FFFFFF", "#FFFFFF", "#FFFFFF")) // SKYRAT EDIT - Customization - ORIGINAL: moth.dna.features["moth_wings"] = "Firewatch" + moth.dna.features[FEATURE_MUTANT_COLOR] = "#E5CD99" // SKYRAT EDIT ADDITION - Customization + moth.dna.mutant_bodyparts[FEATURE_MOTH_ANTENNAE] = list(MUTANT_INDEX_NAME = "Firewatch", MUTANT_INDEX_COLOR_LIST = list("#FFFFFF", "#FFFFFF", "#FFFFFF")) // SKYRAT EDIT - Customization - ORIGINAL: moth.dna.features[FEATURE_MOTH_ANTENNAE] = "Firewatch" + moth.dna.mutant_bodyparts[FEATURE_MOTH_MARKINGS] = list(MUTANT_INDEX_NAME = "None", MUTANT_INDEX_COLOR_LIST = list("#FFFFFF", "#FFFFFF", "#FFFFFF")) // SKYRAT EDIT - Customization - ORIGINAL: moth.dna.features[FEATURE_MOTH_MARKINGS] = "None" + moth.dna.mutant_bodyparts[FEATURE_WINGS] = list(MUTANT_INDEX_NAME = "Moth (Firewatch)", MUTANT_INDEX_COLOR_LIST = list("#FFFFFF", "#FFFFFF", "#FFFFFF")) // SKYRAT EDIT - Customization - ORIGINAL: moth.dna.features[FEATURE_MOTH_WINGS] = "Firewatch" moth.set_species(/datum/species/moth) moth.equipOutfit(/datum/outfit/job/cmo, visuals_only = TRUE) test_screenshot("[/datum/species/moth]", get_flat_icon_for_all_directions(moth)) @@ -36,7 +36,7 @@ // More in depth test for slimes since they have a lot going on for (var/datum/species/slime_type as anything in typesof(/datum/species/jelly)) var/mob/living/carbon/human/slime = allocate(/mob/living/carbon/human/dummy/consistent) - slime.dna.features["mcolor"] = COLOR_PINK + slime.dna.features[FEATURE_MUTANT_COLOR] = COLOR_PINK slime.hairstyle = "Bob Hair 2" slime.hair_color = COLOR_RED // Should be forced to pink slime.set_species(slime_type) diff --git a/code/modules/unit_tests/species_change_clothing.dm b/code/modules/unit_tests/species_change_clothing.dm index fc9867e4033..fcd19994fda 100644 --- a/code/modules/unit_tests/species_change_clothing.dm +++ b/code/modules/unit_tests/species_change_clothing.dm @@ -7,7 +7,7 @@ var/mob/living/carbon/human/morphing_human = allocate(/mob/living/carbon/human/dummy/consistent) morphing_human.equipOutfit(/datum/outfit/job/assistant/consistent) - morphing_human.dna.features["legs"] = DIGITIGRADE_LEGS //you WILL have digitigrade legs + morphing_human.dna.features[FEATURE_LEGS] = DIGITIGRADE_LEGS //you WILL have digitigrade legs /* SKYRAT EDIT REMOVAL START - This part of the test is useless as it's behavior that we actually WANT from those shoes, here. var/obj/item/human_shoes = morphing_human.get_item_by_slot(ITEM_SLOT_FEET) diff --git a/tgstation.dme b/tgstation.dme index 373feebcb95..e0233a4eb80 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -954,7 +954,6 @@ #include "code\datums\dash_weapon.dm" #include "code\datums\datum.dm" #include "code\datums\datumvars.dm" -#include "code\datums\dna.dm" #include "code\datums\dog_fashion.dm" #include "code\datums\drift_handler.dm" #include "code\datums\ductnet.dm" @@ -1594,6 +1593,10 @@ #include "code\datums\diseases\floor_diseases\carpellosis.dm" #include "code\datums\diseases\floor_diseases\gastritium.dm" #include "code\datums\diseases\floor_diseases\nebula_nausea.dm" +#include "code\datums\dna\dna.dm" +#include "code\datums\dna\dna_block.dm" +#include "code\datums\dna\blocks\dna_features_block.dm" +#include "code\datums\dna\blocks\dna_identity_block.dm" #include "code\datums\elements\_element.dm" #include "code\datums\elements\above_mob_drop.dm" #include "code\datums\elements\ai_control_examine.dm"