Fixed countless DNA related bugs, also including Vox and Grey genetic inconsistencies (#30803)

* Fixed countless DNA related bugs, also including Vox and Grey genetics business

* am I retarded?

* edge case

* derp
This commit is contained in:
DeityLink
2021-09-22 03:20:51 +02:00
committed by GitHub
parent 97dc5c682e
commit a1968c64c6
9 changed files with 101 additions and 131 deletions

View File

@@ -113,10 +113,6 @@ var/global/list/facial_hair_styles_female_list = list()
var/struc_enzymes="" // Encoded SE
var/unique_enzymes="" // MD5 of player name
// Internal dirtiness checks
var/dirtyUI=0
var/dirtySE=0
// Okay to read, but you're an idiot if you do.
// BLOCK = VALUE
var/list/SE[DNA_SE_LENGTH]
@@ -200,7 +196,13 @@ var/global/list/facial_hair_styles_female_list = list()
SetUIValueRange(DNA_UI_EYES_G, character.my_appearance.g_eyes, 255, 1)
SetUIValueRange(DNA_UI_EYES_B, character.my_appearance.b_eyes, 255, 1)
SetUIValueRange(DNA_UI_SKIN_TONE, 35-character.my_appearance.s_tone, 220, 1) // Value can be negative.
if (character.species)
if (character.species.name == "Human")
SetUIValueRange(DNA_UI_SKIN_TONE, 35-character.my_appearance.s_tone, 220, 1)
else
SetUIValueRange(DNA_UI_SKIN_TONE, character.my_appearance.s_tone, character.species.max_skin_tone, 1)
else
SetUIValueRange(DNA_UI_SKIN_TONE, 35-character.my_appearance.s_tone, 220, 1)
SetUIState(DNA_UI_GENDER, character.gender!=MALE, 1)
@@ -216,7 +218,6 @@ var/global/list/facial_hair_styles_female_list = list()
ASSERT(value>=0)
ASSERT(value<=4095)
UI[block]=value
dirtyUI=1
if(!defer)
UpdateUI()
@@ -232,7 +233,7 @@ var/global/list/facial_hair_styles_female_list = list()
if (block<=0)
return
ASSERT(maxvalue<=4095)
var/mapped_value = round(map_range(value, 0, maxvalue, 0, 0xFFF))
var/mapped_value = round(map_range(value, 0, max(maxvalue,1), 0, 0xFFF))
SetUIValue(block, mapped_value, defer)
// Getter version of above.
@@ -311,7 +312,6 @@ var/global/list/facial_hair_styles_female_list = list()
ASSERT(value>=0)
ASSERT(value<=4095)
SE[block]=value
dirtySE=1
if(!defer)
UpdateSE()
//testing("SetSEBlock([block],[value],[defer]): [value] -> [GetSEValue(block)]")
@@ -389,7 +389,6 @@ var/global/list/facial_hair_styles_female_list = list()
newBlock+=newSubBlock
else
newBlock+=copytext(oldBlock,i,i+1)
//testing("SetSESubBlock([block],[subBlock],[newSubBlock],[defer]): [oldBlock] -> [newBlock]")
SetSEBlock(block,newBlock,defer)
@@ -403,24 +402,17 @@ var/global/list/facial_hair_styles_female_list = list()
src.uni_identity=""
for(var/block in UI)
uni_identity += EncodeDNABlock(block)
//testing("New UI: [uni_identity]")
dirtyUI=0
/datum/dna/proc/UpdateSE()
//var/oldse=struc_enzymes
struc_enzymes=""
for(var/block in SE)
struc_enzymes += EncodeDNABlock(block)
//testing("Old SE: [oldse]")
//testing("New SE: [struc_enzymes]")
dirtySE=0
// BACK-COMPAT!
// Just checks our character has all the crap it needs.
/datum/dna/proc/check_integrity(var/mob/living/carbon/human/character)
if(character)
if(UI.len != DNA_UI_LENGTH)
ResetUIFrom(character)
ResetUIFrom(character) // Takes care of updating our DNA so it matches our appearance
if(length(struc_enzymes)!= 3*DNA_SE_LENGTH)
ResetSE()
@@ -444,3 +436,4 @@ var/global/list/facial_hair_styles_female_list = list()
reg_dna[unique_enzymes] = character.real_name
if(character.species)
species = character.species.name
character.fixblood()

View File

@@ -149,7 +149,14 @@
my_appearance.g_eyes = dna.GetUIValueRange(DNA_UI_EYES_G, 255)
my_appearance.b_eyes = dna.GetUIValueRange(DNA_UI_EYES_B, 255)
my_appearance.s_tone = 35 - dna.GetUIValueRange(DNA_UI_SKIN_TONE, 220) // Value can be negative.
if (species)
if (species.name == "Human")
my_appearance.s_tone = 35 - dna.GetUIValueRange(DNA_UI_SKIN_TONE, species.max_skin_tone)
else
my_appearance.s_tone = dna.GetUIValueRange(DNA_UI_SKIN_TONE, species.max_skin_tone)
else
my_appearance.s_tone = 35 - dna.GetUIValueRange(DNA_UI_SKIN_TONE, species.max_skin_tone)
setGender(MALE)
if (dna.GetUIState(DNA_UI_GENDER))
setGender(FEMALE)
@@ -158,16 +165,15 @@
//Hair
var/list/species_hair = valid_sprite_accessories(hair_styles_list, null, species.name)
var/hair = clamp(dna.GetUIValueRange(DNA_UI_HAIR_STYLE, species_hair.len) + 1, 1, species_hair.len)
var/hair = clamp(dna.GetUIValueRange(DNA_UI_HAIR_STYLE, species_hair.len), 1, species_hair.len)
my_appearance.h_style = species_hair[hair]
//Facial Hair
var/list/species_facial_hair = valid_sprite_accessories(facial_hair_styles_list, null, species.name)
var/beard = clamp(dna.GetUIValueRange(DNA_UI_BEARD_STYLE, species_facial_hair.len) + 1, 1, species_facial_hair.len)
var/beard = clamp(dna.GetUIValueRange(DNA_UI_BEARD_STYLE, species_facial_hair.len), 1, species_facial_hair.len)
my_appearance.f_style = species_facial_hair[beard]
update_body(0)
update_hair()
regenerate_icons()
return 1

View File

@@ -79,7 +79,7 @@
if("Beard")
var/list/species_facial_hair = valid_sprite_accessories(facial_hair_styles_list, target.gender, target.species.name)
if(species_facial_hair.len)
var/new_style = input(user, "Select a facial hair style", "Grooming") as null|anything in species_facial_hair
var/new_style = input(user, "Select a facial hair style", "Grooming", target.my_appearance.f_style) as null|anything in species_facial_hair
if(!new_style || !attempt(user, target, which))
return
target.my_appearance.f_style = new_style
@@ -88,7 +88,7 @@
if("Hair")
var/list/species_hair = valid_sprite_accessories(hair_styles_list, null, target.species.name) //gender intentionally left null so speshul snowflakes can cross-hairdress
if(species_hair.len)
var/new_style = input(user, "Select a hair style", "Grooming") as null|anything in species_hair
var/new_style = input(user, "Select a hair style", "Grooming", target.my_appearance.h_style) as null|anything in species_hair
if(!new_style || !attempt(user, target, which))
return
target.my_appearance.h_style = new_style
@@ -221,7 +221,7 @@
switch(which)
if("Name")
var/stagename = copytext(sanitize(input(targ, "Pick a name","Name") as null|text), 1, MAX_NAME_LEN)
var/stagename = copytext(sanitize(input(targ, "Pick a name","Name",M.real_name) as null|text), 1, MAX_NAME_LEN)
targ.real_name = stagename
targ.name = stagename

View File

@@ -516,6 +516,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
new_character.dna = new()//Let's first give them a new DNA.
new_character.dna.unique_enzymes = record_found.fields["b_dna"]//Enzymes are based on real name but we'll use the record for conformity.
new_character.dna.b_type = record_found.fields["b_type"]
new_character.fixblood()
// I HATE BYOND. HATE. HATE. - N3X
var/list/newSE= record_found.fields["enzymes"]

View File

@@ -90,6 +90,7 @@
M.dna.UpdateUI()
M.UpdateAppearance()
M.fixblood()
if(husk)
M.ChangeToHusk()

View File

@@ -180,51 +180,78 @@
return list(red, green, blue)
/mob/living/carbon/human/proc/pick_gender(var/mob/user)
var/new_gender = alert(user, "Please select gender.", "Character Generation", "Male", "Female")
/mob/living/carbon/human/proc/pick_gender(var/mob/user, var/title = "Character Generation", var/update_icons = TRUE)
var/new_gender = alert(user, "Please select gender.", title, "Male", "Female")
if (new_gender)
setGender(new_gender == "Male" ? MALE : FEMALE)
update_body()
if (update_icons)
regenerate_icons()
/mob/living/carbon/human/proc/pick_appearance(var/mob/user)
var/new_tone = input(user, "Please select skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Character Generation") as text
if (!new_tone)
new_tone = 35
my_appearance.s_tone = max(min(round(text2num(new_tone)), 220), 1)
my_appearance.s_tone = -src.my_appearance.s_tone + 35
/mob/living/carbon/human/proc/pick_appearance(var/mob/user, var/title = "Character Generation", var/update_icons_and_dna = TRUE)
// SKIN
if (species)
switch (species.name)
if ("Human")
var/new_tone = input(user, "Select skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", title, "[35-my_appearance.s_tone]") as text
if (!new_tone)
new_tone = 35
my_appearance.s_tone = max(min(round(text2num(new_tone)), 220), 1)
my_appearance.s_tone = -my_appearance.s_tone + 35
if ("Vox")
var/new_tone = input(user, "Select feather color: 1-6 (1=dark green, 2=brown, 3=grey, 4=light green, 5=azure, 6=emerald)", title, "[my_appearance.s_tone]") as text
if (!new_tone)
new_tone = 1
my_appearance.s_tone = max(min(round(text2num(new_tone)), 6), 1)
if ("Grey")
var/new_tone = input(user, "Select skin color: 1-4 (1=grey, 2=pale gray, 3=greyish green, 4=greyish blue)", title, "[my_appearance.s_tone]") as text
if (!new_tone)
new_tone = 1
my_appearance.s_tone = max(min(round(text2num(new_tone)), 4), 1)
else
var/new_tone = input(user, "Select skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", title, "[35-my_appearance.s_tone]") as text
if (!new_tone)
new_tone = 35
my_appearance.s_tone = max(min(round(text2num(new_tone)), 220), 1)
my_appearance.s_tone = -my_appearance.s_tone + 35
var/new_facial = input(user, "Please select facial hair color.", "Character Generation") as color
if(new_facial)
my_appearance.r_facial = hex2num(copytext(new_facial, 2, 4))
my_appearance.g_facial = hex2num(copytext(new_facial, 4, 6))
my_appearance.b_facial = hex2num(copytext(new_facial, 6, 8))
// EYES
var/new_eye_color = input(user, "Select eye color.", title,rgb(my_appearance.r_eyes,my_appearance.g_eyes,my_appearance.b_eyes)) as color
if(new_eye_color)
my_appearance.r_eyes = hex2num(copytext(new_eye_color, 2, 4))
my_appearance.g_eyes = hex2num(copytext(new_eye_color, 4, 6))
my_appearance.b_eyes = hex2num(copytext(new_eye_color, 6, 8))
var/new_hair = input(user, "Please select hair color.", "Character Generation") as color
if(new_facial)
my_appearance.r_hair = hex2num(copytext(new_hair, 2, 4))
my_appearance.g_hair = hex2num(copytext(new_hair, 4, 6))
my_appearance.b_hair = hex2num(copytext(new_hair, 6, 8))
// HAIR
if (species)
var/list/valid_hair = valid_sprite_accessories(hair_styles_list, null, species.name) //can morph any hair regardless of gender
if(valid_hair.len)
var/new_style = input(user, "Select hair style", title, my_appearance.h_style) as null|anything in valid_hair
if(new_style)
my_appearance.h_style = new_style
var/new_eyes = input(user, "Please select eye color.", "Character Generation") as color
if(new_eyes)
my_appearance.r_eyes = hex2num(copytext(new_eyes, 2, 4))
my_appearance.g_eyes = hex2num(copytext(new_eyes, 4, 6))
my_appearance.b_eyes = hex2num(copytext(new_eyes, 6, 8))
var/new_hair_color = input(user, "Select hair color.", title,rgb(my_appearance.r_hair,my_appearance.g_hair,my_appearance.b_hair)) as color
if(new_hair_color)
my_appearance.r_hair = hex2num(copytext(new_hair_color, 2, 4))
my_appearance.g_hair = hex2num(copytext(new_hair_color, 4, 6))
my_appearance.b_hair = hex2num(copytext(new_hair_color, 6, 8))
//hair
var/new_hstyle = input(user, "Select a hair style", "Grooming") as null|anything in hair_styles_list
if(new_hstyle)
my_appearance.h_style = new_hstyle
// BEARD
if (species)
var/list/valid_facial_hair = valid_sprite_accessories(facial_hair_styles_list, null, species.name) //can morph any beard regardless of gender
if(valid_facial_hair.len)
var/new_style = input(user, "Select a facial hair style", title, my_appearance.f_style) as null|anything in valid_facial_hair
if(new_style)
my_appearance.f_style = new_style
// facial hair
var/new_fstyle = input(user, "Select a facial hair style", "Grooming") as null|anything in facial_hair_styles_list
if(new_fstyle)
my_appearance.f_style = new_fstyle
var/new_beard_color = input(user, "Select facial hair color.", title,rgb(my_appearance.r_facial,my_appearance.g_facial,my_appearance.b_facial)) as color
if(new_beard_color)
my_appearance.r_facial = hex2num(copytext(new_beard_color, 2, 4))
my_appearance.g_facial = hex2num(copytext(new_beard_color, 4, 6))
my_appearance.b_facial = hex2num(copytext(new_beard_color, 6, 8))
//M.rebuild_appearance()
update_hair()
update_body()
check_dna()
if (update_icons_and_dna)
regenerate_icons()
check_dna()
/datum/human_appearance/send_to_past(var/duration)
..()

View File

@@ -699,7 +699,6 @@
/mob/living/carbon/human/proc/check_dna()
dna.check_integrity(src)
return
/mob/living/carbon/human/get_species()
@@ -803,69 +802,10 @@
src.verbs -= /mob/living/carbon/human/proc/morph
return
var/new_facial = input("Please select facial hair color.", "Character Generation",rgb(my_appearance.r_facial,my_appearance.g_facial,my_appearance.b_facial)) as color
if(new_facial)
my_appearance.r_facial = hex2num(copytext(new_facial, 2, 4))
my_appearance.g_facial = hex2num(copytext(new_facial, 4, 6))
my_appearance.b_facial = hex2num(copytext(new_facial, 6, 8))
pick_appearance(src,"Morph",FALSE)
var/new_hair = input("Please select hair color.", "Character Generation",rgb(my_appearance.r_hair,my_appearance.g_hair,my_appearance.b_hair)) as color
if(new_facial)
my_appearance.r_hair = hex2num(copytext(new_hair, 2, 4))
my_appearance.g_hair = hex2num(copytext(new_hair, 4, 6))
my_appearance.b_hair = hex2num(copytext(new_hair, 6, 8))
pick_gender(src,"Morph",FALSE)
var/new_eyes = input("Please select eye color.", "Character Generation",rgb(my_appearance.r_eyes,my_appearance.g_eyes,my_appearance.b_eyes)) as color
if(new_eyes)
my_appearance.r_eyes = hex2num(copytext(new_eyes, 2, 4))
my_appearance.g_eyes = hex2num(copytext(new_eyes, 4, 6))
my_appearance.b_eyes = hex2num(copytext(new_eyes, 6, 8))
var/new_tone = input("Please select skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Character Generation", "[35-my_appearance.s_tone]") as text
if (!new_tone)
new_tone = 35
my_appearance.s_tone = max(min(round(text2num(new_tone)), 220), 1)
my_appearance.s_tone = -my_appearance.s_tone + 35
// hair
var/list/all_hairs = typesof(/datum/sprite_accessory/hair) - /datum/sprite_accessory/hair
var/list/hairs = list()
// loop through potential hairs
for(var/x in all_hairs)
var/datum/sprite_accessory/hair/H = new x // create new hair datum based on type x
hairs.Add(H.name) // add hair name to hairs
qdel(H) // delete the hair after it's all done
H = null
var/new_style = input("Please select hair style", "Character Generation",my_appearance.h_style) as null|anything in hairs
// if new style selected (not cancel)
if (new_style)
my_appearance.h_style = new_style
// facial hair
var/list/all_fhairs = typesof(/datum/sprite_accessory/facial_hair) - /datum/sprite_accessory/facial_hair
var/list/fhairs = list()
for(var/x in all_fhairs)
var/datum/sprite_accessory/facial_hair/H = new x
fhairs.Add(H.name)
qdel(H)
H = null
new_style = input("Please select facial style", "Character Generation",my_appearance.f_style) as null|anything in fhairs
if(new_style)
my_appearance.f_style = new_style
var/new_gender = alert(usr, "Please select gender.", "Character Generation", "Male", "Female")
if (new_gender)
if(new_gender == "Male")
setGender(MALE)
else
setGender(FEMALE)
regenerate_icons()
check_dna()

View File

@@ -103,6 +103,8 @@ var/global/list/whitelisted_species = list("Human")
var/blood_color = DEFAULT_BLOOD //Red.
var/flesh_color = DEFAULT_FLESH //Pink.
var/base_color //Used when setting species.
var/max_skin_tone = 0
var/uniform_icons = 'icons/mob/uniform.dmi'
var/fat_uniform_icons = 'icons/mob/uniform_fat.dmi'
var/gloves_icons = 'icons/mob/hands.dmi'
@@ -315,6 +317,8 @@ var/global/list/whitelisted_species = list("Human")
anatomy_flags = HAS_SKIN_TONE | HAS_LIPS | HAS_UNDERWEAR | CAN_BE_FAT | HAS_SWEAT_GLANDS
max_skin_tone = 220
/datum/species/human/gib(mob/living/carbon/human/H)
..()
H.default_gib()
@@ -535,6 +539,7 @@ var/global/list/whitelisted_species = list("Human")
footprint_type = /obj/effect/decal/cleanable/blood/tracks/footprints/catbeast
flesh_color = "#AFA59E"
max_skin_tone = 1
has_organ = list(
"heart" = /datum/organ/internal/heart,
@@ -596,6 +601,8 @@ var/global/list/whitelisted_species = list("Human")
max_hurt_damage = 3 // From 5 (for humans)
tacklePower = 25
max_skin_tone = 4
primitive = /mob/living/carbon/monkey/grey
flags = IS_WHITELISTED
@@ -745,6 +752,7 @@ var/global/list/whitelisted_species = list("Human")
blood_color = VOX_BLOOD
flesh_color = "#808D11"
max_skin_tone = 6
footprint_type = /obj/effect/decal/cleanable/blood/tracks/footprints/vox //Bird claws

View File

@@ -38,12 +38,6 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
vessel.add_reagent(BLOOD,560)
spawn(1)
//This lets DNA stuff properly initialize first, otherwise the blood in the vessels won't have any DNA.
//To safely remove this spawn(), find where dna.unique_enzymes/b_type are created and call fixblood() right after.
//Also test that blood driping when you cut yourself with a knife carries DNA properly using the detective scanner to be sure.
fixblood()
//Resets blood data
/mob/living/carbon/human/proc/fixblood()
for(var/datum/reagent/blood/B in vessel.reagent_list)