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)