diff --git a/code/__DEFINES/~skyrat_defines/DNA.dm b/code/__DEFINES/~skyrat_defines/DNA.dm
index d1d31aabacf..f9dd72362a4 100644
--- a/code/__DEFINES/~skyrat_defines/DNA.dm
+++ b/code/__DEFINES/~skyrat_defines/DNA.dm
@@ -62,9 +62,15 @@
#define BODY_SIZE_MAX 1.5
#define BODY_SIZE_MIN 0.8
+//In inches
+#define PENIS_MAX_GIRTH 15
+#define PENIS_MIN_LENGTH 1
+#define PENIS_MAX_LENGTH 20
+
#define SHEATH_NONE "None"
#define SHEATH_NORMAL "Sheath"
#define SHEATH_SLIT "Slit"
+#define SHEATH_MODES list(SHEATH_NONE, SHEATH_NORMAL, SHEATH_SLIT)
#define MANDATORY_FEATURE_LIST list("mcolor" = "FFB","mcolor2" = "FFB","mcolor3" = "FFB","ethcolor" = "FCC","skin_color" = "FED","flavor_text" = "","breasts_size" = 1,"breasts_lactation" = FALSE,"penis_size" = 13,"penis_girth" = 9,"penis_taur_mode" = TRUE,"penis_sheath" = SHEATH_NONE ,"balls_size" = 1, "body_size" = BODY_SIZE_NORMAL, "custom_species" = null, "uses_skintones" = FALSE)
diff --git a/code/datums/dna.dm b/code/datums/dna.dm
index cb3cf31096f..a034cf2c58c 100644
--- a/code/datums/dna.dm
+++ b/code/datums/dna.dm
@@ -48,7 +48,8 @@
destination.dna.unique_enzymes = unique_enzymes
destination.dna.uni_identity = uni_identity
destination.dna.blood_type = blood_type
- destination.set_species(species.type, icon_update=0)
+ //destination.set_species(species.type, icon_update=0) //ORIGINAL
+ destination.set_species(species.type, TRUE, null, features.Copy(), mutant_bodyparts.Copy(), body_markings.Copy()) //SKYRAT EDIT CHANGE - CUSTOMIZATION
destination.dna.features = features.Copy()
destination.dna.real_name = real_name
destination.dna.temporary_mutations = temporary_mutations.Copy()
@@ -63,6 +64,11 @@
new_dna.uni_identity = uni_identity
new_dna.blood_type = blood_type
new_dna.features = features.Copy()
+ //SKYRAT EDIT ADDITION BEGIN - CUSTOMIZATION
+ new_dna.mutant_bodyparts = mutant_bodyparts.Copy()
+ new_dna.body_markings = body_markings.Copy()
+ new_dna.update_body_size()
+ //SKYRAT EDIT ADDITION END
new_dna.species = new species.type
new_dna.real_name = real_name
new_dna.mutations = mutations.Copy()
diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
index efd2475c717..595dd0b1b43 100644
--- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
@@ -11,6 +11,7 @@
exotic_blood = /datum/reagent/toxin/slimejelly
damage_overlay_type = ""
var/datum/action/innate/regenerate_limbs/regenerate_limbs
+ var/datum/action/innate/slime_change/slime_change //SKYRAT EDIT ADDITION - CUSTOMIZATION
liked_food = MEAT
coldmod = 6 // = 3x cold damage
heatmod = 0.5 // = 1/4x heat damage
@@ -24,6 +25,10 @@
/datum/species/jelly/on_species_loss(mob/living/carbon/C)
if(regenerate_limbs)
regenerate_limbs.Remove(C)
+ //SKYRAT EDIT ADDITION BEGIN - CUSTOMIZATION
+ if(slime_change)
+ slime_change.Remove(C)
+ //SKYRAT EDIT ADDITION END
..()
/datum/species/jelly/on_species_gain(mob/living/carbon/C, datum/species/old_species)
@@ -31,6 +36,10 @@
if(ishuman(C))
regenerate_limbs = new
regenerate_limbs.Grant(C)
+ //SKYRAT EDIT ADDITION BEGIN - CUSTOMIZATION
+ slime_change = new
+ slime_change.Grant(C)
+ //SKYRAT EDIT ADDITION END
/datum/species/jelly/spec_life(mob/living/carbon/human/H)
if(H.stat == DEAD) //can't farm slime jelly from a dead slime/jelly person indefinitely
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 43717753027..83b7a01dd72 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -534,7 +534,8 @@
if(current_cycle >= cycles_to_turn)
var/datum/species/species_type = race
- H.set_species(species_type)
+ //H.set_species(species_type) //ORIGINAL
+ H.set_species(species_type, TRUE, null, null, null, null, TRUE) //SKYRAT EDIT CHANGE - CUSTOMIZATION
holder.del_reagent(type)
to_chat(H, "You've become \a [lowertext(initial(species_type.name))]!")
return
@@ -596,7 +597,8 @@
return TRUE
if(current_cycle >= cycles_to_turn) //overwrite since we want subtypes of jelly
var/datum/species/species_type = pick(subtypesof(race))
- H.set_species(species_type)
+ //H.set_species(species_type) //ORIGINAL
+ H.set_species(species_type, TRUE, null, null, null, null, TRUE) //SKYRAT EDIT CHANGE - CUSTOMIZATION
holder.del_reagent(type)
to_chat(H, "You've become \a [initial(species_type.name)]!")
return TRUE
diff --git a/modular_skyrat/modules/cloning/code/game/machinery/cloning.dm b/modular_skyrat/modules/cloning/code/game/machinery/cloning.dm
index c33d4c108b5..92274c210e5 100644
--- a/modular_skyrat/modules/cloning/code/game/machinery/cloning.dm
+++ b/modular_skyrat/modules/cloning/code/game/machinery/cloning.dm
@@ -188,7 +188,7 @@
H.real_name = clonename
H.hardset_dna(ui, mutation_index, H.dna.default_mutation_genes, H.real_name, blood_type, mrace, features, H.dna.mutations, FALSE)
- H.set_species(mrace, TRUE, null, features, mutantparts, markings)
+ H.set_species(mrace, TRUE, null, features.Copy(), mutantparts.Copy(), markings.Copy())
if(!HAS_TRAIT(H, TRAIT_RADIMMUNE))//dont apply mutations if the species is Mutation proof.
if(efficiency > 2)
diff --git a/modular_skyrat/modules/customization/datums/dna.dm b/modular_skyrat/modules/customization/datums/dna.dm
index 8d24b71352f..7a4552e557d 100644
--- a/modular_skyrat/modules/customization/datums/dna.dm
+++ b/modular_skyrat/modules/customization/datums/dna.dm
@@ -26,7 +26,7 @@
holder.transform = holder.transform.Translate(0, translate)
current_body_size = features["body_size"]
-/mob/living/carbon/set_species(datum/species/mrace, icon_update = TRUE, var/datum/preferences/pref_load, var/list/override_features, var/list/override_mutantparts, var/list/override_markings)
+/mob/living/carbon/set_species(datum/species/mrace, icon_update = TRUE, var/datum/preferences/pref_load, var/list/override_features, var/list/override_mutantparts, var/list/override_markings, retain_features = FALSE)
if(mrace && has_dna())
var/datum/species/new_race
if(ispath(mrace))
@@ -48,7 +48,8 @@
dna.body_markings = pref_load.body_markings.Copy()
dna.species.body_markings = pref_load.body_markings.Copy()
else
- dna.features = override_features || new_race.get_random_features()
+ if(!retain_features)
+ dna.features = override_features || new_race.get_random_features()
dna.mutant_bodyparts = override_mutantparts || new_race.get_random_mutant_bodyparts(dna.features)
dna.body_markings = override_markings || new_race.get_random_body_markings(dna.features)
dna.species.body_markings = dna.body_markings.Copy()
@@ -63,6 +64,8 @@
dna.species.mutant_bodyparts = bodyparts_to_add.Copy()
+ dna.update_body_size()
+
dna.species.on_species_gain(src, old_species, pref_load)
//END OF BODYPARTS AND FEATURES
if(ishuman(src))
diff --git a/modular_skyrat/modules/customization/icons/mob/actions/actions_slime.dmi b/modular_skyrat/modules/customization/icons/mob/actions/actions_slime.dmi
new file mode 100644
index 00000000000..78e01866f13
Binary files /dev/null and b/modular_skyrat/modules/customization/icons/mob/actions/actions_slime.dmi differ
diff --git a/modular_skyrat/modules/customization/modules/client/preferences.dm b/modular_skyrat/modules/customization/modules/client/preferences.dm
index ac4c9d6dadd..6007640e656 100644
--- a/modular_skyrat/modules/customization/modules/client/preferences.dm
+++ b/modular_skyrat/modules/customization/modules/client/preferences.dm
@@ -1702,18 +1702,17 @@
if("penis_taur_mode")
features["penis_taur_mode"] = !features["penis_taur_mode"]
if("penis_size")
- var/new_length = input(user, "Choose your penis length:\n(2-20 in inches)", "Character Preference") as num|null
+ var/new_length = input(user, "Choose your penis length:\n([PENIS_MIN_LENGTH]-[PENIS_MAX_LENGTH] in inches)", "Character Preference") as num|null
if(new_length)
- features["penis_size"] = clamp(round(new_length, 1), 2, 20)
+ features["penis_size"] = clamp(round(new_length, 1), PENIS_MIN_LENGTH, PENIS_MAX_LENGTH)
if(features["penis_girth"] >= new_length)
features["penis_girth"] = new_length - 1
if("penis_sheath")
- var/list/sheath_choice_list = list(SHEATH_NONE, SHEATH_NORMAL, SHEATH_SLIT)
- var/new_sheath = input(user, "Choose your penis sheath", "Character Preference") as null|anything in sheath_choice_list
+ var/new_sheath = input(user, "Choose your penis sheath", "Character Preference") as null|anything in SHEATH_MODES
if(new_sheath)
features["penis_sheath"] = new_sheath
if("penis_girth")
- var/max_girth = 15
+ var/max_girth = PENIS_MAX_GIRTH
if(features["penis_size"] >= max_girth)
max_girth = features["penis_size"]
var/new_girth = input(user, "Choose your penis girth:\n(1-[max_girth] (based on length) in inches)", "Character Preference") as num|null
diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm
index c468661470b..3c0bb58bc45 100644
--- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm
+++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm
@@ -12,3 +12,204 @@
coldmod = 3
heatmod = 1
burnmod = 1
+
+/datum/action/innate/slime_change
+ name = "Alter Form"
+ check_flags = AB_CHECK_CONSCIOUS
+ button_icon_state = "alter_form"
+ icon_icon = 'modular_skyrat/modules/customization/icons/mob/actions/actions_slime.dmi'
+ background_icon_state = "bg_alien"
+ var/slime_restricted = TRUE
+
+/datum/action/innate/slime_change/admin
+ slime_restricted = FALSE
+
+/datum/action/innate/slime_change/Activate()
+ var/mob/living/carbon/human/H = owner
+ if(slime_restricted && !isjellyperson(H))
+ return
+ if(slime_restricted)
+ H.visible_message("[owner] gains a look of \
+ concentration while standing perfectly still.\
+ Their body seems to shift and starts getting more goo-like.",
+ "You focus intently on altering your body while \
+ standing perfectly still...")
+ change_form()
+
+/datum/action/innate/slime_change/proc/change_form()
+ var/mob/living/carbon/human/H = owner
+ var/select_alteration = input(H, "Select what part of your form to alter", "Form Alteration", "cancel") in list("Body Colors","Hair Style", "Facial Hair Style", "Mutant Body Parts", "Markings", "DNA Specifics", "Cancel")
+ if(!select_alteration || select_alteration == "Cancel" || QDELETED(H))
+ return
+ var/datum/dna/DNA = H.dna
+ switch(select_alteration)
+ if("Body Colors")
+ var/color_choice = input(H, "What color would you like to change?", "Form Alteration", "cancel") in list("Primary", "Secondary", "Tertiary", "All", "Cancel")
+ if(!color_choice || color_choice == "Cancel" || QDELETED(H))
+ return
+ var/color_target
+ switch(color_choice)
+ if("Primary", "All")
+ color_target = "mcolor"
+ if("Secondary")
+ color_target = "mcolor2"
+ if("Tertiary")
+ color_target = "mcolor3"
+ var/new_mutantcolor = input(H, "Choose your character's new [lowertext(color_choice)] color:", "Form Alteration","#"+DNA.features[color_target]) as color|null
+ if(!new_mutantcolor)
+ return
+ var/marking_reset = alert(H, "Would you like to reset your markings to match your new colors?", "", "Yes", "No")
+ var/mutantpart_reset = alert(H, "Would you like to reset your mutant body parts(not limbs) to match your new colors?", "", "Yes", "No")
+ if(color_choice == "All")
+ DNA.features["mcolor"] = sanitize_hexcolor(new_mutantcolor)
+ DNA.features["mcolor2"] = sanitize_hexcolor(new_mutantcolor)
+ DNA.features["mcolor3"] = sanitize_hexcolor(new_mutantcolor)
+ else
+ DNA.features[color_target] = sanitize_hexcolor(new_mutantcolor)
+ if(marking_reset && marking_reset == "Yes")
+ for(var/zone in DNA.body_markings)
+ for(var/key in DNA.body_markings[zone])
+ var/datum/body_marking/BD = GLOB.body_markings[key]
+ if(BD.always_color_customizable)
+ continue
+ DNA.body_markings[zone][key] = BD.get_default_color(DNA.features, DNA.species)
+ H.icon_render_key = "" //Currently the render key doesnt recognize the markings colors
+ if(mutantpart_reset && mutantpart_reset == "Yes")
+ H.mutant_renderkey = "" //Just in case
+ for(var/mutant_key in DNA.species.mutant_bodyparts)
+ var/mutant_list = DNA.species.mutant_bodyparts[mutant_key]
+ var/datum/sprite_accessory/SP = GLOB.sprite_accessories[mutant_key][mutant_list[MUTANT_INDEX_NAME]]
+ mutant_list[MUTANT_INDEX_COLOR_LIST] = SP.get_default_color(DNA.features, DNA.species)
+
+ H.update_body()
+ H.update_hair()
+ if("Hair Style")
+ var/new_style = input(owner, "Select a hair style", "Hair Alterations") as null|anything in GLOB.hairstyles_list
+ if(new_style)
+ H.hairstyle = new_style
+ H.update_hair()
+ if("Facial Hair Style")
+ var/new_style = input(H, "Select a facial hair style", "Hair Alterations") as null|anything in GLOB.facial_hairstyles_list
+ if(new_style)
+ H.facial_hairstyle = new_style
+ H.update_hair()
+ if("Mutant Body Parts")
+ var/list/key_list = DNA.mutant_bodyparts
+ var/chosen_key = input(H, "Select the part you want to alter", "Body Part Alterations") as null|anything in key_list + "Cancel"
+ if(!chosen_key || chosen_key == "Cancel")
+ return
+ var/choice_list = GLOB.sprite_accessories[chosen_key]
+ var/chosen_name_key = input(H, "What do you want the part to become?", "Body Part Alterations") as null|anything in choice_list + "Cancel"
+ if(!chosen_name_key || chosen_name_key == "Cancel")
+ return
+ var/datum/sprite_accessory/SA = GLOB.sprite_accessories[chosen_key][chosen_name_key]
+ H.mutant_renderkey = "" //Just in case
+ if(!SA.factual)
+ if(SA.organ_type)
+ var/obj/item/organ/path = SA.organ_type
+ var/slot = initial(path.slot)
+ var/obj/item/organ/got_organ = H.getorganslot(slot)
+ if(got_organ)
+ got_organ.Remove(H)
+ qdel(got_organ)
+ else
+ DNA.species.mutant_bodyparts -= chosen_key
+ else
+ if(SA.organ_type)
+ var/obj/item/organ/path = SA.organ_type
+ var/slot = initial(path.slot)
+ var/obj/item/organ/got_organ = H.getorganslot(slot)
+ if(got_organ)
+ got_organ.Remove(H)
+ qdel(got_organ)
+ path = new SA.organ_type
+ var/list/new_acc_list = list()
+ new_acc_list[MUTANT_INDEX_NAME] = SA.name
+ new_acc_list[MUTANT_INDEX_COLOR_LIST] = SA.get_default_color(DNA.features, DNA.species)
+ DNA.mutant_bodyparts[chosen_key] = new_acc_list.Copy()
+ if(ROBOTIC_DNA_ORGANS in DNA.species.species_traits)
+ path.status = ORGAN_ROBOTIC
+ path.organ_flags |= ORGAN_SYNTHETIC
+ path.build_from_dna(DNA, chosen_key)
+ path.Insert(H, 0, FALSE)
+
+ else
+ var/list/new_acc_list = list()
+ new_acc_list[MUTANT_INDEX_NAME] = SA.name
+ new_acc_list[MUTANT_INDEX_COLOR_LIST] = SA.get_default_color(DNA.features, DNA.species)
+ DNA.species.mutant_bodyparts[chosen_key] = new_acc_list
+ DNA.mutant_bodyparts[chosen_key] = new_acc_list.Copy()
+ H.update_mutant_bodyparts()
+ if("Markings")
+ var/list/candidates = GLOB.body_marking_sets
+ var/chosen_name = input(H, "Select which set of markings would you like to change into", "Marking Alterations") as null|anything in candidates + "Cancel"
+ if(!chosen_name || chosen_name == "Cancel")
+ return
+ var/datum/body_marking_set/BMS = GLOB.body_marking_sets[chosen_name]
+ DNA.species.body_markings = assemble_body_markings_from_set(BMS, DNA.features, DNA.species)
+ H.icon_render_key = "" //Just in case
+ H.update_body()
+ if("DNA Specifics")
+ var/dna_alteration = input(H, "Select what part of your DNA you'd like to alter", "DNA Alteration", "cancel") in list("Penis Size","Penis Girth", "Penis Sheath", "Penis Taur Mode", "Balls Size", "Breasts Size", "Breasts Lactation", "Body Size", "Cancel")
+ if(!dna_alteration || dna_alteration == "Cancel")
+ return
+ switch(dna_alteration)
+ if("Breasts Size")
+ var/new_size = input(H, "Choose your character's breasts size:", "DNA Alteration") as null|anything in GLOB.preference_breast_sizes
+ if(new_size)
+ DNA.features["breasts_size"] = breasts_cup_to_size(new_size)
+ var/obj/item/organ/genital/breasts/melons = H.getorganslot(ORGAN_SLOT_BREASTS)
+ if(melons)
+ melons.set_size(DNA.features["breasts_size"])
+ if("Breasts Lactation")
+ DNA.features["breasts_lactation"] = !DNA.features["breasts_lactation"]
+ var/obj/item/organ/genital/breasts/melons = H.getorganslot(ORGAN_SLOT_BREASTS)
+ if(melons)
+ melons.lactates = DNA.features["breasts_lactation"]
+ to_chat(H, "Your breasts [DNA.features["breasts_lactation"] ? "will now lactate" : "will not lactate anymore"].")
+ if("Penis Taur Mode")
+ DNA.features["penis_taur_mode"] = !DNA.features["penis_taur_mode"]
+ to_chat(H, "Your penis [DNA.features["penis_taur_mode"] ? "will be at your taur part" : "will not be at your taur part anymore"].")
+ if("Penis Size")
+ var/new_length = input(H, "Choose your penis length:\n([PENIS_MIN_LENGTH]-[PENIS_MAX_LENGTH] in inches)", "DNA Alteration") as num|null
+ if(new_length)
+ DNA.features["penis_size"] = clamp(round(new_length, 1), PENIS_MIN_LENGTH, PENIS_MAX_LENGTH)
+ var/obj/item/organ/genital/penis/PP = H.getorganslot(ORGAN_SLOT_PENIS)
+ if(DNA.features["penis_girth"] >= new_length)
+ DNA.features["penis_girth"] = new_length - 1
+ if(PP)
+ PP.girth = DNA.features["penis_girth"]
+ if(PP)
+ PP.set_size(DNA.features["penis_size"])
+ if("Penis Sheath")
+ var/new_sheath = input(H, "Choose your penis sheath", "DNA Alteration") as null|anything in SHEATH_MODES
+ if(new_sheath)
+ DNA.features["penis_sheath"] = new_sheath
+ var/obj/item/organ/genital/penis/PP = H.getorganslot(ORGAN_SLOT_PENIS)
+ if(PP)
+ PP.sheath = new_sheath
+ if("Penis Girth")
+ var/max_girth = PENIS_MAX_GIRTH
+ if(DNA.features["penis_size"] >= max_girth)
+ max_girth = DNA.features["penis_size"]
+ var/new_girth = input(H, "Choose your penis girth:\n(1-[max_girth] (based on length) in inches)", "Character Preference") as num|null
+ if(new_girth)
+ DNA.features["penis_girth"] = clamp(round(new_girth, 1), 1, max_girth)
+ var/obj/item/organ/genital/penis/PP = H.getorganslot(ORGAN_SLOT_PENIS)
+ if(PP)
+ PP.girth = DNA.features["penis_girth"]
+ if("Balls Size")
+ var/new_size = input(H, "Choose your character's balls size:", "Character Preference") as null|anything in GLOB.preference_balls_sizes
+ if(new_size)
+ DNA.features["balls_size"] = balls_description_to_size(new_size)
+ var/obj/item/organ/genital/testicles/avocados = H.getorganslot(ORGAN_SLOT_TESTICLES)
+ if(avocados)
+ avocados.set_size(DNA.features["balls_size"])
+ if("Body Size")
+ var/new_body_size = input(H, "Choose your desired sprite size:\n([BODY_SIZE_MIN*100]%-[BODY_SIZE_MAX*100]%), Warning: May make your character look distorted", "Character Preference", DNA.features["body_size"]*100) as num|null
+ if(new_body_size)
+ new_body_size = clamp(new_body_size * 0.01, BODY_SIZE_MIN, BODY_SIZE_MAX)
+ DNA.features["body_size"] = new_body_size
+ DNA.update_body_size()
+ H.mutant_renderkey = "" //Just in case
+ H.update_mutant_bodyparts()