From d44d5168d8a6d23b9032548a5dc11ce45ae9060f Mon Sep 17 00:00:00 2001
From: kevinz000 <2003111+kevinz000@users.noreply.github.com>
Date: Fri, 10 Apr 2020 22:50:53 -0700
Subject: [PATCH] progress..
---
code/modules/mob/living/life.dm | 2 +
.../modules/mob/living/living_active_block.dm | 43 +++++++++++--------
.../mob/living/living_blocking_parrying.dm | 40 ++++++++++++-----
code/modules/mob/living/living_combat.dm | 1 +
4 files changed, 57 insertions(+), 29 deletions(-)
diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm
index d3199d6f8b..5e04e3ec16 100644
--- a/code/modules/mob/living/life.dm
+++ b/code/modules/mob/living/life.dm
@@ -64,6 +64,8 @@
handle_gravity()
+ handle_block_parry(seconds)
+
if(machine)
machine.check_eye(src)
diff --git a/code/modules/mob/living/living_active_block.dm b/code/modules/mob/living/living_active_block.dm
index c0d62f3a49..3fff9a9c03 100644
--- a/code/modules/mob/living/living_active_block.dm
+++ b/code/modules/mob/living/living_active_block.dm
@@ -10,15 +10,17 @@
stop_active_blocking()
return ..()
-/mob/living/proc/stop_active_blocking()
+/mob/living/proc/stop_active_blocking(was_forced = FALSE)
+ if(!active_blocking)
+ return FALSE
var/obj/item/I = active_block_item
active_blocking = FALSE
active_block_item = null
REMOVE_TRAIT(src, TRAIT_MOBILITY_NOUSE, ACTIVE_BLOCK_TRAIT)
remove_movespeed_modifier(MOVESPEED_ID_ACTIVE_BLOCK)
var/datum/block_parry_data/data = get_block_parry_data(I.block_parry_data)
- if(timeToNextMove() < I.data.block_end_click_cd_add)
- changeNext_move(I.data.block_end_click_cd_add)
+ if(timeToNextMove() < data.block_end_click_cd_add)
+ changeNext_move(data.block_end_click_cd_add)
active_block_effect_end()
return TRUE
@@ -28,13 +30,13 @@
if(!(I in held_items))
return FALSE
var/datum/block_parry_data/data = get_block_parry_data(I.block_parry_data)
- if(!istype(I.data)) //Typecheck because if an admin/coder screws up varediting or something we do not want someone being broken forever, the CRASH logs feedback so we know what happened.
- CRASH("start_active_blocking called with an item with no valid data: [I.data]!")
+ if(!istype(data)) //Typecheck because if an admin/coder screws up varediting or something we do not want someone being broken forever, the CRASH logs feedback so we know what happened.
+ CRASH("start_active_blocking called with an item with no valid data: [I] --> [I.block_parry_data]!")
active_blocking = TRUE
active_block_item = I
- if(I.data.block_lock_attacking)
+ if(data.block_lock_attacking)
ADD_TRAIT(src, TRAIT_MOBILITY_NOMOVE, ACTIVE_BLOCK_TRAIT)
- add_movespeed_modifier(MOVESPEED_ID_ACTIVE_BLOCK, TRUE, 100, override = TRUE, multiplicative_slowdown = I.data.block_slowdown, blacklisted_movetypes = FLOATING)
+ add_movespeed_modifier(MOVESPEED_ID_ACTIVE_BLOCK, TRUE, 100, override = TRUE, multiplicative_slowdown = data.block_slowdown, blacklisted_movetypes = FLOATING)
active_block_effect_start()
return TRUE
@@ -67,9 +69,9 @@
/// The amount of damage that is blocked.
/obj/item/proc/active_block_damage_mitigation(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
var/datum/block_parry_data/data = get_block_parry_data(block_parry_data)
- var/absorption = data.block_damage_absorption_override[attack_type]
- var/efficiency = data.block_damage_multiplier_override[attack_type]
- var/limit = data.block_damage_limit_override[attack_type]
+ var/absorption = data.block_damage_absorption_override["[attack_type]"]
+ var/efficiency = data.block_damage_multiplier_override["[attack_type]"]
+ var/limit = data.block_damage_limit_override["[attack_type]"]
// must use isnulls to handle 0's.
if(isnull(absorption))
absorption = data.block_damage_absorption
@@ -92,10 +94,15 @@
/// Amount of stamina from damage blocked. Note that the damage argument is damage_blocked.
/obj/item/proc/active_block_stamina_cost(mob/living/owner, atom/object, damage_blocked, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
var/datum/block_parry_data/data = get_block_parry_data(block_parry_data)
- var/efficiency = data.block_stamina_efficiency_override[attack_type]
+ var/efficiency = data.block_stamina_efficiency_override["[attack_type]"]
if(isnull(efficiency))
efficiency = data.block_stamina_efficiency
- return damage_blocked / efficiency
+ var/multiplier = 1
+ if(!CHECK_MOBILITY(owner, MOBILITY_STAND))
+ multiplier = data.block_resting_stamina_penalty_multiplier_override["["[attack_type]"]"]
+ if(isnull(multiplier))
+ multiplier = data.block_resting_stamina_penalty_multiplier
+ return (damage_blocked / efficiency)
/// Apply the stamina damage to our user, notice how damage argument is stamina_amount.
/obj/item/proc/active_block_do_stamina_damage(mob/living/owner, atom/object, stamina_amount, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
@@ -119,13 +126,13 @@
/obj/item/proc/active_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
if(!CHECK_BITFIELD(item_flags, ITEM_CAN_BLOCK))
- return
- if(!CHECK_BITFIELD(item_flags, ITEM_CAN_BLOCK))
- return
- var/incoming_direction = get_dir(get_turf(attacker) || get_turf(object), src)
- if(!can_block_direction(owner.dir, incoming_direction))
- return
+ return BLOCK_NONE
var/datum/block_parry_data/data = get_block_parry_data(block_parry_data)
+ var/incoming_direction = get_dir(get_turf(attacker) || get_turf(object), src)
+ if(!CHECK_MOBILITY(owner, MOBILITY_STAND) && !(data.block_resting_attack_types_anydir & attack_type) && (!(data.block_resting_attack_types_directional & attack_type) || !can_block_direction(owner.dir, incoming_direction)))
+ return BLOCK_NONE
+ else if(!can_block_direction(owner.dir, incoming_direction))
+ return BLOCK_NONE
block_return[BLOCK_RETURN_ACTIVE_BLOCK] = TRUE
var/damage_mitigated = active_block_damage_mitigation(owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return)
var/final_damage = max(0, damage - damage_mitigated)
diff --git a/code/modules/mob/living/living_blocking_parrying.dm b/code/modules/mob/living/living_blocking_parrying.dm
index eb722973f0..e758d476bc 100644
--- a/code/modules/mob/living/living_blocking_parrying.dm
+++ b/code/modules/mob/living/living_blocking_parrying.dm
@@ -34,6 +34,9 @@ GLOBAL_LIST_EMPTY(block_parry_data)
/// Carries data like list data that would be a waste of memory if we initialized the list on every /item as we can cache datums easier.
/datum/block_parry_data
/////////// BLOCKING ////////////
+
+ /// NOTE: FOR ATTACK_TYPE_DEFINE, you MUST wrap it in "[DEFINE_HERE]"! The defines are bitflags, and therefore, NUMBERS!
+
/// See defines.
var/can_block_directions = BLOCK_DIR_NORTH | BLOCK_DIR_NORTHEAST | BLOCK_DIR_NORTHWEST
/// Our slowdown added while blocking
@@ -47,17 +50,17 @@ GLOBAL_LIST_EMPTY(block_parry_data)
/// Amount of "free" damage blocking absorbs
var/block_damage_absorption = 10
- /// Override absorption, list(ATTACK_TYPE_DEFINE = absorption), see [block_damage_absorption]
+ /// Override absorption, list("[ATTACK_TYPE_DEFINE]" = absorption), see [block_damage_absorption]
var/list/block_damage_absorption_override
/// Ratio of damage block above absorption amount, coefficient, lower is better, this is multiplied by damage to determine how much is blocked.
var/block_damage_multiplier = 0.5
- /// Override damage overrun efficiency, list(ATTACK_TYPE_DEFINE = absorption), see [block_damage_efficiency]
+ /// Override damage overrun efficiency, list("[ATTACK_TYPE_DEFINE]" = absorption), see [block_damage_efficiency]
var/list/block_damage_multiplier_override
/// Upper bound of damage block, anything above this will go right through.
var/block_damage_limit = 80
- /// Override upper bound of damage block, list(ATTACK_TYPE_DEFINE = absorption), see [block_damage_limit]
+ /// Override upper bound of damage block, list("[ATTACK_TYPE_DEFINE]" = absorption), see [block_damage_limit]
var/list/block_damage_limit_override
/*
@@ -69,7 +72,7 @@ GLOBAL_LIST_EMPTY(block_parry_data)
/// Default damage-to-stamina coefficient, higher is better. This is based on amount of damage BLOCKED, not initial damage, to prevent damage from "double dipping".
var/block_stamina_efficiency = 2
- /// Override damage-to-stamina coefficient, see [block_efficiency], this should be list(ATTACK_TYPE_DEFINE = coefficient_number)
+ /// Override damage-to-stamina coefficient, see [block_efficiency], this should be list("[ATTACK_TYPE_DEFINE]" = coefficient_number)
var/list/block_stamina_efficiency_override
/// Ratio of stamina incurred by blocking that goes to the arm holding the object instead of the chest. Has no effect if this is not held in hand.
var/block_stamina_limb_ratio = 0.5
@@ -79,6 +82,15 @@ GLOBAL_LIST_EMPTY(block_parry_data)
/// Stamina dealt directly via adjustStaminaLossBuffered() per SECOND of block.
var/block_stamina_cost_per_second = 1.5
+ /// Bitfield for attack types that we can block while down. This will work in any direction.
+ var/block_resting_attack_types_anydir = ATTACK_TYPE_MELEE | ATTACK_TYPE_UNARMED | ATTACK_TYPE_TACKLE
+ /// Bitfield for attack types that we can block while down but only in our normal directions.
+ var/block_resting_attack_types_directional = ATTACK_TYPE_PROJECTILE | ATTACK_TYPE_THROWN
+ /// Multiplier to stamina damage taken for attacks blocked while downed.
+ var/block_resting_stamina_penalty_multiplier = 1.5
+ /// Override list for multiplier to stamina damage taken for attacks blocked while down. list("[ATTACK_TYPE_DEFINE]" = multiplier_number)
+ var/list/block_resting_stamina_penalty_multiplier_override
+
/// Sounds for blocking
var/list/block_sounds = list('sound/block_parry/block_metal1.ogg' = 1, 'sound/block_parry/block_metal1.ogg' = 1)
@@ -96,11 +108,11 @@ GLOBAL_LIST_EMPTY(block_parry_data)
var/parry_time_perfect = 2.5
/// Time on both sides of perfect parry that still counts as part of the perfect window.
var/parry_time_perfect_leeway = 1
- /// [parry_time_perfect_leeway] override for attack types, list(ATTACK_TYPE_DEFINE = deciseconds)
+ /// [parry_time_perfect_leeway] override for attack types, list("[ATTACK_TYPE_DEFINE]" = deciseconds)
var/list/parry_time_perfect_leeway_override
/// Parry "efficiency" falloff in percent per decisecond once perfect window is over.
var/parry_imperfect_falloff_percent = 20
- /// [parry_imperfect_falloff_percent] override for attack types, list(ATTACK_TYPE_DEFINE = deciseconds)
+ /// [parry_imperfect_falloff_percent] override for attack types, list("[ATTACK_TYPE_DEFINE]" = deciseconds)
var/list/parry_imperfect_falloff_percent_override
/// Efficiency in percent on perfect parry.
var/parry_efficiency_perfect = 120
@@ -109,11 +121,17 @@ GLOBAL_LIST_EMPTY(block_parry_data)
PARRY_REFLEX_COUNTERATTACK = PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN
)
+/mob/living/proc/handle_block_parry(seconds = 1)
+ if(active_blocking)
+ var/datum/block_parry_data/data = get_block_parry_data(active_block_item.block_parry_data)
+ adjustStaminaLossBuffered(data.block_stamina_cost_per_second * seconds)
+
/obj/item/proc/active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
if(!CHECK_BITFIELD(item_flags, ITEM_CAN_PARRY))
return
/// Yadda yadda WIP access block/parry data...
+/*
/mob/living/proc/get_parry_stage()
if(!parrying)
return NOT_PARRYING
@@ -134,15 +152,15 @@ GLOBAL_LIST_EMPTY(block_parry_data)
var/datum/block_parry_data/data = get_parry_data()
if(get_parry_stage() != PARRY_ACTIVE)
return 0
- var/difference = abs(get_parry_time() - (data.parry_time_perfect + data.parry_time_windup)
- var/leeway = data.parry_time_perfect_leeway_override[attack_type]
+ var/difference = abs(get_parry_time() - (data.parry_time_perfect + data.parry_time_windup))
+ var/leeway = data.parry_time_perfect_leeway_override["[attack_type]"]
if(isnull(leeway))
leeway = data.parry_time_perfect_leeway
difference -= leeway
. = data.parry_efficiency_perfect
if(difference <= 0)
return
- var/falloff = data.parry_imperfect_falloff_percent_override[attack_type]
+ var/falloff = data.parry_imperfect_falloff_percent_override["[attack_type]"]
if(isnull(falloff))
falloff = data.parry_imperfect_falloff_percent
. -= falloff * difference
@@ -155,7 +173,7 @@ GLOBAL_LIST_EMPTY(block_parry_data)
/// Run counterattack if any
/mob/living/proc/run_parry_countereffects(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list())
- var/datum/block_parry_data = get_parry_data()
+ var/datum/block_parry_data/data = get_parry_data()
if(data.parry_data[PARRY_REFLEX_COUNTERATTACK])
switch(data.parry_data[PARRY_REFLEX_COUNTERATTACK])
if(PARRY_COUNTERATTACK_PROC)
@@ -184,5 +202,5 @@ GLOBAL_LIST_EMPTY(block_parry_data)
return get_block_parry_data(block_parry_data)
else if(parrying == MARTIAL_PARRY)
return get_block_parry_data(mind.martial_art.block_parry_data)
-
+*/
diff --git a/code/modules/mob/living/living_combat.dm b/code/modules/mob/living/living_combat.dm
index 493f2ffdff..470bba4565 100644
--- a/code/modules/mob/living/living_combat.dm
+++ b/code/modules/mob/living/living_combat.dm
@@ -27,6 +27,7 @@
to_chat(src, was_forced? "Your muscles are forcibly relaxed!" : "You relax your muscles.")
if(update_icon)
update_combat_mode_icon()
+ stop_active_blocking(TRUE)
/mob/living/proc/enable_combat_mode(silent = TRUE, was_forced = FALSE, visible = FALSE, update_icon = TRUE)
if(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)