mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-13 11:12:14 +00:00
Datumizes DNA blocks, makes DNA cleaner in general (#92061)
## About The Pull Request 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 ## Why It's Good For The Game I've been told the maintainers will love me for doing this ## Changelog 🆑 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. /🆑
This commit is contained in:
@@ -44,55 +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
|
||||
|
||||
/// 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
|
||||
|
||||
// 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 16
|
||||
|
||||
#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.
|
||||
|
||||
@@ -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) (GLOB.features_block_lengths["[blocknum]"] || DNA_BLOCK_SIZE)
|
||||
|
||||
@@ -197,3 +197,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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
151
code/datums/dna/blocks/dna_features_block.dm
Normal file
151
code/datums/dna/blocks/dna_features_block.dm
Normal file
@@ -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))]
|
||||
129
code/datums/dna/blocks/dna_identity_block.dm
Normal file
129
code/datums/dna/blocks/dna_identity_block.dm
Normal file
@@ -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)
|
||||
@@ -1,31 +1,3 @@
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@@ -37,9 +9,10 @@ GLOBAL_LIST_INIT(standard_mutation_sources, list(MUTATION_SOURCE_ACTIVATED, MUTA
|
||||
/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())
|
||||
@@ -47,9 +20,10 @@ 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
|
||||
|
||||
/////////////////////////// DNA DATUM
|
||||
/datum/dna
|
||||
@@ -63,7 +37,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
|
||||
@@ -211,77 +185,18 @@ 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)
|
||||
|
||||
/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)
|
||||
|
||||
/**
|
||||
* Picks what mutations this DNA has innate and generates DNA blocks for them
|
||||
@@ -341,96 +256,27 @@ 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))
|
||||
|
||||
/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))
|
||||
|
||||
/**
|
||||
* Checks if two DNAs are practically the same by comparing their most defining features
|
||||
@@ -480,6 +326,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()
|
||||
@@ -502,7 +350,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block())
|
||||
for(var/feature in new_features)
|
||||
features[feature] = new_features[feature]
|
||||
|
||||
features["mcolor"] = "#[random_color()]"
|
||||
features[FEATURE_MUTANT_COLOR] = "#[random_color()]"
|
||||
|
||||
update_dna_identity()
|
||||
|
||||
@@ -636,88 +484,25 @@ 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
|
||||
|
||||
/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)
|
||||
@@ -839,15 +624,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()
|
||||
@@ -859,7 +646,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))
|
||||
@@ -870,13 +657,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)
|
||||
|
||||
@@ -897,12 +686,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)
|
||||
69
code/datums/dna/dna_block.dm
Normal file
69
code/datums/dna/dna_block.dm
Normal file
@@ -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]
|
||||
@@ -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)
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
|
||||
@@ -6,6 +6,6 @@
|
||||
visual = TRUE
|
||||
damage_multiplier = 2
|
||||
|
||||
dna_block = DNA_EARS_BLOCK
|
||||
dna_block = /datum/dna_block/feature/ears
|
||||
bodypart_overlay = /datum/bodypart_overlay/mutant/cat_ears
|
||||
sprite_accessory_override = /datum/sprite_accessory/ears/fox
|
||||
|
||||
@@ -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 = input(race_changer, "Choose your skin color:", "Race change", race_changer.dna.features["mcolor"]) as color|null
|
||||
var/new_mutantcolor = input(race_changer, "Choose your skin color:", "Race change", race_changer.dna.features[FEATURE_MUTANT_COLOR]) as color|null
|
||||
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 = input(user, "Choose your facial hair color", "Hair Color", user.facial_hair_color) as color|null
|
||||
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)
|
||||
. = ..()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -133,12 +133,12 @@
|
||||
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["moth_antennae"] = "Plain"
|
||||
brother2.dna.features["moth_markings"] = "None"
|
||||
brother2.dna.features["moth_wings"] = "Plain"
|
||||
brother2.dna.features[FEATURE_MOTH_ANTENNAE] = "Plain"
|
||||
brother2.dna.features[FEATURE_MOTH_MARKINGS] = "None"
|
||||
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)
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -9,7 +9,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
|
||||
@@ -26,7 +26,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
|
||||
|
||||
@@ -55,7 +55,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"
|
||||
@@ -72,7 +72,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"
|
||||
@@ -89,7 +89,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"
|
||||
@@ -100,7 +100,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)
|
||||
@@ -145,7 +145,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"
|
||||
@@ -157,7 +157,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"
|
||||
@@ -169,7 +169,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
|
||||
|
||||
@@ -9,7 +9,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()
|
||||
return /datum/sprite_accessory/tails/monkey/default::name
|
||||
|
||||
@@ -27,7 +27,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"
|
||||
@@ -77,7 +77,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"
|
||||
@@ -95,4 +95,4 @@
|
||||
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
|
||||
|
||||
@@ -8,4 +8,4 @@
|
||||
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
|
||||
|
||||
@@ -16,7 +16,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))
|
||||
|
||||
@@ -28,4 +28,4 @@
|
||||
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
|
||||
target.dna.features[FEATURE_POD_HAIR] = value
|
||||
|
||||
@@ -199,10 +199,10 @@
|
||||
|
||||
podman.gender = blood_gender
|
||||
podman.faction |= factions
|
||||
if(!features["mcolor"])
|
||||
features["mcolor"] = "#59CE00"
|
||||
if(!features["pod_hair"])
|
||||
features["pod_hair"] = pick(SSaccessories.pod_hair_list)
|
||||
if(!features[FEATURE_MUTANT_COLOR])
|
||||
features[FEATURE_MUTANT_COLOR] = "#59CE00"
|
||||
if(!features[FEATURE_POD_HAIR])
|
||||
features[FEATURE_POD_HAIR] = pick(SSaccessories.pod_hair_list)
|
||||
|
||||
for(var/V in quirks)
|
||||
new V(podman)
|
||||
|
||||
@@ -171,17 +171,17 @@
|
||||
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."))
|
||||
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,
|
||||
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.set_eye_color("#FEE5A3")
|
||||
consumer.set_species(/datum/species/lizard)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1996,7 +1996,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
|
||||
//Note for future: Potentionally add a new C.dna.species() to build a template species for more accurate limb replacement
|
||||
|
||||
var/list/final_bodypart_overrides = new_species.bodypart_overrides.Copy()
|
||||
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
|
||||
|
||||
@@ -2048,7 +2048,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
|
||||
|
||||
@@ -2065,7 +2065,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)
|
||||
|
||||
@@ -105,23 +105,23 @@ 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["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_MUTANT_COLOR] = COLOR_VIBRANT_LIME
|
||||
target.dna.features[FEATURE_ETHEREAL_COLOR] = COLOR_WHITE
|
||||
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)
|
||||
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
|
||||
// In practice this doesn't matter, but this is for the sake of 100%(ish) consistency
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -28,19 +28,19 @@
|
||||
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"
|
||||
if(target_human.dna.features["ears"] == "None")
|
||||
target_human.dna.features[FEATURE_TAIL] = "Cat"
|
||||
if(target_human.dna.features[FEATURE_EARS] == "None")
|
||||
target_human.dna.features[FEATURE_EARS] = "Cat"
|
||||
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)
|
||||
return ..()
|
||||
|
||||
/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)
|
||||
|
||||
@@ -107,7 +107,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)
|
||||
@@ -304,8 +304,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)
|
||||
@@ -371,7 +371,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)
|
||||
@@ -541,7 +541,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"
|
||||
|
||||
@@ -51,7 +51,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
|
||||
|
||||
/datum/species/lizard/get_scream_sound(mob/living/carbon/human/lizard)
|
||||
@@ -225,14 +225,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 ..()
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
/datum/species/moth/randomize_features()
|
||||
var/list/features = ..()
|
||||
features["moth_markings"] = pick(SSaccessories.moth_markings_list)
|
||||
features[FEATURE_MOTH_MARKINGS] = pick(SSaccessories.moth_markings_list)
|
||||
return features
|
||||
|
||||
/datum/species/moth/get_scream_sound(mob/living/carbon/human/moth)
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
|
||||
preference = "feature_mushperson_cap"
|
||||
|
||||
dna_block = DNA_MUSHROOM_CAPS_BLOCK
|
||||
dna_block = /datum/dna_block/feature/mush_cap
|
||||
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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -28,7 +28,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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -589,7 +589,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)
|
||||
@@ -599,7 +599,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)
|
||||
@@ -623,7 +623,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)
|
||||
|
||||
@@ -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..."))
|
||||
|
||||
@@ -982,7 +982,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 = ""
|
||||
|
||||
@@ -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
|
||||
@@ -75,7 +75,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)
|
||||
@@ -109,7 +110,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
|
||||
dna_block = /datum/dna_block/feature/horn
|
||||
restyle_flags = EXTERNAL_RESTYLE_ENAMEL
|
||||
|
||||
bodypart_overlay = /datum/bodypart_overlay/mutant/horns
|
||||
@@ -118,7 +119,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)
|
||||
@@ -142,7 +143,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
|
||||
dna_block = /datum/dna_block/feature/frill
|
||||
restyle_flags = EXTERNAL_RESTYLE_FLESH
|
||||
|
||||
bodypart_overlay = /datum/bodypart_overlay/mutant/frills
|
||||
@@ -151,7 +152,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
|
||||
@@ -176,7 +177,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
|
||||
dna_block = /datum/dna_block/feature/snout
|
||||
restyle_flags = EXTERNAL_RESTYLE_FLESH
|
||||
|
||||
bodypart_overlay = /datum/bodypart_overlay/mutant/snout
|
||||
@@ -185,7 +186,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
|
||||
@@ -208,7 +209,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
|
||||
dna_block = /datum/dna_block/feature/moth_antenna
|
||||
restyle_flags = EXTERNAL_RESTYLE_FLESH
|
||||
|
||||
bodypart_overlay = /datum/bodypart_overlay/mutant/antennae
|
||||
@@ -262,7 +263,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
|
||||
@@ -299,7 +300,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
|
||||
@@ -309,7 +310,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
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
preference = "feature_lizard_spines"
|
||||
|
||||
dna_block = DNA_SPINES_BLOCK
|
||||
dna_block = /datum/dna_block/feature/spine
|
||||
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()
|
||||
|
||||
16
code/modules/surgery/organs/external/tails.dm
vendored
16
code/modules/surgery/organs/external/tails.dm
vendored
@@ -7,7 +7,7 @@
|
||||
zone = BODY_ZONE_PRECISE_GROIN
|
||||
slot = ORGAN_SLOT_EXTERNAL_TAIL
|
||||
|
||||
dna_block = DNA_TAIL_BLOCK
|
||||
dna_block = /datum/dna_block/feature/tail
|
||||
restyle_flags = EXTERNAL_RESTYLE_FLESH
|
||||
|
||||
// defaults to cat, but the parent type shouldn't be created regardless
|
||||
@@ -65,7 +65,7 @@
|
||||
|
||||
tail_spines_overlay = new
|
||||
tail_spines_overlay.tail_spine_key = tail_spine_key
|
||||
var/feature_name = bodypart.owner.dna.features["spines"] //tail spines don't live in DNA, but share feature names with regular spines
|
||||
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_name(feature_name)
|
||||
bodypart.add_bodypart_overlay(tail_spines_overlay)
|
||||
|
||||
@@ -169,7 +169,7 @@
|
||||
|
||||
///Cat tail bodypart overlay
|
||||
/datum/bodypart_overlay/mutant/tail/cat
|
||||
feature_key = "tail_cat"
|
||||
feature_key = FEATURE_TAIL
|
||||
color_source = ORGAN_COLOR_HAIR
|
||||
|
||||
/datum/bodypart_overlay/mutant/tail/cat/get_global_feature_list()
|
||||
@@ -185,7 +185,7 @@
|
||||
///Monkey tail bodypart overlay
|
||||
/datum/bodypart_overlay/mutant/tail/monkey
|
||||
color_source = NONE
|
||||
feature_key = "tail_monkey"
|
||||
feature_key = FEATURE_TAIL_MONKEY
|
||||
|
||||
/datum/bodypart_overlay/mutant/tail/monkey/get_global_feature_list()
|
||||
return SSaccessories.tails_list_monkey
|
||||
@@ -228,7 +228,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"
|
||||
@@ -254,11 +254,11 @@
|
||||
bodypart_overlay = /datum/bodypart_overlay/mutant/tail/lizard
|
||||
|
||||
wag_flags = WAG_ABLE
|
||||
dna_block = DNA_LIZARD_TAIL_BLOCK
|
||||
dna_block = /datum/dna_block/feature/tail_lizard
|
||||
|
||||
///Lizard tail bodypart overlay datum
|
||||
/datum/bodypart_overlay/mutant/tail/lizard
|
||||
feature_key = "tail_lizard"
|
||||
feature_key = FEATURE_TAIL_LIZARD
|
||||
|
||||
/datum/bodypart_overlay/mutant/tail/lizard/get_global_feature_list()
|
||||
return SSaccessories.tails_list_lizard
|
||||
@@ -270,7 +270,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.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
preference = "feature_moth_wings"
|
||||
|
||||
dna_block = DNA_MOTH_WINGS_BLOCK
|
||||
dna_block = /datum/dna_block/feature/moth_wing
|
||||
|
||||
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 = "moth_wings"
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -160,7 +160,7 @@
|
||||
preference = "feature_human_ears"
|
||||
restyle_flags = EXTERNAL_RESTYLE_FLESH
|
||||
|
||||
dna_block = DNA_EARS_BLOCK
|
||||
dna_block = /datum/dna_block/feature/ears
|
||||
|
||||
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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.features["tail_lizard"] = "Smooth"
|
||||
ling.dna.features["snout"] = "Sharp + Light"
|
||||
ling.dna.features["horns"] = "Curled"
|
||||
ling.dna.features["frills"] = "Short"
|
||||
ling.dna.features["spines"] = "Long + Membrane"
|
||||
ling.dna.features["lizard_markings"] = "Light Belly"
|
||||
ling.dna.features["legs"] = DIGITIGRADE_LEGS
|
||||
ling.dna.features[FEATURE_MUTANT_COLOR] = "#886600"
|
||||
ling.dna.features[FEATURE_TAIL_LIZARD] = "Smooth"
|
||||
ling.dna.features[FEATURE_SNOUT] = "Sharp + Light"
|
||||
ling.dna.features[FEATURE_HORNS] = "Curled"
|
||||
ling.dna.features[FEATURE_FRILLS] = "Short"
|
||||
ling.dna.features[FEATURE_SPINES] = "Long + Membrane"
|
||||
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
|
||||
|
||||
@@ -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.features["tail_lizard"] = "Light Tiger"
|
||||
lizard.dna.features["snout"] = "Sharp + Light"
|
||||
lizard.dna.features["horns"] = "Simple"
|
||||
lizard.dna.features["frills"] = "Aquatic"
|
||||
lizard.dna.features["legs"] = "Normal Legs"
|
||||
lizard.dna.features[FEATURE_MUTANT_COLOR] = "#099"
|
||||
lizard.dna.features[FEATURE_TAIL_LIZARD] = "Light Tiger"
|
||||
lizard.dna.features[FEATURE_SNOUT] = "Sharp + Light"
|
||||
lizard.dna.features[FEATURE_HORNS] = "Simple"
|
||||
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,9 +24,9 @@
|
||||
|
||||
// let me have this
|
||||
var/mob/living/carbon/human/moth = allocate(/mob/living/carbon/human/dummy/consistent)
|
||||
moth.dna.features["moth_antennae"] = "Firewatch"
|
||||
moth.dna.features["moth_markings"] = "None"
|
||||
moth.dna.features["moth_wings"] = "Firewatch"
|
||||
moth.dna.features[FEATURE_MOTH_ANTENNAE] = "Firewatch"
|
||||
moth.dna.features[FEATURE_MOTH_MARKINGS] = "None"
|
||||
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))
|
||||
@@ -35,7 +35,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)
|
||||
|
||||
@@ -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
|
||||
|
||||
var/obj/item/human_shoes = morphing_human.get_item_by_slot(ITEM_SLOT_FEET)
|
||||
human_shoes.supports_variations_flags = NONE //do not fit lizards at all costs.
|
||||
|
||||
@@ -812,7 +812,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"
|
||||
@@ -1452,6 +1451,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\ai_control_examine.dm"
|
||||
#include "code\datums\elements\ai_flee_while_injured.dm"
|
||||
|
||||
Reference in New Issue
Block a user