diff --git a/code/game/gamemodes/changeling/powers/armblade.dm b/code/game/gamemodes/changeling/powers/armblade.dm
index ed27a49ba0..947f06cee4 100644
--- a/code/game/gamemodes/changeling/powers/armblade.dm
+++ b/code/game/gamemodes/changeling/powers/armblade.dm
@@ -32,7 +32,7 @@
genomecost = 1
verbpath = /mob/proc/changeling_claw
-//Grows a scary, and powerful arm blade.
+//Grows a scary, and powerful claw.
/mob/proc/changeling_claw()
set category = "Changeling"
set name = "Claw (15)"
@@ -62,6 +62,9 @@
var/weapType = "weapon"
var/weapLocation = "arm"
+ defend_chance = 40 // The base chance for the weapon to parry.
+ projectile_parry_chance = 15 // The base chance for a projectile to be deflected.
+
/obj/item/weapon/melee/changeling/New(location)
..()
START_PROCESSING(SSobj, src)
@@ -107,6 +110,28 @@
if(src)
qdel(src)
+/obj/item/weapon/melee/changeling/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
+ if(default_parry_check(user, attacker, damage_source) && prob(defend_chance))
+ user.visible_message("\The [user] parries [attack_text] with \the [src]!")
+ playsound(user.loc, 'sound/weapons/slash.ogg', 50, 1)
+ return 1
+ if(unique_parry_check(user, attacker, damage_source) && prob(projectile_parry_chance))
+ user.visible_message("\The [user] deflects [attack_text] with \the [src]!")
+ playsound(user.loc, 'sound/weapons/slash.ogg', 50, 1)
+ return 1
+
+ return 0
+
+/obj/item/weapon/melee/changeling/unique_parry_check(mob/user, mob/attacker, atom/damage_source)
+ if(user.incapacitated() || !istype(damage_source, /obj/item/projectile))
+ return 0
+
+ var/bad_arc = reverse_direction(user.dir)
+ if(!check_shield_arc(user, bad_arc, damage_source, attacker))
+ return 0
+
+ return 1
+
/obj/item/weapon/melee/changeling/arm_blade
name = "arm blade"
desc = "A grotesque blade made out of bone and flesh that cleaves through people as a hot knife through butter."
@@ -117,11 +142,15 @@
edge = 1
pry = 1
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
+ defend_chance = 60
+ projectile_parry_chance = 25
/obj/item/weapon/melee/changeling/arm_blade/greater
name = "arm greatblade"
desc = "A grotesque blade made out of bone and flesh that cleaves through people and armor as a hot knife through butter."
armor_penetration = 30
+ defend_chance = 70
+ projectile_parry_chance = 35
/obj/item/weapon/melee/changeling/claw
name = "hand claw"
@@ -131,9 +160,13 @@
sharp = 1
edge = 1
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
+ defend_chance = 50
+ projectile_parry_chance = 15
/obj/item/weapon/melee/changeling/claw/greater
name = "hand greatclaw"
force = 20
armor_penetration = 20
- pry = 1
\ No newline at end of file
+ pry = 1
+ defend_chance = 60
+ projectile_parry_chance = 25
diff --git a/code/game/objects/items/weapons/material/swords.dm b/code/game/objects/items/weapons/material/swords.dm
index 9efe911360..46551e588a 100644
--- a/code/game/objects/items/weapons/material/swords.dm
+++ b/code/game/objects/items/weapons/material/swords.dm
@@ -11,8 +11,7 @@
hitsound = 'sound/weapons/bladeslice.ogg'
/obj/item/weapon/material/sword/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
-
- if(default_parry_check(user, attacker, damage_source) && prob(50))
+ if(unique_parry_check(user, attacker, damage_source) && prob(50))
user.visible_message("\The [user] parries [attack_text] with \the [src]!")
playsound(user.loc, 'sound/weapons/punchmiss.ogg', 50, 1)
return 1
diff --git a/code/game/objects/items/weapons/melee/deflect.dm b/code/game/objects/items/weapons/melee/deflect.dm
new file mode 100644
index 0000000000..293d2b9e29
--- /dev/null
+++ b/code/game/objects/items/weapons/melee/deflect.dm
@@ -0,0 +1,31 @@
+/*
+ * The home of basic deflect / defense code.
+ */
+
+/obj/item/weapon/melee
+ var/defend_chance = 5 // The base chance for the weapon to parry.
+ var/projectile_parry_chance = 0 // The base chance for a projectile to be deflected.
+
+/obj/item/weapon/melee/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
+ if(.)
+ return .
+ if(default_parry_check(user, attacker, damage_source) && prob(defend_chance))
+ user.visible_message("\The [user] parries [attack_text] with \the [src]!")
+ return 1
+ if(unique_parry_check(user, attacker, damage_source) && prob(projectile_parry_chance))
+ user.visible_message("\The [user] deflects [attack_text] with \the [src]!")
+ return 1
+
+ return 0
+
+/obj/item/weapon/melee/unique_parry_check(mob/user, mob/attacker, atom/damage_source)
+ if(.)
+ return .
+ if(user.incapacitated() || !istype(damage_source, /obj/item/projectile))
+ return 0
+
+ var/bad_arc = reverse_direction(user.dir)
+ if(!check_shield_arc(user, bad_arc, damage_source, attacker))
+ return 0
+
+ return 1
diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm
index 72fe26da36..f825577d6f 100644
--- a/code/game/objects/items/weapons/melee/energy.dm
+++ b/code/game/objects/items/weapons/melee/energy.dm
@@ -127,6 +127,8 @@
var/random_color = TRUE
var/active_state = "sword"
+ projectile_parry_chance = 65
+
/obj/item/weapon/melee/energy/sword/dropped(var/mob/user)
..()
if(!istype(loc,/mob))
@@ -173,7 +175,7 @@
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))
+ if(active && default_parry_check(user, attacker, damage_source) && prob(60))
user.visible_message("\The [user] parries [attack_text] with \the [src]!")
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
@@ -181,8 +183,27 @@
spark_system.start()
playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
return 1
+ if(active && unique_parry_check(user, attacker, damage_source) && prob(projectile_parry_chance))
+ user.visible_message("\The [user] deflects [attack_text] with \the [src]!")
+
+ var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
+ spark_system.set_up(5, 0, user.loc)
+ spark_system.start()
+ playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
+ return 1
+
return 0
+/obj/item/weapon/melee/energy/sword/unique_parry_check(mob/user, mob/attacker, atom/damage_source)
+ if(user.incapacitated() || !istype(damage_source, /obj/item/projectile/))
+ return 0
+
+ var/bad_arc = reverse_direction(user.dir)
+ if(!check_shield_arc(user, bad_arc, damage_source, attacker))
+ return 0
+
+ return 1
+
/obj/item/weapon/melee/energy/sword/pirate
name = "energy cutlass"
desc = "Arrrr matey."
@@ -215,6 +236,7 @@
lpower = 2
lcolor = "#0000FF"
active_state = "ionic_rapier"
+ projectile_parry_chance = 30 // It's not specifically designed for cutting and slashing, but it can still, maybe, save your life.
/obj/item/weapon/melee/energy/sword/ionic_rapier/afterattack(var/atom/movable/AM, var/mob/living/user, var/proximity)
if(istype(AM, /obj) && proximity && active)
@@ -250,6 +272,7 @@
origin_tech = list(TECH_COMBAT = 5, TECH_MAGNET = 3, TECH_ILLEGAL = 4)
active_force = 25
armor_penetration = 25
+ projectile_parry_chance = 40
var/hitcost = 75
var/obj/item/weapon/cell/bcell = null
@@ -336,6 +359,7 @@
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
var/mob/living/creator
var/datum/effect/effect/system/spark_spread/spark_system
+ projectile_parry_chance = 60
lcolor = "#00FF00"
/obj/item/weapon/melee/energy/blade/New()
@@ -373,6 +397,37 @@
host.drop_from_inventory(src)
spawn(1) if(src) qdel(src)
+/obj/item/weapon/melee/energy/blade/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
+ if(default_parry_check(user, attacker, damage_source) && prob(60))
+ user.visible_message("\The [user] parries [attack_text] with \the [src]!")
+
+ var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
+ spark_system.set_up(5, 0, user.loc)
+ spark_system.start()
+ playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
+ return 1
+ if(unique_parry_check(user, attacker, damage_source) && prob(projectile_parry_chance))
+ user.visible_message("\The [user] deflects [attack_text] with \the [src]!")
+
+ var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
+ spark_system.set_up(5, 0, user.loc)
+ spark_system.start()
+ playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
+ return 1
+
+ return 0
+
+/obj/item/weapon/melee/energy/blade/unique_parry_check(mob/user, mob/attacker, atom/damage_source)
+
+ if(user.incapacitated() || !istype(damage_source, /obj/item/projectile/))
+ return 0
+
+ var/bad_arc = reverse_direction(user.dir)
+ if(!check_shield_arc(user, bad_arc, damage_source, attacker))
+ return 0
+
+ return 1
+
/*
*Energy Spear
*/
diff --git a/code/game/objects/items/weapons/shields.dm b/code/game/objects/items/weapons/shields.dm
index a1a2756eca..5ea586f43d 100644
--- a/code/game/objects/items/weapons/shields.dm
+++ b/code/game/objects/items/weapons/shields.dm
@@ -29,6 +29,9 @@
return 1
+/obj/item/proc/unique_parry_check(mob/user, mob/attacker, atom/damage_source) // An overrideable version of the above proc.
+ return default_parry_check(user, attacker, damage_source)
+
/obj/item/weapon/shield
name = "shield"
var/base_block_chance = 50
diff --git a/html/changelogs/Mechoid - Melee2RevengeoftheDeflect.yml b/html/changelogs/Mechoid - Melee2RevengeoftheDeflect.yml
new file mode 100644
index 0000000000..6841c34912
--- /dev/null
+++ b/html/changelogs/Mechoid - Melee2RevengeoftheDeflect.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: Mechoid
+
+# 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:
+ - tweak: "Changeling arm-weapons and E-swords can now block projectiles (again)."
diff --git a/vorestation.dme b/vorestation.dme
index d68700dd85..6ad16ba61d 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -1141,6 +1141,7 @@
#include "code\game\objects\items\weapons\material\thrown.dm"
#include "code\game\objects\items\weapons\material\twohanded.dm"
#include "code\game\objects\items\weapons\material\whetstone.dm"
+#include "code\game\objects\items\weapons\melee\deflect.dm"
#include "code\game\objects\items\weapons\melee\energy.dm"
#include "code\game\objects\items\weapons\melee\energy_vr.dm"
#include "code\game\objects\items\weapons\melee\misc.dm"