diff --git a/code/game/objects/items/weapons/material/material_armor.dm b/code/game/objects/items/weapons/material/material_armor.dm
index dccd65b567..1041fb5d1f 100644
--- a/code/game/objects/items/weapons/material/material_armor.dm
+++ b/code/game/objects/items/weapons/material/material_armor.dm
@@ -1,6 +1,29 @@
-// SEE code/modules/materials/materials.dm FOR DETAILS ON INHERITED DATUM.
-// This class of weapons takes armor and appearance data from a material datum.
-// They are also fragile based on material data and many can break/smash apart when hit.
+#define MATERIAL_ARMOR_COEFFICENT 0.05
+/*
+SEE code/modules/materials/materials.dm FOR DETAILS ON INHERITED DATUM.
+This class of armor takes armor and appearance data from a material "datum".
+They are also fragile based on material data and many can break/smash apart when hit.
+
+Materials has a var called protectiveness which plays a major factor in how good it is for armor.
+With the coefficent being 0.05, this is how strong different levels of protectiveness are (for melee)
+For bullets and lasers, material hardness and reflectivity also play a major role, respectively.
+
+
+Protectiveness | Armor %
+ 0 = 0%
+ 5 = 20%
+ 10 = 33%
+ 15 = 42%
+ 20 = 50%
+ 25 = 55%
+ 30 = 60%
+ 40 = 66%
+ 50 = 71%
+ 60 = 75%
+ 70 = 77%
+ 80 = 80%
+*/
+
// Putting these at /clothing/ level saves a lot of code duplication in armor/helmets/gauntlets/etc
/obj/item/clothing
@@ -8,6 +31,7 @@
var/applies_material_color = TRUE
var/unbreakable = FALSE
var/default_material = null // Set this to something else if you want material attributes on init.
+ var/material_armor_modifer = 1 // Adjust if you want seperate types of armor made from the same material to have different protectiveness (e.g. makeshift vs real armor)
/obj/item/clothing/New(var/newloc, var/material_key)
..(newloc)
@@ -23,51 +47,115 @@
/obj/item/clothing/get_material()
return material
-// Debating if this should be made an /atom/movable/ proc.
+// Debating if this should be made an /obj/item/ proc.
/obj/item/clothing/proc/set_material(var/new_material)
material = get_material_by_name(new_material)
if(!material)
qdel(src)
else
name = "[material.display_name] [initial(name)]"
+ health = round(material.integrity/10)
if(applies_material_color)
color = material.icon_colour
if(material.products_need_process())
processing_objects |= src
update_armor()
-//f(x) = (x*a) / (x+b) + c
-// a + c essentially* becomes your maximum possible output,
-// c is your minimum, and b controls how quickly the output values scale and its effectiveness is relative to the value of a.
+// This is called when someone wearing the object gets hit in some form (melee, bullet_act(), etc).
+// Note that this cannot change if someone gets hurt, as it merely reacts to being hit.
+/obj/item/clothing/proc/clothing_impact(var/obj/source, var/damage)
+ if(material && damage)
+ material_impact(source, damage)
-// Max is the cap, excluding min.
-// Mid is the midpoint on the curve.
-// Min adds a floor to the answer. Min + Max is the maximum possible output.
-/proc/calculate_curve(var/X, var/max, var/mid, var/min)
- return (X * max) / (X + mid) + min
+/obj/item/clothing/proc/material_impact(var/obj/source, var/damage)
+ if(!material || unbreakable)
+ return
+
+ if(istype(source, /obj/item/projectile))
+ var/obj/item/projectile/P = source
+ if(P.pass_flags & PASSGLASS)
+ if(material.opacity - 0.3 <= 0)
+ return // Lasers ignore 'fully' transparent material.
+
+ if(material.is_brittle())
+ health = 0
+ else if(!prob(material.hardness))
+ health--
+
+ if(health <= 0)
+ shatter()
+
+/obj/item/clothing/proc/shatter()
+ if(!material)
+ return
+ var/turf/T = get_turf(src)
+ T.visible_message("\The [src] [material.destruction_desc]!")
+ if(istype(loc, /mob/living))
+ var/mob/living/M = loc
+ M.drop_from_inventory(src)
+ if(material.shard_type == SHARD_SHARD) // Wearing glass armor is a bad idea.
+ var/obj/item/weapon/material/shard/S = material.place_shard(T)
+ M.embed(S)
+
+ playsound(src, "shatter", 70, 1)
+ qdel(src)
+
+// Might be best to make ablative vests a material armor using a new material to cut down on this copypaste.
+/obj/item/clothing/suit/armor/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
+ if(!material) // No point checking for reflection.
+ return ..()
+
+ if(material.reflectivity)
+ if(istype(damage_source, /obj/item/projectile/energy) || istype(damage_source, /obj/item/projectile/beam))
+ var/obj/item/projectile/P = damage_source
+
+ if(P.reflected) // Can't reflect twice
+ return ..()
+
+ var/reflectchance = (40 * material.reflectivity) - round(damage/3)
+ reflectchance *= material_armor_modifer
+ if(!(def_zone in list(BP_TORSO, BP_GROIN)))
+ reflectchance /= 2
+ if(P.starting && prob(reflectchance))
+ visible_message("\The [user]'s [src.name] reflects [attack_text]!")
+
+ // Find a turf near or on the original location to bounce to
+ var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
+ var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
+ var/turf/curloc = get_turf(user)
+
+ // redirect the projectile
+ P.redirect(new_x, new_y, curloc, user)
+ P.reflected = 1
+
+ return PROJECTILE_CONTINUE // complete projectile permutation
+
+/proc/calculate_material_armor(amount)
+ var/result = 1 - MATERIAL_ARMOR_COEFFICENT * amount / (1 + MATERIAL_ARMOR_COEFFICENT * abs(amount))
+ result = result * 100
+ result = abs(result - 100)
+ return round(result)
-/client/verb/test_curve(var/X as num, var/A as num, var/B as num, var/C as num)
- src << "Testing values: X:[X], A:[A], B:[B], C:[C]."
- src << calculate_curve(X, A, B, C)
/obj/item/clothing/proc/update_armor()
if(material)
var/melee_armor = 0, bullet_armor = 0, laser_armor = 0, energy_armor = 0, bomb_armor = 0
- melee_armor = round(Clamp(material.hardness, 0, 90))
+ melee_armor = calculate_material_armor(material.protectiveness * material_armor_modifer)
- bullet_armor = round(Clamp(material.hardness * 0.6, 0, 90))
+ bullet_armor = calculate_material_armor((material.protectiveness * (material.hardness / 100) * material_armor_modifer) * 0.7)
- laser_armor = material.hardness * 0.6
- if(material.reflectivity)
- laser_armor *= (material.reflectivity + 1) // Each 0.1th of reflectivity gives 10% more protection.
+ laser_armor = calculate_material_armor((material.protectiveness * (material.reflectivity + 1) * material_armor_modifer) * 0.7)
if(material.opacity != 1)
laser_armor *= max(material.opacity - 0.3, 0) // Glass and such has an opacity of 0.3, but lasers should go through glass armor entirely.
- laser_armor = round(Clamp(laser_armor, 0, 90))
- energy_armor = round(Clamp(laser_armor * 0.7, 0, 90))
+ energy_armor = calculate_material_armor((material.protectiveness * material_armor_modifer) * 0.4)
- bomb_armor = round(Clamp(material.explosion_resistance * 2, 0, 90))
+ bomb_armor = calculate_material_armor((material.protectiveness * material_armor_modifer) * 0.5)
+
+ // Makes sure the numbers stay capped.
+ for(var/number in list(melee_armor, bullet_armor, laser_armor, energy_armor, bomb_armor))
+ number = between(0, number, 100)
armor["melee"] = melee_armor
armor["bullet"] = bullet_armor
@@ -76,29 +164,100 @@
armor["bomb"] = bomb_armor
if(!isnull(material.conductivity))
- siemens_coefficient = Clamp(material.conductivity / 10, 0, 4)
- slowdown = Clamp(round(material.weight / 10, 0.1), 0, 6)
-// armor = list(
-// melee = melee_armor,
-// bullet = bullet_armor,
-// laser = laser_armor,
-// energy = energy_armor,
-// bomb = bomb_armor,
-// bio = 0,
-// rad = 0)
-/*
-/obj/item/weapon/material/proc/update_force()
- if(edge || sharp)
- force = material.get_edge_damage()
- else
- force = material.get_blunt_damage()
- force = round(force*force_divisor)
- throwforce = round(material.get_blunt_damage()*thrown_force_divisor)
- //spawn(1)
- // world << "[src] has force [force] and throwforce [throwforce] when made from default material [material.name]"
-*/
+ siemens_coefficient = between(0, material.conductivity / 10, 10)
+ slowdown = between(0, round(material.weight / 10, 0.1), 6)
+
/obj/item/clothing/suit/armor/material
- icon_state = "material_armor_makeshift" // placeholder
+ name = "armor"
default_material = DEFAULT_WALL_MATERIAL
+/obj/item/clothing/suit/armor/material/makeshift
+ name = "sheet armor"
+ desc = "This appears to be two 'sheets' of a material held together by cable. If the sheets are strong, this could be rather protective."
+ icon_state = "material_armor_makeshift"
+/obj/item/clothing/suit/armor/material/makeshift/durasteel
+ default_material = "durasteel"
+
+/obj/item/clothing/suit/armor/material/makeshift/glass
+ default_material = "glass"
+
+// Used to craft sheet armor, and possibly other things in the Future(tm).
+/obj/item/weapon/material/armor_plating
+ name = "armor plating"
+ desc = "A sheet designed to protect something."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "armor_plate"
+ unbreakable = TRUE
+ force_divisor = 0.05 // Really bad as a weapon.
+ thrown_force_divisor = 0.2
+ var/wired = FALSE
+
+/obj/item/weapon/material/armor_plating/attackby(var/obj/O, mob/user)
+ if(istype(O, /obj/item/stack/cable_coil))
+ var/obj/item/stack/cable_coil/S = O
+ if(wired)
+ to_chat(user, "This already has enough wires on it.")
+ return
+ if(S.use(20))
+ to_chat(user, "You attach several wires to \the [src]. Now it needs another plate.")
+ wired = TRUE
+ icon_state = "[initial(icon_state)]_wired"
+ return
+ else
+ to_chat(user, "You need more wire for that.")
+ return
+ if(istype(O, /obj/item/weapon/material/armor_plating))
+ var/obj/item/weapon/material/armor_plating/second_plate = O
+ if(!wired && !second_plate.wired)
+ to_chat(user, "You need something to hold the two pieces of plating together.")
+ return
+ if(second_plate.material != src.material)
+ to_chat(user, "Both plates need to be the same type of material.")
+ return
+ user.drop_from_inventory(src)
+ user.drop_from_inventory(second_plate)
+ var/obj/item/clothing/suit/armor/material/makeshift/new_armor = new(null, src.material.name)
+ user.put_in_hands(new_armor)
+ qdel(second_plate)
+ qdel(src)
+ else
+ ..()
+
+
+// Used to craft the makeshift helmet
+/obj/item/clothing/head/helmet/bucket
+ name = "bucket"
+ desc = "It's a bucket with a large hole cut into it. You could wear it on your head and look really stupid."
+ flags_inv = HIDEEARS|HIDEEYES|BLOCKHAIR
+ icon_state = "bucket"
+ armor = list(melee = 5, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
+
+/obj/item/clothing/head/helmet/bucket/attackby(var/obj/O, mob/user)
+ if(istype(O, /obj/item/stack/material))
+ var/obj/item/stack/material/S = O
+ if(S.use(2))
+ to_chat(user, "You apply some [S.material.use_name] to \the [src]. Hopefully it'll make the makeshift helmet stronger.")
+ var/obj/item/clothing/head/helmet/material/makeshift/helmet = new(null, S.material.name)
+ user.put_in_hands(helmet)
+ user.drop_from_inventory(src)
+ qdel(src)
+ return
+ else
+ to_chat(user, "You don't have enough material to build a helmet!")
+ else
+ ..()
+
+/obj/item/clothing/head/helmet/material
+ name = "helmet"
+ flags_inv = HIDEEARS|HIDEEYES|BLOCKHAIR
+ default_material = DEFAULT_WALL_MATERIAL
+
+/obj/item/clothing/head/helmet/material/makeshift
+ name = "bucket"
+ desc = "A bucket with plating applied to the outside. Very crude, but could potentially be rather protective, if \
+ it was plated with something strong."
+ icon_state = "material_armor_makeshift"
+
+/obj/item/clothing/head/helmet/material/makeshift/durasteel
+ default_material = "durasteel"
\ No newline at end of file
diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm
index d08726371a..f090312320 100644
--- a/code/modules/clothing/suits/armor.dm
+++ b/code/modules/clothing/suits/armor.dm
@@ -80,6 +80,9 @@
if(istype(damage_source, /obj/item/projectile/energy) || istype(damage_source, /obj/item/projectile/beam))
var/obj/item/projectile/P = damage_source
+ if(P.reflected) // Can't reflect twice
+ return ..()
+
var/reflectchance = 40 - round(damage/3)
if(!(def_zone in list(BP_TORSO, BP_GROIN)))
reflectchance /= 2
diff --git a/code/modules/materials/material_recipes.dm b/code/modules/materials/material_recipes.dm
index 11f6021c75..68fb129108 100644
--- a/code/modules/materials/material_recipes.dm
+++ b/code/modules/materials/material_recipes.dm
@@ -10,6 +10,7 @@
recipes += new/datum/stack_recipe("[display_name] baseball bat", /obj/item/weapon/material/twohanded/baseballbat, 10, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]")
recipes += new/datum/stack_recipe("[display_name] ashtray", /obj/item/weapon/material/ashtray, 2, one_per_turf = 1, on_floor = 1, supplied_material = "[name]")
recipes += new/datum/stack_recipe("[display_name] spoon", /obj/item/weapon/material/kitchen/utensil/spoon/plastic, 1, on_floor = 1, supplied_material = "[name]")
+ recipes += new/datum/stack_recipe("[display_name] armor plate", /obj/item/weapon/material/armor_plating, 1, time = 20, on_floor = 1, supplied_material = "[name]")
if(integrity>=50)
recipes += new/datum/stack_recipe("[display_name] door", /obj/structure/simple_door, 10, one_per_turf = 1, on_floor = 1, supplied_material = "[name]")
diff --git a/code/modules/materials/materials.dm b/code/modules/materials/materials.dm
index 5886c8447f..db4fbebc00 100644
--- a/code/modules/materials/materials.dm
+++ b/code/modules/materials/materials.dm
@@ -90,11 +90,12 @@ var/list/name_to_material
var/ignition_point // K, point at which the material catches on fire.
var/melting_point = 1800 // K, walls will take damage if they're next to a fire hotter than this
var/integrity = 150 // General-use HP value for products.
+ var/protectiveness = 10 // How well this material works as armor. Higher numbers are better, diminishing returns applies.
var/opacity = 1 // Is the material transparent? 0.5< makes transparent walls/doors.
- var/reflectivity = 0 // How reflective to light is the material? Currently used for laser defense.
+ var/reflectivity = 0 // How reflective to light is the material? Currently used for laser reflection and defense.
var/explosion_resistance = 5 // Only used by walls currently.
var/conductive = 1 // Objects with this var add CONDUCTS to flags on spawn.
- var/conductivity = null // How conductive the material is. Based somewhat on megasiemens / metre at 20c
+ var/conductivity = null // How conductive the material is. Iron acts as the baseline, at 10.
var/list/composite_material // If set, object matter var will be a list containing these values.
// Placeholder vars for the time being, todo properly integrate windows/light tiles/rods.
@@ -104,7 +105,7 @@ var/list/name_to_material
var/list/window_options = list()
// Damage values.
- var/hardness = 60 // Prob of wall destruction by hulk, used for edge damage in weapons.
+ var/hardness = 60 // Prob of wall destruction by hulk, used for edge damage in weapons. Also used for bullet protection in armor.
var/weight = 20 // Determines blunt damage/throwforce for weapons.
// Noise when someone is faceplanted onto a table made of this material.
@@ -237,6 +238,7 @@ var/list/name_to_material
icon_colour = "#00FFE1"
opacity = 0.4
reflectivity = 0.6
+ conductivity = 1
shard_type = SHARD_SHARD
tableslam_noise = 'sound/effects/Glasshit.ogg'
hardness = 100
@@ -307,6 +309,8 @@ var/list/name_to_material
shard_type = SHARD_STONE_PIECE
weight = 22
hardness = 55
+ protectiveness = 5 // 20%
+ conductivity = 5
door_icon_base = "stone"
sheet_singular_name = "brick"
sheet_plural_name = "bricks"
@@ -323,7 +327,8 @@ var/list/name_to_material
name = DEFAULT_WALL_MATERIAL
stack_type = /obj/item/stack/material/steel
integrity = 150
- conductivity = 6.99 // Assuming this is carbon steel
+ conductivity = 11 // Assuming this is carbon steel, it would actually be slightly less conductive than iron, but lets ignore that.
+ protectiveness = 10 // 33%
icon_base = "solid"
icon_reinf = "reinf_over"
icon_colour = "#666666"
@@ -359,6 +364,8 @@ var/list/name_to_material
explosion_resistance = 25
hardness = 80
weight = 23
+ protectiveness = 20 // 50%
+ conductivity = 13 // For the purposes of balance.
stack_origin_tech = list(TECH_MATERIAL = 2)
composite_material = list(DEFAULT_WALL_MATERIAL = SHEET_MATERIAL_AMOUNT, "platinum" = SHEET_MATERIAL_AMOUNT) //todo
@@ -374,6 +381,7 @@ var/list/name_to_material
explosion_resistance = 75
hardness = 100
weight = 28
+ protectiveness = 60 // 75%
reflectivity = 0.7 // Not a perfect mirror, but close.
stack_origin_tech = list(TECH_MATERIAL = 8)
composite_material = list("plasteel" = SHEET_MATERIAL_AMOUNT, "diamond" = SHEET_MATERIAL_AMOUNT) //shrug
@@ -398,6 +406,8 @@ var/list/name_to_material
tableslam_noise = 'sound/effects/Glasshit.ogg'
hardness = 30
weight = 15
+ protectiveness = 0 // 0%
+ conductivity = 1 // Glass shards don't conduct.
door_icon_base = "stone"
destruction_desc = "shatters"
window_options = list("One Direction" = 1, "Full Window" = 4, "Windoor" = 2)
@@ -531,6 +541,8 @@ var/list/name_to_material
icon_colour = "#CCCCCC"
hardness = 10
weight = 12
+ protectiveness = 5 // 20%
+ conductivity = 2 // For the sake of material armor diversity, we're gonna pretend this plastic is a good insulator.
melting_point = T0C+371 //assuming heat resistant plastic
stack_origin_tech = list(TECH_MATERIAL = 3)
@@ -561,6 +573,7 @@ var/list/name_to_material
stack_type = /obj/item/stack/material/mhydrogen
icon_colour = "#E6C5DE"
stack_origin_tech = list(TECH_MATERIAL = 6, TECH_POWER = 6, TECH_MAGNET = 5)
+ conductivity = 100
/material/platinum
name = "platinum"
@@ -592,6 +605,7 @@ var/list/name_to_material
explosion_resistance = 200 // Hull plating.
hardness = 500
weight = 500
+ protectiveness = 80 // 80%
// Likewise.
/material/alienalloy/elevatorium
@@ -610,6 +624,8 @@ var/list/name_to_material
shard_can_repair = 0 // you can't weld splinters back into planks
hardness = 15
weight = 18
+ protectiveness = 8 // 28%
+ conductivity = 1
melting_point = T0C+300 //okay, not melting in this case, but hot enough to destroy wood
ignition_point = T0C+288
stack_origin_tech = list(TECH_MATERIAL = 1, TECH_BIO = 1)
@@ -641,6 +657,7 @@ var/list/name_to_material
icon_colour = "#AAAAAA"
hardness = 1
weight = 1
+ protectiveness = 0 // 0%
ignition_point = T0C+232 //"the temperature at which book-paper catches fire, and burns." close enough
melting_point = T0C+232 //temperature at which cardboard walls would be destroyed
stack_origin_tech = list(TECH_MATERIAL = 1)
@@ -657,6 +674,7 @@ var/list/name_to_material
integrity = 1
hardness = 1
weight = 1
+ protectiveness = 0 // 0%
stack_origin_tech = list(TECH_MATERIAL = 1)
melting_point = T0C+1
destruction_desc = "crumples"
@@ -669,6 +687,7 @@ var/list/name_to_material
door_icon_base = "wood"
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
flags = MATERIAL_PADDING
/material/cult
@@ -702,6 +721,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+300
melting_point = T0C+300
+ protectiveness = 3 // 13%
/material/carpet
name = "carpet"
@@ -713,6 +733,7 @@ var/list/name_to_material
melting_point = T0C+300
sheet_singular_name = "tile"
sheet_plural_name = "tiles"
+ protectiveness = 1 // 4%
/material/cotton
name = "cotton"
@@ -721,7 +742,9 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
+// This all needs to be OOP'd and use inheritence if its ever used in the future.
/material/cloth_teal
name = "teal"
display_name ="teal"
@@ -730,6 +753,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
/material/cloth_black
name = "black"
@@ -739,6 +763,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
/material/cloth_green
name = "green"
@@ -748,6 +773,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
/material/cloth_puple
name = "purple"
@@ -757,6 +783,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
/material/cloth_blue
name = "blue"
@@ -766,6 +793,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
/material/cloth_beige
name = "beige"
@@ -775,6 +803,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
/material/cloth_lime
name = "lime"
@@ -784,6 +813,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
+ protectiveness = 1 // 4%
/material/toy_foam
name = "foam"
@@ -794,4 +824,5 @@ var/list/name_to_material
melting_point = T0C+300
icon_colour = "#ff9900"
hardness = 1
- weight = 1
\ No newline at end of file
+ weight = 1
+ protectiveness = 0 // 0%
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 86bbdebc15..f5fa2f582c 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -27,6 +27,11 @@ emp_act
if(!P.nodamage)
organ.add_autopsy_data("[P.name]", P.damage)
+ // Tell clothing we're wearing that it got hit by a bullet/laser/etc
+ var/list/clothing = get_clothing_list_organ(organ)
+ for(var/obj/item/clothing/C in clothing)
+ C.clothing_impact(P, P.damage)
+
//Shrapnel
if(P.can_embed())
var/armor = getarmor_organ(organ, "bullet")
@@ -130,6 +135,15 @@ emp_act
return siemens_coefficient
+// Returns a list of clothing that is currently covering def_zone.
+/mob/living/carbon/human/proc/get_clothing_list_organ(var/obj/item/organ/external/def_zone, var/type)
+ var/list/results = list()
+ var/list/clothing_items = list(head, wear_mask, wear_suit, w_uniform, gloves, shoes)
+ for(var/obj/item/clothing/C in clothing_items)
+ if(istype(C) && (C.body_parts_covered & def_zone.body_part))
+ results.Add(C)
+ return results
+
//this proc returns the armour value for a particular external organ.
/mob/living/carbon/human/proc/getarmor_organ(var/obj/item/organ/external/def_zone, var/type)
if(!type || !def_zone) return 0
@@ -246,6 +260,12 @@ emp_act
if(!affecting)
return 0
+ // Allow clothing to respond to being hit.
+ // This is done up here so that clothing damage occurs even if fully blocked.
+ var/list/clothing = get_clothing_list_organ(affecting)
+ for(var/obj/item/clothing/C in clothing)
+ C.clothing_impact(I, effective_force)
+
if(soaked >= effective_force)
return 0
diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm
index ed27e1a259..bd670cc8bc 100644
--- a/code/modules/reagents/reagent_containers/glass.dm
+++ b/code/modules/reagents/reagent_containers/glass.dm
@@ -243,6 +243,12 @@
user.drop_from_inventory(src)
qdel(src)
return
+ else if(istype(D, /obj/item/weapon/wirecutters))
+ to_chat(user, "You cut a big hole in \the [src] with \the [D]. It's kinda useless as a bucket now.")
+ user.put_in_hands(new /obj/item/clothing/head/helmet/bucket)
+ user.drop_from_inventory(src)
+ qdel(src)
+ return
else if(istype(D, /obj/item/weapon/mop))
if(reagents.total_volume < 1)
user << "\The [src] is empty!"
diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi
index 7407aeefb5..44f920fe30 100644
Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ
diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi
index 9337d5127c..ef18c7bf49 100644
Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ
diff --git a/icons/obj/items.dmi b/icons/obj/items.dmi
index dc3456ba67..778ec461bb 100644
Binary files a/icons/obj/items.dmi and b/icons/obj/items.dmi differ