From 6479c909cdf2a9d9fd340a951a4bd0bf0b4730f9 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Tue, 17 Feb 2015 23:40:51 -0500 Subject: [PATCH] Updates grabs Replaces broken client/Process_Grab(), makes resisting neck grabs actually work. Fixes the grabbed_by list filling up with null entries when a grab is broken. Aggressive grabs now prevent movement, can still be quickly broken using resist or disarm. Neck grabs are easier to resist if the grabber has moved recently. Some minor cleanup. --- .../living/carbon/human/human_attackhand.dm | 10 +- code/modules/mob/living/living.dm | 29 +++-- code/modules/mob/mob.dm | 7 +- code/modules/mob/mob_grab.dm | 101 +++++++++--------- code/modules/mob/mob_movement.dm | 29 ++--- 5 files changed, 83 insertions(+), 93 deletions(-) diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index bb02aee5e0..8dd2e06067 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -209,7 +209,7 @@ w_uniform.add_fingerprint(M) var/datum/organ/external/affecting = get_organ(ran_zone(M.zone_sel.selecting)) - if (istype(r_hand,/obj/item/weapon/gun) || istype(l_hand,/obj/item/weapon/gun)) + if(istype(r_hand,/obj/item/weapon/gun) || istype(l_hand,/obj/item/weapon/gun)) var/obj/item/weapon/gun/W = null var/chance = 0 @@ -231,9 +231,13 @@ var/randn = rand(1, 100) if(!(species.flags & NO_SLIP) && randn <= 25) - apply_effect(3, WEAKEN, run_armor_check(affecting, "melee")) + var/armor_check = run_armor_check(affecting, "melee") + apply_effect(3, WEAKEN, armor_check) playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - visible_message("\red [M] has pushed [src]!") + if(armor_check < 2) + visible_message("[M] has pushed [src]!") + else + visible_message("[M] attempted to push [src]!") return var/talked = 0 // BubbleWrap diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 68e9b0f0e8..5d2e1aa504 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -514,7 +514,7 @@ return //resisting grabs (as if it helps anyone...) - if ((!( L.stat ) && L.canmove && !( L.restrained() ))) + if ((!( L.stat ) && !( L.restrained() ))) var/resisting = 0 for(var/obj/O in L.requests) L.requests.Remove(O) @@ -522,23 +522,20 @@ resisting++ for(var/obj/item/weapon/grab/G in usr.grabbed_by) resisting++ - if (G.state == 1) - del(G) - else - if (G.state == 2) - if (prob(25)) - for(var/mob/O in viewers(L, null)) - O.show_message(text("\red [] has broken free of []'s grip!", L, G.assailant), 1) + switch(G.state) + if(GRAB_PASSIVE) + del(G) + if(GRAB_AGGRESSIVE) + if(prob(60)) //same chance of breaking the grab as disarm + L.visible_message("[L] has broken free of [G.assailant]'s grip!") + del(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 < 20 || !L.stunned) && prob(15)) || prob(3)) + L.visible_message("[L] has broken free of [G.assailant]'s headlock!") del(G) - else - if (G.state == 3) - if (prob(5)) - for(var/mob/O in viewers(usr, null)) - O.show_message(text("\red [] has broken free of []'s headlock!", L, G.assailant), 1) - del(G) if(resisting) - for(var/mob/O in viewers(usr, null)) - O.show_message(text("\red [] resists!", L), 1) + L.visible_message("[L] resists!") //unbuckling yourself diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 5a86291dd5..73623ac043 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -868,7 +868,7 @@ note dizziness decrements automatically in the mob's Life() proc. else if( stat || weakened || paralysis || resting || sleeping || (status_flags & FAKEDEATH)) lying = 1 canmove = 0 - else if( stunned ) + else if(stunned) canmove = 0 else if(captured) anchored = 1 @@ -885,6 +885,11 @@ note dizziness decrements automatically in the mob's Life() proc. else density = 1 + for(var/obj/item/weapon/grab/G in grabbed_by) + if(G.state >= GRAB_AGGRESSIVE) + canmove = 0 + break + //Temporarily moved here from the various life() procs //I'm fixing stuff incrementally so this will likely find a better home. //It just makes sense for now. ~Carn diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm index ed11358838..2b47227dfe 100644 --- a/code/modules/mob/mob_grab.dm +++ b/code/modules/mob/mob_grab.dm @@ -35,6 +35,10 @@ hud.name = "reinforce grab" hud.master = src +/obj/item/weapon/grab/Del() + //make sure the grabbed_by list doesn't fill up with nulls + if(affecting) affecting.grabbed_by -= src + ..() //Used by throw code to hand over the mob, instead of throwing the grab. The grab is then deleted by the throw code. /obj/item/weapon/grab/proc/throw() @@ -67,6 +71,7 @@ if(state <= GRAB_AGGRESSIVE) allow_upgrade = 1 + //disallow upgrading if we're grabbing more than one person if((assailant.l_hand && assailant.l_hand != src && istype(assailant.l_hand, /obj/item/weapon/grab))) var/obj/item/weapon/grab/G = assailant.l_hand if(G.affecting != affecting) @@ -76,31 +81,29 @@ if(G.affecting != affecting) allow_upgrade = 0 if(state == GRAB_AGGRESSIVE) - var/h = affecting.hand - affecting.hand = 0 - affecting.drop_item() - affecting.hand = 1 - affecting.drop_item() - affecting.hand = h + affecting.drop_l_hand() + affecting.drop_r_hand() + //disallow upgrading past aggressive if we're being grabbed aggressively for(var/obj/item/weapon/grab/G in affecting.grabbed_by) if(G == src) continue - if(G.state == GRAB_AGGRESSIVE) + if(G.state >= GRAB_AGGRESSIVE) allow_upgrade = 0 if(allow_upgrade) hud.icon_state = "reinforce" else hud.icon_state = "!reinforce" - else - if(!affecting.buckled) - affecting.loc = assailant.loc + else if(!affecting.buckled) + affecting.loc = assailant.loc if(state >= GRAB_NECK) - affecting.Stun(5) //It will hamper your voice, being choked and all. + affecting.Stun(1) if(isliving(affecting)) var/mob/living/L = affecting L.adjustOxyLoss(1) if(state >= GRAB_KILL) + //affecting.apply_effect(STUTTER, 5) //would do this, but affecting isn't declared as mob/living for some stupid reason. + affecting.stuttering = max(affecting.stuttering, 5) //It will hamper your voice, being choked and all. affecting.Weaken(5) //Should keep you down unless you get help. affecting.losebreath = min(affecting.losebreath + 2, 3) @@ -126,48 +129,46 @@ assailant.visible_message("[assailant] has grabbed [affecting] aggressively (now hands)!") state = GRAB_AGGRESSIVE icon_state = "grabbed1" - else - if(state < GRAB_NECK) - if(isslime(affecting)) - assailant << "You squeeze [affecting], but nothing interesting happens." + else if(state < GRAB_NECK) + if(isslime(affecting)) + assailant << "You squeeze [affecting], but nothing interesting happens." + return + + assailant.visible_message("[assailant] has reinforced \his grip on [affecting] (now neck)!") + state = GRAB_NECK + icon_state = "grabbed+1" + if(!affecting.buckled) + affecting.loc = assailant.loc + affecting.attack_log += "\[[time_stamp()]\] Has had their neck grabbed by [assailant.name] ([assailant.ckey])" + assailant.attack_log += "\[[time_stamp()]\] Grabbed the neck of [affecting.name] ([affecting.ckey])" + msg_admin_attack("[key_name(assailant)] grabbed the neck of [key_name(affecting)]") + hud.icon_state = "disarm/kill" + hud.name = "disarm/kill" + else if(state < GRAB_UPGRADING) + assailant.visible_message("[assailant] starts to tighten \his grip on [affecting]'s neck!") + hud.icon_state = "disarm/kill1" + state = GRAB_UPGRADING + if(do_after(assailant, UPGRADE_KILL_TIMER)) + if(state == GRAB_KILL) return + if(!affecting) + del(src) + return + if(!assailant.canmove || assailant.lying) + del(src) + return + state = GRAB_KILL + assailant.visible_message("[assailant] has tightened \his grip on [affecting]'s neck!") + affecting.attack_log += "\[[time_stamp()]\] Has been strangled (kill intent) by [assailant.name] ([assailant.ckey])" + assailant.attack_log += "\[[time_stamp()]\] Strangled (kill intent) [affecting.name] ([affecting.ckey])" + msg_admin_attack("[key_name(assailant)] strangled (kill intent) [key_name(affecting)]") - assailant.visible_message("[assailant] has reinforced \his grip on [affecting] (now neck)!") - state = GRAB_NECK - icon_state = "grabbed+1" - if(!affecting.buckled) - affecting.loc = assailant.loc - affecting.attack_log += "\[[time_stamp()]\] Has had their neck grabbed by [assailant.name] ([assailant.ckey])" - assailant.attack_log += "\[[time_stamp()]\] Grabbed the neck of [affecting.name] ([affecting.ckey])" - msg_admin_attack("[key_name(assailant)] grabbed the neck of [key_name(affecting)]") - hud.icon_state = "disarm/kill" - hud.name = "disarm/kill" + assailant.next_move = world.time + 10 + affecting.losebreath += 1 else - if(state < GRAB_UPGRADING) - assailant.visible_message("[assailant] starts to tighten \his grip on [affecting]'s neck!") - hud.icon_state = "disarm/kill1" - state = GRAB_UPGRADING - if(do_after(assailant, UPGRADE_KILL_TIMER)) - if(state == GRAB_KILL) - return - if(!affecting) - del(src) - return - if(!assailant.canmove || assailant.lying) - del(src) - return - state = GRAB_KILL - assailant.visible_message("[assailant] has tightened \his grip on [affecting]'s neck!") - affecting.attack_log += "\[[time_stamp()]\] Has been strangled (kill intent) by [assailant.name] ([assailant.ckey])" - assailant.attack_log += "\[[time_stamp()]\] Strangled (kill intent) [affecting.name] ([affecting.ckey])" - msg_admin_attack("[key_name(assailant)] strangled (kill intent) [key_name(affecting)]") - - assailant.next_move = world.time + 10 - affecting.losebreath += 1 - else - assailant.visible_message("[assailant] was unable to tighten \his grip on [affecting]'s neck!") - hud.icon_state = "disarm/kill" - state = GRAB_NECK + assailant.visible_message("[assailant] was unable to tighten \his grip on [affecting]'s neck!") + hud.icon_state = "disarm/kill" + state = GRAB_NECK //This is used to make sure the victim hasn't managed to yackety sax away before using the grab. diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 84f74cacae..ad499e51e5 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -351,30 +351,13 @@ ///Process_Grab() ///Called by client/Move() -///Checks to see if you are being grabbed and if so attemps to break it +///Checks to see if you are grabbing anything and if moving will affect your grab. /client/proc/Process_Grab() - if(locate(/obj/item/weapon/grab, locate(/obj/item/weapon/grab, mob.grabbed_by.len))) - var/list/grabbing = list() - if(istype(mob.l_hand, /obj/item/weapon/grab)) - var/obj/item/weapon/grab/G = mob.l_hand - grabbing += G.affecting - if(istype(mob.r_hand, /obj/item/weapon/grab)) - var/obj/item/weapon/grab/G = mob.r_hand - grabbing += G.affecting - for(var/obj/item/weapon/grab/G in mob.grabbed_by) - if((G.state == 1)&&(!grabbing.Find(G.assailant))) del(G) - if(G.state == 2) - move_delay = world.time + 10 - if(!prob(25)) return 1 - mob.visible_message("\red [mob] has broken free of [G.assailant]'s grip!") - del(G) - if(G.state == 3) - move_delay = world.time + 10 - if(!prob(5)) return 1 - mob.visible_message("\red [mob] has broken free of [G.assailant]'s headlock!") - del(G) - return 0 - + for(var/obj/item/weapon/grab/G in list(mob.l_hand, mob.r_hand)) + if(G.state == GRAB_KILL) //no wandering across the station/asteroid while choking someone + mob.visible_message("[mob] lost \his tight grip on [G.affecting]'s neck!") + G.hud.icon_state = "disarm/kill" + G.state = GRAB_NECK ///Process_Incorpmove ///Called by client/Move()