diff --git a/code/datums/movement/mob.dm b/code/datums/movement/mob.dm
index 0ef1b3127dd..f3e58b26f5a 100644
--- a/code/datums/movement/mob.dm
+++ b/code/datums/movement/mob.dm
@@ -199,6 +199,9 @@
for(var/obj/item/grab/G in mob.grabbed_by)
if(G.assailant != mob && G.stop_move())
+ if(get_dist(G.assailant, mob) > 1 || G.assailant.z != mob.z)
+ qdel(G)
+ continue
if(mover == mob)
to_chat(mob, "You're stuck in a grab!")
mob.ProcessGrabs()
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 7eef2c2d658..252989c20eb 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -537,9 +537,10 @@ var/list/global/slot_flags_enumeration = list(
/obj/item/proc/get_parry_chance(mob/user)
. = base_parry_chance
- if(user)
- if(base_parry_chance || user.skill_check(SKILL_COMBAT, SKILL_TRAINED))
- . += 10 * (user.get_skill_value(SKILL_COMBAT) - SKILL_BASIC)
+ if (user.a_intent == I_HELP)
+ . = 0
+ if (.)
+ . += Clamp((user.get_skill_value(SKILL_COMBAT) * 10) - 20, 0, 75)
/obj/item/proc/on_disarm_attempt(mob/target, mob/living/attacker)
if(force < 1)
diff --git a/code/modules/mob/grab/abomination/abom_aggressive.dm b/code/modules/mob/grab/abomination/abom_aggressive.dm
index 1a89fe18f67..37953ae0257 100644
--- a/code/modules/mob/grab/abomination/abom_aggressive.dm
+++ b/code/modules/mob/grab/abomination/abom_aggressive.dm
@@ -15,6 +15,12 @@
/datum/grab/abomination/aggressive/process_effect(obj/item/grab/G)
var/mob/living/carbon/human/target = G.affecting
+ var/mob/living/carbon/human/assailant = G.assailant
+
+ if(assailant.incapacitated(INCAPACITATION_ALL))
+ target.visible_message(SPAN_WARNING("[assailant] lets go of \his grab!"))
+ qdel(G)
+ return
if(G.target_zone in list(BP_L_HAND, BP_R_HAND))
target.drop_l_hand()
diff --git a/code/modules/mob/grab/abomination/abom_kill.dm b/code/modules/mob/grab/abomination/abom_kill.dm
index 35f8be08dfd..614eea6c983 100644
--- a/code/modules/mob/grab/abomination/abom_kill.dm
+++ b/code/modules/mob/grab/abomination/abom_kill.dm
@@ -22,6 +22,11 @@
var/mob/living/carbon/human/user = G.assailant
var/mob/living/carbon/human/target = G.affecting
+ if(user.incapacitated(INCAPACITATION_ALL))
+ user.visible_message(SPAN_WARNING("[user] lets go of \his grab!"))
+ qdel(G)
+ return
+
target.Stun(3)
switch(user.a_intent)
diff --git a/code/modules/mob/grab/grab_datum.dm b/code/modules/mob/grab/grab_datum.dm
index 60b1b5d06d1..8e2f1def763 100644
--- a/code/modules/mob/grab/grab_datum.dm
+++ b/code/modules/mob/grab/grab_datum.dm
@@ -98,22 +98,22 @@
to_chat(G.assailant, "[string_process(G, fail_down)]")
return
-/datum/grab/proc/let_go(var/obj/item/grab/G)
- if (G)
+/datum/grab/proc/let_go(obj/item/grab/G)
+ if(G)
let_go_effect(G)
G.force_drop()
-/datum/grab/proc/on_target_change(var/obj/item/grab/G, old_zone, new_zone)
+/datum/grab/proc/on_target_change(obj/item/grab/G, old_zone, new_zone)
G.special_target_functional = check_special_target(G)
if(G.special_target_functional)
special_target_change(G, old_zone, new_zone)
special_target_effect(G)
-/datum/grab/proc/process(var/obj/item/grab/G)
+/datum/grab/proc/process(obj/item/grab/G)
special_target_effect(G)
process_effect(G)
-/datum/grab/proc/throw_held(var/obj/item/grab/G)
+/datum/grab/proc/throw_held(obj/item/grab/G)
if(G.assailant == G.affecting)
return
@@ -128,11 +128,12 @@
// check if we're grabbing with our inactive hand
G = thrower.get_inactive_hand()
- if(!istype(G)) return
+ if(!istype(G))
+ return
qdel(G)
return
-/datum/grab/proc/hit_with_grab(var/obj/item/grab/G)
+/datum/grab/proc/hit_with_grab(obj/item/grab/G)
if(downgrade_on_action)
G.downgrade()
@@ -163,11 +164,11 @@
else
to_chat(G.assailant, "You must wait before you can do that.")
-/datum/grab/proc/make_log(var/obj/item/grab/G, var/action)
+/datum/grab/proc/make_log(obj/item/grab/G, action)
admin_attack_log(G.assailant, G.affecting, "[action]s their victim", "was [action]ed", "used [action] on")
-/datum/grab/proc/adjust_position(var/obj/item/grab/G)
+/datum/grab/proc/adjust_position(obj/item/grab/G)
var/mob/living/carbon/human/affecting = G.affecting
var/mob/living/carbon/human/assailant = G.assailant
var/adir = get_dir(assailant, affecting)
@@ -193,7 +194,7 @@
affecting.reset_plane_and_layer()
-/datum/grab/proc/reset_position(var/obj/item/grab/G)
+/datum/grab/proc/reset_position(obj/item/grab/G)
var/mob/living/carbon/human/affecting = G.affecting
if(!affecting.buckled)
@@ -201,7 +202,7 @@
affecting.reset_plane_and_layer()
// This is called whenever the assailant moves.
-/datum/grab/proc/assailant_moved(var/obj/item/grab/G)
+/datum/grab/proc/assailant_moved(obj/item/grab/G)
adjust_position(G)
moved_effect(G)
if(downgrade_on_move)
@@ -214,78 +215,107 @@
*/
// What happens when you upgrade from one grab state to the next.
-/datum/grab/proc/upgrade_effect(var/obj/item/grab/G)
+/datum/grab/proc/upgrade_effect(obj/item/grab/G)
// Conditions to see if upgrading is possible
-/datum/grab/proc/can_upgrade(var/obj/item/grab/G)
+/datum/grab/proc/can_upgrade(obj/item/grab/G)
return 1
// What happens when you downgrade from one grab state to the next.
-/datum/grab/proc/downgrade_effect(var/obj/item/grab/G)
+/datum/grab/proc/downgrade_effect(obj/item/grab/G)
// Conditions to see if downgrading is possible
-/datum/grab/proc/can_downgrade(var/obj/item/grab/G)
+/datum/grab/proc/can_downgrade(obj/item/grab/G)
return 1
// What happens when you let go of someone by either dropping the grab
// or by downgrading from the lowest grab state.
-/datum/grab/proc/let_go_effect(var/obj/item/grab/G)
+/datum/grab/proc/let_go_effect(obj/item/grab/G)
// What happens each tic when process is called.
-/datum/grab/proc/process_effect(var/obj/item/grab/G)
+/datum/grab/proc/process_effect(obj/item/grab/G)
// Handles special targeting like eyes and mouth being covered.
-/datum/grab/proc/special_target_effect(var/obj/item/grab/G)
+/datum/grab/proc/special_target_effect(obj/item/grab/G)
// Handles when they change targeted areas and something is supposed to happen.
-/datum/grab/proc/special_target_change(var/obj/item/grab/G, var/diff_zone)
+/datum/grab/proc/special_target_change(obj/item/grab/G, diff_zone)
// Checks if the special target works on the grabbed humanoid.
-/datum/grab/proc/check_special_target(var/obj/item/grab/G)
+/datum/grab/proc/check_special_target(obj/item/grab/G)
// What happens when you hit the grabbed person with the grab on help intent.
-/datum/grab/proc/on_hit_help(var/obj/item/grab/G)
+/datum/grab/proc/on_hit_help(obj/item/grab/G)
return 1
// What happens when you hit the grabbed person with the grab on disarm intent.
-/datum/grab/proc/on_hit_disarm(var/obj/item/grab/G)
+/datum/grab/proc/on_hit_disarm(obj/item/grab/G)
return 1
// What happens when you hit the grabbed person with the grab on grab intent.
-/datum/grab/proc/on_hit_grab(var/obj/item/grab/G)
+/datum/grab/proc/on_hit_grab(obj/item/grab/G)
return 1
// What happens when you hit the grabbed person with the grab on harm intent.
-/datum/grab/proc/on_hit_harm(var/obj/item/grab/G)
+/datum/grab/proc/on_hit_harm(obj/item/grab/G)
return 1
// What happens when you hit the grabbed person with an open hand and you want it
// to do some special snowflake action based on some other factor such as
// intent.
-/datum/grab/proc/resolve_openhand_attack(var/obj/item/grab/G)
+/datum/grab/proc/resolve_openhand_attack(obj/item/grab/G)
return 0
// Used when you want an effect to happen when the grab enters this state as an upgrade
-/datum/grab/proc/enter_as_up(var/obj/item/grab/G)
+/datum/grab/proc/enter_as_up(obj/item/grab/G)
-/datum/grab/proc/item_attack(var/obj/item/grab/G, var/obj/item)
+/datum/grab/proc/item_attack(obj/item/grab/G, obj/item)
-/datum/grab/proc/resolve_item_attack(var/obj/item/grab/G, var/mob/living/carbon/human/user, var/obj/item/I, var/target_zone)
+/datum/grab/proc/resolve_item_attack(obj/item/grab/G, mob/living/carbon/human/user, obj/item/I, target_zone)
return 0
-/datum/grab/proc/handle_resist(var/obj/item/grab/G)
+/datum/grab/proc/handle_resist(obj/item/grab/G)
var/mob/living/carbon/human/affecting = G.affecting
var/mob/living/carbon/human/assailant = G.assailant
+ if(assailant.incapacitated(INCAPACITATION_ALL))
+ let_go(G)
+ return
+
if(affecting.incapacitated(INCAPACITATION_KNOCKOUT | INCAPACITATION_STUNNED))
- to_chat(G.affecting, "You can't resist in your current state!")
+ to_chat(G.affecting, SPAN_WARNING("You can't resist in your current state!"))
var/skill_mod = Clamp(affecting.get_skill_difference(SKILL_COMBAT, assailant), -1, 1)
var/break_strength = breakability + size_difference(affecting, assailant) + skill_mod
+ var/shock = affecting.get_shock()
+ var/ashock = assailant.get_shock()
if(affecting.incapacitated(INCAPACITATION_ALL))
break_strength--
if(affecting.confused)
break_strength--
+ if(affecting.eye_blind)
+ break_strength--
+ if(affecting.eye_blurry)
+ break_strength--
+ if(shock >= 10)
+ break_strength--
+ if(shock >= 30)
+ break_strength--
+ if(shock >= 50)
+ break_strength--
+
+ if(assailant.confused)
+ break_strength++
+ if(assailant.eye_blind)
+ break_strength++
+ if(assailant.eye_blurry)
+ break_strength++
+ if(ashock >= 10)
+ break_strength++
+ if(ashock >= 30)
+ break_strength++
+ if(ashock >= 50)
+ break_strength++
if(break_strength < 1)
to_chat(G.affecting, "You try to break free but feel that unless something changes, you'll never escape!")
@@ -304,4 +334,5 @@
/datum/grab/proc/size_difference(mob/A, mob/B)
return mob_size_difference(A.mob_size, B.mob_size)
-/datum/grab/proc/moved_effect(var/obj/item/grab/G)
+/datum/grab/proc/moved_effect(obj/item/grab/G)
+ return
diff --git a/code/modules/mob/grab/nab/nab_aggressive.dm b/code/modules/mob/grab/nab/nab_aggressive.dm
index e088c18d11b..90e3e90b28d 100644
--- a/code/modules/mob/grab/nab/nab_aggressive.dm
+++ b/code/modules/mob/grab/nab/nab_aggressive.dm
@@ -10,10 +10,16 @@
break_chance_table = list(3, 18, 45, 100)
-/datum/grab/nab/aggressive/upgrade_effect(var/obj/item/grab/G)
+/datum/grab/nab/aggressive/upgrade_effect(obj/item/grab/G)
process_effect(G)
-/datum/grab/nab/aggressive/process_effect(var/obj/item/grab/G)
+/datum/grab/nab/aggressive/process_effect(obj/item/grab/G)
var/mob/living/carbon/human/affecting = G.affecting
+ var/mob/living/carbon/human/assailant = G.assailant
- affecting.Stun(3)
\ No newline at end of file
+ if(assailant.incapacitated(INCAPACITATION_ALL))
+ affecting.visible_message(SPAN_WARNING("[assailant] lets go of \his grab!"))
+ qdel(G)
+ return
+
+ affecting.Stun(3)
diff --git a/code/modules/mob/grab/nab/nab_kill.dm b/code/modules/mob/grab/nab/nab_kill.dm
index f1460ef5806..1a4cebd5514 100644
--- a/code/modules/mob/grab/nab/nab_kill.dm
+++ b/code/modules/mob/grab/nab/nab_kill.dm
@@ -14,17 +14,22 @@
break_chance_table = list(3, 10, 20, 100)
-/datum/grab/nab/kill/upgrade_effect(var/obj/item/grab/G)
+/datum/grab/nab/kill/upgrade_effect(obj/item/grab/G)
process_effect(G)
-/datum/grab/nab/kill/process_effect(var/obj/item/grab/G)
+/datum/grab/nab/kill/process_effect(obj/item/grab/G)
var/mob/living/carbon/human/assailant = G.assailant
var/mob/living/carbon/human/affecting = G.affecting
+ if(assailant.incapacitated(INCAPACITATION_ALL))
+ affecting.visible_message(SPAN_WARNING("[assailant] lets go of \his grab!"))
+ qdel(G)
+ return
+
affecting.Stun(3)
switch(assailant.a_intent)
if(I_GRAB)
on_hit_grab(G)
if(I_HURT)
- on_hit_harm(G)
\ No newline at end of file
+ on_hit_harm(G)
diff --git a/code/modules/mob/grab/nab/nab_passive.dm b/code/modules/mob/grab/nab/nab_passive.dm
index f030a76360b..26c2f902f7c 100644
--- a/code/modules/mob/grab/nab/nab_passive.dm
+++ b/code/modules/mob/grab/nab/nab_passive.dm
@@ -12,4 +12,4 @@
icon_state = "reinforce1"
- break_chance_table = list(50, 80, 100)
\ No newline at end of file
+ break_chance_table = list(50, 80, 100)
diff --git a/code/modules/mob/grab/normal/norm_aggressive.dm b/code/modules/mob/grab/normal/norm_aggressive.dm
index 2060e80e259..8ca3b23fe99 100644
--- a/code/modules/mob/grab/normal/norm_aggressive.dm
+++ b/code/modules/mob/grab/normal/norm_aggressive.dm
@@ -16,13 +16,20 @@
same_tile = 0
can_throw = 1
force_danger = 1
- breakability = 3
+ breakability = 4
icon_state = "reinforce1"
- break_chance_table = list(5, 20, 40, 80, 100)
-/datum/grab/normal/aggressive/process_effect(var/obj/item/grab/G)
+ break_chance_table = list(25, 30, 35, 40, 45, 50, 55)
+
+/datum/grab/normal/aggressive/process_effect(obj/item/grab/G)
var/mob/living/carbon/human/affecting = G.affecting
+ var/mob/living/carbon/human/assailant = G.assailant
+
+ if(assailant.incapacitated(INCAPACITATION_ALL))
+ affecting.visible_message(SPAN_WARNING("[assailant] lets go of \his grab!"))
+ qdel(G)
+ return
if(G.target_zone in list(BP_L_HAND, BP_R_HAND))
affecting.drop_l_hand()
@@ -32,7 +39,7 @@
if(affecting.lying)
affecting.Weaken(4)
-/datum/grab/normal/aggressive/can_upgrade(var/obj/item/grab/G)
+/datum/grab/normal/aggressive/can_upgrade(obj/item/grab/G)
if(!(G.target_zone in list(BP_CHEST, BP_HEAD)))
to_chat(G.assailant, "You need to be grabbing their torso or head for this!")
return FALSE
@@ -41,4 +48,4 @@
if((C.max_pressure_protection) && C.armor["melee"] > 20)
to_chat(G.assailant, "\The [C] is in the way!")
return FALSE
- return TRUE
\ No newline at end of file
+ return TRUE
diff --git a/code/modules/mob/grab/normal/norm_kill.dm b/code/modules/mob/grab/normal/norm_kill.dm
index ac3a202404b..57f50cf203c 100644
--- a/code/modules/mob/grab/normal/norm_kill.dm
+++ b/code/modules/mob/grab/normal/norm_kill.dm
@@ -20,10 +20,16 @@
icon_state = "kill1"
- break_chance_table = list(5, 20, 40, 80, 100)
+ break_chance_table = list(3, 4, 5, 6, 7)
-/datum/grab/normal/kill/process_effect(var/obj/item/grab/G)
+/datum/grab/normal/kill/process_effect(obj/item/grab/G)
var/mob/living/carbon/human/affecting = G.affecting
+ var/mob/living/carbon/human/assailant = G.assailant
+
+ if(assailant.incapacitated(INCAPACITATION_ALL))
+ affecting.visible_message(SPAN_WARNING("[assailant] lets go of \his grab!"))
+ qdel(G)
+ return
affecting.drop_l_hand()
affecting.drop_r_hand()
@@ -33,6 +39,6 @@
affecting.adjustOxyLoss(1)
- affecting.apply_effect(STUTTER, 5) //It will hamper your voice, being choked and all.
- affecting.Weaken(5) //Should keep you down unless you get help.
+ affecting.apply_effect(STUTTER, 5) // It will hamper your voice, being choked and all.
+ affecting.Weaken(5) // Should keep you down unless you get help.
affecting.losebreath = max(affecting.losebreath + 2, 3)
diff --git a/code/modules/mob/grab/normal/norm_neck.dm b/code/modules/mob/grab/normal/norm_neck.dm
index 357f4e51b95..3033553310d 100644
--- a/code/modules/mob/grab/normal/norm_neck.dm
+++ b/code/modules/mob/grab/normal/norm_neck.dm
@@ -10,6 +10,7 @@
stop_move = 1
+ force_stand = TRUE
reverse_facing = 1
can_absorb = 1
shield_assailant = 1
@@ -22,10 +23,16 @@
icon_state = "kill"
- break_chance_table = list(3, 18, 45, 100)
+ break_chance_table = list(3, 5, 7, 9)
-/datum/grab/normal/neck/process_effect(var/obj/item/grab/G)
+/datum/grab/normal/neck/process_effect(obj/item/grab/G)
var/mob/living/carbon/human/affecting = G.affecting
+ var/mob/living/carbon/human/assailant = G.assailant
+
+ if(assailant.incapacitated(INCAPACITATION_ALL))
+ affecting.visible_message(SPAN_WARNING("[assailant] lets go of \his grab!"))
+ qdel(G)
+ return
affecting.drop_l_hand()
affecting.drop_r_hand()
@@ -33,4 +40,12 @@
if(affecting.lying)
affecting.Weaken(4)
+ if(affecting.stat != CONSCIOUS)
+ force_stand = FALSE
+ shield_assailant = FALSE
+
+ else
+ force_stand = TRUE
+ shield_assailant = TRUE
+
affecting.adjustOxyLoss(1)
diff --git a/code/modules/mob/grab/normal/norm_struggle.dm b/code/modules/mob/grab/normal/norm_struggle.dm
index cc76dfa958b..a499d6d9715 100644
--- a/code/modules/mob/grab/normal/norm_struggle.dm
+++ b/code/modules/mob/grab/normal/norm_struggle.dm
@@ -12,7 +12,7 @@
can_absorb = 0
point_blank_mult = 1
same_tile = 0
- breakability = 3
+ breakability = 4
grab_slowdown = 10
upgrade_cooldown = 20
@@ -21,19 +21,23 @@
icon_state = "reinforce"
- break_chance_table = list(5, 20, 30, 80, 100)
+ break_chance_table = list(35, 40, 45, 50, 55, 60, 65)
-
-/datum/grab/normal/struggle/process_effect(var/obj/item/grab/G)
+/datum/grab/normal/struggle/process_effect(obj/item/grab/G)
var/mob/living/carbon/human/affecting = G.affecting
var/mob/living/carbon/human/assailant = G.assailant
+ if(assailant.incapacitated(INCAPACITATION_ALL))
+ affecting.visible_message(SPAN_WARNING("[assailant] lets go of \his grab!"))
+ qdel(G)
+ return
+
if(affecting.incapacitated(INCAPACITATION_UNRESISTING) || affecting.a_intent == I_HELP)
affecting.visible_message("[affecting] isn't prepared to fight back as [assailant] tightens \his grip!")
G.done_struggle = TRUE
G.upgrade(TRUE)
-/datum/grab/normal/struggle/enter_as_up(var/obj/item/grab/G)
+/datum/grab/normal/struggle/enter_as_up(obj/item/grab/G)
var/mob/living/carbon/human/affecting = G.affecting
var/mob/living/carbon/human/assailant = G.assailant
@@ -52,7 +56,7 @@
addtimer(CALLBACK(G, .proc/handle_resist), 1 SECOND)
resolve_struggle(G)
-/datum/grab/normal/struggle/proc/resolve_struggle(var/obj/item/grab/G)
+/datum/grab/normal/struggle/proc/resolve_struggle(obj/item/grab/G)
set waitfor = FALSE
if(do_after(G.assailant, upgrade_cooldown, G, do_flags = DO_DEFAULT | DO_USER_CAN_MOVE))
G.done_struggle = TRUE
@@ -60,20 +64,20 @@
else
G.downgrade()
-/datum/grab/normal/struggle/can_upgrade(var/obj/item/grab/G)
+/datum/grab/normal/struggle/can_upgrade(obj/item/grab/G)
return G.done_struggle
-/datum/grab/normal/struggle/on_hit_disarm(var/obj/item/grab/normal/G)
+/datum/grab/normal/struggle/on_hit_disarm(obj/item/grab/normal/G)
to_chat(G.assailant, "Your grip isn't strong enough to pin.")
- return 0
+ return FALSE
-/datum/grab/normal/struggle/on_hit_grab(var/obj/item/grab/normal/G)
+/datum/grab/normal/struggle/on_hit_grab(obj/item/grab/normal/G)
to_chat(G.assailant, "Your grip isn't strong enough to jointlock.")
- return 0
+ return FALSE
-/datum/grab/normal/struggle/on_hit_harm(var/obj/item/grab/normal/G)
+/datum/grab/normal/struggle/on_hit_harm(obj/item/grab/normal/G)
to_chat(G.assailant, "Your grip isn't strong enough to dislocate.")
- return 0
+ return FALSE
-/datum/grab/normal/struggle/resolve_openhand_attack(var/obj/item/grab/G)
- return 0
+/datum/grab/normal/struggle/resolve_openhand_attack(obj/item/grab/G)
+ return FALSE
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 1a75e107499..dc1fe222d1d 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -1724,6 +1724,14 @@
. += 15
if(shock_stage > 30)
. += 15
+ if(confused)
+ . += 15
+ if(weakened)
+ . += 15
+ if(eye_blurry)
+ . += 15
+ if(eye_blind)
+ . += 60
/mob/living/carbon/human/ranged_accuracy_mods()
. = ..()
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 12c5eab3b74..505022c83b0 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -142,7 +142,7 @@ meteor_act
return target_zone
var/accuracy_penalty = user.melee_accuracy_mods()
- accuracy_penalty += 10*get_skill_difference(SKILL_COMBAT, user)
+ accuracy_penalty += 5*get_skill_difference(SKILL_COMBAT, user)
accuracy_penalty += 10*(I.w_class - ITEM_SIZE_NORMAL)
accuracy_penalty -= I.melee_accuracy_bonus
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 74006e3b125..644401db125 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -579,8 +579,11 @@ default behaviour is:
else
var/mob/living/M = pulling
if(M.grabbed_by.len)
- if (prob(75))
- var/obj/item/grab/G = pick(M.grabbed_by)
+ var/obj/item/grab/G = pick(M.grabbed_by)
+ if(G.current_grab.shield_assailant)
+ visible_message(SPAN_WARNING("\The [G.assailant] stops \the [src] from pulling \the [G.affecting] from their grip!"), SPAN_WARNING("\The [G.assailant] is holding \the [G.affecting] too tight for you to pull them away!"))
+ return
+ if(prob(75))
if(istype(G))
M.visible_message(SPAN_WARNING("[G.affecting] has been pulled from [G.assailant]'s grip by [src]!"), SPAN_WARNING("[G.affecting] has been pulled from your grip by [src]!"))
qdel(G)
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index e8a2206b3d9..a49f2134433 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -600,17 +600,25 @@
if(pullin)
pullin.icon_state = "pull0"
-/mob/proc/start_pulling(var/atom/movable/AM)
-
- if ( !AM || !usr || src==AM || !isturf(src.loc) ) //if there's no person pulling OR the person is pulling themself OR the object being pulled is inside something: abort!
+/mob/proc/start_pulling(atom/movable/AM)
+ if (!AM || !usr || src==AM || !isturf(src.loc) ) // If there's no person pulling OR the person is pulling themself OR the object being pulled is inside something: abort!
return
- if (AM.anchored)
+ if(AM.anchored)
to_chat(src, "It won't budge!")
return
var/mob/M = AM
if(ismob(AM))
+ var/obj/item/grab/G = locate() in M
+ if(istype(G))
+ if(G.current_grab.shield_assailant) // Check that the pull target isn't holding someone hostage to prevent just yanking them away from their victim.
+ visible_message(SPAN_WARNING("\The [G.assailant] uses \the [G.affecting] to block \the [src] from getting a firm grip!"), SPAN_WARNING("Your grip is blocked by \the [G.assailant] using \the [G.affecting] as a shield!"))
+ return
+ if(prob(25))
+ visible_message(SPAN_WARNING("\The [src] fails to pull \the [G.assailant] away from \the [G.affecting]!"), SPAN_WARNING("You fail to pull \the [G.assailant] away from \the [G.affecting]!"))
+ return
+ qdel(G) // Makes sure dragging the assailant away from their victim makes them release the grab instead of holding it at long range forever.
if(!can_pull_mobs || !can_pull_size)
to_chat(src, "It won't budge!")
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index 9128fb1f81c..c8f7cdf7f54 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -1,6 +1,21 @@
/mob
var/moving = FALSE
+/mob/forceMove(atom/dest)
+ . = ..()
+ GrabsDistanceCheck()
+
+/mob/proc/GrabsDistanceCheck()
+ if(!LAZYLEN(grabbed_by))
+ return
+ for(var/obj/item/grab/G in grabbed_by)
+ var/mob/living/carbon/human/user = G.assailant
+ if(!istype(user))
+ qdel(G)
+ continue
+ if(get_dist(user, src) > 1 || user.z != z)
+ qdel(G)
+
/mob/proc/SelfMove(var/direction)
if(direction == UP || direction == DOWN)
if(buckled)
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index accf1004b0d..e39b44a0a91 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -296,7 +296,7 @@
//if they have a neck grab on someone, that person gets hit instead
var/obj/item/grab/G = locate() in M
if(G && G.shield_assailant())
- visible_message("\The [M] uses [G.affecting] as a shield!")
+ G.affecting.visible_message(SPAN_DANGER("\The [M] uses \the [G.affecting] as a shield!"))
if(Bump(G.affecting, forced=1))
return //If Bump() returns 0 (keep going) then we continue on to attack M.
diff --git a/code/modules/species/species.dm b/code/modules/species/species.dm
index ed11011560c..1e4017081f2 100644
--- a/code/modules/species/species.dm
+++ b/code/modules/species/species.dm
@@ -354,7 +354,7 @@ The slots that you can use are found in items_clothing.dm and are the inventory
var/obj/item/organ/limb_path = organ_data["path"]
organ_data["descriptor"] = initial(limb_path.name)
-/datum/species/proc/equip_survival_gear(var/mob/living/carbon/human/H,var/extendedtank = 1)
+/datum/species/proc/equip_survival_gear(mob/living/carbon/human/H, extendedtank = 1)
if(istype(H.get_equipped_item(slot_back), /obj/item/storage/backpack))
if (extendedtank) H.equip_to_slot_or_del(new /obj/item/storage/box/engineer(H.back), slot_in_backpack)
else H.equip_to_slot_or_del(new /obj/item/storage/box/survival(H.back), slot_in_backpack)
@@ -362,7 +362,7 @@ The slots that you can use are found in items_clothing.dm and are the inventory
if (extendedtank) H.equip_to_slot_or_del(new /obj/item/storage/box/engineer(H), slot_r_hand)
else H.equip_to_slot_or_del(new /obj/item/storage/box/survival(H), slot_r_hand)
-/datum/species/proc/create_organs(var/mob/living/carbon/human/H) //Handles creation of mob organs.
+/datum/species/proc/create_organs(mob/living/carbon/human/H) //Handles creation of mob organs.
H.mob_size = mob_size
for(var/obj/item/organ/organ in H.contents)
@@ -404,7 +404,7 @@ The slots that you can use are found in items_clothing.dm and are the inventory
H.sync_organ_dna()
-/datum/species/proc/hug(var/mob/living/carbon/human/H,var/mob/living/target)
+/datum/species/proc/hug(mob/living/carbon/human/H, mob/living/target)
var/t_him = "them"
switch(target.gender)
@@ -434,12 +434,12 @@ The slots that you can use are found in items_clothing.dm and are the inventory
H.update_personal_goal(/datum/goal/achievement/givehug, TRUE)
target.update_personal_goal(/datum/goal/achievement/gethug, TRUE)
-/datum/species/proc/add_base_auras(var/mob/living/carbon/human/H)
+/datum/species/proc/add_base_auras(mob/living/carbon/human/H)
if(base_auras)
for(var/type in base_auras)
H.add_aura(new type(H))
-/datum/species/proc/remove_base_auras(var/mob/living/carbon/human/H)
+/datum/species/proc/remove_base_auras(mob/living/carbon/human/H)
if(base_auras)
var/list/bcopy = base_auras.Copy()
for(var/a in H.auras)
@@ -449,19 +449,19 @@ The slots that you can use are found in items_clothing.dm and are the inventory
H.remove_aura(A)
qdel(A)
-/datum/species/proc/remove_inherent_verbs(var/mob/living/carbon/human/H)
+/datum/species/proc/remove_inherent_verbs(mob/living/carbon/human/H)
if(inherent_verbs)
for(var/verb_path in inherent_verbs)
H.verbs -= verb_path
return
-/datum/species/proc/add_inherent_verbs(var/mob/living/carbon/human/H)
+/datum/species/proc/add_inherent_verbs(mob/living/carbon/human/H)
if(inherent_verbs)
for(var/verb_path in inherent_verbs)
H.verbs |= verb_path
return
-/datum/species/proc/handle_post_spawn(var/mob/living/carbon/human/H) //Handles anything not already covered by basic species assignment.
+/datum/species/proc/handle_post_spawn(mob/living/carbon/human/H) //Handles anything not already covered by basic species assignment.
add_inherent_verbs(H)
add_base_auras(H)
H.mob_bump_flag = bump_flag
@@ -470,16 +470,16 @@ The slots that you can use are found in items_clothing.dm and are the inventory
H.pass_flags = pass_flags
handle_limbs_setup(H)
-/datum/species/proc/handle_pre_spawn(var/mob/living/carbon/human/H)
+/datum/species/proc/handle_pre_spawn(mob/living/carbon/human/H)
return
-/datum/species/proc/handle_death(var/mob/living/carbon/human/H) //Handles any species-specific death events (such as dionaea nymph spawns).
+/datum/species/proc/handle_death(mob/living/carbon/human/H) //Handles any species-specific death events (such as dionaea nymph spawns).
return
-/datum/species/proc/handle_new_grab(var/mob/living/carbon/human/H, var/obj/item/grab/G)
+/datum/species/proc/handle_new_grab(mob/living/carbon/human/H, obj/item/grab/G)
return
-/datum/species/proc/handle_sleeping(var/mob/living/carbon/human/H)
+/datum/species/proc/handle_sleeping(mob/living/carbon/human/H)
if(prob(2) && !H.failed_last_breath && !H.isSynthetic())
if(!H.paralysis)
H.emote("snore")
@@ -487,37 +487,37 @@ The slots that you can use are found in items_clothing.dm and are the inventory
H.emote("groan")
// Only used for alien plasma weeds atm, but could be used for Dionaea later.
-/datum/species/proc/handle_environment_special(var/mob/living/carbon/human/H)
+/datum/species/proc/handle_environment_special(mob/living/carbon/human/H)
return
-/datum/species/proc/handle_movement_delay_special(var/mob/living/carbon/human/H)
+/datum/species/proc/handle_movement_delay_special(mob/living/carbon/human/H)
return 0
// Used to update alien icons for aliens.
-/datum/species/proc/handle_login_special(var/mob/living/carbon/human/H)
+/datum/species/proc/handle_login_special(mob/living/carbon/human/H)
return
// As above.
-/datum/species/proc/handle_logout_special(var/mob/living/carbon/human/H)
+/datum/species/proc/handle_logout_special(mob/living/carbon/human/H)
return
// Builds the HUD using species-specific icons and usable slots.
-/datum/species/proc/build_hud(var/mob/living/carbon/human/H)
+/datum/species/proc/build_hud(mob/living/carbon/human/H)
return
//Used by xenos understanding larvae and dionaea understanding nymphs.
-/datum/species/proc/can_understand(var/mob/other)
+/datum/species/proc/can_understand(mob/other)
return
-/datum/species/proc/can_overcome_gravity(var/mob/living/carbon/human/H)
+/datum/species/proc/can_overcome_gravity(mob/living/carbon/human/H)
return FALSE
// Used for any extra behaviour when falling and to see if a species will fall at all.
-/datum/species/proc/can_fall(var/mob/living/carbon/human/H)
+/datum/species/proc/can_fall(mob/living/carbon/human/H)
return TRUE
//Used for swimming
-/datum/species/proc/can_float(var/mob/living/carbon/human/H)
+/datum/species/proc/can_float(mob/living/carbon/human/H)
if(!H.is_physically_disabled())
if(H.skill_check(SKILL_HAULING, SKILL_BASIC))
if(H.encumbrance() < 1)
@@ -525,11 +525,11 @@ The slots that you can use are found in items_clothing.dm and are the inventory
return FALSE
// Used to override normal fall behaviour. Use only when the species does fall down a level.
-/datum/species/proc/handle_fall_special(var/mob/living/carbon/human/H, var/turf/landing)
+/datum/species/proc/handle_fall_special(mob/living/carbon/human/H, turf/landing)
return FALSE
// Called when using the shredding behavior.
-/datum/species/proc/can_shred(var/mob/living/carbon/human/H, var/ignore_intent, var/ignore_antag)
+/datum/species/proc/can_shred(mob/living/carbon/human/H, ignore_intent, ignore_antag)
if((!ignore_intent && H.a_intent != I_HURT) || H.pulling_punches)
return 0
@@ -546,10 +546,10 @@ The slots that you can use are found in items_clothing.dm and are the inventory
return 0
// Called in life() when the mob has no client.
-/datum/species/proc/handle_npc(var/mob/living/carbon/human/H)
+/datum/species/proc/handle_npc(mob/living/carbon/human/H)
return
-/datum/species/proc/handle_vision(var/mob/living/carbon/human/H)
+/datum/species/proc/handle_vision(mob/living/carbon/human/H)
var/list/vision = H.get_accumulated_vision_handlers()
H.update_sight()
H.set_sight(H.sight|get_vision_flags(H)|H.equipment_vision_flags|vision[1])
@@ -584,7 +584,7 @@ The slots that you can use are found in items_clothing.dm and are the inventory
return 1
-/datum/species/proc/get_how_nearsighted(var/mob/living/carbon/human/H)
+/datum/species/proc/get_how_nearsighted(mob/living/carbon/human/H)
var/prescriptions = short_sighted
if(H.disabilities & NEARSIGHTED)
prescriptions += 7
@@ -608,7 +608,7 @@ The slots that you can use are found in items_clothing.dm and are the inventory
light -= H.equipment_light_protection
return Clamp(max(prescriptions, light), 0, 7)
-/datum/species/proc/set_default_hair(var/mob/living/carbon/human/H)
+/datum/species/proc/set_default_hair(mob/living/carbon/human/H)
H.h_style = H.species.default_h_style
H.f_style = H.species.default_f_style
H.update_hair()
@@ -616,16 +616,16 @@ The slots that you can use are found in items_clothing.dm and are the inventory
/datum/species/proc/get_blood_name()
return "blood"
-/datum/species/proc/handle_death_check(var/mob/living/carbon/human/H)
+/datum/species/proc/handle_death_check(mob/living/carbon/human/H)
return FALSE
//Mostly for toasters
-/datum/species/proc/handle_limbs_setup(var/mob/living/carbon/human/H)
+/datum/species/proc/handle_limbs_setup(mob/living/carbon/human/H)
for(var/thing in H.organs)
post_organ_rejuvenate(thing, H)
// Impliments different trails for species depending on if they're wearing shoes.
-/datum/species/proc/get_move_trail(var/mob/living/carbon/human/H)
+/datum/species/proc/get_move_trail(mob/living/carbon/human/H)
if(H.lying)
return /obj/effect/decal/cleanable/blood/tracks/body
if(H.shoes || (H.wear_suit && (H.wear_suit.body_parts_covered & FEET)))
@@ -634,10 +634,10 @@ The slots that you can use are found in items_clothing.dm and are the inventory
else
return move_trail
-/datum/species/proc/update_skin(var/mob/living/carbon/human/H)
+/datum/species/proc/update_skin(mob/living/carbon/human/H)
return
-/datum/species/proc/disarm_attackhand(var/mob/living/carbon/human/attacker, var/mob/living/carbon/human/target)
+/datum/species/proc/disarm_attackhand(mob/living/carbon/human/attacker, mob/living/carbon/human/target)
attacker.do_attack_animation(target)
if(target.w_uniform)
@@ -646,30 +646,32 @@ The slots that you can use are found in items_clothing.dm and are the inventory
var/list/holding = list(target.get_active_hand() = 60, target.get_inactive_hand() = 30)
- var/skill_mod = 10 * attacker.get_skill_difference(SKILL_COMBAT, target)
+ var/skill_mod = attacker.get_skill_difference(SKILL_COMBAT, target)
var/state_mod = attacker.melee_accuracy_mods() - target.melee_accuracy_mods()
var/stim_mod = target.chem_effects[CE_STIMULANT]
- var/push_mod = min(max(1 + attacker.get_skill_difference(SKILL_COMBAT, target), 1), 3)
+ var/push_threshold = 12 + (skill_mod - stim_mod)
+ var/disarm_threshold = 24 + ((skill_mod - stim_mod) * 2)
+
if(target.a_intent == I_HELP)
state_mod -= 30
//Handle unintended consequences
for(var/obj/item/I in holding)
- var/hurt_prob = max(holding[I] - 2*skill_mod + state_mod, 0)
+ var/hurt_prob = max(holding[I] - 3*skill_mod, 0)
if(prob(hurt_prob) && I.on_disarm_attempt(target, attacker))
return
- var/randn = rand(1, 100) - skill_mod + state_mod - stim_mod
- if(randn <= 20 && !target.species.check_no_slip(target))
+ var/randn = rand(1, 100) + state_mod
+ if(!(check_no_slip(target)) && randn <= push_threshold)
var/armor_check = 100 * target.get_blocked_ratio(affecting, BRUTE, damage = 20)
playsound(target.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
if(armor_check < 100)
target.visible_message("[attacker] has pushed [target]!")
- target.apply_effect(push_mod, WEAKEN, armor_check)
+ target.apply_effect(2, WEAKEN, armor_check)
else
target.visible_message("[attacker] attempted to push [target]!")
return
- if(randn <= 50)
+ if(randn <= disarm_threshold)
//See about breaking grips or pulls
if(target.break_all_grabs(attacker))
playsound(target.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
@@ -685,7 +687,7 @@ The slots that you can use are found in items_clothing.dm and are the inventory
playsound(target.loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
target.visible_message("[attacker] attempted to disarm \the [target]!")
-/datum/species/proc/disfigure_msg(var/mob/living/carbon/human/H) //Used for determining the message a disfigured face has on examine. To add a unique message, just add this onto a specific species and change the "return" message.
+/datum/species/proc/disfigure_msg(mob/living/carbon/human/H) // Used for determining the message a disfigured face has on examine. To add a unique message, just add this onto a specific species and change the "return" message.
var/datum/gender/T = gender_datums[H.get_gender()]
return "[T.His] face is horribly mangled!\n"
@@ -713,7 +715,7 @@ The slots that you can use are found in items_clothing.dm and are the inventory
L[hairstyle] = S
return L
-/datum/species/proc/get_facial_hair_styles(var/gender)
+/datum/species/proc/get_facial_hair_styles(gender)
var/list/facial_hair_styles_by_species = LAZYACCESS(facial_hair_styles, type)
if(!facial_hair_styles_by_species)
facial_hair_styles_by_species = list()
@@ -739,7 +741,7 @@ The slots that you can use are found in items_clothing.dm and are the inventory
return facial_hair_style_by_gender
-/datum/species/proc/get_description(var/header, var/append, var/verbose = TRUE, var/skip_detail, var/skip_photo)
+/datum/species/proc/get_description(header, append, verbose = TRUE, skip_detail, skip_photo)
var/list/damage_types = list(
"physical trauma" = brute_mod,
"burns" = burn_mod,
@@ -818,15 +820,15 @@ The slots that you can use are found in items_clothing.dm and are the inventory
show_browser(src, species.get_description(), "window=species;size=700x400")
-/datum/species/proc/post_organ_rejuvenate(var/obj/item/organ/org, var/mob/living/carbon/human/H)
+/datum/species/proc/post_organ_rejuvenate(obj/item/organ/org, mob/living/carbon/human/H)
return
-/datum/species/proc/check_no_slip(var/mob/living/carbon/human/H)
+/datum/species/proc/check_no_slip(mob/living/carbon/human/H)
if(can_overcome_gravity(H))
return TRUE
return (species_flags & SPECIES_FLAG_NO_SLIP)
-/datum/species/proc/get_pain_emote(var/mob/living/carbon/human/H, var/pain_power)
+/datum/species/proc/get_pain_emote(mob/living/carbon/human/H, pain_power)
if(!(species_flags & SPECIES_FLAG_NO_PAIN))
return
for(var/pain_emotes in pain_emotes_with_pain_level)