mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-07-20 04:17:33 +01:00
Nerfs human shields (#22670)
Human shields are no longer a 100% chance to block any frontal damage. The opposite arm, legs and head are always exposed and can hit despite the human shield, though this comes with the additional miss-chance from targeting limbs. Additionally, destroyed limbs allow shots to damage both the hostage and the hostage taker when hit. This doesn't make the situation much better for the hostage, but it does mean that carrying around a corpse as a shield in combat is no longer viable. Size also matters, a Ta holding up a human as a shield isn't going to get much cover. <img width="1390" height="325" alt="image" src="https://github.com/user-attachments/assets/cfe61f99-89bb-428d-9f96-4b1fff32c646" /> https://github.com/user-attachments/assets/593acc65-f327-4058-ba8d-9bb596a43d3b
This commit is contained in:
@@ -379,19 +379,39 @@
|
||||
beam_segments[beam_index] = null
|
||||
|
||||
/obj/projectile/proc/check_human_shield(atom/A)
|
||||
if(!isliving(A) || !starting)
|
||||
if(!ishuman(A) || !starting)
|
||||
return FALSE
|
||||
|
||||
var/mob/living/M = A
|
||||
if(point_blank || !(M.dir & get_dir(M, starting)))
|
||||
var/mob/living/carbon/human/M = A
|
||||
var/list/left_hand_defense_zones = list(BP_L_ARM, BP_L_HAND, BP_CHEST, BP_GROIN)
|
||||
var/list/right_hand_defense_zones = list(BP_R_ARM, BP_R_HAND, BP_CHEST, BP_GROIN)
|
||||
if(point_blank || !(M.dir & get_dir(M, starting))) //Don't use the shield if the shot is at point blank, or the shot comes from behind or the sides.
|
||||
return FALSE
|
||||
|
||||
for(var/obj/item/grab/G in list(M.l_hand, M.r_hand))
|
||||
if(!G?.affecting || G.state < GRAB_NECK || G.affecting.lying)
|
||||
continue
|
||||
M.visible_message(SPAN_DANGER("\The [M] uses [G.affecting] as a shield!"))
|
||||
return G.affecting
|
||||
|
||||
if(G.affecting.mob_size < M.mob_size) //Humans are size 9, Unathi and Varuca workers 10, G1 & G2 are 11. This is mostly to make monkeys bad human shields.
|
||||
if (rand(1, M.mob_size) > G.affecting.mob_size)
|
||||
continue
|
||||
if(((G == M.l_hand) && (def_zone in left_hand_defense_zones)) || ((G == M.r_hand) && (def_zone in right_hand_defense_zones))) //Human shields only block shots to the arm holding the person, chest and groin.
|
||||
if(G.affecting.stat == DEAD) //If they are dead hit both the hostage and the hostage taker.
|
||||
penetrating += 1
|
||||
projectile_piercing = PASSMOB
|
||||
pierce_chance = 100
|
||||
M.visible_message(SPAN_WARNING("\The [M] tries to use [G.affecting] as a shield, but the shot punches through their limp body!"))
|
||||
return G.affecting
|
||||
else
|
||||
if(ishuman(G.affecting))
|
||||
var/mob/living/carbon/human/human_shield = G.affecting
|
||||
var/obj/item/organ/external/organ = human_shield.get_organ(def_zone)
|
||||
if(organ.burn_dam + organ.brute_dam > organ.max_damage) //If the hit zone is above the max damage threshold, the shot hits both.
|
||||
penetrating += 1
|
||||
projectile_piercing = PASSMOB
|
||||
pierce_chance = 100
|
||||
M.visible_message(SPAN_WARNING("\The [M] tries to use [G.affecting] as a shield, but the shot punches through their mangled [organ.name]!"))
|
||||
return G.affecting
|
||||
M.visible_message(SPAN_WARNING("\The [M] uses [G.affecting] as a shield!"))
|
||||
return G.affecting
|
||||
M.visible_message(SPAN_WARNING("\The [M] tries to use [G.affecting] as a shield but their [M.organs_by_name[def_zone]] is exposed!"))
|
||||
return FALSE
|
||||
|
||||
/obj/projectile/Collide(atom/A)
|
||||
@@ -420,12 +440,6 @@
|
||||
if(impacted[A.weak_reference]) // NEVER doublehit
|
||||
return FALSE
|
||||
var/turf/T = get_turf(A)
|
||||
var/atom/shield_target = check_human_shield(A)
|
||||
if(shield_target)
|
||||
var/datum/weakref/original_ref = A.weak_reference
|
||||
impacted[original_ref] = TRUE
|
||||
process_hit(T, shield_target, A)
|
||||
impacted -= original_ref
|
||||
var/datum/point/point_cache = trajectory.copy_to()
|
||||
if(ricochets < ricochets_max && check_ricochet_flag(A) && check_ricochet(A))
|
||||
ricochets++
|
||||
@@ -451,6 +465,15 @@
|
||||
if (!def_zone)
|
||||
A.visible_message(SPAN_NOTICE("\The [src] misses [A] narrowly!"))
|
||||
return FALSE
|
||||
var/atom/shield_target = check_human_shield(A)
|
||||
if(shield_target)
|
||||
var/datum/weakref/original_ref = A.weak_reference
|
||||
impacted[original_ref] = TRUE
|
||||
process_hit(T, shield_target, A)
|
||||
impacted -= original_ref
|
||||
penetrating = initial(penetrating)
|
||||
projectile_piercing = initial(projectile_piercing)
|
||||
pierce_chance = initial(pierce_chance)
|
||||
else
|
||||
def_zone = ran_zone(def_zone, clamp(accurate_range - (accuracy_falloff * distance), 5, 100)) //Lower accurancy/longer range tradeoff. 7 is a balanced number to use.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user