[MIRROR] Riot armor and helmets (and similar gear) protect against more melee-based attacks (like RNG punches), bottles aren't near guaranteed knockdowns (#26633)

* Riot armor and helmets (and similar gear) protect against more melee-based attacks (like RNG punches), bottles aren't near guaranteed knockdowns (#81365)

<!-- Write **BELOW** The Headers and **ABOVE** The comments else it may
not be viewable. -->
<!-- You can view Contributing.MD for a detailed description of the pull
request process. -->

partially includes Syndicate modsuits and other suits with a module)

TRAIT_SHOVE_KNOCKDOWN_BLOCKED is now called
TRAIT_BRAWLING_KNOCKDOWN_BLOCKED. This is possessed by riot suits, SWAT
suits and now **plate armor**. Not the chaplain variety, because fuck
them I guess. (this was apparently deliberate so don't complain to me,
okay?)

Anyone with this trait is now unable to be knocked down by;

- Pure RNG on blunt objects attacks to the chest (Probability is
otherwise altered by melee armor already)
- Unarmed punches, both RNG and deterministic
- Bodies thrown at them. Instead, dealing stamina damage and causing
them to become staggered.

A new trait called TRAIT_HEAD_INJURY_BLOCKED, which protects from
various head injury related effects. This is possessed by riot helmets,
SWAT helmets, plate helmets, hardhats and applied to MODsuits with armor
boosters activated/the infiltrator suit while active.

The trait is also granted to anyone wearing a modsuit with the Head
Protection module installed. This can be printed from round start, and
comes pre-installed into all the engineering modsuits, security moduits,
research modsuit and magnate modsuit. (I had to bump up the security
modsuit complexity a bit to put it in iunno if we have a policy about
that)

Anyone with this trait is protected against:

- Bottle smashes to the head.
- RNG Blunt force trauma to the head by blunt objects (Probability is
otherwise altered by melee armor already)
- Partially protects against getting your spine snapped during a bad
tackle (this used to be a check ONLY for the riot helmet or hardhat)

The bottle smash's chance of a knockdown is based on the force and
knockdown duration of the bottle, altered by relevant head melee armor.
It's no longer basically guaranteed due to weird math that would
determine whether or not you were knocked down only if your armor
exceeded certain values or not.

Any instance that would check either for riot armor or riot helmets
instead checks for the new traits.

People weren't particularly happy with the possibility of getting
ownzoned by a naked assistant or random toolbox-wielding tider while in
dedicated melee protection armor as a result of pure RNG jank. [There
was a whole thread here about
it](https://tgstation13.org/phpBB/viewtopic.php?f=83&t=35645) with
regards to unarmed combat.

If you're in riot gear, you should feel like you can confidently combat
improvised/blunt weapons at a cost of general protection from the more
serious dangers to your wellbeing (AKA lead poisoning or heatstroke. Get
it....it's bullets and lasers...)

For some reason, bottle smash knockdowns, despite using the values
just...conveniently don't get blocked by armor except for extreme
values? If at all? I felt like this was really weird for something with
such a hefty and fairly powerful knockdown effect, particularly one you
can lob at someones head at range. I remember, way back when I first
started playing, that this was a feature that used to stun, and one I
used a lot to get cheap kills. The amount of bullshit stuns I got on
people with it still haunt me to this day. It hasn't improved in the
current era, despite being a knockdown, simply because any knockdown
still takes several seconds to exit. An arbitrarily low knockdown is
still a several second one. It's time to bring this in line with similar
equipment.

Rather than using flat values that are _clearly_ meant to be only
applicable to riot armor the decade ago that the code was written, let's
use traits instead. That's way better than relying on magic numbers that
may become irrelevant when the code around it changes, which anyone
touching that code may not even be aware existed.

Since we're using a trait, we can actually allow modsuits to
occasionally fill defensive niches that aren't strictly armor values.
Handy.

<!-- If your PR modifies aspects of the game that can be concretely
observed by players or admins you should add a changelog. If your change
does NOT meet this description, remove this section. Be sure to properly
mark your PRs to prevent unnecessary GBP loss. You can read up on GBP
and it's effects on PRs in the tgstation guides for contributors. Please
note that maintainers freely reserve the right to remove and add tags
should they deem it appropriate. You can attempt to finagle the system
all you want, but it's best to shoot for clear communication right off
the bat. -->

🆑
balance: Nanotrasen, in direct response to the increasing danger posed
by wannabe martial artists and rioters in the fringes of the Spinward
Sector, have upgraded the impact dampeners found in their riot armor.
Staff have also started to rediscover the value of medieval armor; it
isn't particularly easy to topple a knight in a suit of plate with just
your fists.
balance: Melee-focused armor is now more able to protect you from
various RNG-based knockdowns, such as critical hits from punches (as
well as the ones applied through the staggered status), shoves, critical
hits with a blunt weapon to the chest, and body throws.
balance: Melee-focused helmets also protect you from head injuries, such
as bottle smashes, accidentally hitting something dense during a tackle,
and critical hits from a blunt weapon to the head.
balance: Bottlesmash knockdowns are less reliable in general.
add: A new module, the Safety-First Head Protection module, protects you
from head trauma! Available in most modsuits expected to take hits to
the head often. And from roundstart exofabricators.
/🆑

<!-- Both 🆑's are required for the changelog to work! You can put
your name to the right of the first 🆑 if you want to overwrite your
GitHub username as author ingame. -->
<!-- You can use multiple of the same prefix (they're only used for the
icon ingame) and delete the unneeded ones. Despite some of the tags,
changelogs should generally represent how a player might be affected by
the changes rather than a summary of the PR's contents. -->

* oh well

---------

Co-authored-by: necromanceranne <40847847+necromanceranne@users.noreply.github.com>
Co-authored-by: Useroth <37159550+Useroth@users.noreply.github.com>
This commit is contained in:
SkyratBot
2024-02-27 01:59:40 +01:00
committed by GitHub
co-authored by necromanceranne Useroth
parent 11ecffbf8d
commit a0d0f8a7cd
22 changed files with 101 additions and 49 deletions
+4 -2
View File
@@ -211,8 +211,10 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_BLOOD_DEFICIENCY "blood_deficiency"
#define TRAIT_JOLLY "jolly"
#define TRAIT_NOCRITDAMAGE "no_crit"
/// Prevents shovies against a dense object from knocking them down.
#define TRAIT_SHOVE_KNOCKDOWN_BLOCKED "shove_knockdown_blocked"
/// Prevents shovies and some strong blows such as unarmed punches and (unreliably) tackles the owner down
#define TRAIT_BRAWLING_KNOCKDOWN_BLOCKED "brawling_knockdown_blocked"
/// Prevents some severe head injuries being sustained from heavy collisions or blunt force injuries.
#define TRAIT_HEAD_INJURY_BLOCKED "head_injury_blocked"
/// Prevents staggering.
#define TRAIT_NO_STAGGER "no_stagger"
/// Getting hit by thrown movables won't push you away
+2 -1
View File
@@ -140,6 +140,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_BONSAI" = TRAIT_BONSAI,
"TRAIT_BOOZE_SLIDER" = TRAIT_BOOZE_SLIDER,
"TRAIT_BRAINWASHING" = TRAIT_BRAINWASHING,
"TRAIT_BRAWLING_KNOCKDOWN_BLOCKED" = TRAIT_BRAWLING_KNOCKDOWN_BLOCKED,
"TRAIT_BYPASS_EARLY_IRRADIATED_CHECK" = TRAIT_BYPASS_EARLY_IRRADIATED_CHECK,
"TRAIT_BYPASS_MEASURES" = TRAIT_BYPASS_MEASURES,
"TRAIT_CANNOT_BE_UNBUCKLED" = TRAIT_CANNOT_BE_UNBUCKLED,
@@ -237,6 +238,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_HAS_CRANIAL_FISSURE" = TRAIT_HAS_CRANIAL_FISSURE,
"TRAIT_HAS_MARKINGS" = TRAIT_HAS_MARKINGS,
"TRAIT_HATED_BY_DOGS" = TRAIT_HATED_BY_DOGS,
"TRAIT_HEAD_INJURY_BLOCKED" = TRAIT_HEAD_INJURY_BLOCKED,
"TRAIT_HEALS_FROM_CARP_RIFTS" = TRAIT_HEALS_FROM_CARP_RIFTS,
"TRAIT_HEALS_FROM_CULT_PYLONS" = TRAIT_HEALS_FROM_CULT_PYLONS,
"TRAIT_HEAR_THROUGH_DARKNESS" = TRAIT_HEAR_THROUGH_DARKNESS,
@@ -401,7 +403,6 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_SHAVED" = TRAIT_SHAVED,
"TRAIT_SHIFTY_EYES" = TRAIT_SHIFTY_EYES,
"TRAIT_SHOCKIMMUNE" = TRAIT_SHOCKIMMUNE,
"TRAIT_SHOVE_KNOCKDOWN_BLOCKED" = TRAIT_SHOVE_KNOCKDOWN_BLOCKED,
"TRAIT_SIGN_LANG" = TRAIT_SIGN_LANG,
"TRAIT_PAPER_MASTER" = TRAIT_PAPER_MASTER,
"TRAIT_SILENT_FOOTSTEPS" = TRAIT_SILENT_FOOTSTEPS,
+2 -2
View File
@@ -390,7 +390,7 @@
glasses.add_mob_blood(src)
update_worn_glasses()
if(!attacking_item.get_sharpness() && armor_block < 50)
if(!attacking_item.get_sharpness() && !HAS_TRAIT(src, TRAIT_HEAD_INJURY_BLOCKED))
if(prob(damage_done))
adjustOrganLoss(ORGAN_SLOT_BRAIN, 20)
if(stat == CONSCIOUS)
@@ -420,7 +420,7 @@
w_uniform.add_mob_blood(src)
update_worn_undersuit()
if(stat == CONSCIOUS && !attacking_item.get_sharpness() && armor_block < 50)
if(stat == CONSCIOUS && !attacking_item.get_sharpness() && !HAS_TRAIT(src, TRAIT_BRAWLING_KNOCKDOWN_BLOCKED))
if(prob(damage_done))
visible_message(
span_danger("[src] is knocked down!"),
+6 -10
View File
@@ -400,7 +400,7 @@
defense_mod += 2
if(tackle_target.mob_negates_gravity())
defense_mod += 1
if(HAS_TRAIT(tackle_target, TRAIT_SHOVE_KNOCKDOWN_BLOCKED)) // riot armor and such
if(HAS_TRAIT(tackle_target, TRAIT_BRAWLING_KNOCKDOWN_BLOCKED)) // riot armor and such
defense_mod += 5
var/obj/item/organ/external/tail/lizard/el_tail = tackle_target.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL)
@@ -451,7 +451,7 @@
attack_mod += 15
human_sacker.adjustStaminaLoss(100) //AHAHAHAHAHAHAHAHA
if(HAS_TRAIT(human_sacker, TRAIT_SHOVE_KNOCKDOWN_BLOCKED)) // tackling with riot specialized armor, like riot armor, is effective but tiring
if(HAS_TRAIT(human_sacker, TRAIT_BRAWLING_KNOCKDOWN_BLOCKED)) // tackling with riot specialized armor, like riot armor, is effective but tiring
attack_mod += 2
human_sacker.adjustStaminaLoss(20)
@@ -499,14 +499,10 @@
var/danger_zone = (speed - 1) * 13 // for every extra speed we have over 1, take away 13 of the safest chance
danger_zone = max(min(danger_zone, 100), 1)
if(ishuman(user))
var/mob/living/carbon/human/S = user
var/head_slot = S.get_item_by_slot(ITEM_SLOT_HEAD)
var/suit_slot = S.get_item_by_slot(ITEM_SLOT_OCLOTHING)
if(head_slot && (istype(head_slot,/obj/item/clothing/head/helmet) || istype(head_slot,/obj/item/clothing/head/utility/hardhat)))
oopsie_mod -= 6
if(suit_slot && (istype(suit_slot,/obj/item/clothing/suit/armor/riot)))
oopsie_mod -= 6
if(HAS_TRAIT(user, TRAIT_BRAWLING_KNOCKDOWN_BLOCKED))
oopsie_mod -= 6
if(HAS_TRAIT(user, TRAIT_HEAD_INJURY_BLOCKED))
oopsie_mod -= 6
if(HAS_TRAIT(user, TRAIT_CLUMSY))
oopsie_mod += 6 //honk!
+3 -2
View File
@@ -23,7 +23,7 @@
var/hat_type = "yellow"
///Whether the headlamp is on or off.
var/on = FALSE
clothing_traits = list(TRAIT_HEAD_INJURY_BLOCKED)
/datum/armor/utility_hardhat
melee = 15
@@ -224,6 +224,7 @@
light_color = "#fff2bf"
worn_y_offset = 1
dog_fashion = /datum/dog_fashion/head/pumpkin/unlit
clothing_traits = list()
/obj/item/clothing/head/utility/hardhat/pumpkinhead/set_light_on(new_value)
. = ..()
@@ -277,6 +278,6 @@
flags_inv = 0
armor_type = /datum/armor/none
light_range = 1 //luminosity when on
clothing_traits = list()
dog_fashion = /datum/dog_fashion/head/reindeer
+3
View File
@@ -184,6 +184,7 @@
visor_flags_inv = HIDEFACE|HIDESNOUT
flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH | PEPPERPROOF
visor_flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH | PEPPERPROOF
clothing_traits = list(TRAIT_HEAD_INJURY_BLOCKED)
/datum/armor/toggleable_riot
melee = 50
@@ -247,6 +248,7 @@
strip_delay = 80
resistance_flags = FIRE_PROOF | ACID_PROOF
dog_fashion = null
clothing_traits = list(TRAIT_HEAD_INJURY_BLOCKED)
/datum/armor/helmet_swat
melee = 40
@@ -394,6 +396,7 @@
flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
strip_delay = 80
dog_fashion = null
clothing_traits = list(TRAIT_HEAD_INJURY_BLOCKED)
/datum/armor/helmet_knight
melee = 50
+2 -2
View File
@@ -306,7 +306,7 @@
armor_type = /datum/armor/armor_riot
strip_delay = 80
equip_delay_other = 60
clothing_traits = list(TRAIT_SHOVE_KNOCKDOWN_BLOCKED)
clothing_traits = list(TRAIT_BRAWLING_KNOCKDOWN_BLOCKED)
/datum/armor/armor_riot
melee = 50
@@ -410,7 +410,7 @@
max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT
slowdown = 0.7
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
clothing_traits = list(TRAIT_SHOVE_KNOCKDOWN_BLOCKED)
clothing_traits = list(TRAIT_BRAWLING_KNOCKDOWN_BLOCKED)
//All of the armor below is mostly unused
@@ -19,7 +19,7 @@
// as a wise man once wrote: "pull over that ass too fat"
REMOVE_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
// that'd be a too cheeky shield bashing strat
ADD_TRAIT(src, TRAIT_SHOVE_KNOCKDOWN_BLOCKED, INNATE_TRAIT)
ADD_TRAIT(src, TRAIT_BRAWLING_KNOCKDOWN_BLOCKED, INNATE_TRAIT)
AddComponent(/datum/component/seethrough_mob)
/mob/living/carbon/alien/adult/royal/on_lying_down(new_lying_angle)
+7 -1
View File
@@ -85,12 +85,18 @@
span_userdanger("You violently crash into [victim][extra_speed ? " extra hard" : ""], but [victim] managed to block the worst of it!"))
log_combat(src, victim, "crashed into and was blocked by")
return
else if(HAS_TRAIT(src, TRAIT_BRAWLING_KNOCKDOWN_BLOCKED))
victim.take_bodypart_damage(10 + 5 * extra_speed, check_armor = TRUE, wound_bonus = extra_speed * 5)
victim.apply_damage(10 + 10 * extra_speed, STAMINA)
victim.adjust_staggered_up_to(STAGGERED_SLOWDOWN_LENGTH * 2, 10 SECONDS)
visible_message(span_danger("[src] crashes into [victim][extra_speed ? " really hard" : ""], but [victim] was able to stay on their feet!"),\
span_userdanger("You violently crash into [victim][extra_speed ? " extra hard" : ""], but [victim] managed to stay on their feet!"))
else
victim.Paralyze(2 SECONDS)
victim.take_bodypart_damage(10 + 5 * extra_speed, check_armor = TRUE, wound_bonus = extra_speed * 5)
visible_message(span_danger("[src] crashes into [victim][extra_speed ? " really hard" : ""], knocking them both over!"),\
span_userdanger("You violently crash into [victim][extra_speed ? " extra hard" : ""]!"))
log_combat(src, victim, "crashed into")
log_combat(src, victim, "crashed into")
if(oof_noise)
playsound(src,'sound/weapons/punch1.ogg',50,TRUE)
@@ -1229,16 +1229,15 @@ GLOBAL_LIST_EMPTY(features_by_species)
log_combat(user, target, "punched")
//If we rolled a punch high enough to hit our stun threshold, or our target is staggered and they have at least 40 damage+stamina loss, we knock them down
if((target.stat != DEAD) && prob(limb_accuracy) || (target.stat != DEAD) && staggered && (target.getStaminaLoss() + user.getBruteLoss()) >= 40)
target.visible_message(span_danger("[user] knocks [target] down!"), \
span_userdanger("You're knocked down by [user]!"), span_hear("You hear aggressive shuffling followed by a loud thud!"), COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_danger("You knock [target] down!"))
/* SKYRAT EDIT REMOVAL - Less combat lethality and hard stuns
var/knockdown_duration = 4 SECONDS + (target.getStaminaLoss() + (target.getBruteLoss()*0.5))*0.8 //50 total damage = 4 second base stun + 4 second stun modifier = 8 second knockdown duration
target.apply_effect(knockdown_duration, EFFECT_KNOCKDOWN, armor_block)
SKYRAT EDIT REMOVAL END */
target.StaminaKnockdown(20) //SKYRAT EDIT ADDITION
log_combat(user, target, "got a stun punch with their previous punch")
//This does not work against opponents who are knockdown immune, such as from wearing riot armor.
if(!HAS_TRAIT(src, TRAIT_BRAWLING_KNOCKDOWN_BLOCKED))
if((target.stat != DEAD) && prob(limb_accuracy) || (target.stat != DEAD) && staggered && (target.getStaminaLoss() + user.getBruteLoss()) >= 40)
target.visible_message(span_danger("[user] knocks [target] down!"), \
span_userdanger("You're knocked down by [user]!"), span_hear("You hear aggressive shuffling followed by a loud thud!"), COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_danger("You knock [target] down!"))
var/knockdown_duration = 4 SECONDS + (target.getStaminaLoss() + (target.getBruteLoss()*0.5))*0.8 //50 total damage = 4 second base stun + 4 second stun modifier = 8 second knockdown duration
target.apply_effect(knockdown_duration, EFFECT_KNOCKDOWN, armor_block)
log_combat(user, target, "got a stun punch with their previous punch")
/datum/species/proc/disarm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style)
if(user.body_position != STANDING_UP)
@@ -146,7 +146,7 @@
return
if(!(shove_flags & SHOVE_KNOCKDOWN_BLOCKED))
target.Knockdown(SHOVE_KNOCKDOWN_HUMAN)
if(!HAS_TRAIT(src, TRAIT_SHOVE_KNOCKDOWN_BLOCKED))
if(!HAS_TRAIT(src, TRAIT_BRAWLING_KNOCKDOWN_BLOCKED))
Knockdown(SHOVE_KNOCKDOWN_COLLATERAL)
target.visible_message(span_danger("[shover] shoves [target.name] into [name]!"),
span_userdanger("You're shoved into [name] by [shover]!"), span_hear("You hear aggressive shuffling followed by a loud thud!"), COMBAT_MESSAGE_RANGE, src)
+1 -1
View File
@@ -756,7 +756,7 @@
. |= SHOVE_CAN_MOVE
if(!buckled)
. |= SHOVE_CAN_HIT_SOMETHING
if(HAS_TRAIT(src, TRAIT_SHOVE_KNOCKDOWN_BLOCKED))
if(HAS_TRAIT(src, TRAIT_BRAWLING_KNOCKDOWN_BLOCKED))
. |= SHOVE_KNOCKDOWN_BLOCKED
///Send the chat feedback message for shoving
+1 -1
View File
@@ -75,7 +75,7 @@
TRAIT_MADNESS_IMMUNE,
TRAIT_MARTIAL_ARTS_IMMUNE,
TRAIT_NOFIRE_SPREAD,
TRAIT_SHOVE_KNOCKDOWN_BLOCKED,
TRAIT_BRAWLING_KNOCKDOWN_BLOCKED,
)
add_traits(traits_to_apply, ROUNDSTART_TRAIT)
+1 -1
View File
@@ -698,7 +698,7 @@
a few years out of date, leading to an overall lower capacity for modules."
default_skin = "security"
armor_type = /datum/armor/mod_theme_security
complexity_max = DEFAULT_MAX_COMPLEXITY - 3
complexity_max = DEFAULT_MAX_COMPLEXITY - 2
slowdown_inactive = 1
slowdown_active = 0.5
allowed_suit_storage = list(
+7
View File
@@ -55,6 +55,7 @@
/obj/item/mod/module/flashlight,
/obj/item/mod/module/tether,
/obj/item/mod/module/magboot,
/obj/item/mod/module/headprotector,
)
default_pins = list(
/obj/item/mod/module/magboot,
@@ -72,6 +73,7 @@
/obj/item/mod/module/magboot,
/obj/item/mod/module/t_ray,
/obj/item/mod/module/quick_carry,
/obj/item/mod/module/headprotector,
)
default_pins = list(
/obj/item/mod/module/magboot,
@@ -87,6 +89,7 @@
/obj/item/mod/module/rad_protection,
/obj/item/mod/module/flashlight,
/obj/item/mod/module/jetpack,
/obj/item/mod/module/headprotector,
)
default_pins = list(
/obj/item/mod/module/magboot/advanced,
@@ -153,6 +156,7 @@
/obj/item/mod/module/flashlight,
/obj/item/mod/module/circuit,
/obj/item/mod/module/t_ray,
/obj/item/mod/module/headprotector,
)
/obj/item/mod/control/pre_equipped/security
@@ -165,6 +169,7 @@
/obj/item/mod/module/criminalcapture,
/obj/item/mod/module/dispenser/mirage,
/obj/item/mod/module/quick_cuff,
/obj/item/mod/module/headprotector,
)
/obj/item/mod/control/pre_equipped/safeguard
@@ -179,6 +184,7 @@
/obj/item/mod/module/projectile_dampener,
/obj/item/mod/module/pepper_shoulders,
/obj/item/mod/module/quick_cuff,
/obj/item/mod/module/headprotector,
)
default_pins = list(
/obj/item/mod/module/jetpack,
@@ -194,6 +200,7 @@
/obj/item/mod/module/jetpack/advanced,
/obj/item/mod/module/pathfinder,
/obj/item/mod/module/quick_cuff,
/obj/item/mod/module/headprotector,
)
default_pins = list(
/obj/item/mod/module/jetpack/advanced,
+12 -5
View File
@@ -11,7 +11,7 @@
module_type = MODULE_TOGGLE
active_power_cost = DEFAULT_CHARGE_DRAIN * 0.3
removable = FALSE
incompatible_modules = list(/obj/item/mod/module/armor_booster, /obj/item/mod/module/welding)
incompatible_modules = list(/obj/item/mod/module/armor_booster, /obj/item/mod/module/welding, /obj/item/mod/module/headprotector)
cooldown_time = 0.5 SECONDS
overlay_state_inactive = "module_armorbooster_off"
overlay_state_active = "module_armorbooster_on"
@@ -26,6 +26,8 @@
var/list/armor_mod = /datum/armor/mod_module_armor_boost
/// List of parts of the suit that are spaceproofed, for giving them back the pressure protection.
var/list/spaceproofed = list()
/// List of traits added when the mod is activated
var/list/traits_to_add = list(TRAIT_HEAD_INJURY_BLOCKED)
/datum/armor/mod_module_armor_boost
melee = 25
@@ -50,6 +52,7 @@
actual_speed_added = max(0, min(mod.slowdown_active, speed_added))
mod.slowdown -= actual_speed_added
mod.wearer.update_equipment_speed_mods()
mod.wearer.add_traits(traits_to_add, MOD_TRAIT)
var/list/parts = mod.mod_parts + mod
for(var/obj/item/part as anything in parts)
part.set_armor(part.get_armor().add_other_armor(armor_mod))
@@ -69,6 +72,7 @@
balloon_alert(mod.wearer, "armor retracts, EVA ready")
mod.slowdown += actual_speed_added
mod.wearer.update_equipment_speed_mods()
mod.wearer.remove_traits(traits_to_add, MOD_TRAIT)
var/list/parts = mod.mod_parts + mod
for(var/obj/item/part as anything in parts)
part.set_armor(part.get_armor().subtract_other_armor(armor_mod))
@@ -483,12 +487,15 @@
/obj/item/mod/module/infiltrator
name = "MOD infiltration core programs module"
desc = "The primary stealth systems operating within the suit. Utilizing electromagnetic signals, \
the wearer simply cannot be observed closely, or heard clearly by those around them."
the wearer simply cannot be observed closely, or heard clearly by those around them.\
It also contains some dampening systems to help protect a user from blows to the head."
icon_state = "infiltrator"
complexity = 0
removable = FALSE
idle_power_cost = DEFAULT_CHARGE_DRAIN * 0
incompatible_modules = list(/obj/item/mod/module/infiltrator, /obj/item/mod/module/armor_booster, /obj/item/mod/module/welding)
incompatible_modules = list(/obj/item/mod/module/infiltrator, /obj/item/mod/module/armor_booster, /obj/item/mod/module/welding, /obj/item/mod/module/headprotector)
/// List of traits added when the suit is activated
var/list/traits_to_add = list(TRAIT_SILENT_FOOTSTEPS, TRAIT_UNKNOWN, TRAIT_HEAD_INJURY_BLOCKED)
/obj/item/mod/module/infiltrator/on_install()
mod.item_flags |= EXAMINE_SKIP
@@ -497,11 +504,11 @@
mod.item_flags &= ~EXAMINE_SKIP
/obj/item/mod/module/infiltrator/on_suit_activation()
mod.wearer.add_traits(list(TRAIT_SILENT_FOOTSTEPS, TRAIT_UNKNOWN), MOD_TRAIT)
mod.wearer.add_traits(traits_to_add, MOD_TRAIT)
mod.helmet.flash_protect = FLASH_PROTECTION_WELDER
/obj/item/mod/module/infiltrator/on_suit_deactivation(deleting = FALSE)
mod.wearer.remove_traits(list(TRAIT_SILENT_FOOTSTEPS, TRAIT_UNKNOWN), MOD_TRAIT)
mod.wearer.remove_traits(traits_to_add, MOD_TRAIT)
if(deleting)
return
mod.helmet.flash_protect = initial(mod.helmet.flash_protect)
@@ -204,6 +204,24 @@
rcd_scan(src, fade_time = 10 SECONDS)
drain_power(use_power_cost)
///Safety-First Head Protection - Protects your brain matter from sudden impacts.
/obj/item/mod/module/headprotector
name = "MOD Safety-First Head Protection module"
desc = "A series of dampening plates are installed along the back and upper areas of \
the helmet. These plates absorb abrupt kinetic shocks delivered to the skull. \
The bulk of this module prevents it from being installed in any suit that is capable \
of combat armor adjustments. However, the rudimentry nature of the module makes it \
relatively easy to install into most other suits."
icon_state = "welding"
complexity = 1
incompatible_modules = list(/obj/item/mod/module/armor_booster, /obj/item/mod/module/infiltrator)
/obj/item/mod/module/constructor/on_suit_activation()
ADD_TRAIT(mod.wearer, TRAIT_HEAD_INJURY_BLOCKED, MOD_TRAIT)
/obj/item/mod/module/constructor/on_suit_deactivation(deleting = FALSE)
REMOVE_TRAIT(mod.wearer, TRAIT_HEAD_INJURY_BLOCKED, MOD_TRAIT)
///Mister - Sprays water over an area.
/obj/item/mod/module/mister
name = "MOD water mister module"
+2 -2
View File
@@ -587,10 +587,10 @@
incompatible_modules = list(/obj/item/mod/module/shove_blocker)
/obj/item/mod/module/shove_blocker/on_suit_activation()
mod.wearer.add_traits(list(TRAIT_SHOVE_KNOCKDOWN_BLOCKED, TRAIT_NO_STAGGER, TRAIT_NO_THROW_HITPUSH), MOD_TRAIT)
mod.wearer.add_traits(list(TRAIT_BRAWLING_KNOCKDOWN_BLOCKED, TRAIT_NO_STAGGER, TRAIT_NO_THROW_HITPUSH), MOD_TRAIT)
/obj/item/mod/module/shove_blocker/on_suit_deactivation(deleting = FALSE)
mod.wearer.remove_traits(list(TRAIT_SHOVE_KNOCKDOWN_BLOCKED, TRAIT_NO_STAGGER, TRAIT_NO_THROW_HITPUSH), MOD_TRAIT)
mod.wearer.remove_traits(list(TRAIT_BRAWLING_KNOCKDOWN_BLOCKED, TRAIT_NO_STAGGER, TRAIT_NO_THROW_HITPUSH), MOD_TRAIT)
/obj/item/mod/module/shove_blocker/locked
name = "superglued MOD bulwark module"
@@ -82,7 +82,7 @@
var/obj/item/bodypart/affecting = user.zone_selected //Find what the player is aiming at
var/armor_block = 0 //Get the target's armor values for normal attack damage.
var/armor_duration = 0 //The more force the bottle has, the longer the duration.
var/knockdown_effectiveness = 0 //The more force the bottle has, the longer the duration.
//Calculating duration and calculating damage.
if(ishuman(target))
@@ -95,23 +95,23 @@
if(istype(H.head, /obj/item/clothing/head) && affecting == BODY_ZONE_HEAD)
headarmor = H.head.get_armor_rating(MELEE)
//Calculate the knockdown duration for the target.
armor_duration = (bottle_knockdown_duration - headarmor) + force
knockdown_effectiveness = (bottle_knockdown_duration - headarmor) + force
else
//Only humans can have armor, right?
armor_block = living_target.run_armor_check(affecting, MELEE)
if(affecting == BODY_ZONE_HEAD)
armor_duration = bottle_knockdown_duration + force
knockdown_effectiveness = bottle_knockdown_duration + force
//Apply the damage!
armor_block = min(90,armor_block)
living_target.apply_damage(force, BRUTE, affecting, armor_block)
// You are going to knock someone down for longer if they are not wearing a helmet.
var/head_attack_message = ""
if(affecting == BODY_ZONE_HEAD && iscarbon(target))
if(affecting == BODY_ZONE_HEAD && iscarbon(target) && !HAS_TRAIT(target, TRAIT_HEAD_INJURY_BLOCKED))
head_attack_message = " on the head"
if(armor_duration)
living_target.apply_effect(min(armor_duration, 200) , EFFECT_KNOCKDOWN)
if(knockdown_effectiveness && prob(knockdown_effectiveness))
living_target.apply_effect(min(knockdown_effectiveness, 200) , EFFECT_KNOCKDOWN)
//Display an attack message.
if(target != user)
@@ -2052,6 +2052,17 @@
category = list(
RND_CATEGORY_MODSUIT_MODULES + RND_SUBCATEGORY_MODSUIT_MODULES_ENGINEERING
)
/datum/design/module/mod_head_protection
name = "Safety-First Head Protection Module"
id = "mod_safety"
materials = list(
/datum/material/iron =SMALL_MATERIAL_AMOUNT*5,
/datum/material/glass =HALF_SHEET_MATERIAL_AMOUNT,
)
build_path = /obj/item/mod/module/headprotector
category = list(
RND_CATEGORY_MODSUIT_MODULES + RND_SUBCATEGORY_MODSUIT_MODULES_ENGINEERING
)
/datum/design/module/mod_t_ray
name = "T-Ray Scanner Module"
id = "mod_t_ray"
@@ -210,6 +210,7 @@
"mod_plating_standard",
"mod_storage",
"mod_welding",
"mod_safety",
"mod_mouthhole",
"mod_flashlight",
"mod_longfall",
@@ -23,7 +23,7 @@
actions_types = list(/datum/action/item_action/hev_toggle/nri, /datum/action/item_action/hev_toggle_notifs/nri, /datum/action/item_action/toggle_spacesuit)
resistance_flags = FIRE_PROOF|UNACIDABLE|ACID_PROOF|FREEZE_PROOF
clothing_flags = STOPSPRESSUREDAMAGE|SNUG_FIT
clothing_traits = list(TRAIT_SHOVE_KNOCKDOWN_BLOCKED)
clothing_traits = list(TRAIT_BRAWLING_KNOCKDOWN_BLOCKED)
activation_song = null //No nice song.