diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index a1bb4122a8..42199174e7 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -290,7 +290,7 @@
#define COMSIG_LIVING_ACTIVE_BLOCK_START "active_block_start" //from base of mob/living/keybind_start_active_blocking(): (obj/item/blocking_item, list/backup_items)
#define COMPONENT_PREVENT_BLOCK_START 1
-#define COMSIG_LIVING_ACTIVE_PARRY_START "active_parry_start" //from base of mob/living/initiate_parry_sequence(): (parrying_method, datum/parrying_item_mob_or_art, list/backup_items)
+#define COMSIG_LIVING_ACTIVE_PARRY_START "active_parry_start" //from base of mob/living/initiate_parry_sequence(): (parrying_method, datum/parrying_item_mob_or_art, list/backup_items, list/override)
#define COMPONENT_PREVENT_PARRY_START 1
//ALL OF THESE DO NOT TAKE INTO ACCOUNT WHETHER AMOUNT IS 0 OR LOWER AND ARE SENT REGARDLESS!
diff --git a/code/modules/clothing/gloves/miscellaneous.dm b/code/modules/clothing/gloves/miscellaneous.dm
index c069649848..a558abbfe8 100644
--- a/code/modules/clothing/gloves/miscellaneous.dm
+++ b/code/modules/clothing/gloves/miscellaneous.dm
@@ -161,6 +161,68 @@
return NO_AUTO_CLICKDELAY_HANDLING | ATTACK_IGNORE_ACTION
+/obj/item/clothing/gloves/fingerless/ablative
+ name = "ablative armwraps"
+ desc = "Armwraps made out of a highly durable, reflective metal. Has the side effect of absorbing shocks."
+ siemens_coefficient = 0
+ icon_state = "ablative_armwraps"
+ item_state = "ablative_armwraps"
+ block_parry_data = /datum/block_parry_data/ablative_armwraps
+ var/wornonce = FALSE
+
+/obj/item/clothing/gloves/fingerless/ablative/proc/get_component_parry_data(datum/source, parrying_method, datum/parrying_item_mob_or_art, list/backup_items, list/override)
+ if(parrying_method && !(parrying_method == UNARMED_PARRY))
+ return
+ override[src] = ITEM_PARRY
+
+/obj/item/clothing/gloves/fingerless/ablative/equipped(mob/user, slot)
+ . = ..()
+ if(current_equipped_slot == SLOT_GLOVES)
+ RegisterSignal(user, COMSIG_LIVING_ACTIVE_PARRY_START, .proc/get_component_parry_data)
+ wornonce = TRUE
+
+/obj/item/clothing/gloves/fingerless/ablative/dropped(mob/user)
+ . = ..()
+ if(wornonce)
+ UnregisterSignal(user, COMSIG_LIVING_ACTIVE_PARRY_START)
+ wornonce = FALSE
+
+/obj/item/clothing/gloves/fingerless/ablative/can_active_parry(mob/user)
+ var/mob/living/carbon/human/H = user
+ if(!istype(H))
+ return FALSE
+ return src == H.gloves
+
+/obj/item/clothing/gloves/fingerless/ablative/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
+ . = ..()
+ if(parry_efficiency > 0)
+ owner.visible_message("[owner] deflects \the [object] with their armwraps!")
+
+/datum/block_parry_data/ablative_armwraps
+ parry_stamina_cost = 4
+ parry_attack_types = ATTACK_TYPE_UNARMED | ATTACK_TYPE_PROJECTILE | ATTACK_TYPE_TACKLE | ATTACK_TYPE_THROWN | ATTACK_TYPE_MELEE
+ parry_flags = NONE
+
+ parry_time_windup = 0
+ parry_time_spindown = 0
+ parry_time_active = 7.5
+
+ parry_time_perfect = 1
+ parry_time_perfect_leeway = 7.5
+ parry_imperfect_falloff_percent = 20
+ parry_efficiency_perfect = 100
+ parry_time_perfect_leeway_override = list(
+ TEXT_ATTACK_TYPE_MELEE = 1
+ )
+
+ parry_efficiency_considered_successful = 0.01
+ parry_efficiency_to_counterattack = INFINITY // no auto counter
+ parry_max_attacks = INFINITY
+ parry_failed_cooldown_duration = 2.25 SECONDS
+ parry_failed_stagger_duration = 2.25 SECONDS
+ parry_cooldown = 0
+ parry_failed_clickcd_duration = 0
+
/obj/item/clothing/gloves/botanic_leather
name = "botanist's leather gloves"
desc = "These leather gloves protect against thorns, barbs, prickles, spikes and other harmful objects of floral origin. They're also quite warm."
diff --git a/code/modules/mob/living/living_active_parry.dm b/code/modules/mob/living/living_active_parry.dm
index 8d1ee38de6..c0423286c1 100644
--- a/code/modules/mob/living/living_active_parry.dm
+++ b/code/modules/mob/living/living_active_parry.dm
@@ -2,7 +2,7 @@
/**
* Determines if we can actively parry.
*/
-/obj/item/proc/can_active_parry()
+/obj/item/proc/can_active_parry(mob/user)
return block_parry_data && (item_flags & ITEM_CAN_PARRY)
/**
@@ -29,7 +29,7 @@
var/datum/block_parry_data/data
var/datum/tool
var/method
- if(using_item?.can_active_parry())
+ if(using_item?.can_active_parry(src))
data = using_item.block_parry_data
method = ITEM_PARRY
tool = using_item
@@ -50,9 +50,20 @@
using_item = backup
method = ITEM_PARRY
var/list/other_items = list()
- if(SEND_SIGNAL(src, COMSIG_LIVING_ACTIVE_PARRY_START, method, tool, other_items) & COMPONENT_PREVENT_PARRY_START)
+ var/list/override = list()
+ if(SEND_SIGNAL(src, COMSIG_LIVING_ACTIVE_PARRY_START, method, tool, other_items, override) & COMPONENT_PREVENT_PARRY_START)
to_chat(src, "Something is preventing you from parrying!")
return
+ if(length(override))
+ var/datum/thing = override[1]
+ var/_method = override[thing]
+ if(_method == ITEM_PARRY)
+ using_item = thing
+ method = ITEM_PARRY
+ data = using_item.block_parry_data
+ else if(_method == UNARMED_PARRY)
+ method = UNARMED_PARRY
+ data = thing
if(!using_item && !method && length(other_items))
using_item = other_items[1]
method = ITEM_PARRY
@@ -94,7 +105,7 @@
*/
/mob/living/proc/find_backup_parry_item()
for(var/obj/item/I in held_items - get_active_held_item())
- if(I.can_active_parry())
+ if(I.can_active_parry(src))
return I
/**
@@ -231,7 +242,7 @@
var/efficiency = data.get_parry_efficiency(attack_type, get_parry_time())
switch(parrying)
if(ITEM_PARRY)
- if(!active_parry_item.can_active_parry())
+ if(!active_parry_item.can_active_parry(src))
return BLOCK_NONE
. = active_parry_item.on_active_parry(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, get_parry_time())
if(UNARMED_PARRY)
@@ -243,6 +254,18 @@
if(efficiency <= 0) // Do not allow automatically handled/standardized parries that increase damage for now.
return
. |= BLOCK_SHOULD_PARTIAL_MITIGATE
+ if(efficiency >= data.parry_efficiency_perfect)
+ . |= data.perfect_parry_block_return_flags
+ if(data.perfect_parry_block_return_list)
+ return_list |= data.perfect_parry_block_return_list
+ else if(efficiency >= data.parry_efficiency_considered_successful)
+ . |= data.imperfect_parry_block_return_flags
+ if(data.imperfect_parry_block_return_list)
+ return_list |= data.imperfect_parry_block_return_list
+ else
+ . |= data.failed_parry_block_return_flags
+ if(data.failed_parry_block_return_list)
+ return_list |= data.failed_parry_block_return_list
if(isnull(return_list[BLOCK_RETURN_MITIGATION_PERCENT])) // if one of the on_active_parry procs overrode. We don't have to worry about interference since parries are the first thing checked in the [do_run_block()] sequence.
return_list[BLOCK_RETURN_MITIGATION_PERCENT] = clamp(efficiency, 0, 100) // do not allow > 100% or < 0% for now.
if((return_list[BLOCK_RETURN_MITIGATION_PERCENT] >= 100) || (damage <= 0))
diff --git a/code/modules/mob/living/living_blocking_parrying.dm b/code/modules/mob/living/living_blocking_parrying.dm
index e290956873..9e974177e5 100644
--- a/code/modules/mob/living/living_blocking_parrying.dm
+++ b/code/modules/mob/living/living_blocking_parrying.dm
@@ -157,6 +157,16 @@ GLOBAL_LIST_EMPTY(block_parry_data)
/// Parry cooldown post-parry if failed. This is ADDED to parry_cooldown!!!
var/parry_failed_cooldown_duration = 0 SECONDS
+ // Advanced
+ /// Flags added to return value
+ var/perfect_parry_block_return_flags = NONE
+ var/imperfect_parry_block_return_flags = NONE
+ var/failed_parry_block_return_flags = NONE
+ /// List appended to block return
+ var/perfect_parry_block_return_list
+ var/imperfect_parry_block_return_list
+ var/failed_parry_block_return_list
+
/**
* Quirky proc to get average of flags in list that are in attack_type because why is attack_type a flag.
*/
diff --git a/code/modules/uplink/uplink_items/uplink_clothing.dm b/code/modules/uplink/uplink_items/uplink_clothing.dm
index 6163e5722a..de15b16b68 100644
--- a/code/modules/uplink/uplink_items/uplink_clothing.dm
+++ b/code/modules/uplink/uplink_items/uplink_clothing.dm
@@ -104,3 +104,10 @@
desc = "An eyepatch that connects itself to your eye socket, enhancing your shooting to an impossible degree, allowing your bullets to ricochet far more often than usual."
item = /obj/item/clothing/glasses/eyepatch/syndicate
cost = 8
+
+/datum/uplink_item/device_tools/ablative_armwraps
+ name = "Ablative Armwraps"
+ desc = "A pair of highly reinforced armwraps allowing the user to parry almost anything. Fully reflects projectiles, no downsides to failing, but is very hard to parry melee with."
+ cost = 6
+ item = /obj/item/clothing/gloves/fingerless/ablative
+ exclude_modes = list(/datum/game_mode/nuclear)
diff --git a/icons/mob/clothing/hands.dmi b/icons/mob/clothing/hands.dmi
index b95c377e12..406b0fe62a 100644
Binary files a/icons/mob/clothing/hands.dmi and b/icons/mob/clothing/hands.dmi differ
diff --git a/icons/obj/clothing/gloves.dmi b/icons/obj/clothing/gloves.dmi
index 0feb6a75db..629b989520 100644
Binary files a/icons/obj/clothing/gloves.dmi and b/icons/obj/clothing/gloves.dmi differ