From 565bfbbe0956b7eb602d12070c4700a2fb362084 Mon Sep 17 00:00:00 2001
From: Paxilmaniac <82386923+Paxilmaniac@users.noreply.github.com>
Date: Sat, 2 Dec 2023 14:01:21 -0500
Subject: [PATCH] Armor tech of the current* year | Protect yourself from all
them "guncargos" the old people keep warning you about (#24947)
* oh yeah i havent saved any of this
* fixes some things that weren't quite right
* makes the sacrificial armor actually take damage
* slight numbers tweak
* adds cargo packs to let sec bulk order this stuff
* shortens the normal desc of the hardened vests
* potentially actually fixes the sacrificial armor not working (evil)
* certified copy paste moment
* buffs protection lowers durability of sacrificial armor
* maybe possibly fixes that sound
* tweaks colors of peacekeeper helmet slightly
* makes the import company look nicer
* fixes crate access and armor value sin
* fixes the vest for digitgrades
* fixes sacrificial armor
* removes a bunch of debug messages
* fixes weird compiler thing
* armor defines, buffs sacrificial armor slightly and pk armor more
* adds a face shield for the val
* adds an examine relating to the face shields
* makes the val face shield not hide your face
* Update modular_skyrat/modules/specialist_armor/code/sacrificial.dm
Co-authored-by: GoldenAlpharex <58045821+GoldenAlpharex@users.noreply.github.com>
* stuff holden suggests
---------
Co-authored-by: GoldenAlpharex <58045821+GoldenAlpharex@users.noreply.github.com>
---
.../~skyrat_defines/armor_defines.dm | 8 +
.../~skyrat_defines/traits/declarations.dm | 3 +
code/_globalvars/traits/_traits.dm | 1 +
code/_globalvars/traits/admin_tooling.dm | 1 +
.../code/armament_datums/sol_defense.dm | 54 +++++-
.../specialist_armor/code/cargo_packs.dm | 30 ++++
.../code/clothing_bullet_damage_component.dm | 81 +++++++++
.../modules/specialist_armor/code/hardened.dm | 99 +++++++++++
.../specialist_armor/code/peacekeeper.dm | 75 +++++++++
.../specialist_armor/code/sacrificial.dm | 156 ++++++++++++++++++
.../modules/specialist_armor/icons/armor.dmi | Bin 0 -> 2417 bytes
.../specialist_armor/icons/armor_worn.dmi | Bin 0 -> 5316 bytes
tgstation.dme | 6 +
13 files changed, 508 insertions(+), 6 deletions(-)
create mode 100644 code/__DEFINES/~skyrat_defines/armor_defines.dm
create mode 100644 modular_skyrat/modules/specialist_armor/code/cargo_packs.dm
create mode 100644 modular_skyrat/modules/specialist_armor/code/clothing_bullet_damage_component.dm
create mode 100644 modular_skyrat/modules/specialist_armor/code/hardened.dm
create mode 100644 modular_skyrat/modules/specialist_armor/code/peacekeeper.dm
create mode 100644 modular_skyrat/modules/specialist_armor/code/sacrificial.dm
create mode 100644 modular_skyrat/modules/specialist_armor/icons/armor.dmi
create mode 100644 modular_skyrat/modules/specialist_armor/icons/armor_worn.dmi
diff --git a/code/__DEFINES/~skyrat_defines/armor_defines.dm b/code/__DEFINES/~skyrat_defines/armor_defines.dm
new file mode 100644
index 00000000000..bfb239621e2
--- /dev/null
+++ b/code/__DEFINES/~skyrat_defines/armor_defines.dm
@@ -0,0 +1,8 @@
+#define ARMOR_LEVEL_TINY 10
+#define ARMOR_LEVEL_WEAK 30
+#define ARMOR_LEVEL_MID 50
+#define ARMOR_LEVEL_INSANE 90
+
+#define WOUND_ARMOR_WEAK 10
+#define WOUND_ARMOR_STANDARD 20
+#define WOUND_ARMOR_HIGH 30
diff --git a/code/__DEFINES/~skyrat_defines/traits/declarations.dm b/code/__DEFINES/~skyrat_defines/traits/declarations.dm
index cad3083144d..e7eb77d9224 100644
--- a/code/__DEFINES/~skyrat_defines/traits/declarations.dm
+++ b/code/__DEFINES/~skyrat_defines/traits/declarations.dm
@@ -150,4 +150,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_CONDOM_BROKEN "broken"
+/// If clothing can also be damaged by piercing wound checks, instead of JUST slashes and burns
+#define TRAIT_CLOTHES_DAMAGED_BY_PIERCING "clothing_damaged_by_piercing"
+
// END TRAIT DEFINES
diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm
index 0c237f43fbf..f0af4914d60 100644
--- a/code/_globalvars/traits/_traits.dm
+++ b/code/_globalvars/traits/_traits.dm
@@ -629,6 +629,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_XENOARCH_QUALIFIED" = TRAIT_XENOARCH_QUALIFIED,
"TRAIT_XENO_HEAL_AURA" = TRAIT_XENO_HEAL_AURA,
"TRAIT_XENO_INNATE" = TRAIT_XENO_INNATE,
+ "TRAIT_CLOTHES_DAMAGED_BY_PIERCING" = TRAIT_CLOTHES_DAMAGED_BY_PIERCING,
),
// SKYRAT EDIT ADDITION END
))
diff --git a/code/_globalvars/traits/admin_tooling.dm b/code/_globalvars/traits/admin_tooling.dm
index 3e061e884af..f852a1decbc 100644
--- a/code/_globalvars/traits/admin_tooling.dm
+++ b/code/_globalvars/traits/admin_tooling.dm
@@ -347,6 +347,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
"TRAIT_XENOARCH_QUALIFIED" = TRAIT_XENOARCH_QUALIFIED,
"TRAIT_XENO_HEAL_AURA" = TRAIT_XENO_HEAL_AURA,
"TRAIT_XENO_INNATE" = TRAIT_XENO_INNATE,
+ "TRAIT_CLOTHES_DAMAGED_BY_PIERCING" = TRAIT_CLOTHES_DAMAGED_BY_PIERCING,
),
// SKYRAT EDIT ADDITION END
))
diff --git a/modular_skyrat/modules/company_imports/code/armament_datums/sol_defense.dm b/modular_skyrat/modules/company_imports/code/armament_datums/sol_defense.dm
index adc25d80147..0d7e4a8eca1 100644
--- a/modular_skyrat/modules/company_imports/code/armament_datums/sol_defense.dm
+++ b/modular_skyrat/modules/company_imports/code/armament_datums/sol_defense.dm
@@ -2,21 +2,63 @@
category = SOL_DEFENSE_DEFENSE_NAME
company_bitflag = CARGO_COMPANY_SOL_DEFENSE
-// Basic armor vests
+// Armor vests for protecting against bullets
/datum/armament_entry/company_import/sol_defense/armor
- subcategory = "Light Body Armor"
-
-/datum/armament_entry/company_import/sol_defense/armor/slim_vest
- name = "type I vest - slim"
- item_type = /obj/item/clothing/suit/armor/vest
+ subcategory = "Ballistic Armor"
cost = PAYCHECK_CREW * 3
+/datum/armament_entry/company_import/sol_defense/armor/ballistic_helmet
+ item_type = /obj/item/clothing/head/helmet/sf_peacekeeper/debranded
+
+/datum/armament_entry/company_import/sol_defense/armor/sf_ballistic_helmet
+ item_type = /obj/item/clothing/head/helmet/sf_peacekeeper
+
+/datum/armament_entry/company_import/sol_defense/armor/soft_vest
+ item_type = /obj/item/clothing/suit/armor/sf_peacekeeper/debranded
+
+/datum/armament_entry/company_import/sol_defense/armor/sf_soft_vest
+ item_type = /obj/item/clothing/suit/armor/sf_peacekeeper
+
/datum/armament_entry/company_import/sol_defense/armor/normal_vest
name = "type I vest - normal"
item_type = /obj/item/clothing/suit/armor/vest/alt
+
+/datum/armament_entry/company_import/sol_defense/armor/slim_vest
+ name = "type I vest - slim"
+ item_type = /obj/item/clothing/suit/armor/vest
+
+/datum/armament_entry/company_import/sol_defense/armor_hardened
+ subcategory = "Hardened Armor"
cost = PAYCHECK_CREW * 3
+/datum/armament_entry/company_import/sol_defense/armor_hardened/enclosed_helmet
+ item_type = /obj/item/clothing/head/helmet/toggleable/sf_hardened
+
+
+/datum/armament_entry/company_import/sol_defense/armor_hardened/emt_enclosed_helmet
+ item_type = /obj/item/clothing/head/helmet/toggleable/sf_hardened/emt
+
+/datum/armament_entry/company_import/sol_defense/armor_hardened/hardened_vest
+ item_type = /obj/item/clothing/suit/armor/sf_hardened
+
+/datum/armament_entry/company_import/sol_defense/armor_hardened/emt_hardened_vest
+ item_type = /obj/item/clothing/suit/armor/sf_hardened/emt
+
+/datum/armament_entry/company_import/sol_defense/armor_sacrifice
+ subcategory = "Sacrifical Armor"
+ cost = PAYCHECK_CREW * 3
+
+/datum/armament_entry/company_import/sol_defense/armor_sacrifice/sacrificial_helmet
+ item_type = /obj/item/clothing/head/helmet/sf_sacrificial
+
+/datum/armament_entry/company_import/sol_defense/armor_sacrifice/face_shield
+ item_type = /obj/item/sacrificial_face_shield
+ cost = PAYCHECK_LOWER
+
+/datum/armament_entry/company_import/sol_defense/armor_sacrifice/sacrificial_vest
+ item_type = /obj/item/clothing/suit/armor/sf_sacrificial
+
/datum/armament_entry/company_import/sol_defense/case
subcategory = "Weapon Cases"
diff --git a/modular_skyrat/modules/specialist_armor/code/cargo_packs.dm b/modular_skyrat/modules/specialist_armor/code/cargo_packs.dm
new file mode 100644
index 00000000000..8dbe34ebc3c
--- /dev/null
+++ b/modular_skyrat/modules/specialist_armor/code/cargo_packs.dm
@@ -0,0 +1,30 @@
+/datum/supply_pack/security/armory/soft_armor
+ name = "Soft Armor Kit Crate"
+ crate_name = "soft armor kit crate"
+ desc = "Contains three sets of SolFed-made soft body armor and matching helmets."
+ cost = CARGO_CRATE_VALUE * 5
+ contains = list(
+ /obj/item/clothing/head/helmet/sf_peacekeeper/debranded = 3,
+ /obj/item/clothing/suit/armor/sf_peacekeeper/debranded = 3,
+ )
+
+/datum/supply_pack/security/armory/hardened_armor
+ name = "Hardened Armor Kit Crate"
+ crate_name = "hardened armor kit crate"
+ desc = "Contains three sets of SolFed-made hardened body armor and matching helmets."
+ cost = CARGO_CRATE_VALUE * 5
+ contains = list(
+ /obj/item/clothing/head/helmet/toggleable/sf_hardened = 3,
+ /obj/item/clothing/suit/armor/sf_hardened = 3,
+ )
+
+/datum/supply_pack/security/armory/sacrificial_armor
+ name = "Sacrificial Armor Kit Crate"
+ crate_name = "sacrificial armor kit crate"
+ desc = "Contains three sets of SolFed-made sacrificial body armor and matching helmets."
+ cost = CARGO_CRATE_VALUE * 5
+ contains = list(
+ /obj/item/clothing/head/helmet/sf_sacrificial = 3,
+ /obj/item/sacrificial_face_shield = 3,
+ /obj/item/clothing/suit/armor/sf_sacrificial = 3,
+ )
diff --git a/modular_skyrat/modules/specialist_armor/code/clothing_bullet_damage_component.dm b/modular_skyrat/modules/specialist_armor/code/clothing_bullet_damage_component.dm
new file mode 100644
index 00000000000..48d56948660
--- /dev/null
+++ b/modular_skyrat/modules/specialist_armor/code/clothing_bullet_damage_component.dm
@@ -0,0 +1,81 @@
+/// Component that lets clothing be damaged in zones by piercing bullets. The parent MUST have limb_integrity set.
+/datum/component/clothing_damaged_by_bullets
+ /// How much of the incoming projectile damage is taken, multiplier
+ var/projectile_damage_multiplier
+ /// Who is wearing the target?
+ var/mob/living/wearer
+
+/datum/component/clothing_damaged_by_bullets/Initialize(projectile_damage_multiplier = 1)
+ if(!istype(parent, /obj/item/clothing)) // Just in case someone loses it and tries to put this on something that's not clothing
+ return COMPONENT_INCOMPATIBLE
+
+ var/obj/item/clothing/parent_clothing = parent
+
+ src.projectile_damage_multiplier = projectile_damage_multiplier
+
+ if(ismob(parent_clothing.loc))
+ var/mob/holder = parent_clothing.loc
+ if(holder.is_holding(parent_clothing))
+ return
+ set_wearer(holder)
+
+/datum/component/clothing_damaged_by_bullets/RegisterWithParent()
+ RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine))
+ RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(on_equipped))
+ RegisterSignal(parent, COMSIG_ITEM_DROPPED, PROC_REF(lost_wearer))
+
+/datum/component/clothing_damaged_by_bullets/UnregisterFromParent()
+ UnregisterSignal(parent, list(COMSIG_ATOM_EXAMINE, COMSIG_ITEM_DROPPED, COMSIG_ITEM_EQUIPPED, COMSIG_QDELETING, COMSIG_ATOM_BULLET_ACT))
+
+/// Check if we've been equipped to a valid slot to shield
+/datum/component/clothing_damaged_by_bullets/proc/on_equipped(datum/source, mob/user, slot)
+ SIGNAL_HANDLER
+
+ if((slot & ITEM_SLOT_HANDS))
+ lost_wearer(source, user)
+ return
+ set_wearer(user)
+
+/// Either we've been dropped or our wearer has been QDEL'd. Either way, they're no longer our problem
+/datum/component/clothing_damaged_by_bullets/proc/lost_wearer(datum/source, mob/user)
+ SIGNAL_HANDLER
+
+ wearer = null
+ UnregisterSignal(parent, list(COMSIG_QDELETING, COMSIG_ATOM_BULLET_ACT))
+
+/// Sets the wearer and registers the appropriate signals for them
+/datum/component/clothing_damaged_by_bullets/proc/set_wearer(mob/user)
+ if(wearer == user)
+ return
+ if(!isnull(wearer))
+ CRASH("[type] called set_wearer with [user] but [wearer] was already the wearer!")
+
+ wearer = user
+ RegisterSignal(wearer, COMSIG_QDELETING, PROC_REF(lost_wearer))
+ RegisterSignal(wearer, COMSIG_ATOM_BULLET_ACT, PROC_REF(hit_by_projectile))
+
+/// Checks an incoming projectile to see if it should damage the thing we're attached to,
+/datum/component/clothing_damaged_by_bullets/proc/hit_by_projectile(mob/living/dude_getting_hit, obj/projectile/hitting_projectile, def_zone)
+ SIGNAL_HANDLER
+
+ var/obj/item/clothing/clothing_parent = parent
+
+ if(!(def_zone in cover_flags2body_zones(clothing_parent.body_parts_covered)))
+ return
+ if(hitting_projectile.sharpness == SHARP_EDGED)
+ return
+ if(hitting_projectile.damage_type != BRUTE)
+ return
+
+ /// This seems complex but the actual math is simple, the damage of the projectile * vest damage multiplier, divided by two if the projectile is weak to armour, then modified by wound bonus
+ var/total_damage = ((hitting_projectile.damage * projectile_damage_multiplier) * (hitting_projectile.weak_against_armour ? 0.5 : 1) * (1 + (hitting_projectile.wound_bonus / 10)))
+ var/damage_dealt = clothing_parent.take_damage(total_damage, BRUTE, hitting_projectile.armour_penetration, FALSE)
+
+ if(clothing_parent.limb_integrity)
+ clothing_parent.take_damage_zone(def_zone, damage_dealt, BRUTE)
+
+/// Warns any examiner that the clothing we're stuck to will be damaged by piercing bullets
+/datum/component/clothing_damaged_by_bullets/proc/on_examine(obj/item/source, mob/examiner, list/examine_list)
+ SIGNAL_HANDLER
+
+ examine_list += "
[span_warning("This will be damaged when it protects you from bullets, taking [projectile_damage_multiplier] times the damage that the bullet deals.")]"
diff --git a/modular_skyrat/modules/specialist_armor/code/hardened.dm b/modular_skyrat/modules/specialist_armor/code/hardened.dm
new file mode 100644
index 00000000000..777bfed67e0
--- /dev/null
+++ b/modular_skyrat/modules/specialist_armor/code/hardened.dm
@@ -0,0 +1,99 @@
+// Hardened vests negate any and all projectile armor penetration, in exchange for having mid af bullet armor
+/datum/armor/armor_sf_hardened
+ melee = ARMOR_LEVEL_WEAK
+ bullet = ARMOR_LEVEL_MID
+ laser = ARMOR_LEVEL_WEAK
+ energy = ARMOR_LEVEL_TINY
+ bomb = ARMOR_LEVEL_WEAK
+ fire = ARMOR_LEVEL_MID
+ acid = ARMOR_LEVEL_WEAK
+ wound = WOUND_ARMOR_WEAK
+
+/obj/item/clothing/suit/armor/sf_hardened
+ name = "'Muur' hardened armor vest"
+ desc = "A large white breastplate, and a semi-flexible mail of dense panels that cover the torso. \
+ While not so incredible at directly stopping bullets, the vest is uniquely suited to cause bullets \
+ to lose much of their armor penetrating energy before any damage can be done."
+ icon = 'modular_skyrat/modules/specialist_armor/icons/armor.dmi'
+ icon_state = "hardened_standard"
+ worn_icon = 'modular_skyrat/modules/specialist_armor/icons/armor_worn.dmi'
+ inhand_icon_state = "armor"
+ blood_overlay_type = "armor"
+ armor_type = /datum/armor/armor_sf_hardened
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
+
+/obj/item/clothing/suit/armor/sf_hardened/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text, final_block_chance, damage, attack_type, damage_type)
+ . = ..()
+
+ if(istype(hitby, /obj/projectile))
+ var/obj/projectile/incoming_projectile = hitby
+ incoming_projectile.armour_penetration = 0
+ playsound(owner, SFX_RICOCHET, BLOCK_SOUND_VOLUME, vary = TRUE)
+
+/obj/item/clothing/suit/armor/sf_hardened/examine_more(mob/user)
+ . = ..()
+
+ . += "What do you do in an age where armor penetration technology keeps getting better and better, \
+ and you're quite fond of not being a corpse? The 'Muur' type armor was a pretty successful attempt at an answer \
+ to the question. Using some advanced materials, micro-scale projectile dampener fields, and a whole \
+ host of other technologies that some poor SolFed procurement general had to talked to death about, \
+ it offers a unique advantage over many armor piercing bullets. Why stop the bullet from piercing the armor \
+ with more armor, when you could simply force the bullet to penetrate less and get away with less protection? \
+ Some people would rather the bullet just be stopped, of course, but when you have to make choices, many choose \
+ this one."
+
+ return .
+
+/obj/item/clothing/suit/armor/sf_hardened/emt
+ name = "'Archangel' hardened armor vest"
+ desc = "A large white breastplate with a lone red stripe, and a semi-flexible mail of dense panels that cover the torso. \
+ While not so incredible at directly stopping bullets, the vest is uniquely suited to cause bullets \
+ to lose much of their armor penetrating energy before any damage can be done."
+ icon_state = "hardened_emt"
+
+/obj/item/clothing/head/helmet/toggleable/sf_hardened
+ name = "'Muur' enclosed helmet"
+ desc = "A thick-fronted helmet with extendable visor for whole face protection. The materials and geometry of the helmet \
+ combine in such a way that bullets lose much of their armor penetrating energy before any damage can be done, rather than penetrate into it."
+ icon = 'modular_skyrat/modules/specialist_armor/icons/armor.dmi'
+ icon_state = "enclosed_standard"
+ worn_icon = 'modular_skyrat/modules/specialist_armor/icons/armor_worn.dmi'
+ inhand_icon_state = "helmet"
+ armor_type = /datum/armor/armor_sf_hardened
+ toggle_message = "You extend the visor on"
+ alt_toggle_message = "You retract the visor on"
+ flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
+ visor_flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
+ flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH | PEPPERPROOF
+ visor_flags_cover = HEADCOVERSEYES
+ dog_fashion = null
+ supports_variations_flags = CLOTHING_SNOUTED_VARIATION_NO_NEW_ICON
+
+/obj/item/clothing/head/helmet/toggleable/sf_hardened/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text, final_block_chance, damage, attack_type, damage_type)
+ . = ..()
+
+ if(istype(hitby, /obj/projectile))
+ var/obj/projectile/incoming_projectile = hitby
+ incoming_projectile.armour_penetration = 0
+ playsound(src, SFX_RICOCHET, BLOCK_SOUND_VOLUME, vary = TRUE)
+
+/obj/item/clothing/head/helmet/toggleable/sf_hardened/examine_more(mob/user)
+ . = ..()
+
+ . += "What do you do in an age where armor penetration technology keeps getting better and better, \
+ and you're quite fond of not being a corpse? The 'Muur' type armor was a pretty successful attempt at an answer \
+ to the question. Using some advanced materials, micro-scale projectile dampener fields, and a whole \
+ host of other technologies that some poor SolFed procurement general had to talked to death about, \
+ it offers a unique advantage over many armor piercing bullets. Why stop the bullet from piercing the armor \
+ with more armor, when you could simply force the bullet to penetrate less and get away with less protection? \
+ Some people would rather the bullet just be stopped, of course, but when you have to make choices, many choose \
+ this one."
+
+ return .
+
+/obj/item/clothing/head/helmet/toggleable/sf_hardened/emt
+ name = "'Archangel' enclosed helmet"
+ desc = "A thick-fronted helmet with extendable visor for whole face protection. The materials and geometry of the helmet \
+ combine in such a way that bullets lose much of their armor penetrating energy before any damage can be done, rather than penetrate into it. \
+ This one has a red stripe down the front."
+ icon_state = "enclosed_emt"
diff --git a/modular_skyrat/modules/specialist_armor/code/peacekeeper.dm b/modular_skyrat/modules/specialist_armor/code/peacekeeper.dm
new file mode 100644
index 00000000000..999d3bf9508
--- /dev/null
+++ b/modular_skyrat/modules/specialist_armor/code/peacekeeper.dm
@@ -0,0 +1,75 @@
+// The peacekeeper armors and helmets will be less effective at stopping bullet damage than bulletproof vests, but stronger against wounds especially, and some other damage types
+/datum/armor/armor_sf_peacekeeper
+ melee = ARMOR_LEVEL_WEAK
+ bullet = ARMOR_LEVEL_MID
+ laser = ARMOR_LEVEL_TINY
+ energy = ARMOR_LEVEL_TINY
+ bomb = ARMOR_LEVEL_WEAK
+ fire = ARMOR_LEVEL_MID
+ acid = ARMOR_LEVEL_WEAK
+ wound = WOUND_ARMOR_HIGH
+
+/obj/item/clothing/suit/armor/sf_peacekeeper
+ name = "'Touvou' peacekeeper armor vest"
+ desc = "A bright blue vest, proudly bearing 'SF' in white on its front and back. Dense fabric with a thin layer of rolled metal \
+ will protect you from bullets best, a few blunt blows, and the wounds they cause. Lasers will burn more or less straight through it."
+ icon = 'modular_skyrat/modules/specialist_armor/icons/armor.dmi'
+ icon_state = "soft_peacekeeper"
+ worn_icon = 'modular_skyrat/modules/specialist_armor/icons/armor_worn.dmi'
+ inhand_icon_state = "armor"
+ blood_overlay_type = "armor"
+ armor_type = /datum/armor/armor_sf_peacekeeper
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
+
+/obj/item/clothing/suit/armor/sf_peacekeeper/examine_more(mob/user)
+ . = ..()
+
+ . += "A common SolFed designed armor vest for a common cause, not having your innards become outards. \
+ While heavier armors certainly exist, the 'Touvou' is relatively cheap for the protection you do get, \
+ and many soldiers and officers around the galaxy will tell you the convenience of a mostly soft body armor. \
+ Not for any of the protection, but for the relative comfort, especially in areas where you don't need to care \
+ much if you're able to stop an anti materiel round with your chest. Likely due to all those factors, \
+ it is a common sight on SolFed peacekeepers around the galaxy, alongside other misfits and corporate baddies \
+ across the galaxy."
+
+ return .
+
+/obj/item/clothing/suit/armor/sf_peacekeeper/debranded
+ name = "'Touvou' soft armor vest"
+ desc = "A bright white vest, notably missing an 'SF' marking on either its front or back. Dense fabric with a thin layer of rolled metal \
+ will protect you from bullets best, a few blunt blows, and the wounds they cause. Lasers will burn more or less straight through it."
+ icon_state = "soft_civilian"
+
+/obj/item/clothing/head/helmet/sf_peacekeeper
+ name = "'Kastrol' peacekeeper helmet"
+ desc = "A large, almost always ill-fitting helmet painted in bright blue. It proudly bears the emblems of SolFed on its sides. \
+ It will protect from bullets best, with some protection against blunt blows, but falters easily in the presence of lasers."
+ icon = 'modular_skyrat/modules/specialist_armor/icons/armor.dmi'
+ icon_state = "helmet_peacekeeper"
+ worn_icon = 'modular_skyrat/modules/specialist_armor/icons/armor_worn.dmi'
+ inhand_icon_state = "helmet"
+ armor_type = /datum/armor/armor_sf_peacekeeper
+ dog_fashion = null
+ flags_inv = null
+ supports_variations_flags = CLOTHING_SNOUTED_VARIATION_NO_NEW_ICON
+
+/obj/item/clothing/head/helmet/sf_peacekeeper/examine_more(mob/user)
+ . = ..()
+
+ . += "A common SolFed designed ballistic helmet for a common cause, keeping your brain inside your head. \
+ While heavier helmets certainly exist, the 'Kastrol' is relatively cheap for the protection you do get, \
+ and many soldiers don't mind it much due to its large over-head size bypassing a lot of the fitting issues \
+ some more advanced or more protective helmets might have. \
+ Especially in areas where you don't need to care \
+ much if you're able to stop an anti materiel round with your forehead, it does the job just fine. \
+ Likely due to all those factors, \
+ it is a common sight on SolFed peacekeepers around the galaxy, alongside other misfits and corporate baddies \
+ across the galaxy."
+
+ return .
+
+/obj/item/clothing/head/helmet/sf_peacekeeper/debranded
+ name = "'Kastrol' ballistic helmet"
+ desc = "A large, almost always ill-fitting helmet painted a dull grey. This one seems to lack any special markings. \
+ It will protect from bullets best, with some protection against blunt blows, but falters easily in the presence of lasers."
+ icon_state = "helmet_grey"
diff --git a/modular_skyrat/modules/specialist_armor/code/sacrificial.dm b/modular_skyrat/modules/specialist_armor/code/sacrificial.dm
new file mode 100644
index 00000000000..45643140f83
--- /dev/null
+++ b/modular_skyrat/modules/specialist_armor/code/sacrificial.dm
@@ -0,0 +1,156 @@
+// Sacrificial armor has massive bullet protection, but gets damaged by being shot, thus, is sacrificing itself to protect the wearer
+/datum/armor/armor_sf_sacrificial
+ melee = ARMOR_LEVEL_WEAK
+ bullet = ARMOR_LEVEL_INSANE // When the level IV plates stop the bullet but not the energy transfer
+ laser = ARMOR_LEVEL_TINY
+ energy = ARMOR_LEVEL_TINY
+ bomb = ARMOR_LEVEL_MID
+ fire = ARMOR_LEVEL_MID
+ acid = ARMOR_LEVEL_WEAK
+ wound = WOUND_ARMOR_HIGH
+
+/obj/item/clothing/suit/armor/sf_sacrificial
+ name = "'Val' sacrificial ballistic vest"
+ desc = "A hefty vest with a unique pattern of hexes on its outward faces. \
+ As the 'sacrificial' name might imply, this vest has extremely high bullet protection \
+ in exchange for allowing itself to be destroyed by impacts. It'll protect you from hell, \
+ but only for so long."
+ icon = 'modular_skyrat/modules/specialist_armor/icons/armor.dmi'
+ icon_state = "hexagon"
+ worn_icon = 'modular_skyrat/modules/specialist_armor/icons/armor_worn.dmi'
+ inhand_icon_state = "armor"
+ blood_overlay_type = "armor"
+ armor_type = /datum/armor/armor_sf_sacrificial
+ max_integrity = 200
+ limb_integrity = 200
+ repairable_by = null // No being cheeky and keeping a pile of repair materials in your bag to fix it either
+ supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON
+
+/obj/item/clothing/suit/armor/sf_sacrificial/Initialize(mapload)
+ . = ..()
+
+ AddComponent(/datum/component/clothing_damaged_by_bullets)
+
+/obj/item/clothing/suit/armor/sf_sacrificial/examine_more(mob/user)
+ . = ..()
+
+ . += "An extreme solution to an extreme problem. While many galactic armors have some semblance of self-repairing tech \
+ in them to prevent the armor becoming useless after being shot enough, it does have its limits. Those limits tend to be \
+ that the self-repairing, while handy, take the place of what could have simply been more armor. For a small market, \
+ one that doesn't care if their armor lasts more than one gunfight, there exists a niche for armors such as the 'Val'. \
+ Passing up self-repair for nigh-immunity to bullets, the right tool for a certain job, if you can find whatever that job may be."
+
+ return .
+
+/obj/item/clothing/head/helmet/sf_sacrificial
+ name = "'Val' sacrificial ballistic helmet"
+ desc = "A large, almost always ill-fitting helmet painted in a tacticool black. \
+ As the 'sacrificial' name might imply, this helmet has extremely high bullet protection \
+ in exchange for allowing itself to be destroyed by impacts. It'll protect you from hell, \
+ but only for so long."
+ icon = 'modular_skyrat/modules/specialist_armor/icons/armor.dmi'
+ icon_state = "bulletproof"
+ worn_icon = 'modular_skyrat/modules/specialist_armor/icons/armor_worn.dmi'
+ inhand_icon_state = "helmet"
+ armor_type = /datum/armor/armor_sf_sacrificial
+ max_integrity = 200
+ limb_integrity = 200
+ repairable_by = null // No being cheeky and keeping a pile of repair materials in your bag to fix it either
+ dog_fashion = null
+ flags_inv = null
+ supports_variations_flags = CLOTHING_SNOUTED_VARIATION_NO_NEW_ICON
+ /// Holds the faceshield for quick reference
+ var/obj/item/sacrificial_face_shield/face_shield
+
+/obj/item/clothing/head/helmet/sf_sacrificial/Initialize(mapload)
+ . = ..()
+
+ AddComponent(/datum/component/clothing_damaged_by_bullets)
+
+/obj/item/clothing/head/helmet/sf_sacrificial/attackby(obj/item/attacking_item, mob/user, params)
+ . = ..()
+
+ if(!(istype(attacking_item, /obj/item/sacrificial_face_shield)))
+ return
+
+ add_face_shield(user, attacking_item)
+
+/obj/item/clothing/head/helmet/sf_sacrificial/Destroy()
+ QDEL_NULL(face_shield)
+ return ..()
+
+/obj/item/clothing/head/helmet/sf_sacrificial/AltClick(mob/user)
+ remove_face_shield(user)
+
+/// Attached the passed face shield to the helmet.
+/obj/item/clothing/head/helmet/sf_sacrificial/proc/add_face_shield(mob/living/carbon/human/user, obj/shield_in_question)
+ if(face_shield)
+ return
+ if(!user.transferItemToLoc(shield_in_question, src))
+ return
+
+ flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDESNOUT
+ flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH | PEPPERPROOF
+
+ playsound(src, 'sound/items/modsuit/magnetic_harness.ogg', 50, TRUE)
+ face_shield = shield_in_question
+
+ icon_state = "bulletproof_glass"
+ worn_icon_state = icon_state
+ update_appearance()
+
+/// Removes the face shield from the helmet, breaking it into a glass shard decal if that's wanted, too.
+/obj/item/clothing/head/helmet/sf_sacrificial/proc/remove_face_shield(mob/living/carbon/human/user, break_it)
+ if(!face_shield)
+ return
+
+ flags_inv = initial(flags_inv)
+ flags_cover = initial(flags_cover)
+
+ if(break_it)
+ playsound(src, SFX_SHATTER, 70, TRUE)
+ new /obj/effect/decal/cleanable/glass(drop_location(src))
+ qdel(face_shield)
+ face_shield = null // just to be safe
+ else
+ user.put_in_hands(face_shield)
+ playsound(src, 'sound/items/modsuit/magnetic_harness.ogg', 50, TRUE)
+ face_shield = null
+
+ icon_state = initial(icon_state)
+ worn_icon_state = icon_state // Against just to be safe
+ update_appearance()
+
+/obj/item/clothing/head/helmet/sf_sacrificial/take_damage_zone(def_zone, damage_amount, damage_type, armour_penetration)
+ . = ..()
+
+ if((damage_amount > 20) && face_shield)
+ remove_face_shield(break_it = TRUE)
+
+/obj/item/clothing/head/helmet/sf_sacrificial/examine(mob/user)
+ . = ..()
+ if(face_shield)
+ . += span_notice("The face shield can be removed with Right-Click.")
+ else
+ . += span_notice("A face shield can be attached to it.")
+
+ return .
+
+/obj/item/clothing/head/helmet/sf_sacrificial/examine_more(mob/user)
+ . = ..()
+
+ . += "An extreme solution to an extreme problem. While many galactic armors have some semblance of self-repairing tech \
+ in them to prevent the armor becoming useless after being shot enough, it does have its limits. Those limits tend to be \
+ that the self-repairing, while handy, take the place of what could have simply been more armor. For a small market, \
+ one that doesn't care if their armor lasts more than one gunfight, there exists a niche for armors such as the 'Val'. \
+ Passing up self-repair for nigh-immunity to bullets, the right tool for a certain job, if you can find whatever that job may be."
+
+ return .
+
+/obj/item/sacrificial_face_shield
+ name = "'Val' ballistic add-on face plate"
+ desc = "A thick piece of glass with mounting points for slotting onto a 'Val' sacrificial ballistic helmet. \
+ While it does not make the helmet any stronger, it does protect your face much like a riot helmet would."
+ icon = 'modular_skyrat/modules/specialist_armor/icons/armor.dmi'
+ icon_state = "face_shield"
+ w_class = WEIGHT_CLASS_NORMAL
diff --git a/modular_skyrat/modules/specialist_armor/icons/armor.dmi b/modular_skyrat/modules/specialist_armor/icons/armor.dmi
new file mode 100644
index 0000000000000000000000000000000000000000..d3e56a6b051d400af9db90a2f0363811067a21b0
GIT binary patch
literal 2417
zcmZ`*SvVVr7EWrZ*p1ltSVl3`($bX>CeqecOGk~hYN;whYN;ibqLw5@?K{n&h+3Lf
z396P(+KR2(s%8*DQZh_}rXp8o?tI^Uxew?6&v`g6=llP2&OIjwxP+*(C;$MEK-k$_
zK4A3s5D`AWAqzk90lkZN{UzGwdek*!NJMl<_$>e+w&Fql8_5@%(&^*NN3!}<_-)>o
zRF(!w)@j$TW`UJ!+^F9ECnwTs`_>1{jXH6Yu%vTxC(c%n0hkRF(T*`>ImE5}J2EeC
z!+rpM5U~_pDTV7RyqzX}88G-YMe?@Q4@X>6(?w}(f=Y3J@&3py`AmWa&v2u;ASg#Drl55l%!^zlO~Ot5QX~H(2k$kx`z-%O1PGeD8#u;;{-^I
zOr*?15glF$9%JJ2_;1zoEAbl<^v_ZBswgU*pXTTNHi~6xIv!OO6-e*Zw-wP!m$v>6
z`8A2d_{OODCnC%n0UaHIoQuxM{HnhT6GEs}7t$j<9d*(q51-sYMx1;9SC&F)i;>TE
zi9)H-Yeq#=&-3R7zgr1+ys1lW?)HVlBP)xBP)gKuoYzy_kBvUXrxOCIccK7KpLzPQ
zOd0$@ez8?FevQ98gW$a9eK{k(WOQqo*WaTF(9>U6HB-SF*#f3TV=OgX?h
zB5{|sXvQv)FSu#P%bCN!ym*q^s*O&+tr#oK`c)0q9rCWnl!^~AZXWFMLZ*JB?KMuZBm25%M5Bx3@siN
zdlK2=z8A}=m^of8E}rmEQuU*cv!n?wOrG~n1|Y0Hz0FZMI+t|_!Ypq{xxZ8}_E`EY
zns4J^xI;BF(PA@a*PE$LA~$ca{hj}!zFz=wdwVW}M$Mg<|?)1Xzw=r)QNvF~P^$HxU
z_#<+fLN8<16wv0Dd^}C%=%~(ojIhW)05=f2n({Ps5*0raR^LVjH%}b4Ml==Rg$tdwPfq;RY7SeL5e4^{3?$zYMqO-
zdhrJs2tX2P+q6g{v!N1Ku@Nm3j=ieI)2UF;y%TH;QR^&{NXTlUV0ufUOp7*vTZR~w
z0&%#IAHj7#6%G%rnyuI5D7HUcEHi$&dtm455eB~jA(!4@g-+k2EcaW0^GFR6UP~%$
zN1F{eODA#gcpuB(ZgL}8z9JhP@PQCxf9P0JmbX=^y=3O=Hw6M#5ZpnQ%fd9J(vm*0
z8U`b8LPX(5ZBwGupvO>`L_p#>s+cMS@qvL-tDxPetJ3gmqO2W@)^#hWQ9x6|WL`)+
zJt7rZdhyFb8L(9i+LOs##?toO42ymo)~3!6>9U7*7X{DwC*0r6OHcAe9y*@%7`gf^
zrh~ShQ=DXu&sk7lzcxMvdyWE+vBAC{&DJvk84l$6NEw-knhQ>0rop&u3lk6WDmShvCOb
zOmE$iI%qvDshsWp&L?M8LEFLi>WxjMr=QJhtGLW{v;?frxa%OR1lkEeVY2@tj(^uD
z&efz_bDc$%^=l)^dV1&WT-n%%RCN*v;ZgQIaP#b>%D@@cCsVt^Yjt$m9>-2BQC1nz
zf28#T`|Me0*%rk##wA&i=b#3oY-`kxoUlEO(fWzq;xWy-(vK3veR#x)`x>wx?~LiX
zr*7@s_@Pq;(eKd7Al?Qj@mIE64R4HMb}q>J#9DaQh9ZODCC)Ew`Y)-6H4C6SgD{6@
z!h82YHxhYzzY?fTl9~nJ;EZ`}(_-YP{+1&uA5YmGO#jnM${
z50`y90!)J<&9@SDk~pZH7|e-z5<
zb*_VpOW`n7-0uNp=g)=hb8(g0!yxo2>&wC!3LgHM1p?_M{h#GQYdzXJR?4(?3g}A&
z5-t7L>|Dgk+=7CsxhBF^a>bEd#C-EzTX?g4SQOjNH9p-9rjtR=Ez3@Tm%J(lvLAP`7iBB
Yq1)jj2HCz92R{@5Ve4SiX6>8$A4Z0$@Bjb+
literal 0
HcmV?d00001
diff --git a/modular_skyrat/modules/specialist_armor/icons/armor_worn.dmi b/modular_skyrat/modules/specialist_armor/icons/armor_worn.dmi
new file mode 100644
index 0000000000000000000000000000000000000000..ad052b7aaf3040cda33b0e239c4fbead5d620c5b
GIT binary patch
literal 5316
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