diff --git a/code/modules/mob/mob_defines_vr.dm b/code/modules/mob/mob_defines_vr.dm
index df9e1f8edd2..ab1670560fb 100644
--- a/code/modules/mob/mob_defines_vr.dm
+++ b/code/modules/mob/mob_defines_vr.dm
@@ -1,3 +1,5 @@
/mob
var/vantag_hud = 0 // Do I have the HUD enabled?
- var/flying = 0 //Allows flight
\ No newline at end of file
+ var/flying = 0 //Allows flight
+ var/can_be_drop_prey = 0
+ var/can_be_drop_pred = 1 //Mobs are pred by default.
\ No newline at end of file
diff --git a/code/modules/multiz/movement.dm b/code/modules/multiz/movement.dm
index 2f0d0f76f6d..7f13cc25e92 100644
--- a/code/modules/multiz/movement.dm
+++ b/code/modules/multiz/movement.dm
@@ -352,11 +352,11 @@
"You hear something slam into \the [landing].")
playsound(loc, "punch", 25, 1, -1)
var/damage = 15 // Because wounds heal rather quickly, 15 should be enough to discourage jumping off but not be enough to ruin you, at least for the first time.
- for(var/mob/M in landing.contents) //VOREStation Edit Start
- if(M != src)
- M.visible_message("\The [src] drops onto \the [M]!")
- M.Weaken(8)
- damage = 5 //VOREStation Edit END
+ var/mob/living/carbon/human/pred = src //VOREStation Edit Start
+ var/belly = src.vore_selected
+ var/datum/belly/belly_target = pred.vore_organs[belly]
+ if(belly_target && belly_target.internal_contents.len != 0)
+ damage = 5 //VOREStation Edit End
apply_damage(rand(0, damage), BRUTE, BP_HEAD)
apply_damage(rand(0, damage), BRUTE, BP_TORSO)
apply_damage(rand(0, damage), BRUTE, BP_L_LEG)
diff --git a/code/modules/multiz/movement_vr.dm b/code/modules/multiz/movement_vr.dm
index 3f6641b38fd..227b9bac4fc 100644
--- a/code/modules/multiz/movement_vr.dm
+++ b/code/modules/multiz/movement_vr.dm
@@ -1,52 +1,46 @@
-/*/mob/handle_fall(var/turf/landing)
- for(var/mob/M in landing)
- if(M != src && M.CheckFall(src))
- return 1
- for(var/atom/A in landing)
- if(!A.CanPass(src, src.loc, 1, 0))
- return FALSE
- // TODO - Stairs should operate thru a different mechanism, not falling, to allow side-bumping.
-
- // Now lets move there!
- if(!Move(landing))
- return 1
-
- // Detect if we made a silent landing.
- if(locate(/obj/structure/stairs) in landing)
- return 1
-
- if(isopenspace(oldloc))
- oldloc.visible_message("\The [src] falls down through \the [oldloc]!", "You hear something falling through the air.")
-
- // If the turf has density, we give it first dibs
- if (landing.density && landing.CheckFall(src))
- return
-
- // First hit objects in the turf!
- for(var/atom/movable/A in landing)
- if(A != src && A.CheckFall(src))
- return
-
- // If none of them stopped us, then hit the turf itself
- landing.CheckFall(src)
-*/
-/mob/handle_fall(var/turf/landing)
+/mob/living/handle_fall(var/turf/landing)
var/mob/drop_mob= locate(/mob, loc)
- if(drop_mob)
- drop_mob.visible_message("\The [drop_mob] is dropped onto by \the [src]!")
+ if(drop_mob && drop_mob != src && ismob(drop_mob)) //Shitload of checks. This is because the game finds various ways to screw me over.
drop_mob.fall_impact(src)
// Then call parent to have us actually fall
return ..()
/mob/CheckFall(var/atom/movable/falling_atom)
return falling_atom.fall_impact(src)
-
-/mob/fall_impact(var/atom/hit_atom)
- if(ismob(hit_atom))
- var/mob/M = hit_atom
- M.visible_message("\The [src] falls onto \the [M]!")
- M.Weaken(8)
+/* //Leaving this here to show my previous iterations which failed.
+/mob/living/fall_impact(var/atom/hit_atom) //This is called even when a humanoid falls. Dunno why, it just does.
+ if(isliving(hit_atom)) //THIS WEAKENS THE PERSON FALLING & NOMS THE PERSON FALLEN ONTO. SRC is person fallen onto. hit_atom is the person falling. Confusing.
+ var/mob/living/pred = hit_atom
+ pred.visible_message("\The [pred] falls onto \the [src]! FALL IMPACT MOB")
+ pred.Weaken(8) //Stun the person you're dropping onto! You /are/ suffering massive damage for a single stun.
+ if(isliving(hit_atom) && isliving(src))
+ var/mob/living/prey = src
+ if(pred.can_be_drop_pred && prey.can_be_drop_prey) //Is person falling pred & person being fallen onto prey?
+ pred.feed_grabbed_to_self_falling_nom(pred,prey)
+ else if(prey.can_be_drop_pred && pred.can_be_drop_prey) //Is person being fallen onto pred & person falling prey
+ pred.feed_grabbed_to_self_falling_nom(prey,pred) //oh, how the tables have turned.
+*/
+/mob/zshadow/fall_impact(var/atom/hit_atom) //You actually "fall" onto their shadow, first.
+ /*
+ var/floor_below = src.loc.below //holy fuck
+ for(var/mob/M in floor_below.contents)
+ if(M && M != src) //THIS WEAKENS THE MOBS YOU'RE FALLING ONTO
+ M.visible_message("\The [src] drops onto \the [M]! FALL IMPACT SHADOW WEAKEN 8")
+ M.Weaken(8)
+ */
+ if(isliving(hit_atom)) //THIS WEAKENS THE PERSON FALLING & NOMS THE PERSON FALLEN ONTO. SRC is person fallen onto. hit_atom is the person falling. Confusing.
+ var/mob/living/pred = hit_atom
+ pred.visible_message("\The [hit_atom] falls onto \the [src]!")
+ pred.Weaken(8) //Stun the person you're dropping onto! You /are/ suffering massive damage for a single stun.
+ var/mob/living/prey = src.owner //The shadow's owner
+ if(isliving(prey))
+ if(pred.can_be_drop_pred && prey.can_be_drop_prey) //Is person falling pred & person being fallen onto prey?
+ pred.feed_grabbed_to_self_falling_nom(pred,prey)
+ else if(prey.can_be_drop_pred && pred.can_be_drop_prey) //Is person being fallen onto pred & person falling prey
+ pred.feed_grabbed_to_self_falling_nom(prey,pred) //oh, how the tables have turned.
+ else
+ prey.Weaken(8) //Just fall onto them if neither of the above apply.
/mob/proc/CanZPass(atom/A, direction)
if(z == A.z) //moving FROM this turf
diff --git a/code/modules/vore/eating/living_vr.dm b/code/modules/vore/eating/living_vr.dm
index 1a1ba7ff3fa..4b2940172ee 100644
--- a/code/modules/vore/eating/living_vr.dm
+++ b/code/modules/vore/eating/living_vr.dm
@@ -235,6 +235,8 @@
P.vore_taste = src.vore_taste
P.nif_examine = src.nif_examine
P.conceal_nif = src.conceal_nif
+ P.can_be_drop_prey = src.can_be_drop_prey
+ P.can_be_drop_pred = src.can_be_drop_pred
return 1
@@ -253,6 +255,8 @@
src.vore_taste = P.vore_taste
src.nif_examine = P.nif_examine
src.conceal_nif = P.conceal_nif
+ src.can_be_drop_prey = P.can_be_drop_prey
+ src.can_be_drop_pred = P.can_be_drop_pred
for(var/I in P.belly_prefs)
var/datum/belly/Bp = P.belly_prefs[I]
@@ -511,3 +515,50 @@
B.internal_contents += src
return
return
+
+/mob/living/proc/feed_grabbed_to_self_falling_nom(var/mob/living/user, var/mob/living/prey)
+ var/belly = user.vore_selected
+ return perform_the_falling_nom(user, prey, user, belly)
+
+/mob/living/proc/perform_the_falling_nom(var/mob/living/user, var/mob/living/prey, var/mob/living/pred, var/belly) //For dropnoms.
+ //Sanity
+ belly = pred.vore_selected
+ if(!user || !prey || !pred || !belly || !(belly in pred.vore_organs))
+ log_debug("[user] attempted to feed [prey] to [pred], via [belly] but it went wrong.")
+ return
+
+ // The belly selected at the time of noms
+ var/datum/belly/belly_target = pred.vore_organs[belly]
+ var/success_msg = "ERROR: Vore message couldn't be created. Notify a dev. (sc)"
+
+ //Final distance check. Time has passed, menus have come and gone. Can't use do_after adjacent because doesn't behave for held micros
+ var/user_to_pred = get_dist(get_turf(user),get_turf(pred))
+ var/user_to_prey = get_dist(get_turf(user),get_turf(prey))
+
+ if(user_to_pred > 1 || user_to_prey > 1)
+ return 0
+
+ // Prepare messages
+ if(user == pred) //Feeding someone to yourself
+ success_msg = text("[] manages to [] [] into their []!",pred,lowertext(belly_target.vore_verb),prey,lowertext(belly_target.name))
+ else //Feeding someone to another person. This shouldn't happen.
+ success_msg = text("[] manages to make [] [] [] into their []!",user,pred,lowertext(belly_target.vore_verb),prey,lowertext(belly_target.name))
+
+ user.visible_message(success_msg)
+ if(belly_target.vore_sound)
+ playsound(user, belly_target.vore_sound, 100, 1)
+
+ // Actually shove prey into the belly.
+ belly_target.nom_mob(prey, user)
+ user.update_icons()
+
+ // Flavor handling
+ if(belly_target.can_taste && prey.get_taste_message(0))
+ to_chat(belly_target.owner, "[prey] tastes of [prey.get_taste_message(0)].")
+
+ // Inform Admins
+ if (pred == user)
+ msg_admin_attack("[key_name(pred)] ate [key_name(prey)] via dropnoms!. ([pred ? "JMP" : "null"])")
+ else
+ msg_admin_attack("[key_name(user)] forced [key_name(pred)] to eat [key_name(prey)] via dropnoms! ([pred ? "JMP" : "null"])")
+ return 1
\ No newline at end of file
diff --git a/code/modules/vore/eating/vore_vr.dm b/code/modules/vore/eating/vore_vr.dm
index 024e0ad4afb..0440e927dee 100644
--- a/code/modules/vore/eating/vore_vr.dm
+++ b/code/modules/vore/eating/vore_vr.dm
@@ -46,6 +46,8 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
var/vore_taste
var/conceal_nif
var/nif_examine
+ var/can_be_drop_prey
+ var/can_be_drop_pred
//Mechanically required
var/path
@@ -107,6 +109,8 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
S["vore_taste"] >> vore_taste
S["conceal_nif"] >> conceal_nif
S["nif_examine"] >> nif_examine
+ S["can_be_drop_prey"] >> can_be_drop_prey
+ S["can_be_drop_pred"] >> can_be_drop_pred
if(isnull(digestable))
digestable = 1
@@ -127,5 +131,7 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
S["vore_taste"] << vore_taste
S["conceal_nif"] << conceal_nif
S["nif_examine"] << nif_examine
+ S["can_be_drop_prey"] << can_be_drop_prey
+ S["can_be_drop_pred"] << can_be_drop_pred
return 1
diff --git a/code/modules/vore/eating/vorepanel_vr.dm b/code/modules/vore/eating/vorepanel_vr.dm
index b26a0d6affe..8e0d411eb4b 100644
--- a/code/modules/vore/eating/vorepanel_vr.dm
+++ b/code/modules/vore/eating/vorepanel_vr.dm
@@ -284,6 +284,9 @@
dat += "
Set NIF concealment" //These two get their own, custom row.
dat += "Set NIF Examine Message."
+ dat += "
Toggle Drop-nom Prey Mode" //These two get their own, custom row, too.
+ dat += "Toggle Drop-nom Pred Mode"
+
//Returns the dat html to the vore_look
return dat
@@ -751,6 +754,26 @@
else //Returned null
return 0
+ if(href_list["toggle_dropnom_pred"])
+ var/choice = alert(user, "You are currently [user.can_be_drop_pred ? " able to eat prey that fall from above or that you fall onto" : "not able to eat prey that fall from above or that you fall onto."]", "", "Be Pred", "Cancel", "Don't be Pred")
+ switch(choice)
+ if("Cancel")
+ return 0
+ if("Be Pred")
+ user.can_be_drop_pred = 1
+ if("Don't be Pred")
+ user.can_be_drop_pred = 0
+
+ if(href_list["toggle_dropnom_prey"])
+ var/choice = alert(user, "You are currently [user.can_be_drop_prey ? "able to be eaten." : "not able to be eaten."]", "", "Be Prey", "Cancel", "Don't Be Prey")
+ switch(choice)
+ if("Cancel")
+ return 0
+ if("Be Prey")
+ user.can_be_drop_prey = 1
+ if("Don't Be Prey")
+ user.can_be_drop_prey = 0
+
if(href_list["toggledg"])
var/choice = alert(user, "This button is for those who don't like being digested. It can make you undigestable. Don't abuse this button by toggling it back and forth to extend a scene or whatever, or you'll make the admins cry. Digesting you is currently: [user.digestable ? "Allowed" : "Prevented"]", "", "Allow Digestion", "Cancel", "Prevent Digestion")
switch(choice)