From ae9fc5789df5a5e57038f9db869017e5819cc622 Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Sat, 30 May 2020 00:35:17 -0700 Subject: [PATCH] adds more support to stuff --- code/__DEFINES/combat.dm | 15 +++++++-- code/__DEFINES/combat/block_parry.dm | 8 +++++ code/modules/mob/living/living.dm | 2 ++ .../modules/mob/living/living_active_parry.dm | 31 ++++++++++++++----- .../mob/living/living_blocking_parrying.dm | 14 +++++++-- code/modules/mob/living/living_defines.dm | 15 ++++----- 6 files changed, 64 insertions(+), 21 deletions(-) diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index fc7d9e13e0..cdb5c48dbd 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -29,10 +29,11 @@ #define EFFECT_DROWSY "drowsy" #define EFFECT_JITTER "jitter" +// mob/living/var/combat_flags variable. /// Default combat flags for those affected by sprinting (combat mode has been made into its own component) -#define COMBAT_FLAGS_DEFAULT NONE +#define COMBAT_FLAGS_DEFAULT (COMBAT_FLAG_PARRY_CAPABLE | COMBAT_FLAG_BLOCK_CAPABLE) /// Default combat flags for everyone else (so literally everyone but humans). -#define COMBAT_FLAGS_SPRINT_EXEMPT (COMBAT_FLAG_SPRINT_ACTIVE | COMBAT_FLAG_SPRINT_TOGGLED | COMBAT_FLAG_SPRINT_FORCED) +#define COMBAT_FLAGS_SPRINT_EXEMPT (COMBAT_FLAG_SPRINT_ACTIVE | COMBAT_FLAG_SPRINT_TOGGLED | COMBAT_FLAG_SPRINT_FORCED | COMBAT_FLAG_PARRY_CAPABLE | COMBAT_FLAG_BLOCK_CAPABLE) /// The user wants sprint mode on #define COMBAT_FLAG_SPRINT_TOGGLED (1<<0) @@ -50,6 +51,16 @@ #define COMBAT_FLAG_SOFT_STAMCRIT (1<<6) /// Force sprint mode on at all times, overrides everything including sprint disable traits. #define COMBAT_FLAG_SPRINT_FORCED (1<<7) +/// This mob is capable of using the active parrying system. +#define COMBAT_FLAG_PARRY_CAPABLE (1<<8) +/// This mob is capable of using the active blocking system. +#define COMBAT_FLAG_BLOCK_CAPABLE (1<<9) +/// This mob is capable of unarmed parrying +#define COMBAT_FLAG_UNARMED_PARRY (1<<10) +/// This mob is currently actively blocking +#define COMBAT_FLAG_ACTIVE_BLOCKING (1<<11) +/// This mob is currently starting an active block +#define COMBAT_FLAG_ACTIVE_BLOCK_STARTING (1<<12) // Helpers for getting someone's stamcrit state. Cast to living. #define NOT_STAMCRIT 0 diff --git a/code/__DEFINES/combat/block_parry.dm b/code/__DEFINES/combat/block_parry.dm index ed7a889321..66c35a405d 100644 --- a/code/__DEFINES/combat/block_parry.dm +++ b/code/__DEFINES/combat/block_parry.dm @@ -37,6 +37,14 @@ GLOBAL_LIST_INIT(dir2blockdir, list( #define PARRY_ACTIVE 2 #define PARRY_SPINDOWN 3 +// /datum/block_parry_data/var/parry_flags +/// Default handling for audio/visual feedback +#define PARRY_DEFAULT_HANDLE_FEEDBACK (1<<0) +/// Lock sprinting while parrying +#define PARRY_LOCK_SPRINTING (1<<1) +/// Lock attacking while parrying +#define PARRY_LOCK_ATTACKING (1<<2) + /// Parry effects. /// List association must be one of the things underneath #define PARRY_REFLEX_COUNTERATTACK "reflex_counter" diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index c1038fbb41..5b21abfb84 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -19,6 +19,8 @@ med_hud_set_status() /mob/living/Destroy() + end_parry_sequence() + stop_active_blocking() if(LAZYLEN(status_effects)) for(var/s in status_effects) var/datum/status_effect/S = s diff --git a/code/modules/mob/living/living_active_parry.dm b/code/modules/mob/living/living_active_parry.dm index a1ddb6e2b5..ef23c28d70 100644 --- a/code/modules/mob/living/living_active_parry.dm +++ b/code/modules/mob/living/living_active_parry.dm @@ -39,7 +39,7 @@ 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. // can always implement it later, whatever. - if(data.parry_respect_clickdelay && (next_move > world.time)) + if((data.parry_respect_clickdelay && (next_move > world.time)) || ((parry_end_time_last + data.parry_cooldown) > world.time)) to_chat(src, "You are not ready to parry (again)!") return // Point of no return, make sure everything is set. @@ -50,6 +50,10 @@ parry_start_time = world.time successful_parries = list() addtimer(CALLBACK(src, .proc/end_parry_sequence), full_parry_duration) + if(data.parry_flags & PARRY_LOCK_ATTACKING) + ADD_TRAIT(src, TRAIT_MOBILITY_NOUSE, ACTIVE_PARRY_TRAIT) + if(data.parry_flags & PARRY_LOCK_SPRINTING) + ADD_TRAIT(src, TRAIT_SPRINT_LOCKED, ACTIVE_PARRY_TRAIT) handle_parry_starting_effects(data) return TRUE @@ -59,9 +63,16 @@ /mob/living/proc/end_parry_sequence() if(!parrying) return + if(parry_visual_effect) + QDEL_NULL(parry_visual_effect) var/datum/block_parry_data/data = get_parry_data() var/list/effect_text = list() - if(!length(successful_parries)) // didn't parry anything successfully + var/successful = FALSE + for(var/efficiency in successful_parries) + if(efficiency >= data.parry_efficiency_considered_successful) + successful = TRUE + break + if(!successful) // didn't parry anything successfully if(data.parry_failed_stagger_duration) Stagger(data.parry_failed_stagger_duration) effect_text += "staggering themselves" @@ -78,7 +89,7 @@ */ /mob/living/proc/handle_parry_starting_effects(datum/block_parry_data/data) playsound(src, data.parry_start_sound, 75, 1) - new /obj/effect/abstract/parry/main(null, data, src) + parry_visual_effect = new /obj/effect/abstract/parry/main(null, data, src, data.parry_effect_icon_state) switch(parrying) if(ITEM_PARRY) visible_message("[src] swings [active_parry_item]!") @@ -185,7 +196,7 @@ /// same return values as normal blocking, called with absolute highest priority in the block "chain". /mob/living/proc/run_parry(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list()) var/stage = get_parry_stage() - if(stage == NOT_PARRYING) + if(stage != PARRY_ACTIVE) return BLOCK_NONE if(!CHECK_MOBILITY(src, MOBILITY_USE)) to_chat(src, "Your parry is interrupted!") @@ -208,10 +219,14 @@ . |= BLOCK_SHOULD_PARTIAL_MITIGATE 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. - var/list/effect_text = run_parry_countereffects(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency) - if(data.parry_default_handle_feedback) + var/list/effect_text + if(efficiency >= data.parry_efficiency_to_counterattack) + run_parry_countereffects(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency) + if(data.parry_flags & PARRY_DEFAULT_HANDLE_FEEDBACK) handle_parry_feedback(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, effect_text) successful_parries += efficiency + if(length(successful_parries) >= data.parry_max_attacks) + end_parry_sequence() /mob/living/proc/handle_parry_feedback(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list(), parry_efficiency, list/effect_text) var/datum/block_parry_data/data = get_parry_data() @@ -283,10 +298,10 @@ /obj/effect/abstract/parry/main name = null - icon_state = "parry_bm_hold" -/obj/effect/abstract/parry/main/Initialize(mapload, datum/block_parry_data/data, mob/living/owner) +/obj/effect/abstract/parry/main/Initialize(mapload, datum/block_parry_data/data, mob/living/owner, icon_state) . = ..() + src.icon_state = icon_state if(owner) attach_to(owner) if(data) diff --git a/code/modules/mob/living/living_blocking_parrying.dm b/code/modules/mob/living/living_blocking_parrying.dm index a5971afed2..0a4bf18768 100644 --- a/code/modules/mob/living/living_blocking_parrying.dm +++ b/code/modules/mob/living/living_blocking_parrying.dm @@ -93,6 +93,8 @@ GLOBAL_LIST_EMPTY(block_parry_data) var/parry_stamina_cost = 5 /// Attack types we can block var/parry_attack_types = ALL + /// Parry flags + var/parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK | PARRY_LOCK_ATTACKING /// Parry windup duration in deciseconds. 0 to this is windup, afterwards is main stage. var/parry_time_windup = 2 @@ -116,8 +118,16 @@ GLOBAL_LIST_EMPTY(block_parry_data) var/list/parry_data = list( PARRY_REFLEX_COUNTERATTACK = PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN ) - /// Enable default handling of audio/visual feedback - var/parry_default_handle_feedback = TRUE + /// Efficiency must be at least this to be considered successful + var/parry_efficiency_considered_successful = 0.1 + /// Efficiency must be at least this to run automatic counterattack + var/parry_efficiency_to_counterattack = 0.1 + /// Maximum attacks to parry successfully or unsuccessfully during active period, hitting this immediately ends the sequence. + var/parry_max_attacks = INFINITY + /// Visual icon state override for parrying + var/parry_effect_icon_state = "parry_bm_hold" + /// Parrying cooldown, separate of clickdelay. It must be this much deciseconds since their last parry for them to parry with this object. + var/parry_cooldown = 0 /// Parry start sound var/parry_start_sound = 'sound/block_parry/sfx-parry.ogg' /// Sounds for parrying diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 6e19d2147c..b9e8feee7f 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -29,14 +29,8 @@ // Combat - Blocking/Parrying system /// Our block_parry_data for unarmed blocks/parries. Currently only used for parrying, as unarmed block isn't implemented yet. YOU MUST RUN [get_block_parry_data(this)] INSTEAD OF DIRECTLY ACCESSING! - var/datum/block_parry_data/block_parry_data + var/datum/block_parry_data/block_parry_data = /datum/block_parry_data // defaults to *something* because [combat_flags] dictates whether or not we can unarmed block/parry. // Blocking - /// Whether or not the user is actively blocking. - var/active_blocking = FALSE - /// Whether or not we can actively block. Disabled by default since a lot of mobs do not support stamina damage. Imagine a dextrous guardian with a shield.. - var/active_block_enabled = FALSE - /// Whether or not we are in the process of raising our shield/whatever. - var/active_block_starting = FALSE /// The item the user is actively blocking with if any. var/obj/item/active_block_item // Parrying @@ -46,8 +40,11 @@ var/obj/item/active_parry_item /// world.time of parry action start var/parry_start_time = 0 - /// Whether or not we can unarmed parry - var/parry_while_unarmed = FALSE + /// Current parry effect. + var/obj/effect/abstract/parry/parry_visual_effect + /// world.time of last parry end + var/parry_end_time_last = 0 + #warn implement above /// Successful parries within the current parry cycle. It's a list of efficiency percentages. var/list/successful_parries