diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm
index 583ceadd10b..e442b3a03a5 100644
--- a/code/modules/reagents/reagent_containers/hypospray.dm
+++ b/code/modules/reagents/reagent_containers/hypospray.dm
@@ -20,7 +20,7 @@
// reagents.add_reagent("tricordrazine", 30)
// return
-/obj/item/weapon/reagent_containers/hypospray/attack(mob/living/M as mob, mob/user as mob)
+/obj/item/weapon/reagent_containers/hypospray/attack(mob/living/M as mob, mob/user as mob, var/target_zone)
if(!reagents.total_volume)
user << "[src] is empty."
return
@@ -29,7 +29,7 @@
var/mob/living/carbon/human/H = M
if(istype(H))
- var/obj/item/organ/external/affected = H.get_organ(user.zone_sel.selecting)
+ var/obj/item/organ/external/affected = H.get_organ(target_zone)
if(!affected)
user << "\The [H] is missing that limb!"
return
@@ -37,9 +37,13 @@
user << "You cannot inject a robotic limb."
return
+ user.visible_message("[user] is trying to inject [target] with [src]!","You are trying to inject [M] with [src].")
+ if(H.run_armor_check(target_zone,"melee",0,"Your armor slows down the injection!","Your armor slows down the injection!"))
+ if(!do_mob(user, M, 60))
+ return
+
user.setClickCooldown(DEFAULT_QUICK_COOLDOWN)
user.do_attack_animation(M)
- user << "You inject [M] with [src]."
M << "You feel a tiny prick!"
playsound(src, 'sound/items/hypospray.ogg',25)
diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm
index 8e595221256..649b08192a7 100644
--- a/code/modules/reagents/reagent_containers/syringes.dm
+++ b/code/modules/reagents/reagent_containers/syringes.dm
@@ -25,268 +25,266 @@
var/visible_name = "a syringe"
var/time = 30
- on_reagent_change()
- update_icon()
-
- pickup(mob/user)
- ..()
- update_icon()
-
- dropped(mob/user)
- ..()
- update_icon()
-
- attack_self(mob/user as mob)
-
- switch(mode)
- if(SYRINGE_DRAW)
- mode = SYRINGE_INJECT
- if(SYRINGE_INJECT)
- mode = SYRINGE_DRAW
- if(SYRINGE_BROKEN)
- return
- update_icon()
-
- attack_hand()
- ..()
- update_icon()
-
- attackby(obj/item/I as obj, mob/user as mob)
- return
-
- afterattack(obj/target, mob/user, proximity)
- if(!proximity || !target.reagents)
- return
-
- if(mode == SYRINGE_BROKEN)
- user << "This syringe is broken!"
- return
-
- if(user.a_intent == I_HURT && ismob(target))
- if((CLUMSY in user.mutations) && prob(50))
- target = user
- syringestab(target, user)
- return
-
-
- switch(mode)
- if(SYRINGE_DRAW)
-
- if(!reagents.get_free_space())
- user << "The syringe is full."
- mode = SYRINGE_INJECT
- return
-
- if(ismob(target))//Blood!
- if(reagents.has_reagent("blood"))
- user << "There is already a blood sample in this syringe."
- return
- if(istype(target, /mob/living/carbon))
- if(istype(target, /mob/living/carbon/slime))
- user << "You are unable to locate any blood."
- return
- var/amount = reagents.get_free_space()
- var/mob/living/carbon/T = target
- if(!T.dna)
- user << "You are unable to locate any blood. (To be specific, your target seems to be missing their DNA datum)."
- return
- if(NOCLONE in T.mutations) //target done been et, no more blood in him
- user << "You are unable to locate any blood."
- return
-
- var/datum/reagent/B
- if(istype(T, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = T
- if(H.species && H.species.flags & NO_BLOOD)
- H.reagents.trans_to_obj(src, amount)
- else
- B = T.take_blood(src, amount)
- else
- B = T.take_blood(src,amount)
-
- if (B)
- reagents.reagent_list += B
- reagents.update_total()
- on_reagent_change()
- reagents.handle_reactions()
- user << "You take a blood sample from [target]."
- for(var/mob/O in viewers(4, user))
- O.show_message("[user] takes a blood sample from [target].", 1)
-
- else //if not mob
- if(!target.reagents.total_volume)
- user << "[target] is empty."
- return
-
- if(!target.is_open_container() && !istype(target, /obj/structure/reagent_dispensers) && !istype(target, /obj/item/slime_extract))
- user << "You cannot directly remove reagents from this object."
- return
-
- var/trans = target.reagents.trans_to_obj(src, amount_per_transfer_from_this)
- user << "You fill the syringe with [trans] units of the solution."
- update_icon()
-
- if(!reagents.get_free_space())
- mode = SYRINGE_INJECT
- update_icon()
-
- if(SYRINGE_INJECT)
- if(!reagents.total_volume)
- user << "The syringe is empty."
- mode = SYRINGE_DRAW
- return
- if(istype(target, /obj/item/weapon/implantcase/chem))
- return
-
- if(!target.is_open_container() && !ismob(target) && !istype(target, /obj/item/weapon/reagent_containers/food) && !istype(target, /obj/item/slime_extract) && !istype(target, /obj/item/clothing/mask/smokable/cigarette) && !istype(target, /obj/item/weapon/storage/fancy/cigarettes))
- user << "You cannot directly fill this object."
- return
- if(!target.reagents.get_free_space())
- user << "[target] is full."
- return
-
- var/mob/living/carbon/human/H = target
- if(istype(H))
- var/obj/item/organ/external/affected = H.get_organ(user.zone_sel.selecting)
- if(!affected)
- user << "\The [H] is missing that limb!"
- return
- else if(affected.status & ORGAN_ROBOT)
- user << "You cannot inject a robotic limb."
- return
-
- if(ismob(target) && target != user)
-
- var/injtime = time //Injecting through a voidsuit takes longer due to needing to find a port.
-
- if(istype(H))
- if(H.wear_suit)
- if(istype(H.wear_suit, /obj/item/clothing/suit/space))
- injtime = injtime * 2
- else if(!H.can_inject(user, 1))
- return
- if(isvaurca(H))
- injtime = injtime * 2
-
- else if(isliving(target))
-
- var/mob/living/M = target
- if(!M.can_inject(user, 1))
- return
-
- if(injtime == time)
- user.visible_message("[user] is trying to inject [target] with [visible_name]!")
- else
- if(isvaurca(H))
- user.visible_message("[user] begins hunting for an injection port on [target]'s carapace!")
- else
- user.visible_message("[user] begins hunting for an injection port on [target]'s suit!")
-
- user.setClickCooldown(DEFAULT_QUICK_COOLDOWN)
- user.do_attack_animation(target)
-
- if(!do_mob(user, target, injtime))
- return
-
- user.visible_message("[user] injects [target] with the syringe!")
-
- var/trans
- if(ismob(target))
- var/contained = reagentlist()
- trans = reagents.trans_to_mob(target, amount_per_transfer_from_this, CHEM_BLOOD)
- admin_inject_log(user, target, src, contained, trans)
- else
- trans = reagents.trans_to(target, amount_per_transfer_from_this)
- user << "You inject [trans] units of the solution. The syringe now contains [src.reagents.total_volume] units."
- if (reagents.total_volume <= 0 && mode == SYRINGE_INJECT)
- mode = SYRINGE_DRAW
- update_icon()
-
- return
-
+/obj/item/weapon/reagent_containers/syringe/on_reagent_change()
update_icon()
- cut_overlays()
- if(mode == SYRINGE_BROKEN)
- icon_state = "broken"
+/obj/item/weapon/reagent_containers/syringe/pickup(mob/user)
+ ..()
+ update_icon()
+
+/obj/item/weapon/reagent_containers/syringe/dropped(mob/user)
+ ..()
+ update_icon()
+
+/obj/item/weapon/reagent_containers/syringe/attack_self(mob/user as mob)
+ switch(mode)
+ if(SYRINGE_DRAW)
+ mode = SYRINGE_INJECT
+ if(SYRINGE_INJECT)
+ mode = SYRINGE_DRAW
+ if(SYRINGE_BROKEN)
return
+ update_icon()
- var/rounded_vol = round(reagents.total_volume, round(reagents.maximum_volume / 3))
- if(ismob(loc))
- var/injoverlay
- switch(mode)
- if (SYRINGE_DRAW)
- injoverlay = "draw"
- if (SYRINGE_INJECT)
- injoverlay = "inject"
- add_overlay(injoverlay)
- icon_state = "[rounded_vol]"
- item_state = "syringe_[rounded_vol]"
+/obj/item/weapon/reagent_containers/syringe/attack_hand()
+ ..()
+ update_icon()
- if(reagents.total_volume)
- filling = image('icons/obj/reagentfillings.dmi', src, "syringe10")
+/obj/item/weapon/reagent_containers/syringe/attackby(obj/item/I as obj, mob/user as mob)
+ return
- filling.icon_state = "syringe[rounded_vol]"
+/obj/item/weapon/reagent_containers/syringe/afterattack(obj/target, mob/user, proximity)
+ if(!proximity || !target.reagents)
+ return
- filling.color = reagents.get_color()
- add_overlay(filling)
+ if(mode == SYRINGE_BROKEN)
+ user << "This syringe is broken!"
+ return
- proc/syringestab(mob/living/carbon/target as mob, mob/living/carbon/user as mob)
+ if(user.a_intent == I_HURT && ismob(target))
+ if((CLUMSY in user.mutations) && prob(50))
+ target = user
+ syringestab(target, user)
+ return
- if(istype(target, /mob/living/carbon/human))
+
+ switch(mode)
+ if(SYRINGE_DRAW)
+
+ if(!reagents.get_free_space())
+ user << "The syringe is full."
+ mode = SYRINGE_INJECT
+ return
+
+ if(ismob(target))//Blood!
+ if(reagents.has_reagent("blood"))
+ user << "There is already a blood sample in this syringe."
+ return
+ if(istype(target, /mob/living/carbon))
+ if(istype(target, /mob/living/carbon/slime))
+ user << "You are unable to locate any blood."
+ return
+ var/amount = reagents.get_free_space()
+ var/mob/living/carbon/T = target
+ if(!T.dna)
+ user << "You are unable to locate any blood. (To be specific, your target seems to be missing their DNA datum)."
+ return
+ if(NOCLONE in T.mutations) //target done been et, no more blood in him
+ user << "You are unable to locate any blood."
+ return
+
+ var/datum/reagent/B
+ if(istype(T, /mob/living/carbon/human))
+ var/mob/living/carbon/human/H = T
+ if(H.species && H.species.flags & NO_BLOOD)
+ H.reagents.trans_to_obj(src, amount)
+ else
+ B = T.take_blood(src, amount)
+ else
+ B = T.take_blood(src,amount)
+
+ if (B)
+ reagents.reagent_list += B
+ reagents.update_total()
+ on_reagent_change()
+ reagents.handle_reactions()
+ user << "You take a blood sample from [target]."
+ for(var/mob/O in viewers(4, user))
+ O.show_message("[user] takes a blood sample from [target].", 1)
+
+ else //if not mob
+ if(!target.reagents.total_volume)
+ user << "[target] is empty."
+ return
+
+ if(!target.is_open_container() && !istype(target, /obj/structure/reagent_dispensers) && !istype(target, /obj/item/slime_extract))
+ user << "You cannot directly remove reagents from this object."
+ return
+
+ var/trans = target.reagents.trans_to_obj(src, amount_per_transfer_from_this)
+ user << "You fill the syringe with [trans] units of the solution."
+ update_icon()
+
+ if(!reagents.get_free_space())
+ mode = SYRINGE_INJECT
+ update_icon()
+
+ if(SYRINGE_INJECT)
+ if(!reagents.total_volume)
+ user << "The syringe is empty."
+ mode = SYRINGE_DRAW
+ return
+ if(istype(target, /obj/item/weapon/implantcase/chem))
+ return
+
+ if(!target.is_open_container() && !ismob(target) && !istype(target, /obj/item/weapon/reagent_containers/food) && !istype(target, /obj/item/slime_extract) && !istype(target, /obj/item/clothing/mask/smokable/cigarette) && !istype(target, /obj/item/weapon/storage/fancy/cigarettes))
+ user << "You cannot directly fill this object."
+ return
+ if(!target.reagents.get_free_space())
+ user << "[target] is full."
+ return
var/mob/living/carbon/human/H = target
+ if(istype(H))
+ var/obj/item/organ/external/affected = H.get_organ(user.zone_sel.selecting)
+ if(!affected)
+ user << "\The [H] is missing that limb!"
+ return
+ else if(affected.status & ORGAN_ROBOT)
+ user << "You cannot inject a robotic limb."
+ return
- var/target_zone = ran_zone(check_zone(user.zone_sel.selecting, target))
- var/obj/item/organ/external/affecting = H.get_organ(target_zone)
+ if(ismob(target) && target != user)
- if (!affecting || affecting.is_stump())
- user << "They are missing that limb!"
- return
+ var/injtime = time //Injecting through a voidsuit takes longer due to needing to find a port.
- var/hit_area = affecting.name
+ if(istype(H))
+ if(H.wear_suit)
+ if(istype(H.wear_suit, /obj/item/clothing/suit/space))
+ injtime = injtime * 2
+ else if(!H.can_inject(user, 1))
+ return
+ if(isvaurca(H))
+ injtime = injtime * 2
- if((user != target) && H.check_shields(7, src, user, "\the [src]"))
- return
+ else if(isliving(target))
- if (target != user && H.getarmor(target_zone, "melee") > 5 && prob(50))
- for(var/mob/O in viewers(world.view, user))
- O.show_message(text("[user] tries to stab [target] in \the [hit_area] with [src.name], but the attack is deflected by armor!"), 1)
- user.remove_from_mob(src)
- qdel(src)
+ var/mob/living/M = target
+ if(!M.can_inject(user, 1))
+ return
- user.attack_log += "\[[time_stamp()]\] Attacked [target.name] ([target.ckey]) with \the [src] (INTENT: HARM)."
- target.attack_log += "\[[time_stamp()]\] Attacked by [user.name] ([user.ckey]) with [src.name] (INTENT: HARM)."
- msg_admin_attack("[key_name_admin(user)] attacked [key_name_admin(target)] with [src.name] (INTENT: HARM) (JMP)",ckey=key_name(user),ckey_target=key_name(src))
+ if(injtime == time)
+ user.visible_message("[user] is trying to inject [target] with [visible_name]!")
+ else
+ if(isvaurca(H))
+ user.visible_message("[user] begins hunting for an injection port on [target]'s carapace!")
+ else
+ user.visible_message("[user] begins hunting for an injection port on [target]'s suit!")
- return
+ user.setClickCooldown(DEFAULT_QUICK_COOLDOWN)
+ user.do_attack_animation(target)
- user.visible_message("[user] stabs [target] in \the [hit_area] with [src.name]!")
+ if(!do_mob(user, target, injtime))
+ return
- if(affecting.take_damage(3))
- H.UpdateDamageIcon()
+ user.visible_message("[user] injects [target] with the syringe!")
- else
- user.visible_message("[user] stabs [target] with [src.name]!")
- target.take_organ_damage(3)// 7 is the same as crowbar punch
+ var/trans
+ if(ismob(target))
+ var/contained = reagentlist()
+ trans = reagents.trans_to_mob(target, amount_per_transfer_from_this, CHEM_BLOOD)
+ admin_inject_log(user, target, src, contained, trans)
+ else
+ trans = reagents.trans_to(target, amount_per_transfer_from_this)
+ user << "You inject [trans] units of the solution. The syringe now contains [src.reagents.total_volume] units."
+ if (reagents.total_volume <= 0 && mode == SYRINGE_INJECT)
+ mode = SYRINGE_DRAW
+ update_icon()
+
+ return
+
+/obj/item/weapon/reagent_containers/syringe/update_icon()
+ cut_overlays()
+
+ if(mode == SYRINGE_BROKEN)
+ icon_state = "broken"
+ return
+
+ var/rounded_vol = round(reagents.total_volume, round(reagents.maximum_volume / 3))
+ if(ismob(loc))
+ var/injoverlay
+ switch(mode)
+ if (SYRINGE_DRAW)
+ injoverlay = "draw"
+ if (SYRINGE_INJECT)
+ injoverlay = "inject"
+ add_overlay(injoverlay)
+ icon_state = "[rounded_vol]"
+ item_state = "syringe_[rounded_vol]"
+
+ if(reagents.total_volume)
+ filling = image('icons/obj/reagentfillings.dmi', src, "syringe10")
+
+ filling.icon_state = "syringe[rounded_vol]"
+
+ filling.color = reagents.get_color()
+ add_overlay(filling)
+
+/obj/item/weapon/reagent_containers/syringe/proc/syringestab(mob/living/carbon/target as mob, mob/living/carbon/user as mob)
+ if(istype(target, /mob/living/carbon/human))
+
+ var/mob/living/carbon/human/H = target
+
+ var/target_zone = ran_zone(check_zone(user.zone_sel.selecting, target))
+ var/obj/item/organ/external/affecting = H.get_organ(target_zone)
+
+ if (!affecting || affecting.is_stump())
+ user << "They are missing that limb!"
+ return
+
+ var/hit_area = affecting.name
+
+ if((user != target) && H.check_shields(7, src, user, "\the [src]"))
+ return
+
+ if (target != user && H.getarmor(target_zone, "melee") > 5 && prob(50))
+ for(var/mob/O in viewers(world.view, user))
+ O.show_message(text("[user] tries to stab [target] in \the [hit_area] with [src.name], but the attack is deflected by armor!"), 1)
+ user.remove_from_mob(src)
+ qdel(src)
+
+ user.attack_log += "\[[time_stamp()]\] Attacked [target.name] ([target.ckey]) with \the [src] (INTENT: HARM)."
+ target.attack_log += "\[[time_stamp()]\] Attacked by [user.name] ([user.ckey]) with [src.name] (INTENT: HARM)."
+ msg_admin_attack("[key_name_admin(user)] attacked [key_name_admin(target)] with [src.name] (INTENT: HARM) (JMP)",ckey=key_name(user),ckey_target=key_name(src))
+
+ return
+
+ user.visible_message("[user] stabs [target] in \the [hit_area] with [src.name]!")
+
+ if(affecting.take_damage(3))
+ H.UpdateDamageIcon()
+
+ else
+ user.visible_message("[user] stabs [target] with [src.name]!")
+ target.take_organ_damage(3)// 7 is the same as crowbar punch
- var/syringestab_amount_transferred = rand(0, (reagents.total_volume - 5)) //nerfed by popular demand
- var/contained_reagents = reagents.get_reagents()
- var/trans = reagents.trans_to_mob(target, syringestab_amount_transferred, CHEM_BLOOD)
- if(isnull(trans)) trans = 0
- admin_inject_log(user, target, src, contained_reagents, trans, violent=1)
- break_syringe(target, user)
+ var/syringestab_amount_transferred = rand(0, (reagents.total_volume - 5)) //nerfed by popular demand
+ var/contained_reagents = reagents.get_reagents()
+ var/trans = reagents.trans_to_mob(target, syringestab_amount_transferred, CHEM_BLOOD)
+ if(isnull(trans)) trans = 0
+ admin_inject_log(user, target, src, contained_reagents, trans, violent=1)
+ break_syringe(target, user)
- proc/break_syringe(mob/living/carbon/target, mob/living/carbon/user)
- desc += " It is broken."
- mode = SYRINGE_BROKEN
- if(target)
- add_blood(target)
- if(user)
- add_fingerprint(user)
- update_icon()
+/obj/item/weapon/reagent_containers/syringe/proc/break_syringe(mob/living/carbon/target, mob/living/carbon/user)
+ desc += " It is broken."
+ mode = SYRINGE_BROKEN
+ if(target)
+ add_blood(target)
+ if(user)
+ add_fingerprint(user)
+ update_icon()
/obj/item/weapon/reagent_containers/syringe/ld50_syringe
name = "Lethal Injection Syringe"
diff --git a/html/changelogs/Arrow769-hypospray.yml b/html/changelogs/Arrow769-hypospray.yml
new file mode 100644
index 00000000000..fae2af44831
--- /dev/null
+++ b/html/changelogs/Arrow769-hypospray.yml
@@ -0,0 +1,37 @@
+################################
+# Example Changelog File
+#
+# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
+#
+# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
+# When it is, any changes listed below will disappear.
+#
+# Valid Prefixes:
+# bugfix
+# wip (For works in progress)
+# tweak
+# soundadd
+# sounddel
+# rscadd (general adding of nice things)
+# rscdel (general deleting of nice things)
+# imageadd
+# imagedel
+# maptweak
+# spellcheck (typo fixes)
+# experiment
+# balance
+#################################
+
+# Your name.
+author: Arrow768
+
+# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
+delete-after: True
+
+# Any changes you've made. See valid prefix list above.
+# INDENT WITH TWO SPACES. NOT TABS. SPACES.
+# SCREW THIS UP AND IT WON'T WORK.
+# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
+# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
+changes:
+ - balance: "Injecting armored targets with the hypospray now takes a while."