Porting components updates and fixing phantom thief component.

This commit is contained in:
Ghommie
2019-10-23 13:01:31 +02:00
parent 432a7dba5d
commit fc1f10c97f
41 changed files with 271 additions and 253 deletions

View File

@@ -7,6 +7,7 @@
#define GET_COMPONENT(varname, path) GET_COMPONENT_FROM(varname, path, src) #define GET_COMPONENT(varname, path) GET_COMPONENT_FROM(varname, path, src)
#define COMPONENT_INCOMPATIBLE 1 #define COMPONENT_INCOMPATIBLE 1
#define COMPONENT_NOTRANSFER 2
// How multiple components of the exact same type are handled in the same datum // How multiple components of the exact same type are handled in the same datum

View File

@@ -1550,3 +1550,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
for(var/i in L) for(var/i in L)
if(condition.Invoke(i)) if(condition.Invoke(i))
. |= i . |= i
/proc/CallAsync(datum/source, proctype, list/arguments)
set waitfor = FALSE
return call(source, proctype)(arglist(arguments))

View File

@@ -6,11 +6,9 @@ SUBSYSTEM_DEF(vis_overlays)
var/list/vis_overlay_cache var/list/vis_overlay_cache
var/list/currentrun var/list/currentrun
var/datum/callback/rotate_cb
/datum/controller/subsystem/vis_overlays/Initialize() /datum/controller/subsystem/vis_overlays/Initialize()
vis_overlay_cache = list() vis_overlay_cache = list()
rotate_cb = CALLBACK(src, .proc/rotate_vis_overlay)
return ..() return ..()
/datum/controller/subsystem/vis_overlays/fire(resumed = FALSE) /datum/controller/subsystem/vis_overlays/fire(resumed = FALSE)
@@ -52,7 +50,7 @@ SUBSYSTEM_DEF(vis_overlays)
if(!thing.managed_vis_overlays) if(!thing.managed_vis_overlays)
thing.managed_vis_overlays = list(overlay) 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 else
thing.managed_vis_overlays += overlay thing.managed_vis_overlays += overlay

View File

@@ -2,6 +2,10 @@
var/dupe_mode = COMPONENT_DUPE_HIGHLANDER var/dupe_mode = COMPONENT_DUPE_HIGHLANDER
var/dupe_type var/dupe_type
var/datum/parent 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, ...) /datum/component/New(datum/P, ...)
parent = P parent = P
@@ -83,7 +87,7 @@
/datum/component/proc/UnregisterFromParent() /datum/component/proc/UnregisterFromParent()
return 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)) if(QDELETED(src) || QDELETED(target))
return return
@@ -96,15 +100,12 @@
if(!lookup) if(!lookup)
target.comp_lookup = lookup = list() 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) 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) for(var/sig_type in sig_types)
if(!override && procs[target][sig_type]) if(!override && procs[target][sig_type])
stack_trace("[sig_type] overridden. Use override = TRUE to suppress this warning") 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 if(!lookup[sig_type]) // Nothing has registered here yet
lookup[sig_type] = src lookup[sig_type] = src
@@ -154,7 +155,7 @@
return return
/datum/component/proc/PostTransfer() /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) /datum/component/proc/_GetInverseTypeList(our_type = type)
//we can do this one simple trick //we can do this one simple trick
@@ -171,17 +172,20 @@
var/datum/C = target var/datum/C = target
if(!C.signal_enabled) if(!C.signal_enabled)
return NONE return NONE
var/datum/callback/CB = C.signal_procs[src][sigtype] var/proctype = C.signal_procs[src][sigtype]
return CB.InvokeAsync(arglist(arguments)) return NONE | CallAsync(C, proctype, arguments)
. = NONE . = NONE
for(var/I in target) for(var/I in target)
var/datum/C = I var/datum/C = I
if(!C.signal_enabled) if(!C.signal_enabled)
continue continue
var/datum/callback/CB = C.signal_procs[src][sigtype] var/proctype = C.signal_procs[src][sigtype]
. |= CB.InvokeAsync(arglist(arguments)) . |= 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 var/list/dc = datum_components
if(!dc) if(!dc)
return null return null
@@ -220,10 +224,6 @@
if(ispath(nt)) if(ispath(nt))
if(nt == /datum/component) if(nt == /datum/component)
CRASH("[nt] attempted instantiation!") CRASH("[nt] attempted instantiation!")
if(!isnum(dm))
CRASH("[nt]: Invalid dupe_mode ([dm])!")
if(dt && !ispath(dt))
CRASH("[nt]: Invalid dupe_type ([dt])!")
else else
new_comp = nt new_comp = nt
nt = new_comp.type nt = new_comp.type
@@ -285,10 +285,13 @@
if(target.parent) if(target.parent)
target.RemoveComponent() target.RemoveComponent()
target.parent = src target.parent = src
if(target.PostTransfer() == COMPONENT_INCOMPATIBLE) var/result = target.PostTransfer()
switch(result)
if(COMPONENT_INCOMPATIBLE)
var/c_type = target.type var/c_type = target.type
qdel(target) qdel(target)
CRASH("Incompatible [c_type] transfer attempt to a [type]!") CRASH("Incompatible [c_type] transfer attempt to a [type]!")
if(target == AddComponent(target)) if(target == AddComponent(target))
target._JoinParent() target._JoinParent()
@@ -298,9 +301,12 @@
return return
var/comps = dc[/datum/component] var/comps = dc[/datum/component]
if(islist(comps)) if(islist(comps))
for(var/I in comps) for(var/datum/component/I in comps)
if(I.can_transfer)
target.TakeComponent(I) target.TakeComponent(I)
else else
var/datum/component/C = comps
if(C.can_transfer)
target.TakeComponent(comps) target.TakeComponent(comps)
/datum/component/ui_host() /datum/component/ui_host()

View File

@@ -1,6 +1,6 @@
/datum/component/decal /datum/component/decal
dupe_mode = COMPONENT_DUPE_ALLOWED dupe_mode = COMPONENT_DUPE_ALLOWED
can_transfer = TRUE
var/cleanable var/cleanable
var/description var/description
var/mutable_appearance/pic var/mutable_appearance/pic

View File

@@ -1,11 +1,11 @@
/datum/component/wearertargeting/earprotection /datum/component/wearertargeting/earprotection
signals = list(COMSIG_CARBON_SOUNDBANG) signals = list(COMSIG_CARBON_SOUNDBANG)
mobtype = /mob/living/carbon mobtype = /mob/living/carbon
proctype = .proc/reducebang
/datum/component/wearertargeting/earprotection/Initialize(_valid_slots) /datum/component/wearertargeting/earprotection/Initialize(_valid_slots)
. = ..() . = ..()
valid_slots = _valid_slots valid_slots = _valid_slots
callback = CALLBACK(src, .proc/reducebang)
/datum/component/wearertargeting/earprotection/proc/reducebang(datum/source, list/reflist) /datum/component/wearertargeting/earprotection/proc/reducebang(datum/source, list/reflist)
reflist[1]-- reflist[1]--

View File

@@ -1,5 +1,6 @@
/datum/component/forensics /datum/component/forensics
dupe_mode = COMPONENT_DUPE_UNIQUE dupe_mode = COMPONENT_DUPE_UNIQUE
can_transfer = TRUE
var/list/fingerprints //assoc print = print var/list/fingerprints //assoc print = print
var/list/hiddenprints //assoc ckey = realname/gloves/ckey var/list/hiddenprints //assoc ckey = realname/gloves/ckey
var/list/blood_DNA //assoc dna = bloodtype var/list/blood_DNA //assoc dna = bloodtype
@@ -21,8 +22,18 @@
blood_DNA = new_blood_DNA blood_DNA = new_blood_DNA
fibers = new_fibers fibers = new_fibers
check_blood() check_blood()
/datum/component/forensics/RegisterWithParent()
check_blood()
RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_act) 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() /datum/component/forensics/proc/wipe_fingerprints()
fingerprints = null fingerprints = null
return TRUE return TRUE

View File

@@ -237,6 +237,3 @@
LOCKON_RANGING_BREAK_CHECK LOCKON_RANGING_BREAK_CHECK
cd++ cd++
CHECK_TICK CHECK_TICK
/datum/component/lockon_aiming/PostTransfer(datum/new_parent)
return COMPONENT_INCOMPATIBLE

View File

@@ -1,4 +1,5 @@
/datum/component/mirage_border /datum/component/mirage_border
can_transfer = TRUE
var/obj/effect/abstract/mirage_holder/holder var/obj/effect/abstract/mirage_holder/holder
/datum/component/mirage_border/Initialize(turf/target, direction, range=world.view) /datum/component/mirage_border/Initialize(turf/target, direction, range=world.view)

View File

@@ -1,8 +1,7 @@
/datum/component/orbiter /datum/component/orbiter
can_transfer = TRUE
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
var/list/orbiters 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) //radius: range to orbit at, radius of the circle formed by orbiting (in pixels)
//clockwise: whether you orbit clockwise or anti clockwise //clockwise: whether you orbit clockwise or anti clockwise
@@ -14,8 +13,6 @@
return COMPONENT_INCOMPATIBLE return COMPONENT_INCOMPATIBLE
orbiters = list() orbiters = list()
orbiter_spy = CALLBACK(src, .proc/orbiter_move_react)
orbited_spy = CALLBACK(src, .proc/move_react)
var/atom/master = parent var/atom/master = parent
master.orbiters = src master.orbiters = src
@@ -25,7 +22,7 @@
/datum/component/orbiter/RegisterWithParent() /datum/component/orbiter/RegisterWithParent()
var/atom/target = parent var/atom/target = parent
while(ismovableatom(target)) while(ismovableatom(target))
RegisterSignal(target, COMSIG_MOVABLE_MOVED, orbited_spy) RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/move_react)
target = target.loc target = target.loc
/datum/component/orbiter/UnregisterFromParent() /datum/component/orbiter/UnregisterFromParent()
@@ -40,8 +37,6 @@
for(var/i in orbiters) for(var/i in orbiters)
end_orbit(i) end_orbit(i)
orbiters = null orbiters = null
QDEL_NULL(orbiter_spy)
QDEL_NULL(orbited_spy)
return ..() return ..()
/datum/component/orbiter/InheritComponent(datum/component/orbiter/newcomp, original, list/arguments) /datum/component/orbiter/InheritComponent(datum/component/orbiter/newcomp, original, list/arguments)
@@ -64,7 +59,7 @@
orbiter.orbiting.end_orbit(orbiter) orbiter.orbiting.end_orbit(orbiter)
orbiters[orbiter] = TRUE orbiters[orbiter] = TRUE
orbiter.orbiting = src 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) var/matrix/initial_transform = matrix(orbiter.transform)
// Head first! // Head first!
@@ -120,7 +115,7 @@
if(orbited?.loc && orbited.loc != newturf) // We want to know when anything holding us moves too if(orbited?.loc && orbited.loc != newturf) // We want to know when anything holding us moves too
var/atom/target = orbited.loc var/atom/target = orbited.loc
while(ismovableatom(target)) while(ismovableatom(target))
RegisterSignal(target, COMSIG_MOVABLE_MOVED, orbited_spy, TRUE) RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/move_react, TRUE)
target = target.loc target = target.loc
var/atom/curloc = master.loc var/atom/curloc = master.loc

View File

@@ -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)

View File

@@ -44,19 +44,21 @@
if(src.rotation_flags & ROTATION_CLOCKWISE) if(src.rotation_flags & ROTATION_CLOCKWISE)
default_rotation_direction = 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_CLICK_ALT, .proc/HandRot)
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/ExamineMessage) 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) 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 var/atom/movable/AM = parent
if(src.rotation_flags & ROTATION_FLIP) if(rotation_flags & ROTATION_FLIP)
AM.verbs += /atom/movable/proc/simple_rotate_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 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 AM.verbs += /atom/movable/proc/simple_rotate_counterclockwise
/datum/component/simple_rotation/proc/remove_verbs() /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_clockwise
AM.verbs -= /atom/movable/proc/simple_rotate_counterclockwise 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_verbs()
remove_signals()
. = ..()
/datum/component/simple_rotation/Destroy()
QDEL_NULL(can_user_rotate) QDEL_NULL(can_user_rotate)
QDEL_NULL(can_be_rotated) QDEL_NULL(can_be_rotated)
QDEL_NULL(after_rotation) QDEL_NULL(after_rotation)
//Signals + verbs removed via UnRegister
. = ..() . = ..()
/datum/component/simple_rotation/RemoveComponent() /datum/component/simple_rotation/RemoveComponent()

View File

@@ -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))

View File

@@ -4,6 +4,7 @@
// /mob/living/Move() in /modules/mob/living/living.dm - hiding storage boxes on mob movement // /mob/living/Move() in /modules/mob/living/living.dm - hiding storage boxes on mob movement
/datum/component/storage/concrete /datum/component/storage/concrete
can_transfer = TRUE
var/drop_all_on_deconstruct = TRUE var/drop_all_on_deconstruct = TRUE
var/drop_all_on_destroy = FALSE var/drop_all_on_destroy = FALSE
var/drop_all_on_break = FALSE var/drop_all_on_break = FALSE

View File

@@ -1,5 +1,5 @@
/datum/component/virtual_reality /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/mastermind // where is my mind t. pixies
var/datum/mind/current_mind var/datum/mind/current_mind
var/obj/machinery/vr_sleeper/vr_sleeper var/obj/machinery/vr_sleeper/vr_sleeper

View File

@@ -3,7 +3,7 @@
/datum/component/wearertargeting /datum/component/wearertargeting
var/list/valid_slots = list() var/list/valid_slots = list()
var/list/signals = list() var/list/signals = list()
var/datum/callback/callback = CALLBACK(GLOBAL_PROC, .proc/pass) var/proctype = .proc/pass
var/mobtype = /mob/living var/mobtype = /mob/living
/datum/component/wearertargeting/Initialize() /datum/component/wearertargeting/Initialize()
@@ -14,13 +14,9 @@
/datum/component/wearertargeting/proc/on_equip(datum/source, mob/equipper, slot) /datum/component/wearertargeting/proc/on_equip(datum/source, mob/equipper, slot)
if((slot in valid_slots) && istype(equipper, mobtype)) if((slot in valid_slots) && istype(equipper, mobtype))
RegisterSignal(equipper, signals, callback, TRUE) RegisterSignal(equipper, signals, proctype, TRUE)
else else
UnregisterSignal(equipper, signals) UnregisterSignal(equipper, signals)
/datum/component/wearertargeting/proc/on_drop(datum/source, mob/user) /datum/component/wearertargeting/proc/on_drop(datum/source, mob/user)
UnregisterSignal(user, signals) UnregisterSignal(user, signals)
/datum/component/wearertargeting/Destroy()
QDEL_NULL(callback) //is likely to ourselves.
return ..()

View File

@@ -1,5 +1,6 @@
/datum/component/wet_floor /datum/component/wet_floor
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
can_transfer = TRUE
var/highest_strength = TURF_DRY var/highest_strength = TURF_DRY
var/lube_flags = NONE //why do we have this? var/lube_flags = NONE //why do we have this?
var/list/time_left_list //In deciseconds. var/list/time_left_list //In deciseconds.
@@ -26,14 +27,19 @@
if(!isopenturf(parent)) if(!isopenturf(parent))
return COMPONENT_INCOMPATIBLE return COMPONENT_INCOMPATIBLE
add_wet(strength, duration_minimum, duration_add, duration_maximum) 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 permanent = _permanent
if(!permanent) if(!permanent)
START_PROCESSING(SSwet_floors, src) START_PROCESSING(SSwet_floors, src)
addtimer(CALLBACK(src, .proc/gc, TRUE), 1) //GC after initialization. addtimer(CALLBACK(src, .proc/gc, TRUE), 1) //GC after initialization.
last_process = world.time 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() /datum/component/wet_floor/Destroy()
STOP_PROCESSING(SSwet_floors, src) STOP_PROCESSING(SSwet_floors, src)
var/turf/T = parent var/turf/T = parent
@@ -138,12 +144,19 @@
/datum/component/wet_floor/PreTransfer() /datum/component/wet_floor/PreTransfer()
var/turf/O = parent var/turf/O = parent
O.cut_overlay(current_overlay) 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() /datum/component/wet_floor/PostTransfer()
if(!isopenturf(parent)) if(!isopenturf(parent))
return COMPONENT_INCOMPATIBLE return COMPONENT_INCOMPATIBLE
var/turf/T = parent var/turf/T = parent
T.add_overlay(current_overlay) 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) /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) var/static/list/allowed_types = list(TURF_WET_WATER, TURF_WET_LUBE, TURF_WET_ICE, TURF_WET_PERMAFROST)

View File

@@ -5,7 +5,6 @@
alert_type = /obj/screen/alert/status_effect/freon alert_type = /obj/screen/alert/status_effect/freon
var/icon/cube var/icon/cube
var/can_melt = TRUE var/can_melt = TRUE
var/datum/weakref/redirect_component
/obj/screen/alert/status_effect/freon /obj/screen/alert/status_effect/freon
name = "Frozen Solid" name = "Frozen Solid"
@@ -13,7 +12,7 @@
icon_state = "frozen" icon_state = "frozen"
/datum/status_effect/freon/on_apply() /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) if(!owner.stat)
to_chat(owner, "<span class='userdanger'>You become frozen in a cube!</span>") to_chat(owner, "<span class='userdanger'>You become frozen in a cube!</span>")
cube = icon('icons/effects/freeze.dmi', "ice_cube") cube = icon('icons/effects/freeze.dmi', "ice_cube")
@@ -40,8 +39,7 @@
owner.cut_overlay(cube) owner.cut_overlay(cube)
owner.adjust_bodytemperature(100) owner.adjust_bodytemperature(100)
owner.update_canmove() owner.update_canmove()
qdel(redirect_component.resolve()) UnregisterSignal(owner, COMSIG_LIVING_RESIST)
redirect_component = null
/datum/status_effect/freon/watcher /datum/status_effect/freon/watcher
duration = 8 duration = 8

View File

@@ -13,7 +13,7 @@
/obj/machinery/washing_machine/ComponentInitialize() /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) /obj/machinery/washing_machine/examine(mob/user)
..() ..()

View File

@@ -5,7 +5,6 @@
var/list/checkers //list of /obj/effect/abstract/proximity_checkers var/list/checkers //list of /obj/effect/abstract/proximity_checkers
var/current_range 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/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) /datum/proximity_monitor/New(atom/_host, range, _ignore_if_not_on_turf = TRUE)
checkers = list() checkers = list()
@@ -15,15 +14,17 @@
SetHost(_host) SetHost(_host)
/datum/proximity_monitor/proc/SetHost(atom/H,atom/R) /datum/proximity_monitor/proc/SetHost(atom/H,atom/R)
if(H == host)
return
if(host)
UnregisterSignal(host, COMSIG_MOVABLE_MOVED)
if(R) if(R)
hasprox_receiver = R hasprox_receiver = R
else if(hasprox_receiver == host) //Default case else if(hasprox_receiver == host) //Default case
hasprox_receiver = H hasprox_receiver = H
host = H host = H
RegisterSignal(host, COMSIG_MOVABLE_MOVED, .proc/HandleMove)
last_host_loc = host.loc 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) SetRange(current_range,TRUE)
/datum/proximity_monitor/Destroy() /datum/proximity_monitor/Destroy()
@@ -31,7 +32,6 @@
last_host_loc = null last_host_loc = null
hasprox_receiver = null hasprox_receiver = null
QDEL_LIST(checkers) QDEL_LIST(checkers)
QDEL_NULL(movement_tracker)
return ..() return ..()
/datum/proximity_monitor/proc/HandleMove() /datum/proximity_monitor/proc/HandleMove()

View File

@@ -20,8 +20,8 @@
var/ghetto = FALSE var/ghetto = FALSE
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
var/datum/component/mobhook
var/datum/radial_menu/persistent/wiring_gui_menu var/datum/radial_menu/persistent/wiring_gui_menu
var/mob/listeningTo
/obj/item/twohanded/rcl/attackby(obj/item/W, mob/user) /obj/item/twohanded/rcl/attackby(obj/item/W, mob/user)
if(istype(W, /obj/item/stack/cable_coil)) if(istype(W, /obj/item/stack/cable_coil))
@@ -86,7 +86,7 @@
/obj/item/twohanded/rcl/Destroy() /obj/item/twohanded/rcl/Destroy()
QDEL_NULL(loaded) QDEL_NULL(loaded)
last = null last = null
QDEL_NULL(mobhook) listeningTo = null
QDEL_NULL(wiring_gui_menu) QDEL_NULL(wiring_gui_menu)
return ..() return ..()
@@ -141,9 +141,8 @@
/obj/item/twohanded/rcl/dropped(mob/wearer) /obj/item/twohanded/rcl/dropped(mob/wearer)
..() ..()
if(mobhook) UnregisterSignal(wearer, COMSIG_MOVABLE_MOVED)
active = FALSE listeningTo = null
QDEL_NULL(mobhook)
last = null last = null
/obj/item/twohanded/rcl/attack_self(mob/user) /obj/item/twohanded/rcl/attack_self(mob/user)
@@ -158,13 +157,12 @@
break break
obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook) obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook)
if(to_hook) if(listeningTo == to_hook)
if(mobhook && mobhook.parent != to_hook) return
QDEL_NULL(mobhook) if(listeningTo)
if (!mobhook) UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
mobhook = to_hook.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/trigger))) RegisterSignal(to_hook, COMSIG_MOVABLE_MOVED, .proc/trigger)
else listeningTo = to_hook
QDEL_NULL(mobhook)
/obj/item/twohanded/rcl/proc/trigger(mob/user) /obj/item/twohanded/rcl/proc/trigger(mob/user)
if(active) if(active)

View File

@@ -297,15 +297,16 @@
var/grab_ghost = FALSE var/grab_ghost = FALSE
var/tlimit = DEFIB_TIME_LIMIT * 10 var/tlimit = DEFIB_TIME_LIMIT * 10
var/datum/component/mobhook var/mob/listeningTo
/obj/item/twohanded/shockpaddles/equipped(mob/user, slot) /obj/item/twohanded/shockpaddles/equipped(mob/user, slot)
. = ..() . = ..()
if(req_defib) if(!req_defib || listeningTo == user)
if (mobhook && mobhook.parent != user) return
QDEL_NULL(mobhook) if(listeningTo)
if (!mobhook) UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/check_range))) RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/check_range)
listeningTo = user
/obj/item/twohanded/shockpaddles/Moved() /obj/item/twohanded/shockpaddles/Moved()
. = ..() . = ..()
@@ -362,8 +363,8 @@
/obj/item/twohanded/shockpaddles/dropped(mob/user) /obj/item/twohanded/shockpaddles/dropped(mob/user)
if(!req_defib) if(!req_defib)
return ..() return ..()
if (mobhook) if(listeningTo)
QDEL_NULL(mobhook) UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
if(user) if(user)
var/obj/item/twohanded/offhand/O = user.get_inactive_held_item() var/obj/item/twohanded/offhand/O = user.get_inactive_held_item()
if(istype(O)) if(istype(O))

View File

@@ -203,21 +203,25 @@
return TRUE return TRUE
/obj/item/geiger_counter/cyborg /obj/item/geiger_counter/cyborg
var/datum/component/mobhook var/mob/listeningTo
/obj/item/geiger_counter/cyborg/equipped(mob/user) /obj/item/geiger_counter/cyborg/equipped(mob/user)
. = ..() . = ..()
if (mobhook && mobhook.parent != user) if(listeningTo == user)
QDEL_NULL(mobhook) return
if (!mobhook) if(listeningTo)
mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_ATOM_RAD_ACT = CALLBACK(src, .proc/redirect_rad_act))) 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) /obj/item/geiger_counter/cyborg/proc/redirect_rad_act(datum/source, amount)
rad_act(amount) rad_act(amount)
/obj/item/geiger_counter/cyborg/dropped() /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_NORMAL
#undef RAD_LEVEL_MODERATE #undef RAD_LEVEL_MODERATE

View File

@@ -29,7 +29,7 @@
. = ..() . = ..()
START_PROCESSING(SSprocessing, src) START_PROCESSING(SSprocessing, src)
GLOB.poi_list += 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() /obj/item/his_grace/Destroy()
STOP_PROCESSING(SSprocessing, src) STOP_PROCESSING(SSprocessing, src)

View File

@@ -105,7 +105,7 @@
w_class = WEIGHT_CLASS_NORMAL w_class = WEIGHT_CLASS_NORMAL
component_type = /datum/component/storage/concrete/stack 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/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 rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
/obj/item/storage/bag/ore/ComponentInitialize() /obj/item/storage/bag/ore/ComponentInitialize()
@@ -118,15 +118,17 @@
/obj/item/storage/bag/ore/equipped(mob/user) /obj/item/storage/bag/ore/equipped(mob/user)
. = ..() . = ..()
if (mobhook && mobhook.parent != user) if(listeningTo == user)
QDEL_NULL(mobhook) return
if (!mobhook) if(listeningTo)
mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/Pickup_ores))) UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/Pickup_ores)
listeningTo = user
/obj/item/storage/bag/ore/dropped() /obj/item/storage/bag/ore/dropped()
. = ..() . = ..()
if (mobhook) UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
QDEL_NULL(mobhook) listeningTo = null
/obj/item/storage/bag/ore/proc/Pickup_ores(mob/living/user) /obj/item/storage/bag/ore/proc/Pickup_ores(mob/living/user)
var/show_message = FALSE var/show_message = FALSE

View File

@@ -847,18 +847,20 @@
righthand_file = 'icons/mob/inhands/items_righthand.dmi' righthand_file = 'icons/mob/inhands/items_righthand.dmi'
slot_flags = ITEM_SLOT_BELT slot_flags = ITEM_SLOT_BELT
w_class = WEIGHT_CLASS_SMALL w_class = WEIGHT_CLASS_SMALL
var/datum/component/mobhook var/mob/listeningTo
var/zoom_out_amt = 6 var/zoom_out_amt = 6
var/zoom_amt = 10 var/zoom_amt = 10
/obj/item/twohanded/binoculars/Destroy()
listeningTo = null
return ..()
/obj/item/twohanded/binoculars/wield(mob/user) /obj/item/twohanded/binoculars/wield(mob/user)
. = ..() . = ..()
if(!wielded) if(!wielded)
return return
if(QDELETED(mobhook)) RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/unwield)
mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/unwield))) listeningTo = user
else
user.TakeComponent(mobhook)
user.visible_message("[user] holds [src] up to [user.p_their()] eyes.","You hold [src] up to your eyes.") user.visible_message("[user] holds [src] up to [user.p_their()] eyes.","You hold [src] up to your eyes.")
item_state = "binoculars_wielded" item_state = "binoculars_wielded"
user.regenerate_icons() user.regenerate_icons()
@@ -882,7 +884,8 @@
/obj/item/twohanded/binoculars/unwield(mob/user) /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].") user.visible_message("[user] lowers [src].","You lower [src].")
item_state = "binoculars" item_state = "binoculars"
user.regenerate_icons() user.regenerate_icons()

View File

@@ -31,7 +31,6 @@ the new instance inside the host to be updated to the template's stats.
var/browser_open = FALSE var/browser_open = FALSE
var/mob/living/following_host var/mob/living/following_host
var/datum/component/redirect/move_listener
var/list/disease_instances var/list/disease_instances
var/list/hosts //this list is associative, affected_mob -> disease_instance var/list/hosts //this list is associative, affected_mob -> disease_instance
var/datum/disease/advance/sentient_disease/disease_template 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() refresh_adaptation_menu()
/mob/camera/disease/proc/set_following(mob/living/L) /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 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() follow_mob()
/mob/camera/disease/proc/follow_next(reverse = FALSE) /mob/camera/disease/proc/follow_next(reverse = FALSE)

View File

@@ -10,7 +10,7 @@
var/maxlength = 8 var/maxlength = 8
var/list/obj/effect/beam/i_beam/beams var/list/obj/effect/beam/i_beam/beams
var/olddir = 0 var/olddir = 0
var/datum/component/redirect/listener var/turf/listeningTo
var/hearing_range = 3 var/hearing_range = 3
/obj/item/assembly/infra/Initialize() /obj/item/assembly/infra/Initialize()
@@ -33,7 +33,7 @@
/obj/item/assembly/infra/Destroy() /obj/item/assembly/infra/Destroy()
STOP_PROCESSING(SSobj, src) STOP_PROCESSING(SSobj, src)
QDEL_NULL(listener) listeningTo = null
QDEL_LIST(beams) QDEL_LIST(beams)
. = ..() . = ..()
@@ -163,8 +163,12 @@
next_activate = world.time + 30 next_activate = world.time + 30
/obj/item/assembly/infra/proc/switchListener(turf/newloc) /obj/item/assembly/infra/proc/switchListener(turf/newloc)
QDEL_NULL(listener) if(listeningTo == newloc)
listener = newloc.AddComponent(/datum/component/redirect, list(COMSIG_ATOM_EXITED = CALLBACK(src, .proc/check_exit))) 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) /obj/item/assembly/infra/proc/check_exit(datum/source, atom/movable/offender)
if(QDELETED(src)) if(QDELETED(src))

View File

@@ -14,7 +14,7 @@
/obj/item/clothing/gloves/ComponentInitialize() /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) /obj/item/clothing/gloves/proc/clean_blood(datum/source, strength)
if(strength < CLEAN_STRENGTH_BLOOD) if(strength < CLEAN_STRENGTH_BLOOD)

View File

@@ -21,7 +21,7 @@
/obj/item/clothing/shoes/ComponentInitialize() /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) /obj/item/clothing/shoes/suicide_act(mob/living/carbon/user)
if(rand(2)>1) if(rand(2)>1)

View File

@@ -605,7 +605,6 @@
armor = list("melee" = 30, "bullet" = 5, "laser" = 5, "energy" = 0, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 75) armor = list("melee" = 30, "bullet" = 5, "laser" = 5, "energy" = 0, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 75)
item_color = "ancient" item_color = "ancient"
resistance_flags = FIRE_PROOF resistance_flags = FIRE_PROOF
var/datum/component/mobhook
/obj/item/clothing/suit/space/hardsuit/ancient /obj/item/clothing/suit/space/hardsuit/ancient
name = "prototype RIG hardsuit" name = "prototype RIG hardsuit"
@@ -617,7 +616,7 @@
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ancient helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ancient
resistance_flags = FIRE_PROOF resistance_flags = FIRE_PROOF
var/footstep = 1 var/footstep = 1
var/datum/component/mobhook var/mob/listeningTo
/obj/item/clothing/suit/space/hardsuit/ancient/mason /obj/item/clothing/suit/space/hardsuit/ancient/mason
name = "M.A.S.O.N RIG" name = "M.A.S.O.N RIG"
@@ -674,20 +673,24 @@
/obj/item/clothing/suit/space/hardsuit/ancient/equipped(mob/user, slot) /obj/item/clothing/suit/space/hardsuit/ancient/equipped(mob/user, slot)
. = ..() . = ..()
if (slot == SLOT_WEAR_SUIT) if(slot != SLOT_WEAR_SUIT)
if (mobhook && mobhook.parent != user) if(listeningTo)
QDEL_NULL(mobhook) UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
if (!mobhook) return
mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/on_mob_move))) if(listeningTo == user)
else return
QDEL_NULL(mobhook) 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() /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() /obj/item/clothing/suit/space/hardsuit/ancient/Destroy()
QDEL_NULL(mobhook) // mobhook is not our component listeningTo = null
return ..() return ..()
/////////////SHIELDED////////////////////////////////// /////////////SHIELDED//////////////////////////////////

View File

@@ -283,7 +283,7 @@
var/field_type = /datum/proximity_monitor/advanced/debug var/field_type = /datum/proximity_monitor/advanced/debug
var/operating = FALSE var/operating = FALSE
var/datum/proximity_monitor/advanced/current = null var/datum/proximity_monitor/advanced/current = null
var/datum/component/mobhook var/mob/listeningTo
/obj/item/multitool/field_debug/Initialize() /obj/item/multitool/field_debug/Initialize()
. = ..() . = ..()
@@ -292,7 +292,7 @@
/obj/item/multitool/field_debug/Destroy() /obj/item/multitool/field_debug/Destroy()
STOP_PROCESSING(SSobj, src) STOP_PROCESSING(SSobj, src)
QDEL_NULL(current) QDEL_NULL(current)
QDEL_NULL(mobhook) listeningTo = null
return ..() return ..()
/obj/item/multitool/field_debug/proc/setup_debug_field() /obj/item/multitool/field_debug/proc/setup_debug_field()
@@ -303,16 +303,20 @@
/obj/item/multitool/field_debug/attack_self(mob/user) /obj/item/multitool/field_debug/attack_self(mob/user)
operating = !operating operating = !operating
to_chat(user, "You turn [src] [operating? "on":"off"].") to_chat(user, "You turn [src] [operating? "on":"off"].")
QDEL_NULL(mobhook) UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
listeningTo = null
if(!istype(current) && operating) 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() setup_debug_field()
else if(!operating) else if(!operating)
QDEL_NULL(current) QDEL_NULL(current)
/obj/item/multitool/field_debug/dropped() /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() /obj/item/multitool/field_debug/proc/on_mob_move()
check_turf(get_turf(src)) check_turf(get_turf(src))

View File

@@ -32,7 +32,7 @@
if(CONFIG_GET(flag/disable_stambuffer)) if(CONFIG_GET(flag/disable_stambuffer))
togglesprint() 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() /mob/living/carbon/human/ComponentInitialize()

View File

@@ -76,7 +76,7 @@
var/static/image/drained_overlay = image(icon = 'icons/obj/guns/energy.dmi', icon_state = "esniper_empty") 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/action/item_action/zoom_lock_action/zoom_lock_action
var/datum/component/mobhook var/mob/listeningTo
/obj/item/gun/energy/beam_rifle/debug /obj/item/gun/energy/beam_rifle/debug
delay = 0 delay = 0
@@ -172,7 +172,7 @@
STOP_PROCESSING(SSfastprocess, src) STOP_PROCESSING(SSfastprocess, src)
set_user(null) set_user(null)
QDEL_LIST(current_tracers) QDEL_LIST(current_tracers)
QDEL_NULL(mobhook) listeningTo = null
return ..() return ..()
/obj/item/gun/energy/beam_rifle/emp_act(severity) /obj/item/gun/energy/beam_rifle/emp_act(severity)
@@ -259,14 +259,17 @@
if(user == current_user) if(user == current_user)
return return
stop_aiming(current_user) stop_aiming(current_user)
QDEL_NULL(mobhook) if(listeningTo)
UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
listeningTo = null
if(istype(current_user)) if(istype(current_user))
LAZYREMOVE(current_user.mousemove_intercept_objects, src) LAZYREMOVE(current_user.mousemove_intercept_objects, src)
current_user = null current_user = null
if(istype(user)) if(istype(user))
current_user = user current_user = user
LAZYOR(current_user.mousemove_intercept_objects, src) 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) /obj/item/gun/energy/beam_rifle/onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
if(aiming) if(aiming)

View File

@@ -64,10 +64,9 @@
var/interrupted = FALSE var/interrupted = FALSE
var/mob/target var/mob/target
var/icon/bluespace var/icon/bluespace
var/datum/weakref/redirect_component
/datum/status_effect/slimerecall/on_apply() /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, "<span class='danger'>You feel a sudden tug from an unknown force, and feel a pull to bluespace!</span>") to_chat(owner, "<span class='danger'>You feel a sudden tug from an unknown force, and feel a pull to bluespace!</span>")
to_chat(owner, "<span class='notice'>Resist if you wish avoid the force!</span>") to_chat(owner, "<span class='notice'>Resist if you wish avoid the force!</span>")
bluespace = icon('icons/effects/effects.dmi',"chronofield") bluespace = icon('icons/effects/effects.dmi',"chronofield")
@@ -77,9 +76,9 @@
/datum/status_effect/slimerecall/proc/resistField() /datum/status_effect/slimerecall/proc/resistField()
interrupted = TRUE interrupted = TRUE
owner.remove_status_effect(src) owner.remove_status_effect(src)
/datum/status_effect/slimerecall/on_remove() /datum/status_effect/slimerecall/on_remove()
qdel(redirect_component.resolve()) UnregisterSignal(owner, COMSIG_LIVING_RESIST)
redirect_component = null
owner.cut_overlay(bluespace) owner.cut_overlay(bluespace)
if(interrupted || !ismob(target)) if(interrupted || !ismob(target))
to_chat(owner, "<span class='warning'>The bluespace tug fades away, and you feel that the force has passed you by.</span>") to_chat(owner, "<span class='warning'>The bluespace tug fades away, and you feel that the force has passed you by.</span>")
@@ -98,10 +97,9 @@
duration = -1 //Will remove self when block breaks. duration = -1 //Will remove self when block breaks.
alert_type = /obj/screen/alert/status_effect/freon/stasis alert_type = /obj/screen/alert/status_effect/freon/stasis
var/obj/structure/ice_stasis/cube var/obj/structure/ice_stasis/cube
var/datum/weakref/redirect_component
/datum/status_effect/frozenstasis/on_apply() /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)) cube = new /obj/structure/ice_stasis(get_turf(owner))
owner.forceMove(cube) owner.forceMove(cube)
owner.status_flags |= GODMODE owner.status_flags |= GODMODE
@@ -118,8 +116,7 @@
if(cube) if(cube)
qdel(cube) qdel(cube)
owner.status_flags &= ~GODMODE owner.status_flags &= ~GODMODE
qdel(redirect_component.resolve()) UnregisterSignal(owner, COMSIG_LIVING_RESIST)
redirect_component = null
/datum/status_effect/slime_clone /datum/status_effect/slime_clone
id = "slime_cloned" id = "slime_cloned"

View File

@@ -29,8 +29,6 @@
var/datum/action/innate/slime_scan/scan_action var/datum/action/innate/slime_scan/scan_action
var/datum/action/innate/feed_potion/potion_action var/datum/action/innate/feed_potion/potion_action
var/datum/component/redirect/listener
var/list/stored_slimes var/list/stored_slimes
var/obj/item/slimepotion/slime/current_potion var/obj/item/slimepotion/slime/current_potion
var/max_slimes = 5 var/max_slimes = 5
@@ -50,7 +48,7 @@
scan_action = new scan_action = new
potion_action = new potion_action = new
stored_slimes = list() 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() /obj/machinery/computer/camera_advanced/xenobio/Destroy()
stored_slimes = null stored_slimes = null

View File

@@ -2,6 +2,7 @@
//Keep this sorted alphabetically //Keep this sorted alphabetically
#ifdef UNIT_TESTS #ifdef UNIT_TESTS
#include "component_tests.dm"
#include "reagent_id_typos.dm" #include "reagent_id_typos.dm"
#include "reagent_recipe_collisions.dm" #include "reagent_recipe_collisions.dm"
#include "spawn_humans.dm" #include "spawn_humans.dm"

View File

@@ -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(",")])")

View File

@@ -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)

View File

@@ -6,27 +6,25 @@
icon_state = "s-ninja" icon_state = "s-ninja"
item_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 /obj/item/clothing/glasses/phantomthief/syndicate
name = "suspicious plastic mask" name = "suspicious plastic mask"
desc = "A cheap, bulky, Syndicate-branded plastic face mask. You have to break in to break out." desc = "A cheap, bulky, Syndicate-branded plastic face mask. You have to break in to break out."
var/nextadrenalinepop 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) if(world.time >= nextadrenalinepop)
to_chat(user, "<span class='notice'>The built-in adrenaline injector is ready for use.</span>") to_chat(user, "<span class='notice'>The built-in adrenaline injector is ready for use.</span>")
else else
to_chat(user, "<span class='notice'>[DisplayTimeText(nextadrenalinepop - world.time)] left before the adrenaline injector can be used again.") to_chat(user, "<span class='notice'>[DisplayTimeText(nextadrenalinepop - world.time)] left before the adrenaline injector can be used again.")
/obj/item/clothing/glasses/phantomthief/syndicate/proc/injectadrenaline(mob/user, combatmodestate) /obj/item/clothing/glasses/phantomthief/syndicate/proc/injectadrenaline(mob/user, combatmodestate)
if(istype(user)) if(istype(user) && combatmodestate && world.time >= nextadrenalinepop)
if(combatmodestate && world.time >= nextadrenalinepop)
nextadrenalinepop = world.time + 5 MINUTES nextadrenalinepop = world.time + 5 MINUTES
user.reagents.add_reagent("syndicateadrenals", 5) user.reagents.add_reagent("syndicateadrenals", 5)
user.playsound_local(user, 'modular_citadel/sound/misc/adrenalinject.ogg', 100, 0, pressure_affected = FALSE) user.playsound_local(user, 'modular_citadel/sound/misc/adrenalinject.ogg', 100, 0, pressure_affected = FALSE)
@@ -37,12 +35,10 @@
return return
if(slot != SLOT_GLASSES) if(slot != SLOT_GLASSES)
return return
if(!combattoggle_redir) RegisterSignal(user, COMSIG_COMBAT_TOGGLED, .proc/injectadrenaline)
combattoggle_redir = user.AddComponent(/datum/component/redirect, list(COMSIG_COMBAT_TOGGLED = CALLBACK(src, .proc/injectadrenaline)))
/obj/item/clothing/glasses/phantomthief/syndicate/dropped(mob/user) /obj/item/clothing/glasses/phantomthief/syndicate/dropped(mob/user)
. = ..() . = ..()
if(!istype(user)) if(!istype(user))
return return
if(combattoggle_redir) UnregisterSignal(user, COMSIG_COMBAT_TOGGLED)
QDEL_NULL(combattoggle_redir)

View File

@@ -370,12 +370,12 @@
#include "code\datums\components\ntnet_interface.dm" #include "code\datums\components\ntnet_interface.dm"
#include "code\datums\components\orbiter.dm" #include "code\datums\components\orbiter.dm"
#include "code\datums\components\paintable.dm" #include "code\datums\components\paintable.dm"
#include "code\datums\components\phantomthief.dm"
#include "code\datums\components\rad_insulation.dm" #include "code\datums\components\rad_insulation.dm"
#include "code\datums\components\radioactive.dm" #include "code\datums\components\radioactive.dm"
#include "code\datums\components\remote_materials.dm" #include "code\datums\components\remote_materials.dm"
#include "code\datums\components\riding.dm" #include "code\datums\components\riding.dm"
#include "code\datums\components\rotation.dm" #include "code\datums\components\rotation.dm"
#include "code\datums\components\signal_redirect.dm"
#include "code\datums\components\slippery.dm" #include "code\datums\components\slippery.dm"
#include "code\datums\components\spooky.dm" #include "code\datums\components\spooky.dm"
#include "code\datums\components\squeak.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\job.dm"
#include "modular_citadel\code\controllers\subsystem\shuttle.dm" #include "modular_citadel\code\controllers\subsystem\shuttle.dm"
#include "modular_citadel\code\datums\components\material_container.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\components\souldeath.dm"
#include "modular_citadel\code\datums\mood_events\chem_events.dm" #include "modular_citadel\code\datums\mood_events\chem_events.dm"
#include "modular_citadel\code\datums\mood_events\generic_negative_events.dm" #include "modular_citadel\code\datums\mood_events\generic_negative_events.dm"