diff --git a/code/__HELPERS/traits.dm b/code/__HELPERS/traits.dm
index efe5a33b3da..02b517e74ce 100644
--- a/code/__HELPERS/traits.dm
+++ b/code/__HELPERS/traits.dm
@@ -218,6 +218,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define CHANGELING_TRAIT "changeling"
#define LYING_DOWN_TRAIT "lying_down"
#define SLIME_TRAIT "slime"
+#define BERSERK_TRAIT "berserk"
// unique trait sources
#define STATUE_MUTE "statue"
diff --git a/code/modules/clothing/spacesuits/ert.dm b/code/modules/clothing/spacesuits/ert.dm
index 6ab76b685fd..2f4a9473e6c 100644
--- a/code/modules/clothing/spacesuits/ert.dm
+++ b/code/modules/clothing/spacesuits/ert.dm
@@ -261,22 +261,6 @@
armor = list(MELEE = 95, BULLET = 50, LASER = 50, ENERGY = 50, BOMB = 50, BIO = INFINITY, RAD = INFINITY, FIRE = 200, ACID = 200)
slowdown = 0
-/obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/berserker
- name = "champion's helmet"
- desc = "Peering into the eyes of the helmet is enough to seal damnation."
- icon_state = "hardsuit0-berserker"
- item_color = "berserker"
- max_heat_protection_temperature = SPACE_HELM_MAX_TEMP_PROTECT
- armor = list(MELEE = 60, BULLET = 20, LASER = 15, ENERGY = 15, BOMB = 75, BIO = INFINITY, RAD = 25, FIRE = 200, ACID = 200)
-
-/obj/item/clothing/suit/space/hardsuit/ert/paranormal/berserker
- name = "champion's hardsuit"
- desc = "Voices echo from the hardsuit, driving the user insane."
- icon_state = "hardsuit-berserker"
- max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT
- helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/berserker
- armor = list(MELEE = 60, BULLET = 20, LASER = 15, ENERGY = 15, BOMB = 75, BIO = INFINITY, RAD = 25, FIRE = 200, ACID = 200)
- slowdown = 0
// Solgov
diff --git a/code/modules/clothing/suits/hood.dm b/code/modules/clothing/suits/hood.dm
index be05ced4fd8..eff09bbbd72 100644
--- a/code/modules/clothing/suits/hood.dm
+++ b/code/modules/clothing/suits/hood.dm
@@ -4,6 +4,8 @@
actions_types = list(/datum/action/item_action/toggle)
var/obj/item/clothing/head/hooded/hood
var/hoodtype = /obj/item/clothing/head/hooded/winterhood //so the chaplain hoodie or other hoodies can override this
+ /// If this variable is true, the hood can not be removed if the hood is nodrop
+ var/respects_nodrop = FALSE
/obj/item/clothing/suit/hooded/Initialize(mapload)
. = ..()
@@ -67,6 +69,11 @@
var/datum/action/A = X
A.UpdateButtonIcon()
else
+ if((hood.flags & NODROP) && respects_nodrop)
+ if(ishuman(loc))
+ var/mob/living/carbon/human/H = loc
+ to_chat(H, "[hood] is stuck to your head!")
+ return
RemoveHood()
/obj/item/clothing/head/hooded
diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index fda0f0b26e1..4dfb3f4eaf9 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -42,7 +42,7 @@
if(11)
new /obj/item/ship_in_a_bottle(src)
if(12)
- new /obj/item/clothing/suit/space/hardsuit/ert/paranormal/berserker(src)
+ new /obj/item/clothing/suit/hooded/berserker(src)
if(13)
new /obj/item/nullrod/scythe/talking(src)
if(14)
@@ -150,6 +150,159 @@
//Spooky special loot
+// Beserker armor
+
+#define MAX_BERSERK_CHARGE 100
+#define PROJECTILE_HIT_MULTIPLIER 1.5
+#define DAMAGE_TO_CHARGE_SCALE 0.75
+#define CHARGE_DRAINED_PER_SECOND 5
+#define BERSERK_DAMAGE_REDUCTION 0.6
+#define BERSERK_ATTACK_SPEED_MODIFIER 0.5
+#define BERSERK_COLOUR "#950a0a"
+
+/obj/item/clothing/suit/hooded/berserker
+ name = "champion's hardsuit"
+ desc = "Voices echo from the hardsuit, driving the user insane. Is not space-proof."
+ icon_state = "hardsuit-berserker"
+ allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator, /obj/item/pickaxe, /obj/item/twohanded/spear)
+ armor = list(MELEE = 30, BULLET = 15, LASER = 10, ENERGY = 10, BOMB = 150, BIO = 0, RAD = 0, FIRE = INFINITY, ACID = INFINITY)
+ hoodtype = /obj/item/clothing/head/hooded/berserker
+ flags_inv = HIDEGLOVES | HIDESHOES | HIDEJUMPSUIT | HIDETAIL
+ heat_protection = UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS
+ body_parts_covered = UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS
+ max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
+ resistance_flags = FIRE_PROOF | ACID_PROOF
+ respects_nodrop = TRUE
+ sprite_sheets = list(
+ "Tajaran" = 'icons/mob/clothing/species/tajaran/suit.dmi',
+ "Unathi" = 'icons/mob/clothing/species/unathi/suit.dmi',
+ "Vox" = 'icons/mob/clothing/species/vox/suit.dmi',
+ "Vulpkanin" = 'icons/mob/clothing/species/vulpkanin/suit.dmi'
+ )
+ hide_tail_by_species = list("Unathi, Tajaran, Vox, Vulpkanin")
+
+/obj/item/clothing/head/hooded/berserker
+ name = "berserker helmet"
+ desc = "Peering into the eyes of the helmet is enough to seal damnation."
+ icon_state = "hardsuit0-berserker"
+ item_color = "berserker"
+ light_color = BERSERK_COLOUR
+ light_power = 4
+ actions_types = list(/datum/action/item_action/berserk_mode)
+ armor = list(MELEE = 30, BULLET = 15, LASER = 10, ENERGY = 10, BOMB = 150, BIO = 0, RAD = 0, FIRE = INFINITY, ACID = INFINITY)
+ heat_protection = HEAD
+ max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
+ resistance_flags = FIRE_PROOF | ACID_PROOF
+ flags = BLOCKHAIR
+ flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
+ flags_inv = HIDEMASK | HIDEEARS | HIDEEYES | HIDEFACE
+ sprite_sheets = list(
+ "Grey" = 'icons/mob/clothing/species/grey/helmet.dmi',
+ "Tajaran" = 'icons/mob/clothing/species/tajaran/helmet.dmi',
+ "Unathi" = 'icons/mob/clothing/species/unathi/helmet.dmi',
+ "Vox" = 'icons/mob/clothing/species/vox/helmet.dmi',
+ "Vulpkanin" = 'icons/mob/clothing/species/vulpkanin/helmet.dmi'
+ )
+ /// Current charge of berserk, goes from 0 to 100
+ var/berserk_charge = 0
+ /// Status of berserk
+ var/berserk_active = FALSE
+
+
+/obj/item/clothing/head/hooded/berserker/examine()
+ . = ..()
+ . += "Berserk mode is [berserk_charge]% charged."
+
+/obj/item/clothing/head/hooded/berserker/process()
+ if(berserk_active)
+ berserk_charge = clamp(berserk_charge - CHARGE_DRAINED_PER_SECOND * 2, 0, MAX_BERSERK_CHARGE)
+ if(!berserk_charge)
+ if(ishuman(loc))
+ end_berserk(loc)
+
+/obj/item/clothing/head/hooded/berserker/dropped(mob/user)
+ . = ..()
+ end_berserk(user)
+
+/obj/item/clothing/head/hooded/berserker/Destroy()
+ end_berserk()
+ return ..()
+
+
+/obj/item/clothing/head/hooded/berserker/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
+ if(berserk_active)
+ return
+ if(istype(hitby, /obj/item/projectile))
+ var/obj/item/projectile/P = hitby
+ if(P.damage_type == STAMINA)
+ return //no disabler rage
+ var/berserk_value = damage * DAMAGE_TO_CHARGE_SCALE
+ if(attack_type == PROJECTILE_ATTACK)
+ berserk_value *= PROJECTILE_HIT_MULTIPLIER
+ berserk_charge = clamp(round(berserk_charge + berserk_value), 0, MAX_BERSERK_CHARGE)
+ if(berserk_charge >= MAX_BERSERK_CHARGE)
+ to_chat(owner, "Berserk mode is fully charged!")
+
+/// Starts berserk, giving the wearer 40% brute / burn resist, doubled attacking speed, NOGUNS trait, and colours them blood red.
+/obj/item/clothing/head/hooded/berserker/proc/berserk_mode(mob/living/carbon/human/user)
+ to_chat(user, "You enter berserk mode.")
+ playsound(user, 'sound/magic/staff_healing.ogg', 50)
+ set_light(3)
+ user.physiology.burn_mod *= BERSERK_DAMAGE_REDUCTION
+ user.physiology.brute_mod *= BERSERK_DAMAGE_REDUCTION
+ user.next_move_modifier *= BERSERK_ATTACK_SPEED_MODIFIER
+ user.add_atom_colour(BERSERK_COLOUR, TEMPORARY_COLOUR_PRIORITY)
+ ADD_TRAIT(user, TRAIT_CHUNKYFINGERS, BERSERK_TRAIT)
+ flags |= NODROP
+ suit.flags |= NODROP
+ berserk_active = TRUE
+ START_PROCESSING(SSobj, src)
+
+/// Ends berserk, reverting the changes from the proc [berserk_mode]
+/obj/item/clothing/head/hooded/berserker/proc/end_berserk(mob/living/carbon/human/user)
+ if(!berserk_active)
+ return
+ berserk_active = FALSE
+ if(QDELETED(user))
+ return
+ to_chat(user, "You exit berserk mode.")
+ playsound(user, 'sound/magic/summonitems_generic.ogg', 50)
+ set_light(0)
+ user.physiology.burn_mod /= BERSERK_DAMAGE_REDUCTION
+ user.physiology.brute_mod /= BERSERK_DAMAGE_REDUCTION
+ user.next_move_modifier /= BERSERK_ATTACK_SPEED_MODIFIER
+ user.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, BERSERK_COLOUR)
+ REMOVE_TRAIT(user, TRAIT_CHUNKYFINGERS, BERSERK_TRAIT)
+ flags &= ~NODROP
+ suit.flags &= ~NODROP
+ STOP_PROCESSING(SSobj, src)
+
+/datum/action/item_action/berserk_mode
+ name = "Berserk"
+ desc = "Increase your movement and melee speed while also increasing your melee armor for a short amount of time."
+
+/datum/action/item_action/berserk_mode/Trigger(trigger_flags)
+ if(istype(target, /obj/item/clothing/head/hooded/berserker))
+ var/obj/item/clothing/head/hooded/berserker/berzerk = target
+ if(berzerk.berserk_active)
+ to_chat(owner, "You are already berserk!")
+ return
+ if(berzerk.berserk_charge < 100)
+ to_chat(owner, "You don't have a full charge.")
+ return
+ berzerk.berserk_mode(owner)
+ return
+ return ..()
+
+#undef MAX_BERSERK_CHARGE
+#undef PROJECTILE_HIT_MULTIPLIER
+#undef DAMAGE_TO_CHARGE_SCALE
+#undef CHARGE_DRAINED_PER_SECOND
+#undef BERSERK_DAMAGE_REDUCTION
+#undef BERSERK_ATTACK_SPEED_MODIFIER
+#undef BERSERK_COLOUR
+
+
//Rod of Asclepius
#define RIGHT_HAND 0
#define LEFT_HAND 1
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index f77be18e688..fa800639d97 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -238,6 +238,9 @@ emp_act
if(w_uniform && w_uniform.hit_reaction(src, AM, attack_text, 0, damage, attack_type))
return TRUE
+ if(head && head.hit_reaction(src, AM, attack_text, 0, damage, attack_type))
+ return TRUE
+
return FALSE
#undef BLOCK_CHANCE_CALCULATION
diff --git a/icons/mob/clothing/species/tajaran/suit.dmi b/icons/mob/clothing/species/tajaran/suit.dmi
index 72b90047159..c4c1f4c6bda 100644
Binary files a/icons/mob/clothing/species/tajaran/suit.dmi and b/icons/mob/clothing/species/tajaran/suit.dmi differ
diff --git a/icons/mob/clothing/species/unathi/suit.dmi b/icons/mob/clothing/species/unathi/suit.dmi
index a0ecc8a5155..d50092797b5 100644
Binary files a/icons/mob/clothing/species/unathi/suit.dmi and b/icons/mob/clothing/species/unathi/suit.dmi differ
diff --git a/icons/mob/clothing/species/vox/suit.dmi b/icons/mob/clothing/species/vox/suit.dmi
index dc58332c558..5ad6e19e306 100644
Binary files a/icons/mob/clothing/species/vox/suit.dmi and b/icons/mob/clothing/species/vox/suit.dmi differ
diff --git a/icons/mob/clothing/species/vulpkanin/suit.dmi b/icons/mob/clothing/species/vulpkanin/suit.dmi
index 0287e9ed7fd..d3f64f16eb5 100644
Binary files a/icons/mob/clothing/species/vulpkanin/suit.dmi and b/icons/mob/clothing/species/vulpkanin/suit.dmi differ