mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 10:21:11 +00:00
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:
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -90,6 +90,7 @@
|
||||
|
||||
M.dna.UpdateUI()
|
||||
M.UpdateAppearance()
|
||||
M.fixblood()
|
||||
|
||||
if(husk)
|
||||
M.ChangeToHusk()
|
||||
|
||||
@@ -180,50 +180,77 @@
|
||||
|
||||
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
|
||||
/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 = -src.my_appearance.s_tone + 35
|
||||
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()
|
||||
if (update_icons_and_dna)
|
||||
regenerate_icons()
|
||||
check_dna()
|
||||
|
||||
/datum/human_appearance/send_to_past(var/duration)
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user