diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm index ca06fad93e..593aa599c0 100644 --- a/code/game/objects/items/shields.dm +++ b/code/game/objects/items/shields.dm @@ -26,7 +26,6 @@ /datum/block_parry_data/shield - /obj/item/shield/examine(mob/user) . = ..() if(shield_flags & SHIELD_CAN_BASH) diff --git a/code/modules/mob/living/living_active_block.dm b/code/modules/mob/living/living_active_block.dm index ae779f2dd4..53e292a32f 100644 --- a/code/modules/mob/living/living_active_block.dm +++ b/code/modules/mob/living/living_active_block.dm @@ -19,10 +19,10 @@ return FALSE var/obj/item/I = active_block_item active_blocking = FALSE + active_block_effect_end() active_block_item = null REMOVE_TRAIT(src, TRAIT_MOBILITY_NOUSE, ACTIVE_BLOCK_TRAIT) remove_movespeed_modifier(/datum/movespeed_modifier/active_block) - active_block_effect_end() var/datum/block_parry_data/data = I.get_block_parry_data() if(timeToNextMove() < data.block_end_click_cd_add) changeNext_move(data.block_end_click_cd_add) @@ -183,11 +183,17 @@ else owner.adjustStaminaLossBuffered(stamina_amount) -/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) +/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, override_direction) if(!can_active_block()) return BLOCK_NONE var/datum/block_parry_data/data = get_block_parry_data() - var/incoming_direction = get_dir(get_turf(attacker) || get_turf(object), src) + var/incoming_direction + if(isnull(override_direction)) + if(istype(object, /obj/item/projectile)) + var/obj/item/projectile/P = object + incoming_direction = angle2dir(P.Angle) + else + 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)) @@ -218,7 +224,7 @@ block_return[BLOCK_RETURN_ACTIVE_BLOCK_DAMAGE_MITIGATED] = active_block_damage_mitigation(owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return) /** - * Gets the list of directions we can block. Include DOWN to block attacks from our same tile. + * Gets the block direction bitflags of what we can block. */ /obj/item/proc/blockable_directions() var/datum/block_parry_data/data = get_block_parry_data() @@ -237,7 +243,7 @@ // dir2angle(), ss13 proc is clockwise so dir2angle(EAST) == 90 // turn(), byond proc is counterclockwise so turn(NORTH, 90) == WEST their_dir = turn(their_dir, turn_angle) - return (DIR2BLOCKDIR(their_dir) in blockable_directions()) + return (DIR2BLOCKDIR(their_dir) & blockable_directions()) /** * can_block_direction but for "compound" directions to check all of them and return the number of directions that were blocked. diff --git a/code/modules/mob/living/living_block.dm b/code/modules/mob/living/living_block.dm index 6fc20f6478..a4454c3cdc 100644 --- a/code/modules/mob/living/living_block.dm +++ b/code/modules/mob/living/living_block.dm @@ -1,12 +1,12 @@ // This file has a weird name, but it's for anything related to the checks for shields, blocking, dodging, and similar "stop this attack before it actually impacts the target" as opposed to "defend once it has hit". ///Check whether or not we can block, without "triggering" a block. Basically run checks without effects like depleting shields. Wrapper for do_run_block(). The arguments on that means the same as for this. -/mob/living/proc/check_block(atom/object, damage, attack_text = "the attack", attack_type, armour_penetration, mob/attacker, def_zone, list/return_list) - return do_run_block(FALSE, object, damage, attack_text, attack_type, armour_penetration, attacker, check_zone(def_zone), return_list) +/mob/living/proc/check_block(atom/object, damage, attack_text = "the attack", attack_type, armour_penetration, mob/attacker, def_zone, list/return_list, attack_direction) + return do_run_block(FALSE, object, damage, attack_text, attack_type, armour_penetration, attacker, check_zone(def_zone), return_list, attack_direction) /// Runs a block "sequence", effectively checking and then doing effects if necessary. Wrapper for do_run_block(). The arguments on that means the same as for this. -/mob/living/proc/run_block(atom/object, damage, attack_text = "the attack", attack_type, armour_penetration, mob/attacker, def_zone, list/return_list) - return do_run_block(TRUE, object, damage, attack_text, attack_type, armour_penetration, attacker, check_zone(def_zone), return_list) +/mob/living/proc/run_block(atom/object, damage, attack_text = "the attack", attack_type, armour_penetration, mob/attacker, def_zone, list/return_list, attack_direction) + return do_run_block(TRUE, object, damage, attack_text, attack_type, armour_penetration, attacker, check_zone(def_zone), return_list, attack_direction) /** The actual proc for block checks. DO NOT USE THIS DIRECTLY UNLESS YOU HAVE VERY GOOD REASON TO. To reduce copypaste for differences between handling for real attacks and virtual checks. * Automatically checks all held items for /obj/item/proc/run_block() with the same parameters. @@ -21,14 +21,15 @@ * attacker - Set to the mob attacking IF KNOWN. Do not expect this to always be set! * def_zone - The zone this'll impact. * return_list - If something wants to grab things from what items/whatever put into list/block_return on obj/item/run_block and the comsig, pass in a list so you can grab anything put in it after block runs. + * attack_direction - Direction of the attack. It is highly recommended to put this in, as the automatic guesswork that's done otherwise is quite inaccurate at times. */ -/mob/living/proc/do_run_block(real_attack = TRUE, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list()) +/mob/living/proc/do_run_block(real_attack = TRUE, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list(), attack_direction) if(real_attack) . = run_parry(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list) //Parry - Highest priority! if((. & BLOCK_SUCCESS) && !(. & BLOCK_CONTINUE_CHAIN)) return // Component signal block runs have highest priority.. for now. - . = SEND_SIGNAL(src, COMSIG_LIVING_RUN_BLOCK, real_attack, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list) + . = SEND_SIGNAL(src, COMSIG_LIVING_RUN_BLOCK, real_attack, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, attack_direction) if((. & BLOCK_SUCCESS) && !(. & BLOCK_CONTINUE_CHAIN)) return var/list/obj/item/tocheck = get_blocking_items() @@ -41,7 +42,7 @@ var/final_block_chance = I.block_chance - (clamp((armour_penetration-I.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example var/results if(I == active_block_item) - results = I.active_block(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, return_list) + results = I.active_block(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, return_list, attack_direction) else results = I.run_block(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, return_list) . |= results @@ -52,7 +53,7 @@ // i don't like this too var/final_block_chance = I.block_chance - (clamp((armour_penetration-I.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example if(I == active_block_item) //block is long termed enough we give a damn. parry, not so much. - I.check_active_block(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, return_list) + I.check_active_block(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, return_list, attack_direction) else I.check_block(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, return_list) diff --git a/code/modules/mob/living/living_blocking_parrying.dm b/code/modules/mob/living/living_blocking_parrying.dm index 32a9734232..44fb1f91a8 100644 --- a/code/modules/mob/living/living_blocking_parrying.dm +++ b/code/modules/mob/living/living_blocking_parrying.dm @@ -39,7 +39,7 @@ GLOBAL_LIST_EMPTY(block_parry_data) /// NOTE: FOR ATTACK_TYPE_DEFINE, you MUST wrap it in "[DEFINE_HERE]"! The defines are bitflags, and therefore, NUMBERS! - /// See defines. + /// See defines. Point of reference is someone facing north. var/can_block_directions = BLOCK_DIR_NORTH | BLOCK_DIR_NORTHEAST | BLOCK_DIR_NORTHWEST /// Our slowdown added while blocking var/block_slowdown = 2