diff --git a/modular_chomp/code/modules/client/preferences.dm b/modular_chomp/code/modules/client/preferences.dm
index 6c9af02123..63ca5acd26 100644
--- a/modular_chomp/code/modules/client/preferences.dm
+++ b/modular_chomp/code/modules/client/preferences.dm
@@ -186,6 +186,7 @@
body_descriptors[entry] = descriptor.default_value // Species datums have initial default value.
else
body_descriptors[entry] = CLAMP(last_descriptors[entry], 1, LAZYLEN(descriptor.standalone_value_descriptors))
+ character.descriptors = body_descriptors
if (copy_flavour)
character.flavor_texts["general"] = flavor_texts["general"]
diff --git a/modular_chomp/code/modules/mob/living/carbon/human/human_helpers.dm b/modular_chomp/code/modules/mob/living/carbon/human/human_helpers.dm
new file mode 100644
index 0000000000..6f950f1762
--- /dev/null
+++ b/modular_chomp/code/modules/mob/living/carbon/human/human_helpers.dm
@@ -0,0 +1,138 @@
+/mob/living/carbon/human/proc/transform_into_other_human(var/mob/living/carbon/human/character, var/copy_name, var/copy_flavour = TRUE, var/convert_to_prosthetics = FALSE)
+ /*
+ name, nickname, flavour, OOC notes
+ gender, sex
+ custom species name, custom bodytype, weight, scale, scaling center, sound type, sound freq
+ custom say verbs
+ ears, wings, tail, hair, facial hair
+ ears colors, wings colors, tail colors
+ body color, prosthetics (if they're a protean) (convert to DSI if protean and not prosthetic), eye color, hair color etc
+ markings
+ custom synth markings toggle, custom synth color toggle
+ digitigrade
+ blood color
+ */
+ if (copy_name)
+ name = character.name
+ nickname = character.nickname
+ gender = character.gender
+ identifying_gender = character.identifying_gender
+
+ r_eyes = character.r_eyes
+ g_eyes = character.g_eyes
+ b_eyes = character.b_eyes
+ h_style = character.h_style
+ r_hair = character.r_hair
+ g_hair = character.g_hair
+ b_hair = character.b_hair
+ r_grad = character.r_grad
+ g_grad = character.g_grad
+ b_grad = character.b_grad
+ f_style = character.f_style
+ r_facial = character.r_facial
+ g_facial = character.g_facial
+ b_facial = character.b_facial
+ r_skin = character.r_skin
+ g_skin = character.g_skin
+ b_skin = character.b_skin
+ s_tone = character.s_tone
+ h_style = character.h_style
+ grad_style = character.grad_style
+ f_style = character.f_style
+ grad_style = character.grad_style
+ b_type = character.b_type
+ synth_color = character.synth_color
+ r_synth = character.r_synth
+ g_synth = character.g_synth
+ b_synth = character.b_synth
+ synth_markings = character.synth_markings
+
+ ear_style = character.ear_style
+ r_ears = character.r_ears
+ b_ears = character.b_ears
+ g_ears = character.g_ears
+ r_ears2 = character.r_ears2
+ b_ears2 = character.b_ears2
+ g_ears2 = character.g_ears2
+ r_ears3 = character.r_ears3
+ b_ears3 = character.b_ears3
+ g_ears3 = character.g_ears3
+
+ tail_style = character.tail_style
+ r_tail = character.r_tail
+ b_tail = character.b_tail
+ g_tail = character.g_tail
+ r_tail2 = character.r_tail2
+ b_tail2 = character.b_tail2
+ g_tail2 = character.g_tail2
+ r_tail3 = character.r_tail3
+ b_tail3 = character.b_tail3
+ g_tail3 = character.g_tail3
+
+ wing_style = character.wing_style
+ r_wing = character.r_wing
+ b_wing = character.b_wing
+ g_wing = character.g_wing
+ r_wing2 = character.r_wing2
+ b_wing2 = character.b_wing2
+ g_wing2 = character.g_wing2
+ r_wing3 = character.r_wing3
+ b_wing3 = character.b_wing3
+ g_wing3 = character.g_wing3
+
+
+ var/bodytype = character.species?.get_bodytype()
+
+ if (convert_to_prosthetics) //should only really be run for proteans
+ for(var/name in BP_ALL)
+ var/obj/item/organ/external/I = character.organs_by_name[name]
+ var/obj/item/organ/external/O = organs_by_name[name]
+ if(O)
+ if(I.robotic >= ORGAN_ROBOT)
+ O.robotize(I.model)
+ else
+ var/dsi_company = GLOB.dsi_to_species[bodytype]
+ if (!dsi_company)
+ dsi_company = "DSI - Synthetic"
+ O.robotize(dsi_company)
+
+ for(var/N in character.organs_by_name)
+ var/obj/item/organ/external/O = organs_by_name[N]
+ var/obj/item/organ/external/I = character.organs_by_name[N]
+ O.markings = I.markings.Copy()
+
+ markings_len = character.markings_len
+
+ descriptors = character.descriptors?.Copy()
+
+ if (copy_flavour)
+ flavor_texts = character.flavor_texts?.Copy()
+
+ weight = character.weight
+ weight_gain = character.weight_gain
+ weight_loss = character.weight_loss
+ fuzzy = character.fuzzy
+ offset_override = character.offset_override //CHOMPEdit
+ voice_freq = character.voice_freq
+ character.resize(character.size_multiplier, animate = TRUE, ignore_prefs = TRUE)
+ voice_sounds_list = character.voice_sounds_list
+
+ species?.blood_color = character.species?.blood_color
+
+ dna?.base_species = bodytype
+ species?.base_species = bodytype
+ species?.vanity_base_fit = bodytype
+ if (istype(species, /datum/species/shapeshifter))
+ wrapped_species_by_ref["\ref[src]"] = bodytype
+
+ custom_species = character.custom_species
+ custom_say = character.custom_say
+ custom_ask = character.custom_ask
+ custom_whisper = character.custom_whisper
+ custom_exclaim = character.custom_exclaim
+
+ digitigrade = character.digitigrade
+
+ dna?.ResetUIFrom(src)
+ force_update_limbs()
+ regenerate_icons()
diff --git a/modular_chomp/code/modules/mob/living/carbon/human/species/station/protean/protean_blob.dm b/modular_chomp/code/modules/mob/living/carbon/human/species/station/protean/protean_blob.dm
index 8fef3aaa20..c26d3ca134 100644
--- a/modular_chomp/code/modules/mob/living/carbon/human/species/station/protean/protean_blob.dm
+++ b/modular_chomp/code/modules/mob/living/carbon/human/species/station/protean/protean_blob.dm
@@ -180,6 +180,11 @@
/mob/living/simple_mob/protean_blob/isSynthetic()
return TRUE // yup
+/mob/living/simple_mob/protean_blob/get_available_emotes()
+ var/list/fulllist = global._robot_default_emotes.Copy()
+ fulllist |= global._human_default_emotes //they're living nanites, they can make whatever sounds they want
+ return fulllist
+
/mob/living/simple_mob/protean_blob/Stat()
..()
if(humanform)
diff --git a/modular_chomp/code/modules/mob/living/carbon/human/species/station/protean/protean_powers.dm b/modular_chomp/code/modules/mob/living/carbon/human/species/station/protean/protean_powers.dm
index 77a0cdbc2b..513979c618 100644
--- a/modular_chomp/code/modules/mob/living/carbon/human/species/station/protean/protean_powers.dm
+++ b/modular_chomp/code/modules/mob/living/carbon/human/species/station/protean/protean_powers.dm
@@ -130,12 +130,81 @@
to_chat(caller, "You begin to reassemble. You will need to remain still.")
caller.visible_message("[caller] rapidly contorts and shifts!", "You begin to reassemble.")
if(do_after(caller, 40,exclusive = TASK_ALL_EXCLUSIVE))
- if(client.prefs) //Make sure we didn't d/c
+ if(caller.client.prefs) //Make sure we didn't d/c
var/obj/item/weapon/rig/protean/Rig = species?:OurRig
- caller.client.prefs.vanity_copy_to(caller, FALSE, flavour, oocnotes, TRUE)
+ caller.client.prefs.vanity_copy_to(src, FALSE, flavour, oocnotes, TRUE)
species?:OurRig = Rig //Get a reference to our Rig and put it back after reassembling
caller.visible_message("[caller] adopts a new form!", "You have reassembled.")
+
+/mob/living/carbon/human/proc/nano_copy_body()
+ set name = "Copy Form"
+ set desc = "If you are aggressively grabbing someone, with their consent, you can turn into a copy of them. (Without their name)."
+ set category = "Abilities"
+ set hidden = 1
+ var/mob/living/caller = src
+ if(temporary_form)
+ caller = temporary_form
+
+ var/grabbing_but_not_enough
+ var/mob/living/carbon/human/victim = null
+ for(var/obj/item/weapon/grab/G in caller)
+ if(G.state < GRAB_AGGRESSIVE)
+ grabbing_but_not_enough = TRUE
+ return
+ else
+ victim = G.affecting
+ if (!victim)
+ if (grabbing_but_not_enough)
+ to_chat(caller, "You need a better grip to do that!")
+ else
+ to_chat(caller, "You need to be aggressively grabbing someone before you can copy their form.")
+ return
+ if (!istype(victim))
+ to_chat(caller, "You can only perform this on human mobs!")
+ return
+ if (!victim.client)
+ to_chat(caller, "The person you try this on must have a client!")
+ return
+
+
+ to_chat(caller, "Waiting for other person's consent.")
+ var/consent = tgui_alert(victim, "Allow [src] to copy what you look like?", "Consent", list("Yes", "No"))
+ if (consent != "Yes")
+ to_chat(caller, "They declined your request.")
+ return
+
+ var/input = tgui_alert(caller,{"Copy [victim]'s flavourtext?"},"Copy Form",list("Yes","No","Cancel"))
+ if(input == "Cancel" || !input)
+ return
+ var/flavour = 0
+ if(input == "Yes")
+ flavour = 1
+
+ var/checking = FALSE
+ for(var/obj/item/weapon/grab/G in caller)
+ if(G.affecting == victim && G.state >= GRAB_AGGRESSIVE)
+ checking = TRUE
+ if (!checking)
+ to_chat(caller, "You lost your grip on [victim]!")
+ return
+
+ to_chat(caller, "You begin to reassemble into [victim]. You will need to remain still.")
+ caller.visible_message("[caller] rapidly contorts and shifts!", "You begin to reassemble into [victim].")
+ if(do_after(caller, 40,exclusive = TASK_ALL_EXCLUSIVE))
+ checking = FALSE
+ for(var/obj/item/weapon/grab/G in caller)
+ if(G.affecting == victim && G.state >= GRAB_AGGRESSIVE)
+ checking = TRUE
+ if (!checking)
+ to_chat(caller, "You lost your grip on [victim]!")
+ return
+ if(caller.client) //Make sure we didn't d/c
+ var/obj/item/weapon/rig/protean/Rig = species?:OurRig
+ transform_into_other_human(victim, FALSE, flavour, TRUE)
+ species?:OurRig = Rig //Get a reference to our Rig and put it back after reassembling
+ caller.visible_message("[caller] adopts the form of [victim]!", "You have reassembled into [victim].")
+
////
// Storing metal
////
@@ -491,4 +560,10 @@
icon_state = "latch"
to_call = /mob/living/carbon/human/proc/nano_latch
+/obj/effect/protean_ability/copy_form
+ ability_name = "Copy Form"
+ desc = "If you are aggressively grabbing someone, with their consent, you can turn into a copy of them. (Without their name)."
+ icon_state = "copy_form"
+ to_call = /mob/living/carbon/human/proc/nano_copy_body
+
#undef PER_LIMB_STEEL_COST
diff --git a/modular_chomp/code/modules/mob/living/carbon/human/species/station/protean/protean_species.dm b/modular_chomp/code/modules/mob/living/carbon/human/species/station/protean/protean_species.dm
index e94b767e84..55667c2f42 100644
--- a/modular_chomp/code/modules/mob/living/carbon/human/species/station/protean/protean_species.dm
+++ b/modular_chomp/code/modules/mob/living/carbon/human/species/station/protean/protean_species.dm
@@ -95,6 +95,7 @@
/mob/living/carbon/human/proc/nano_metalnom,
/mob/living/carbon/human/proc/nano_blobform,
/mob/living/carbon/human/proc/nano_rig_transform,
+ /mob/living/carbon/human/proc/nano_copy_body,
/mob/living/carbon/human/proc/appearance_switch,
/mob/living/carbon/human/proc/nano_latch,
/mob/living/proc/set_size,
diff --git a/modular_chomp/icons/mob/species/protean/protean_powers.dmi b/modular_chomp/icons/mob/species/protean/protean_powers.dmi
index 3120d9d0ce..efcd821a81 100644
Binary files a/modular_chomp/icons/mob/species/protean/protean_powers.dmi and b/modular_chomp/icons/mob/species/protean/protean_powers.dmi differ
diff --git a/vorestation.dme b/vorestation.dme
index bf3e245c88..e8b6e7b269 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -4557,6 +4557,7 @@
#include "modular_chomp\code\modules\mob\living\carbon\human\emote.dm"
#include "modular_chomp\code\modules\mob\living\carbon\human\human.dm"
#include "modular_chomp\code\modules\mob\living\carbon\human\human_defines.dm"
+#include "modular_chomp\code\modules\mob\living\carbon\human\human_helpers.dm"
#include "modular_chomp\code\modules\mob\living\carbon\human\update_icons.dm"
#include "modular_chomp\code\modules\mob\living\carbon\human\species\species.dm"
#include "modular_chomp\code\modules\mob\living\carbon\human\species\species_shapeshift_ch.dm"