diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm
index c89c563cf11..5727a024149 100644
--- a/code/__defines/misc.dm
+++ b/code/__defines/misc.dm
@@ -233,6 +233,7 @@
#define PROJECTILE_CONTINUE -1 //if the projectile should continue flying after calling bullet_act()
#define PROJECTILE_FORCE_MISS -2 //if the projectile should treat the attack as a miss (suppresses attack and admin logs) - only applies to mobs.
#define PROJECTILE_DODGED -3 //this is similar to the above, but the check and message is run on the mob, instead of on the projectile code. basically just has a unique message
+#define PROJECTILE_STOPPED -4 //stops the projectile completely, as if a shield absorbed it
//Camera capture modes
#define CAPTURE_MODE_REGULAR 0 //Regular polaroid camera mode
diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm
index 244799a7098..cc31ada747b 100644
--- a/code/defines/obj/weapon.dm
+++ b/code/defines/obj/weapon.dm
@@ -86,7 +86,7 @@
if (targetIsHuman)
var/mob/living/carbon/human/targethuman = target
armorpercent = targethuman.get_blocked_ratio(target_zone, BRUTE, damage = force)*100
- wasblocked = targethuman.check_shields(force, src, user, target_zone, null) //returns 1 if it's a block
+ wasblocked = targethuman.check_shields(force, src, user, target_zone, null)
var/damageamount = force
diff --git a/code/game/gamemodes/technomancer/devices/shield_armor.dm b/code/game/gamemodes/technomancer/devices/shield_armor.dm
index 40a9bd90f70..6316e6779b4 100644
--- a/code/game/gamemodes/technomancer/devices/shield_armor.dm
+++ b/code/game/gamemodes/technomancer/devices/shield_armor.dm
@@ -27,10 +27,10 @@
..()
spark(src, 5, cardinal)
-/obj/item/clothing/suit/armor/shield/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
+/obj/item/clothing/suit/armor/shield/handle_shield(mob/user, var/on_back, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
//Since this is a pierce of armor that is passive, we do not need to check if the user is incapacitated.
if(!active)
- return 0
+ return FALSE
var/modified_block_percentage = block_percentage
@@ -65,7 +65,7 @@
spark(src, 5, cardinal)
playsound(src, 'sound/weapons/blade.ogg', 50, 1)
- return 0 // This shield does not block all damage, so returning 0 is needed to tell the game to apply the new damage.
+ return FALSE // This shield does not block all damage, so returning 0 is needed to tell the game to apply the new damage.
/obj/item/clothing/suit/armor/shield/attack_self(mob/user)
active = !active
diff --git a/code/game/gamemodes/technomancer/devices/tesla_armor.dm b/code/game/gamemodes/technomancer/devices/tesla_armor.dm
index 8803bc590c3..95fda406d08 100644
--- a/code/game/gamemodes/technomancer/devices/tesla_armor.dm
+++ b/code/game/gamemodes/technomancer/devices/tesla_armor.dm
@@ -21,7 +21,7 @@
var/normal_icon_state = "tesla_armor_0"
var/cooldown_to_charge = 15 SECONDS
-/obj/item/clothing/suit/armor/tesla/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
+/obj/item/clothing/suit/armor/tesla/handle_shield(mob/user, var/on_back, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
//First, some retaliation.
if(active)
if(istype(damage_source, /obj/item/projectile))
@@ -46,8 +46,8 @@
addtimer(CALLBACK(src, .proc/recharge, user), cooldown_to_charge)
visible_message("\The [user]'s [src.name] blocks [attack_text]!")
update_icon()
- return 1
- return 0
+ return PROJECTILE_STOPPED
+ return FALSE
/obj/item/clothing/suit/armor/tesla/proc/recharge(var/mob/user)
ready = TRUE
diff --git a/code/game/gamemodes/technomancer/spells/reflect.dm b/code/game/gamemodes/technomancer/spells/reflect.dm
index 1bb277b37cc..b713c02ca63 100644
--- a/code/game/gamemodes/technomancer/spells/reflect.dm
+++ b/code/game/gamemodes/technomancer/spells/reflect.dm
@@ -26,16 +26,16 @@
to_chat(owner, "Your shield expires!")
return ..()
-/obj/item/spell/reflect/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
+/obj/item/spell/reflect/handle_shield(mob/user, var/on_back, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
if(user.incapacitated())
- return 0
+ return FALSE
var/damage_to_energy_cost = (damage_to_energy_multiplier * damage)
if(!pay_energy(damage_to_energy_cost))
to_chat(owner, "Your shield fades due to lack of energy!")
qdel(src)
- return 0
+ return FALSE
//block as long as they are not directly behind us
var/bad_arc = reverse_direction(user.dir) //arc of directions from which we cannot block
@@ -85,5 +85,5 @@
spawn(2 SECONDS) //To ensure that most or all of a burst fire cycle is reflected.
to_chat(owner, "Your shield fades due being used up!")
qdel(src)
- return 1
- return 0
+ return PROJECTILE_STOPPED
+ return FALSE
\ No newline at end of file
diff --git a/code/game/gamemodes/technomancer/spells/shield.dm b/code/game/gamemodes/technomancer/spells/shield.dm
index b403e4e0805..31a253a9e75 100644
--- a/code/game/gamemodes/technomancer/spells/shield.dm
+++ b/code/game/gamemodes/technomancer/spells/shield.dm
@@ -21,9 +21,9 @@
. = ..()
set_light(3, 2, l_color = "#006AFF")
-/obj/item/spell/shield/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
+/obj/item/spell/shield/handle_shield(mob/user, var/on_back, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
if(user.incapacitated())
- return 0
+ return FALSE
var/damage_to_energy_cost = damage_to_energy_multiplier * damage
@@ -41,7 +41,7 @@
if(!pay_energy(damage_to_energy_cost))
to_chat(owner, "Your shield fades due to lack of energy!")
qdel(src)
- return 0
+ return FALSE
//block as long as they are not directly behind us
var/bad_arc = reverse_direction(user.dir) //arc of directions from which we cannot block
@@ -50,5 +50,5 @@
spark(src, 3, cardinal)
playsound(src, 'sound/weapons/blade.ogg', 50, 1)
adjust_instability(2)
- return 1
- return 0
+ return PROJECTILE_STOPPED
+ return FALSE
\ No newline at end of file
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 32b00537d9e..b86c58ffcfb 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -530,12 +530,11 @@ var/list/global/slot_flags_enumeration = list(
attack_self(usr)
//RETURN VALUES
-//handle_shield should return a positive value to indicate that the attack is blocked and should be prevented.
-//If a negative value is returned, it should be treated as a special return value for bullet_act() and handled appropriately.
-//For non-projectile attacks this usually means the attack is blocked.
+//handle_shield
+//Return a negative value corresponding to the degree an attack is blocked. PROJECTILE_STOPPED stops the attack entirely, and is the default for projectile and non-projectile attacks
//Otherwise should return 0 to indicate that the attack is not affected in any way.
/obj/item/proc/handle_shield(mob/user, var/on_back, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
- return 0
+ return FALSE
/obj/item/proc/can_shield_back()
return
diff --git a/code/game/objects/items/weapons/material/swords.dm b/code/game/objects/items/weapons/material/swords.dm
index 16dec2374aa..0f628f72fb3 100644
--- a/code/game/objects/items/weapons/material/swords.dm
+++ b/code/game/objects/items/weapons/material/swords.dm
@@ -32,8 +32,8 @@
if(default_parry_check(user, attacker, damage_source) && prob(parry_chance * parry_bonus))
user.visible_message("\The [user] parries [attack_text] with \the [src]!")
playsound(user.loc, 'sound/weapons/bladeparry.ogg', 50, 1)
- return 1
- return 0
+ return PROJECTILE_STOPPED
+ return FALSE
/obj/item/material/sword/perform_technique(var/mob/living/carbon/human/target, var/mob/living/carbon/human/user, var/target_zone)
var/armor_reduction = target.get_blocked_ratio(target_zone, BRUTE, DAM_EDGE|DAM_SHARP, damage = force)*100
diff --git a/code/game/objects/items/weapons/material/twohanded.dm b/code/game/objects/items/weapons/material/twohanded.dm
index c704c2ded0f..f8cfc2d3e08 100644
--- a/code/game/objects/items/weapons/material/twohanded.dm
+++ b/code/game/objects/items/weapons/material/twohanded.dm
@@ -89,8 +89,8 @@
if(wielded && default_parry_check(user, attacker, damage_source) && prob(parry_chance))
user.visible_message("\The [user] parries [attack_text] with \the [src]!")
playsound(user.loc, /decl/sound_category/punchmiss_sound, 50, 1)
- return 1
- return 0
+ return PROJECTILE_STOPPED
+ return FALSE
/obj/item/material/twohanded/update_icon()
icon_state = "[base_icon][wielded]"
diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm
index 15c34aae441..a9ccaab6b37 100644
--- a/code/game/objects/items/weapons/melee/energy.dm
+++ b/code/game/objects/items/weapons/melee/energy.dm
@@ -65,17 +65,15 @@
/obj/item/melee/energy/handle_shield(mob/user, var/on_back, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
if(active && default_parry_check(user, attacker, damage_source) && prob(50))
user.visible_message("\The [user] parries [attack_text] with \the [src]!")
-
spark(src, 5)
playsound(user.loc, 'sound/weapons/blade.ogg', 50, 1)
- return 1
+ return PROJECTILE_STOPPED
else
-
if(!active)
- return 0 //turn it on first!
+ return FALSE //turn it on first!
if(user.incapacitated())
- return 0
+ return FALSE
//block as long as they are not directly behind us
var/bad_arc = reverse_direction(user.dir) //arc of directions from which we cannot block
@@ -90,7 +88,7 @@
visible_message("\The [user]'s [src.name] overloads!")
deactivate()
shield_power = initial(shield_power)
- return 0
+ return FALSE
if(istype(damage_source, /obj/item/projectile/energy) || istype(damage_source, /obj/item/projectile/beam))
var/obj/item/projectile/P = damage_source
@@ -112,7 +110,7 @@
return PROJECTILE_CONTINUE // complete projectile permutation
else
user.visible_message("\The [user] blocks [attack_text] with \the [src]!")
- return 1
+ return PROJECTILE_STOPPED
else if(istype(damage_source, /obj/item/projectile/bullet) && can_block_bullets)
var/reflectchance = (base_reflectchance) - round(damage/3)
@@ -120,7 +118,7 @@
reflectchance /= 2
if(prob(reflectchance))
user.visible_message("\The [user] blocks [attack_text] with \the [src]!")
- return 1
+ return PROJECTILE_STOPPED
/obj/item/melee/energy/get_print_info()
. = ..()
diff --git a/code/game/objects/items/weapons/shields.dm b/code/game/objects/items/weapons/shields.dm
index 0ba75c8ca3c..84649f5c308 100644
--- a/code/game/objects/items/weapons/shields.dm
+++ b/code/game/objects/items/weapons/shields.dm
@@ -41,7 +41,7 @@
/obj/item/shield/handle_shield(mob/user, var/on_back, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
if(user.incapacitated())
- return 0
+ return FALSE
var/shield_dir = reverse_dir[user.dir]
if(on_back)
@@ -52,8 +52,8 @@
if(check_shield_arc(user, bad_arc, damage_source, attacker))
if(prob(get_block_chance(user, damage, damage_source, attacker)))
user.visible_message("\The [user] blocks [attack_text] with \the [src]!")
- return 1
- return 0
+ return PROJECTILE_STOPPED
+ return FALSE
/obj/item/shield/can_shield_back()
return TRUE
@@ -148,10 +148,10 @@
/obj/item/shield/energy/handle_shield(mob/user, var/on_back, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
if(!active)
- return 0 //turn it on first!
+ return FALSE //turn it on first!
if(user.incapacitated())
- return 0
+ return FALSE
if(.)
spark(user.loc, 5)
@@ -178,7 +178,7 @@
w_class = ITEMSIZE_TINY
playsound(user, 'sound/weapons/saberoff.ogg', 50, 1)
shield_power = initial(shield_power)
- return 0
+ return FALSE
if(istype(damage_source, /obj/item/projectile/energy) || istype(damage_source, /obj/item/projectile/beam))
var/obj/item/projectile/P = damage_source
@@ -198,10 +198,10 @@
return PROJECTILE_CONTINUE // complete projectile permutation
else
user.visible_message("\The [user] blocks [attack_text] with \the [src]!")
- return 1
+ return PROJECTILE_STOPPED
else
user.visible_message("\The [user] blocks [attack_text] with \the [src]!")
- return 1
+ return PROJECTILE_STOPPED
/obj/item/shield/energy/get_block_chance(mob/user, var/damage, atom/damage_source = null, mob/attacker = null)
if(istype(damage_source, /obj/item/projectile))
@@ -304,9 +304,9 @@
/obj/item/shield/riot/tact/handle_shield(mob/user)
if(!active)
- return 0 //turn it on first!
- . = ..()
+ return FALSE //turn it on first!
+ . = ..()
if(.)
if(.) playsound(user.loc, 'sound/weapons/genhit.ogg', 50, 1)
diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm
index 0ebdbbb1f97..6ccbb45912f 100644
--- a/code/modules/clothing/suits/armor.dm
+++ b/code/modules/clothing/suits/armor.dm
@@ -168,7 +168,7 @@
user.forceMove(picked)
return PROJECTILE_FORCE_MISS
- return 0
+ return FALSE
/obj/item/clothing/suit/armor/reactive/attack_self(mob/user as mob)
src.active = !( src.active )
diff --git a/code/modules/holodeck/HolodeckObjects.dm b/code/modules/holodeck/HolodeckObjects.dm
index 53bcae8cc34..97996674d3f 100644
--- a/code/modules/holodeck/HolodeckObjects.dm
+++ b/code/modules/holodeck/HolodeckObjects.dm
@@ -272,8 +272,8 @@
spark(user.loc, 5)
playsound(user.loc, 'sound/weapons/blade.ogg', 50, 1)
- return 1
- return 0
+ return PROJECTILE_STOPPED
+ return FALSE
/obj/item/holo/esword/New()
if(!item_color)
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index c4c05b35977..1c76a0f5049 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -165,15 +165,15 @@ emp_act
for(var/obj/item/shield in list(l_hand, r_hand, wear_suit, back))
if(!shield)
continue
- if(!shield.can_shield_back())
- continue
var/is_on_back = FALSE
if(back && back == shield)
+ if(!shield.can_shield_back())
+ continue
is_on_back = TRUE
. = shield.handle_shield(src, is_on_back, damage, damage_source, attacker, def_zone, attack_text)
if(.)
return
- return 0
+ return FALSE
/mob/living/carbon/human/emp_act(severity)
if(isipc(src))
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 1657ca84e52..8ca0f3e7ca0 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -480,8 +480,7 @@
else if(grabstate >= GRAB_AGGRESSIVE)
damage_mult = 1.5
P.damage *= damage_mult
- //you can't miss at point blank..
- P.can_miss = 1
+ P.point_blank = TRUE
/obj/item/gun/proc/process_accuracy(obj/projectile, mob/user, atom/target, acc_mod, dispersion)
var/obj/item/projectile/P = projectile
diff --git a/code/modules/projectiles/guns/projectile/revolver.dm b/code/modules/projectiles/guns/projectile/revolver.dm
index e60d6a1caaa..416d67137fc 100644
--- a/code/modules/projectiles/guns/projectile/revolver.dm
+++ b/code/modules/projectiles/guns/projectile/revolver.dm
@@ -274,5 +274,5 @@
if(default_parry_check(user, attacker, damage_source) && prob(20))
user.visible_message(SPAN_DANGER("\The [user] parries [attack_text] with \the [src]!"))
playsound(user.loc, "punchmiss", 50, 1)
- return TRUE
+ return PROJECTILE_STOPPED
return FALSE
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 3b9a0090712..74b447bae91 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -23,7 +23,7 @@
var/dispersion = 0.0
//used for shooting at blank range, you shouldn't be able to miss
- var/can_miss = 0
+ var/point_blank = FALSE
//Effects
var/damage = 10
@@ -190,19 +190,26 @@
return TRUE
result = target_mob.bullet_act(src, def_zone)
- if(result == PROJECTILE_FORCE_MISS && (can_miss == 0)) //if you're shooting at point blank you can't miss.
- if(!silenced)
- target_mob.visible_message("\The [src] misses [target_mob] narrowly!")
- playsound(target_mob, /decl/sound_category/bulletflyby_sound, 50, 1)
- return FALSE
-
- if(result == PROJECTILE_DODGED)
- return FALSE
+ switch(result)
+ if(PROJECTILE_FORCE_MISS)
+ if(!point_blank)
+ if(!silenced)
+ target_mob.visible_message("\The [src] misses [target_mob] narrowly!")
+ playsound(target_mob, /decl/sound_category/bulletflyby_sound, 50, 1)
+ return FALSE
+ if(PROJECTILE_DODGED)
+ return FALSE
+ if(PROJECTILE_STOPPED)
+ return TRUE
var/impacted_organ = parse_zone(def_zone)
- if(istype(target_mob, /mob/living/simple_animal))
+ if(isanimal(target_mob))
var/mob/living/simple_animal/SA = target_mob
impacted_organ = pick(SA.organ_names)
+ else if(ishuman(target_mob))
+ var/mob/living/carbon/human/H = target_mob
+ var/obj/item/organ/external/E = H.organs_by_name[impacted_organ]
+ impacted_organ = E.name
//hit messages
if(silenced)
to_chat(target_mob, "You've been hit in the [impacted_organ] by \a [src]!")
diff --git a/html/changelogs/geeves-shield_fix.yml b/html/changelogs/geeves-shield_fix.yml
new file mode 100644
index 00000000000..1004775d248
--- /dev/null
+++ b/html/changelogs/geeves-shield_fix.yml
@@ -0,0 +1,7 @@
+author: Geeves
+
+delete-after: True
+
+changes:
+ - bugfix: "Fixed a bug that caused technomancer shields to entirely not work."
+ - tweak: "Getting hit by a projectile will now properly say the limb name instead of the attack zone name."
\ No newline at end of file