diff --git a/code/__DEFINES/monkeys.dm b/code/__DEFINES/monkeys.dm
new file mode 100644
index 00000000000..76f7ea850c3
--- /dev/null
+++ b/code/__DEFINES/monkeys.dm
@@ -0,0 +1,38 @@
+//Monkey defines, placed here so they can be read by other things!
+
+//Mode defines
+#define MONKEY_IDLE 0 // idle
+#define MONKEY_HUNT 1 // found target, hunting
+#define MONKEY_FLEE 2 // free from enemies
+#define MONKEY_DISPOSE 3 // dump body in disposals
+
+#define MONKEY_FLEE_HEALTH 50 // below this health value the monkey starts to flee from enemies
+#define MONKEY_ENEMY_VISION 9 // how close an enemy must be to trigger aggression
+#define MONKEY_FLEE_VISION 4 // how close an enemy must be before it triggers flee
+#define MONKEY_ITEM_SNATCH_DELAY 25 // How long does it take the item to be taken from a mobs hand
+#define MONKEY_CUFF_RETALIATION_PROB 20 // Probability monkey will aggro when cuffed
+#define MONKEY_SYRINGE_RETALIATION_PROB 20 // Probability monkey will aggro when syringed
+
+// Probability per Life tick that the monkey will:
+#define MONKEY_RESIST_PROB 50 // resist out of restraints
+ // when the monkey is idle
+#define MONKEY_PULL_AGGRO_PROB 5 // aggro against the mob pulling it
+#define MONKEY_PICKUP_PROB 5 // if not currently getting an item, pickup an item around it
+#define MONKEY_STEAL_PROB 5 // if not currently getting an item, steal an item from someone around it
+ // when the monkey is hunting
+#define MONKEY_ATTACK_DISARM_PROB 50 // disarm an armed attacker
+#define MONKEY_WEAPON_PROB 20 // if not currently getting an item, search for a weapon around it
+#define MONKEY_RECRUIT_PROB 25 // recruit a monkey near it
+#define MONKEY_SWITCH_TARGET_PROB 25 // switch targets if it sees another enemy
+
+#define MONKEY_RETALIATE_HARM_PROB 95 // probability for the monkey to aggro when attacked with harm intent
+#define MONKEY_RETALIATE_DISARM_PROB 20 // probability for the monkey to aggro when attacked with disarm intent
+
+#define MONKEY_HATRED_AMOUNT 4 // amount of aggro to add to an enemy when they attack user
+#define MONKEY_HATRED_REDUCTION_PROB 25 // probability of reducing aggro by one when the monkey attacks
+
+// how many Life ticks the monkey will fail to:
+#define MONKEY_HUNT_FRUSTRATION_LIMIT 8 // Chase after an enemy before giving up
+#define MONKEY_DISPOSE_FRUSTRATION_LIMIT 16 // Dispose of a body before giving up
+
+#define MONKEY_AGGRESSIVE_MVM_PROB 1 // If you mass edit monkies to be aggressive. there is a small chance of in-fighting
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm
index ba86befd06e..f09b2847b9d 100644
--- a/code/game/objects/items/weapons/handcuffs.dm
+++ b/code/game/objects/items/weapons/handcuffs.dm
@@ -29,7 +29,13 @@
user << "Uh... how do those things work?!"
apply_cuffs(user,user)
return
-
+
+ // chance of monkey retaliation
+ if(istype(C, /mob/living/carbon/monkey) && prob(MONKEY_CUFF_RETALIATION_PROB))
+ var/mob/living/carbon/monkey/M
+ M = C
+ M.retaliate(user)
+
if(!C.handcuffed)
if(C.get_num_arms() >= 2 || C.get_arm_ignore())
C.visible_message("[user] is trying to put [src.name] on [C]!", \
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 9cb27e4a1ac..bf1385acb8e 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -213,6 +213,18 @@
..() //shaking
return 0
+ if(M.a_intent == INTENT_DISARM) //Always drop item in hand, if no item, get stunned instead.
+ if(get_active_held_item() && drop_item())
+ playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1)
+ visible_message("[M] disarmed [src]!", \
+ "[M] disarmed [src]!")
+ else if(!M.client || prob(5)) // only natural monkeys get to stun reliably, (they only do it occasionaly)
+ playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
+ Weaken(5)
+ add_logs(M, src, "tackled")
+ visible_message("[M] has tackled down [src]!", \
+ "[M] has tackled down [src]!")
+
if(M.limb_destroyer)
dismembering_strike(M, affecting.body_zone)
diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm
index 5e79e85c99c..75ef76eb08e 100644
--- a/code/modules/mob/living/carbon/human/inventory.dm
+++ b/code/modules/mob/living/carbon/human/inventory.dm
@@ -1,16 +1,6 @@
/mob/living/carbon/human/can_equip(obj/item/I, slot, disable_warning = 0)
return dna.species.can_equip(I, slot, disable_warning, src)
-
-/mob/living/carbon/human/proc/equip_in_one_of_slots(obj/item/I, list/slots, qdel_on_fail = 1)
- for(var/slot in slots)
- if(equip_to_slot_if_possible(I, slots[slot], qdel_on_fail = 0, disable_warning = TRUE))
- return slot
- if(qdel_on_fail)
- qdel(I)
- return null
-
-
// Return the item currently in the slot ID
/mob/living/carbon/human/get_item_by_slot(slot_id)
switch(slot_id)
diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm
index 891a62cab9e..bb7ff6f45b6 100644
--- a/code/modules/mob/living/carbon/inventory.dm
+++ b/code/modules/mob/living/carbon/inventory.dm
@@ -14,6 +14,13 @@
return legcuffed
return null
+/mob/living/carbon/proc/equip_in_one_of_slots(obj/item/I, list/slots, qdel_on_fail = 1)
+ for(var/slot in slots)
+ if(equip_to_slot_if_possible(I, slots[slot], qdel_on_fail = 0, disable_warning = TRUE))
+ return slot
+ if(qdel_on_fail)
+ qdel(I)
+ return null
//This is an UNSAFE proc. Use mob_can_equip() before calling this one! Or rather use equip_to_slot_if_possible() or advanced_equip_to_slot_if_possible()
/mob/living/carbon/equip_to_slot(obj/item/I, slot)
diff --git a/code/modules/mob/living/carbon/monkey/combat.dm b/code/modules/mob/living/carbon/monkey/combat.dm
new file mode 100644
index 00000000000..8ebd2216186
--- /dev/null
+++ b/code/modules/mob/living/carbon/monkey/combat.dm
@@ -0,0 +1,457 @@
+
+/mob/living/carbon/monkey
+ var/aggressive=0 // set to 1 using VV for an angry monkey
+ var/frustration=0
+ var/pickupTimer=0
+ var/list/enemies = list()
+ var/mob/living/target
+ var/obj/item/pickupTarget
+ var/mode = MONKEY_IDLE
+ var/list/myPath = list()
+ var/list/blacklistItems = list()
+ var/maxStepsTick = 6
+ var/best_force = 0
+ var/martial_art = new/datum/martial_art
+ var/resisting = FALSE
+ var/pickpocketing = FALSE
+ var/disposing_body = FALSE
+ var/obj/machinery/disposal/bodyDisposal = null
+
+/mob/living/carbon/monkey/proc/IsStandingStill()
+ return resisting || pickpocketing || disposing_body
+
+// blocks
+// taken from /mob/living/carbon/human/interactive/
+/mob/living/carbon/monkey/proc/walk2derpless(target)
+ if(!target || IsStandingStill())
+ return 0
+
+ if(myPath.len <= 0)
+ myPath = get_path_to(src, get_turf(target), /turf/proc/Distance, MAX_RANGE_FIND + 1, 250,1)
+
+ if(myPath)
+ if(myPath.len > 0)
+ for(var/i = 0; i < maxStepsTick; ++i)
+ if(!IsDeadOrIncap())
+ if(myPath.len >= 1)
+ walk_to(src,myPath[1],0,5)
+ myPath -= myPath[1]
+ return 1
+
+ // failed to path correctly so just try to head straight for a bit
+ walk_to(src,get_turf(target),0,5)
+ sleep(1)
+ walk_to(src,0)
+
+ return 0
+
+// taken from /mob/living/carbon/human/interactive/
+/mob/living/carbon/monkey/proc/IsDeadOrIncap(checkDead = TRUE)
+ if(!canmove)
+ return 1
+ if(health <= 0 && checkDead)
+ return 1
+ if(paralysis)
+ return 1
+ if(stunned)
+ return 1
+ if(stat)
+ return 1
+ return 0
+
+/mob/living/carbon/monkey/proc/equip_item(var/obj/item/I)
+
+ if(I.loc == src)
+ return TRUE
+
+ if(I.anchored)
+ blacklistItems[I] ++
+ return FALSE
+
+ // WEAPONS
+ if(istype(I, /obj/item/weapon))
+ var/obj/item/weapon/W = I
+ if(W.force >= best_force)
+ put_in_hands(W)
+ best_force = W.force
+ return TRUE
+
+ // CLOTHING
+ else if(istype(I,/obj/item/clothing))
+ var/obj/item/clothing/C = I
+ monkeyDrop(C)
+ addtimer(CALLBACK(src, .proc/pickup_and_wear, C), 5)
+ return TRUE
+
+ // EVERYTHING ELSE
+ else
+ if(!get_item_for_held_index(1) || !get_item_for_held_index(2))
+ put_in_hands(I)
+ return TRUE
+
+ blacklistItems[I] ++
+ return FALSE
+
+/mob/living/carbon/monkey/proc/pickup_and_wear(var/obj/item/clothing/C)
+ if(!equip_to_appropriate_slot(C))
+ monkeyDrop(get_item_by_slot(C)) // remove the existing item if worn
+ sleep(5)
+ equip_to_appropriate_slot(C)
+
+/mob/living/carbon/monkey/resist_restraints()
+ var/obj/item/I = null
+ if(handcuffed)
+ I = handcuffed
+ else if(legcuffed)
+ I = legcuffed
+ if(I)
+ changeNext_move(CLICK_CD_BREAKOUT)
+ last_special = world.time + CLICK_CD_BREAKOUT
+ cuff_resist(I)
+
+/mob/living/carbon/monkey/proc/should_target(var/mob/living/L)
+
+ if(L == src)
+ return 0
+
+ if(enemies[L])
+ return 1
+
+ // target non-monkey mobs when aggressive, with a small probability of monkey v monkey
+ if(aggressive && (!istype(L, /mob/living/carbon/monkey/) || prob(MONKEY_AGGRESSIVE_MVM_PROB)))
+ return 1
+
+ return 0
+
+/mob/living/carbon/monkey/proc/handle_combat()
+
+ if(on_fire || buckled || restrained())
+ if(!resisting && prob(MONKEY_RESIST_PROB))
+ resisting = TRUE
+ walk_to(src,0)
+ resist()
+ else
+ resisting = FALSE
+
+
+ if(IsDeadOrIncap())
+ return TRUE
+
+ // have we been disarmed
+ if(!locate(/obj/item/weapon) in held_items)
+ best_force = 0
+
+ if(restrained() || blacklistItems[pickupTarget])
+ pickupTarget = null
+
+ if(!resisting && pickupTarget)
+ pickupTimer++
+
+ // next to target
+ if(Adjacent(pickupTarget) || Adjacent(pickupTarget.loc))
+ addtimer(CALLBACK(src, .proc/walk2derpless, pickupTarget.loc), 0)
+
+ // who cares about these items, i want that one!
+ drop_all_held_items()
+
+ // on floor
+ if(isturf(pickupTarget.loc))
+ equip_item(pickupTarget)
+ pickupTarget = null
+ pickupTimer = 0
+
+ // in someones hand
+ else if(ismob(pickupTarget.loc))
+ var/mob/M = pickupTarget.loc
+ if(!pickpocketing)
+ pickpocketing = TRUE
+ M.visible_message("[src] starts trying to take [pickupTarget] from [M]", "[src] tries to take [pickupTarget]!")
+ addtimer(CALLBACK(src, .proc/pickpocket, M), 0)
+
+ else
+ if(pickupTimer >= 8)
+ blacklistItems[pickupTarget] ++
+ pickupTarget = null
+ pickupTimer = 0
+ else
+ addtimer(CALLBACK(src, .proc/walk2derpless, pickupTarget.loc), 0)
+
+ return TRUE
+
+ // nuh uh you don't pull me!
+ if(pulledby && (mode != MONKEY_IDLE || prob(MONKEY_PULL_AGGRO_PROB)))
+ if(Adjacent(pulledby))
+ a_intent = INTENT_DISARM
+ monkey_attack(pulledby)
+ retaliate(pulledby)
+ return TRUE
+
+ switch(mode)
+
+ if(MONKEY_IDLE) // idle
+
+ var/list/around = view(src, MONKEY_ENEMY_VISION)
+ bodyDisposal = locate(/obj/machinery/disposal/) in around
+
+ // scan for enemies
+ for(var/mob/living/L in around)
+ if( should_target(L) )
+ if(L.stat == CONSCIOUS)
+ emote(pick("roar","screech"))
+ retaliate(L)
+ return TRUE
+ else if(bodyDisposal)
+ target = L
+ mode = MONKEY_DISPOSE
+ return TRUE
+
+ // pickup any nearby objects
+ if(!pickupTarget && prob(MONKEY_PICKUP_PROB))
+ var/obj/item/I = locate(/obj/item/) in oview(5,src)
+ if(I && !blacklistItems[I])
+ pickupTarget = I
+
+ // I WANNA STEAL
+ if(!pickupTarget && prob(MONKEY_STEAL_PROB))
+ var/mob/living/carbon/human/H = locate(/mob/living/carbon/human/) in oview(5,src)
+ if(H)
+ pickupTarget = pick(H.held_items)
+
+ // clear any combat walking
+ if(!resisting)
+ walk_to(src,0)
+
+ return IsStandingStill()
+
+ if(MONKEY_HUNT) // hunting for attacker
+ if(health < MONKEY_FLEE_HEALTH)
+ mode = MONKEY_FLEE
+ return TRUE
+
+ if(target != null)
+ addtimer(CALLBACK(src, .proc/walk2derpless, target), 0)
+
+ // pickup any nearby weapon
+ if(!pickupTarget && prob(MONKEY_WEAPON_PROB))
+ var/obj/item/weapon/W = locate(/obj/item/weapon/) in oview(2,src)
+ if(W && !blacklistItems[W] && W.force > best_force)
+ pickupTarget = W
+
+ // recruit other monkies
+ var/list/around = view(src, MONKEY_ENEMY_VISION)
+ for(var/mob/living/carbon/monkey/M in around)
+ if(M.mode == MONKEY_IDLE && prob(MONKEY_RECRUIT_PROB))
+ M.emote(pick("roar","screech"))
+ M.target = target
+ M.mode = MONKEY_HUNT
+
+ // switch targets
+ for(var/mob/living/L in around)
+ if(L != target && should_target(L) && L.stat == CONSCIOUS && prob(MONKEY_SWITCH_TARGET_PROB))
+ target = L
+ return TRUE
+
+ // if can't reach target for long enough, go idle
+ if(frustration >= MONKEY_HUNT_FRUSTRATION_LIMIT)
+ back_to_idle()
+ return TRUE
+
+ if(target && target.stat == CONSCIOUS) // make sure target exists
+ if(Adjacent(target) && isturf(target.loc)) // if right next to perp
+
+ // check if target has a weapon
+ var/obj/item/weapon/W = locate(/obj/item/weapon) in target.held_items
+
+ // if the target has a weapon, chance to disarm them
+ if(W && prob(MONKEY_ATTACK_DISARM_PROB))
+ pickupTarget = W
+ a_intent = INTENT_DISARM
+ monkey_attack(target)
+
+ else
+ a_intent = INTENT_HARM
+ monkey_attack(target)
+
+ return TRUE
+
+ else // not next to perp
+ var/turf/olddist = get_dist(src, target)
+ if((get_dist(src, target)) >= (olddist))
+ frustration++
+ else
+ frustration = 0
+ else
+ back_to_idle()
+
+ if(MONKEY_FLEE)
+ var/list/around = view(src, MONKEY_FLEE_VISION)
+ target = null
+
+ // flee from anyone who attacked us and we didn't beat down
+ for(var/mob/living/L in around)
+ if( enemies[L] && L.stat == CONSCIOUS )
+ target = L
+
+ if(target != null)
+ walk_away(src, target, MONKEY_ENEMY_VISION, 5)
+ else
+ back_to_idle()
+
+ return TRUE
+
+ if(MONKEY_DISPOSE)
+
+ // if can't dispose of body go back to idle
+ if(!target || !bodyDisposal || frustration >= MONKEY_DISPOSE_FRUSTRATION_LIMIT)
+ back_to_idle()
+ return TRUE
+
+ if(target.pulledby != src && !istype(target.pulledby, /mob/living/carbon/monkey/))
+
+ addtimer(CALLBACK(src, .proc/walk2derpless, target.loc), 0)
+
+ if(Adjacent(target) && isturf(target.loc))
+ a_intent = INTENT_GRAB
+ target.grabbedby(src)
+ else
+ var/turf/olddist = get_dist(src, target)
+ if((get_dist(src, target)) >= (olddist))
+ frustration++
+ else
+ frustration = 0
+
+ else if(!disposing_body)
+ addtimer(CALLBACK(src, .proc/walk2derpless, bodyDisposal.loc), 0)
+
+ if(Adjacent(bodyDisposal))
+ disposing_body = TRUE
+ addtimer(CALLBACK(src, .proc/stuff_mob_in), 5)
+
+ else
+ var/turf/olddist = get_dist(src, bodyDisposal)
+ if((get_dist(src, bodyDisposal)) >= (olddist))
+ frustration++
+ else
+ frustration = 0
+
+ return TRUE
+
+
+
+ return IsStandingStill()
+
+/mob/living/carbon/monkey/proc/pickpocket(var/mob/M)
+ if(do_mob(src, M, MONKEY_ITEM_SNATCH_DELAY) && pickupTarget)
+ for(var/obj/item/I in M.held_items)
+ if(I == pickupTarget)
+ M.visible_message("[src] snatches [pickupTarget] from [M].", "[src] snatched [pickupTarget]!")
+ M.unEquip(pickupTarget)
+ if(!qdeleted(pickupTarget))
+ equip_item(pickupTarget)
+ pickpocketing = FALSE
+ pickupTarget = null
+ pickupTimer = 0
+
+/mob/living/carbon/monkey/proc/stuff_mob_in()
+ if(bodyDisposal && target && Adjacent(bodyDisposal))
+ bodyDisposal.stuff_mob_in(target, src)
+ disposing_body = FALSE
+ back_to_idle()
+
+/mob/living/carbon/monkey/proc/back_to_idle()
+
+ if(pulling)
+ stop_pulling()
+
+ mode = MONKEY_IDLE
+ target = null
+ a_intent = INTENT_HELP
+ frustration = 0
+ walk_to(src,0)
+
+// attack using a held weapon otherwise bite the enemy, then if we are angry there is a chance we might calm down a little
+/mob/living/carbon/monkey/proc/monkey_attack(mob/living/L)
+ var/obj/item/weapon/Weapon = locate(/obj/item/weapon) in held_items
+
+ // attack with weapon if we have one
+ if(Weapon)
+ L.attackby(Weapon, src)
+ else
+ L.attack_paw(src)
+
+ // no de-aggro
+ if(aggressive)
+ return
+
+ // if we arn't enemies, we were likely recruited to attack this target, jobs done if we calm down so go back to idle
+ if(!enemies[L])
+ if( target == L && prob(MONKEY_HATRED_REDUCTION_PROB) )
+ back_to_idle()
+ return // already de-aggroed
+
+ if(prob(MONKEY_HATRED_REDUCTION_PROB))
+ enemies[L] --
+
+ // if we are not angry at our target, go back to idle
+ if(enemies[L] <= 0)
+ enemies.Remove(L)
+ if( target == L )
+ back_to_idle()
+
+// get angry are a mob
+/mob/living/carbon/monkey/proc/retaliate(mob/living/L)
+ mode = MONKEY_HUNT
+ target = L
+ enemies[L] += MONKEY_HATRED_AMOUNT
+
+ if(a_intent != INTENT_HARM)
+ emote(pick("roar","screech"))
+ a_intent = INTENT_HARM
+
+/mob/living/carbon/monkey/attack_hand(mob/living/L)
+ if(L.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB))
+ retaliate(L)
+ else if(L.a_intent == INTENT_DISARM && prob(MONKEY_RETALIATE_DISARM_PROB))
+ retaliate(L)
+ return ..()
+
+/mob/living/carbon/monkey/attack_paw(mob/living/L)
+ if(L.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB))
+ retaliate(L)
+ else if(L.a_intent == INTENT_DISARM && prob(MONKEY_RETALIATE_DISARM_PROB))
+ retaliate(L)
+ return ..()
+
+/mob/living/carbon/monkey/attackby(obj/item/weapon/W, mob/user, params)
+ ..()
+ if((W.force) && (!target) && (W.damtype != STAMINA) )
+ retaliate(user)
+
+/mob/living/carbon/monkey/bullet_act(obj/item/projectile/Proj)
+ if(istype(Proj ,/obj/item/projectile/beam)||istype(Proj,/obj/item/projectile/bullet))
+ if((Proj.damage_type == BURN) || (Proj.damage_type == BRUTE))
+ if(!Proj.nodamage && Proj.damage < src.health)
+ retaliate(Proj.firer)
+ ..()
+
+/mob/living/carbon/monkey/hitby(atom/movable/AM, skipcatch = 0, hitpush = 1, blocked = 0)
+ if(istype(AM, /obj/item))
+ var/obj/item/I = AM
+ if(I.throwforce < src.health && I.thrownby && ishuman(I.thrownby))
+ var/mob/living/carbon/human/H = I.thrownby
+ retaliate(H)
+ ..()
+
+/mob/living/carbon/monkey/Crossed(atom/movable/AM)
+ if(!IsDeadOrIncap() && ismob(AM) && target)
+ var/mob/living/carbon/monkey/M = AM
+ if(!istype(M) || !M)
+ return
+ knockOver(M)
+ return
+ ..()
+
+/mob/living/carbon/monkey/proc/monkeyDrop(var/obj/item/A)
+ if(A)
+ unEquip(A, 1)
+ update_icons()
diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm
index a55cf64dde7..5b686c0a175 100644
--- a/code/modules/mob/living/carbon/monkey/life.dm
+++ b/code/modules/mob/living/carbon/monkey/life.dm
@@ -10,13 +10,17 @@
if (notransform)
return
- ..()
+ if(..())
- if(!client && stat == CONSCIOUS)
- if(prob(33) && canmove && isturf(loc) && !pulledby)
- step(src, pick(cardinal))
- if(prob(1))
- emote(pick("scratch","jump","roll","tail"))
+ if(!client)
+ if(stat == CONSCIOUS)
+ if(!handle_combat())
+ if(prob(33) && canmove && isturf(loc) && !pulledby)
+ step(src, pick(cardinal))
+ if(prob(1))
+ emote(pick("scratch","jump","roll","tail"))
+ else
+ walk_to(src,0)
/mob/living/carbon/monkey/handle_mutations_and_radiation()
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index af6bed51839..809303da446 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -898,3 +898,15 @@
IgniteMob()
//Mobs on Fire end
+
+// used by secbot and monkeys Crossed
+/mob/living/proc/knockOver(var/mob/living/carbon/C)
+ C.visible_message("[pick( \
+ "[C] dives out of [src]'s way!", \
+ "[C] stumbles over [src]!", \
+ "[C] jumps out of [src]'s path!", \
+ "[C] trips over [src] and falls!", \
+ "[C] topples over [src]!", \
+ "[C] leaps out of [src]'s way!")]")
+ C.Weaken(2)
+
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm
index 8b441d3ed4a..8cf7faa3fab 100644
--- a/code/modules/mob/living/simple_animal/bot/secbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/secbot.dm
@@ -403,14 +403,7 @@ Auto Patrol: []"},
var/mob/living/carbon/C = AM
if(!istype(C) || !C || in_range(src, target))
return
- C.visible_message("[pick( \
- "[C] dives out of [src]'s way!", \
- "[C] stumbles over [src]!", \
- "[C] jumps out of [src]'s path!", \
- "[C] trips over [src] and falls!", \
- "[C] topples over [src]!", \
- "[C] leaps out of [src]'s way!")]")
- C.Weaken(2)
+ knockOver(C)
return
..()
diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm
index 51632b18a66..e63ea7aa406 100644
--- a/code/modules/reagents/reagent_containers/syringes.dm
+++ b/code/modules/reagents/reagent_containers/syringes.dm
@@ -61,6 +61,12 @@
if(!L.can_inject(user, 1))
return
+ // chance of monkey retaliation
+ if(istype(target, /mob/living/carbon/monkey) && prob(MONKEY_SYRINGE_RETALIATION_PROB))
+ var/mob/living/carbon/monkey/M
+ M = target
+ M.retaliate(user)
+
switch(mode)
if(SYRINGE_DRAW)
diff --git a/tgstation.dme b/tgstation.dme
index 5feb54186c1..223c360e542 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -42,6 +42,7 @@
#include "code\__DEFINES\MC.dm"
#include "code\__DEFINES\misc.dm"
#include "code\__DEFINES\mobs.dm"
+#include "code\__DEFINES\monkeys.dm"
#include "code\__DEFINES\pinpointers.dm"
#include "code\__DEFINES\pipe_construction.dm"
#include "code\__DEFINES\preferences.dm"
@@ -1482,6 +1483,7 @@
#include "code\modules\mob\living\carbon\human\species_types\skeletons.dm"
#include "code\modules\mob\living\carbon\human\species_types\synths.dm"
#include "code\modules\mob\living\carbon\human\species_types\zombies.dm"
+#include "code\modules\mob\living\carbon\monkey\combat.dm"
#include "code\modules\mob\living\carbon\monkey\death.dm"
#include "code\modules\mob\living\carbon\monkey\inventory.dm"
#include "code\modules\mob\living\carbon\monkey\life.dm"