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.")