diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm
index ddf3deb4a3..72b12ab988 100644
--- a/code/__DEFINES/components.dm
+++ b/code/__DEFINES/components.dm
@@ -10,6 +10,11 @@
#define COMPONENT_DUPE_ALLOWED 1 //duplicates allowed
#define COMPONENT_DUPE_UNIQUE 2 //new component is deleted
+// Signal return value flags
+// The other defines are under the signal they're used in
+
+#define COMPONENT_ACTIVATED 1 // call parent.ComponentActivated(comp) and component.AfterComponentActivated()
+
// All signals. Format:
// When the signal is called: (signal arguments)
@@ -23,6 +28,7 @@
// /atom signals
#define COMSIG_PARENT_ATTACKBY "atom_attackby" //from base of atom/attackby(): (/obj/item, /mob/living, params)
+ #define COMPONENT_NO_AFTERATTACK 2 //Return this in response if you don't want afterattack to be called
#define COMSIG_ATOM_HULK_ATTACK "hulk_attack" //from base of atom/attack_hulk(): (/mob/living/carbon/human)
#define COMSIG_PARENT_EXAMINE "atom_examine" //from base of atom/examine(): (/mob)
#define COMSIG_ATOM_ENTERED "atom_entered" //from base of atom/Entered(): (/atom/movable, /atom)
diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index acdccba3df..56cd1d8e4c 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -34,7 +34,9 @@
// No comment
/atom/proc/attackby(obj/item/W, mob/user, params)
- return SendSignal(COMSIG_PARENT_ATTACKBY, W, user, params)
+ if(SendSignal(COMSIG_PARENT_ATTACKBY, W, user, params) & COMPONENT_NO_AFTERATTACK)
+ return TRUE
+ return FALSE
/obj/attackby(obj/item/I, mob/living/user, params)
return ..() || (can_be_hit && I.attack_obj(src, user))
diff --git a/code/datums/components/README.md b/code/datums/components/README.md
index 11cbf1858d..476d820bc2 100644
--- a/code/datums/components/README.md
+++ b/code/datums/components/README.md
@@ -78,6 +78,7 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
1. `/datum/proc/SendSignal(signal, ...)` (public, final)
* Call to send a signal to the components of the target datum
* Extra arguments are to be specified in the signal definition
+ * Returns a bitflag with signal specific information assembled from all activated components
1. `/datum/component/New(datum/parent, ...)` (private, final)
* Runs internal setup for the component
* Extra arguments are passed to `Initialize()`
diff --git a/code/datums/components/_component.dm b/code/datums/components/_component.dm
index 4fb71acf84..39980b4f9d 100644
--- a/code/datums/components/_component.dm
+++ b/code/datums/components/_component.dm
@@ -164,24 +164,24 @@
/datum/proc/SendSignal(sigtype, ...)
var/list/comps = datum_components
if(!comps)
- return FALSE
+ return NONE
var/list/arguments = args.Copy()
arguments.Cut(1, 2)
var/target = comps[/datum/component]
if(!length(target))
var/datum/component/C = target
if(!C.enabled)
- return FALSE
+ return NONE
var/list/sps = C.signal_procs
var/datum/callback/CB = LAZYACCESS(sps, sigtype)
if(!CB)
- return FALSE
+ return NONE
. = CB.InvokeAsync(arglist(arguments))
- if(.)
+ if(. & COMPONENT_ACTIVATED)
ComponentActivated(C)
C.AfterComponentActivated()
else
- . = FALSE
+ . = NONE
for(var/I in target)
var/datum/component/C = I
if(!C.enabled)
@@ -190,10 +190,11 @@
var/datum/callback/CB = LAZYACCESS(sps, sigtype)
if(!CB)
continue
- if(CB.InvokeAsync(arglist(arguments)))
+ var/retval = CB.InvokeAsync(arglist(arguments))
+ . |= retval
+ if(retval & COMPONENT_ACTIVATED)
ComponentActivated(C)
C.AfterComponentActivated()
- . = TRUE
/datum/proc/ComponentActivated(datum/component/C)
set waitfor = FALSE
diff --git a/code/datums/components/archaeology.dm b/code/datums/components/archaeology.dm
index ac4e3c107c..05a56952b6 100644
--- a/code/datums/components/archaeology.dm
+++ b/code/datums/components/archaeology.dm
@@ -20,27 +20,26 @@
/datum/component/archaeology/proc/Dig(obj/item/W, mob/living/user)
if(dug)
to_chat(user, "Looks like someone has dug here already.")
- return FALSE
- else
- var/digging_speed
- if (istype(W, /obj/item/shovel))
- var/obj/item/shovel/S = W
- digging_speed = S.digspeed
- else if (istype(W, /obj/item/pickaxe))
- var/obj/item/pickaxe/P = W
- digging_speed = P.digspeed
+ return
+
+ var/digging_speed
+ if (istype(W, /obj/item/shovel))
+ var/obj/item/shovel/S = W
+ digging_speed = S.digspeed
+ else if (istype(W, /obj/item/pickaxe))
+ var/obj/item/pickaxe/P = W
+ digging_speed = P.digspeed
+
+ if (digging_speed && isturf(user.loc))
+ to_chat(user, "You start digging...")
+ playsound(parent, 'sound/effects/shovel_dig.ogg', 50, 1)
- if (digging_speed && isturf(user.loc))
- to_chat(user, "You start digging...")
- playsound(parent, 'sound/effects/shovel_dig.ogg', 50, 1)
-
- if(do_after(user, digging_speed, target = parent))
- to_chat(user, "You dig a hole.")
- gets_dug()
- dug = TRUE
- SSblackbox.record_feedback("tally", "pick_used_mining", 1, W.type)
- return TRUE
- return FALSE
+ if(do_after(user, digging_speed, target = parent))
+ to_chat(user, "You dig a hole.")
+ gets_dug()
+ dug = TRUE
+ SSblackbox.record_feedback("tally", "pick_used_mining", 1, W.type)
+ return COMPONENT_NO_AFTERATTACK
/datum/component/archaeology/proc/gets_dug()
if(dug)
diff --git a/code/datums/components/infective.dm b/code/datums/components/infective.dm
index cedede6b04..5b2232b8a9 100644
--- a/code/datums/components/infective.dm
+++ b/code/datums/components/infective.dm
@@ -10,4 +10,4 @@
if(istype(victim))
for(var/datum/disease/D in diseases)
victim.ContactContractDisease(D, "feet")
- return TRUE
\ No newline at end of file
+ return COMPONENT_ACTIVATED
\ No newline at end of file
diff --git a/code/datums/components/material_container.dm b/code/datums/components/material_container.dm
index c6acb7d78d..ec9ac1d1e6 100644
--- a/code/datums/components/material_container.dm
+++ b/code/datums/components/material_container.dm
@@ -53,11 +53,11 @@
/datum/component/material_container/proc/OnAttackBy(obj/item/I, mob/living/user)
var/list/tc = allowed_typecache
if(user.a_intent == INTENT_HARM)
- return FALSE
+ return
if((I.flags_2 & (HOLOGRAM_2 | NO_MAT_REDEMPTION_2)) || (tc && !is_type_in_typecache(I, tc)))
to_chat(user, "[parent] won't accept [I]!")
- return FALSE
- . = TRUE
+ return
+ . = COMPONENT_ACTIVATED | COMPONENT_NO_AFTERATTACK
last_insert_success = FALSE
var/datum/callback/pc = precondition
if(pc && !pc.Invoke())
diff --git a/code/datums/components/paintable.dm b/code/datums/components/paintable.dm
index 2ea94334d0..01e81d27c0 100644
--- a/code/datums/components/paintable.dm
+++ b/code/datums/components/paintable.dm
@@ -14,8 +14,8 @@
/datum/component/spraycan_paintable/proc/Repaint(obj/item/toy/crayon/spraycan/spraycan, mob/living/user)
if(!istype(spraycan) || user.a_intent == INTENT_HARM)
- return FALSE
- . = TRUE
+ return
+ . = COMPONENT_NO_AFTERATTACK
if(spraycan.is_capped)
to_chat(user, "Take the cap off first!")
return
diff --git a/code/datums/components/slippery.dm b/code/datums/components/slippery.dm
index 573bb81d11..c174ba5ecb 100644
--- a/code/datums/components/slippery.dm
+++ b/code/datums/components/slippery.dm
@@ -12,7 +12,7 @@
var/mob/victim = AM
if(istype(victim) && !victim.is_flying() && victim.slip(intensity, parent, lube_flags))
slip_victim = victim
- return TRUE
+ return COMPONENT_ACTIVATED
/datum/component/slippery/AfterComponentActivated()
slip_victim = null
diff --git a/code/datums/components/spooky.dm b/code/datums/components/spooky.dm
index 966baf7c4a..3f3b0341ee 100644
--- a/code/datums/components/spooky.dm
+++ b/code/datums/components/spooky.dm
@@ -19,7 +19,7 @@
if(ishuman(C))
var/mob/living/carbon/human/H = C
if(istype(H.dna.species, /datum/species/skeleton))
- return ..() //undeads are unaffected by the spook-pocalypse.
+ return //undeads are unaffected by the spook-pocalypse.
if(istype(H.dna.species, /datum/species/zombie))
H.adjustStaminaLoss(25)
H.Knockdown(15) //zombies can't resist the doot