diff --git a/code/modules/mob/living/carbon/alien/alien_defenses.dm b/code/modules/mob/living/carbon/alien/alien_defenses.dm
index 95ed75f18a0..16b7a17721c 100644
--- a/code/modules/mob/living/carbon/alien/alien_defenses.dm
+++ b/code/modules/mob/living/carbon/alien/alien_defenses.dm
@@ -49,6 +49,8 @@ In all, this is a lot like the monkey code. /N
/mob/living/carbon/alien/attack_hand(mob/living/carbon/human/M as mob)
if(..()) //to allow surgery to return properly.
return 0
+ if(istype(src,/mob/living/carbon/alien/humanoid))
+ return 0 //this is horrible but 100% necessary
switch(M.a_intent)
if("help")
diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
index 3d346f83941..c054f766dac 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
@@ -254,18 +254,7 @@
help_shake_act(M)
if ("grab")
- if (M == src || anchored)
- return
- var/obj/item/weapon/grab/G = new /obj/item/weapon/grab(M, src)
-
- M.put_in_active_hand(G)
-
- G.synch()
-
- LAssailant = M
-
- playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
- visible_message("[M] has grabbed [src] passively!")
+ grabbedby(M)
if ("harm")
M.do_attack_animation(src)
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 925636dbba5..73244f1a6c5 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -27,34 +27,47 @@ mob/living
if(germ_level < GERM_LEVEL_MOVE_CAP && prob(8))
germ_level++
+#define STOMACH_ATTACK_DELAY 4
+
+/mob/living/carbon/var/last_stomach_attack //defining this here because no one would look in carbon_defines for it
+
/mob/living/carbon/relaymove(var/mob/user, direction)
if(user in src.stomach_contents)
- if(prob(40))
- for(var/mob/M in hearers(4, src))
- if(M.client)
- M.show_message(text("\red You hear something rumbling inside [src]'s stomach..."), 2)
- var/obj/item/I = user.get_active_hand()
- if(I && I.force)
- var/d = rand(round(I.force / 4), I.force)
- if(istype(src, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = src
- var/obj/item/organ/external/organ = H.get_organ("chest")
- if (istype(organ))
- if(organ.take_damage(d, 0))
- H.UpdateDamageIcon()
- H.updatehealth()
- else
- src.take_organ_damage(d)
- for(var/mob/M in viewers(user, null))
- if(M.client)
- M.show_message(text("\red [user] attacks [src]'s stomach wall with the [I.name]!"), 2)
- playsound(user.loc, 'sound/effects/attackblob.ogg', 50, 1)
+ if(last_stomach_attack + STOMACH_ATTACK_DELAY > world.time) return
- if(prob(src.getBruteLoss() - 50))
- for(var/atom/movable/A in stomach_contents)
- A.loc = loc
- stomach_contents.Remove(A)
- src.gib()
+ last_stomach_attack = world.time
+ for(var/mob/M in hearers(4, src))
+ if(M.client)
+ M.show_message(text("\red You hear something rumbling inside [src]'s stomach..."), 2)
+
+ var/obj/item/I = user.get_active_hand()
+ if(I && I.force)
+ var/d = rand(round(I.force / 4), I.force)
+
+ if(istype(src, /mob/living/carbon/human))
+ var/mob/living/carbon/human/H = src
+ var/obj/item/organ/external/organ = H.get_organ("chest")
+ if (istype(organ))
+ if(organ.take_damage(d, 0))
+ H.UpdateDamageIcon()
+
+ H.updatehealth()
+
+ else
+ src.take_organ_damage(d)
+
+ for(var/mob/M in viewers(user, null))
+ if(M.client)
+ M.show_message(text("\red [user] attacks [src]'s stomach wall with the [I.name]!"), 2)
+ playsound(user.loc, 'sound/effects/attackblob.ogg', 50, 1)
+
+ if(prob(src.getBruteLoss() - 50))
+ for(var/atom/movable/A in stomach_contents)
+ A.loc = loc
+ stomach_contents.Remove(A)
+ src.gib()
+
+#undef STOMACH_ATTACK_DELAY
/mob/living/carbon/gib()
for(var/mob/M in src)
diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm
index b04c0832350..a15cf352e25 100644
--- a/code/modules/mob/mob_grab.dm
+++ b/code/modules/mob/mob_grab.dm
@@ -1,6 +1,13 @@
#define UPGRADE_COOLDOWN 40
#define UPGRADE_KILL_TIMER 100
+//times it takes for a mob to eat
+#define EAT_TIME_XENO 30
+#define EAT_TIME_FAT 100
+
+//time it takes for a mob to be eaten (in deciseconds) (overrides mob eat time)
+#define EAT_TIME_MOUSE 30
+
/obj/item/weapon/grab
name = "grab"
flags = NOBLUDGEON | ABSTRACT
@@ -187,22 +194,47 @@
if(!affecting)
return
- if(M == affecting)
+ if(M == affecting) //what the actual fuck is this
s_click(hud)
return
- if(M == assailant && state >= GRAB_AGGRESSIVE)
- if( (ishuman(user) && (FAT in user.mutations) && iscarbon(affecting) ) || ( isalien(user) && iscarbon(affecting) ) || ( istype(user,/mob/living/carbon/human/kidan) && istype(affecting,/mob/living/carbon/monkey/diona) ) || ( ishuman(user) && user.get_species() == "Tajaran" && istype(affecting,/mob/living/simple_animal/mouse) ) )
+
+ if(M == assailant && state >= GRAB_AGGRESSIVE) //no eatin unless you have an agressive grab
+ if(checkvalid(user, affecting)) //wut
var/mob/living/carbon/attacker = user
user.visible_message("[user] is attempting to devour \the [affecting]!")
- if(istype(user, /mob/living/carbon/alien/humanoid/hunter) || istype(affecting, /mob/living/simple_animal/mouse)) //mice are easy to eat
- if(!do_mob(user, affecting)||!do_after(user, 30)) return
- else
- if(!do_mob(user, affecting)||!do_after(user, 100)) return
+
+ if(!do_mob(user, affecting) || !do_after(user, checktime(user, affecting))) return
+
user.visible_message("[user] devours \the [affecting]!")
- affecting.loc = user
- attacker.stomach_contents.Add(affecting)
+
+ affecting.loc = user //add the mob to the user
+ attacker.stomach_contents.Add(affecting) //list keeping
+
del(src)
+/obj/item/weapon/grab/proc/checkvalid(var/mob/attacker, var/mob/prey) //does all the checking for the attack proc to see if a mob can eat another with the grab
+ if(ishuman(attacker) && (FAT in attacker.mutations) && iscarbon(prey)) //Fat people eating carbon mobs
+ return 1
+
+ if(isalien(attacker) && iscarbon(prey)) //Xenomorphs eating carbon mobs
+ return 1
+
+ if(ishuman(attacker) && attacker.get_species() == "Kidan" && istype(prey,/mob/living/carbon/monkey/diona)) //Kidan eating nymphs
+ return 1
+
+ if(ishuman(attacker) && attacker.get_species() == "Tajaran" && istype(prey,/mob/living/simple_animal/mouse)) //Tajaran eating mice. Meow!
+ return 1
+
+ return 0
+
+/obj/item/weapon/grab/proc/checktime(var/mob/attacker, var/mob/prey) //Returns the time the attacker has to wait before they eat the prey
+ if(isalien(attacker))
+ return EAT_TIME_XENO //xenos get a speed boost
+
+ if(istype(prey,/mob/living/simple_animal/mouse)) //mice get eaten at xeno-eating-speed regardless
+ return EAT_TIME_MOUSE
+
+ return EAT_TIME_FAT //if it doesn't fit into the above, it's probably a fat guy, take EAT_TIME_FAT to do it
/obj/item/weapon/grab/dropped()
del(src)
@@ -211,3 +243,8 @@
/obj/item/weapon/grab/Destroy()
del(hud)
..()
+
+#undef EAT_TIME_XENO
+#undef EAT_TIME_FAT
+
+#undef EAT_TIME_MOUSE
\ No newline at end of file