diff --git a/code/controllers/admin.dm b/code/controllers/admin.dm
index 19fef285973..7127a1866b4 100644
--- a/code/controllers/admin.dm
+++ b/code/controllers/admin.dm
@@ -5,10 +5,20 @@
INITIALIZE_IMMEDIATE(/obj/effect/statclick)
-/obj/effect/statclick/Initialize(mapload, text, target) //Don't port this to Initialize it's too critical
+/obj/effect/statclick/Initialize(mapload, text, target)
. = ..()
name = text
src.target = target
+ if(istype(target, /datum)) //Harddel man bad
+ RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/cleanup)
+
+/obj/effect/statclick/Destroy()
+ target = null
+ return ..()
+
+/obj/effect/statclick/proc/cleanup()
+ SIGNAL_HANDLER
+ qdel(src)
/obj/effect/statclick/proc/update(text)
name = text
diff --git a/code/controllers/subsystem/throwing.dm b/code/controllers/subsystem/throwing.dm
index e265c997834..16374fbd201 100644
--- a/code/controllers/subsystem/throwing.dm
+++ b/code/controllers/subsystem/throwing.dm
@@ -85,6 +85,7 @@ SUBSYSTEM_DEF(throwing)
/datum/thrownthing/Destroy()
SSthrowing.processing -= thrownthing
+ SSthrowing.currentrun -= thrownthing
thrownthing.throwing = null
thrownthing = null
target = null
diff --git a/code/datums/action.dm b/code/datums/action.dm
index b5497af1827..0447d7d4a81 100644
--- a/code/datums/action.dm
+++ b/code/datums/action.dm
@@ -37,8 +37,7 @@
if(owner)
Remove(owner)
target = null
- qdel(button)
- button = null
+ QDEL_NULL(button)
return ..()
/datum/action/proc/Grant(mob/M)
diff --git a/code/datums/ai/monkey/monkey_behaviors.dm b/code/datums/ai/monkey/monkey_behaviors.dm
index b8aa1f6fa8a..e8ffa84ac53 100644
--- a/code/datums/ai/monkey/monkey_behaviors.dm
+++ b/code/datums/ai/monkey/monkey_behaviors.dm
@@ -12,6 +12,8 @@
var/obj/item/target = controller.blackboard[BB_MONKEY_PICKUPTARGET]
item_blacklist[target] = TRUE
+ if(istype(controller, /datum/ai_controller/monkey)) //What the fuck
+ controller.RegisterSignal(target, COMSIG_PARENT_QDELETING, /datum/ai_controller/monkey/proc/target_del)
controller.blackboard[BB_MONKEY_PICKUPTARGET] = null
diff --git a/code/datums/ai/monkey/monkey_controller.dm b/code/datums/ai/monkey/monkey_controller.dm
index 15bacae2d11..77ab2fac0af 100644
--- a/code/datums/ai/monkey/monkey_controller.dm
+++ b/code/datums/ai/monkey/monkey_controller.dm
@@ -224,3 +224,7 @@ have ways of interacting with a specific mob and control it.
/datum/ai_controller/monkey/proc/update_movespeed(mob/living/pawn)
SIGNAL_HANDLER
movement_delay = pawn.cached_multiplicative_slowdown
+
+/datum/ai_controller/monkey/proc/target_del(target)
+ SIGNAL_HANDLER
+ blackboard[BB_MONKEY_BLACKLISTITEMS] -= target
diff --git a/code/datums/wounds/_wounds.dm b/code/datums/wounds/_wounds.dm
index 9390e4c6c7f..6975f86c799 100644
--- a/code/datums/wounds/_wounds.dm
+++ b/code/datums/wounds/_wounds.dm
@@ -73,8 +73,6 @@
/// What status effect we assign on application
var/status_effect_type
- /// The status effect we're linked to
- var/datum/status_effect/linked_status_effect
/// If we're operating on this wound and it gets healed, we'll nix the surgery too
var/datum/surgery/attached_surgery
/// if you're a lazy git and just throw them in cryo, the wound will go away after accumulating severity * 25 power
@@ -129,12 +127,13 @@
return
victim = L.owner
+ RegisterSignal(victim, COMSIG_PARENT_QDELETING, .proc/null_victim)
set_limb(L)
LAZYADD(victim.all_wounds, src)
LAZYADD(limb.wounds, src)
limb.update_wounds()
if(status_effect_type)
- linked_status_effect = victim.apply_status_effect(status_effect_type, src)
+ victim.apply_status_effect(status_effect_type, src)
SEND_SIGNAL(victim, COMSIG_CARBON_GAIN_WOUND, src, limb)
if(!victim.alerts["wound"]) // only one alert is shared between all of the wounds
victim.throw_alert("wound", /atom/movable/screen/alert/status_effect/wound)
@@ -162,6 +161,14 @@
wound_injury(old_wound)
second_wind()
+/datum/wound/proc/null_victim()
+ SIGNAL_HANDLER
+ victim = null
+
+/datum/wound/proc/source_died()
+ SIGNAL_HANDLER
+ qdel(src)
+
/// Remove the wound from whatever it's afflicting, and cleans up whateverstatus effects it had or modifiers it had on interaction times. ignore_limb is used for detachments where we only want to forget the victim
/datum/wound/proc/remove_wound(ignore_limb, replaced = FALSE)
//TODO: have better way to tell if we're getting removed without replacement (full heal) scar stuff
@@ -206,7 +213,10 @@
if(limb == new_value)
return FALSE //Limb can either be a reference to something or `null`. Returning the number variable makes it clear no change was made.
. = limb
+ if(limb)
+ UnregisterSignal(limb, COMSIG_PARENT_QDELETING)
limb = new_value
+ RegisterSignal(new_value, COMSIG_PARENT_QDELETING, .proc/source_died)
if(. && disabling)
var/obj/item/bodypart/old_limb = .
REMOVE_TRAIT(old_limb, TRAIT_PARALYSIS, src)
diff --git a/code/datums/wounds/scars/_scars.dm b/code/datums/wounds/scars/_scars.dm
index 60e2899280a..a43ef59f86d 100644
--- a/code/datums/wounds/scars/_scars.dm
+++ b/code/datums/wounds/scars/_scars.dm
@@ -32,6 +32,8 @@
LAZYREMOVE(limb.scars, src)
if(victim)
LAZYREMOVE(victim.all_scars, src)
+ limb = null
+ victim = null
. = ..()
/**
@@ -46,6 +48,8 @@
*/
/datum/scar/proc/generate(obj/item/bodypart/BP, datum/wound/W, add_to_scars=TRUE)
limb = BP
+ RegisterSignal(limb, COMSIG_PARENT_QDELETING, .proc/limb_gone)
+
severity = W.severity
if(limb.owner)
victim = limb.owner
@@ -88,6 +92,7 @@
return
limb = BP
+ RegisterSignal(limb, COMSIG_PARENT_QDELETING, .proc/limb_gone)
if(limb.owner)
victim = limb.owner
if(victim.get_biological_state() != biology)
@@ -113,6 +118,10 @@
visibility = 7
return src
+/datum/scar/proc/limb_gone()
+ SIGNAL_HANDLER
+ qdel(src)
+
/// What will show up in examine_more() if this scar is visible
/datum/scar/proc/get_examine_description(mob/viewer)
if(!victim || !is_visible(viewer))
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index a946f8f2c17..345e44eff17 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -373,7 +373,18 @@ GLOBAL_LIST_EMPTY(teleportlocs)
* Also cycles the icons of all firealarms and deregisters the area from processing on SSOBJ
*/
/area/proc/firereset(obj/source)
- if (fire)
+ var/should_reset_alarms = fire
+ if(source)
+ if(istype(source, /obj/machinery/firealarm))
+ var/obj/machinery/firealarm/alarm = source
+ if(alarm.triggered)
+ alarm.triggered = FALSE
+ triggered_firealarms -= 1
+ if(triggered_firealarms > 0)
+ should_reset_alarms = FALSE
+ should_reset_alarms = should_reset_alarms & power_environ //No resetting if there's no power
+
+ if (should_reset_alarms) // if there's a source, make sure there's no fire alarms left
unset_fire_alarm_effects()
ModifyFiredoors(TRUE)
for(var/item in firealarms)
@@ -394,6 +405,18 @@ GLOBAL_LIST_EMPTY(teleportlocs)
p.cancelAlarm("Fire", src, source)
STOP_PROCESSING(SSobj, src)
+///Get rid of any dangling camera refs
+/area/proc/clear_camera(obj/machinery/camera/cam)
+ LAZYREMOVE(cameras, cam)
+ for (var/mob/living/silicon/aiPlayer as anything in GLOB.silicon_mobs)
+ aiPlayer.freeCamera(src, cam)
+ for (var/obj/machinery/computer/station_alert/comp as anything in GLOB.alert_consoles)
+ comp.freeCamera(src, cam)
+ for (var/mob/living/simple_animal/drone/drone_on as anything in GLOB.drones_list)
+ drone_on.freeCamera(src, cam)
+ for(var/datum/computer_file/program/alarm_monitor/monitor as anything in GLOB.alarmdisplay)
+ monitor.freeCamera(src, cam)
+
/**
* If 100 ticks has elapsed, toggle all the firedoors closed again
*/
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index c205c445397..474a04b743d 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -120,6 +120,9 @@
. = ..()
+ //We add ourselves to this list, best to clear it out
+ LAZYCLEARLIST(area_sensitive_contents)
+
for(var/movable_content in contents)
qdel(movable_content)
@@ -127,6 +130,8 @@
moveToNullspace()
+ vis_contents.Cut()
+
/atom/movable/proc/update_emissive_block()
if(blocks_emissive != EMISSIVE_BLOCK_GENERIC)
diff --git a/code/game/machinery/Beacon.dm b/code/game/machinery/Beacon.dm
index fd918d1cb2d..91415544261 100644
--- a/code/game/machinery/Beacon.dm
+++ b/code/game/machinery/Beacon.dm
@@ -22,7 +22,7 @@
return ..()
/obj/machinery/bluespace_beacon/process()
- if(!Beacon)
+ if(QDELETED(Beacon)) //Don't move it out of nullspace BACK INTO THE GAME for the love of god
var/turf/T = loc
Beacon = new(T)
Beacon.invisibility = INVISIBILITY_MAXIMUM
diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index b6e9a71b1df..98574bb6258 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -101,15 +101,15 @@
if(can_use())
toggle_cam(null, 0) //kick anyone viewing out and remove from the camera chunks
GLOB.cameranet.cameras -= src
+ cancelCameraAlarm()
if(isarea(myarea))
- LAZYREMOVE(myarea.cameras, src)
+ myarea.clear_camera(src)
QDEL_NULL(assembly)
if(bug)
- bug.bugged_cameras -= src.c_tag
+ bug.bugged_cameras -= c_tag
if(bug.current == src)
bug.current = null
bug = null
- cancelCameraAlarm()
return ..()
/obj/machinery/camera/examine(mob/user)
diff --git a/code/game/machinery/computer/station_alert.dm b/code/game/machinery/computer/station_alert.dm
index eca75f5a52b..4e8d9ff5275 100644
--- a/code/game/machinery/computer/station_alert.dm
+++ b/code/game/machinery/computer/station_alert.dm
@@ -38,31 +38,46 @@
return data
-/obj/machinery/computer/station_alert/proc/triggerAlarm(class, area/A, O, obj/source)
+/obj/machinery/computer/station_alert/proc/triggerAlarm(class, area/home, cameras, obj/source)
if(source.z != z)
return
if(machine_stat & (BROKEN))
return
- var/list/L = alarms[class]
- for(var/I in L)
- if (I == A.name)
- var/list/alarm = L[I]
+ var/list/our_sort = alarms[class]
+ for(var/areaname in our_sort)
+ if (areaname == home.name)
+ var/list/alarm = our_sort[areaname]
var/list/sources = alarm[3]
if (!(source in sources))
sources += source
- return 1
- var/obj/machinery/camera/C = null
- var/list/CL = null
- if(O && islist(O))
- CL = O
- if (CL.len == 1)
- C = CL[1]
- else if(O && istype(O, /obj/machinery/camera))
- C = O
- L[A.name] = list(A, (C ? C : O), list(source))
- return 1
+ return TRUE
+ var/obj/machinery/camera/cam = null
+ var/list/our_cams = null
+ if(cameras && islist(cameras))
+ our_cams = cameras
+ if (our_cams.len == 1)
+ cam = our_cams[1]
+ else if(cameras && istype(cameras, /obj/machinery/camera))
+ cam = cameras
+ our_sort[home.name] = list(home, (cam ? cam : cameras), list(source))
+ return TRUE
+
+/obj/machinery/computer/station_alert/proc/freeCamera(area/home, obj/machinery/camera/cam)
+ for(var/class in alarms)
+ var/our_area = alarms[class][home.name]
+ if(!our_area)
+ continue
+ var/cams = our_area[2] //Get the cameras
+ if(!cams)
+ continue
+ if(islist(cams))
+ cams -= cam
+ if(length(cams) == 1)
+ our_area[2] = cams[1]
+ else
+ our_area[2] = null
/obj/machinery/computer/station_alert/proc/cancelAlarm(class, area/A, obj/origin)
if(machine_stat & (BROKEN))
diff --git a/code/game/machinery/embedded_controller/embedded_controller_base.dm b/code/game/machinery/embedded_controller/embedded_controller_base.dm
index bfbe73af79e..6da86086275 100644
--- a/code/game/machinery/embedded_controller/embedded_controller_base.dm
+++ b/code/game/machinery/embedded_controller/embedded_controller_base.dm
@@ -3,6 +3,10 @@
var/state
var/obj/machinery/embedded_controller/master
+/datum/computer/file/embedded_program/Destroy()
+ master = null
+ . = ..()
+
/datum/computer/file/embedded_program/proc/post_signal(datum/signal/signal, comm_line)
if(master)
master.post_signal(signal, comm_line)
@@ -25,6 +29,11 @@
var/on = TRUE
+/obj/machinery/embedded_controller/Destroy()
+ if(program)
+ QDEL_NULL(program)
+ . = ..()
+
/obj/machinery/embedded_controller/ui_interact(mob/user)
. = ..()
user.set_machine(src)
diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm
index 2f06b5f02c1..9444c33cb97 100644
--- a/code/game/machinery/firealarm.dm
+++ b/code/game/machinery/firealarm.dm
@@ -57,10 +57,8 @@
AddElement(/datum/element/atmos_sensitive)
/obj/machinery/firealarm/Destroy()
+ myarea.firereset(src)
LAZYREMOVE(myarea.firealarms, src)
- if(triggered)
- triggered = FALSE
- myarea.triggered_firealarms -= 1
return ..()
/obj/machinery/firealarm/update_icon_state()
@@ -162,7 +160,7 @@
if(!is_operational)
return
var/area/A = get_area(src)
- A.firereset(src)
+ A.firereset()
if(user)
log_game("[user] reset a fire alarm at [COORD(src)]")
diff --git a/code/game/machinery/limbgrower.dm b/code/game/machinery/limbgrower.dm
index aac7160cc9a..a2916c1d390 100644
--- a/code/game/machinery/limbgrower.dm
+++ b/code/game/machinery/limbgrower.dm
@@ -150,7 +150,7 @@
limb.desc = "A synthetically produced [selected_category] limb, grown in a tube. This one is for the [parse_zone(limb.body_zone)]."
limb.species_id = selected_category
limb.update_icon_dropped()
- limb.original_owner = "limb grower" //prevents updating the icon, so a lizard arm on a human stays a lizard arm etc.
+ limb.original_owner = WEAKREF(src) //prevents updating the icon, so a lizard arm on a human stays a lizard arm etc.
/obj/machinery/limbgrower/RefreshParts()
reagents.maximum_volume = 0
diff --git a/code/game/machinery/mechlaunchpad.dm b/code/game/machinery/mechlaunchpad.dm
index 63b405fc3c8..f1da47aa571 100644
--- a/code/game/machinery/mechlaunchpad.dm
+++ b/code/game/machinery/mechlaunchpad.dm
@@ -24,6 +24,7 @@
connected_console = null
for(var/obj/machinery/computer/mechpad/console in consoles)
console.mechpads -= src
+ GLOB.mechpad_list -= src
return ..()
/obj/machinery/mechpad/screwdriver_act(mob/user, obj/item/tool)
diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm
index 7aab3e76ec1..9eceb1d1729 100644
--- a/code/game/objects/effects/decals/cleanable/humans.dm
+++ b/code/game/objects/effects/decals/cleanable/humans.dm
@@ -89,6 +89,7 @@
layer = LOW_OBJ_LAYER
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6")
mergeable_decal = FALSE
+ turf_loc_check = FALSE
dryname = "rotting gibs"
drydesc = "They look bloody and gruesome while some terrible smell fills the air."
@@ -100,6 +101,9 @@
if(mapload) //Don't rot at roundstart for the love of god
return
+/obj/effect/decal/cleanable/blood/gibs/replace_decal(obj/effect/decal/cleanable/C)
+ return FALSE //Never fail to place us
+
/obj/effect/decal/cleanable/blood/gibs/dry()
. = ..()
AddComponent(/datum/component/rot/gibs)
diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm
index df5f8387947..247ec4875ca 100644
--- a/code/game/objects/items/circuitboards/machine_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm
@@ -631,11 +631,37 @@
def_components = list(/obj/item/stock_parts/cell = /obj/item/stock_parts/cell/high)
needs_anchored = FALSE
+/obj/item/circuitboard/machine/chem_dispenser/fullupgrade
+ build_path = /obj/machinery/chem_dispenser/fullupgrade
+ req_components = list(
+ /obj/item/stock_parts/matter_bin/bluespace = 2,
+ /obj/item/stock_parts/capacitor/quadratic = 2,
+ /obj/item/stock_parts/manipulator/femto = 2,
+ /obj/item/stack/sheet/glass = 1,
+ /obj/item/stock_parts/cell/bluespace = 1,
+ )
+
+/obj/item/circuitboard/machine/chem_dispenser/mutagensaltpeter
+ build_path = /obj/machinery/chem_dispenser/mutagensaltpeter
+ req_components = list(
+ /obj/item/stock_parts/matter_bin/bluespace = 2,
+ /obj/item/stock_parts/capacitor/quadratic = 2,
+ /obj/item/stock_parts/manipulator/femto = 2,
+ /obj/item/stack/sheet/glass = 1,
+ /obj/item/stock_parts/cell/bluespace = 1,
+ )
+
/obj/item/circuitboard/machine/chem_dispenser/abductor
name = "Reagent Synthesizer (Abductor Machine Board)"
icon_state = "abductor_mod"
build_path = /obj/machinery/chem_dispenser/abductor
- def_components = list(/obj/item/stock_parts/cell = /obj/item/stock_parts/cell/high)
+ req_components = list(
+ /obj/item/stock_parts/matter_bin/bluespace = 2,
+ /obj/item/stock_parts/capacitor/quadratic = 2,
+ /obj/item/stock_parts/manipulator/femto = 2,
+ /obj/item/stack/sheet/glass = 1,
+ /obj/item/stock_parts/cell/bluespace = 1,
+ )
needs_anchored = FALSE
/obj/item/circuitboard/machine/chem_heater
@@ -992,11 +1018,31 @@
icon_state = "service"
build_path = /obj/machinery/chem_dispenser/drinks
+/obj/item/circuitboard/machine/chem_dispenser/drinks/fullupgrade
+ build_path = /obj/machinery/chem_dispenser/drinks/fullupgrade
+ req_components = list(
+ /obj/item/stock_parts/matter_bin/bluespace = 2,
+ /obj/item/stock_parts/capacitor/quadratic = 2,
+ /obj/item/stock_parts/manipulator/femto = 2,
+ /obj/item/stack/sheet/glass = 1,
+ /obj/item/stock_parts/cell/bluespace = 1,
+ )
+
/obj/item/circuitboard/machine/chem_dispenser/drinks/beer
name = "Booze Dispenser (Machine Board)"
icon_state = "service"
build_path = /obj/machinery/chem_dispenser/drinks/beer
+/obj/item/circuitboard/machine/chem_dispenser/drinks/beer/fullupgrade
+ build_path = /obj/machinery/chem_dispenser/drinks/beer/fullupgrade
+ req_components = list(
+ /obj/item/stock_parts/matter_bin/bluespace = 2,
+ /obj/item/stock_parts/capacitor/quadratic = 2,
+ /obj/item/stock_parts/manipulator/femto = 2,
+ /obj/item/stack/sheet/glass = 1,
+ /obj/item/stock_parts/cell/bluespace = 1,
+ )
+
/obj/item/circuitboard/machine/chem_master/condi
name = "CondiMaster 3000 (Machine Board)"
icon_state = "service"
diff --git a/code/game/objects/items/devices/beacon.dm b/code/game/objects/items/devices/beacon.dm
index db801e54388..ca4f3dc5c4a 100644
--- a/code/game/objects/items/devices/beacon.dm
+++ b/code/game/objects/items/devices/beacon.dm
@@ -17,7 +17,7 @@
icon_state = "beacon-off"
/obj/item/beacon/Destroy()
- GLOB.teleportbeacons.Remove(src)
+ GLOB.teleportbeacons -= src
return ..()
/obj/item/beacon/attack_self(mob/user)
@@ -27,7 +27,7 @@
GLOB.teleportbeacons += src
else
icon_state = "beacon-off"
- GLOB.teleportbeacons.Remove(src)
+ GLOB.teleportbeacons -= src
to_chat(user, "You [enabled ? "enable" : "disable"] the beacon.")
return
diff --git a/code/game/objects/items/devices/geiger_counter.dm b/code/game/objects/items/devices/geiger_counter.dm
index f93abd99e5c..b5e8b612804 100644
--- a/code/game/objects/items/devices/geiger_counter.dm
+++ b/code/game/objects/items/devices/geiger_counter.dm
@@ -36,6 +36,8 @@
/obj/item/geiger_counter/Destroy()
STOP_PROCESSING(SSobj, src)
+ QDEL_NULL(soundloop)
+
return ..()
/obj/item/geiger_counter/process(delta_time)
diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm
index a4ea1f0b9b1..222d780f97c 100644
--- a/code/game/objects/items/devices/taperecorder.dm
+++ b/code/game/objects/items/devices/taperecorder.dm
@@ -39,6 +39,11 @@
soundloop = new(list(src))
update_appearance()
+/obj/item/taperecorder/Destroy()
+ QDEL_NULL(soundloop)
+ QDEL_NULL(mytape)
+ return ..()
+
/obj/item/taperecorder/proc/readout()
if(mytape)
if(playing)
diff --git a/code/game/objects/items/tanks/jetpack.dm b/code/game/objects/items/tanks/jetpack.dm
index 0fd34857efc..70fb93e3021 100644
--- a/code/game/objects/items/tanks/jetpack.dm
+++ b/code/game/objects/items/tanks/jetpack.dm
@@ -20,6 +20,10 @@
ion_trail.auto_process = FALSE
ion_trail.set_up(src)
+/obj/item/tank/jetpack/Destroy()
+ QDEL_NULL(ion_trail)
+ return ..()
+
/obj/item/tank/jetpack/populate_gas()
if(gas_type)
air_contents.assert_gas(gas_type)
diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm
index f0d6cf58f19..5597779c51e 100644
--- a/code/game/objects/structures/crates_lockers/crates.dm
+++ b/code/game/objects/structures/crates_lockers/crates.dm
@@ -160,7 +160,7 @@
/obj/structure/closet/crate/freezer/Destroy()
recursive_organ_check(src)
- ..()
+ return ..()
/obj/structure/closet/crate/freezer/Initialize()
. = ..()
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 7c3a819fddb..b0d003b9b3c 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -155,6 +155,8 @@ GLOBAL_LIST_EMPTY(station_turfs)
flags_1 &= ~INITIALIZED_1
requires_activation = FALSE
..()
+
+ vis_contents.Cut()
/turf/attack_hand(mob/user, list/modifiers)
. = ..()
diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm
index c050e4a60f1..81fa39925be 100644
--- a/code/modules/atmospherics/machinery/airalarm.dm
+++ b/code/modules/atmospherics/machinery/airalarm.dm
@@ -233,6 +233,8 @@
SSradio.remove_object(src, frequency)
qdel(wires)
wires = null
+ var/area/ourarea = get_area(src)
+ ourarea.atmosalert(FALSE, src)
return ..()
/obj/machinery/airalarm/Initialize(mapload)
diff --git a/code/modules/cargo/orderconsole.dm b/code/modules/cargo/orderconsole.dm
index 9f7c0fba022..d528f24b162 100644
--- a/code/modules/cargo/orderconsole.dm
+++ b/code/modules/cargo/orderconsole.dm
@@ -41,7 +41,7 @@
/obj/machinery/computer/cargo/Destroy()
QDEL_NULL(radio)
- ..()
+ return ..()
/obj/machinery/computer/cargo/proc/get_export_categories()
. = EXPORT_CARGO
diff --git a/code/modules/clothing/gloves/tacklers.dm b/code/modules/clothing/gloves/tacklers.dm
index c5790548200..80b858f4b44 100644
--- a/code/modules/clothing/gloves/tacklers.dm
+++ b/code/modules/clothing/gloves/tacklers.dm
@@ -23,6 +23,10 @@
/// See: [/datum/component/tackler/var/skill_mod]
var/skill_mod = 0
+/obj/item/clothing/gloves/tackler/Destroy()
+ tackler = null
+ return ..()
+
/obj/item/clothing/gloves/tackler/equipped(mob/user, slot)
. = ..()
if(!ishuman(user))
@@ -37,7 +41,7 @@
return
var/mob/living/carbon/human/H = user
if(H.get_item_by_slot(ITEM_SLOT_GLOVES) == src)
- qdel(tackler)
+ QDEL_NULL(tackler)
/obj/item/clothing/gloves/tackler/dolphin
name = "dolphin gloves"
diff --git a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm
index 16e2a323c11..d7787da0e06 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm
@@ -41,6 +41,10 @@ GLOBAL_LIST_INIT(oilfry_blacklisted_items, typecacheof(list(
reagents.add_reagent(/datum/reagent/consumable/cooking_oil, 25)
fry_loop = new(list(src), FALSE)
+/obj/machinery/deepfryer/Destroy()
+ QDEL_NULL(fry_loop)
+ return ..()
+
/obj/machinery/deepfryer/RefreshParts()
var/oil_efficiency
for(var/obj/item/stock_parts/micro_laser/M in component_parts)
diff --git a/code/modules/food_and_drinks/kitchen_machinery/grill.dm b/code/modules/food_and_drinks/kitchen_machinery/grill.dm
index d2b84ac64ab..7b5cf577e15 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/grill.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/grill.dm
@@ -20,6 +20,10 @@
. = ..()
grill_loop = new(list(src), FALSE)
+/obj/machinery/grill/Destroy()
+ QDEL_NULL(grill_loop)
+ return ..()
+
/obj/machinery/grill/update_icon_state()
if(grilled_item)
icon_state = "grill"
diff --git a/code/modules/food_and_drinks/kitchen_machinery/microwave.dm b/code/modules/food_and_drinks/kitchen_machinery/microwave.dm
index 8d1072a3895..95e88e5ef6e 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/microwave.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/microwave.dm
@@ -42,6 +42,7 @@
eject()
if(wires)
QDEL_NULL(wires)
+ QDEL_NULL(soundloop)
. = ..()
/obj/machinery/microwave/RefreshParts()
diff --git a/code/modules/lighting/lighting_source.dm b/code/modules/lighting/lighting_source.dm
index b4368ca40ab..12206a408e1 100644
--- a/code/modules/lighting/lighting_source.dm
+++ b/code/modules/lighting/lighting_source.dm
@@ -58,6 +58,10 @@
if (needs_update)
SSlighting.sources_queue -= src
+ top_atom = null
+ source_atom = null
+ source_turf = null
+ pixel_turf = null
. = ..()
// Yes this doesn't align correctly on anything other than 4 width tabs.
diff --git a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
index 96286cf1b6e..7e7e2e44e30 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
@@ -17,10 +17,6 @@ Doesn't work on other aliens/AI.*/
action_icon_state = "spell_default"
action_background_icon_state = "bg_alien"
-/obj/effect/proc_holder/alien/Initialize()
- . = ..()
- action = new(src)
-
/obj/effect/proc_holder/alien/Click()
if(!iscarbon(usr))
return 1
diff --git a/code/modules/mob/living/carbon/carbon_update_icons.dm b/code/modules/mob/living/carbon/carbon_update_icons.dm
index 8f39855b7d6..07b54cb1fe7 100644
--- a/code/modules/mob/living/carbon/carbon_update_icons.dm
+++ b/code/modules/mob/living/carbon/carbon_update_icons.dm
@@ -223,7 +223,7 @@
/mob/living/carbon/proc/assign_bodypart_ownership()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
- BP.original_owner = src
+ BP.original_owner = WEAKREF(src)
//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular)
/*
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index a95c212241d..e91a24c9b2f 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -520,43 +520,61 @@
Bot.call_bot(src, waypoint)
call_bot_cooldown = 0
-/mob/living/silicon/ai/triggerAlarm(class, area/A, O, obj/alarmsource)
- if(alarmsource.z != z)
+/mob/living/silicon/ai/triggerAlarm(class, area/home, cameras, obj/source)
+ if(source.z != z)
return
- var/list/L = alarms[class]
- for (var/I in L)
- if (I == A.name)
- var/list/alarm = L[I]
+ var/list/our_sort = alarms[class]
+ for(var/areaname in our_sort)
+ if (areaname == home.name)
+ var/list/alarm = our_sort[areaname]
var/list/sources = alarm[3]
- if (!(alarmsource in sources))
- sources += alarmsource
- return 1
- var/obj/machinery/camera/C = null
- var/list/CL = null
- if (O && istype(O, /list))
- CL = O
- if (CL.len == 1)
- C = CL[1]
- else if (O && istype(O, /obj/machinery/camera))
- C = O
- L[A.name] = list(A, (C) ? C : O, list(alarmsource))
- if (O)
- if (C?.can_use())
- queueAlarm("--- [class] alarm detected in [A.name]! ([C.c_tag])", class)
- else if (CL?.len)
+ if (!(source in sources))
+ sources += source
+ return TRUE
+
+ var/obj/machinery/camera/cam = null
+ var/list/our_cams = null
+ if(cameras && islist(cameras))
+ our_cams = cameras
+ if (our_cams.len == 1)
+ cam = our_cams[1]
+ else if(cameras && istype(cameras, /obj/machinery/camera))
+ cam = cameras
+ our_sort[home.name] = list(home, (cam ? cam : cameras), list(source))
+
+ if (cameras)
+ if (cam?.can_use())
+ queueAlarm("--- [class] alarm detected in [home.name]! ([cam.c_tag])", class)
+ else if (our_cams?.len)
var/foo = 0
var/dat2 = ""
- for (var/obj/machinery/camera/I in CL)
+ for (var/obj/machinery/camera/I in our_cams)
dat2 += text("[][]", (!foo) ? "" : " | ", I.c_tag) //I'm not fixing this shit...
foo = 1
- queueAlarm(text ("--- [] alarm detected in []! ([])", class, A.name, dat2), class)
+ queueAlarm(text ("--- [] alarm detected in []! ([])", class, home.name, dat2), class)
else
- queueAlarm(text("--- [] alarm detected in []! (No Camera)", class, A.name), class)
+ queueAlarm(text("--- [] alarm detected in []! (No Camera)", class, home.name), class)
else
- queueAlarm(text("--- [] alarm detected in []! (No Camera)", class, A.name), class)
- if (viewalerts) ai_alerts()
+ queueAlarm(text("--- [] alarm detected in []! (No Camera)", class, home.name), class)
+ if (viewalerts)
+ ai_alerts()
return 1
+/mob/living/silicon/ai/freeCamera(area/home, obj/machinery/camera/cam)
+ for(var/class in alarms)
+ var/our_area = alarms[class][home.name]
+ if(!our_area)
+ continue
+ var/cams = our_area[2] //Get the cameras
+ if(!cams)
+ continue
+ if(islist(cams))
+ cams -= cam
+ if(length(cams) == 1)
+ our_area[2] = cams[1]
+ else
+ our_area[2] = null
+
/mob/living/silicon/ai/cancelAlarm(class, area/A, obj/origin)
var/list/L = alarms[class]
var/cleared = 0
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 9ef5be235cd..bfd5c934093 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -248,31 +248,47 @@
. += "Master AI: [connected_ai.name]"
-/mob/living/silicon/robot/triggerAlarm(class, area/A, O, obj/alarmsource)
- if(alarmsource.z != z)
+/mob/living/silicon/robot/triggerAlarm(class, area/home, cameras, obj/source)
+ if(source.z != z)
return
if(stat == DEAD)
return TRUE
- var/list/L = alarms[class]
- for (var/I in L)
- if (I == A.name)
- var/list/alarm = L[I]
+ var/list/our_sort = alarms[class]
+ for(var/areaname in our_sort)
+ if (areaname == home.name)
+ var/list/alarm = our_sort[areaname]
var/list/sources = alarm[3]
- if (!(alarmsource in sources))
- sources += alarmsource
+ if (!(source in sources))
+ sources += source
return TRUE
- var/obj/machinery/camera/C = null
- var/list/CL = null
- if (O && istype(O, /list))
- CL = O
- if (CL.len == 1)
- C = CL[1]
- else if (O && istype(O, /obj/machinery/camera))
- C = O
- L[A.name] = list(A, (C) ? C : O, list(alarmsource))
- queueAlarm(text("--- [class] alarm detected in [A.name]!"), class)
+
+ var/obj/machinery/camera/cam = null
+ var/list/our_cams = null
+ if(cameras && islist(cameras))
+ our_cams = cameras
+ if (our_cams.len == 1)
+ cam = our_cams[1]
+ else if(cameras && istype(cameras, /obj/machinery/camera))
+ cam = cameras
+ our_sort[home.name] = list(home, (cam ? cam : cameras), list(source))
+ queueAlarm(text("--- [class] alarm detected in [home.name]!"), class)
return TRUE
+/mob/living/silicon/robot/freeCamera(area/home, obj/machinery/camera/cam)
+ for(var/class in alarms)
+ var/our_area = alarms[class][home.name]
+ if(!our_area)
+ continue
+ var/cams = our_area[2] //Get the cameras
+ if(!cams)
+ continue
+ if(islist(cams))
+ cams -= cam
+ if(length(cams) == 1)
+ our_area[2] = cams[1]
+ else
+ our_area[2] = null
+
/mob/living/silicon/robot/cancelAlarm(class, area/A, obj/origin)
var/list/L = alarms[class]
var/cleared = FALSE
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index ba1afd9709f..f3e8e5759a6 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -81,6 +81,9 @@
/mob/living/silicon/proc/cancelAlarm()
return
+/mob/living/silicon/proc/freeCamera()
+ return
+
/mob/living/silicon/proc/triggerAlarm()
return
diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm
index 2376e53d871..c1c6cead2c3 100644
--- a/code/modules/mob/living/simple_animal/bot/bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/bot.dm
@@ -190,9 +190,9 @@
GLOB.bots_list -= src
if(paicard)
ejectpai()
- qdel(Radio)
- qdel(access_card)
- qdel(bot_core)
+ QDEL_NULL(Radio)
+ QDEL_NULL(access_card)
+ QDEL_NULL(bot_core)
return ..()
/mob/living/simple_animal/bot/bee_friendly()
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
index 3dc85a604f0..51ef71cc72f 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
@@ -265,20 +265,26 @@
* * O - unused argument, see [/mob/living/silicon/robot/triggerAlarm]
* * alarmsource - [/atom] source of the alarm
*/
-/mob/living/simple_animal/drone/proc/triggerAlarm(class, area/A, O, obj/alarmsource)
- if(alarmsource.z != z)
+/mob/living/simple_animal/drone/proc/triggerAlarm(class, area/home, cameras, obj/source)
+ if(source.z != z)
return
- if(stat != DEAD)
- var/list/L = src.alarms[class]
- for (var/I in L)
- if (I == A.name)
- var/list/alarm = L[I]
- var/list/sources = alarm[2]
- if (!(alarmsource in sources))
- sources += alarmsource
- return
- L[A.name] = list(A, list(alarmsource))
- to_chat(src, "--- [class] alarm detected in [A.name]!")
+ if(stat == DEAD)
+ return
+ var/list/our_sort = alarms[class]
+ for(var/areaname in our_sort)
+ if (areaname == home.name)
+ var/list/alarm = our_sort[areaname]
+ var/list/sources = alarm[3]
+ if (!(source in sources))
+ sources += source
+ return TRUE
+
+ our_sort[home.name] = list(home, list(source))
+ to_chat(src, "--- [class] alarm detected in [home.name]!")
+
+///This isn't currently needed since drones do jack shit with cameras. I hate this code so much
+/mob/living/simple_animal/drone/proc/freeCamera(area/home, obj/machinery/camera/cam)
+ return
/**
* Clears alarm and alerts drones
diff --git a/code/modules/mob/mob_lists.dm b/code/modules/mob/mob_lists.dm
index 14f519ec30f..bd47d511e1d 100644
--- a/code/modules/mob/mob_lists.dm
+++ b/code/modules/mob/mob_lists.dm
@@ -10,6 +10,8 @@
///Adds the mob reference to the list of all mobs alive. If mob is cliented, it adds it to the list of all living player-mobs.
/mob/proc/add_to_alive_mob_list()
+ if(QDELETED(src))
+ return
GLOB.alive_mob_list |= src
if(client)
add_to_current_living_players()
@@ -23,6 +25,8 @@
///Adds the mob reference to the list of all the dead mobs. If mob is cliented, it adds it to the list of all dead player-mobs.
/mob/proc/add_to_dead_mob_list()
+ if(QDELETED(src))
+ return
GLOB.dead_mob_list |= src
if(client)
add_to_current_dead_players()
diff --git a/code/modules/modular_computers/file_system/programs/alarm.dm b/code/modules/modular_computers/file_system/programs/alarm.dm
index 8ef71a93067..d0fec22b0bc 100644
--- a/code/modules/modular_computers/file_system/programs/alarm.dm
+++ b/code/modules/modular_computers/file_system/programs/alarm.dm
@@ -37,35 +37,49 @@
return data
-/datum/computer_file/program/alarm_monitor/proc/triggerAlarm(class, area/A, O, obj/source)
+/datum/computer_file/program/alarm_monitor/proc/triggerAlarm(class, area/home, cameras, obj/source)
if(is_station_level(source.z))
- if(!(A.type in GLOB.the_station_areas))
+ if(!(home.type in GLOB.the_station_areas))
return
- else if(!is_mining_level(source.z) || istype(A, /area/ruin))
+ else if(!is_mining_level(source.z) || istype(home, /area/ruin))
return
- var/list/L = alarms[class]
- for(var/I in L)
- if (I == A.name)
- var/list/alarm = L[I]
+ var/list/our_sort = alarms[class]
+ for(var/areaname in our_sort)
+ if (areaname == home.name)
+ var/list/alarm = our_sort[areaname]
var/list/sources = alarm[3]
if (!(source in sources))
sources += source
- return 1
- var/obj/machinery/camera/C = null
- var/list/CL = null
- if(O && istype(O, /list))
- CL = O
- if (CL.len == 1)
- C = CL[1]
- else if(O && istype(O, /obj/machinery/camera))
- C = O
- L[A.name] = list(A, (C ? C : O), list(source))
+ return TRUE
+
+ var/obj/machinery/camera/cam = null
+ var/list/our_cams = null
+ if(cameras && islist(cameras))
+ our_cams = cameras
+ if (our_cams.len == 1)
+ cam = our_cams[1]
+ else if(cameras && istype(cameras, /obj/machinery/camera))
+ cam = cameras
+ our_sort[home.name] = list(home, (cam ? cam : cameras), list(source))
update_alarm_display()
+ return TRUE
- return 1
-
+/datum/computer_file/program/alarm_monitor/proc/freeCamera(area/home, obj/machinery/camera/cam)
+ for(var/class in alarms)
+ var/our_area = alarms[class][home.name]
+ if(!our_area)
+ continue
+ var/cams = our_area[2] //Get the cameras
+ if(!cams)
+ continue
+ if(islist(cams))
+ cams -= cam
+ if(length(cams) == 1)
+ our_area[2] = cams[1]
+ else
+ our_area[2] = null
/datum/computer_file/program/alarm_monitor/proc/cancelAlarm(class, area/A, obj/origin)
var/list/L = alarms[class]
diff --git a/code/modules/paperwork/ticketmachine.dm b/code/modules/paperwork/ticketmachine.dm
index b66a5c546f8..3a5526d60c0 100644
--- a/code/modules/paperwork/ticketmachine.dm
+++ b/code/modules/paperwork/ticketmachine.dm
@@ -82,15 +82,15 @@
if(M.buffer && !istype(M.buffer, /obj/machinery/ticket_machine))
return
var/obj/item/assembly/control/ticket_machine/controller = device
- controller.linked = M.buffer
+ controller.linked = WEAKREF(M.buffer)
id = null
controller.id = null
- to_chat(user, "You've linked [src] to [controller.linked].")
+ to_chat(user, "You've linked [src] to [M.buffer].")
/obj/item/assembly/control/ticket_machine
name = "ticket machine controller"
desc = "A remote controller for the HoP's ticket machine."
- var/obj/machinery/ticket_machine/linked //To whom are we linked?
+ var/datum/weakref/linked //To whom are we linked?
/obj/item/assembly/control/ticket_machine/Initialize()
..()
@@ -102,7 +102,7 @@
/obj/item/assembly/control/ticket_machine/proc/find_machine() //Locate the one to which we're linked
for(var/obj/machinery/ticket_machine/ticketsplease in GLOB.machines)
if(ticketsplease.id == id)
- linked = ticketsplease
+ linked = WEAKREF(ticketsplease)
if(linked)
return TRUE
else
@@ -113,8 +113,11 @@
return
if(!linked)
return
+ var/obj/machinery/ticket_machine/machine = linked.resolve()
+ if(!machine)
+ return
cooldown = TRUE
- linked.increment()
+ machine.increment()
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 10)
/obj/machinery/ticket_machine/update_icon()
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index ce6a818f84a..f07af00a513 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -258,6 +258,7 @@
area.power_equip = FALSE
area.power_environ = FALSE
area.power_change()
+ area.poweralert(FALSE, src)
if(occupier)
malfvacate(1)
qdel(wires)
diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm
index a4043662f01..86e958710b7 100644
--- a/code/modules/power/lighting.dm
+++ b/code/modules/power/lighting.dm
@@ -620,7 +620,7 @@
drop_light_tube()
new /obj/item/stack/cable_coil(loc, 1, "red")
transfer_fingerprints_to(newlight)
- if(cell)
+ if(!QDELETED(cell))
newlight.cell = cell
cell.forceMove(newlight)
cell = null
diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
index 1079bcadf5f..3d932c6f015 100644
--- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
@@ -591,27 +591,12 @@
desc = "Contains a large reservoir of soft drinks. This model has had its safeties shorted out."
obj_flags = CAN_BE_HIT | EMAGGED
flags_1 = NODECONSTRUCT_1
+ circuit = /obj/item/circuitboard/machine/chem_dispenser/drinks/fullupgrade
/obj/machinery/chem_dispenser/drinks/fullupgrade/Initialize()
. = ..()
dispensable_reagents |= emagged_reagents //adds emagged reagents
- // Cache the old_parts first, we'll delete it after we've changed component_parts to a new list.
- // This stops handle_atom_del being called on every part when not necessary.
- var/list/old_parts = component_parts.Copy()
-
- component_parts = list()
- component_parts += new /obj/item/circuitboard/machine/chem_dispenser/drinks(src)
- component_parts += new /obj/item/stock_parts/matter_bin/bluespace(src)
- component_parts += new /obj/item/stock_parts/matter_bin/bluespace(src)
- component_parts += new /obj/item/stock_parts/capacitor/quadratic(src)
- component_parts += new /obj/item/stock_parts/manipulator/femto(src)
- component_parts += new /obj/item/stack/sheet/glass(src, 1)
- component_parts += new /obj/item/stock_parts/cell/bluespace(src)
-
- QDEL_LIST(old_parts)
- RefreshParts()
-
/obj/machinery/chem_dispenser/drinks/beer
name = "booze dispenser"
desc = "Contains a large reservoir of the good stuff."
@@ -654,27 +639,12 @@
desc = "Contains a large reservoir of the good stuff. This model has had its safeties shorted out."
obj_flags = CAN_BE_HIT | EMAGGED
flags_1 = NODECONSTRUCT_1
+ circuit = /obj/item/circuitboard/machine/chem_dispenser/drinks/beer/fullupgrade
/obj/machinery/chem_dispenser/drinks/beer/fullupgrade/Initialize()
. = ..()
dispensable_reagents |= emagged_reagents //adds emagged reagents
- // Cache the old_parts first, we'll delete it after we've changed component_parts to a new list.
- // This stops handle_atom_del being called on every part when not necessary.
- var/list/old_parts = component_parts.Copy()
-
- component_parts = list()
- component_parts += new /obj/item/circuitboard/machine/chem_dispenser/drinks/beer(src)
- component_parts += new /obj/item/stock_parts/matter_bin/bluespace(src)
- component_parts += new /obj/item/stock_parts/matter_bin/bluespace(src)
- component_parts += new /obj/item/stock_parts/capacitor/quadratic(src)
- component_parts += new /obj/item/stock_parts/manipulator/femto(src)
- component_parts += new /obj/item/stack/sheet/glass(src, 1)
- component_parts += new /obj/item/stock_parts/cell/bluespace(src)
-
- QDEL_LIST(old_parts)
- RefreshParts()
-
/obj/machinery/chem_dispenser/mutagen
name = "mutagen dispenser"
desc = "Creates and dispenses mutagen."
@@ -688,6 +658,8 @@
desc = "Creates and dispenses chemicals useful for botany."
flags_1 = NODECONSTRUCT_1
+ circuit = /obj/item/circuitboard/machine/chem_dispenser/mutagensaltpeter
+
dispensable_reagents = list(
/datum/reagent/toxin/mutagen,
/datum/reagent/saltpetre,
@@ -704,50 +676,16 @@
/datum/reagent/diethylamine)
upgrade_reagents = null
-/obj/machinery/chem_dispenser/mutagensaltpeter/Initialize()
- . = ..()
-
- // Cache the old_parts first, we'll delete it after we've changed component_parts to a new list.
- // This stops handle_atom_del being called on every part when not necessary.
- var/list/old_parts = component_parts.Copy()
-
- component_parts = list()
- component_parts += new /obj/item/circuitboard/machine/chem_dispenser(src)
- component_parts += new /obj/item/stock_parts/matter_bin/bluespace(src)
- component_parts += new /obj/item/stock_parts/matter_bin/bluespace(src)
- component_parts += new /obj/item/stock_parts/capacitor/quadratic(src)
- component_parts += new /obj/item/stock_parts/manipulator/femto(src)
- component_parts += new /obj/item/stack/sheet/glass(src, 1)
- component_parts += new /obj/item/stock_parts/cell/bluespace(src)
-
- QDEL_LIST(old_parts)
- RefreshParts()
-
/obj/machinery/chem_dispenser/fullupgrade //fully ugpraded stock parts, emagged
desc = "Creates and dispenses chemicals. This model has had its safeties shorted out."
obj_flags = CAN_BE_HIT | EMAGGED
flags_1 = NODECONSTRUCT_1
+ circuit = /obj/item/circuitboard/machine/chem_dispenser/fullupgrade
/obj/machinery/chem_dispenser/fullupgrade/Initialize()
. = ..()
dispensable_reagents |= emagged_reagents //adds emagged reagents
- // Cache the old_parts first, we'll delete it after we've changed component_parts to a new list.
- // This stops handle_atom_del being called on every part when not necessary.
- var/list/old_parts = component_parts.Copy()
-
- component_parts = list()
- component_parts += new /obj/item/circuitboard/machine/chem_dispenser(src)
- component_parts += new /obj/item/stock_parts/matter_bin/bluespace(src)
- component_parts += new /obj/item/stock_parts/matter_bin/bluespace(src)
- component_parts += new /obj/item/stock_parts/capacitor/quadratic(src)
- component_parts += new /obj/item/stock_parts/manipulator/femto(src)
- component_parts += new /obj/item/stack/sheet/glass(src, 1)
- component_parts += new /obj/item/stock_parts/cell/bluespace(src)
-
- QDEL_LIST(old_parts)
- RefreshParts()
-
/obj/machinery/chem_dispenser/abductor
name = "reagent synthesizer"
desc = "Synthesizes a variety of reagents using proto-matter."
@@ -798,22 +736,3 @@
/datum/reagent/toxin/plasma,
/datum/reagent/uranium
)
-
-/obj/machinery/chem_dispenser/abductor/Initialize()
- . = ..()
-
- // Cache the old_parts first, we'll delete it after we've changed component_parts to a new list.
- // This stops handle_atom_del being called on every part when not necessary.
- var/list/old_parts = component_parts.Copy()
-
- component_parts = list()
- component_parts += new /obj/item/circuitboard/machine/chem_dispenser(src)
- component_parts += new /obj/item/stock_parts/matter_bin/bluespace(src)
- component_parts += new /obj/item/stock_parts/matter_bin/bluespace(src)
- component_parts += new /obj/item/stock_parts/capacitor/quadratic(src)
- component_parts += new /obj/item/stock_parts/manipulator/femto(src)
- component_parts += new /obj/item/stack/sheet/glass(src, 1)
- component_parts += new /obj/item/stock_parts/cell/bluespace(src)
-
- QDEL_LIST(old_parts)
- RefreshParts()
diff --git a/code/modules/recycling/disposal/pipe.dm b/code/modules/recycling/disposal/pipe.dm
index a01c9f6af2d..ea212bed07e 100644
--- a/code/modules/recycling/disposal/pipe.dm
+++ b/code/modules/recycling/disposal/pipe.dm
@@ -51,7 +51,7 @@
if(H)
H.active = FALSE
expel(H, get_turf(src), 0)
- QDEL_NULL(stored)
+ stored = null //The qdel is handled in expel()
return ..()
/obj/structure/disposalpipe/handle_atom_del(atom/A)
diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm
index 1571c03756a..6b30abc9d63 100644
--- a/code/modules/spells/spell.dm
+++ b/code/modules/spells/spell.dm
@@ -37,8 +37,7 @@
GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for the badmin verb for now
/obj/effect/proc_holder/Destroy()
- if (action)
- qdel(action)
+ QDEL_NULL(action)
if(ranged_ability_user)
remove_ranged_ability()
return ..()
diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm
index c3bbe01ebab..0cafc5d1d1a 100644
--- a/code/modules/surgery/bodyparts/_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/_bodyparts.dm
@@ -9,7 +9,7 @@
icon_state = ""
layer = BELOW_MOB_LAYER //so it isn't hidden behind objects when on the floor
var/mob/living/carbon/owner = null
- var/mob/living/carbon/original_owner = null
+ var/datum/weakref/original_owner = null
var/status = BODYPART_ORGANIC
//var/needs_processing = FALSE SKYRAT EDIT REMOVAL
@@ -776,10 +776,10 @@
if(source)
C = source
if(!original_owner)
- original_owner = source
+ original_owner = WEAKREF(source)
else
C = owner
- if(original_owner && owner != original_owner) //Foreign limb
+ if(original_owner && !IS_WEAKREF_OF(owner, original_owner)) //Foreign limb
no_update = TRUE
else
no_update = FALSE
diff --git a/code/modules/vehicles/mecha/_mecha.dm b/code/modules/vehicles/mecha/_mecha.dm
index 38d7caad19f..366b8e58572 100644
--- a/code/modules/vehicles/mecha/_mecha.dm
+++ b/code/modules/vehicles/mecha/_mecha.dm
@@ -224,6 +224,7 @@
for(var/obj/item/mecha_parts/mecha_equipment/equip as anything in equipment)
equip.detach(loc)
qdel(equip)
+ radio = null
STOP_PROCESSING(SSobj, src)
LAZYCLEARLIST(equipment)
@@ -237,6 +238,8 @@
QDEL_NULL(smoke_system)
GLOB.mechas_list -= src //global mech list
+ for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds)
+ diag_hud.remove_from_hud(src) //YEET
return ..()
/obj/vehicle/sealed/mecha/obj_destruction()