diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm
index 714e011a29..2fdd6a98bc 100644
--- a/code/__DEFINES/combat.dm
+++ b/code/__DEFINES/combat.dm
@@ -228,21 +228,27 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
/// Attack outright missed because the target dodged. Should usually be combined with redirection passthrough or something (see martial arts)
#define BLOCK_TARGET_DODGED (1<<7)
/// Meta-flag for run_block/do_run_block : By default, BLOCK_SUCCESS tells do_run_block() to assume the attack is completely blocked and not continue the block chain. If this is present, it will continue to check other items in the chain rather than stopping.
-#define BLOCK_cONTINUE_CHAIN (1<<8)
+#define BLOCK_CONTINUE_CHAIN (1<<8)
/// For keys in associative list/block_return as we don't want to saturate our (somewhat) limited flags.
#define BLOCK_RETURN_REDIRECT_METHOD "REDIRECT_METHOD"
/// Pass through victim
#define REDIRECT_METHOD_PASSTHROUGH "passthrough"
- /// Reflect using normal angular/mirrorlike reflection
- #define REDIRECT_METHOD_REFLECT "reflect"
/// Deflect at randomish angle
#define REDIRECT_METHOD_DEFLECT "deflect"
- /// do not taser the bad man with the desword
+ /// reverse 180 angle, basically (as opposed to "realistic" wall reflections)
+ #define REDIRECT_METHOD_REFLECT "reflect"
+ /// "do not taser the bad man with the desword" - actually aims at the firer/attacker rather than just reversing
#define REDIRECT_METHOD_RETURN_TO_SENDER "no_you"
+/// These keys are generally only applied to the list if real_attack is FALSE. Used incase we want to make "smarter" mob AI in the future or something.
+/// Tells the caller how likely from 0 (none) to 100 (always) we are to reflect energy projectiles
+#define BLOCK_RETURN_REFLECT_PROJECTILE_CHANCE
+/// Tells the caller how likely we are to block attacks from 0 to 100 in general
+#define BLOCK_RETURN_NORMAL_BLOCK_CHANCE
+
/// Default if the above isn't set in the list.
-#define DEFAULT_REDIRECT_METHOD_PROJECTILE REDIRECT_METHOD_REFLECT
+#define DEFAULT_REDIRECT_METHOD_PROJECTILE REDIRECT_METHOD_DEFLECT
/// Block priorities
#define BLOCK_PRIORITY_HELD_ITEM 100
diff --git a/code/game/objects/items/grenades/grenade.dm b/code/game/objects/items/grenades/grenade.dm
index 85ec9ad634..c72813bec3 100644
--- a/code/game/objects/items/grenades/grenade.dm
+++ b/code/game/objects/items/grenades/grenade.dm
@@ -121,7 +121,7 @@
if(damage && !P.nodamage && (P.damage_type != STAMINA) && prob(15))
owner.visible_message("[attack_text] hits [owner]'s [src], setting it off! What a shot!")
prime()
- return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL | BLOCK_INTERRUPT_CHAIN
+ return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL
return ..()
/obj/item/proc/grenade_prime_react(obj/item/grenade/nade)
diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm
index dafb7430ae..66f85bb459 100644
--- a/code/game/objects/items/twohanded.dm
+++ b/code/game/objects/items/twohanded.dm
@@ -755,7 +755,7 @@
if(real_attack && (attack_type & ATTACK_TYPE_PROJECTILE))
owner.visible_message("Ranged attacks just make [owner] angrier!")
playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, 1)
- return BLOCK_SUCCESS | BLOCK_INTERRUPT_CHAIN | BLOCK_PHYSICAL_EXTERNAL
+ return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL
return ..()
//GREY TIDE
@@ -908,7 +908,7 @@
return BLOCK_SUCCESS | BLOCK_REDIRECTED | BLOCK_SHOULD_REDIRECT | BLOCK_PHYSICAL_EXTERNAL
else
owner.visible_message("[owner] parries [attack_text] with [src]!")
- return BLOCK_SUCCESS | BLOCK_PARRY
+ return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL
return NONE
/obj/item/twohanded/vibro_weapon/update_icon_state()
diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm
index 8746ac49a5..58c8aa2d8e 100644
--- a/code/game/objects/items/weaponry.dm
+++ b/code/game/objects/items/weaponry.dm
@@ -157,7 +157,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/obj/item/claymore/highlander/run_block(mob/living/owner, real_attack, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
if((attack_type & ATTACK_TYPE_PROJECTILE) && is_energy_reflectable_projectile(object))
- return BLOCK_SUCCESS | BLOCK_SHOULD_REDIRECT | BLOCK_PHYSICAL_EXTERNAL | BLOCK_REDIRECT
+ return BLOCK_SUCCESS | BLOCK_SHOULD_REDIRECT | BLOCK_PHYSICAL_EXTERNAL | BLOCK_REDIRECTED
return ..()
/obj/item/claymore/highlander/proc/add_notch(mob/living/user) //DYNAMIC CLAYMORE PROGRESSION SYSTEM - THIS IS THE FUTURE
@@ -583,14 +583,13 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
force = 12
throwforce = 15
-/obj/item/melee/baseball_bat/ablative/IsReflect()//some day this will reflect thrown items instead of lasers
- var/picksound = rand(1,2)
- var/turf = get_turf(src)
- if(picksound == 1)
- playsound(turf, 'sound/weapons/effects/batreflect1.ogg', 50, 1)
- if(picksound == 2)
- playsound(turf, 'sound/weapons/effects/batreflect2.ogg', 50, 1)
- return 1
+/obj/item/melee/baseball_bat/ablative/run_block(mob/living/owner, real_attack, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
+ //some day this will reflect thrown items instead of lasers
+ if(is_energy_reflectable_projectile(object) && (attack_type == ATTACK_TYPE_PROJECTILE))
+ var/turf = get_turf(src)
+ playsound(turf, pick('sound/weapons/effects/batreflect1.ogg', 'sound/weapons/effects/batreflect2.ogg'), 50, 1)
+ return BLOCK_SUCESS | BLOCK_SHOULD_REDIRECT | BLOCK_PHYSICAL_EXTERNAL | BLOCK_REDIRECTED
+ return ..()
/obj/item/melee/baseball_bat/ablative/syndi
name = "syndicate major league bat"
diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm
index 7d1bbeeddc..cc6ea983e8 100644
--- a/code/modules/antagonists/cult/cult_items.dm
+++ b/code/modules/antagonists/cult/cult_items.dm
@@ -725,19 +725,19 @@
playsound(T, 'sound/effects/glassbr3.ogg', 100)
qdel(src)
-/obj/item/twohanded/cult_spear/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
+/obj/item/twohanded/cult_spear/run_block(mob/living/owner, real_attack, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
if(wielded)
final_block_chance *= 2
if(prob(final_block_chance))
- if(attack_type & PROJECTILE_ATTACK)
+ if(attack_type & ATTACK_TYPE_PROJECTILE)
owner.visible_message("[owner] deflects [attack_text] with [src]!")
playsound(src, pick('sound/weapons/effects/ric1.ogg', 'sound/weapons/effects/ric2.ogg', 'sound/weapons/effects/ric3.ogg', 'sound/weapons/effects/ric4.ogg', 'sound/weapons/effects/ric5.ogg'), 100, 1)
- return TRUE
+ return BLOCK_SUCCESS | BLOCK_SHOULD_REDIRECT | BLOCK_REDIRECTED | BLOCK_PHYSICAL_EXTERNAL
else
playsound(src, 'sound/weapons/parry.ogg', 100, 1)
owner.visible_message("[owner] parries [attack_text] with [src]!")
- return TRUE
- return FALSE
+ return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL
+ return BLOCK_NONE
/datum/action/innate/cult/spear
name = "Bloody Bond"
@@ -936,10 +936,13 @@
hitsound = 'sound/weapons/smash.ogg'
var/illusions = 2
-/obj/item/shield/mirror/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
+/obj/item/shield/mirror/run_block(mob/living/owner, real_attack, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
+ if(!real_attack)
+ block_return[BLOCK_RETURN_REFLECT_PROJECTILE_CHANCE] = final_block_chance
+ return ..()
if(iscultist(owner))
- if(istype(hitby, /obj/item/projectile))
- var/obj/item/projectile/P = hitby
+ if(istype(object, /obj/item/projectile) && (attack_type == ATTACK_TYPE_PROJECTILE))
+ var/obj/item/projectile/P = object
if(P.damage >= 30)
var/turf/T = get_turf(owner)
T.visible_message("The sheer force from [P] shatters the mirror shield!")
@@ -947,11 +950,13 @@
playsound(T, 'sound/effects/glassbr3.ogg', 100)
owner.DefaultCombatKnockdown(25)
qdel(src)
- return FALSE
+ return BLOCK_NONE
if(P.is_reflectable)
- return FALSE //To avoid reflection chance double-dipping with block chance
+ if(prob(final_block_chance))
+ return BLOCK_SUCCESS | BLOCK_SHOULD_REDIRECT | BLOCK_PHYSICAL_EXTERNAL | BLOCK_REDIRECTED
+ return BLOCK_NONE //To avoid reflection chance double-dipping with block chance
. = ..()
- if(.)
+ if(. & BLOCK_SUCCESS)
playsound(src, 'sound/weapons/parry.ogg', 100, 1)
if(illusions > 0)
illusions--
@@ -966,7 +971,7 @@
E.Copy_Parent(owner, 70, 10)
E.GiveTarget(owner)
E.Goto(owner, owner.movement_delay(), E.minimum_distance)
- return TRUE
+ return
else
if(prob(50))
var/mob/living/simple_animal/hostile/illusion/H = new(owner.loc)
@@ -975,7 +980,7 @@
H.GiveTarget(owner)
H.move_to_delay = owner.movement_delay()
to_chat(owner, "[src] betrays you!")
- return FALSE
+ return BLOCK_NONE
/obj/item/shield/mirror/proc/readd()
illusions++
diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm
index 1bad198c73..a3d4cf367b 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -757,7 +757,11 @@
if(!allowed)
allowed = GLOB.advanced_hardsuit_allowed
-/obj/item/clothing/suit/space/hardsuit/shielded/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
+/obj/item/clothing/suit/space/hardsuit/shielded/run_block(mob/living/owner, real_attack, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
+ if(!real_attack)
+ if(current_charges > 0)
+ return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL
+ return BLOCK_NONE
recharge_cooldown = world.time + recharge_delay
if(current_charges > 0)
var/datum/effect_system/spark_spread/s = new
@@ -771,8 +775,8 @@
owner.visible_message("[owner]'s shield overloads!")
shield_state = "broken"
owner.update_inv_wear_suit()
- return 1
- return 0
+ return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL
+ return BLOCK_NONE
/obj/item/clothing/suit/space/hardsuit/shielded/Destroy()
STOP_PROCESSING(SSobj, src)
diff --git a/code/modules/clothing/suits/reactive_armour.dm b/code/modules/clothing/suits/reactive_armour.dm
index fb8d62e350..24280f953a 100644
--- a/code/modules/clothing/suits/reactive_armour.dm
+++ b/code/modules/clothing/suits/reactive_armour.dm
@@ -4,7 +4,6 @@
icon_state = "reactiveoff"
icon = 'icons/obj/clothing/suits.dmi'
w_class = WEIGHT_CLASS_BULKY
- var/hit_reaction_chance = 50
/obj/item/reactive_armour_shell/attackby(obj/item/I, mob/user, params)
..()
@@ -39,6 +38,7 @@
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
hit_reaction_chance = 50 // Only on the chest yet blocks all attacks?
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
+ var/hit_reaction_chance = 50
/obj/item/clothing/suit/armor/reactive/attack_self(mob/user)
active = !(active)
diff --git a/code/modules/clothing/under/color.dm b/code/modules/clothing/under/color.dm
index c02f78cb8f..cce41b9fc0 100644
--- a/code/modules/clothing/under/color.dm
+++ b/code/modules/clothing/under/color.dm
@@ -81,8 +81,9 @@
/obj/item/clothing/under/color/grey/glorf/run_block(mob/living/owner, real_attack, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
. = ..()
- if(real_attack)
- owner.forcesay(GLOB.hit_appends)
+ if(real_attack && ishuman(owner))
+ var/mob/living/human/H = owner
+ H.forcesay(GLOB.hit_appends)
/obj/item/clothing/under/color/blue
name = "blue jumpsuit"
diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index bf25bb9da8..d0b8c113b4 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -835,9 +835,9 @@
force = CLAMP((ghost_counter * 4), 0, 75)
user.visible_message("[user] strikes with the force of [ghost_counter] vengeful spirits!")
- ..()
+ return ..()
-/obj/item/melee/ghost_sword/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
+/obj/item/melee/ghost_sword/run_block(mob/living/owner, real_attack, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
var/ghost_counter = ghost_check()
final_block_chance += CLAMP((ghost_counter * 5), 0, 75)
owner.visible_message("[owner] is protected by a ring of [ghost_counter] ghosts!")
diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm
index 189af32da8..1bb545b8ea 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm
@@ -63,7 +63,7 @@
if(hit_atom)
if(isliving(hit_atom))
var/mob/living/L = hit_atom
- if(L.run_block(src, 0, "the [name]", attack_type = LEAP_ATTACK, 0, src) & BLOCK_SUCCESS)
+ if(L.run_block(src, 0, "the [name]", attack_type = ATTACK_TYPE_TACKLE, 0, src) & BLOCK_SUCCESS)
DefaultCombatKnockdown(40, 1, 1)
else
L.visible_message("[src] pounces on [L]!", "[src] pounces on you!")
diff --git a/code/modules/mob/living/living_block.dm b/code/modules/mob/living/living_block.dm
index 13e236a931..c3b9fc73f4 100644
--- a/code/modules/mob/living/living_block.dm
+++ b/code/modules/mob/living/living_block.dm
@@ -76,9 +76,15 @@
/// Block priority, higher means we check this higher in the "chain".
var/block_priority = BLOCK_PRIORITY_DEFAULT
+/// Runs block and returns flag for do_run_block to process.
/obj/item/proc/run_block(mob/living/owner, real_attack, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
SEND_SIGNAL(src, COMSIG_ITEM_RUN_BLOCK, args)
if(prob(final_block_chance))
owner.visible_message("[owner] blocks [attack_text] with [src]!")
return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL
return BLOCK_NONE
+
+/// Returns block information using list/block_return. Used for check_block() on mobs.
+/obj/item/proc/check_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
+ SEND_SIGNAL(src, COMSIG_ITEM_CHECK_BLOCK, args)
+ block_return[BLOCK_RETURN_NORMAL_BLOCK_CHANCE] = final_block_chance
diff --git a/code/modules/mob/living/silicon/silicon_defense.dm b/code/modules/mob/living/silicon/silicon_defense.dm
index 1c6784ab95..98d990e5ea 100644
--- a/code/modules/mob/living/silicon/silicon_defense.dm
+++ b/code/modules/mob/living/silicon/silicon_defense.dm
@@ -115,7 +115,7 @@
if(reflect_bullet_check(P, def_zone))
return -1 // complete projectile permutation
#warn implement blocktypes
- if(run_block(P, P.damage, "the [P.name]", PROJECTILE_ATTACK, P.armour_penetration) & BLOCK_SUCCESS)
+ if(run_block(P, P.damage, "the [P.name]", ATTACK_TYPE_PROJECTILE, P.armour_penetration) & BLOCK_SUCCESS)
P.on_hit(src, 100, def_zone)
return BULLET_ACT_BLOCK
if((P.damage_type == BRUTE || P.damage_type == BURN))
diff --git a/code/modules/mob/living/simple_animal/guardian/types/charger.dm b/code/modules/mob/living/simple_animal/guardian/types/charger.dm
index 10f7b6893f..9457c8153d 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/charger.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/charger.dm
@@ -54,7 +54,7 @@
var/blocked = FALSE
if(hasmatchingsummoner(hit_atom)) //if the summoner matches don't hurt them
blocked = TRUE
- if(L.run_block(src, 90, "[name]", attack_type = ATTACK_TYPE_LEAP, 0, src) & BLOCK_SUCCESS)
+ if(L.run_block(src, 90, "[name]", attack_type = ATTACK_TYPE_TACKLE, 0, src) & BLOCK_SUCCESS)
blocked = TRUE
if(!blocked)
L.drop_all_held_items()
diff --git a/code/modules/projectiles/guns/magic/staff.dm b/code/modules/projectiles/guns/magic/staff.dm
index c81880ab55..274a1c96f9 100644
--- a/code/modules/projectiles/guns/magic/staff.dm
+++ b/code/modules/projectiles/guns/magic/staff.dm
@@ -92,7 +92,7 @@
/obj/item/gun/magic/staff/spellblade/run_block(mob/living/owner, real_attack, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
// Do not block projectiles.
- if(attack_type & PROJECTILE_ATTACK)
+ if(attack_type & ATTACK_TYPE_PROJECTILE)
return BLOCK_NONE
return ..()
diff --git a/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm b/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm
index 5cf4abb5bf..a38f58b655 100644
--- a/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm
+++ b/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm
@@ -424,7 +424,7 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
if(hit_atom)
if(isliving(hit_atom))
var/mob/living/L = hit_atom
- if(L.run_block(0, "the [name]", src, attack_type = LEAP_ATTACK, 0, src) & BLOCK_SUCCESS)
+ if(L.run_block(0, "the [name]", src, attack_type = ATTACK_TYPE_TACKLE, 0, src) & BLOCK_SUCCESS)
DefaultCombatKnockdown(15, 1, 1)
else
L.visible_message("[src] pounces on [L]!", "[src] pounces on you!")