diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 9404b57df8f..f8ed791c3f4 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -410,9 +410,6 @@ GLOBAL_LIST_INIT(pda_styles, sortList(list(MONO, VT, ORBITRON, SHARE))) #define MAX_PROC_DEPTH 195 // 200 proc calls deep and shit breaks, this is a bit lower to give some safety room -#define SYRINGE_DRAW 0 -#define SYRINGE_INJECT 1 - //gold slime core spawning #define NO_SPAWN 0 #define HOSTILE_SPAWN 1 diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm index 08714ae174a..be938ea3a18 100644 --- a/code/modules/hydroponics/hydroponics.dm +++ b/code/modules/hydroponics/hydroponics.dm @@ -520,12 +520,6 @@ if(IS_EDIBLE(O) || istype(O, /obj/item/reagent_containers)) // Syringe stuff (and other reagent containers now too) var/obj/item/reagent_containers/reagent_source = O - if(istype(reagent_source, /obj/item/reagent_containers/syringe)) - var/obj/item/reagent_containers/syringe/syr = reagent_source - if(syr.mode != 1) - to_chat(user, "You can't get any extract out of this plant." ) - return - if(!reagent_source.reagents.total_volume) to_chat(user, "[reagent_source] is empty!") return 1 @@ -548,8 +542,6 @@ if(istype(reagent_source, /obj/item/reagent_containers/syringe/)) var/obj/item/reagent_containers/syringe/syr = reagent_source visi_msg="[user] injects [target] with [syr]" - if(syr.reagents.total_volume <= syr.amount_per_transfer_from_this) - syr.mode = 0 // Beakers, bottles, buckets, etc. if(reagent_source.is_drainable()) playsound(loc, 'sound/effects/slosh.ogg', 25, TRUE) @@ -741,6 +733,12 @@ else return ..() +/obj/machinery/hydroponics/attackby_secondary(obj/item/weapon, mob/user, params) + if (istype(weapon, /obj/item/reagent_containers/syringe)) + to_chat(user, "You can't get any extract out of this plant.") + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return SECONDARY_ATTACK_CALL_NORMAL + /obj/machinery/hydroponics/can_be_unfasten_wrench(mob/user, silent) if (!unwrenchable) // case also covered by NODECONSTRUCT checks in default_unfasten_wrench return CANT_UNFASTEN diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index 6ccfb9729c8..36c4982b97c 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -35,6 +35,11 @@ /obj/item/reagent_containers/Destroy() return ..() +/obj/item/reagent_containers/attack(mob/living/M, mob/living/user, params) + if (!user.combat_mode) + return + return ..() + /obj/item/reagent_containers/proc/on_reagents_del(datum/reagents/reagents) SIGNAL_HANDLER UnregisterSignal(reagents, list(COMSIG_REAGENTS_NEW_REAGENT, COMSIG_REAGENTS_ADD_REAGENT, COMSIG_REAGENTS_DEL_REAGENT, COMSIG_REAGENTS_REM_REAGENT, COMSIG_PARENT_QDELETING)) diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index a13f550ac3e..417d42a605a 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -8,9 +8,8 @@ icon_state = "0" worn_icon_state = "pen" amount_per_transfer_from_this = 5 - possible_transfer_amounts = list() + possible_transfer_amounts = list(5, 10, 15) volume = 15 - var/mode = SYRINGE_DRAW var/busy = FALSE // needed for delayed drawing of blood var/proj_piercing = 0 //does it pierce through thick clothes when shot with syringe gun custom_materials = list(/datum/material/iron=10, /datum/material/glass=20) @@ -18,138 +17,109 @@ custom_price = PAYCHECK_EASY * 0.5 sharpness = SHARP_POINTY -/obj/item/reagent_containers/syringe/Initialize() - . = ..() - if(list_reagents) //syringe starts in inject mode if its already got something inside - mode = SYRINGE_INJECT - update_icon() - -/obj/item/reagent_containers/syringe/ComponentInitialize() - . = ..() - AddElement(/datum/element/update_icon_updates_onmob) - -/obj/item/reagent_containers/syringe/pickup(mob/user) - ..() - update_icon() - -/obj/item/reagent_containers/syringe/dropped(mob/user) - ..() - update_icon() - -/obj/item/reagent_containers/syringe/attack_self(mob/user) - mode = !mode - update_icon() - -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/reagent_containers/syringe/attack_hand() - . = ..() - update_icon() - -/obj/item/reagent_containers/syringe/attack_paw(mob/user) - return attack_hand(user) - /obj/item/reagent_containers/syringe/attackby(obj/item/I, mob/user, params) return -/obj/item/reagent_containers/syringe/afterattack(atom/target, mob/user , proximity) - . = ..() +/obj/item/reagent_containers/syringe/proc/try_syringe(atom/target, mob/user, proximity) if(busy) - return + return FALSE if(!proximity) - return + return FALSE if(!target.reagents) - return + return FALSE - var/mob/living/L if(isliving(target)) - L = target - if(!L.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE)) - return + var/mob/living/living_target = target + if(!living_target.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE)) + return FALSE // chance of monkey retaliation SEND_SIGNAL(target, COMSIG_LIVING_TRY_SYRINGE, user) + return TRUE - switch(mode) - if(SYRINGE_DRAW) +/obj/item/reagent_containers/syringe/afterattack(atom/target, mob/user, proximity) + . = ..() - if(reagents.total_volume >= reagents.maximum_volume) - to_chat(user, "The syringe is full.") + if (!try_syringe(target, user, proximity)) + return + + var/contained = reagents.log_list() + log_combat(user, target, "attempted to inject", src, addition="which had [contained]") + + if(!reagents.total_volume) + to_chat(user, "[src] is empty! Right-click to draw.") + return + + if(!isliving(target) && !target.is_injectable(user)) + 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(isliving(target)) + var/mob/living/living_target = target + if(!living_target.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE)) + return + if(living_target != user) + living_target.visible_message("[user] is trying to inject [living_target]!", \ + "[user] is trying to inject you!") + if(!do_mob(user, living_target, 3 SECONDS, extra_checks = CALLBACK(living_target, /mob/living/proc/try_inject, user, null, INJECT_TRY_SHOW_ERROR_MESSAGE))) return - - if(L) //living mob - var/drawn_amount = reagents.maximum_volume - reagents.total_volume - if(target != user) - target.visible_message("[user] is trying to take a blood sample from [target]!", \ - "[user] is trying to take a blood sample from you!") - busy = TRUE - if(!do_mob(user, target, extra_checks=CALLBACK(L, /mob/living/proc/try_inject, user, null, INJECT_TRY_SHOW_ERROR_MESSAGE))) - busy = FALSE - return - if(reagents.total_volume >= reagents.maximum_volume) - return - busy = FALSE - if(L.transfer_blood_to(src, drawn_amount)) - user.visible_message("[user] takes a blood sample from [L].") - else - to_chat(user, "You are unable to draw any blood from [L]!") - - else //if not mob - if(!target.reagents.total_volume) - to_chat(user, "[target] is empty!") - return - - if(!target.is_drawable(user)) - to_chat(user, "You cannot directly remove reagents from [target]!") - return - - var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this, transfered_by = user) // transfer from, transfer to - who cares? - - to_chat(user, "You fill [src] with [trans] units of the solution. It now contains [reagents.total_volume] units.") - if (reagents.total_volume >= reagents.maximum_volume) - mode=!mode - update_icon() - - if(SYRINGE_INJECT) - // Always log attemped injections for admins - var/contained = reagents.log_list() - log_combat(user, target, "attempted to inject", src, addition="which had [contained]") - if(!reagents.total_volume) - to_chat(user, "[src] is empty!") return - - if(!L && !target.is_injectable(user)) //only checks on non-living mobs, due to how can_inject() handles - to_chat(user, "You cannot directly fill [target]!") + if(living_target.reagents.total_volume >= living_target.reagents.maximum_volume) return + living_target.visible_message("[user] injects [living_target] with the syringe!", \ + "[user] injects you with the syringe!") - if(target.reagents.total_volume >= target.reagents.maximum_volume) - to_chat(user, "[target] is full.") - return + if (living_target == user) + living_target.log_message("injected themselves ([contained]) with [name]", LOG_ATTACK, color="orange") + else + log_combat(user, living_target, "injected", src, addition="which had [contained]") + reagents.trans_to(target, amount_per_transfer_from_this, transfered_by = user, methods = INJECT) + to_chat(user, "You inject [amount_per_transfer_from_this] units of the solution. The syringe now contains [reagents.total_volume] units.") - if(L) //living mob - if(!L.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE)) - return - if(L != user) - L.visible_message("[user] is trying to inject [L]!", \ - "[user] is trying to inject you!") - if(!do_mob(user, L, extra_checks=CALLBACK(L, /mob/living/proc/try_inject, user, null, INJECT_TRY_SHOW_ERROR_MESSAGE))) - return - if(!reagents.total_volume) - return - if(L.reagents.total_volume >= L.reagents.maximum_volume) - return - L.visible_message("[user] injects [L] with the syringe!", \ - "[user] injects you with the syringe!") +/obj/item/reagent_containers/syringe/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters) + if (!try_syringe(target, user, proximity_flag)) + return SECONDARY_ATTACK_CONTINUE_CHAIN - if(L != user) - log_combat(user, L, "injected", src, addition="which had [contained]") - else - L.log_message("injected themselves ([contained]) with [src.name]", LOG_ATTACK, color="orange") - reagents.trans_to(target, amount_per_transfer_from_this, transfered_by = user, methods = INJECT) - to_chat(user, "You inject [amount_per_transfer_from_this] units of the solution. The syringe now contains [reagents.total_volume] units.") - if (reagents.total_volume <= 0 && mode==SYRINGE_INJECT) - mode = SYRINGE_DRAW - update_icon() + if(reagents.total_volume >= reagents.maximum_volume) + to_chat(user, "[src] is full.") + return SECONDARY_ATTACK_CONTINUE_CHAIN + + if(isliving(target)) + var/mob/living/living_target = target + var/drawn_amount = reagents.maximum_volume - reagents.total_volume + if(target != user) + target.visible_message("[user] is trying to take a blood sample from [target]!", \ + "[user] is trying to take a blood sample from you!") + busy = TRUE + if(!do_mob(user, target, 3 SECONDS, extra_checks = CALLBACK(living_target, /mob/living/proc/try_inject, user, null, INJECT_TRY_SHOW_ERROR_MESSAGE))) + busy = FALSE + return SECONDARY_ATTACK_CONTINUE_CHAIN + if(reagents.total_volume >= reagents.maximum_volume) + return SECONDARY_ATTACK_CONTINUE_CHAIN + busy = FALSE + if(living_target.transfer_blood_to(src, drawn_amount)) + user.visible_message("[user] takes a blood sample from [living_target].") + else + to_chat(user, "You are unable to draw any blood from [living_target]!") + else + if(!target.reagents.total_volume) + to_chat(user, "[target] is empty!") + return SECONDARY_ATTACK_CONTINUE_CHAIN + + if(!target.is_drawable(user)) + to_chat(user, "You cannot directly remove reagents from [target]!") + return SECONDARY_ATTACK_CONTINUE_CHAIN + + var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this, transfered_by = user) // transfer from, transfer to - who cares? + + to_chat(user, "You fill [src] with [trans] units of the solution. It now contains [reagents.total_volume] units.") + + return SECONDARY_ATTACK_CONTINUE_CHAIN /* * On accidental consumption, inject the eater with 2/3rd of the syringe and reveal it @@ -177,14 +147,6 @@ var/mutable_appearance/filling_overlay = mutable_appearance('icons/obj/reagentfillings.dmi', "syringe[rounded_vol]") filling_overlay.color = mix_color_from_reagents(reagents.reagent_list) . += filling_overlay - if(ismob(loc)) - var/injoverlay - switch(mode) - if (SYRINGE_DRAW) - injoverlay = "draw" - if (SYRINGE_INJECT) - injoverlay = "inject" - . += injoverlay ///Used by update_icon() and update_overlays() /obj/item/reagent_containers/syringe/proc/get_rounded_vol() @@ -258,12 +220,14 @@ name = "bluespace syringe" desc = "An advanced syringe that can hold 60 units of chemicals." amount_per_transfer_from_this = 20 + possible_transfer_amounts = list(10, 20, 30, 40, 50, 60) volume = 60 /obj/item/reagent_containers/syringe/piercing name = "piercing syringe" desc = "A diamond-tipped syringe that pierces armor when launched at high velocity. It can hold up to 10 units." volume = 10 + possible_transfer_amounts = list(5, 10) proj_piercing = 1 /obj/item/reagent_containers/syringe/spider_extract diff --git a/code/modules/unit_tests/metabolizing.dm b/code/modules/unit_tests/metabolizing.dm index f7b689574c6..36c12693426 100644 --- a/code/modules/unit_tests/metabolizing.dm +++ b/code/modules/unit_tests/metabolizing.dm @@ -72,10 +72,7 @@ syringe.volume = meth.addiction_threshold syringe.amount_per_transfer_from_this = meth.addiction_threshold syringe.reagents.add_reagent(meth.type, meth.addiction_threshold) - - syringe.mode = SYRINGE_INJECT - syringe_user.set_combat_mode(TRUE) - syringe.afterattack(syringe_user, syringe_user, TRUE) + syringe.melee_attack_chain(syringe_user, syringe_user) syringe_user.Life() @@ -90,10 +87,7 @@ // One half pill pill_two.reagents.add_reagent(meth.type, (meth.addiction_threshold * 0.5) + 1) pill_two.attack(pill_syringe_user, pill_syringe_user) - - pill_syringe_user.set_combat_mode(TRUE) - syringe.mode = SYRINGE_INJECT - syringe.afterattack(pill_syringe_user, pill_syringe_user, TRUE) + syringe.melee_attack_chain(pill_syringe_user, pill_syringe_user) // Set the metabolism efficiency to 1.0 so it transfers all reagents to the body in one go. pill_belly = pill_syringe_user.getorganslot(ORGAN_SLOT_STOMACH) diff --git a/code/modules/unit_tests/reagent_mod_expose.dm b/code/modules/unit_tests/reagent_mod_expose.dm index 3fe02e044d4..d893fef405f 100644 --- a/code/modules/unit_tests/reagent_mod_expose.dm +++ b/code/modules/unit_tests/reagent_mod_expose.dm @@ -50,8 +50,7 @@ // INJECT syringe.reagents.add_reagent(/datum/reagent/method_patch_test, 1) - syringe.mode = SYRINGE_INJECT - syringe.afterattack(human, human, TRUE) + syringe.melee_attack_chain(human, human) TEST_ASSERT_EQUAL(human.health, 80, "Human health did not update after injection from syringe") /datum/unit_test/reagent_mob_expose/Destroy() diff --git a/icons/obj/syringe.dmi b/icons/obj/syringe.dmi index df2e20cf5f1..2981293d1a8 100644 Binary files a/icons/obj/syringe.dmi and b/icons/obj/syringe.dmi differ