From fc1f10c97f9aa4fcb94815f5e958ff3a443e1d97 Mon Sep 17 00:00:00 2001
From: Ghommie <42542238+Ghommie@users.noreply.github.com>
Date: Wed, 23 Oct 2019 13:01:31 +0200
Subject: [PATCH] Porting components updates and fixing phantom thief
component.
---
code/__DEFINES/components.dm | 1 +
code/__HELPERS/unsorted.dm | 4 ++
code/controllers/subsystem/vis_overlays.dm | 4 +-
code/datums/components/_component.dm | 50 +++++++++++--------
code/datums/components/decal.dm | 2 +-
code/datums/components/earprotection.dm | 2 +-
code/datums/components/forensics.dm | 11 ++++
code/datums/components/lockon_aiming.dm | 3 --
code/datums/components/mirage_border.dm | 1 +
code/datums/components/orbiter.dm | 13 ++---
code/datums/components/phantomthief.dm | 39 +++++++++++++++
code/datums/components/rotation.dm | 36 ++++++++++---
code/datums/components/signal_redirect.dm | 33 ------------
.../components/storage/concrete/_concrete.dm | 1 +
code/datums/components/virtual_reality.dm | 2 +-
code/datums/components/wearertargeting.dm | 10 ++--
code/datums/components/wet_floor.dm | 17 ++++++-
code/datums/status_effects/gas.dm | 6 +--
code/game/machinery/washing_machine.dm | 2 +-
code/game/objects/effects/proximity.dm | 10 ++--
code/game/objects/items/RCL.dm | 22 ++++----
code/game/objects/items/defib.dm | 17 ++++---
.../objects/items/devices/geiger_counter.dm | 16 +++---
code/game/objects/items/his_grace.dm | 2 +-
code/game/objects/items/storage/bags.dm | 16 +++---
code/game/objects/items/twohanded.dm | 15 +++---
.../antagonists/disease/disease_mob.dm | 13 ++---
code/modules/assembly/infrared.dm | 12 +++--
code/modules/clothing/gloves/_gloves.dm | 2 +-
code/modules/clothing/shoes/_shoes.dm | 2 +-
code/modules/clothing/spacesuits/hardsuit.dm | 25 ++++++----
code/modules/fields/fields.dm | 14 ++++--
code/modules/mob/living/carbon/human/human.dm | 2 +-
.../projectiles/guns/misc/beam_rifle.dm | 13 +++--
.../crossbreeding/_status_effects.dm | 13 ++---
.../research/xenobiology/xenobio_camera.dm | 4 +-
code/modules/unit_tests/_unit_tests.dm | 1 +
code/modules/unit_tests/component_tests.dm | 12 +++++
.../code/datums/components/phantomthief.dm | 49 ------------------
.../modules/clothing/glasses/phantomthief.dm | 24 ++++-----
tgstation.dme | 3 +-
41 files changed, 271 insertions(+), 253 deletions(-)
create mode 100644 code/datums/components/phantomthief.dm
delete mode 100644 code/datums/components/signal_redirect.dm
create mode 100644 code/modules/unit_tests/component_tests.dm
delete mode 100644 modular_citadel/code/datums/components/phantomthief.dm
diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm
index c2482f6fbf..4b339cdb79 100644
--- a/code/__DEFINES/components.dm
+++ b/code/__DEFINES/components.dm
@@ -7,6 +7,7 @@
#define GET_COMPONENT(varname, path) GET_COMPONENT_FROM(varname, path, src)
#define COMPONENT_INCOMPATIBLE 1
+#define COMPONENT_NOTRANSFER 2
// How multiple components of the exact same type are handled in the same datum
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index 3c8d62ce3a..ec82765a5f 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -1550,3 +1550,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
for(var/i in L)
if(condition.Invoke(i))
. |= i
+
+/proc/CallAsync(datum/source, proctype, list/arguments)
+ set waitfor = FALSE
+ return call(source, proctype)(arglist(arguments))
\ No newline at end of file
diff --git a/code/controllers/subsystem/vis_overlays.dm b/code/controllers/subsystem/vis_overlays.dm
index 435414a899..107d65a558 100644
--- a/code/controllers/subsystem/vis_overlays.dm
+++ b/code/controllers/subsystem/vis_overlays.dm
@@ -6,11 +6,9 @@ SUBSYSTEM_DEF(vis_overlays)
var/list/vis_overlay_cache
var/list/currentrun
- var/datum/callback/rotate_cb
/datum/controller/subsystem/vis_overlays/Initialize()
vis_overlay_cache = list()
- rotate_cb = CALLBACK(src, .proc/rotate_vis_overlay)
return ..()
/datum/controller/subsystem/vis_overlays/fire(resumed = FALSE)
@@ -52,7 +50,7 @@ SUBSYSTEM_DEF(vis_overlays)
if(!thing.managed_vis_overlays)
thing.managed_vis_overlays = list(overlay)
- RegisterSignal(thing, COMSIG_ATOM_DIR_CHANGE, rotate_cb)
+ RegisterSignal(thing, COMSIG_ATOM_DIR_CHANGE, .proc/rotate_vis_overlay)
else
thing.managed_vis_overlays += overlay
diff --git a/code/datums/components/_component.dm b/code/datums/components/_component.dm
index b3d3b46434..fbe94cbb9e 100644
--- a/code/datums/components/_component.dm
+++ b/code/datums/components/_component.dm
@@ -2,6 +2,10 @@
var/dupe_mode = COMPONENT_DUPE_HIGHLANDER
var/dupe_type
var/datum/parent
+ //only set to true if you are able to properly transfer this component
+ //At a minimum RegisterWithParent and UnregisterFromParent should be used
+ //Make sure you also implement PostTransfer for any post transfer handling
+ var/can_transfer = FALSE
/datum/component/New(datum/P, ...)
parent = P
@@ -83,7 +87,7 @@
/datum/component/proc/UnregisterFromParent()
return
-/datum/proc/RegisterSignal(datum/target, sig_type_or_types, proc_or_callback, override = FALSE)
+/datum/proc/RegisterSignal(datum/target, sig_type_or_types, proctype, override = FALSE)
if(QDELETED(src) || QDELETED(target))
return
@@ -96,15 +100,12 @@
if(!lookup)
target.comp_lookup = lookup = list()
- if(!istype(proc_or_callback, /datum/callback)) //if it wasnt a callback before, it is now
- proc_or_callback = CALLBACK(src, proc_or_callback)
-
var/list/sig_types = islist(sig_type_or_types) ? sig_type_or_types : list(sig_type_or_types)
for(var/sig_type in sig_types)
if(!override && procs[target][sig_type])
stack_trace("[sig_type] overridden. Use override = TRUE to suppress this warning")
- procs[target][sig_type] = proc_or_callback
+ procs[target][sig_type] = proctype
if(!lookup[sig_type]) // Nothing has registered here yet
lookup[sig_type] = src
@@ -154,7 +155,7 @@
return
/datum/component/proc/PostTransfer()
- return
+ return COMPONENT_INCOMPATIBLE //Do not support transfer by default as you must properly support it
/datum/component/proc/_GetInverseTypeList(our_type = type)
//we can do this one simple trick
@@ -171,17 +172,20 @@
var/datum/C = target
if(!C.signal_enabled)
return NONE
- var/datum/callback/CB = C.signal_procs[src][sigtype]
- return CB.InvokeAsync(arglist(arguments))
+ var/proctype = C.signal_procs[src][sigtype]
+ return NONE | CallAsync(C, proctype, arguments)
. = NONE
for(var/I in target)
var/datum/C = I
if(!C.signal_enabled)
continue
- var/datum/callback/CB = C.signal_procs[src][sigtype]
- . |= CB.InvokeAsync(arglist(arguments))
+ var/proctype = C.signal_procs[src][sigtype]
+ . |= CallAsync(C, proctype, arguments)
-/datum/proc/GetComponent(c_type)
+// The type arg is casted so initial works, you shouldn't be passing a real instance into this
+/datum/proc/GetComponent(datum/component/c_type)
+ if(initial(c_type.dupe_mode) == COMPONENT_DUPE_ALLOWED)
+ stack_trace("GetComponent was called to get a component of which multiple copies could be on an object. This can easily break and should be changed. Type: \[[c_type]\]")
var/list/dc = datum_components
if(!dc)
return null
@@ -220,10 +224,6 @@
if(ispath(nt))
if(nt == /datum/component)
CRASH("[nt] attempted instantiation!")
- if(!isnum(dm))
- CRASH("[nt]: Invalid dupe_mode ([dm])!")
- if(dt && !ispath(dt))
- CRASH("[nt]: Invalid dupe_type ([dt])!")
else
new_comp = nt
nt = new_comp.type
@@ -285,10 +285,13 @@
if(target.parent)
target.RemoveComponent()
target.parent = src
- if(target.PostTransfer() == COMPONENT_INCOMPATIBLE)
- var/c_type = target.type
- qdel(target)
- CRASH("Incompatible [c_type] transfer attempt to a [type]!")
+ var/result = target.PostTransfer()
+ switch(result)
+ if(COMPONENT_INCOMPATIBLE)
+ var/c_type = target.type
+ qdel(target)
+ CRASH("Incompatible [c_type] transfer attempt to a [type]!")
+
if(target == AddComponent(target))
target._JoinParent()
@@ -298,10 +301,13 @@
return
var/comps = dc[/datum/component]
if(islist(comps))
- for(var/I in comps)
- target.TakeComponent(I)
+ for(var/datum/component/I in comps)
+ if(I.can_transfer)
+ target.TakeComponent(I)
else
- target.TakeComponent(comps)
+ var/datum/component/C = comps
+ if(C.can_transfer)
+ target.TakeComponent(comps)
/datum/component/ui_host()
return parent
diff --git a/code/datums/components/decal.dm b/code/datums/components/decal.dm
index e5547ee0ec..bdc1d3a2f6 100644
--- a/code/datums/components/decal.dm
+++ b/code/datums/components/decal.dm
@@ -1,6 +1,6 @@
/datum/component/decal
dupe_mode = COMPONENT_DUPE_ALLOWED
-
+ can_transfer = TRUE
var/cleanable
var/description
var/mutable_appearance/pic
diff --git a/code/datums/components/earprotection.dm b/code/datums/components/earprotection.dm
index 2084943756..9256c4310a 100644
--- a/code/datums/components/earprotection.dm
+++ b/code/datums/components/earprotection.dm
@@ -1,11 +1,11 @@
/datum/component/wearertargeting/earprotection
signals = list(COMSIG_CARBON_SOUNDBANG)
mobtype = /mob/living/carbon
+ proctype = .proc/reducebang
/datum/component/wearertargeting/earprotection/Initialize(_valid_slots)
. = ..()
valid_slots = _valid_slots
- callback = CALLBACK(src, .proc/reducebang)
/datum/component/wearertargeting/earprotection/proc/reducebang(datum/source, list/reflist)
reflist[1]--
diff --git a/code/datums/components/forensics.dm b/code/datums/components/forensics.dm
index c7a1f7eba5..6d34051ed7 100644
--- a/code/datums/components/forensics.dm
+++ b/code/datums/components/forensics.dm
@@ -1,5 +1,6 @@
/datum/component/forensics
dupe_mode = COMPONENT_DUPE_UNIQUE
+ can_transfer = TRUE
var/list/fingerprints //assoc print = print
var/list/hiddenprints //assoc ckey = realname/gloves/ckey
var/list/blood_DNA //assoc dna = bloodtype
@@ -21,8 +22,18 @@
blood_DNA = new_blood_DNA
fibers = new_fibers
check_blood()
+
+/datum/component/forensics/RegisterWithParent()
+ check_blood()
RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_act)
+/datum/component/forensics/UnregisterFromParent()
+ UnregisterSignal(parent, list(COMSIG_COMPONENT_CLEAN_ACT))
+
+/datum/component/forensics/PostTransfer()
+ if(!isatom(parent))
+ return COMPONENT_INCOMPATIBLE
+
/datum/component/forensics/proc/wipe_fingerprints()
fingerprints = null
return TRUE
diff --git a/code/datums/components/lockon_aiming.dm b/code/datums/components/lockon_aiming.dm
index cc41e793ed..38b707ac19 100644
--- a/code/datums/components/lockon_aiming.dm
+++ b/code/datums/components/lockon_aiming.dm
@@ -237,6 +237,3 @@
LOCKON_RANGING_BREAK_CHECK
cd++
CHECK_TICK
-
-/datum/component/lockon_aiming/PostTransfer(datum/new_parent)
- return COMPONENT_INCOMPATIBLE
diff --git a/code/datums/components/mirage_border.dm b/code/datums/components/mirage_border.dm
index 2e6f8f79f6..20e3b317ec 100644
--- a/code/datums/components/mirage_border.dm
+++ b/code/datums/components/mirage_border.dm
@@ -1,4 +1,5 @@
/datum/component/mirage_border
+ can_transfer = TRUE
var/obj/effect/abstract/mirage_holder/holder
/datum/component/mirage_border/Initialize(turf/target, direction, range=world.view)
diff --git a/code/datums/components/orbiter.dm b/code/datums/components/orbiter.dm
index 301e50dc42..efa0fd14d5 100644
--- a/code/datums/components/orbiter.dm
+++ b/code/datums/components/orbiter.dm
@@ -1,8 +1,7 @@
/datum/component/orbiter
+ can_transfer = TRUE
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
var/list/orbiters
- var/datum/callback/orbiter_spy
- var/datum/callback/orbited_spy
//radius: range to orbit at, radius of the circle formed by orbiting (in pixels)
//clockwise: whether you orbit clockwise or anti clockwise
@@ -14,8 +13,6 @@
return COMPONENT_INCOMPATIBLE
orbiters = list()
- orbiter_spy = CALLBACK(src, .proc/orbiter_move_react)
- orbited_spy = CALLBACK(src, .proc/move_react)
var/atom/master = parent
master.orbiters = src
@@ -25,7 +22,7 @@
/datum/component/orbiter/RegisterWithParent()
var/atom/target = parent
while(ismovableatom(target))
- RegisterSignal(target, COMSIG_MOVABLE_MOVED, orbited_spy)
+ RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/move_react)
target = target.loc
/datum/component/orbiter/UnregisterFromParent()
@@ -40,8 +37,6 @@
for(var/i in orbiters)
end_orbit(i)
orbiters = null
- QDEL_NULL(orbiter_spy)
- QDEL_NULL(orbited_spy)
return ..()
/datum/component/orbiter/InheritComponent(datum/component/orbiter/newcomp, original, list/arguments)
@@ -64,7 +59,7 @@
orbiter.orbiting.end_orbit(orbiter)
orbiters[orbiter] = TRUE
orbiter.orbiting = src
- RegisterSignal(orbiter, COMSIG_MOVABLE_MOVED, orbiter_spy)
+ RegisterSignal(orbiter, COMSIG_MOVABLE_MOVED, .proc/orbiter_move_react)
var/matrix/initial_transform = matrix(orbiter.transform)
// Head first!
@@ -120,7 +115,7 @@
if(orbited?.loc && orbited.loc != newturf) // We want to know when anything holding us moves too
var/atom/target = orbited.loc
while(ismovableatom(target))
- RegisterSignal(target, COMSIG_MOVABLE_MOVED, orbited_spy, TRUE)
+ RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/move_react, TRUE)
target = target.loc
var/atom/curloc = master.loc
diff --git a/code/datums/components/phantomthief.dm b/code/datums/components/phantomthief.dm
new file mode 100644
index 0000000000..ff1c48936f
--- /dev/null
+++ b/code/datums/components/phantomthief.dm
@@ -0,0 +1,39 @@
+//This component applies a customizable drop_shadow filter to its wearer when they toggle combat mode on or off. This can stack.
+
+/datum/component/wearertargeting/phantomthief
+ dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
+ signals = list(COMSIG_COMBAT_TOGGLED)
+ proctype = .proc/handlefilterstuff
+ var/filter_x
+ var/filter_y
+ var/filter_size
+ var/filter_border
+ var/filter_color
+
+/datum/component/wearertargeting/phantomthief/Initialize(_x = -2, _y = 0, _size = 0, _border = 0, _color = "#E62111", list/_valid_slots = list(SLOT_GLASSES))
+ . = ..()
+ if(. == COMPONENT_INCOMPATIBLE)
+ return
+ filter_x = _x
+ filter_y = _y
+ filter_size = _size
+ filter_border = _border
+ filter_color = _color
+ valid_slots = _valid_slots
+
+/datum/component/wearertargeting/phantomthief/proc/handlefilterstuff(datum/source, mob/user, combatmodestate)
+ if(istype(user))
+ var/thefilter = filter(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, border = filter_border, color = filter_color)
+ if(!combatmodestate)
+ user.filters -= thefilter
+ else
+ user.filters += thefilter
+
+/datum/component/wearertargeting/phantomthief/proc/stripdesiredfilter(mob/user)
+ if(istype(user))
+ var/thefilter = filter(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, border = filter_border, color = filter_color)
+ user.filters -= thefilter
+
+/datum/component/wearertargeting/phantomthief/on_drop(datum/source, mob/user)
+ . = ..()
+ stripdesiredfilter(user)
diff --git a/code/datums/components/rotation.dm b/code/datums/components/rotation.dm
index ff424dc02e..fa6c4decd5 100644
--- a/code/datums/components/rotation.dm
+++ b/code/datums/components/rotation.dm
@@ -44,19 +44,21 @@
if(src.rotation_flags & ROTATION_CLOCKWISE)
default_rotation_direction = ROTATION_CLOCKWISE
- if(src.rotation_flags & ROTATION_ALTCLICK)
+/datum/component/simple_rotation/proc/add_signals()
+ if(rotation_flags & ROTATION_ALTCLICK)
RegisterSignal(parent, COMSIG_CLICK_ALT, .proc/HandRot)
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/ExamineMessage)
- if(src.rotation_flags & ROTATION_WRENCH)
+ if(rotation_flags & ROTATION_WRENCH)
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/WrenchRot)
- if(src.rotation_flags & ROTATION_VERBS)
+/datum/component/simple_rotation/proc/add_verbs()
+ if(rotation_flags & ROTATION_VERBS)
var/atom/movable/AM = parent
- if(src.rotation_flags & ROTATION_FLIP)
+ if(rotation_flags & ROTATION_FLIP)
AM.verbs += /atom/movable/proc/simple_rotate_flip
- if(src.rotation_flags & ROTATION_CLOCKWISE)
+ if(rotation_flags & ROTATION_CLOCKWISE)
AM.verbs += /atom/movable/proc/simple_rotate_clockwise
- if(src.rotation_flags & ROTATION_COUNTERCLOCKWISE)
+ if(rotation_flags & ROTATION_COUNTERCLOCKWISE)
AM.verbs += /atom/movable/proc/simple_rotate_counterclockwise
/datum/component/simple_rotation/proc/remove_verbs()
@@ -66,11 +68,31 @@
AM.verbs -= /atom/movable/proc/simple_rotate_clockwise
AM.verbs -= /atom/movable/proc/simple_rotate_counterclockwise
-/datum/component/simple_rotation/Destroy()
+
+/datum/component/simple_rotation/proc/remove_signals()
+ UnregisterSignal(parent, list(COMSIG_CLICK_ALT, COMSIG_PARENT_EXAMINE, COMSIG_PARENT_ATTACKBY))
+
+/datum/component/simple_rotation/RegisterWithParent()
+ add_verbs()
+ add_signals()
+ . = ..()
+
+/datum/component/simple_rotation/PostTransfer()
+ //Because of the callbacks which we don't track cleanly we can't transfer this
+ //item cleanly, better to let the new of the new item create a new rotation datum
+ //instead (there's no real state worth transferring)
+ return COMPONENT_NOTRANSFER
+
+/datum/component/simple_rotation/UnregisterFromParent()
remove_verbs()
+ remove_signals()
+ . = ..()
+
+/datum/component/simple_rotation/Destroy()
QDEL_NULL(can_user_rotate)
QDEL_NULL(can_be_rotated)
QDEL_NULL(after_rotation)
+ //Signals + verbs removed via UnRegister
. = ..()
/datum/component/simple_rotation/RemoveComponent()
diff --git a/code/datums/components/signal_redirect.dm b/code/datums/components/signal_redirect.dm
deleted file mode 100644
index db98d5664a..0000000000
--- a/code/datums/components/signal_redirect.dm
+++ /dev/null
@@ -1,33 +0,0 @@
-// This should only be used by non components trying to listen to a signal
-// If you use this inside a component I will replace your eyes with lemons ~ninjanomnom
-
-/datum/component/redirect
- dupe_mode = COMPONENT_DUPE_ALLOWED
- var/list/signals
- var/datum/callback/turfchangeCB
-
-/datum/component/redirect/Initialize(list/_signals, flags=NONE)
- //It's not our job to verify the right signals are registered here, just do it.
- if(!LAZYLEN(_signals))
- return COMPONENT_INCOMPATIBLE
- if(flags & REDIRECT_TRANSFER_WITH_TURF && isturf(parent))
- // If they also want to listen to the turf change then we need to set it up so both callbacks run
- if(_signals[COMSIG_TURF_CHANGE])
- turfchangeCB = _signals[COMSIG_TURF_CHANGE]
- if(!istype(turfchangeCB))
- . = COMPONENT_INCOMPATIBLE
- CRASH("Redirect components must be given instanced callbacks, not proc paths.")
- _signals[COMSIG_TURF_CHANGE] = CALLBACK(src, .proc/turf_change)
-
- signals = _signals
-
-/datum/component/redirect/RegisterWithParent()
- for(var/signal in signals)
- RegisterSignal(parent, signal, signals[signal])
-
-/datum/component/redirect/UnregisterFromParent()
- UnregisterSignal(parent, signals)
-
-/datum/component/redirect/proc/turf_change(datum/source, path, new_baseturfs, flags, list/transfers)
- transfers += src
- return turfchangeCB?.InvokeAsync(arglist(args))
diff --git a/code/datums/components/storage/concrete/_concrete.dm b/code/datums/components/storage/concrete/_concrete.dm
index 0b78605869..f7ca711421 100644
--- a/code/datums/components/storage/concrete/_concrete.dm
+++ b/code/datums/components/storage/concrete/_concrete.dm
@@ -4,6 +4,7 @@
// /mob/living/Move() in /modules/mob/living/living.dm - hiding storage boxes on mob movement
/datum/component/storage/concrete
+ can_transfer = TRUE
var/drop_all_on_deconstruct = TRUE
var/drop_all_on_destroy = FALSE
var/drop_all_on_break = FALSE
diff --git a/code/datums/components/virtual_reality.dm b/code/datums/components/virtual_reality.dm
index 750cc045ce..f8f0679e9b 100644
--- a/code/datums/components/virtual_reality.dm
+++ b/code/datums/components/virtual_reality.dm
@@ -1,5 +1,5 @@
/datum/component/virtual_reality
- dupe_mode = COMPONENT_DUPE_ALLOWED //mindswap memes, shouldn't stack up otherwise.
+ can_transfer = TRUE
var/datum/mind/mastermind // where is my mind t. pixies
var/datum/mind/current_mind
var/obj/machinery/vr_sleeper/vr_sleeper
diff --git a/code/datums/components/wearertargeting.dm b/code/datums/components/wearertargeting.dm
index 0aa0831127..feaa88f934 100644
--- a/code/datums/components/wearertargeting.dm
+++ b/code/datums/components/wearertargeting.dm
@@ -3,7 +3,7 @@
/datum/component/wearertargeting
var/list/valid_slots = list()
var/list/signals = list()
- var/datum/callback/callback = CALLBACK(GLOBAL_PROC, .proc/pass)
+ var/proctype = .proc/pass
var/mobtype = /mob/living
/datum/component/wearertargeting/Initialize()
@@ -14,13 +14,9 @@
/datum/component/wearertargeting/proc/on_equip(datum/source, mob/equipper, slot)
if((slot in valid_slots) && istype(equipper, mobtype))
- RegisterSignal(equipper, signals, callback, TRUE)
+ RegisterSignal(equipper, signals, proctype, TRUE)
else
UnregisterSignal(equipper, signals)
/datum/component/wearertargeting/proc/on_drop(datum/source, mob/user)
- UnregisterSignal(user, signals)
-
-/datum/component/wearertargeting/Destroy()
- QDEL_NULL(callback) //is likely to ourselves.
- return ..()
\ No newline at end of file
+ UnregisterSignal(user, signals)
\ No newline at end of file
diff --git a/code/datums/components/wet_floor.dm b/code/datums/components/wet_floor.dm
index 6d504cefd4..84b0320375 100644
--- a/code/datums/components/wet_floor.dm
+++ b/code/datums/components/wet_floor.dm
@@ -1,5 +1,6 @@
/datum/component/wet_floor
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
+ can_transfer = TRUE
var/highest_strength = TURF_DRY
var/lube_flags = NONE //why do we have this?
var/list/time_left_list //In deciseconds.
@@ -26,14 +27,19 @@
if(!isopenturf(parent))
return COMPONENT_INCOMPATIBLE
add_wet(strength, duration_minimum, duration_add, duration_maximum)
- RegisterSignal(parent, COMSIG_TURF_IS_WET, .proc/is_wet)
- RegisterSignal(parent, COMSIG_TURF_MAKE_DRY, .proc/dry)
permanent = _permanent
if(!permanent)
START_PROCESSING(SSwet_floors, src)
addtimer(CALLBACK(src, .proc/gc, TRUE), 1) //GC after initialization.
last_process = world.time
+/datum/component/wet_floor/RegisterWithParent()
+ RegisterSignal(parent, COMSIG_TURF_IS_WET, .proc/is_wet)
+ RegisterSignal(parent, COMSIG_TURF_MAKE_DRY, .proc/dry)
+
+/datum/component/wet_floor/UnregisterFromParent()
+ UnregisterSignal(parent, list(COMSIG_TURF_IS_WET, COMSIG_TURF_MAKE_DRY))
+
/datum/component/wet_floor/Destroy()
STOP_PROCESSING(SSwet_floors, src)
var/turf/T = parent
@@ -138,12 +144,19 @@
/datum/component/wet_floor/PreTransfer()
var/turf/O = parent
O.cut_overlay(current_overlay)
+ //That turf is no longer slippery, we're out of here
+ //Slippery components don't transfer due to callbacks
+ qdel(O.GetComponent(/datum/component/slippery))
/datum/component/wet_floor/PostTransfer()
if(!isopenturf(parent))
return COMPONENT_INCOMPATIBLE
var/turf/T = parent
T.add_overlay(current_overlay)
+ //Make sure to add/update any slippery component on the new turf (update_flags calls LoadComponent)
+ update_flags()
+
+ //NB it's possible we get deleted after this, due to inherit
/datum/component/wet_floor/proc/add_wet(type, duration_minimum = 0, duration_add = 0, duration_maximum = MAXIMUM_WET_TIME, _permanent = FALSE)
var/static/list/allowed_types = list(TURF_WET_WATER, TURF_WET_LUBE, TURF_WET_ICE, TURF_WET_PERMAFROST)
diff --git a/code/datums/status_effects/gas.dm b/code/datums/status_effects/gas.dm
index dfe0a1d94e..0041799314 100644
--- a/code/datums/status_effects/gas.dm
+++ b/code/datums/status_effects/gas.dm
@@ -5,7 +5,6 @@
alert_type = /obj/screen/alert/status_effect/freon
var/icon/cube
var/can_melt = TRUE
- var/datum/weakref/redirect_component
/obj/screen/alert/status_effect/freon
name = "Frozen Solid"
@@ -13,7 +12,7 @@
icon_state = "frozen"
/datum/status_effect/freon/on_apply()
- redirect_component = WEAKREF(owner.AddComponent(/datum/component/redirect, list(COMSIG_LIVING_RESIST = CALLBACK(src, .proc/owner_resist))))
+ RegisterSignal(owner, COMSIG_LIVING_RESIST, .proc/owner_resist)
if(!owner.stat)
to_chat(owner, "You become frozen in a cube!")
cube = icon('icons/effects/freeze.dmi', "ice_cube")
@@ -40,8 +39,7 @@
owner.cut_overlay(cube)
owner.adjust_bodytemperature(100)
owner.update_canmove()
- qdel(redirect_component.resolve())
- redirect_component = null
+ UnregisterSignal(owner, COMSIG_LIVING_RESIST)
/datum/status_effect/freon/watcher
duration = 8
diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm
index 5e8515d3d5..b6b78683e8 100644
--- a/code/game/machinery/washing_machine.dm
+++ b/code/game/machinery/washing_machine.dm
@@ -13,7 +13,7 @@
/obj/machinery/washing_machine/ComponentInitialize()
. = ..()
- AddComponent(/datum/component/redirect, list(COMSIG_COMPONENT_CLEAN_ACT = CALLBACK(src, .proc/clean_blood)))
+ RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_blood)
/obj/machinery/washing_machine/examine(mob/user)
..()
diff --git a/code/game/objects/effects/proximity.dm b/code/game/objects/effects/proximity.dm
index de17582f27..6c9525008d 100644
--- a/code/game/objects/effects/proximity.dm
+++ b/code/game/objects/effects/proximity.dm
@@ -5,7 +5,6 @@
var/list/checkers //list of /obj/effect/abstract/proximity_checkers
var/current_range
var/ignore_if_not_on_turf //don't check turfs in range if the host's loc isn't a turf
- var/datum/component/movement_tracker
/datum/proximity_monitor/New(atom/_host, range, _ignore_if_not_on_turf = TRUE)
checkers = list()
@@ -15,15 +14,17 @@
SetHost(_host)
/datum/proximity_monitor/proc/SetHost(atom/H,atom/R)
+ if(H == host)
+ return
+ if(host)
+ UnregisterSignal(host, COMSIG_MOVABLE_MOVED)
if(R)
hasprox_receiver = R
else if(hasprox_receiver == host) //Default case
hasprox_receiver = H
host = H
+ RegisterSignal(host, COMSIG_MOVABLE_MOVED, .proc/HandleMove)
last_host_loc = host.loc
- if(movement_tracker)
- QDEL_NULL(movement_tracker)
- movement_tracker = host.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/HandleMove)))
SetRange(current_range,TRUE)
/datum/proximity_monitor/Destroy()
@@ -31,7 +32,6 @@
last_host_loc = null
hasprox_receiver = null
QDEL_LIST(checkers)
- QDEL_NULL(movement_tracker)
return ..()
/datum/proximity_monitor/proc/HandleMove()
diff --git a/code/game/objects/items/RCL.dm b/code/game/objects/items/RCL.dm
index 63f460f9aa..93293155a3 100644
--- a/code/game/objects/items/RCL.dm
+++ b/code/game/objects/items/RCL.dm
@@ -20,8 +20,8 @@
var/ghetto = FALSE
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
- var/datum/component/mobhook
var/datum/radial_menu/persistent/wiring_gui_menu
+ var/mob/listeningTo
/obj/item/twohanded/rcl/attackby(obj/item/W, mob/user)
if(istype(W, /obj/item/stack/cable_coil))
@@ -86,7 +86,7 @@
/obj/item/twohanded/rcl/Destroy()
QDEL_NULL(loaded)
last = null
- QDEL_NULL(mobhook)
+ listeningTo = null
QDEL_NULL(wiring_gui_menu)
return ..()
@@ -141,9 +141,8 @@
/obj/item/twohanded/rcl/dropped(mob/wearer)
..()
- if(mobhook)
- active = FALSE
- QDEL_NULL(mobhook)
+ UnregisterSignal(wearer, COMSIG_MOVABLE_MOVED)
+ listeningTo = null
last = null
/obj/item/twohanded/rcl/attack_self(mob/user)
@@ -158,13 +157,12 @@
break
obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook)
- if(to_hook)
- if(mobhook && mobhook.parent != to_hook)
- QDEL_NULL(mobhook)
- if (!mobhook)
- mobhook = to_hook.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/trigger)))
- else
- QDEL_NULL(mobhook)
+ if(listeningTo == to_hook)
+ return
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
+ RegisterSignal(to_hook, COMSIG_MOVABLE_MOVED, .proc/trigger)
+ listeningTo = to_hook
/obj/item/twohanded/rcl/proc/trigger(mob/user)
if(active)
diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm
index a4f286bf88..03544c1ccb 100644
--- a/code/game/objects/items/defib.dm
+++ b/code/game/objects/items/defib.dm
@@ -297,15 +297,16 @@
var/grab_ghost = FALSE
var/tlimit = DEFIB_TIME_LIMIT * 10
- var/datum/component/mobhook
+ var/mob/listeningTo
/obj/item/twohanded/shockpaddles/equipped(mob/user, slot)
. = ..()
- if(req_defib)
- if (mobhook && mobhook.parent != user)
- QDEL_NULL(mobhook)
- if (!mobhook)
- mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/check_range)))
+ if(!req_defib || listeningTo == user)
+ return
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
+ RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/check_range)
+ listeningTo = user
/obj/item/twohanded/shockpaddles/Moved()
. = ..()
@@ -362,8 +363,8 @@
/obj/item/twohanded/shockpaddles/dropped(mob/user)
if(!req_defib)
return ..()
- if (mobhook)
- QDEL_NULL(mobhook)
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
if(user)
var/obj/item/twohanded/offhand/O = user.get_inactive_held_item()
if(istype(O))
diff --git a/code/game/objects/items/devices/geiger_counter.dm b/code/game/objects/items/devices/geiger_counter.dm
index 90cdd0386c..110676de1b 100644
--- a/code/game/objects/items/devices/geiger_counter.dm
+++ b/code/game/objects/items/devices/geiger_counter.dm
@@ -203,21 +203,25 @@
return TRUE
/obj/item/geiger_counter/cyborg
- var/datum/component/mobhook
+ var/mob/listeningTo
/obj/item/geiger_counter/cyborg/equipped(mob/user)
. = ..()
- if (mobhook && mobhook.parent != user)
- QDEL_NULL(mobhook)
- if (!mobhook)
- mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_ATOM_RAD_ACT = CALLBACK(src, .proc/redirect_rad_act)))
+ if(listeningTo == user)
+ return
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_ATOM_RAD_ACT)
+ RegisterSignal(user, COMSIG_ATOM_RAD_ACT, .proc/redirect_rad_act)
+ listeningTo = user
/obj/item/geiger_counter/cyborg/proc/redirect_rad_act(datum/source, amount)
rad_act(amount)
/obj/item/geiger_counter/cyborg/dropped()
. = ..()
- QDEL_NULL(mobhook)
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_ATOM_RAD_ACT)
+ listeningTo = null
#undef RAD_LEVEL_NORMAL
#undef RAD_LEVEL_MODERATE
diff --git a/code/game/objects/items/his_grace.dm b/code/game/objects/items/his_grace.dm
index 3be57d23f1..7e7dddefb6 100644
--- a/code/game/objects/items/his_grace.dm
+++ b/code/game/objects/items/his_grace.dm
@@ -29,7 +29,7 @@
. = ..()
START_PROCESSING(SSprocessing, src)
GLOB.poi_list += src
- AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_POST_THROW = CALLBACK(src, .proc/move_gracefully)))
+ RegisterSignal(src, COMSIG_MOVABLE_POST_THROW, .proc/move_gracefully)
/obj/item/his_grace/Destroy()
STOP_PROCESSING(SSprocessing, src)
diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm
index 0a475b2af1..9a9ff6c59b 100644
--- a/code/game/objects/items/storage/bags.dm
+++ b/code/game/objects/items/storage/bags.dm
@@ -105,7 +105,7 @@
w_class = WEIGHT_CLASS_NORMAL
component_type = /datum/component/storage/concrete/stack
var/spam_protection = FALSE //If this is TRUE, the holder won't receive any messages when they fail to pick up ore through crossing it
- var/datum/component/mobhook
+ var/mob/listeningTo
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
/obj/item/storage/bag/ore/ComponentInitialize()
@@ -118,15 +118,17 @@
/obj/item/storage/bag/ore/equipped(mob/user)
. = ..()
- if (mobhook && mobhook.parent != user)
- QDEL_NULL(mobhook)
- if (!mobhook)
- mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/Pickup_ores)))
+ if(listeningTo == user)
+ return
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
+ RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/Pickup_ores)
+ listeningTo = user
/obj/item/storage/bag/ore/dropped()
. = ..()
- if (mobhook)
- QDEL_NULL(mobhook)
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
+ listeningTo = null
/obj/item/storage/bag/ore/proc/Pickup_ores(mob/living/user)
var/show_message = FALSE
diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm
index b1c2c36585..dc88da41e6 100644
--- a/code/game/objects/items/twohanded.dm
+++ b/code/game/objects/items/twohanded.dm
@@ -847,18 +847,20 @@
righthand_file = 'icons/mob/inhands/items_righthand.dmi'
slot_flags = ITEM_SLOT_BELT
w_class = WEIGHT_CLASS_SMALL
- var/datum/component/mobhook
+ var/mob/listeningTo
var/zoom_out_amt = 6
var/zoom_amt = 10
+/obj/item/twohanded/binoculars/Destroy()
+ listeningTo = null
+ return ..()
+
/obj/item/twohanded/binoculars/wield(mob/user)
. = ..()
if(!wielded)
return
- if(QDELETED(mobhook))
- mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/unwield)))
- else
- user.TakeComponent(mobhook)
+ RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/unwield)
+ listeningTo = user
user.visible_message("[user] holds [src] up to [user.p_their()] eyes.","You hold [src] up to your eyes.")
item_state = "binoculars_wielded"
user.regenerate_icons()
@@ -882,7 +884,8 @@
/obj/item/twohanded/binoculars/unwield(mob/user)
. = ..()
- mobhook.RemoveComponent()
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
+ listeningTo = null
user.visible_message("[user] lowers [src].","You lower [src].")
item_state = "binoculars"
user.regenerate_icons()
diff --git a/code/modules/antagonists/disease/disease_mob.dm b/code/modules/antagonists/disease/disease_mob.dm
index 49c34131fc..faea113ac5 100644
--- a/code/modules/antagonists/disease/disease_mob.dm
+++ b/code/modules/antagonists/disease/disease_mob.dm
@@ -31,7 +31,6 @@ the new instance inside the host to be updated to the template's stats.
var/browser_open = FALSE
var/mob/living/following_host
- var/datum/component/redirect/move_listener
var/list/disease_instances
var/list/hosts //this list is associative, affected_mob -> disease_instance
var/datum/disease/advance/sentient_disease/disease_template
@@ -261,16 +260,10 @@ the new instance inside the host to be updated to the template's stats.
refresh_adaptation_menu()
/mob/camera/disease/proc/set_following(mob/living/L)
+ if(following_host)
+ UnregisterSignal(following_host, COMSIG_MOVABLE_MOVED)
+ RegisterSignal(L, COMSIG_MOVABLE_MOVED, .proc/follow_mob)
following_host = L
- if(!move_listener)
- move_listener = L.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/follow_mob)))
- else
- if(L)
- L.TakeComponent(move_listener)
- if(QDELING(move_listener))
- move_listener = null
- else
- QDEL_NULL(move_listener)
follow_mob()
/mob/camera/disease/proc/follow_next(reverse = FALSE)
diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm
index 07f31a6678..7405549b3d 100644
--- a/code/modules/assembly/infrared.dm
+++ b/code/modules/assembly/infrared.dm
@@ -10,7 +10,7 @@
var/maxlength = 8
var/list/obj/effect/beam/i_beam/beams
var/olddir = 0
- var/datum/component/redirect/listener
+ var/turf/listeningTo
var/hearing_range = 3
/obj/item/assembly/infra/Initialize()
@@ -33,7 +33,7 @@
/obj/item/assembly/infra/Destroy()
STOP_PROCESSING(SSobj, src)
- QDEL_NULL(listener)
+ listeningTo = null
QDEL_LIST(beams)
. = ..()
@@ -163,8 +163,12 @@
next_activate = world.time + 30
/obj/item/assembly/infra/proc/switchListener(turf/newloc)
- QDEL_NULL(listener)
- listener = newloc.AddComponent(/datum/component/redirect, list(COMSIG_ATOM_EXITED = CALLBACK(src, .proc/check_exit)))
+ if(listeningTo == newloc)
+ return
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_ATOM_EXITED)
+ RegisterSignal(newloc, COMSIG_ATOM_EXITED, .proc/check_exit)
+ listeningTo = newloc
/obj/item/assembly/infra/proc/check_exit(datum/source, atom/movable/offender)
if(QDELETED(src))
diff --git a/code/modules/clothing/gloves/_gloves.dm b/code/modules/clothing/gloves/_gloves.dm
index f0c1eeb833..2bb6100298 100644
--- a/code/modules/clothing/gloves/_gloves.dm
+++ b/code/modules/clothing/gloves/_gloves.dm
@@ -14,7 +14,7 @@
/obj/item/clothing/gloves/ComponentInitialize()
. = ..()
- AddComponent(/datum/component/redirect, list(COMSIG_COMPONENT_CLEAN_ACT = CALLBACK(src, .proc/clean_blood)))
+ RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_blood)
/obj/item/clothing/gloves/proc/clean_blood(datum/source, strength)
if(strength < CLEAN_STRENGTH_BLOOD)
diff --git a/code/modules/clothing/shoes/_shoes.dm b/code/modules/clothing/shoes/_shoes.dm
index 00cb2678cd..4118a149a8 100644
--- a/code/modules/clothing/shoes/_shoes.dm
+++ b/code/modules/clothing/shoes/_shoes.dm
@@ -21,7 +21,7 @@
/obj/item/clothing/shoes/ComponentInitialize()
. = ..()
- AddComponent(/datum/component/redirect, list(COMSIG_COMPONENT_CLEAN_ACT = CALLBACK(src, .proc/clean_blood)))
+ RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_blood)
/obj/item/clothing/shoes/suicide_act(mob/living/carbon/user)
if(rand(2)>1)
diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm
index 2694497579..b2aac5407e 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -605,7 +605,6 @@
armor = list("melee" = 30, "bullet" = 5, "laser" = 5, "energy" = 0, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 75)
item_color = "ancient"
resistance_flags = FIRE_PROOF
- var/datum/component/mobhook
/obj/item/clothing/suit/space/hardsuit/ancient
name = "prototype RIG hardsuit"
@@ -617,7 +616,7 @@
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ancient
resistance_flags = FIRE_PROOF
var/footstep = 1
- var/datum/component/mobhook
+ var/mob/listeningTo
/obj/item/clothing/suit/space/hardsuit/ancient/mason
name = "M.A.S.O.N RIG"
@@ -674,20 +673,24 @@
/obj/item/clothing/suit/space/hardsuit/ancient/equipped(mob/user, slot)
. = ..()
- if (slot == SLOT_WEAR_SUIT)
- if (mobhook && mobhook.parent != user)
- QDEL_NULL(mobhook)
- if (!mobhook)
- mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/on_mob_move)))
- else
- QDEL_NULL(mobhook)
+ if(slot != SLOT_WEAR_SUIT)
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
+ return
+ if(listeningTo == user)
+ return
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
+ RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/on_mob_move)
+ listeningTo = user
/obj/item/clothing/suit/space/hardsuit/ancient/dropped()
. = ..()
- QDEL_NULL(mobhook)
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
/obj/item/clothing/suit/space/hardsuit/ancient/Destroy()
- QDEL_NULL(mobhook) // mobhook is not our component
+ listeningTo = null
return ..()
/////////////SHIELDED//////////////////////////////////
diff --git a/code/modules/fields/fields.dm b/code/modules/fields/fields.dm
index 5e34c934d9..5b0b4bc1f8 100644
--- a/code/modules/fields/fields.dm
+++ b/code/modules/fields/fields.dm
@@ -283,7 +283,7 @@
var/field_type = /datum/proximity_monitor/advanced/debug
var/operating = FALSE
var/datum/proximity_monitor/advanced/current = null
- var/datum/component/mobhook
+ var/mob/listeningTo
/obj/item/multitool/field_debug/Initialize()
. = ..()
@@ -292,7 +292,7 @@
/obj/item/multitool/field_debug/Destroy()
STOP_PROCESSING(SSobj, src)
QDEL_NULL(current)
- QDEL_NULL(mobhook)
+ listeningTo = null
return ..()
/obj/item/multitool/field_debug/proc/setup_debug_field()
@@ -303,16 +303,20 @@
/obj/item/multitool/field_debug/attack_self(mob/user)
operating = !operating
to_chat(user, "You turn [src] [operating? "on":"off"].")
- QDEL_NULL(mobhook)
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
+ listeningTo = null
if(!istype(current) && operating)
- mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/on_mob_move)))
+ RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/on_mob_move)
+ listeningTo = user
setup_debug_field()
else if(!operating)
QDEL_NULL(current)
/obj/item/multitool/field_debug/dropped()
. = ..()
- QDEL_NULL(mobhook)
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
+ listeningTo = null
/obj/item/multitool/field_debug/proc/on_mob_move()
check_turf(get_turf(src))
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 02e6043462..98b885fa74 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -32,7 +32,7 @@
if(CONFIG_GET(flag/disable_stambuffer))
togglesprint()
- AddComponent(/datum/component/redirect, list(COMSIG_COMPONENT_CLEAN_ACT = CALLBACK(src, .proc/clean_blood)))
+ RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_blood)
/mob/living/carbon/human/ComponentInitialize()
diff --git a/code/modules/projectiles/guns/misc/beam_rifle.dm b/code/modules/projectiles/guns/misc/beam_rifle.dm
index e4d13ad315..b6e6a01dbd 100644
--- a/code/modules/projectiles/guns/misc/beam_rifle.dm
+++ b/code/modules/projectiles/guns/misc/beam_rifle.dm
@@ -45,7 +45,7 @@
var/aiming_lastangle = 0
var/mob/current_user = null
var/list/obj/effect/projectile/tracer/current_tracers
-
+
var/structure_piercing = 1
var/structure_bleed_coeff = 0.7
var/wall_pierce_amount = 0
@@ -76,7 +76,7 @@
var/static/image/drained_overlay = image(icon = 'icons/obj/guns/energy.dmi', icon_state = "esniper_empty")
var/datum/action/item_action/zoom_lock_action/zoom_lock_action
- var/datum/component/mobhook
+ var/mob/listeningTo
/obj/item/gun/energy/beam_rifle/debug
delay = 0
@@ -172,7 +172,7 @@
STOP_PROCESSING(SSfastprocess, src)
set_user(null)
QDEL_LIST(current_tracers)
- QDEL_NULL(mobhook)
+ listeningTo = null
return ..()
/obj/item/gun/energy/beam_rifle/emp_act(severity)
@@ -259,14 +259,17 @@
if(user == current_user)
return
stop_aiming(current_user)
- QDEL_NULL(mobhook)
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
+ listeningTo = null
if(istype(current_user))
LAZYREMOVE(current_user.mousemove_intercept_objects, src)
current_user = null
if(istype(user))
current_user = user
LAZYOR(current_user.mousemove_intercept_objects, src)
- mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/on_mob_move)))
+ RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/on_mob_move)
+ listeningTo = user
/obj/item/gun/energy/beam_rifle/onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
if(aiming)
diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
index b9e7122d07..6ad4ec34f8 100644
--- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
+++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
@@ -64,10 +64,9 @@
var/interrupted = FALSE
var/mob/target
var/icon/bluespace
- var/datum/weakref/redirect_component
/datum/status_effect/slimerecall/on_apply()
- redirect_component = WEAKREF(owner.AddComponent(/datum/component/redirect, list(COMSIG_LIVING_RESIST = CALLBACK(src, .proc/resistField))))
+ RegisterSignal(owner, COMSIG_LIVING_RESIST, .proc/resistField)
to_chat(owner, "You feel a sudden tug from an unknown force, and feel a pull to bluespace!")
to_chat(owner, "Resist if you wish avoid the force!")
bluespace = icon('icons/effects/effects.dmi',"chronofield")
@@ -77,9 +76,9 @@
/datum/status_effect/slimerecall/proc/resistField()
interrupted = TRUE
owner.remove_status_effect(src)
+
/datum/status_effect/slimerecall/on_remove()
- qdel(redirect_component.resolve())
- redirect_component = null
+ UnregisterSignal(owner, COMSIG_LIVING_RESIST)
owner.cut_overlay(bluespace)
if(interrupted || !ismob(target))
to_chat(owner, "The bluespace tug fades away, and you feel that the force has passed you by.")
@@ -98,10 +97,9 @@
duration = -1 //Will remove self when block breaks.
alert_type = /obj/screen/alert/status_effect/freon/stasis
var/obj/structure/ice_stasis/cube
- var/datum/weakref/redirect_component
/datum/status_effect/frozenstasis/on_apply()
- redirect_component = WEAKREF(owner.AddComponent(/datum/component/redirect, list(COMSIG_LIVING_RESIST = CALLBACK(src, .proc/breakCube))))
+ RegisterSignal(owner, COMSIG_LIVING_RESIST, .proc/breakCube)
cube = new /obj/structure/ice_stasis(get_turf(owner))
owner.forceMove(cube)
owner.status_flags |= GODMODE
@@ -118,8 +116,7 @@
if(cube)
qdel(cube)
owner.status_flags &= ~GODMODE
- qdel(redirect_component.resolve())
- redirect_component = null
+ UnregisterSignal(owner, COMSIG_LIVING_RESIST)
/datum/status_effect/slime_clone
id = "slime_cloned"
diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm
index 5aebd1bafa..594ca117d7 100644
--- a/code/modules/research/xenobiology/xenobio_camera.dm
+++ b/code/modules/research/xenobiology/xenobio_camera.dm
@@ -29,8 +29,6 @@
var/datum/action/innate/slime_scan/scan_action
var/datum/action/innate/feed_potion/potion_action
- var/datum/component/redirect/listener
-
var/list/stored_slimes
var/obj/item/slimepotion/slime/current_potion
var/max_slimes = 5
@@ -50,7 +48,7 @@
scan_action = new
potion_action = new
stored_slimes = list()
- listener = AddComponent(/datum/component/redirect, list(COMSIG_ATOM_CONTENTS_DEL = CALLBACK(src, .proc/on_contents_del)))
+ RegisterSignal(src, COMSIG_ATOM_CONTENTS_DEL, .proc/on_contents_del)
/obj/machinery/computer/camera_advanced/xenobio/Destroy()
stored_slimes = null
diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm
index 8da5d7c113..642052026b 100644
--- a/code/modules/unit_tests/_unit_tests.dm
+++ b/code/modules/unit_tests/_unit_tests.dm
@@ -2,6 +2,7 @@
//Keep this sorted alphabetically
#ifdef UNIT_TESTS
+#include "component_tests.dm"
#include "reagent_id_typos.dm"
#include "reagent_recipe_collisions.dm"
#include "spawn_humans.dm"
diff --git a/code/modules/unit_tests/component_tests.dm b/code/modules/unit_tests/component_tests.dm
new file mode 100644
index 0000000000..409d7f4322
--- /dev/null
+++ b/code/modules/unit_tests/component_tests.dm
@@ -0,0 +1,12 @@
+/datum/unit_test/component_duping/Run()
+ var/list/bad_dms = list()
+ var/list/bad_dts = list()
+ for(var/t in typesof(/datum/component))
+ var/datum/component/comp = t
+ if(!isnum(initial(comp.dupe_mode)))
+ bad_dms += t
+ var/dupe_type = initial(comp.dupe_type)
+ if(dupe_type && !ispath(dupe_type))
+ bad_dts += t
+ if(length(bad_dms) || length(bad_dts))
+ Fail("Components with invalid dupe modes: ([bad_dms.Join(",")]) ||| Components with invalid dupe types: ([bad_dts.Join(",")])")
\ No newline at end of file
diff --git a/modular_citadel/code/datums/components/phantomthief.dm b/modular_citadel/code/datums/components/phantomthief.dm
deleted file mode 100644
index d34e16f6e9..0000000000
--- a/modular_citadel/code/datums/components/phantomthief.dm
+++ /dev/null
@@ -1,49 +0,0 @@
-//This component applies a customizable drop_shadow filter to its wearer when they toggle combat mode on or off. This can stack.
-
-/datum/component/phantomthief
- dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
-
- var/filter_x
- var/filter_y
- var/filter_size
- var/filter_border
- var/filter_color
-
- var/datum/component/redirect/combattoggle_redir
-
-/datum/component/phantomthief/Initialize(_x = -2, _y = 0, _size = 0, _border = 0, _color = "#E62111")
- filter_x = _x
- filter_y = _y
- filter_size = _size
- filter_border = _border
- filter_color = _color
-
- RegisterSignal(parent, COMSIG_COMBAT_TOGGLED, .proc/handlefilterstuff)
- RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/OnEquipped)
- RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/OnDropped)
-
-/datum/component/phantomthief/proc/handlefilterstuff(mob/user, combatmodestate)
- if(istype(user))
- var/thefilter = filter(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, border = filter_border, color = filter_color)
- if(!combatmodestate)
- user.filters -= thefilter
- else
- user.filters += thefilter
-
-/datum/component/phantomthief/proc/stripdesiredfilter(mob/user)
- if(istype(user))
- var/thefilter = filter(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, border = filter_border, color = filter_color)
- user.filters -= thefilter
-
-/datum/component/phantomthief/proc/OnEquipped(mob/user, slot)
- if(!istype(user))
- return
- if(!combattoggle_redir)
- combattoggle_redir = user.AddComponent(/datum/component/redirect, list(COMSIG_COMBAT_TOGGLED = CALLBACK(src, .proc/handlefilterstuff)))
-
-/datum/component/phantomthief/proc/OnDropped(mob/user)
- if(!istype(user))
- return
- if(combattoggle_redir)
- QDEL_NULL(combattoggle_redir)
- stripdesiredfilter(user)
diff --git a/modular_citadel/code/modules/clothing/glasses/phantomthief.dm b/modular_citadel/code/modules/clothing/glasses/phantomthief.dm
index 1b13ba5dc8..5e488b9837 100644
--- a/modular_citadel/code/modules/clothing/glasses/phantomthief.dm
+++ b/modular_citadel/code/modules/clothing/glasses/phantomthief.dm
@@ -6,30 +6,28 @@
icon_state = "s-ninja"
item_state = "s-ninja"
-/obj/item/clothing/glasses/phantomthief/Initialize()
+/obj/item/clothing/glasses/phantomthief/ComponentInitialize()
. = ..()
- AddComponent(/datum/component/phantomthief)
+ AddComponent(/datum/component/wearertargeting/phantomthief)
/obj/item/clothing/glasses/phantomthief/syndicate
name = "suspicious plastic mask"
desc = "A cheap, bulky, Syndicate-branded plastic face mask. You have to break in to break out."
var/nextadrenalinepop
- var/datum/component/redirect/combattoggle_redir
-/obj/item/clothing/glasses/phantomthief/syndicate/examine(user)
+/obj/item/clothing/glasses/phantomthief/syndicate/examine(mob/user)
. = ..()
- if(combattoggle_redir)
+ if(user.get_item_by_slot(SLOT_GLASSES) == src)
if(world.time >= nextadrenalinepop)
to_chat(user, "The built-in adrenaline injector is ready for use.")
else
to_chat(user, "[DisplayTimeText(nextadrenalinepop - world.time)] left before the adrenaline injector can be used again.")
/obj/item/clothing/glasses/phantomthief/syndicate/proc/injectadrenaline(mob/user, combatmodestate)
- if(istype(user))
- if(combatmodestate && world.time >= nextadrenalinepop)
- nextadrenalinepop = world.time + 5 MINUTES
- user.reagents.add_reagent("syndicateadrenals", 5)
- user.playsound_local(user, 'modular_citadel/sound/misc/adrenalinject.ogg', 100, 0, pressure_affected = FALSE)
+ if(istype(user) && combatmodestate && world.time >= nextadrenalinepop)
+ nextadrenalinepop = world.time + 5 MINUTES
+ user.reagents.add_reagent("syndicateadrenals", 5)
+ user.playsound_local(user, 'modular_citadel/sound/misc/adrenalinject.ogg', 100, 0, pressure_affected = FALSE)
/obj/item/clothing/glasses/phantomthief/syndicate/equipped(mob/user, slot)
. = ..()
@@ -37,12 +35,10 @@
return
if(slot != SLOT_GLASSES)
return
- if(!combattoggle_redir)
- combattoggle_redir = user.AddComponent(/datum/component/redirect, list(COMSIG_COMBAT_TOGGLED = CALLBACK(src, .proc/injectadrenaline)))
+ RegisterSignal(user, COMSIG_COMBAT_TOGGLED, .proc/injectadrenaline)
/obj/item/clothing/glasses/phantomthief/syndicate/dropped(mob/user)
. = ..()
if(!istype(user))
return
- if(combattoggle_redir)
- QDEL_NULL(combattoggle_redir)
+ UnregisterSignal(user, COMSIG_COMBAT_TOGGLED)
diff --git a/tgstation.dme b/tgstation.dme
index 702f34f80c..c259f24df7 100755
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -370,12 +370,12 @@
#include "code\datums\components\ntnet_interface.dm"
#include "code\datums\components\orbiter.dm"
#include "code\datums\components\paintable.dm"
+#include "code\datums\components\phantomthief.dm"
#include "code\datums\components\rad_insulation.dm"
#include "code\datums\components\radioactive.dm"
#include "code\datums\components\remote_materials.dm"
#include "code\datums\components\riding.dm"
#include "code\datums\components\rotation.dm"
-#include "code\datums\components\signal_redirect.dm"
#include "code\datums\components\slippery.dm"
#include "code\datums\components\spooky.dm"
#include "code\datums\components\squeak.dm"
@@ -2947,7 +2947,6 @@
#include "modular_citadel\code\controllers\subsystem\job.dm"
#include "modular_citadel\code\controllers\subsystem\shuttle.dm"
#include "modular_citadel\code\datums\components\material_container.dm"
-#include "modular_citadel\code\datums\components\phantomthief.dm"
#include "modular_citadel\code\datums\components\souldeath.dm"
#include "modular_citadel\code\datums\mood_events\chem_events.dm"
#include "modular_citadel\code\datums\mood_events\generic_negative_events.dm"