mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-09 16:05:07 +00:00
[MIRROR] Refactor can_inject, and introduce try_inject (#3300)
* Refactor can_inject, and introduce try_inject (#56816) Splits can_inject into can_inject and try_inject. The latter can perform side effects, while the former cannot. Moved the show_error bool parameter to a flag that try_inject checks. Changes the signature to can_inject(mob/user, target_zone, injection_flags). This was previously redefined in several places, making it impossible to use named parameters. This refactor now allows named parameters to be used, and thus avoiding the ugliness of TRUE, FALSE, FALSE in parameters. * Refactor can_inject, and introduce try_inject Co-authored-by: Mothblocks <35135081+Jared-Fogle@users.noreply.github.com>
This commit is contained in:
8
code/__DEFINES/injection.dm
Normal file
8
code/__DEFINES/injection.dm
Normal file
@@ -0,0 +1,8 @@
|
||||
/// This injection can penetrate through thick clothing.
|
||||
#define INJECT_CHECK_PENETRATE_THICK (1 << 0)
|
||||
|
||||
/// This injection bypasses species specific restrictions.
|
||||
#define INJECT_CHECK_IGNORE_SPECIES (1 << 1)
|
||||
|
||||
/// When trying this injection, show an error message if it fails.
|
||||
#define INJECT_TRY_SHOW_ERROR_MESSAGE (1 << 2)
|
||||
@@ -247,7 +247,7 @@
|
||||
|
||||
if(ishuman(victim)) // check to see if the limb is actually exposed
|
||||
var/mob/living/carbon/human/victim_human = victim
|
||||
if(!victim_human.can_inject(user, TRUE, limb.body_zone, ignore_species = TRUE))
|
||||
if(!victim_human.try_inject(user, limb.body_zone, INJECT_CHECK_IGNORE_SPECIES | INJECT_TRY_SHOW_ERROR_MESSAGE))
|
||||
return TRUE
|
||||
|
||||
INVOKE_ASYNC(src, .proc/tweezePluck, possible_tweezers, user)
|
||||
|
||||
@@ -296,7 +296,7 @@
|
||||
// & such may need to use bone gel but may be wearing a space suit for..... whatever reason a skeleton would wear a space suit for
|
||||
if(ishuman(victim))
|
||||
var/mob/living/carbon/human/victim_human = victim
|
||||
if(!victim_human.can_inject(user, TRUE, ignore_species = TRUE))
|
||||
if(!victim_human.try_inject(user, injection_flags = INJECT_CHECK_IGNORE_SPECIES | INJECT_TRY_SHOW_ERROR_MESSAGE))
|
||||
return TRUE
|
||||
|
||||
// lastly, treat them
|
||||
|
||||
@@ -151,7 +151,7 @@
|
||||
suture(I, user)
|
||||
|
||||
/datum/wound/slash/try_handling(mob/living/carbon/human/user)
|
||||
if(user.pulling != victim || user.zone_selected != limb.body_zone || !isfelinid(user) || !victim.can_inject(user, TRUE))
|
||||
if(user.pulling != victim || user.zone_selected != limb.body_zone || !isfelinid(user) || !victim.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE))
|
||||
return FALSE
|
||||
if(DOING_INTERACTION_WITH_TARGET(user, victim))
|
||||
to_chat(user, "<span class='warning'>You're already interacting with [victim]!</span>")
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
return
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/human/humantarget = target
|
||||
if (!humantarget.can_inject(user, 1))
|
||||
if (!humantarget.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE))
|
||||
return
|
||||
log_combat(user, target, "attempted to inject", src)
|
||||
|
||||
|
||||
@@ -38,17 +38,17 @@
|
||||
|
||||
/// In which we print the message that we're starting to heal someone, then we try healing them. Does the do_after whether or not it can actually succeed on a targeted mob
|
||||
/obj/item/stack/medical/proc/try_heal(mob/living/patient, mob/user, silent = FALSE)
|
||||
if(!patient.can_inject(user, TRUE))
|
||||
if(!patient.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE))
|
||||
return
|
||||
if(patient == user)
|
||||
if(!silent)
|
||||
user.visible_message("<span class='notice'>[user] starts to apply [src] on [user.p_them()]self...</span>", "<span class='notice'>You begin applying [src] on yourself...</span>")
|
||||
if(!do_mob(user, patient, self_delay, extra_checks=CALLBACK(patient, /mob/living/proc/can_inject, user, TRUE)))
|
||||
if(!do_mob(user, patient, self_delay, extra_checks=CALLBACK(patient, /mob/living/proc/try_inject, user, null, INJECT_TRY_SHOW_ERROR_MESSAGE)))
|
||||
return
|
||||
else if(other_delay)
|
||||
if(!silent)
|
||||
user.visible_message("<span class='notice'>[user] starts to apply [src] on [patient].</span>", "<span class='notice'>You begin applying [src] on [patient]...</span>")
|
||||
if(!do_mob(user, patient, other_delay, extra_checks=CALLBACK(patient, /mob/living/proc/can_inject, user, TRUE)))
|
||||
if(!do_mob(user, patient, other_delay, extra_checks=CALLBACK(patient, /mob/living/proc/try_inject, user, null, INJECT_TRY_SHOW_ERROR_MESSAGE)))
|
||||
return
|
||||
|
||||
if(heal(patient, user))
|
||||
|
||||
@@ -516,7 +516,7 @@
|
||||
/datum/plant_gene/trait/stinging/on_throw_impact(obj/item/food/grown/G, atom/target)
|
||||
if(isliving(target) && G.reagents && G.reagents.total_volume)
|
||||
var/mob/living/L = target
|
||||
if(L.reagents && L.can_inject(null, 0))
|
||||
if(L.reagents && L.can_inject())
|
||||
var/injecting_amount = max(1, G.seed.potency*0.2) // Minimum of 1, max of 20
|
||||
G.reagents.trans_to(L, injecting_amount, methods = INJECT)
|
||||
to_chat(target, "<span class='danger'>You are pricked by [G]!</span>")
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
// as a wise man once wrote: "pull over that ass too fat"
|
||||
REMOVE_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
|
||||
|
||||
/mob/living/carbon/alien/humanoid/royal/can_inject()
|
||||
/mob/living/carbon/alien/humanoid/royal/can_inject(mob/user, target_zone, injection_flags)
|
||||
return FALSE
|
||||
|
||||
/mob/living/carbon/alien/humanoid/royal/queen
|
||||
|
||||
@@ -184,7 +184,7 @@
|
||||
|
||||
/mob/living/carbon/attack_paw(mob/living/carbon/human/M, modifiers)
|
||||
|
||||
if(can_inject(M, TRUE))
|
||||
if(try_inject(M, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE))
|
||||
for(var/thing in diseases)
|
||||
var/datum/disease/D = thing
|
||||
if((D.spread_flags & DISEASE_SPREAD_CONTACT_SKIN) && prob(85))
|
||||
|
||||
@@ -527,25 +527,29 @@
|
||||
/mob/living/carbon/human/proc/canUseHUD()
|
||||
return (mobility_flags & MOBILITY_USE)
|
||||
|
||||
/mob/living/carbon/human/can_inject(mob/user, error_msg, target_zone, penetrate_thick = FALSE, ignore_species = FALSE)
|
||||
/mob/living/carbon/human/can_inject(mob/user, target_zone, injection_flags)
|
||||
. = TRUE // Default to returning true.
|
||||
if(user && !target_zone)
|
||||
target_zone = user.zone_selected
|
||||
// we may choose to ignore species trait pierce immunity in case we still want to check skellies for thick clothing without insta failing them (wounds)
|
||||
if(ignore_species)
|
||||
if(injection_flags & INJECT_CHECK_IGNORE_SPECIES)
|
||||
if(HAS_TRAIT_NOT_FROM(src, TRAIT_PIERCEIMMUNE, SPECIES_TRAIT))
|
||||
. = FALSE
|
||||
else if(HAS_TRAIT(src, TRAIT_PIERCEIMMUNE))
|
||||
. = FALSE
|
||||
var/obj/item/bodypart/the_part = get_bodypart(target_zone) || get_bodypart(BODY_ZONE_CHEST)
|
||||
// Loop through the clothing covering this bodypart and see if there's any thiccmaterials
|
||||
if(!penetrate_thick)
|
||||
if(!(injection_flags & INJECT_CHECK_PENETRATE_THICK))
|
||||
for(var/obj/item/clothing/iter_clothing in clothingonpart(the_part))
|
||||
if(iter_clothing.clothing_flags & THICKMATERIAL)
|
||||
. = FALSE
|
||||
break
|
||||
if(!. && error_msg && user)
|
||||
// Might need re-wording.
|
||||
|
||||
/mob/living/carbon/human/try_inject(mob/user, target_zone, injection_flags)
|
||||
. = ..()
|
||||
if(!. && (injection_flags & INJECT_TRY_SHOW_ERROR_MESSAGE) && user)
|
||||
var/obj/item/bodypart/the_part = get_bodypart(target_zone) || get_bodypart(BODY_ZONE_CHEST)
|
||||
|
||||
to_chat(user, "<span class='alert'>There is no exposed flesh or thin material on [p_their()] [the_part.name].</span>")
|
||||
|
||||
/mob/living/carbon/human/assess_threat(judgement_criteria, lasercolor = "", datum/callback/weaponcheck=null)
|
||||
|
||||
@@ -249,7 +249,7 @@
|
||||
if(M.limb_destroyer)
|
||||
dismembering_strike(M, affecting.body_zone)
|
||||
|
||||
if(can_inject(M, 1, affecting))//Thick suits can stop monkey bites.
|
||||
if(try_inject(M, affecting, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE))//Thick suits can stop monkey bites.
|
||||
if(..()) //successful monkey bite, this handles disease contraction.
|
||||
var/damage = rand(M.dna.species.punchdamagelow, M.dna.species.punchdamagehigh)
|
||||
if(!damage)
|
||||
|
||||
@@ -620,10 +620,30 @@
|
||||
ret |= F.contents
|
||||
return ret
|
||||
|
||||
// Living mobs use can_inject() to make sure that the mob is not syringe-proof in general.
|
||||
/mob/living/proc/can_inject()
|
||||
/**
|
||||
* Returns whether or not the mob can be injected. Should not perform any side effects.
|
||||
*
|
||||
* Arguments:
|
||||
* * user - The user trying to inject the mob.
|
||||
* * target_zone - The zone being targeted.
|
||||
* * injection_flags - A bitflag for extra properties to check.
|
||||
* Check __DEFINES/injection.dm for more details, specifically the ones prefixed INJECT_CHECK_*.
|
||||
*/
|
||||
/mob/living/proc/can_inject(mob/user, target_zone, injection_flags)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Like can_inject, but it can perform side effects.
|
||||
*
|
||||
* Arguments:
|
||||
* * user - The user trying to inject the mob.
|
||||
* * target_zone - The zone being targeted.
|
||||
* * injection_flags - A bitflag for extra properties to check. Check __DEFINES/injection.dm for more details.
|
||||
* Check __DEFINES/injection.dm for more details. Unlike can_inject, the INJECT_TRY_* defines will behave differently.
|
||||
*/
|
||||
/mob/living/proc/try_inject(mob/user, target_zone, injection_flags)
|
||||
return can_inject(user, target_zone, injection_flags)
|
||||
|
||||
/mob/living/is_injectable(mob/user, allowmobs = TRUE)
|
||||
return (allowmobs && reagents && can_inject(user))
|
||||
|
||||
|
||||
@@ -160,11 +160,14 @@
|
||||
for(var/key in alarm_types_clear)
|
||||
alarm_types_clear[key] = 0
|
||||
|
||||
/mob/living/silicon/can_inject(mob/user, error_msg)
|
||||
if(error_msg)
|
||||
to_chat(user, "<span class='alert'>[p_their(TRUE)] outer shell is too tough.</span>")
|
||||
/mob/living/silicon/can_inject(mob/user, target_zone, injection_flags)
|
||||
return FALSE
|
||||
|
||||
/mob/living/silicon/try_inject(mob/user, target_zone, injection_flags)
|
||||
. = ..()
|
||||
if(!. && (injection_flags & INJECT_TRY_SHOW_ERROR_MESSAGE))
|
||||
to_chat(user, "<span class='alert'>[p_their(TRUE)] outer shell is too tough.</span>")
|
||||
|
||||
/proc/islinked(mob/living/silicon/robot/bot, mob/living/silicon/ai/ai)
|
||||
if(!istype(bot) || !istype(ai))
|
||||
return FALSE
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
return
|
||||
|
||||
if(!force)
|
||||
if(M.can_inject(user, 1))
|
||||
if(M.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE))
|
||||
to_chat(user, "<span class='warning'>You stab [M] with the pen.</span>")
|
||||
if(!stealth)
|
||||
to_chat(M, "<span class='danger'>You feel a tiny prick!</span>")
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/M = target
|
||||
if(blocked != 100) // not completely blocked
|
||||
if(M.can_inject(null, FALSE, def_zone, piercing)) // Pass the hit zone to see if it can inject by whether it hit the head or the body.
|
||||
if(M.can_inject(target_zone = def_zone, injection_flags = piercing ? INJECT_CHECK_PENETRATE_THICK : null)) // Pass the hit zone to see if it can inject by whether it hit the head or the body.
|
||||
..()
|
||||
reagents.trans_to(M, reagents.total_volume, methods = INJECT)
|
||||
return BULLET_ACT_HIT
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/M = target
|
||||
if(blocked != 100)
|
||||
if(M.can_inject(null, FALSE, def_zone, FALSE))
|
||||
if(M.can_inject(target_zone = def_zone))
|
||||
if(injector.inject(M, firer))
|
||||
QDEL_NULL(injector)
|
||||
return BULLET_ACT_HIT
|
||||
|
||||
@@ -109,7 +109,7 @@ Borg Hypospray
|
||||
return
|
||||
if(!istype(M))
|
||||
return
|
||||
if(R.total_volume && M.can_inject(user, 1, user.zone_selected,bypass_protection))
|
||||
if(R.total_volume && M.try_inject(user, user.zone_selected, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE | (bypass_protection ? INJECT_CHECK_PENETRATE_THICK : 0)))
|
||||
to_chat(M, "<span class='warning'>You feel a tiny prick!</span>")
|
||||
to_chat(user, "<span class='notice'>You inject [M] with the injector.</span>")
|
||||
if(M.reagents)
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
var/contained = english_list(injected)
|
||||
log_combat(user, M, "attempted to inject", src, "([contained])")
|
||||
|
||||
if(reagents.total_volume && (ignore_flags || M.can_inject(user, 1))) // Ignore flag should be checked first or there will be an error message.
|
||||
if(reagents.total_volume && (ignore_flags || M.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE))) // Ignore flag should be checked first or there will be an error message.
|
||||
to_chat(M, "<span class='warning'>You feel a tiny prick!</span>")
|
||||
to_chat(user, "<span class='notice'>You inject [M] with [src].</span>")
|
||||
var/fraction = min(amount_per_transfer_from_this/reagents.total_volume, 1)
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
var/mob/living/L
|
||||
if(isliving(target))
|
||||
L = target
|
||||
if(!L.can_inject(user, 1))
|
||||
if(!L.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE))
|
||||
return
|
||||
|
||||
// chance of monkey retaliation
|
||||
@@ -82,7 +82,7 @@
|
||||
target.visible_message("<span class='danger'>[user] is trying to take a blood sample from [target]!</span>", \
|
||||
"<span class='userdanger'>[user] is trying to take a blood sample from you!</span>")
|
||||
busy = TRUE
|
||||
if(!do_mob(user, target, extra_checks=CALLBACK(L, /mob/living/proc/can_inject, user, 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)
|
||||
@@ -127,12 +127,12 @@
|
||||
return
|
||||
|
||||
if(L) //living mob
|
||||
if(!L.can_inject(user, TRUE))
|
||||
if(!L.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE))
|
||||
return
|
||||
if(L != user)
|
||||
L.visible_message("<span class='danger'>[user] is trying to inject [L]!</span>", \
|
||||
"<span class='userdanger'>[user] is trying to inject you!</span>")
|
||||
if(!do_mob(user, L, extra_checks=CALLBACK(L, /mob/living/proc/can_inject, user, TRUE)))
|
||||
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
|
||||
|
||||
@@ -151,7 +151,7 @@ To add a crossbreed:
|
||||
if(self_use_only && M != user)
|
||||
to_chat(user, "<span class='warning'>This can only be used on yourself.</span>")
|
||||
return
|
||||
if(reagents.total_volume && (ignore_flags || M.can_inject(user, 1)))
|
||||
if(reagents.total_volume && (ignore_flags || M.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE)))
|
||||
reagents.trans_to(M, reagents.total_volume, transfered_by = user)
|
||||
if(user != M)
|
||||
to_chat(M, "<span class='warning'>[user] presses [src] against you!</span>")
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
#include "code\__DEFINES\forensics.dm"
|
||||
#include "code\__DEFINES\hud.dm"
|
||||
#include "code\__DEFINES\icon_smoothing.dm"
|
||||
#include "code\__DEFINES\injection.dm"
|
||||
#include "code\__DEFINES\instruments.dm"
|
||||
#include "code\__DEFINES\interaction_flags.dm"
|
||||
#include "code\__DEFINES\inventory.dm"
|
||||
|
||||
Reference in New Issue
Block a user