diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index f4a9088c345..43933ce6127 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -77,6 +77,8 @@
#define isguardian(A) (istype(A, /mob/living/simple_animal/hostile/guardian))
+#define ishostile(A) (istype(A, /mob/living/simple_animal/hostile))
+
#define islimb(A) (istype(A, /obj/item/bodypart))
#define isbot(A) (istype(A, /mob/living/simple_animal/bot))
diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
index b7fe9f9fd2f..051bdb1add5 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
@@ -3,6 +3,7 @@
icon_state = "alien_s"
pass_flags = PASSTABLE
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/xeno = 5, /obj/item/stack/sheet/animalhide/xeno = 1)
+ limb_destroyer = 1
var/obj/item/r_store = null
var/obj/item/l_store = null
var/caste = ""
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index 4fc25452cda..31a7cc60e3a 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -103,4 +103,26 @@
"[src] devours you!")
C.forceMove(src)
stomach_contents.Add(C)
- add_logs(src, C, "devoured")
\ No newline at end of file
+ add_logs(src, C, "devoured")
+
+/mob/living/carbon/proc/dismembering_strike(mob/living/attacker, dam_zone)
+ if(!attacker.limb_destroyer || !has_limbs)
+ return dam_zone
+ var/obj/item/bodypart/affecting
+ if(dam_zone && attacker.client)
+ affecting = get_bodypart(ran_zone(dam_zone))
+ else
+ var/list/things_to_ruin = shuffle(bodyparts.Copy())
+ for(var/B in things_to_ruin)
+ var/obj/item/bodypart/bodypart = B
+ if(bodypart.body_zone == "head" || bodypart.body_zone == "chest")
+ continue
+ if(!affecting || ((affecting.get_damage() / affecting.max_damage) < (bodypart.get_damage() / bodypart.max_damage)))
+ affecting = bodypart
+ if(affecting)
+ dam_zone = affecting.body_zone
+ if(affecting.get_damage() >= affecting.max_damage)
+ affecting.dismember()
+ return null
+ return affecting.body_zone
+ return dam_zone
diff --git a/code/modules/mob/living/carbon/human/human_attackalien.dm b/code/modules/mob/living/carbon/human/human_attackalien.dm
index 3f7acda2524..f3a4606fc72 100644
--- a/code/modules/mob/living/carbon/human/human_attackalien.dm
+++ b/code/modules/mob/living/carbon/human/human_attackalien.dm
@@ -19,7 +19,8 @@
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
visible_message("[M] has slashed at [src]!", \
"[M] has slashed at [src]!")
-
+ if(!dismembering_strike(M, M.zone_selected)) //Dismemberment successful
+ return 1
apply_damage(damage, BRUTE, affecting, armor_block)
if (prob(30))
visible_message("[M] has wounded [src]!", \
diff --git a/code/modules/mob/living/carbon/human/human_attackpaw.dm b/code/modules/mob/living/carbon/human/human_attackpaw.dm
index 63dcd230169..4c666a86799 100644
--- a/code/modules/mob/living/carbon/human/human_attackpaw.dm
+++ b/code/modules/mob/living/carbon/human/human_attackpaw.dm
@@ -6,6 +6,9 @@
..() //shaking
return 0
+ if(M.limb_destroyer)
+ dismembering_strike(M, affecting.body_zone)
+
if(can_inject(M, 1, affecting))//Thick suits can stop monkey bites.
if(..()) //successful monkey bite, this handles disease contraction.
var/damage = rand(1, 3)
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 1727fe4f0de..d8d73767278 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -271,7 +271,9 @@
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
if(check_shields(damage, "the [M.name]", null, MELEE_ATTACK, M.armour_penetration))
return 0
- var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")
+ var/dam_zone = dismembering_strike(M, pick("chest", "l_hand", "r_hand", "l_leg", "r_leg"))
+ if(!dam_zone) //Dismemberment successful
+ return 1
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
var/armor = run_armor_check(affecting, "melee", armour_penetration = M.armour_penetration)
apply_damage(damage, M.melee_damage_type, affecting, armor)
@@ -301,7 +303,9 @@
if(check_shields(damage, "the [M.name]"))
return 0
- var/dam_zone = pick("head", "chest", "l_arm", "r_arm", "l_leg", "r_leg", "groin")
+ var/dam_zone = dismembering_strike(M, pick("head", "chest", "l_arm", "r_arm", "l_leg", "r_leg"))
+ if(!dam_zone) //Dismemberment successful
+ return 1
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
var/armor_block = run_armor_check(affecting, "melee")
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index b32fce8c02b..6e518ead263 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -970,6 +970,8 @@
H.visible_message("[M] has [atk_verb]ed [H]!", \
"[M] has [atk_verb]ed [H]!")
+ if(M.limb_destroyer)
+ H.dismembering_strike(M, affecting.body_zone)
H.apply_damage(damage, BRUTE, affecting, armor_block)
add_logs(M, H, "punched")
if((H.stat != DEAD) && damage >= M.dna.species.punchstunthreshold)
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index e56d5bc7dd6..51fc556a6cb 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -41,6 +41,8 @@
var/bloodcrawl = 0 //0 No blood crawling, BLOODCRAWL for bloodcrawling, BLOODCRAWL_EAT for crawling+mob devour
var/holder = null //The holder for blood crawling
var/ventcrawler = 0 //0 No vent crawling, 1 vent crawling in the nude, 2 vent crawling always
+ var/limb_destroyer = 0 //1 Sets AI behavior that allows mobs to target and dismember limbs with their basic attack.
+
var/floating = 0
var/mob_size = MOB_SIZE_HUMAN
var/metabolism_efficiency = 1 //more or less efficiency to metabolize helpful/harmful reagents and regulate body temperature..
diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm
index 07a52affb0f..fa4f0104228 100644
--- a/code/modules/mob/living/simple_animal/hostile/hostile.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm
@@ -41,7 +41,6 @@
var/stat_attack = 0 //Mobs with stat_attack to 1 will attempt to attack things that are unconscious, Mobs with stat_attack set to 2 will attempt to attack the dead.
var/stat_exclusive = 0 //Mobs with this set to 1 will exclusively attack things defined by stat_attack, stat_attack 2 means they will only attack corpses
var/attack_same = 0 //Set us to 1 to allow us to attack our own faction, or 2, to only ever attack our own faction
-
var/AIStatus = AI_ON //The Status of our AI, can be set to AI_ON (On, usual processing), AI_IDLE (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever)
var/atom/targets_from = null //all range/attack/etc. calculations should be done from this atom, defaults to the mob itself, useful for Vehicles and such
diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
index bb6135079d1..871e7a9d9e0 100644
--- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm
+++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
@@ -161,6 +161,7 @@
minbodytemp = 0
mob_size = MOB_SIZE_TINY
flying = 1
+ limb_destroyer = 1
speak_emote = list("states")
bubble_icon = "syndibot"
gold_core_spawnable = 1
diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm
index 123694aef90..90749a39bc0 100644
--- a/code/modules/research/xenobiology/xenobiology.dm
+++ b/code/modules/research/xenobiology/xenobiology.dm
@@ -596,7 +596,7 @@
/obj/effect/timestop/proc/unfreeze_mob(mob/living/M)
M.AdjustStunned(-10, 1, 1)
M.anchored = 0
- if(istype(M, /mob/living/simple_animal/hostile))
+ if(ishostile(M))
var/mob/living/simple_animal/hostile/H = M
H.AIStatus = initial(H.AIStatus)