diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm
index 4b7db053bd8..3c0f7623b63 100644
--- a/code/game/objects/items/weapons/melee/energy.dm
+++ b/code/game/objects/items/weapons/melee/energy.dm
@@ -5,9 +5,13 @@
var/active_w_class
sharp = 0
edge = 0
- armor_penetration = 50
+ armor_penetration = 10
flags = NOBLOODY
can_embed = 0//No embedding pls
+ var/base_reflectchance = 40
+ var/base_block_chance = 25
+ var/shield_power = 100
+ var/can_block_bullets = 0
var/datum/effect_system/sparks/spark_system
/obj/item/weapon/melee/energy/New()
@@ -56,6 +60,66 @@
add_fingerprint(user)
return
+/obj/item/weapon/melee/energy/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
+ if(active && default_parry_check(user, attacker, damage_source) && prob(50))
+ user.visible_message("\The [user] parries [attack_text] with \the [src]!")
+
+ spark_system.queue()
+ playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
+ return 1
+ else
+
+ if(!active)
+ return 0 //turn it on first!
+
+ if(user.incapacitated())
+ return 0
+
+ //block as long as they are not directly behind us
+ var/bad_arc = reverse_direction(user.dir) //arc of directions from which we cannot block
+ if(check_shield_arc(user, bad_arc, damage_source, attacker))
+
+ if(prob(base_block_chance))
+ spark_system.queue()
+ playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
+ shield_power -= round(damage/4)
+
+ if(shield_power <= 0)
+ visible_message("\The [user]'s [src.name] overloads!")
+ deactivate()
+ shield_power = initial(shield_power)
+ return 0
+
+ if(istype(damage_source, /obj/item/projectile/energy) || istype(damage_source, /obj/item/projectile/beam))
+ var/obj/item/projectile/P = damage_source
+
+ var/reflectchance = base_reflectchance - round(damage/3)
+ if(!(def_zone in list("chest", "groin","head")))
+ 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)
+
+ return PROJECTILE_CONTINUE // complete projectile permutation
+ else
+ user.visible_message("\The [user] blocks [attack_text] with \the [src]!")
+ return 1
+
+ else if(istype(damage_source, /obj/item/projectile/bullet) && can_block_bullets)
+ var/reflectchance = (base_reflectchance) - round(damage/3)
+ if(!(def_zone in list("chest", "groin","head")))
+ reflectchance /= 2
+ if(prob(reflectchance))
+ user.visible_message("\The [user] blocks [attack_text] with \the [src]!")
+ return 1
+
/obj/item/weapon/melee/energy/glaive
name = "energy glaive"
desc = "An energized glaive."
@@ -74,6 +138,11 @@
sharp = 1
edge = 1
slot_flags = SLOT_BACK
+ base_reflectchance = 0
+ base_block_chance = 0 //cannot be used to block guns
+ shield_power = 0
+ can_block_bullets = 0
+ armor_penetration = 20
/obj/item/weapon/melee/energy/glaive/activate(mob/living/user)
..()
@@ -108,6 +177,11 @@
attack_verb = list("attacked", "chopped", "cleaved", "torn", "cut")
sharp = 1
edge = 1
+ base_reflectchance = 0
+ base_block_chance = 0 //cannot be used to block guns
+ shield_power = 0
+ can_block_bullets = 0
+ armor_penetration = 35
/obj/item/weapon/melee/energy/axe/activate(mob/living/user)
..()
@@ -140,6 +214,7 @@
sharp = 1
edge = 1
var/blade_color
+ shield_power = 75
/obj/item/weapon/melee/energy/sword/dropped(var/mob/user)
..()
@@ -175,19 +250,12 @@
attack_verb = list()
icon_state = initial(icon_state)
-/obj/item/weapon/melee/energy/sword/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
- if(active && default_parry_check(user, attacker, damage_source) && prob(50))
- user.visible_message("\The [user] parries [attack_text] with \the [src]!")
-
- spark_system.queue()
- playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
- return 1
- return 0
-
/obj/item/weapon/melee/energy/sword/pirate
name = "energy cutlass"
desc = "Arrrr matey."
icon_state = "cutlass0"
+ base_reflectchance = 60
+ base_block_chance = 60
/obj/item/weapon/melee/energy/sword/pirate/activate(mob/living/user)
..()
@@ -196,13 +264,12 @@
/*
*Energy Blade
*/
-
-//Can't be activated or deactivated, so no reason to be a subtype of energy
/obj/item/weapon/melee/energy/blade
name = "energy blade"
desc = "A concentrated beam of energy in the shape of a blade. Very stylish... and lethal."
icon_state = "blade"
- force = 40 //Normal attacks deal very high damage - about the same as wielded fire axe
+ force = 40
+ active_force = 40 //Normal attacks deal very high damage - about the same as wielded fire axe
armor_penetration = 100
sharp = 1
edge = 1
@@ -214,6 +281,12 @@
flags = NOBLOODY
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
var/mob/living/creator
+ base_reflectchance = 140
+ base_block_chance = 75
+ shield_power = 150
+ can_block_bullets = 1
+ active = 1
+ armor_penetration = 20
/obj/item/weapon/melee/energy/blade/New()
processing_objects |= src
@@ -223,10 +296,14 @@
processing_objects -= src
..()
-/obj/item/weapon/melee/energy/blade/attack_self(mob/user as mob)
+/obj/item/weapon/melee/energy/blade/deactivate(mob/living/user)
+ if(!active)
+ return
+ playsound(user, 'sound/weapons/saberoff.ogg', 50, 1)
user.drop_from_inventory(src)
spawn(1) if(src) qdel(src)
+
/obj/item/weapon/melee/energy/blade/dropped()
spawn(1) if(src) qdel(src)
diff --git a/code/game/objects/items/weapons/shields.dm b/code/game/objects/items/weapons/shields.dm
index d57d312ab15..45483b8c8f0 100644
--- a/code/game/objects/items/weapons/shields.dm
+++ b/code/game/objects/items/weapons/shields.dm
@@ -103,17 +103,62 @@
w_class = 2
origin_tech = list(TECH_MATERIAL = 4, TECH_MAGNET = 3, TECH_ILLEGAL = 4)
attack_verb = list("shoved", "bashed")
+ var/shield_power = 150
var/active = 0
-/obj/item/weapon/shield/energy/handle_shield(mob/user)
+/obj/item/weapon/shield/energy/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
if(!active)
return 0 //turn it on first!
- . = ..()
+ if(user.incapacitated())
+ return 0
+
if(.)
spark(user.loc, 5)
playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
+ //block as long as they are not directly behind us
+ var/bad_arc = reverse_direction(user.dir) //arc of directions from which we cannot block
+ if(check_shield_arc(user, bad_arc, damage_source, attacker))
+
+ if(prob(get_block_chance(user, damage, damage_source, attacker)))
+ spark(user.loc, 5)
+ playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
+ shield_power -= round(damage/4)
+
+ if(shield_power <= 0)
+ visible_message("\The [user]'s [src.name] overloads!")
+ active = 0
+ force = 3
+ update_icon()
+ w_class = 1
+ playsound(user, 'sound/weapons/saberoff.ogg', 50, 1)
+ shield_power = initial(shield_power)
+ return 0
+
+ if(istype(damage_source, /obj/item/projectile/energy) || istype(damage_source, /obj/item/projectile/beam))
+ var/obj/item/projectile/P = damage_source
+
+ var/reflectchance = 80 - round(damage/3)
+ 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)
+
+ return PROJECTILE_CONTINUE // complete projectile permutation
+ else
+ user.visible_message("\The [user] blocks [attack_text] with \the [src]!")
+ return 1
+ else
+ user.visible_message("\The [user] blocks [attack_text] with \the [src]!")
+ return 1
+
/obj/item/weapon/shield/energy/get_block_chance(mob/user, var/damage, atom/damage_source = null, mob/attacker = null)
if(istype(damage_source, /obj/item/projectile))
var/obj/item/projectile/P = damage_source
diff --git a/html/changelogs/LordFowl - 11081998.yml b/html/changelogs/LordFowl - 11081998.yml
new file mode 100644
index 00000000000..03d6d3be098
--- /dev/null
+++ b/html/changelogs/LordFowl - 11081998.yml
@@ -0,0 +1,36 @@
+################################
+# Example Changelog File
+#
+# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
+#
+# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
+# When it is, any changes listed below will disappear.
+#
+# Valid Prefixes:
+# bugfix
+# wip (For works in progress)
+# tweak
+# soundadd
+# sounddel
+# rscadd (general adding of nice things)
+# rscdel (general deleting of nice things)
+# imageadd
+# imagedel
+# maptweak
+# spellcheck (typo fixes)
+# experiment
+#################################
+
+# Your name.
+author: LordFowl
+
+# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
+delete-after: True
+
+# Any changes you've made. See valid prefix list above.
+# INDENT WITH TWO SPACES. NOT TABS. SPACES.
+# SCREW THIS UP AND IT WON'T WORK.
+# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
+# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
+changes:
+ - rscadd: "Energy swords and shields can now reflect energy weapon projectiles. The ninja sword additionally can deflect bullets."