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