diff --git a/code/modules/mob/living/carbon/alien/humanoid/queen.dm b/code/modules/mob/living/carbon/alien/humanoid/queen.dm
index 1333bc4399..6141a97c12 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/queen.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/queen.dm
@@ -13,7 +13,7 @@
var/alt_inhands_file = 'icons/mob/alienqueen.dmi'
-/mob/living/carbon/alien/humanoid/royal/can_inject()
+/mob/living/carbon/alien/humanoid/royal/can_inject(mob/user, error_msg, target_zone, penetrate_thick = FALSE, bypass_immunity = FALSE)
return 0
/mob/living/carbon/alien/humanoid/royal/queen
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 72b7b580f7..9142ed6b22 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -453,7 +453,7 @@
return ret
// Living mobs use can_inject() to make sure that the mob is not syringe-proof in general.
-/mob/living/proc/can_inject()
+/mob/living/proc/can_inject(mob/user, error_msg, target_zone, penetrate_thick = FALSE, bypass_immunity = FALSE)
return TRUE
/mob/living/is_injectable(allowmobs = TRUE)
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 33c66079d5..e5881848d5 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -151,7 +151,7 @@
for(var/key in alarm_types_clear)
alarm_types_clear[key] = 0
-/mob/living/silicon/can_inject(mob/user, error_msg)
+/mob/living/silicon/can_inject(mob/user, error_msg, target_zone, penetrate_thick = FALSE, bypass_immunity = FALSE)
if(error_msg)
to_chat(user, "[p_their(TRUE)] outer shell is too tough.")
return FALSE
diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm
index f509ad0b10..ca87deac3d 100644
--- a/code/modules/reagents/reagent_containers/hypospray.dm
+++ b/code/modules/reagents/reagent_containers/hypospray.dm
@@ -362,30 +362,14 @@
return
/obj/item/hypospray/mkii/afterattack(atom/target, mob/user, proximity)
- if(!vial)
+ if(!vial || !proximity || !isliving(target))
+ return
+ var/mob/living/L = target
+
+ if(!L.reagents || !L.can_inject(user, TRUE, user.zone_selected, penetrates))
return
- if(!proximity)
- return
-
- if(!ismob(target))
- return
-
- var/mob/living/L
- if(isliving(target))
- L = target
- if(!penetrates && !L.can_inject(user, 1)) //This check appears another four times, since otherwise the penetrating sprays will break in do_mob.
- return
-
- if(!L && !target.is_injectable()) //only checks on non-living mobs, due to how can_inject() handles
- to_chat(user, "You cannot directly fill [target]!")
- return
-
- if(target.reagents.total_volume >= target.reagents.maximum_volume)
- to_chat(user, "[target] is full.")
- return
-
- if(ishuman(L))
+ if(iscarbon(L))
var/obj/item/bodypart/affecting = L.get_bodypart(check_zone(user.zone_selected))
if(!affecting)
to_chat(user, "The limb is missing!")
@@ -394,84 +378,42 @@
to_chat(user, "Medicine won't work on a robotic limb!")
return
+ //Always log attemped injections for admins
var/contained = vial.reagents.log_list()
log_combat(user, L, "attemped to inject", src, addition="which had [contained]")
-//Always log attemped injections for admins
- if(vial != null)
- switch(mode)
- if(HYPO_INJECT)
- if(L) //living mob
- if(L != user)
- L.visible_message("[user] is trying to inject [L] with [src]!", \
- "[user] is trying to inject [L] with [src]!")
- if(!do_mob(user, L, inject_wait))
- return
- if(!penetrates && !L.can_inject(user, 1))
- return
- if(!vial.reagents.total_volume)
- return
- if(L.reagents.total_volume >= L.reagents.maximum_volume)
- return
- L.visible_message("[user] uses the [src] on [L]!", \
- "[user] uses the [src] on [L]!")
- else
- if(!do_mob(user, L, inject_self))
- return
- if(!penetrates && !L.can_inject(user, 1))
- return
- if(!vial.reagents.total_volume)
- return
- if(L.reagents.total_volume >= L.reagents.maximum_volume)
- return
- log_attack("[user.name] ([user.ckey]) applied [src] to [L.name] ([L.ckey]), which had [contained] (INTENT: [uppertext(user.a_intent)]) (MODE: [src.mode])")
- L.log_message("applied [src] to themselves ([contained]).", INDIVIDUAL_ATTACK_LOG)
- var/fraction = min(vial.amount_per_transfer_from_this/vial.reagents.total_volume, 1)
- vial.reagents.reaction(L, INJECT, fraction)
- vial.reagents.trans_to(target, vial.amount_per_transfer_from_this)
- if(vial.amount_per_transfer_from_this >= 15)
- playsound(loc,'sound/items/hypospray_long.ogg',50, 1, -1)
- if(vial.amount_per_transfer_from_this < 15)
- playsound(loc, pick('sound/items/hypospray.ogg','sound/items/hypospray2.ogg'), 50, 1, -1)
- to_chat(user, "You inject [vial.amount_per_transfer_from_this] units of the solution. The hypospray's cartridge now contains [vial.reagents.total_volume] units.")
-
- if(HYPO_SPRAY)
- if(L) //living mob
- if(L != user)
- L.visible_message("[user] is trying to spray [L] with [src]!", \
- "[user] is trying to spray [L] with [src]!")
- if(!do_mob(user, L, spray_wait))
- return
- if(!penetrates && !L.can_inject(user, 1))
- return
- if(!vial.reagents.total_volume)
- return
- if(L.reagents.total_volume >= L.reagents.maximum_volume)
- return
- L.visible_message("[user] uses the [src] on [L]!", \
- "[user] uses the [src] on [L]!")
- else
- if(!do_mob(user, L, spray_self))
- return
- if(!penetrates && !L.can_inject(user, 1))
- return
- if(!vial.reagents.total_volume)
- return
- if(L.reagents.total_volume >= L.reagents.maximum_volume)
- return
- log_attack("[user.name] ([user.ckey]) applied [src] to [L.name] ([L.ckey]), which had [contained] (INTENT: [uppertext(user.a_intent)]) (MODE: [src.mode])")
- L.log_message("applied [src] to themselves ([contained]).", INDIVIDUAL_ATTACK_LOG)
- var/fraction = min(vial.amount_per_transfer_from_this/vial.reagents.total_volume, 1)
- vial.reagents.reaction(L, PATCH, fraction)
- vial.reagents.trans_to(target, vial.amount_per_transfer_from_this)
- if(vial.amount_per_transfer_from_this >= 15)
- playsound(loc,'sound/items/hypospray_long.ogg',50, 1, -1)
- if(vial.amount_per_transfer_from_this < 15)
- playsound(loc, pick('sound/items/hypospray.ogg','sound/items/hypospray2.ogg'), 50, 1, -1)
- to_chat(user, "You spray [vial.amount_per_transfer_from_this] units of the solution. The hypospray's cartridge now contains [vial.reagents.total_volume] units.")
- else
- to_chat(user, "[src] doesn't work here!")
+ if(!vial)
+ to_chat(user, "[src] doesn't have any vial installed!")
return
+ if(vial.reagents.total_volume)
+ to_chat(user, "[src]'s vial is empty!")
+ return
+
+ var/fp_verb = mode == HYPO_SPRAY ? "spray" : "inject"
+ var/method = mode == HYPO_SPRAY ? TOUCH : INJECT
+
+ if(L != user)
+ L.visible_message("[user] is trying to [fp_verb] [L] with [src]!", \
+ "[user] is trying to [fp_verb] you with [src]!")
+ if(!do_mob(user, L, inject_wait, extra_checks = CALLBACK(L, /mob/living/proc/can_inject, user, FALSE, user.zone_selected, penetrates))
+ return
+ if(!vial.reagents.total_volume)
+ return
+ log_attack("[user.name] ([user.ckey]) applied [src] to [L.name] ([L.ckey]), which had [contained] (INTENT: [uppertext(user.a_intent)]) (MODE: [mode])")
+ if(L != user)
+ L.visible_message("[user] uses the [src] on [L]!", \
+ "[user] uses the [src] on you!")
+ else
+ L.log_message("applied [src] to themselves ([contained]).", INDIVIDUAL_ATTACK_LOG)
+
+ var/fraction = min(vial.amount_per_transfer_from_this/vial.reagents.total_volume, 1)
+ vial.reagents.reaction(L, method, fraction)
+ vial.reagents.trans_to(target, vial.amount_per_transfer_from_this)
+ if(vial.amount_per_transfer_from_this >= 15)
+ playsound(loc,'sound/items/hypospray_long.ogg',50, 1, -1)
+ if(vial.amount_per_transfer_from_this < 15)
+ playsound(loc, pick('sound/items/hypospray.ogg','sound/items/hypospray2.ogg'), 50, 1, -1)
+ to_chat(user, "You [fp_verb] [vial.amount_per_transfer_from_this] units of the solution. The hypospray's cartridge now contains [vial.reagents.total_volume] units.")
/obj/item/hypospray/mkii/attack_self(mob/living/user)
if(user)