From 3f5976bc3b27c2faa04e2defe71b1e79df86a149 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Sun, 31 May 2015 11:05:46 -0400 Subject: [PATCH] Updates knifing Fixes weirdness with knifing where attempting to knife someone before `world.time >= (G.last_action + 20)` could be met. Knifing damage scales with weapon force and an attempted measure of throat protection. Knifing switches on harm intent. --- code/_onclick/item_attack.dm | 25 +++-------- code/modules/mob/living/bot/bot.dm | 3 ++ code/modules/mob/living/living_defense.dm | 50 ++++++++++++++++++++++ code/modules/mob/living/silicon/silicon.dm | 4 +- 4 files changed, 63 insertions(+), 19 deletions(-) diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 0c8685162f..d3c3df942e 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -34,23 +34,6 @@ attacked_by() will handle hitting/missing/logging as it does now, and will call if(!istype(M) || (can_operate(M) && do_surgery(M,user,src))) return 0 - // Knifing - if(edge) - for(var/obj/item/weapon/grab/G in M.grabbed_by) - if(G.assailant == user && G.state >= GRAB_NECK && world.time >= (G.last_action + 20)) - //TODO: better alternative for applying damage multiple times? Nice knifing sound? - M.apply_damage(20, BRUTE, "head", 0, sharp=sharp, edge=edge) - M.apply_damage(20, BRUTE, "head", 0, sharp=sharp, edge=edge) - M.apply_damage(20, BRUTE, "head", 0, sharp=sharp, edge=edge) - M.adjustOxyLoss(60) // Brain lacks oxygen immediately, pass out - flick(G.hud.icon_state, G.hud) - G.last_action = world.time - user.visible_message("[user] slit [M]'s throat open with \the [name]!") - user.attack_log += "\[[time_stamp()]\] Knifed [M.name] ([M.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" - M.attack_log += "\[[time_stamp()]\] Got knifed by [user.name] ([user.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" - msg_admin_attack("[key_name(user)] knifed [key_name(M)] with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" ) - return - ///////////////////////// user.lastattacked = M M.lastattacker = user @@ -61,6 +44,12 @@ attacked_by() will handle hitting/missing/logging as it does now, and will call msg_admin_attack("[key_name(user)] attacked [key_name(M)] with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" ) ///////////////////////// + // Attacking someone with a weapon while they are neck-grabbed + if(user.a_intent == I_HURT) + for(var/obj/item/weapon/grab/G in M.grabbed_by) + if(G.assailant == user && G.state >= GRAB_NECK) + M.attack_throat(src, G, user) + var/power = force if(HULK in user.mutations) power *= 2 @@ -72,7 +61,7 @@ attacked_by() will handle hitting/missing/logging as it does now, and will call // Handle striking to cripple. var/dislocation_str - if(user.a_intent == "disarm") + if(user.a_intent == I_DISARM) dislocation_str = H.attack_joint(src, user, def_zone) if(H.attacked_by(src, user, def_zone) && hitsound) playsound(loc, hitsound, 50, 1, -1) diff --git a/code/modules/mob/living/bot/bot.dm b/code/modules/mob/living/bot/bot.dm index 36110c600c..649e4e5764 100644 --- a/code/modules/mob/living/bot/bot.dm +++ b/code/modules/mob/living/bot/bot.dm @@ -121,3 +121,6 @@ /mob/living/bot/proc/explode() qdel(src) + +/mob/living/bot/attack_throat() + return diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 9dd399a804..e5f4f12e7f 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -246,3 +246,53 @@ //Scale quadratically so that single digit numbers of fire stacks don't burn ridiculously hot. return round(FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE*(fire_stacks/FIRE_MAX_FIRESUIT_STACKS)**2) + +//If simple_animals are ever moved under carbon, then this can probably be moved to carbon as well +/mob/living/proc/attack_throat(obj/item/W, obj/item/weapon/grab/G, mob/user) + + // Knifing + if(!W.edge || !W.force || W.damtype != BRUTE) return //unsuitable weapon + + user.visible_message("\The [user] begins to slit [src]'s throat with \the [W]!") + + user.next_move = world.time + 20 //also should prevent user from triggering this repeatedly + if(!do_after(user, 20)) + return + if(!(G && G.assailant == user && G.affecting == src)) //check that we still have a grab + return + + var/damage_mod = 1 + //presumably, if they are wearing a helmet that stops pressure effects, then it probably covers the throat as well + var/obj/item/clothing/head/helmet = get_equipped_item(slot_head) + if(istype(helmet) && (helmet.body_parts_covered & HEAD) && (helmet.flags & STOPPRESSUREDAMAGE)) + //we don't do an armor_check here because this is not an impact effect like a weapon swung with momentum, that either penetrates or glances off. + damage_mod = 1.0 - (helmet.armor["melee"]/100) + + var/total_damage = 0 + for(var/i in 1 to 3) + var/damage = min(W.force*1.5, 20)*damage_mod + apply_damage(damage, W.damtype, "head", 0, sharp=W.sharp, edge=W.edge) + total_damage += damage + + var/oxyloss = total_damage + if(total_damage >= 40) //threshold to make someone pass out + oxyloss = 60 // Brain lacks oxygen immediately, pass out + + adjustOxyLoss(min(oxyloss, 100 - getOxyLoss())) //don't put them over 100 oxyloss + + if(total_damage) + if(oxyloss >= 40) + user.visible_message("\The [user] slit [src]'s throat open with \the [W]!") + else + user.visible_message("\The [user] cut [src]'s neck with \the [W]!") + + if(W.hitsound) + playsound(loc, W.hitsound, 50, 1, -1) + + G.last_action = world.time + flick(G.hud.icon_state, G.hud) + + user.attack_log += "\[[time_stamp()]\] Knifed [name] ([ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])" + src.attack_log += "\[[time_stamp()]\] Got knifed by [user.name] ([user.ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])" + msg_admin_attack("[key_name(user)] knifed [key_name(src)] with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])" ) + return diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index d2e30953e7..77b13a8b11 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -126,6 +126,9 @@ updatehealth() return 1*/ +/mob/living/silicon/attack_throat() + return + /proc/islinked(var/mob/living/silicon/robot/bot, var/mob/living/silicon/ai/ai) if(!istype(bot) || !istype(ai)) return 0 @@ -345,4 +348,3 @@ /mob/living/silicon/proc/is_malf_or_traitor() return is_traitor() || is_malf() -