diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm
index 12a1b57364..aefa5d3cc8 100644
--- a/code/game/objects/items/shields.dm
+++ b/code/game/objects/items/shields.dm
@@ -24,12 +24,16 @@
var/shieldbash_push_distance = 1
/datum/block_parry_data/shield
- block_stamina_efficiency = 1.5
- block_stamina_cost_per_second = 3
- block_start_delay = 3
- block_damage_absorption = 0
+ block_damage_multiplier = 0.25
+ block_stamina_efficiency = 2.5
+ block_stamina_cost_per_second = 3.5
+ block_slowdown = 0
+ block_lock_attacking = FALSE
+ block_lock_sprinting = TRUE
+ block_start_delay = 1.5
+ block_damage_absorption = 5
block_resting_stamina_penalty_multiplier = 2
- block_projectile_mitigation = 50
+ block_projectile_mitigation = 75
/obj/item/shield/examine(mob/user)
. = ..()
diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm
index 698adfd9d7..4437eefbf8 100644
--- a/code/game/objects/items/twohanded.dm
+++ b/code/game/objects/items/twohanded.dm
@@ -310,12 +310,14 @@
/datum/block_parry_data/dual_esword
block_damage_absorption = 2
- block_damage_multiplier = 0.3
+ block_damage_multiplier = 0.15
+ block_damage_multiplier_override = list(
+ ATTACK_TYPE_MELEE = 0.25
+ )
block_start_delay = 0 // instantaneous block
- block_stamina_cost_per_second = 2
+ block_stamina_cost_per_second = 2.5
block_stamina_efficiency = 3
- // slowdown
- block_slowdown = 1
+ block_lock_sprinting = TRUE
// no attacking while blocking
block_lock_attacking = TRUE
block_projectile_mitigation = 75
diff --git a/code/modules/keybindings/keybind/mob.dm b/code/modules/keybindings/keybind/mob.dm
index ca539e3ab7..2ce4dc35a0 100644
--- a/code/modules/keybindings/keybind/mob.dm
+++ b/code/modules/keybindings/keybind/mob.dm
@@ -17,6 +17,7 @@
return TRUE
/datum/keybinding/mob/cycle_intent_right
+ hotkey_keys = list("Unbound")
name = "cycle_intent_right"
full_name = "Cycle Action Intent Right"
description = ""
@@ -27,6 +28,7 @@
return TRUE
/datum/keybinding/mob/cycle_intent_left
+ hotkey_keys = list("Unbound")
name = "cycle_intent_left"
full_name = "Cycle Action Intent Left"
description = ""
diff --git a/code/modules/mob/living/living_active_block.dm b/code/modules/mob/living/living_active_block.dm
index 64f9a8f6e7..4560b33bdb 100644
--- a/code/modules/mob/living/living_active_block.dm
+++ b/code/modules/mob/living/living_active_block.dm
@@ -7,6 +7,7 @@
active_block_effect_end()
active_block_item = null
REMOVE_TRAIT(src, TRAIT_MOBILITY_NOUSE, ACTIVE_BLOCK_TRAIT)
+ REMOVE_TRAIT(src, TRAIT_SPRINT_LOCKED, ACTIVE_BLOCK_TRAIT)
remove_movespeed_modifier(/datum/movespeed_modifier/active_block)
var/datum/block_parry_data/data = I.get_block_parry_data()
if(timeToNextMove() < data.block_end_click_cd_add)
@@ -25,6 +26,8 @@
active_block_item = I
if(data.block_lock_attacking)
ADD_TRAIT(src, TRAIT_MOBILITY_NOUSE, ACTIVE_BLOCK_TRAIT) //probably should be something else at some point
+ if(data.block_lock_sprinting)
+ ADD_TRAIT(src, TRAIT_SPRINT_LOCKED, ACTIVE_BLOCK_TRAIT)
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/active_block, multiplicative_slowdown = data.block_slowdown)
active_block_effect_start()
return TRUE
@@ -75,10 +78,16 @@
/mob/living/proc/keybind_start_active_blocking()
if(combat_flags & (COMBAT_FLAG_ACTIVE_BLOCK_STARTING | COMBAT_FLAG_ACTIVE_BLOCKING))
return FALSE
+ if(!(combat_flags & COMBAT_FLAG_BLOCK_CAPABLE))
+ to_chat(src, "You're not something that can actively block.")
+ return FALSE
+ // QOL: Attempt to toggle on combat mode if it isn't already
+ SEND_SIGNAL(src, COMSIG_ENABLE_COMBAT_MODE)
if(!SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE))
to_chat(src, "You must be in combat mode to actively block!")
return FALSE
- var/obj/item/I = get_active_held_item()
+ // QOL: Instead of trying to just block with held item, grab first available item.
+ var/obj/item/I = find_active_block_item()
if(!I)
to_chat(src, "You can't block with your bare hands!")
return
@@ -89,7 +98,7 @@
var/delay = data.block_start_delay
combat_flags |= COMBAT_FLAG_ACTIVE_BLOCK_STARTING
animate(src, pixel_x = get_standard_pixel_x_offset(), pixel_y = get_standard_pixel_y_offset(), time = delay, FALSE, SINE_EASING | EASE_IN)
- if(!do_after_advanced(src, delay, src, DO_AFTER_REQUIRES_USER_ON_TURF|DO_AFTER_NO_COEFFICIENT|DO_AFTER_DISALLOW_ACTIVE_ITEM_CHANGE, CALLBACK(src, .proc/continue_starting_active_block), MOBILITY_USE, null, null, I))
+ if(!do_after_advanced(src, delay, src, DO_AFTER_REQUIRES_USER_ON_TURF|DO_AFTER_NO_COEFFICIENT, CALLBACK(src, .proc/continue_starting_active_block), MOBILITY_USE, null, null, I))
to_chat(src, "You fail to raise [I].")
combat_flags &= ~(COMBAT_FLAG_ACTIVE_BLOCK_STARTING)
animate(src, pixel_x = get_standard_pixel_x_offset(), pixel_y = get_standard_pixel_y_offset(), time = 2.5, FALSE, SINE_EASING | EASE_IN, ANIMATION_END_NOW)
@@ -97,6 +106,18 @@
combat_flags &= ~(COMBAT_FLAG_ACTIVE_BLOCK_STARTING)
start_active_blocking(I)
+/**
+ * Gets the first item we can that can block, but if that fails, default to active held item.COMSIG_ENABLE_COMBAT_MODE
+ */
+/mob/living/proc/find_active_block_item()
+ var/obj/item/held = get_active_held_item()
+ if(!held.can_active_block())
+ for(var/i in held_items - held)
+ var/obj/item/I = i
+ if(I.can_active_block())
+ return I
+ return held
+
/**
* Proc called by keybindings to stop active blocking.
*/
@@ -110,7 +131,7 @@
* Returns if we can actively block.
*/
/obj/item/proc/can_active_block()
- return item_flags & ITEM_CAN_BLOCK
+ return block_parry_data && (item_flags & ITEM_CAN_BLOCK)
/**
* Calculates FINAL ATTACK DAMAGE after mitigation
diff --git a/code/modules/mob/living/living_active_parry.dm b/code/modules/mob/living/living_active_parry.dm
index f281399960..6ae83c5647 100644
--- a/code/modules/mob/living/living_active_parry.dm
+++ b/code/modules/mob/living/living_active_parry.dm
@@ -3,7 +3,7 @@
* Determines if we can actively parry.
*/
/obj/item/proc/can_active_parry()
- return item_flags & ITEM_CAN_PARRY
+ return block_parry_data && (item_flags & ITEM_CAN_PARRY)
/**
* Called from keybindings.
@@ -20,6 +20,8 @@
if(!(combat_flags & COMBAT_FLAG_PARRY_CAPABLE))
to_chat(src, "You are not something that can parry attacks.")
return
+ //QOL: Try to enable combat mode if it isn't already
+ SEND_SIGNAL(src, COMSIG_ENABLE_COMBAT_MODE)
if(!SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE))
to_chat(src, "You must be in combat mode to parry!")
return FALSE
@@ -38,8 +40,14 @@
data = block_parry_data
method = UNARMED_PARRY
else
- to_chat(src, "You have nothing to parry with!")
- return FALSE
+ // QOL: If none of the above work, try to find another item.
+ var/obj/item/backup = find_backup_parry_item()
+ if(!backup)
+ to_chat(src, "You have nothing to parry with!")
+ return FALSE
+ data = backup.block_parry_data
+ using_item = backup
+ method = ITEM_PARRY
data = return_block_parry_datum(data)
var/full_parry_duration = data.parry_time_windup + data.parry_time_active + data.parry_time_spindown
// no system in place to "fallback" if out of the 3 the top priority one can't parry due to constraints but something else can.
@@ -62,6 +70,16 @@
handle_parry_starting_effects(data)
return TRUE
+/**
+ * Tries to find a backup parry item.
+ * Does not look at active held item.
+ */
+/mob/living/proc/find_backup_parry_item()
+ for(var/i in held_items - get_active_held_item())
+ var/obj/item/I = i
+ if(I.can_active_parry())
+ return I
+
/**
* Called via timer when the parry sequence ends.
*/
diff --git a/code/modules/mob/living/living_blocking_parrying.dm b/code/modules/mob/living/living_blocking_parrying.dm
index 67d90a37f3..9f1ad1c27a 100644
--- a/code/modules/mob/living/living_blocking_parrying.dm
+++ b/code/modules/mob/living/living_blocking_parrying.dm
@@ -28,11 +28,13 @@ GLOBAL_LIST_EMPTY(block_parry_data)
/// Attacks we can block
var/can_block_attack_types = ALL
/// Our slowdown added while blocking
- var/block_slowdown = 2
+ var/block_slowdown = 1
/// Clickdelay added to user after block ends
var/block_end_click_cd_add = 0
/// Disallow attacking during block
var/block_lock_attacking = TRUE
+ /// Disallow sprinting during block
+ var/block_lock_sprinting = FALSE
/// The priority we get in [mob/do_run_block()] while we're being used to parry.
var/block_active_priority = BLOCK_PRIORITY_ACTIVE_BLOCK
/// Windup before we have our blocking active.