diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm
index b7e55cddb8..5e01c43e55 100644
--- a/code/game/objects/items/weapons/stunbaton.dm
+++ b/code/game/objects/items/weapons/stunbaton.dm
@@ -122,7 +122,7 @@
var/mob/living/carbon/human/H = target
affecting = H.get_organ(hit_zone)
- if(user.a_intent == I_HURT)
+ if(user.a_intent == I_HURT || user.a_intent == I_DISARM)
. = ..()
//whacking someone causes a much poorer electrical contact than deliberately prodding them.
agony *= 0.5
diff --git a/code/modules/mob/holder.dm b/code/modules/mob/holder.dm
index 121b999d21..d608bb0988 100644
--- a/code/modules/mob/holder.dm
+++ b/code/modules/mob/holder.dm
@@ -114,6 +114,11 @@ var/list/holder_mob_icon_cache = list()
if(!holder_type || buckled || pinned.len)
return
+ if(self_grab)
+ if(src.incapacitated()) return
+ else
+ if(grabber.incapacitated()) return
+
var/obj/item/weapon/holder/H = new holder_type(get_turf(src))
H.held_mob = src
src.forceMove(H)
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 6b9cbf0258..4eaf5aa8fe 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -194,7 +194,7 @@
status += "hurts when touched"
if(org.status & ORGAN_DEAD)
status += "is bruised and necrotic"
- if(!org.is_usable())
+ if(!org.is_usable() || org.is_dislocated())
status += "dangling uselessly"
if(status.len)
src.show_message("My [org.name] is [english_list(status)].",1)
@@ -309,14 +309,19 @@
if(!item) return
+ var/throw_range = item.throw_range
if (istype(item, /obj/item/weapon/grab))
var/obj/item/weapon/grab/G = item
item = G.throw_held() //throw the person instead of the grab
if(ismob(item))
+ var/mob/M = item
+
+ //limit throw range by relative mob size
+ throw_range = round(M.throw_range * min(src.mob_size/M.mob_size, 1))
+
var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors
var/turf/end_T = get_turf(target)
if(start_T && end_T)
- var/mob/M = item
var/start_T_descriptor = "tile at [start_T.x], [start_T.y], [start_T.z] in area [get_area(start_T)]"
var/end_T_descriptor = "tile at [end_T.x], [end_T.y], [end_T.z] in area [get_area(end_T)]"
@@ -324,31 +329,28 @@
usr.attack_log += text("\[[time_stamp()]\] Has thrown [M.name] ([M.ckey]) from [start_T_descriptor] with the target [end_T_descriptor]")
msg_admin_attack("[usr.name] ([usr.ckey]) has thrown [M.name] ([M.ckey]) from [start_T_descriptor] with the target [end_T_descriptor] (JMP)")
- if(!item) return //Grab processing has a chance of returning null
-
-
- src.remove_from_mob(item)
- item.loc = src.loc
+ src.drop_from_inventory(item)
+ if(!item || !isturf(item.loc))
+ return
//actually throw it!
- if (item)
- src.visible_message("\red [src] has thrown [item].")
+ src.visible_message("[src] has thrown [item].")
- if(!src.lastarea)
- src.lastarea = get_area(src.loc)
- if((istype(src.loc, /turf/space)) || (src.lastarea.has_gravity == 0))
- src.inertia_dir = get_dir(target, src)
- step(src, inertia_dir)
+ if(!src.lastarea)
+ src.lastarea = get_area(src.loc)
+ if((istype(src.loc, /turf/space)) || (src.lastarea.has_gravity == 0))
+ src.inertia_dir = get_dir(target, src)
+ step(src, inertia_dir)
/*
- if(istype(src.loc, /turf/space) || (src.flags & NOGRAV)) //they're in space, move em one space in the opposite direction
- src.inertia_dir = get_dir(target, src)
- step(src, inertia_dir)
+ if(istype(src.loc, /turf/space) || (src.flags & NOGRAV)) //they're in space, move em one space in the opposite direction
+ src.inertia_dir = get_dir(target, src)
+ step(src, inertia_dir)
*/
- item.throw_at(target, item.throw_range, item.throw_speed, src)
+ item.throw_at(target, throw_range, item.throw_speed, src)
/mob/living/carbon/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
..()
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index d6a88f35ff..e884dbcd5d 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -1324,8 +1324,8 @@
var/list/limbs = list()
for(var/limb in organs_by_name)
var/obj/item/organ/external/current_limb = organs_by_name[limb]
- if(current_limb && current_limb.dislocated == 2)
- limbs |= limb
+ if(current_limb && current_limb.dislocated > 0 && !current_limb.is_parent_dislocated()) //if the parent is also dislocated you will have to relocate that first
+ limbs |= current_limb
var/choice = input(usr,"Which joint do you wish to relocate?") as null|anything in limbs
if(!choice)
diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm
index 7cc3156f18..d8d40ab660 100644
--- a/code/modules/mob/living/carbon/human/human_attackhand.dm
+++ b/code/modules/mob/living/carbon/human/human_attackhand.dm
@@ -326,7 +326,7 @@
if(!target_zone)
return 0
var/obj/item/organ/external/organ = get_organ(check_zone(target_zone))
- if(!organ || organ.is_dislocated() || organ.dislocated == -1)
+ if(!organ || organ.dislocated > 0 || organ.dislocated == -1) //don't use is_dislocated() here, that checks parent
return 0
user.visible_message("[user] begins to dislocate [src]'s [organ.joint]!")
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 614bbe1de8..6edefd2951 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -187,11 +187,13 @@ emp_act
// Handle striking to cripple.
if(user.a_intent == I_DISARM)
- effective_force /= 2
- if(..(I, user, effective_force, blocked, hit_zone))
- attack_joint(affecting, I, blocked)
- else
+ effective_force *= 0.66 //reduced effective force...
+ if(!..(I, user, effective_force, blocked, hit_zone))
return 0
+
+ //set the dislocate mult less than the effective force mult so that
+ //dislocating limbs on disarm is a bit easier than breaking limbs on harm
+ attack_joint(affecting, I, effective_force, 0.5, blocked) //...but can dislocate joints
else if(!..())
return 0
@@ -242,10 +244,16 @@ emp_act
return 1
-/mob/living/carbon/human/proc/attack_joint(var/obj/item/organ/external/organ, var/obj/item/W, var/blocked)
+/mob/living/carbon/human/proc/attack_joint(var/obj/item/organ/external/organ, var/obj/item/W, var/effective_force, var/dislocate_mult, var/blocked)
if(!organ || (organ.dislocated == 2) || (organ.dislocated == -1) || blocked >= 100)
return 0
- if(prob(W.force * (100 - blocked)/100))
+
+ if(W.damtype != BRUTE)
+ return 0
+
+ //want the dislocation chance to be such that the limb is expected to dislocate after dealing a fraction of the damage needed to break the limb
+ var/dislocate_chance = effective_force/(dislocate_mult * organ.min_broken_damage * config.organ_health_multiplier)*100
+ if(prob(dislocate_chance * (100 - blocked)/100))
visible_message("[src]'s [organ.joint] [pick("gives way","caves in","crumbles","collapses")]!")
organ.dislocate(1)
return 1
diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm
index f65b9926c8..8db85ef5fe 100644
--- a/code/modules/mob/living/carbon/human/human_organs.dm
+++ b/code/modules/mob/living/carbon/human/human_organs.dm
@@ -68,7 +68,7 @@
/mob/living/carbon/human/proc/handle_stance()
// Don't need to process any of this if they aren't standing anyways
// unless their stance is damaged, and we want to check if they should stay down
- if (!stance_damage && (lying || resting) && (life_tick % 4) == 0)
+ if (!stance_damage && (lying || resting) && (life_tick % 4) != 0)
return
stance_damage = 0
@@ -80,7 +80,7 @@
var/limb_pain
for(var/limb_tag in list("l_leg","r_leg","l_foot","r_foot"))
var/obj/item/organ/external/E = organs_by_name[limb_tag]
- if(!E || (E.status & (ORGAN_MUTATED|ORGAN_DEAD)) || E.is_stump()) //should just be !E.is_usable() here but dislocation screws that up.
+ if(!E || !E.is_usable())
stance_damage += 2 // let it fail even if just foot&leg
else if (E.is_malfunctioning())
//malfunctioning only happens intermittently so treat it as a missing limb when it procs
@@ -93,7 +93,7 @@
spark_system.start()
spawn(10)
qdel(spark_system)
- else if (E.is_broken() || !E.is_usable())
+ else if (E.is_broken())
stance_damage += 1
else if (E.is_dislocated())
stance_damage += 0.5
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 80798fa57b..8e892436e0 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -847,7 +847,10 @@
if(!isSynthetic() && (species.flags & IS_PLANT) && (!light_organ || light_organ.is_broken()))
if(nutrition < 200)
take_overall_damage(2,0)
- traumatic_shock++
+
+ //traumatic_shock is updated every tick, incrementing that is pointless - shock_stage is the counter.
+ //Not that it matters much for diona, who have NO_PAIN.
+ shock_stage++
// TODO: stomach and bloodstream organ.
if(!isSynthetic())
diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm
index 25a8149e48..def9ae59f2 100644
--- a/code/modules/mob/living/carbon/human/species/species.dm
+++ b/code/modules/mob/living/carbon/human/species/species.dm
@@ -190,6 +190,7 @@
/datum/species/proc/create_organs(var/mob/living/carbon/human/H) //Handles creation of mob organs.
+ H.mob_size = mob_size
for(var/obj/item/organ/organ in H.contents)
if((organ in H.organs) || (organ in H.internal_organs))
qdel(organ)
@@ -249,7 +250,6 @@
H.mob_swap_flags = swap_flags
H.mob_push_flags = push_flags
H.pass_flags = pass_flags
- H.mob_size = mob_size
/datum/species/proc/handle_death(var/mob/living/carbon/human/H) //Handles any species-specific death events (such as dionaea nymph spawns).
return
diff --git a/code/modules/mob/living/carbon/shock.dm b/code/modules/mob/living/carbon/shock.dm
index 92eccc66df..370d3f89d2 100644
--- a/code/modules/mob/living/carbon/shock.dm
+++ b/code/modules/mob/living/carbon/shock.dm
@@ -23,8 +23,10 @@
if(istype(src,/mob/living/carbon/human))
var/mob/living/carbon/human/M = src
for(var/obj/item/organ/external/organ in M.organs)
- if(organ && (organ.is_broken() || organ.open))
+ if(organ.is_broken() || organ.open)
src.traumatic_shock += 30
+ else if(organ.is_dislocated())
+ src.traumatic_shock += 15
if(src.traumatic_shock < 0)
src.traumatic_shock = 0
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 4d2e254d30..be397a6def 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -623,26 +623,9 @@ default behaviour is:
/mob/living/proc/resist_grab()
var/resisting = 0
- for(var/obj/O in requests)
- requests.Remove(O)
- qdel(O)
- resisting++
for(var/obj/item/weapon/grab/G in grabbed_by)
resisting++
- switch(G.state)
- if(GRAB_PASSIVE)
- qdel(G)
- if(GRAB_AGGRESSIVE)
- //Not standing up makes it much harder to break, so it is easier to cuff someone who is down without forcing them into unconsciousness.
- //Otherwise, it's the same chance of breaking the grab as disarm.
- if(incapacitated(INCAPACITATION_KNOCKDOWN)? prob(15) : prob(60))
- visible_message("[src] has broken free of [G.assailant]'s grip!")
- qdel(G)
- if(GRAB_NECK)
- //If the you move when grabbing someone then it's easier for them to break free. Same if the affected mob is immune to stun.
- if (((world.time - G.assailant.l_move_time < 30 || !stunned) && prob(15)) || prob(3))
- visible_message("[src] has broken free of [G.assailant]'s headlock!")
- qdel(G)
+ G.handle_resist()
if(resisting)
visible_message("[src] resists!")
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index b67e58af3e..5b937a57e2 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -121,7 +121,6 @@
var/datum/hud/hud_used = null
var/list/grabbed_by = list( )
- var/list/requests = list( )
var/list/mapobjs = list()
diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm
index 47e0584740..e40b14dffd 100644
--- a/code/modules/mob/mob_grab.dm
+++ b/code/modules/mob/mob_grab.dm
@@ -3,10 +3,15 @@
///Process_Grab()
///Called by client/Move()
-///Checks to see if you are grabbing anything and if moving will affect your grab.
+///Checks to see if you are grabbing or being grabbed by anything and if moving will affect your grab.
/client/proc/Process_Grab()
- if(istype(mob, /mob/living))
+ //if we are being grabbed
+ if(isliving(mob))
var/mob/living/L = mob
+ if(!L.canmove && L.grabbed_by.len)
+ L.resist() //shortcut for resisting grabs
+
+ //if we are grabbing someone
for(var/obj/item/weapon/grab/G in list(L.l_hand, L.r_hand))
G.reset_kill_state() //no wandering across the station/asteroid while choking someone
@@ -131,7 +136,7 @@
handle_eye_mouth_covering(affecting, assailant, assailant.zone_sel.selecting)
if(force_down)
- if(affecting.loc != assailant.loc)
+ if(affecting.loc != assailant.loc || size_difference(affecting, assailant) > 0)
force_down = 0
else
affecting.Weaken(2)
@@ -232,7 +237,7 @@
if(state < GRAB_AGGRESSIVE)
if(!allow_upgrade)
return
- if(!affecting.lying)
+ if(!affecting.lying || size_difference(affecting, assailant) > 0)
assailant.visible_message("[assailant] has grabbed [affecting] aggressively (now hands)!")
else
assailant.visible_message("[assailant] pins [affecting] down to the ground (now hands)!")
@@ -335,6 +340,40 @@
hud.icon_state = "kill"
state = GRAB_NECK
+/obj/item/weapon/grab/proc/handle_resist()
+ var/grab_name
+ var/break_strength = 1
+ var/list/break_chance_table = list(100)
+ switch(state)
+ //if(GRAB_PASSIVE)
+
+ if(GRAB_AGGRESSIVE)
+ grab_name = "grip"
+ //Being knocked down makes it harder to break a grab, so it is easier to cuff someone who is down without forcing them into unconsciousness.
+ if(!affecting.incapacitated(INCAPACITATION_KNOCKDOWN))
+ break_strength++
+ break_chance_table = list(15, 60, 100)
+
+ if(GRAB_NECK)
+ grab_name = "headlock"
+ //If the you move when grabbing someone then it's easier for them to break free. Same if the affected mob is immune to stun.
+ if(world.time - assailant.l_move_time < 30 || !affecting.stunned)
+ break_strength++
+ break_chance_table = list(3, 18, 45, 100)
+
+ //It's easier to break out of a grab by a smaller mob
+ break_strength += max(size_difference(affecting, assailant), 0)
+
+ var/break_chance = break_chance_table[Clamp(break_strength, 1, break_chance_table.len)]
+ if(prob(break_chance))
+ if(grab_name)
+ affecting.visible_message("[affecting] has broken free of [assailant]'s [grab_name]!")
+ qdel(src)
+
+//returns the number of size categories between affecting and assailant, rounded. Positive means A is larger than B
+/obj/item/weapon/grab/proc/size_difference(mob/A, mob/B)
+ return mob_size_difference(A.mob_size, B.mob_size)
+
/obj/item/weapon/grab
var/destroying = 0
diff --git a/code/modules/mob/mob_grab_specials.dm b/code/modules/mob/mob_grab_specials.dm
index 5158a7f3d0..e7b75a2e5d 100644
--- a/code/modules/mob/mob_grab_specials.dm
+++ b/code/modules/mob/mob_grab_specials.dm
@@ -51,10 +51,16 @@
return
attacker.visible_message("[attacker] [pick("bent", "twisted")] [target]'s [organ.name] into a jointlock!")
+
+ if(target.species.flags & NO_PAIN)
+ return
+
var/armor = target.run_armor_check(target, "melee")
if(armor < 60)
target << "You feel extreme pain!"
- affecting.adjustHalLoss(Clamp(0, 60-affecting.halloss, 30)) //up to 60 halloss
+
+ var/max_halloss = round(target.species.total_health * 0.8) //up to 80% of passing out
+ affecting.adjustHalLoss(Clamp(0, max_halloss - affecting.halloss, 30))
/obj/item/weapon/grab/proc/attack_eye(mob/living/carbon/human/target, mob/living/carbon/human/attacker)
if(!istype(attacker))
@@ -125,6 +131,10 @@
return
if(force_down)
attacker << "You are already pinning [target] to the ground."
+ return
+ if(size_difference(affecting, assailant) > 0)
+ attacker << "You are too small to do that!"
+ return
attacker.visible_message("[attacker] starts forcing [target] to the ground!")
if(do_after(attacker, 20) && target)
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index 22da202ede..2f788862f8 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -5,6 +5,9 @@
return L.mob_size <= MOB_SMALL
return 0
+//returns the number of size categories between two mob_sizes, rounded. Positive means A is larger than B
+/proc/mob_size_difference(var/mob_size_A, var/mob_size_B)
+ return round(log(2, mob_size_A/mob_size_B), 1)
/proc/istiny(A)
if(A && istype(A, /mob/living))
diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm
index 13eef2eaf4..d8533239e7 100644
--- a/code/modules/organs/organ.dm
+++ b/code/modules/organs/organ.dm
@@ -50,6 +50,7 @@ var/list/organ_cache = list()
max_damage = min_broken_damage * 2
if(istype(holder))
src.owner = holder
+ src.w_class = max(src.w_class + mob_size_difference(holder.mob_size, MOB_MEDIUM), 1) //smaller mobs have smaller organs.
species = all_species["Human"]
if(holder.dna)
dna = holder.dna.Clone()
diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm
index a1a31fad7c..d3b309fd84 100644
--- a/code/modules/organs/organ_external.dm
+++ b/code/modules/organs/organ_external.dm
@@ -60,7 +60,7 @@
var/cannot_gib // Impossible to gib, distinct from amputation.
var/joint = "joint" // Descriptive string used in dislocation.
var/amputation_point // Descriptive string used in amputation.
- var/dislocated = 0 // If you target a joint, you can dislocate the limb, causing temporary damage to the organ.
+ var/dislocated = 0 // If you target a joint, you can dislocate the limb, impairing it's usefulness and causing pain
var/encased // Needs to be opened with a saw to access the organs.
// Surgery vars.
@@ -156,32 +156,38 @@
/obj/item/organ/external/proc/is_dislocated()
if(dislocated > 0)
return 1
- if(parent)
- return parent.is_dislocated()
+ if(is_parent_dislocated())
+ return 1//if any parent is dislocated, we are considered dislocated as well
return 0
-/obj/item/organ/external/proc/dislocate(var/primary)
- if(dislocated != -1)
- if(primary)
- dislocated = 2
- else
- dislocated = 1
- owner.verbs |= /mob/living/carbon/human/proc/undislocate
- if(children && children.len)
- for(var/obj/item/organ/external/child in children)
- child.dislocate()
+/obj/item/organ/external/proc/is_parent_dislocated()
+ var/obj/item/organ/external/O = parent
+ while(O && O.dislocated != -1)
+ if(O.dislocated == 1)
+ return 1
+ O = O.parent
+ return 0
+
+
+/obj/item/organ/external/proc/dislocate()
+ if(dislocated == -1)
+ return
+
+ dislocated = 1
+ if(owner)
+ owner.verbs |= /mob/living/carbon/human/proc/undislocate
/obj/item/organ/external/proc/undislocate()
- if(dislocated != -1)
- dislocated = 0
- if(children && children.len)
- for(var/obj/item/organ/external/child in children)
- if(child.dislocated == 1)
- child.undislocate()
+ if(dislocated == -1)
+ return
+
+ dislocated = 0
if(owner)
owner.shock_stage += 20
+
+ //check to see if we still need the verb
for(var/obj/item/organ/external/limb in owner.organs)
- if(limb.dislocated == 2)
+ if(limb.dislocated == 1)
return
owner.verbs -= /mob/living/carbon/human/proc/undislocate
@@ -1085,7 +1091,7 @@ Note that amputating the affected organ does in fact remove the infection from t
return 0
/obj/item/organ/external/proc/is_usable()
- return !is_dislocated() && !(status & (ORGAN_MUTATED|ORGAN_DEAD))
+ return !(status & (ORGAN_MUTATED|ORGAN_DEAD))
/obj/item/organ/external/proc/is_malfunctioning()
return ((robotic >= ORGAN_ROBOT) && (brute_dam + burn_dam) >= 10 && prob(brute_dam + burn_dam))
diff --git a/code/modules/organs/subtypes/diona.dm b/code/modules/organs/subtypes/diona.dm
index ab5c436758..0776e318b4 100644
--- a/code/modules/organs/subtypes/diona.dm
+++ b/code/modules/organs/subtypes/diona.dm
@@ -206,4 +206,5 @@
amputation_point = "branch"
joint = "structural ligament"
dislocated = -1
- vital = 0
\ No newline at end of file
+ vital = 0
+ slot_flags = SLOT_BELT
diff --git a/code/modules/organs/subtypes/standard.dm b/code/modules/organs/subtypes/standard.dm
index 36fc7ba677..e33a319f69 100644
--- a/code/modules/organs/subtypes/standard.dm
+++ b/code/modules/organs/subtypes/standard.dm
@@ -2,6 +2,8 @@
ORGAN DEFINES
****************************************************/
+//Make sure that w_class is set as if the parent mob was medium sized! This is because w_class is adjusted automatically for mob_size in New()
+
/obj/item/organ/external/chest
name = "upper body"
organ_tag = BP_TORSO
@@ -148,6 +150,7 @@
organ_tag = BP_HEAD
icon_name = "head"
name = "head"
+ slot_flags = SLOT_BELT
max_damage = 75
min_broken_damage = 35
w_class = 3
diff --git a/html/changelogs/HarpyEagle-dislocation-cleanup.yml b/html/changelogs/HarpyEagle-dislocation-cleanup.yml
new file mode 100644
index 0000000000..84ae3a66b6
--- /dev/null
+++ b/html/changelogs/HarpyEagle-dislocation-cleanup.yml
@@ -0,0 +1,7 @@
+author: HarpyEagle
+
+delete-after: True
+
+changes:
+ - bugfix: "Fixes disarm-attack dislocation chances being so low that you were very likely to break the targeted limb before it would dislocate."
+ - bugfix: "It is now possible to disarm-attack with stunbatons like with other melee weapons. Note that this means that using a stunbaton on disarm intent will hurt people."
diff --git a/html/changelogs/HarpyEagle-mob-grab.yml b/html/changelogs/HarpyEagle-mob-grab.yml
new file mode 100644
index 0000000000..04125ebdf9
--- /dev/null
+++ b/html/changelogs/HarpyEagle-mob-grab.yml
@@ -0,0 +1,9 @@
+author: HarpyEagle
+
+delete-after: True
+
+changes:
+ - rscadd: "Trying to move while being grabbed will now automatically resist."
+ - tweak: "Small mobs are no longer able to pin larger mobs."
+ - tweak: "Resisting a smaller mob's grab is more likely to be successful."
+ - bugfix: "Fixed being able to climb onto a larger mob while restrained, weakened, unconscious, or dead."