diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm index d3d35ac4ddf..d775224a6a2 100644 --- a/code/_onclick/hud/robot.dm +++ b/code/_onclick/hud/robot.dm @@ -300,6 +300,11 @@ icon_state = "[base_icon_state]_[robot?.lamp_enabled ? "on" : "off"]" return ..() +/atom/movable/screen/robot/lamp/Destroy() + robot.lampButton = null + robot = null + return ..() + /atom/movable/screen/robot/modPC name = "Modular Interface" icon_state = "template" @@ -311,6 +316,11 @@ return robot.modularInterface?.interact(robot) +/atom/movable/screen/robot/modPC/Destroy() + robot.interfaceButton = null + robot = null + return ..() + /atom/movable/screen/robot/alerts name = "Alert Panel" icon = 'icons/hud/screen_ai.dmi' diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm index 499278ca176..1ca37d04882 100644 --- a/code/_onclick/observer.dm +++ b/code/_onclick/observer.dm @@ -76,6 +76,12 @@ return ..() /obj/machinery/teleport/hub/attack_ghost(mob/user) - if(power_station?.engaged && power_station.teleporter_console && power_station.teleporter_console.target) - user.abstract_move(get_turf(power_station.teleporter_console.target)) - return ..() + if(!power_station?.engaged || !power_station.teleporter_console || !power_station.teleporter_console.target_ref) + return ..() + + var/atom/target = power_station.teleporter_console.target_ref.resolve() + if(!target) + power_station.teleporter_console.target_ref = null + return ..() + + user.abstract_move(get_turf(target)) diff --git a/code/controllers/subsystem/icon_smooth.dm b/code/controllers/subsystem/icon_smooth.dm index 2979a2645e5..ec941f9b18c 100644 --- a/code/controllers/subsystem/icon_smooth.dm +++ b/code/controllers/subsystem/icon_smooth.dm @@ -47,7 +47,7 @@ SUBSYSTEM_DEF(icon_smooth) CHECK_TICK queue = blueprint_queue - blueprint_queue = list() + blueprint_queue = null for(var/item in queue) var/atom/movable/movable_item = item @@ -70,5 +70,6 @@ SUBSYSTEM_DEF(icon_smooth) /datum/controller/subsystem/icon_smooth/proc/remove_from_queues(atom/thing) thing.smoothing_flags &= ~SMOOTH_QUEUED smooth_queue -= thing - blueprint_queue -= thing + if(blueprint_queue) + blueprint_queue -= thing deferred -= thing diff --git a/code/controllers/subsystem/throwing.dm b/code/controllers/subsystem/throwing.dm index 16374fbd201..6b3ab2ccf9b 100644 --- a/code/controllers/subsystem/throwing.dm +++ b/code/controllers/subsystem/throwing.dm @@ -42,7 +42,6 @@ SUBSYSTEM_DEF(throwing) /datum/thrownthing var/atom/movable/thrownthing - var/atom/target var/turf/target_turf var/target_zone var/init_dir @@ -66,11 +65,10 @@ SUBSYSTEM_DEF(throwing) var/last_move = 0 -/datum/thrownthing/New(thrownthing, target, target_turf, init_dir, maxrange, speed, thrower, diagonals_first, force, gentle, callback, target_zone) +/datum/thrownthing/New(thrownthing, target_turf, init_dir, maxrange, speed, thrower, diagonals_first, force, gentle, callback, target_zone) . = ..() src.thrownthing = thrownthing RegisterSignal(thrownthing, COMSIG_PARENT_QDELETING, .proc/on_thrownthing_qdel) - src.target = target src.target_turf = target_turf src.init_dir = init_dir src.maxrange = maxrange @@ -88,7 +86,6 @@ SUBSYSTEM_DEF(throwing) SSthrowing.currentrun -= thrownthing thrownthing.throwing = null thrownthing = null - target = null thrower = null if(callback) QDEL_NULL(callback) //It stores a reference to the thrownthing, its source. Let's clean that. diff --git a/code/datums/brain_damage/split_personality.dm b/code/datums/brain_damage/split_personality.dm index 756903fa5ce..5efe286e0f8 100644 --- a/code/datums/brain_damage/split_personality.dm +++ b/code/datums/brain_damage/split_personality.dm @@ -58,6 +58,13 @@ QDEL_NULL(owner_backseat) ..() +/datum/brain_trauma/severe/split_personality/Destroy() + if(stranger_backseat) + QDEL_NULL(stranger_backseat) + if(owner_backseat) + QDEL_NULL(owner_backseat) + return ..() + /datum/brain_trauma/severe/split_personality/proc/switch_personalities(reset_to_owner = FALSE) if(QDELETED(owner) || QDELETED(stranger_backseat) || QDELETED(owner_backseat)) return diff --git a/code/datums/components/chasm.dm b/code/datums/components/chasm.dm index 68c8daea7aa..74f916d9785 100644 --- a/code/datums/components/chasm.dm +++ b/code/datums/components/chasm.dm @@ -4,7 +4,8 @@ var/fall_message = "GAH! Ah... where are you?" var/oblivion_message = "You stumble and stare into the abyss before you. It stares back, and you fall into the enveloping dark." - var/static/list/falling_atoms = list() // Atoms currently falling into chasms + /// List of refs to falling objects -> how many levels deep we've fallen + var/static/list/falling_atoms = list() var/static/list/forbidden_types = typecacheof(list( /obj/singularity, /obj/energy_ball, @@ -54,7 +55,6 @@ return LAZYLEN(found_safeties) /datum/component/chasm/proc/drop_stuff(AM) - . = 0 if (is_safe()) return FALSE @@ -62,12 +62,13 @@ var/to_check = AM ? list(AM) : parent.contents for (var/thing in to_check) if (droppable(thing)) - . = 1 + . = TRUE INVOKE_ASYNC(src, .proc/drop, thing) /datum/component/chasm/proc/droppable(atom/movable/AM) + var/datum/weakref/falling_ref = WEAKREF(AM) // avoid an infinite loop, but allow falling a large distance - if(falling_atoms[AM] && falling_atoms[AM] > 30) + if(falling_atoms[falling_ref] && falling_atoms[falling_ref] > 30) return FALSE if(!isliving(AM) && !isobj(AM)) return FALSE @@ -91,10 +92,12 @@ return TRUE /datum/component/chasm/proc/drop(atom/movable/AM) + var/datum/weakref/falling_ref = WEAKREF(AM) //Make sure the item is still there after our sleep - if(!AM || QDELETED(AM)) + if(!AM || !falling_ref?.resolve()) + falling_atoms -= falling_ref return - falling_atoms[AM] = (falling_atoms[AM] || 0) + 1 + falling_atoms[falling_ref] = (falling_atoms[falling_ref] || 0) + 1 var/turf/T = target_turf if(T) @@ -106,7 +109,7 @@ var/mob/living/L = AM L.Paralyze(100) L.adjustBruteLoss(30) - falling_atoms -= AM + falling_atoms -= falling_ref else // send to oblivion @@ -135,7 +138,7 @@ var/mob/living/silicon/robot/S = AM qdel(S.mmi) - falling_atoms -= AM + falling_atoms -= falling_ref qdel(AM) if(AM && !QDELETED(AM)) //It's indestructible var/atom/parent = src.parent diff --git a/code/datums/elements/weather_listener.dm b/code/datums/elements/weather_listener.dm index 956a355d97b..c5a568a480c 100644 --- a/code/datums/elements/weather_listener.dm +++ b/code/datums/elements/weather_listener.dm @@ -24,8 +24,8 @@ weather_trait = trait playlist = weather_playlist - RegisterSignal(target, COMSIG_MOVABLE_Z_CHANGED, .proc/handle_z_level_change) - RegisterSignal(target, COMSIG_MOB_LOGOUT, .proc/handle_logout) + RegisterSignal(target, COMSIG_MOVABLE_Z_CHANGED, .proc/handle_z_level_change, override = TRUE) + RegisterSignal(target, COMSIG_MOB_LOGOUT, .proc/handle_logout, override = TRUE) /datum/element/weather_listener/Detach(datum/source) . = ..() diff --git a/code/datums/holocall.dm b/code/datums/holocall.dm index 1702bafcaa6..c165ae480df 100644 --- a/code/datums/holocall.dm +++ b/code/datums/holocall.dm @@ -81,6 +81,7 @@ if(!QDELETED(hologram)) hologram.HC = null QDEL_NULL(hologram) + hologram = null for(var/I in dialed_holopads) var/obj/machinery/holopad/H = I diff --git a/code/datums/mergers/_merger.dm b/code/datums/mergers/_merger.dm index 76ba6202727..d59470b9313 100644 --- a/code/datums/mergers/_merger.dm +++ b/code/datums/mergers/_merger.dm @@ -19,10 +19,7 @@ #endif /// Signals in members to trigger a refresh - var/static/list/refresh_signals = list( - COMSIG_PARENT_QDELETING, - COMSIG_MOVABLE_MOVED, - ) + var/static/list/refresh_signals = list(COMSIG_MOVABLE_MOVED) /datum/merger/New(id, list/merged_typecache, atom/origin, attempt_merge_proc) #if MERGERS_DEBUG @@ -42,18 +39,21 @@ /datum/merger/proc/RemoveMember(atom/thing, clean=TRUE) SEND_SIGNAL(thing, COMSIG_MERGER_REMOVING, src) UnregisterSignal(thing, refresh_signals) + UnregisterSignal(thing, COMSIG_PARENT_QDELETING) if(!thing.mergers) return thing.mergers -= id if(clean && !length(thing.mergers)) thing.mergers = null members -= thing + origin = null if(origin == thing && length(members)) origin = pick(members) /datum/merger/proc/AddMember(atom/thing, connected_dir) // note that this fires for the origin of the merger as well SEND_SIGNAL(thing, COMSIG_MERGER_ADDING, src) RegisterSignal(thing, refresh_signals, .proc/QueueRefresh) + RegisterSignal(thing, COMSIG_PARENT_QDELETING, .proc/HandleMemberDel) if(!thing.mergers) thing.mergers = list() else if(thing.mergers[id]) @@ -73,6 +73,11 @@ sleep(1 SECONDS) #endif +/datum/merger/proc/HandleMemberDel(atom/source) + SIGNAL_HANDLER + RemoveMember(source) + QueueRefresh() + /datum/merger/proc/QueueRefresh() SIGNAL_HANDLER addtimer(CALLBACK(src, .proc/Refresh), 1, TIMER_UNIQUE) diff --git a/code/datums/mutations/antenna.dm b/code/datums/mutations/antenna.dm index 15721f888f7..77bb76e0345 100644 --- a/code/datums/mutations/antenna.dm +++ b/code/datums/mutations/antenna.dm @@ -6,7 +6,7 @@ text_lose_indication = "Your antenna shrinks back down." instability = 5 difficulty = 8 - var/obj/item/implant/radio/antenna/linked_radio + var/datum/weakref/radio_weakref /obj/item/implant/radio/antenna name = "internal antenna organ" @@ -21,13 +21,16 @@ /datum/mutation/human/antenna/on_acquiring(mob/living/carbon/human/owner) if(..()) return - linked_radio = new(owner) + var/obj/item/implant/radio/antenna/linked_radio = new(owner) linked_radio.implant(owner, null, TRUE, TRUE) + radio_weakref = WEAKREF(linked_radio) /datum/mutation/human/antenna/on_losing(mob/living/carbon/human/owner) if(..()) return - QDEL_NULL(linked_radio) + var/obj/item/implant/radio/antenna/linked_radio = radio_weakref.resolve() + if(linked_radio) + QDEL_NULL(linked_radio) /datum/mutation/human/antenna/New(class_ = MUT_OTHER, timer, datum/mutation/human/copymut) ..() diff --git a/code/datums/status_effects/status_effect.dm b/code/datums/status_effects/status_effect.dm index 5fd836948ae..85e18550ff9 100644 --- a/code/datums/status_effects/status_effect.dm +++ b/code/datums/status_effects/status_effect.dm @@ -21,11 +21,11 @@ /datum/status_effect/proc/on_creation(mob/living/new_owner, ...) if(new_owner) owner = new_owner - if(owner) - LAZYADD(owner.status_effects, src) - if(!owner || !on_apply()) + if(QDELETED(owner) || !on_apply()) qdel(src) return + if(owner) + LAZYADD(owner.status_effects, src) if(duration != -1) duration = world.time + duration tick_interval = world.time + tick_interval diff --git a/code/game/atoms.dm b/code/game/atoms.dm index c4852738ec8..344dd1598b4 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -455,7 +455,6 @@ ///Take air from the passed in gas mixture datum /atom/proc/assume_air(datum/gas_mixture/giver) - qdel(giver) return null ///Remove air from this atom diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 663d5041978..62a5801ab7a 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -129,6 +129,8 @@ if(pulledby) pulledby.stop_pulling() + if(pulling) + stop_pulling() if(orbiting) orbiting.end_orbit(src) @@ -159,7 +161,7 @@ gen_emissive_blocker.appearance_flags |= appearance_flags return gen_emissive_blocker else if(blocks_emissive == EMISSIVE_BLOCK_UNIQUE) - if(!em_block) + if(!em_block && !QDELETED(src)) render_target = ref(src) em_block = new(src, render_target) return em_block @@ -872,7 +874,7 @@ else target_zone = thrower.zone_selected - var/datum/thrownthing/TT = new(src, target, get_turf(target), get_dir(src, target), range, speed, thrower, diagonals_first, force, gentle, callback, target_zone) + var/datum/thrownthing/TT = new(src, get_turf(target), get_dir(src, target), range, speed, thrower, diagonals_first, force, gentle, callback, target_zone) var/dist_x = abs(target.x - src.x) var/dist_y = abs(target.y - src.y) diff --git a/code/game/communications.dm b/code/game/communications.dm index ae36cda5343..3c52c5b2eaa 100644 --- a/code/game/communications.dm +++ b/code/game/communications.dm @@ -134,8 +134,9 @@ GLOBAL_LIST_INIT(reverseradiochannels, list( )) /datum/radio_frequency - var/frequency as num - var/list/list/obj/devices = list() + var/frequency + /// List of filters -> list of devices + var/list/list/datum/weakref/devices = list() /datum/radio_frequency/New(freq) frequency = freq @@ -165,7 +166,11 @@ GLOBAL_LIST_INIT(reverseradiochannels, list( //Send the data for(var/current_filter in filter_list) - for(var/obj/device in devices[current_filter]) + for(var/datum/weakref/device_ref as anything in devices[current_filter]) + var/obj/device = device_ref.resolve() + if(!device) + devices[current_filter] -= device_ref + continue if(device == source) continue if(range) @@ -183,7 +188,7 @@ GLOBAL_LIST_INIT(reverseradiochannels, list( var/list/devices_line = devices[filter] if(!devices_line) devices[filter] = devices_line = list() - devices_line += device + devices_line += WEAKREF(device) /datum/radio_frequency/proc/remove_listener(obj/device) @@ -191,7 +196,7 @@ GLOBAL_LIST_INIT(reverseradiochannels, list( var/list/devices_line = devices[devices_filter] if(!devices_line) devices -= devices_filter - devices_line -= device + devices_line -= WEAKREF(device) if(!devices_line.len) devices -= devices_filter diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index e4ef225894e..5a06e4a2cf1 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -23,7 +23,7 @@ var/start_active = FALSE //If it ignores the random chance to start broken on round start var/invuln = null var/obj/item/camera_bug/bug = null - var/obj/structure/camera_assembly/assembly = null + var/datum/weakref/assembly_ref = null var/area/myarea = null //OTHER @@ -56,6 +56,7 @@ for(var/i in network) network -= i network += lowertext(i) + var/obj/structure/camera_assembly/assembly if(CA) assembly = CA if(assembly.xray_module) @@ -73,6 +74,7 @@ else assembly = new(src) assembly.state = 4 //STATE_FINISHED + assembly_ref = WEAKREF(assembly) GLOB.cameranet.cameras += src GLOB.cameranet.addCamera(src) if (isturf(loc)) @@ -100,11 +102,12 @@ /obj/machinery/camera/Destroy() if(can_use()) toggle_cam(null, 0) //kick anyone viewing out and remove from the camera chunks + GLOB.cameranet.removeCamera(src) GLOB.cameranet.cameras -= src cancelCameraAlarm() if(isarea(myarea)) myarea.clear_camera(src) - QDEL_NULL(assembly) + QDEL_NULL(assembly_ref) if(bug) bug.bugged_cameras -= c_tag if(bug.current == src) @@ -204,6 +207,10 @@ . = ..() if(!panel_open) return + var/obj/structure/camera_assembly/assembly = assembly_ref?.resolve() + if(!assembly) + assembly_ref = null + return var/list/droppable_parts = list() if(assembly.xray_module) droppable_parts += assembly.xray_module @@ -267,6 +274,9 @@ /obj/machinery/camera/attackby(obj/item/I, mob/living/user, params) // UPGRADES if(panel_open) + var/obj/structure/camera_assembly/assembly = assembly_ref?.resolve() + if(!assembly) + assembly_ref = null if(I.tool_behaviour == TOOL_ANALYZER) if(!isXRay(TRUE)) //don't reveal it was already upgraded if was done via MALF AI Upgrade Camera Network ability if(!user.temporarilyRemoveItemFromInventory(I)) @@ -342,7 +352,7 @@ else to_chat(user, span_notice("Camera bugged.")) bug = I - bug.bugged_cameras[src.c_tag] = src + bug.bugged_cameras[src.c_tag] = WEAKREF(src) return return ..() @@ -364,12 +374,13 @@ /obj/machinery/camera/deconstruct(disassembled = TRUE) if(!(flags_1 & NODECONSTRUCT_1)) if(disassembled) + var/obj/structure/camera_assembly/assembly = assembly_ref?.resolve() if(!assembly) assembly = new() assembly.forceMove(drop_location()) assembly.state = 1 assembly.setDir(dir) - assembly = null + assembly_ref = null else var/obj/item/I = new /obj/item/wallframe/camera (loc) I.update_integrity(I.max_integrity * 0.5) diff --git a/code/game/machinery/camera/motion.dm b/code/game/machinery/camera/motion.dm index 4dd308a6fe7..5914e2f1930 100644 --- a/code/game/machinery/camera/motion.dm +++ b/code/game/machinery/camera/motion.dm @@ -38,10 +38,9 @@ return TRUE /obj/machinery/camera/Destroy() - var/area/ai_monitored/A = get_area(src) localMotionTargets = null - if(istype(A)) - A.motioncameras -= src + if(area_motion) + area_motion.motioncameras -= src cancelAlarm() return ..() diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm index 47615a045f5..fa61ebceda4 100644 --- a/code/game/machinery/camera/presets.dm +++ b/code/game/machinery/camera/presets.dm @@ -72,12 +72,14 @@ // UPGRADE PROCS /obj/machinery/camera/proc/isEmpProof(ignore_malf_upgrades) - return (upgrades & CAMERA_UPGRADE_EMP_PROOF) && (!(ignore_malf_upgrades && assembly.malf_emp_firmware_active)) + var/obj/structure/camera_assembly/assembly = assembly_ref?.resolve() + return (upgrades & CAMERA_UPGRADE_EMP_PROOF) && (!(ignore_malf_upgrades && assembly?.malf_emp_firmware_active)) /obj/machinery/camera/proc/upgradeEmpProof(malf_upgrade, ignore_malf_upgrades) if(isEmpProof(ignore_malf_upgrades)) //pass a malf upgrade to ignore_malf_upgrades so we can replace the malf module with the normal one return //that way if someone tries to upgrade an already malf-upgraded camera, it'll just upgrade it to a normal version. AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES | EMP_PROTECT_CONTENTS) + var/obj/structure/camera_assembly/assembly = assembly_ref?.resolve() if(malf_upgrade) assembly.malf_emp_firmware_active = TRUE //don't add parts to drop, update icon, ect. reconstructing it will also retain the upgrade. assembly.malf_emp_firmware_present = TRUE //so the upgrade is retained after incompatible parts are removed. @@ -98,11 +100,13 @@ /obj/machinery/camera/proc/isXRay(ignore_malf_upgrades) + var/obj/structure/camera_assembly/assembly = assembly_ref?.resolve() return (upgrades & CAMERA_UPGRADE_XRAY) && (!(ignore_malf_upgrades && assembly.malf_xray_firmware_active)) /obj/machinery/camera/proc/upgradeXRay(malf_upgrade, ignore_malf_upgrades) if(isXRay(ignore_malf_upgrades)) //pass a malf upgrade to ignore_malf_upgrades so we can replace the malf upgrade with the normal one return //that way if someone tries to upgrade an already malf-upgraded camera, it'll just upgrade it to a normal version. + var/obj/structure/camera_assembly/assembly = assembly_ref?.resolve() if(malf_upgrade) assembly.malf_xray_firmware_active = TRUE //don't add parts to drop, update icon, ect. reconstructing it will also retain the upgrade. assembly.malf_xray_firmware_present = TRUE //so the upgrade is retained after incompatible parts are removed. @@ -128,6 +132,8 @@ /obj/machinery/camera/proc/upgradeMotion() if(isMotion()) return + var/obj/structure/camera_assembly/assembly = assembly_ref?.resolve() + if(name == initial(name)) name = "motion-sensitive security camera" if(!assembly.proxy_module) diff --git a/code/game/machinery/computer/atmos_control.dm b/code/game/machinery/computer/atmos_control.dm index 492c9807464..e970c28a236 100644 --- a/code/game/machinery/computer/atmos_control.dm +++ b/code/game/machinery/computer/atmos_control.dm @@ -417,7 +417,16 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers) /obj/machinery/computer/atmos_control/tank/proc/reconnect(mob/user) var/list/IO = list() var/datum/radio_frequency/freq = SSradio.return_frequency(frequency) - var/list/devices = freq.devices["_default"] + + var/list/devices = list() + var/list/device_refs = freq.devices["_default"] + for(var/datum/weakref/device_ref as anything in device_refs) + var/atom/device = device_ref.resolve() + if(!device) + device_refs -= device_ref + continue + devices += device + for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in devices) var/list/text = splittext(U.id_tag, "_") IO |= text[1] diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm index 7d7c23db397..b654cc1a710 100644 --- a/code/game/machinery/computer/crew.dm +++ b/code/game/machinery/computer/crew.dm @@ -172,11 +172,11 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new) ui.open() /datum/crewmonitor/proc/show(mob/M, source) - ui_sources[M] = source + ui_sources[WEAKREF(M)] = source ui_interact(M) /datum/crewmonitor/ui_host(mob/user) - return ui_sources[user] + return ui_sources[WEAKREF(user)] /datum/crewmonitor/ui_data(mob/user) var/z = user.z diff --git a/code/game/machinery/computer/teleporter.dm b/code/game/machinery/computer/teleporter.dm index e679ef3fde6..4579f1dcbd3 100644 --- a/code/game/machinery/computer/teleporter.dm +++ b/code/game/machinery/computer/teleporter.dm @@ -10,7 +10,8 @@ var/id var/obj/machinery/teleport/station/power_station var/calibrating - var/turf/target + ///Weakref to the target atom we're pointed at currently + var/datum/weakref/target_ref /obj/machinery/computer/teleporter/Initialize() . = ..() @@ -45,6 +46,11 @@ ui.open() /obj/machinery/computer/teleporter/ui_data(mob/user) + var/atom/target + if(target_ref) + target = target_ref.resolve() + if(!target) + target_ref = null var/list/data = list() data["power_station"] = power_station ? TRUE : FALSE data["teleporter_hub"] = power_station?.teleporter_hub ? TRUE : FALSE @@ -85,7 +91,7 @@ set_target(usr) . = TRUE if("calibrate") - if(!target) + if(!target_ref) say("Error: No target set to calibrate to.") return if(power_station.teleporter_hub.calibrated || power_station.teleporter_hub.accuracy >= 3) @@ -96,13 +102,14 @@ calibrating = TRUE power_station.update_appearance() addtimer(CALLBACK(src, .proc/finish_calibration), 50 * (3 - power_station.teleporter_hub.accuracy)) //Better parts mean faster calibration - . = TRUE + return TRUE /obj/machinery/computer/teleporter/proc/set_teleport_target(new_target) - if (target == new_target) + var/datum/weakref/new_target_ref = WEAKREF(new_target) + if (target_ref == new_target_ref) return SEND_SIGNAL(src, COMSIG_TELEPORTER_NEW_TARGET, new_target) - target = new_target + target_ref = new_target_ref /obj/machinery/computer/teleporter/proc/finish_calibration() calibrating = FALSE @@ -152,8 +159,8 @@ var/desc = input("Please select a location to lock in.", "Locking Computer") as null|anything in sortList(L) set_teleport_target(L[desc]) - var/turf/T = get_turf(target) - log_game("[key_name(user)] has set the teleporter target to [target] at [AREACOORD(T)]") + var/turf/T = get_turf(L[desc]) + log_game("[key_name(user)] has set the teleporter target to [L[desc]] at [AREACOORD(T)]") else var/list/S = power_station.linked_stations diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 44507d4d70a..2e17fbd3dec 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -137,7 +137,8 @@ GLOBAL_LIST_EMPTY(cryopod_computers) /// Cooldown for when it's now safe to try an despawn the player. COOLDOWN_DECLARE(despawn_world_time) - var/obj/machinery/computer/cryopod/control_computer + ///Weakref to our controller + var/datum/weakref/control_computer_weakref COOLDOWN_DECLARE(last_no_computer_message) /obj/machinery/cryopod/Initialize() @@ -150,27 +151,27 @@ GLOBAL_LIST_EMPTY(cryopod_computers) // This is not a good situation /obj/machinery/cryopod/Destroy() - control_computer = null + control_computer_weakref = null return ..() /obj/machinery/cryopod/proc/find_control_computer(urgent = FALSE) for(var/cryo_console as anything in GLOB.cryopod_computers) var/obj/machinery/computer/cryopod/console = cryo_console if(get_area(console) == get_area(src)) - control_computer = console + control_computer_weakref = WEAKREF(console) break // Don't send messages unless we *need* the computer, and less than five minutes have passed since last time we messaged - if(!control_computer && urgent && COOLDOWN_FINISHED(src, last_no_computer_message)) + if(!control_computer_weakref && urgent && COOLDOWN_FINISHED(src, last_no_computer_message)) COOLDOWN_START(src, last_no_computer_message, 5 MINUTES) log_admin("Cryopod in [get_area(src)] could not find control computer!") message_admins("Cryopod in [get_area(src)] could not find control computer!") last_no_computer_message = world.time - return control_computer != null + return control_computer_weakref != null /obj/machinery/cryopod/close_machine(atom/movable/target) - if(!control_computer) + if(!control_computer_weakref) find_control_computer(TRUE) if((isnull(target) || isliving(target)) && state_open && !panel_open) ..(target) @@ -204,7 +205,7 @@ GLOBAL_LIST_EMPTY(cryopod_computers) open_machine() if(!mob_occupant.client && COOLDOWN_FINISHED(src, despawn_world_time)) - if(!control_computer) + if(!control_computer_weakref) find_control_computer(urgent = TRUE) despawn_occupant() @@ -298,7 +299,11 @@ GLOBAL_LIST_EMPTY(cryopod_computers) announce_rank = general_record.fields["rank"] qdel(general_record) - control_computer?.frozen_crew += list(crew_member) + var/obj/machinery/computer/cryopod/control_computer = control_computer_weakref?.resolve() + if(!control_computer) + control_computer_weakref = null + else + control_computer.frozen_crew += list(crew_member) // Make an announcement and log the person entering storage. if(GLOB.announcement_systems.len) @@ -323,13 +328,6 @@ GLOBAL_LIST_EMPTY(cryopod_computers) else mob_occupant.transferItemToLoc(item_content, drop_location(), force = TRUE, silent = TRUE) // Skyrat Edit End - // Ghost and delete the mob. - if(!mob_occupant.get_ghost(TRUE)) - if(world.time < 15 MINUTES) // before the 15 minute mark - mob_occupant.ghostize(FALSE) // Players despawned too early may not re-enter the game - else - mob_occupant.ghostize(TRUE) - handle_objectives() QDEL_NULL(occupant) open_machine() diff --git a/code/game/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm index fb1df3b0acc..0e07c5d3052 100644 --- a/code/game/machinery/doors/brigdoors.dm +++ b/code/game/machinery/doors/brigdoors.dm @@ -32,7 +32,13 @@ var/timer_duration = 0 var/timing = FALSE // boolean, true/1 timer is on, false/0 means it's not timing - var/list/obj/machinery/targets = list() + ///List of weakrefs to nearby doors + var/list/doors = list() + ///List of weakrefs to nearby flashers + var/list/flashers = list() + ///List of weakrefs to nearby closets + var/list/closets = list() + var/obj/item/radio/Radio //needed to send messages to sec radio maptext_height = 26 @@ -50,17 +56,17 @@ if(id != null) for(var/obj/machinery/door/window/brigdoor/M in urange(20, src)) if (M.id == id) - targets += M + doors += WEAKREF(M) for(var/obj/machinery/flasher/F in urange(20, src)) if(F.id == id) - targets += F + flashers += WEAKREF(F) for(var/obj/structure/closet/secure_closet/brig/C in urange(20, src)) if(C.id == id) - targets += C + closets += WEAKREF(C) - if(!targets.len) + if(!length(doors) && !length(flashers) && length(closets)) obj_break() update_appearance() @@ -88,18 +94,26 @@ activation_time = world.realtime //SKYRAT EDIT CHANGE timing = TRUE - for(var/obj/machinery/door/window/brigdoor/door in targets) + for(var/datum/weakref/door_ref as anything in doors) + var/obj/machinery/door/window/brigdoor/door = door_ref.resolve() + if(!door) + doors -= door_ref + continue if(door.density) continue INVOKE_ASYNC(door, /obj/machinery/door/window/brigdoor.proc/close) - for(var/obj/structure/closet/secure_closet/brig/C in targets) - if(C.broken) + for(var/datum/weakref/closet_ref as anything in closets) + var/obj/structure/closet/secure_closet/brig/closet = closet_ref.resolve() + if(!closet) + closets -= closet_ref continue - if(C.opened && !C.close()) + if(closet.broken) continue - C.locked = TRUE - C.update_appearance() + if(closet.opened && !closet.close()) + continue + closet.locked = TRUE + closet.update_appearance() return 1 @@ -117,18 +131,26 @@ set_timer(0) update_appearance() - for(var/obj/machinery/door/window/brigdoor/door in targets) + for(var/datum/weakref/door_ref as anything in doors) + var/obj/machinery/door/window/brigdoor/door = door_ref.resolve() + if(!door) + doors -= door_ref + continue if(!door.density) continue INVOKE_ASYNC(door, /obj/machinery/door/window/brigdoor.proc/open) - for(var/obj/structure/closet/secure_closet/brig/C in targets) - if(C.broken) + for(var/datum/weakref/closet_ref as anything in closets) + var/obj/structure/closet/secure_closet/brig/closet = closet_ref.resolve() + if(!closet) + closets -= closet_ref continue - if(C.opened) + if(closet.broken) continue - C.locked = FALSE - C.update_appearance() + if(closet.opened) + continue + closet.locked = FALSE + closet.update_appearance() return 1 @@ -200,8 +222,12 @@ data["minutes"] = round((time_left - data["seconds"]) / 60) data["timing"] = timing data["flash_charging"] = FALSE - for(var/obj/machinery/flasher/F in targets) - if(F.last_flash && (F.last_flash + 15 SECONDS) > world.time) + for(var/datum/weakref/flash_ref as anything in flashers) + var/obj/machinery/flasher/flasher = flash_ref.resolve() + if(!flasher) + flashers -= flash_ref + continue + if(flasher.last_flash && (flasher.last_flash + 15 SECONDS) > world.time) data["flash_charging"] = TRUE break return data @@ -238,8 +264,12 @@ if("flash") investigate_log("[key_name(usr)] has flashed cell [id]", INVESTIGATE_RECORDS) user.log_message("[key_name(usr)] has flashed cell [id]", LOG_ATTACK) - for(var/obj/machinery/flasher/F in targets) - F.flash() + for(var/datum/weakref/flash_ref as anything in flashers) + var/obj/machinery/flasher/flasher = flash_ref.resolve() + if(!flasher) + flashers -= flash_ref + continue + flasher.flash() if("preset") var/preset = params["preset"] var/preset_time = time_left() diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index c0e34d39738..966459a9d96 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -726,6 +726,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ Impersonation = null if(!QDELETED(HC)) HC.Disconnect(HC.calling_holopad) + HC = null return ..() /obj/effect/overlay/holo_pad_hologram/Process_Spacemove(movement_dir = 0) diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm index a40d0beb844..672ed0e2501 100644 --- a/code/game/machinery/teleporter.dm +++ b/code/game/machinery/teleporter.dm @@ -68,12 +68,15 @@ var/obj/machinery/computer/teleporter/com = power_station.teleporter_console if (QDELETED(com)) return - if (QDELETED(com.target)) - com.target = null + var/atom/target + if(com.target_ref) + target = com.target_ref.resolve() + if (!target) + com.target_ref = null visible_message(span_alert("Cannot authenticate locked on coordinates. Please reinstate coordinate matrix.")) return if (ismovable(M)) - if(do_teleport(M, com.target, channel = TELEPORT_CHANNEL_BLUESPACE)) + if(do_teleport(M, target, channel = TELEPORT_CHANNEL_BLUESPACE)) use_power(5000) if(!calibrated && prob(30 - ((accuracy) * 10))) //oh dear a problem if(ishuman(M))//don't remove people from the round randomly you jerks @@ -214,7 +217,7 @@ /obj/machinery/teleport/station/proc/toggle(mob/user) if(machine_stat & (BROKEN|NOPOWER) || !teleporter_hub || !teleporter_console ) return - if (teleporter_console.target) + if (teleporter_console.target_ref?.resolve()) if(teleporter_hub.panel_open || teleporter_hub.machine_stat & (BROKEN|NOPOWER)) to_chat(user, span_alert("The teleporter hub isn't responding.")) else @@ -222,6 +225,7 @@ use_power(5000) to_chat(user, span_notice("Teleporter [engaged ? "" : "dis"]engaged!")) else + teleporter_console.target_ref = null to_chat(user, span_alert("No target detected.")) engaged = FALSE teleporter_hub.update_appearance() diff --git a/code/game/objects/items/devices/camera_bug.dm b/code/game/objects/items/devices/camera_bug.dm index 5db602dffb1..2e66a70c102 100644 --- a/code/game/objects/items/devices/camera_bug.dm +++ b/code/game/objects/items/devices/camera_bug.dm @@ -39,7 +39,8 @@ STOP_PROCESSING(SSobj, src) get_cameras() for(var/cam_tag in bugged_cameras) - var/obj/machinery/camera/camera = bugged_cameras[cam_tag] + var/datum/weakref/camera_ref = bugged_cameras[cam_tag] + var/obj/machinery/camera/camera = camera_ref.resolve() if(camera && camera.bug == src) camera.bug = null bugged_cameras = list() @@ -81,8 +82,11 @@ for(var/obj/machinery/camera/camera in GLOB.cameranet.cameras) if(camera.machine_stat || !camera.can_use()) continue - if(length(list("ss13","mine", "rd", "labor", "toxins", "minisat")&camera.network)) - bugged_cameras[camera.c_tag] = camera + if(length(list("ss13","mine", "rd", "labor", "toxins", "minisat") & camera.network)) + var/datum/weakref/camera_ref = WEAKREF(camera) + if(!camera_ref || !camera.c_tag) + continue + bugged_cameras[camera.c_tag] = camera_ref return sortList(bugged_cameras) @@ -95,15 +99,17 @@ if(BUGMODE_LIST) html = "
| [entry] | [functions] |
| [entry] | [functions] |