diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/morph/morph.dm b/code/modules/mob/living/simple_mob/subtypes/vore/morph/morph.dm
index 329b747f971..c20182fe58e 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/morph/morph.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/morph/morph.dm
@@ -42,6 +42,8 @@
showvoreprefs = 0
vore_active = 1
+ vore_default_mode = DM_HOLD
+
var/morphed = FALSE
var/tooltip = TRUE
@@ -50,6 +52,8 @@
var/atom/movable/form = null
var/morph_time = 0
var/our_size_multiplier = 1
+ var/original_ckey
+ var/prey_ckey
var/static/list/blacklist_typecache = typecacheof(list(
/obj/screen,
/obj/singularity,
@@ -58,6 +62,7 @@
/mob/living/simple_mob/vore/hostile/morph/Initialize()
verbs += /mob/living/proc/ventcrawl
+ verbs += /mob/living/simple_mob/vore/hostile/morph/proc/take_over_prey
return ..()
/mob/living/simple_mob/vore/hostile/morph/Destroy()
@@ -70,7 +75,7 @@
/mob/living/simple_mob/vore/hostile/morph/examine(mob/user)
if(morphed)
. = form.examine(user)
- if(get_dist(user, src) <= 3)
+ if(get_dist(user, src) <= 3 && !resting)
. += "[form] doesn't look quite right..."
else
. = ..()
@@ -193,6 +198,22 @@
var/temp_state = icon_state
..()
icon_state = temp_state
+ //Stolen from protean blobs, ambush noms from resting! Doesn't hide you any better, but makes noms sneakier.
+ if(resting)
+ plane = ABOVE_OBJ_PLANE
+ to_chat(src,"Your form settles in, appearing more 'normal'... laying in wait.")
+ else
+ plane = MOB_PLANE
+ to_chat(src,"Your form quivers back to life, allowing you to move again!")
+ if(can_be_drop_pred) //Toggleable in vore panel
+ var/list/potentials = living_mobs(0)
+ if(potentials.len)
+ var/mob/living/target = pick(potentials)
+ if(istype(target) && target.devourable && target.can_be_drop_prey && vore_selected)
+ if(target.buckled)
+ target.buckled.unbuckle_mob(target, force = TRUE)
+ target.forceMove(vore_selected)
+ to_chat(target,"\The [src] quickly engulfs you, [vore_selected.vore_verb]ing you into their [vore_selected.name]!")
else
..()
@@ -215,3 +236,88 @@
src.transform = M
else
..()
+
+/mob/living/simple_mob/vore/hostile/morph/proc/take_over_prey()
+ set name = "Take Over Prey"
+ set category = "Abilities"
+ set desc = "Take command of your prey's body."
+ if(morphed)
+ to_chat(src, "You must restore to your original form first!")
+ return
+ var/list/possible_mobs = list()
+ for(var/obj/belly/B in src.vore_organs)
+ for(var/mob/living/carbon/human/H in B)
+ if(ishuman(H) && H.ckey)
+ possible_mobs += H
+ else
+ continue
+ var/mob/living/carbon/human/M
+ var/input = tgui_input_list(src, "Select a mob to take over:", "Take Over Prey", possible_mobs)
+ if(!input)
+ return
+ M = input
+ if(!M)
+ return
+ if(M.resleeve_lock && ckey != M.resleeve_lock)
+ to_chat(src, "\The [M] cannot be impersonated!")
+ return
+ if(tgui_alert(src, "You selected [M] to attempt to take over. Are you sure?", "Take Over Prey",list("No","Yes")) == "Yes")
+ log_admin("[key_name_admin(src)] offered [M] to swap bodies as a morph.")
+ if(tgui_alert(M, "\The [src] has elected to attempt to take over your body and control you. Is this something you will allow to happen?", "Allow Morph To Take Over",list("No","Yes")) == "Yes")
+ if(tgui_alert(M, "Are you sure? The only way to undo this on your own is to OOC Escape.", "Allow Morph To Take Over",list("No","Yes")) == "Yes")
+ original_ckey = ckey
+ log_and_message_admins("[key_name_admin(src)] has swapped bodies with [key_name_admin(M)] as a morph at [get_area(src)] - [COORD(src)].")
+ new /mob/living/simple_mob/vore/hostile/morph/dominated_prey(M.vore_selected, M.ckey, src, M)
+ else
+ to_chat(src, "\The [M] declined your request for control.")
+ else
+ to_chat(src, "\The [M] declined your request for control.")
+
+/mob/living/simple_mob/vore/hostile/morph/dominated_prey
+ name = "subservient node"
+ color = "#171717"
+ digestable = 0
+ devourable = 0
+ var/mob/living/simple_mob/vore/hostile/morph/parent_morph
+ var/mob/living/carbon/human/prey_body
+
+
+/mob/living/simple_mob/vore/hostile/morph/dominated_prey/New(loc, pckey, parent, prey)
+ . = ..()
+ if(pckey)
+ prey_ckey = pckey
+ parent_morph = parent
+ prey_body = prey
+ prey_body.forceMove(get_turf(parent_morph))
+ ckey = prey_ckey
+ prey_body.ckey = parent_morph.original_ckey
+ parent_morph.forceMove(src)
+ name = "[prey_body.name]"
+ to_chat(prey_body, "You have completely assumed the form of [prey_body]. Your form is now unable to change anymore until you restore control back to them. You can do this by 'ejecting' them from your [prey_body.vore_selected]. This will not actually release them from your body in this state, but instead return control to them, and restore you to your original form.")
+ else
+ qdel(src)
+
+/mob/living/simple_mob/vore/hostile/morph/dominated_prey/death(gibbed)
+ . = ..()
+ undo_prey_takeover(FALSE)
+
+
+/mob/living/simple_mob/vore/hostile/morph/dominated_prey/Destroy()
+ . = ..()
+ parent_morph = null
+ prey_body = null
+
+/mob/living/simple_mob/vore/hostile/morph/dominated_prey/proc/undo_prey_takeover(ooc_escape)
+ if(ooc_escape)
+ prey_body.forceMove(get_turf(src))
+ parent_morph.forceMove(get_turf(src))
+ parent_morph.ckey = parent_morph.original_ckey
+ prey_body.ckey = prey_ckey
+ log_and_message_admins("[key_name_admin(prey_body)] used the OOC escape button to get out of [key_name_admin(parent_morph)]. They have been returned to their original bodies. [ADMIN_FLW(src)]")
+ else
+ parent_morph.forceMove(get_turf(prey_body))
+ parent_morph.ckey = parent_morph.original_ckey
+ prey_body.ckey = prey_ckey
+ prey_body.forceMove(parent_morph.vore_selected)
+ log_and_message_admins("[key_name_admin(prey_body)] and [key_name_admin(parent_morph)] have been returned to their original bodies. [get_area(src)] - [COORD(src)].")
+ qdel(src)
diff --git a/code/modules/vore/eating/belly_obj_vr.dm b/code/modules/vore/eating/belly_obj_vr.dm
index f96af5c204c..10d1dd44f32 100644
--- a/code/modules/vore/eating/belly_obj_vr.dm
+++ b/code/modules/vore/eating/belly_obj_vr.dm
@@ -354,6 +354,10 @@
if (!(M in contents))
return 0 // They weren't in this belly anyway
+ if(istype(M, /mob/living/simple_mob/vore/hostile/morph/dominated_prey))
+ var/mob/living/simple_mob/vore/hostile/morph/dominated_prey/p = M
+ p.undo_prey_takeover(FALSE)
+ return 0
for(var/mob/living/L in M.contents)
L.muffled = 0
for(var/obj/item/weapon/holder/H in M.contents)
diff --git a/code/modules/vore/eating/living_vr.dm b/code/modules/vore/eating/living_vr.dm
index ffaaa5ec09c..7a9cab7a2b6 100644
--- a/code/modules/vore/eating/living_vr.dm
+++ b/code/modules/vore/eating/living_vr.dm
@@ -405,6 +405,11 @@
//You're in a belly!
if(isbelly(loc))
+ //You've been taken over by a morph
+ if(istype(src, /mob/living/simple_mob/vore/hostile/morph/dominated_prey))
+ var/mob/living/simple_mob/vore/hostile/morph/dominated_prey/s = src
+ s.undo_prey_takeover(TRUE)
+ return
var/obj/belly/B = loc
var/confirm = tgui_alert(src, "You're in a mob. Don't use this as a trick to get out of hostile animals. This is for escaping from preference-breaking and if you're otherwise unable to escape from endo (pred AFK for a long time).", "Confirmation", list("Okay", "Cancel"))
if(confirm != "Okay" || loc != B)
@@ -445,7 +450,6 @@
crystal.bound_mob = null
crystal.bound_mob = capture_crystal = 0
log_and_message_admins("[key_name(src)] used the OOC escape button to get out of [crystal] owned by [crystal.owner]. [ADMIN_FLW(src)]")
-
//Don't appear to be in a vore situation
else
to_chat(src,"You aren't inside anyone, though, is the thing.")