diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/_type2type.dm similarity index 99% rename from code/__HELPERS/type2type.dm rename to code/__HELPERS/_type2type.dm index 04ab67fdb3ea..8a57d986800d 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/_type2type.dm @@ -62,8 +62,6 @@ return SOUTHEAST if("SOUTHWEST") return SOUTHWEST - else - return //Converts an angle (degrees) into a ss13 direction GLOBAL_LIST_INIT(modulo_angle_to_dir, list(NORTH,NORTHEAST,EAST,SOUTHEAST,SOUTH,SOUTHWEST,WEST,NORTHWEST)) diff --git a/code/__HELPERS/combat_helpers.dm b/code/__HELPERS/combat_helpers.dm new file mode 100644 index 000000000000..4ea817b573b3 --- /dev/null +++ b/code/__HELPERS/combat_helpers.dm @@ -0,0 +1,26 @@ +/// Returns an angle between 0 and 180, where 0 is the attacker is directly infront of the defender, 180 for directly behind. +/proc/get_relative_attack_angle(mob/living/carbon/human/defender, atom/movable/hitby) + var/attack_dir = defender.dir // Default to the defender's dir so that the attack angle is 0 by default + var/turf/defender_turf = get_turf(defender) + + if(isprojectile(hitby)) + var/obj/projectile/P = hitby + if(P.starting != defender_turf) + attack_dir = REVERSE_DIR(angle2dir(P.Angle)) + + else if(isitem(hitby)) + if(ismob(hitby.loc)) + attack_dir = get_dir(defender, hitby.loc) + else + attack_dir = get_dir(defender, hitby) + + else + attack_dir = get_dir(defender, hitby) + + var/attack_angle = dir2angle(attack_dir) || 0 // If attack_dir == 0, dir2angle returns null + var/facing_angle = dir2angle(defender.dir) || 0 + var/delta = abs(attack_angle - facing_angle) + if(delta > 180) + delta = 360 - delta + + return delta diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm index 0ee74a0861f4..4ff03c66aaa8 100644 --- a/code/datums/martial/sleeping_carp.dm +++ b/code/datums/martial/sleeping_carp.dm @@ -229,7 +229,7 @@ else return ..() -/obj/item/staff/bostaff/get_block_chance(atom/movable/hitby, damage, attack_type, armor_penetration) - if(wielded) - return ..() - return FALSE +/obj/item/staff/bostaff/can_block_attack(mob/living/carbon/human/wielder, atom/movable/hitby, attack_type) + if(!wielded) + return FALSE + return ..() diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 74b7f7e0c49d..000860038ceb 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -239,6 +239,9 @@ DEFINE_INTERACTABLE(/obj/item) /// The baseline chance to block **ANY** attack, projectiles included var/block_chance = 0 + /// The angle infront of the defender that is a valid block range. + var/block_angle = 45 // Infront and infront + sides, but not direct sides + /// The type of effect to create on a successful block var/obj/effect/temp_visual/block_effect = /obj/effect/temp_visual/block @@ -703,7 +706,8 @@ DEFINE_INTERACTABLE(/obj/item) var/sig_return = SEND_SIGNAL(src, COMSIG_ITEM_CHECK_BLOCK) var/block_result = sig_return & COMPONENT_CHECK_BLOCK_BLOCKED - block_result ||= prob(get_block_chance(wielder, hitby, damage, attack_type, armor_penetration)) + if(!block_result && can_block_attack(wielder, hitby, attack_type)) + block_result = prob(get_block_chance(wielder, hitby, damage, attack_type, armor_penetration)) var/list/reaction_args = args.Copy() if(block_result) @@ -720,6 +724,14 @@ DEFINE_INTERACTABLE(/obj/item) return block_result +/// Checks if this item can block an incoming attack. +/obj/item/proc/can_block_attack(mob/living/carbon/human/wielder, atom/movable/hitby, attack_type) + var/angle = get_relative_attack_angle(wielder, hitby) + if(angle <= block_angle) + return TRUE + + return FALSE + /// Returns a number to feed into prob() to determine if the attack was blocked. /obj/item/proc/get_block_chance(mob/living/carbon/human/wielder, atom/movable/hitby, damage, attack_type, armor_penetration) var/block_chance_modifier = round(damage / -3) diff --git a/code/game/objects/items/dualsaber.dm b/code/game/objects/items/dualsaber.dm index 47cca01b5fc1..0501d38f7a0a 100644 --- a/code/game/objects/items/dualsaber.dm +++ b/code/game/objects/items/dualsaber.dm @@ -138,10 +138,10 @@ else user.stamina.adjust(-25) -/obj/item/dualsaber/get_block_chance(atom/movable/hitby, damage, attack_type, armor_penetration) - if(wielded) - return ..() - return FALSE +/obj/item/dualsaber/can_block_attack(mob/living/carbon/human/wielder, atom/movable/hitby, attack_type) + if(!wielded) + return FALSE + return ..() /obj/item/dualsaber/process() if(!wielded) diff --git a/code/game/objects/items/grenades/_grenade.dm b/code/game/objects/items/grenades/_grenade.dm index 0fd9effa49ea..68701ab8f322 100644 --- a/code/game/objects/items/grenades/_grenade.dm +++ b/code/game/objects/items/grenades/_grenade.dm @@ -214,10 +214,10 @@ /obj/item/grenade/get_block_chance(mob/living/carbon/human/wielder, atom/movable/hitby, damage, attack_type, armor_penetration) var/obj/projectile/hit_projectile = hitby if(!istype(hitby)) - return FALSE + return 0 if(damage && attack_type == PROJECTILE_ATTACK && hit_projectile.damage_type != STAMINA && prob(15)) - return TRUE + return 100 /obj/item/grenade/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", damage = 0, attack_type = MELEE_ATTACK, block_success = TRUE) . = ..() diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm index 22bd9187ce2c..93f7b0901582 100644 --- a/code/game/objects/items/holy_weapons.dm +++ b/code/game/objects/items/holy_weapons.dm @@ -248,7 +248,7 @@ attack_verb_simple = list("attack", "slash", "stab", "slice", "tear", "lacerate", "rip", "dice", "cut") menu_description = "A sharp claymore which provides a low chance of blocking incoming melee attacks. Can be worn on the back or belt." -/obj/item/nullrod/claymore/get_block_chance(mob/living/carbon/human/wielder, atom/movable/hitby, damage, attack_type, armor_penetration) +/obj/item/nullrod/claymore/can_block_attack(mob/living/carbon/human/wielder, atom/movable/hitby, attack_type) if(attack_type == PROJECTILE_ATTACK) return FALSE return ..() diff --git a/code/game/objects/items/melee/energy.dm b/code/game/objects/items/melee/energy.dm index f564eab2358f..16608aeb186d 100644 --- a/code/game/objects/items/melee/energy.dm +++ b/code/game/objects/items/melee/energy.dm @@ -179,10 +179,10 @@ block_chance = 50 embedding = list("embed_chance" = 75, "impact_pain_mult" = 10) -/obj/item/melee/energy/sword/get_block_chance(mob/living/carbon/human/wielder, atom/movable/hitby, damage, attack_type, armor_penetration) - if(blade_active) - return ..() - return FALSE +/obj/item/melee/energy/sword/can_block_attack(mob/living/carbon/human/wielder, atom/movable/hitby, attack_type) + if(!blade_active) + return FALSE + return ..() /obj/item/melee/energy/sword/cyborg name = "cyborg energy sword" @@ -223,7 +223,7 @@ active_force = 30 sword_color_icon = null // Stops icon from breaking when turned on. -/obj/item/melee/energy/sword/cyborg/saw/get_block_chance(mob/living/carbon/human/wielder, atom/movable/hitby, damage, attack_type, armor_penetration) +/obj/item/melee/energy/sword/cyborg/saw/can_block_attack(mob/living/carbon/human/wielder, atom/movable/hitby, attack_type) return FALSE // The colored energy swords we all know and love. diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index cd148bbb1bb4..2574df19f6d0 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -76,9 +76,9 @@ . = ..() AddComponent(/datum/component/butchering, 30, 95, 5) //fast and effective, but as a sword, it might damage the results. -/obj/item/melee/sabre/get_block_chance(mob/living/carbon/human/wielder, atom/movable/hitby, damage, attack_type, armor_penetration) +/obj/item/melee/sabre/can_block_attack(mob/living/carbon/human/wielder, atom/movable/hitby, attack_type) if(attack_type == PROJECTILE_ATTACK) - return FALSE //Don't bring a sword to a gunfight + return FALSE return ..() /obj/item/melee/sabre/on_exit_storage(datum/storage/container) diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm index 330d4e0ce9ec..fc8fab1886f3 100644 --- a/code/game/objects/items/shields.dm +++ b/code/game/objects/items/shields.dm @@ -28,9 +28,12 @@ max_integrity = 75 -/obj/item/shield/get_block_chance(mob/living/carbon/human/wielder, atom/movable/hitby, damage, attack_type, armor_penetration) +/obj/item/shield/can_block_attack(mob/living/carbon/human/wielder, atom/movable/hitby, attack_type) if(transparent && (hitby.pass_flags & PASSGLASS)) return FALSE + return ..() + +/obj/item/shield/get_block_chance(mob/living/carbon/human/wielder, atom/movable/hitby, damage, attack_type, armor_penetration) . = ..() if(attack_type == THROWN_PROJECTILE_ATTACK) . += 30 @@ -269,10 +272,10 @@ attack_verb_simple_on = list("smack", "strike", "crack", "beat")) RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, PROC_REF(on_transform)) -/obj/item/shield/riot/tele/get_block_chance(mob/living/carbon/human/wielder, atom/movable/hitby, damage, attack_type, armor_penetration) - if(extended) - return ..() - return FALSE +/obj/item/shield/riot/tele/can_block_attack(mob/living/carbon/human/wielder, atom/movable/hitby, attack_type) + if(!extended) + return FALSE + return ..() /* * Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM]. diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index f2a198164a38..6e8d863687ee 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -520,7 +520,7 @@ attack_verb_continuous = list("attacks", "strikes", "hits") attack_verb_simple = list("attack", "strike", "hit") -/obj/item/dualsaber/toy/get_block_chance(mob/living/carbon/human/wielder, atom/movable/hitby, damage, attack_type, armor_penetration) +/obj/item/dualsaber/toy/can_block_attack(mob/living/carbon/human/wielder, atom/movable/hitby, attack_type) return FALSE /obj/item/dualsaber/toy/IsReflect() //Stops Toy Dualsabers from reflecting energy projectiles diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index e89f377cfaf4..c2a1690d158c 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -780,7 +780,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 /obj/item/highfrequencyblade/get_block_chance(mob/living/carbon/human/wielder, atom/movable/hitby, damage, attack_type, armor_penetration) if((attack_type == PROJECTILE_ATTACK) && wielded) - return TRUE + return 100 . = ..() diff --git a/code/game/objects/structures/beds_chairs/chair.dm b/code/game/objects/structures/beds_chairs/chair.dm index 9e5036d222fa..f0706668849b 100644 --- a/code/game/objects/structures/beds_chairs/chair.dm +++ b/code/game/objects/structures/beds_chairs/chair.dm @@ -368,7 +368,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/chair/stool/bar, 0) /obj/item/chair/get_block_chance(mob/living/carbon/human/wielder, atom/movable/hitby, damage, attack_type, armor_penetration) . = ..() if(prob(50) && ((attack_type == UNARMED_ATTACK) || (attack_type == LEAP_ATTACK))) - return TRUE + return 100 /obj/item/chair/block_feedback(mob/living/carbon/human/wielder, attack_text, attack_type, do_message = TRUE, do_sound = TRUE) if(do_message) diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm index 88d2819b21e0..60c61e229ad9 100644 --- a/code/modules/antagonists/cult/cult_items.dm +++ b/code/modules/antagonists/cult/cult_items.dm @@ -37,11 +37,10 @@ Striking a noncultist, however, will tear their flesh."} AddComponent(/datum/component/cult_ritual_item, span_cult(examine_text)) -/obj/item/melee/cultblade/dagger/get_block_chance(mob/living/carbon/human/wielder, atom/movable/hitby, damage, attack_type, armor_penetration) - if(IS_CULTIST(wielder) && attack_type != PROJECTILE_ATTACK) - return ..() - - return FALSE +/obj/item/melee/cultblade/dagger/can_block_attack(mob/living/carbon/human/wielder, atom/movable/hitby, attack_type) + if(attack_type == PROJECTILE_ATTACK) + return FALSE + return ..() /obj/item/melee/cultblade/dagger/block_feedback(mob/living/carbon/human/wielder, attack_text, attack_type, do_message = TRUE, do_sound = TRUE) if(do_message) @@ -78,7 +77,7 @@ Striking a noncultist, however, will tear their flesh."} . = ..() AddComponent(/datum/component/butchering, 40, 100) -/obj/item/melee/cultblade/get_block_chance(mob/living/carbon/human/wielder, atom/movable/hitby, damage, attack_type, armor_penetration) +/obj/item/melee/cultblade/can_block_attack(mob/living/carbon/human/wielder, atom/movable/hitby, attack_type) if(IS_CULTIST(wielder)) return ..() @@ -278,6 +277,7 @@ Striking a noncultist, however, will tear their flesh."} holder.apply_status_effect(/datum/status_effect/sword_spin) sword.spinning = TRUE sword.block_chance = 100 + sword.block_angle = 180 sword.slowdown += 1.5 addtimer(CALLBACK(src, PROC_REF(stop_spinning)), 50) holder?.update_mob_action_buttons() @@ -285,6 +285,7 @@ Striking a noncultist, however, will tear their flesh."} /datum/action/innate/cult/spin2win/proc/stop_spinning() sword.spinning = FALSE sword.block_chance = 50 + sword.block_angle = 45 sword.slowdown -= 1.5 sleep(sword.spin_cooldown) holder?.update_mob_action_buttons() @@ -775,8 +776,6 @@ Striking a noncultist, however, will tear their flesh."} qdel(src) /obj/item/melee/cultblade/halberd/get_block_chance(mob/living/carbon/human/wielder, atom/movable/hitby, damage, attack_type, armor_penetration) - if(!IS_CULTIST(wielder)) - return FALSE . = ..() if(wielded) . *= 2 diff --git a/code/modules/clothing/suits/reactive_armour.dm b/code/modules/clothing/suits/reactive_armour.dm index 6a1a9a57510a..4f82eb3998cf 100644 --- a/code/modules/clothing/suits/reactive_armour.dm +++ b/code/modules/clothing/suits/reactive_armour.dm @@ -67,7 +67,7 @@ update_icon() add_fingerprint(user) -/obj/item/clothing/suit/armor/reactive/get_block_chance(mob/living/carbon/human/wielder, atom/movable/hitby, damage, attack_type, armor_penetration) +/obj/item/clothing/suit/armor/reactive/can_block_attack(mob/living/carbon/human/wielder, atom/movable/hitby, attack_type) if(!active) return FALSE diff --git a/code/modules/projectiles/guns/magic/staff.dm b/code/modules/projectiles/guns/magic/staff.dm index 558b75d71c50..94c41149c96a 100644 --- a/code/modules/projectiles/guns/magic/staff.dm +++ b/code/modules/projectiles/guns/magic/staff.dm @@ -182,7 +182,7 @@ . = ..() AddComponent(/datum/component/butchering, 15, 125, 0, hitsound) -/obj/item/gun/magic/staff/spellblade/get_block_chance(mob/living/carbon/human/wielder, atom/movable/hitby, damage, attack_type, armor_penetration) +/obj/item/gun/magic/staff/spellblade/can_block_attack(mob/living/carbon/human/wielder, atom/movable/hitby, attack_type) if(attack_type == PROJECTILE_ATTACK) return FALSE diff --git a/code/modules/religion/sparring/ceremonial_gear.dm b/code/modules/religion/sparring/ceremonial_gear.dm index 8860706ff2ca..2c5d11816db2 100644 --- a/code/modules/religion/sparring/ceremonial_gear.dm +++ b/code/modules/religion/sparring/ceremonial_gear.dm @@ -42,10 +42,12 @@ force = old_force throwforce = old_throwforce -/obj/item/ceremonial_blade/get_block_chance(mob/living/carbon/human/wielder, atom/movable/hitby, damage, attack_type, armor_penetration) +/obj/item/ceremonial_blade/can_block_attack(mob/living/carbon/human/wielder, atom/movable/hitby, attack_type) if(attack_type != MELEE_ATTACK || !ishuman(hitby.loc)) - return ..() + return FALSE + return ..() +/obj/item/ceremonial_blade/get_block_chance(mob/living/carbon/human/wielder, atom/movable/hitby, damage, attack_type, armor_penetration) . = ..() if(HAS_TRAIT(hitby.loc, TRAIT_SPARRING)) //becomes 30 block diff --git a/daedalus.dme b/daedalus.dme index acba9598a0f6..f2a13c5ed015 100644 --- a/daedalus.dme +++ b/daedalus.dme @@ -342,6 +342,7 @@ #include "code\__HELPERS\_lists.dm" #include "code\__HELPERS\_logging.dm" #include "code\__HELPERS\_string_lists.dm" +#include "code\__HELPERS\_type2type.dm" #include "code\__HELPERS\admin.dm" #include "code\__HELPERS\ai.dm" #include "code\__HELPERS\areas.dm" @@ -355,6 +356,7 @@ #include "code\__HELPERS\clients.dm" #include "code\__HELPERS\cmp.dm" #include "code\__HELPERS\colors.dm" +#include "code\__HELPERS\combat_helpers.dm" #include "code\__HELPERS\config.dm" #include "code\__HELPERS\construction.dm" #include "code\__HELPERS\dates.dm" @@ -408,7 +410,6 @@ #include "code\__HELPERS\time.dm" #include "code\__HELPERS\traits.dm" #include "code\__HELPERS\turfs.dm" -#include "code\__HELPERS\type2type.dm" #include "code\__HELPERS\type_processing.dm" #include "code\__HELPERS\typelists.dm" #include "code\__HELPERS\varset_callback.dm"