Files
Bubberstation/code/modules/mob/living/basic/basic_defense.dm
Ghom 68677dc721 Disarm refactor, plus shoving people with shields (#80123)
## About The Pull Request
I wanted to add the ability to shove people with shields by
right-clicking your target, just like how it works barehanded.

This also required a solid refactor of disarm code, effectively bringing
down the core of it to `mob/living` from `mob/living/carbon` or
`mob/living/carbon/human`. This also means you can shove simple mobs
inside closets, bins and on tables.

Xenos and borgs are pretty much immune to regular disarms, but using a
shield will work (borgs and royal xenos are immune to the knockdown).

The riot shield armor has been balanced. It now tanks melee attacks
pretty well, but will break against bullets in just about 2 to 4 hits
depending on the bullet damage. I've always found the lack of sturdiness
of the riot shields for what they're supposed to be good for a bit
detrimental.

Because I've refactored an item flag into a trait, I've had to add a new
MOD module that grants protection from shove knockdown and staggering;
found pre-installed in the administrative MODsuit, but I've also added
it to the black market to make it cooler.

You can bash people with the strobe shield on combat mode.

## Why It's Good For The Game
Currently, shields are simply items that take a held slot in return of
some block chance without being anything special, save for the strobe
shield's integrated flash I guess, but are also a botherance as most
crumple under the duress of less than half a dozen attacks. Meanwhile
swords and other weapons with blok chance just don't care.
TL;DR, I want them a bit more remarkable, and flexible as a tool.

Of course, this ended up in a larger refactor because the right-click /
disarm code was inconsistent.

## Changelog

🆑
add: Shields (and pillows) can be used to shove people around the same
way barehanded right-clicking does. Xenos and borgs can actually be
moved this way.
add: Added a new MODsuit module, the bulwark module, which prevents
knockdown and staggering from shoving, and getting pushed away by thrown
objects. Inbuilt for the safeguard MODsuit, but one might also it in the
black market.
refactor: Disarming has been refactored. You can now shove simple
critters onto tables and into bins and closets
balance: Shields now take their own armor values and the armor
penetration of the attack they blocked when damaged. This means shields
are a bit sturdier now.
balance: Riot shields can tank a lot more damage against melee weapons,
but less against bullets.
qol: strobe shields can now be used to bash people while combat mode is
on.
/🆑
2024-01-16 19:35:56 -06:00

185 lines
6.3 KiB
Plaintext

/mob/living/basic/attack_hand(mob/living/carbon/human/user, list/modifiers)
// so that martial arts don't double dip
if (..())
return TRUE
if(LAZYACCESS(modifiers, RIGHT_CLICK))
user.disarm(src)
return TRUE
if(!user.combat_mode)
if (stat != DEAD)
visible_message(
span_notice("[user] [response_help_continuous] [src]."),
span_notice("[user] [response_help_continuous] you."),
ignored_mobs = user,
)
to_chat(user, span_notice("You [response_help_simple] [src]."))
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, TRUE, -1)
return TRUE
if(HAS_TRAIT(user, TRAIT_PACIFISM))
to_chat(user, span_warning("You don't want to hurt [src]!"))
return TRUE
var/obj/item/bodypart/arm/active_arm = user.get_active_hand()
var/damage = (basic_mob_flags & IMMUNE_TO_FISTS) ? 0 : rand(active_arm.unarmed_damage_low, active_arm.unarmed_damage_high)
if(check_block(user, damage, "[user]'s punch", UNARMED_ATTACK, 0, BRUTE))
return
user.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
visible_message(
span_danger("[user] [response_harm_continuous] [src]!"),
span_userdanger("[user] [response_harm_continuous] you!"),
vision_distance = COMBAT_MESSAGE_RANGE,
ignored_mobs = user,
)
to_chat(user, span_danger("You [response_harm_simple] [src]!"))
playsound(loc, attacked_sound, 25, TRUE, -1)
apply_damage(damage)
log_combat(user, src, "attacked")
updatehealth()
return TRUE
/mob/living/basic/get_shoving_message(mob/living/shover, obj/item/weapon, shove_flags)
if(weapon) // no "gently pushing aside" if you're pressing a shield at them.
return ..()
var/moved = !(shove_flags & SHOVE_BLOCKED)
shover.visible_message(
span_danger("[shover.name] [response_disarm_continuous] [src][moved ? ", pushing [p_them()]" : ""]!"),
span_danger("You [response_disarm_simple] [src][moved ? ", pushing [p_them()]" : ""]!"),
span_hear("You hear aggressive shuffling!"),
COMBAT_MESSAGE_RANGE,
list(src),
)
to_chat(src, span_userdanger("You're [moved ? "pushed" : "shoved"] by [shover.name]!"))
/mob/living/basic/attack_hulk(mob/living/carbon/human/user)
. = ..()
if(!.)
return
playsound(loc, SFX_PUNCH, 25, TRUE, -1)
visible_message(span_danger("[user] punches [src]!"), \
span_userdanger("You're punched by [user]!"), null, COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_danger("You punch [src]!"))
apply_damage(15, damagetype = BRUTE)
/mob/living/basic/attack_paw(mob/living/carbon/human/user, list/modifiers)
if(..()) //successful monkey bite.
if(stat != DEAD)
return apply_damage(rand(1, 3))
if (!user.combat_mode)
if (health > 0)
visible_message(span_notice("[user.name] [response_help_continuous] [src]."), \
span_notice("[user.name] [response_help_continuous] you."), null, COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_notice("You [response_help_simple] [src]."))
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, TRUE, -1)
/mob/living/basic/attack_alien(mob/living/carbon/alien/adult/user, list/modifiers)
. = ..()
if(!.)
return
if(LAZYACCESS(modifiers, RIGHT_CLICK))
playsound(loc, 'sound/weapons/pierce.ogg', 25, TRUE, -1)
visible_message(span_danger("[user] [response_disarm_continuous] [name]!"), \
span_userdanger("[user] [response_disarm_continuous] you!"), null, COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_danger("You [response_disarm_simple] [name]!"))
log_combat(user, src, "disarmed")
return
var/damage = rand(user.melee_damage_lower, user.melee_damage_upper)
visible_message(span_danger("[user] slashes at [src]!"), \
span_userdanger("You're slashed at by [user]!"), null, COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_danger("You slash at [src]!"))
playsound(loc, 'sound/weapons/slice.ogg', 25, TRUE, -1)
apply_damage(damage)
log_combat(user, src, "attacked")
/mob/living/basic/attack_larva(mob/living/carbon/alien/larva/attacking_larva, list/modifiers)
. = ..()
if(. && stat != DEAD) //successful larva bite
var/damage_done = apply_damage(rand(attacking_larva.melee_damage_lower, attacking_larva.melee_damage_upper), BRUTE)
if(damage_done > 0)
attacking_larva.amount_grown = min(attacking_larva.amount_grown + damage_done, attacking_larva.max_grown)
/mob/living/basic/attack_drone(mob/living/basic/drone/attacking_drone)
if(attacking_drone.combat_mode) //No kicking dogs even as a rogue drone. Use a weapon.
return
return ..()
/mob/living/basic/attack_drone_secondary(mob/living/basic/drone/attacking_drone)
if(attacking_drone.combat_mode)
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
return ..()
/mob/living/basic/check_projectile_armor(def_zone, obj/projectile/impacting_projectile, is_silent)
return 0
/mob/living/basic/ex_act(severity, target, origin)
. = ..()
if(!. || QDELETED(src))
return FALSE
var/bomb_armor = getarmor(null, BOMB)
switch(severity)
if (EXPLODE_DEVASTATE)
if(prob(bomb_armor))
apply_damage(500, damagetype = BRUTE)
else
investigate_log("has been gibbed by an explosion.", INVESTIGATE_DEATHS)
gib(DROP_ALL_REMAINS)
if (EXPLODE_HEAVY)
var/bloss = 60
if(prob(bomb_armor))
bloss = bloss / 1.5
apply_damage(bloss, damagetype = BRUTE)
if (EXPLODE_LIGHT)
var/bloss = 30
if(prob(bomb_armor))
bloss = bloss / 1.5
apply_damage(bloss, damagetype = BRUTE)
return TRUE
/mob/living/basic/blob_act(obj/structure/blob/attacking_blob)
. = ..()
if (!.)
return
apply_damage(20, damagetype = BRUTE)
/mob/living/basic/do_attack_animation(atom/attacked_atom, visual_effect_icon, used_item, no_effect)
if(!no_effect && !visual_effect_icon && melee_damage_upper)
if(attack_vis_effect && !iswallturf(attacked_atom)) // override the standard visual effect.
visual_effect_icon = attack_vis_effect
else if(melee_damage_upper < 10)
visual_effect_icon = ATTACK_EFFECT_PUNCH
else
visual_effect_icon = ATTACK_EFFECT_SMASH
..()
/mob/living/basic/update_stat()
if(status_flags & GODMODE)
return
if(stat != DEAD)
if(health <= 0)
death()
else
set_stat(CONSCIOUS)
med_hud_set_status()
/mob/living/basic/emp_act(severity)
. = ..()
if(mob_biotypes & MOB_ROBOTIC)
emp_reaction(severity)
/mob/living/basic/proc/emp_reaction(severity)
switch(severity)
if(EMP_LIGHT)
visible_message(span_danger("[src] shakes violently, its parts coming loose!"))
apply_damage(maxHealth * 0.6)
Shake(duration = 1 SECONDS)
if(EMP_HEAVY)
visible_message(span_danger("[src] suddenly bursts apart!"))
apply_damage(maxHealth)