diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index 648f86ff999..eef432fb2ed 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -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 diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 35d8b079721..20e592a8448 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -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, diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 745d63b5b94..174aac2fc62 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -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!"), diff --git a/code/datums/components/tackle.dm b/code/datums/components/tackle.dm index acd25fb328b..b6cc4d32c97 100644 --- a/code/datums/components/tackle.dm +++ b/code/datums/components/tackle.dm @@ -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! diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm index ce6becd524e..3550690b426 100644 --- a/code/modules/clothing/head/hardhat.dm +++ b/code/modules/clothing/head/hardhat.dm @@ -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 diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 2960260255f..7741251f3f5 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -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 diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index bcfe4776b76..02e6110b3ee 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -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 diff --git a/code/modules/mob/living/carbon/alien/adult/queen.dm b/code/modules/mob/living/carbon/alien/adult/queen.dm index 1a08d2446d2..4387f7db3ec 100644 --- a/code/modules/mob/living/carbon/alien/adult/queen.dm +++ b/code/modules/mob/living/carbon/alien/adult/queen.dm @@ -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) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index db21a9635ad..7b4f7834377 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -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) diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index d6aedcf91d7..f361a3dcfb2 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -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) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 470a72b9d88..62a201cc1a6 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -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) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index bb39ab60663..262df8c99b5 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -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 diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 12f9a293b45..14f3bb4ba3d 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -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) diff --git a/code/modules/mod/mod_theme.dm b/code/modules/mod/mod_theme.dm index 3efc26214bf..509cdfc1ed7 100644 --- a/code/modules/mod/mod_theme.dm +++ b/code/modules/mod/mod_theme.dm @@ -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( diff --git a/code/modules/mod/mod_types.dm b/code/modules/mod/mod_types.dm index 0933c7e8f18..0659dd6208b 100644 --- a/code/modules/mod/mod_types.dm +++ b/code/modules/mod/mod_types.dm @@ -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, diff --git a/code/modules/mod/modules/modules_antag.dm b/code/modules/mod/modules/modules_antag.dm index cf72f62d6c4..a35e39365b9 100644 --- a/code/modules/mod/modules/modules_antag.dm +++ b/code/modules/mod/modules/modules_antag.dm @@ -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) diff --git a/code/modules/mod/modules/modules_engineering.dm b/code/modules/mod/modules/modules_engineering.dm index 9095bbd2c24..fa746048e82 100644 --- a/code/modules/mod/modules/modules_engineering.dm +++ b/code/modules/mod/modules/modules_engineering.dm @@ -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" diff --git a/code/modules/mod/modules/modules_security.dm b/code/modules/mod/modules/modules_security.dm index 3b8bc8cb3a8..be271ae61e6 100644 --- a/code/modules/mod/modules/modules_security.dm +++ b/code/modules/mod/modules/modules_security.dm @@ -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" diff --git a/code/modules/reagents/reagent_containers/cups/glassbottle.dm b/code/modules/reagents/reagent_containers/cups/glassbottle.dm index 83754dd571f..9deb6582508 100644 --- a/code/modules/reagents/reagent_containers/cups/glassbottle.dm +++ b/code/modules/reagents/reagent_containers/cups/glassbottle.dm @@ -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) diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm index 3ec6604b329..4532ec0d43d 100644 --- a/code/modules/research/designs/mechfabricator_designs.dm +++ b/code/modules/research/designs/mechfabricator_designs.dm @@ -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" diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index d45d819b252..4355dbeca71 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -210,6 +210,7 @@ "mod_plating_standard", "mod_storage", "mod_welding", + "mod_safety", "mod_mouthhole", "mod_flashlight", "mod_longfall", diff --git a/modular_skyrat/modules/novaya_ert/code/suit.dm b/modular_skyrat/modules/novaya_ert/code/suit.dm index 3a6542a562d..587f63549aa 100644 --- a/modular_skyrat/modules/novaya_ert/code/suit.dm +++ b/modular_skyrat/modules/novaya_ert/code/suit.dm @@ -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.