[MIRROR] EVEN MORE HARDDEL FIXES (#7017)

* EVEN MORE HARDDEL FIXES (#60228)

Fixes a ton of harddels, sourced from #59996
I think this brings us down to like, ~100 per round from ~200, with only like 20 of those being proper hell failures. I've seen harddel profiles below 1 second of total cost. Feeling good.

See you on the other side

Makes the cryopod control computer into a weakref, never trust bee code
Converts brig door timer internal lists to weakrefs
Fixes a harddel caused by qdeling a motion sensitive camera after it had left its source area, jesus christ why didn't we do this already holy shit
Converts the radio implant ref held by the antenna mutation to weakrefs because it isn't reliably cleaned up, makes the radio implant actually qdel its fucking radio
Removes the target var from the throwing datum, it does literally nothing and just exists to cause harddels, mostly for the singularity
 Fixes a cable harddel sourced from things that try to enter blueprints after smoothing, but before roundstart. IE, shuttles. Removes shuttles from the blueprints
Fixes emmisive blockers being added post qdel
Removes some manual ghosting from cryopods, I initially did this for harddel reasons, but I figured out a better fix for that. I'm now doing it because it's got this really strange logic for like "re-entering the game" that doesn't actually link to what the ghostize proc does. We should remove this at some point
Fixes robot hud objects harddeling due to hanging refs
Fixes buildmode related hanging refs, I'm coming for you admin team
Fixes a few instances of trying to add the forensics component post qdel, hhhhhhhhhhh
Fixes some split personality harddels/weirdness
Replaces a use of disconnect_duct with an init qdel hint, I suspect there's more issues with duct harddels, I've seen some odd logs about ahhh the area_contents list, but we can worry about that later
Makes teleporter targets into weakrefs, properly types them as /atom
Makes frequency devices into weakrefs
Makes cameras remove themselves from camera nets on Destroy
Makes tgui ui datums implement destroy, this means if I ever see one hang a ref to user or whatever, I know there's an error with calling close() properly. I've seen this harddel once, but not after this change so I assume there was some error with close(). IDK maybe this is a papering over? Would have to ask @ stylemistake
I've seen logs of beartraps being in world post del, putting a return there just in case. The same is true of nerf darts, but I haven't really looked into that yet
Makes a shoe's ref to untying alerts a weakref, yes this is needed.
Moves clearing client_in_contents to the Login of the new mob. This prevents doing things like ghosting someone before a mob qdel causing harddels
Fixes a harddel set sourced from adding a status effect to a qdeleted thing. Is this an error? I'm honestly not sure.
Converts bsa code to weakrefs
Converts the partner var of heat exchangers to weakrefs
Converts camera assemblies to weakrefs
Fixes some dumb behavior with ammo casings and assuming you'll be on a turf post Destroy parent call
Fixes? merger related harddels, you were never cleared from your own members list, so origin objects would end up making a new list, creating harddels. Potential input from @ ninjanomnom about the logic
Chasms store a static list of "falling atoms", which only exists for chasms that go somewhere else. This list wasn't being cleared of qdeleted objects, which is what happens when you fall in most chasms. Fixes this, and converts the list to weakrefs.
Fixes some runtimes in both sheet code, and the weather listener element. This is here because runtime spam made testing more of a pain, didn't think it needed its own pr
Fixes colorful reagent harddels sourced from reagents that were qdel'd before roundstart. I'm only like 50% sure this actually got it, but the issue may have been solved by #60174, so eh
Turns the nuke op antag datum's ref to the war button into a weakref
Fixes some holopad code that was not nulling refs all the time
Converts camera bugs to weakrefs, this was the result of the bug being "reworked" like 6 years back without taking the existing ref clearing into account. Whole item needs a redo, but this'll do for now.
Ensures that the both pulling and pullee refs are cleared on Destroy
The crew monitor held all users in a non clearing list, makes that list a weakref because I hate everything

Oh and I removed all sources of gas_mixture qdeletion, I'm kinda unsure on this since it's not technically supported, but any harddels from it might? indicate something going wrong with like, gas passing logic. I'd like @ MrStonedOne's thoughts, since I trust him to call me an idiot if I'm wrong.

<!-- Please add a short description of why you think these changes would benefit the game. If you can't justify it in words, it might not be worth adding. -->

## Why it's not good for the game

I crashed sybil like 10 times to get this data, I'm gonna put it to good use. Don't think you're safe sybilites, I'm coming for you.

* EVEN MORE HARDDEL FIXES

Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
This commit is contained in:
SkyratBot
2021-07-20 12:59:41 +02:00
committed by GitHub
co-authored by LemonInTheDark
parent 0847eb3b35
commit c1163dff19
53 changed files with 358 additions and 187 deletions
+10
View File
@@ -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'
+9 -3
View File
@@ -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))
+3 -2
View File
@@ -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
+1 -4
View File
@@ -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.
@@ -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
+11 -8
View File
@@ -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
+2 -2
View File
@@ -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)
. = ..()
+1
View File
@@ -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
+9 -4
View File
@@ -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)
+6 -3
View File
@@ -6,7 +6,7 @@
text_lose_indication = "<span class='notice'>Your antenna shrinks back down.</span>"
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)
..()
+3 -3
View File
@@ -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
-1
View File
@@ -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
+4 -2
View File
@@ -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)
+10 -5
View File
@@ -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
+15 -4
View File
@@ -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)
+2 -3
View File
@@ -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 ..()
+7 -1
View File
@@ -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)
+10 -1
View File
@@ -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]
+2 -2
View File
@@ -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
+14 -7
View File
@@ -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
+13 -15
View File
@@ -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()
+51 -21
View File
@@ -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()
+1
View File
@@ -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)
+8 -4
View File
@@ -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()
+40 -30
View File
@@ -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 = "<h3>Select a camera:</h3> <a href='?src=[REF(src)];view'>\[Cancel camera view\]</a><hr><table>"
for(var/entry in cameras)
var/obj/machinery/camera/C = cameras[entry]
if(QDELETED(C))
var/datum/weakref/camera_ref = cameras[entry]
var/obj/machinery/camera/camera = camera_ref.resolve()
if(!camera)
cameras -= camera_ref
continue
var/functions = ""
if(C.bug == src)
functions = " - <a href='?src=[REF(src)];monitor=[REF(C)]'>\[Monitor\]</a> <a href='?src=[REF(src)];emp=[REF(C)]'>\[Disable\]</a>"
if(camera.bug == src)
functions = " - <a href='?src=[REF(src)];monitor=[REF(camera_ref)]'>\[Monitor\]</a> <a href='?src=[REF(src)];emp=[REF(camera_ref)]'>\[Disable\]</a>"
else
functions = " - <a href='?src=[REF(src)];monitor=[REF(C)]'>\[Monitor\]</a>"
html += "<tr><td><a href='?src=[REF(src)];view=[REF(C)]'>[entry]</a></td><td>[functions]</td></tr>"
functions = " - <a href='?src=[REF(src)];monitor=[REF(camera_ref)]'>\[Monitor\]</a>"
html += "<tr><td><a href='?src=[REF(src)];view=[REF(camera_ref)]'>[entry]</a></td><td>[functions]</td></tr>"
if(BUGMODE_MONITOR)
if(current)
@@ -117,10 +123,11 @@
html = "Tracking '[tracked_name]' <a href='?[REF(src)];mode=0'>\[Cancel Tracking\]</a> <a href='?src=[REF(src)];view'>\[Cancel camera view\]</a><br>"
if(last_found)
var/time_diff = round((world.time - last_seen) / 150)
var/obj/machinery/camera/C = bugged_cameras[last_found]
var/datum/weakref/camera_ref = bugged_cameras[last_found]
var/obj/machinery/camera/camera = camera_ref.resolve()
var/outstring
if(C)
outstring = "<a href='?[REF(src)];view=[REF(C)]'>[last_found]</a>"
if(camera)
outstring = "<a href='?[REF(src)];view=[REF(camera_ref)]'>[last_found]</a>"
else
outstring = last_found
if(!time_diff)
@@ -132,8 +139,8 @@
if(!s)
s = "00"
html += "Last seen near [outstring] ([m]:[s] minute\s ago)<br>"
if( C && (C.bug == src)) //Checks to see if the camera has a bug
html += "<a href='?src=[REF(src)];emp=[REF(C)]'>\[Disable\]</a>"
if(camera && (camera.bug == src)) //Checks to see if the camera has a bug
html += "<a href='?src=[REF(src)];emp=[REF(camera_ref)]'>\[Disable\]</a>"
else
html += "Not yet seen."
@@ -204,12 +211,13 @@
if("monitor" in href_list)
//You can't locate on a list with keys
var/list/cameras = flatten_list(bugged_cameras)
var/obj/machinery/camera/C = locate(href_list["monitor"]) in cameras
if(C && istype(C))
if(!same_z_level(C))
var/datum/weakref/camera_ref = locate(href_list["monitor"]) in cameras
var/obj/machinery/camera/camera = camera_ref.resolve()
if(camera && istype(camera))
if(!same_z_level(camera))
return
track_mode = BUGMODE_MONITOR
current = C
current = camera
usr.reset_perspective(null)
interact()
if("track" in href_list)
@@ -225,13 +233,14 @@
if("emp" in href_list)
//You can't locate on a list with keys
var/list/cameras = flatten_list(bugged_cameras)
var/obj/machinery/camera/C = locate(href_list["emp"]) in cameras
if(C && istype(C) && C.bug == src)
if(!same_z_level(C))
var/datum/weakref/camera_ref = locate(href_list["emp"]) in cameras
var/obj/machinery/camera/camera = camera_ref.resolve()
if(camera && istype(camera) && camera.bug == src)
if(!same_z_level(camera))
return
C.emp_act(EMP_HEAVY)
C.bug = null
bugged_cameras -= C.c_tag
camera.emp_act(EMP_HEAVY)
camera.bug = null
bugged_cameras -= camera.c_tag
interact()
return
if("close" in href_list)
@@ -241,17 +250,18 @@
if("view" in href_list)
//You can't locate on a list with keys
var/list/cameras = flatten_list(bugged_cameras)
var/obj/machinery/camera/C = locate(href_list["view"]) in cameras
if(C && istype(C))
if(!same_z_level(C))
var/datum/weakref/camera_ref = locate(href_list["view"]) in cameras
var/obj/machinery/camera/camera = camera_ref.resolve()
if(camera && istype(camera))
if(!same_z_level(camera))
return
if(!C.can_use())
if(!camera.can_use())
to_chat(usr, span_warning("Something's wrong with that camera! You can't get a feed."))
return
current = C
current = camera
spawn(6)
if(src.check_eye(usr))
usr.reset_perspective(C)
usr.reset_perspective(camera)
interact()
else
usr.unset_machine()
+1
View File
@@ -479,6 +479,7 @@
var/obj/item/restraints/legcuffs/beartrap/B = new /obj/item/restraints/legcuffs/beartrap/energy/cyborg(get_turf(hit_atom))
B.spring_trap(null, hit_atom)
qdel(src)
return
. = ..()
/**
@@ -77,6 +77,10 @@
radio.keyslot = new radio_key
radio.recalculateChannels()
/obj/item/implant/radio/Destroy()
QDEL_NULL(radio)
return ..()
/obj/item/implant/radio/mining
radio_key = /obj/item/encryptionkey/headset_cargo
@@ -61,11 +61,12 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
var/obj/item/stack/rods/V = W
if (V.get_amount() >= 1 && get_amount() >= 1)
var/obj/item/stack/sheet/rglass/RG = new (get_turf(user))
RG.add_fingerprint(user)
if(!QDELETED(RG))
RG.add_fingerprint(user)
var/replace = user.get_inactive_held_item()==src
V.use(1)
use(1)
if(QDELETED(src) && replace)
if(QDELETED(src) && replace && !QDELETED(RG))
user.put_in_hands(RG)
else
to_chat(user, span_warning("You need one rod and one sheet of glass to make reinforced glass!"))
+1 -3
View File
@@ -86,9 +86,7 @@
return
/obj/item/tank/Destroy()
if(air_contents)
QDEL_NULL(air_contents)
air_contents = null
STOP_PROCESSING(SSobj, src)
return ..()
+15 -10
View File
@@ -172,15 +172,17 @@
//SKYRAT EDIT END
var/list/locations = list()
for(var/obj/machinery/computer/teleporter/computer in GLOB.machines)
if(!computer.target)
var/atom/target = computer.target_ref?.resolve()
if(!target)
computer.target_ref = null
continue
var/area/computer_area = get_area(computer.target)
var/area/computer_area = get_area(target)
if(!computer_area || (computer_area.area_flags & NOTELEPORT))
continue
if(computer.power_station?.teleporter_hub && computer.power_station.engaged)
locations["[get_area(computer.target)] (Active)"] = computer
locations["[get_area(target)] (Active)"] = computer
else
locations["[get_area(computer.target)] (Inactive)"] = computer
locations["[get_area(target)] (Inactive)"] = computer
locations["None (Dangerous)"] = PORTAL_LOCATION_DANGEROUS
@@ -212,7 +214,7 @@
user.show_message(span_notice("[src] is recharging!"))
return
var/teleport_turf
var/atom/teleport_target
if (teleport_location == PORTAL_LOCATION_DANGEROUS)
var/list/dangerous_turfs = list()
@@ -226,16 +228,19 @@
continue
dangerous_turfs += dangerous_turf
teleport_turf = pick(dangerous_turfs)
teleport_target = pick(dangerous_turfs)
else
var/obj/machinery/computer/teleporter/computer = teleport_location
teleport_turf = computer.target
var/atom/target = computer.target_ref?.resolve()
if(!target)
computer.target_ref = null
teleport_target = target
if (teleport_turf == null)
if (teleport_target == null)
to_chat(user, span_notice("[src] vibrates, then stops. Maybe you should try something else."))
return
var/area/teleport_area = get_area(teleport_turf)
var/area/teleport_area = get_area(teleport_target)
if (teleport_area.area_flags & NOTELEPORT)
to_chat(user, span_notice("[src] is malfunctioning."))
return
@@ -243,7 +248,7 @@
if (!can_teleport_notifies(user))
return
var/list/obj/effect/portal/created = create_portal_pair(get_turf(user), get_teleport_turf(get_turf(teleport_turf)), 300, 1, null, atmos_link_override)
var/list/obj/effect/portal/created = create_portal_pair(get_turf(user), get_teleport_turf(get_turf(teleport_target)), 300, 1, null, atmos_link_override)
if(LAZYLEN(created) != 2)
return
+1
View File
@@ -72,6 +72,7 @@
obj_flags &= ~string_to_objflag[flag]
else
obj_flags |= string_to_objflag[flag]
if((obj_flags & ON_BLUEPRINTS) && isturf(loc))
var/turf/T = loc
T.add_blueprints_preround(src)
+5
View File
@@ -43,6 +43,7 @@
var/obj/item/stack/sheet/iron/M = new (loc, 2)
M.add_fingerprint(user)
qdel(src)
return
else if(istype(W, /obj/item/stack))
if(iswallturf(loc))
@@ -70,6 +71,7 @@
var/obj/structure/falsewall/iron/FW = new (loc)
transfer_fingerprints_to(FW)
qdel(src)
return
else
if(S.get_amount() < 5)
to_chat(user, span_warning("You need at least five rods to add plating!"))
@@ -104,6 +106,7 @@
var/obj/structure/falsewall/F = new (loc)
transfer_fingerprints_to(F)
qdel(src)
return
else if(state == GIRDER_REINF)
to_chat(user, span_warning("You can't finish a reinforced girder with regular iron. You need a plasteel sheet for that."))
return
@@ -137,6 +140,7 @@
var/obj/structure/falsewall/reinforced/FW = new (loc)
transfer_fingerprints_to(FW)
qdel(src)
return
else if(state == GIRDER_REINF)
if(S.get_amount() < 1)
return
@@ -183,6 +187,7 @@
var/obj/structure/falsewall/FW = new falsewall_type (loc)
transfer_fingerprints_to(FW)
qdel(src)
return
else
if(S.get_amount() < 2)
to_chat(user, span_warning("You need at least two sheets to add plating!"))
-2
View File
@@ -190,11 +190,9 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
var/datum/excited_group/stashed_group = excited_group
. = ..() //If path == type this will return us, don't bank on making a new type
if (!.) // changeturf failed or didn't do anything
QDEL_NULL(stashed_air)
return
var/turf/open/newTurf = .
newTurf.air.copy_from(stashed_air)
QDEL_NULL(stashed_air)
newTurf.excited = stashed_state
newTurf.excited_group = stashed_group
#ifdef VISUALIZE_ACTIVE_TURFS
+1 -1
View File
@@ -524,7 +524,7 @@ GLOBAL_LIST_EMPTY(station_turfs)
LAZYADD(blueprint_data, I)
/turf/proc/add_blueprints_preround(atom/movable/AM)
if(!SSticker.HasRoundStarted())
if(!SSicon_smooth.initialized)
if(AM.layer == WIRE_LAYER) //wires connect to adjacent positions after its parent init, meaning we need to wait (in this case, until smoothing) to take its image
SSicon_smooth.blueprint_queue += AM
else
+8 -4
View File
@@ -50,12 +50,16 @@
output += "&nbsp;&nbsp;<b>ERROR</b><br>"
continue
for (var/filter in fqs.devices)
var/list/f = fqs.devices[filter]
if (!f)
var/list/filtered = fqs.devices[filter]
if (!filtered)
output += "&nbsp;&nbsp;[filter]: ERROR<br>"
continue
output += "&nbsp;&nbsp;[filter]: [f.len]<br>"
for (var/device in f)
output += "&nbsp;&nbsp;[filter]: [filtered.len]<br>"
for(var/datum/weakref/device_ref as anything in filtered)
var/atom/device = device_ref.resolve()
if(!device)
filtered -= device_ref
continue
if (istype(device, /atom))
var/atom/A = device
output += "&nbsp;&nbsp;&nbsp;&nbsp;[device] ([AREACOORD(A)])<br>"
+4 -3
View File
@@ -187,7 +187,7 @@
dukinuki.forceMove(H.drop_location())
else
H.put_in_hands(dukinuki, TRUE)
nuke_team.war_button = dukinuki
nuke_team.war_button_ref = WEAKREF(dukinuki)
owner.announce_objectives()
addtimer(CALLBACK(src, .proc/nuketeam_name_assign), 1)
@@ -251,7 +251,7 @@
var/core_objective = /datum/objective/nuclear
var/memorized_code
var/list/team_discounts
var/obj/item/nuclear_challenge/war_button
var/datum/weakref/war_button_ref
/datum/team/nuclear/New()
..()
@@ -394,7 +394,8 @@
disk_report += "</table>"
var/common_part = ..()
var/challenge_report
if(!QDELETED(war_button))
var/obj/item/nuclear_challenge/war_button = war_button_ref?.resolve()
if(war_button)
challenge_report += "<b>War not declared.</b> <a href='?_src_=holder;[HrefToken()];force_war=[REF(war_button)]'>\[Force war\]</a>"
return common_part + disk_report + challenge_report
@@ -788,7 +788,8 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module))
var/upgraded_cameras = 0
for(var/V in GLOB.cameranet.cameras)
var/obj/machinery/camera/C = V
if(C.assembly)
var/obj/structure/camera_assembly/assembly = C.assembly_ref?.resolve()
if(assembly)
var/upgraded = FALSE
if(!C.isXRay())
@@ -803,7 +804,6 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module))
if(upgraded)
upgraded_cameras++
unlock_text = replacetext(unlock_text, "CAMSUPGRADED", "<b>[upgraded_cameras]</b>") //This works, since unlock text is called after upgrade()
/// AI Turret Upgrade: Increases the health and damage of all turrets.
@@ -91,7 +91,7 @@
/obj/machinery/atmospherics/components/nullifyNode(i)
if(parents[i])
nullifyPipenet(parents[i])
QDEL_NULL(airs[i])
airs[i] = null
return ..()
/obj/machinery/atmospherics/components/on_construction()
@@ -10,7 +10,7 @@
layer = LOW_OBJ_LAYER
var/obj/machinery/atmospherics/components/unary/heat_exchanger/partner = null
var/datum/weakref/partner_ref = null
var/update_cycle
pipe_state = "heunary"
@@ -35,20 +35,26 @@
PIPING_LAYER_SHIFT(src, piping_layer)
/obj/machinery/atmospherics/components/unary/heat_exchanger/atmosinit()
var/obj/machinery/atmospherics/components/unary/heat_exchanger/partner = partner_ref?.resolve()
if(!partner)
partner_ref = null
var/partner_connect = turn(dir,180)
for(var/obj/machinery/atmospherics/components/unary/heat_exchanger/target in get_step(src,partner_connect))
if(target.dir & get_dir(src,target))
partner = target
partner.partner = src
partner_ref = WEAKREF(target)
target.partner_ref = WEAKREF(src)
break
..()
/obj/machinery/atmospherics/components/unary/heat_exchanger/process_atmos()
..()
if(!partner || SSair.times_fired <= update_cycle)
var/obj/machinery/atmospherics/components/unary/heat_exchanger/partner = partner_ref?.resolve()
if(!partner)
partner_ref = null
return
if(SSair.times_fired <= update_cycle)
return
update_cycle = SSair.times_fired
@@ -82,7 +82,6 @@
QDEL_NULL(parent)
releaseAirToTurf()
QDEL_NULL(air_temporary)
var/turf/T = loc
for(var/obj/machinery/meter/meter in T)
@@ -26,7 +26,7 @@
/obj/machinery/portable_atmospherics/Destroy()
disconnect()
QDEL_NULL(air_contents)
air_contents = null
SSair.stop_processing_machine(src)
return ..()
+2
View File
@@ -45,8 +45,10 @@
/datum/buildmode/Destroy()
close_switchstates()
holder.player_details.post_login_callbacks -= li_cb
li_cb = null
holder = null
QDEL_NULL(mode)
QDEL_LIST(buttons)
QDEL_LIST(modeswitch_buttons)
QDEL_LIST(dirswitch_buttons)
return ..()
+10 -7
View File
@@ -19,8 +19,8 @@
var/tied = SHOES_TIED
///How long it takes to lace/unlace these shoes
var/lace_time = 5 SECONDS
///any alerts we have active
var/atom/movable/screen/alert/our_alert
///An active alert
var/datum/weakref/our_alert_ref
/obj/item/clothing/shoes/suicide_act(mob/living/carbon/user)
if(rand(2)>1)
@@ -76,7 +76,7 @@
/obj/item/clothing/shoes/equipped(mob/user, slot)
. = ..()
if(can_be_tied && tied == SHOES_UNTIED)
our_alert = user.throw_alert("shoealert", /atom/movable/screen/alert/shoes/untied)
our_alert_ref = WEAKREF(user.throw_alert("shoealert", /atom/movable/screen/alert/shoes/untied))
RegisterSignal(src, COMSIG_SHOES_STEP_ACTION, .proc/check_trip, override=TRUE)
/obj/item/clothing/shoes/proc/restore_offsets(mob/user)
@@ -85,7 +85,10 @@
worn_y_dimension = world.icon_size
/obj/item/clothing/shoes/dropped(mob/user)
if(our_alert && our_alert.owner == user)
var/atom/movable/screen/alert/our_alert = our_alert_ref?.resolve()
if(!our_alert)
our_alert_ref = null
if(our_alert?.owner == user)
user.clear_alert("shoealert")
if(offset && equipped_before_drop)
restore_offsets(user)
@@ -125,7 +128,7 @@
UnregisterSignal(src, COMSIG_SHOES_STEP_ACTION)
else
if(tied == SHOES_UNTIED && our_guy && user == our_guy)
our_alert = our_guy.throw_alert("shoealert", /atom/movable/screen/alert/shoes/untied) // if we're the ones unknotting our own laces, of course we know they're untied
our_alert_ref = WEAKREF(our_guy.throw_alert("shoealert", /atom/movable/screen/alert/shoes/untied)) // if we're the ones unknotting our own laces, of course we know they're untied
RegisterSignal(src, COMSIG_SHOES_STEP_ACTION, .proc/check_trip, override=TRUE)
/**
@@ -216,7 +219,7 @@
our_guy.Knockdown(10)
our_guy.visible_message(span_danger("[our_guy] trips on [our_guy.p_their()] knotted shoelaces and falls! What a klutz!"), span_userdanger("You trip on your knotted shoelaces and fall over!"))
SEND_SIGNAL(our_guy, COMSIG_ADD_MOOD_EVENT, "trip", /datum/mood_event/tripped) // well we realized they're knotted now!
our_alert = our_guy.throw_alert("shoealert", /atom/movable/screen/alert/shoes/knotted)
our_alert_ref = WEAKREF(our_guy.throw_alert("shoealert", /atom/movable/screen/alert/shoes/knotted))
else if(tied == SHOES_UNTIED)
var/wiser = TRUE // did we stumble and realize our laces are undone?
@@ -248,7 +251,7 @@
wiser = FALSE
if(wiser)
SEND_SIGNAL(our_guy, COMSIG_ADD_MOOD_EVENT, "untied", /datum/mood_event/untied) // well we realized they're untied now!
our_alert = our_guy.throw_alert("shoealert", /atom/movable/screen/alert/shoes/untied)
our_alert_ref = WEAKREF(our_guy.throw_alert("shoealert", /atom/movable/screen/alert/shoes/untied))
/obj/item/clothing/shoes/attack_hand(mob/living/carbon/human/user, list/modifiers)
+3 -2
View File
@@ -77,8 +77,9 @@
var/obj/effect/decal/cleanable/blood/splatter/B = locate() in src
if(QDELETED(B)) // SKYRAT EDIT - SANITY CHECK; DONT ADD DNA TO A FUCKING DELETED BLOOD SPATTER - original: if(!B)
B = new /obj/effect/decal/cleanable/blood/splatter(src, diseases)
B.add_blood_DNA(blood_dna) //give blood info to the blood decal.
return TRUE //we bloodied the floor
if(!QDELETED(B))
B.add_blood_DNA(blood_dna) //give blood info to the blood decal.
return TRUE //we bloodied the floor
/mob/living/carbon/human/add_blood_DNA(list/blood_dna, list/datum/disease/diseases)
if(wear_suit)
+3
View File
@@ -48,6 +48,9 @@
if(!client)
return FALSE
//We do this here to prevent hanging refs from ghostize or whatever, since if we were in another mob before this'll take care of it
clear_client_in_contents()
SEND_SIGNAL(src, COMSIG_MOB_LOGIN)
if (key != client.key)
-1
View File
@@ -43,7 +43,6 @@
observe.reset_perspective(null)
qdel(hud_used)
QDEL_LIST(client_colours)
clear_client_in_contents() //Gotta do this here as well as Logout, since client will be null by the time it gets there, cause of that ghostize
ghostize() //False, since we're deleting it currently
if(mind?.current == src) //Let's just be safe yeah? This will occasionally be cleared, but not always. Can't do it with ghostize without changing behavior
mind.set_current(null)
+3 -2
View File
@@ -61,7 +61,7 @@ All the important duct code:
if(D == src)
continue
if(D.duct_layer & duct_layer)
disconnect_duct()
return INITIALIZE_HINT_QDEL //If we have company, end it all
attempt_connect()
AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE)
@@ -166,8 +166,9 @@ All the important duct code:
lose_neighbours()
reset_connects(0)
update_appearance()
if(ispath(drop_on_wrench) && !QDELING(src))
if(ispath(drop_on_wrench))
new drop_on_wrench(drop_location())
if(!QDELETED(src))
qdel(src)
///Special proc to draw a new connect frame based on neighbours. not the norm so we can support multiple duct kinds
@@ -51,12 +51,11 @@
update_appearance()
/obj/item/ammo_casing/Destroy()
. = ..()
var/turf/T = get_turf(src)
if(T && !loaded_projectile && is_station_level(T.z))
SSblackbox.record_feedback("tally", "station_mess_destroyed", 1, name)
QDEL_NULL(loaded_projectile)
return ..()
/obj/item/ammo_casing/add_weapon_description()
AddElement(/datum/element/weapon_description, attached_proc = .proc/add_notes_ammo)
@@ -33,9 +33,12 @@
. = ..()
var/obj/item/beacon/teletarget = null
for(var/obj/machinery/computer/teleporter/com in GLOB.machines)
if(com.target)
var/atom/target = com.target_ref.resolve()
if(target)
if(com.power_station && com.power_station.teleporter_hub && com.power_station.engaged)
teletarget = com.target
teletarget = target
else
com.target_ref = null
addtimer(CALLBACK(src, .proc/pop, teletarget), 30)
@@ -2066,12 +2066,20 @@
taste_description = "rainbows"
var/can_colour_mobs = TRUE
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
var/datum/callback/color_callback
/datum/reagent/colorful_reagent/New()
SSticker.OnRoundstart(CALLBACK(src,.proc/UpdateColor))
color_callback = CALLBACK(src, .proc/UpdateColor)
SSticker.OnRoundstart(color_callback)
return ..()
/datum/reagent/colorful_reagent/Destroy()
LAZYREMOVE(SSticker.round_end_events, color_callback) //Prevents harddels during roundstart
color_callback = null //Fly free little callback
return ..()
/datum/reagent/colorful_reagent/proc/UpdateColor()
color_callback = null
color = pick(random_color_list)
/datum/reagent/colorful_reagent/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
@@ -16,7 +16,6 @@
var/hasmob = FALSE // contains a mob
/obj/structure/disposalholder/Destroy()
QDEL_NULL(gas)
active = FALSE
return ..()
+21 -10
View File
@@ -65,8 +65,8 @@
name = "Bluespace Artillery Fusor"
desc = "Contents classified by Nanotrasen Naval Command. Needs to be linked with the other BSA parts using a multitool."
icon_state = "fuel_chamber"
var/obj/machinery/bsa/back/back
var/obj/machinery/bsa/front/front
var/datum/weakref/back_ref
var/datum/weakref/front_ref
/obj/machinery/bsa/middle/multitool_act(mob/living/user, obj/item/I)
if(!multitool_check_buffer(user, I))
@@ -74,18 +74,20 @@
var/obj/item/multitool/M = I
if(M.buffer)
if(istype(M.buffer, /obj/machinery/bsa/back))
back = M.buffer
back_ref = WEAKREF(M.buffer)
to_chat(user, span_notice("You link [src] with [M.buffer]."))
M.buffer = null
to_chat(user, span_notice("You link [src] with [back]."))
else if(istype(M.buffer, /obj/machinery/bsa/front))
front = M.buffer
front_ref = WEAKREF(M.buffer)
to_chat(user, span_notice("You link [src] with [M.buffer]."))
M.buffer = null
to_chat(user, span_notice("You link [src] with [front]."))
else
to_chat(user, span_warning("[I]'s data buffer is empty!"))
return TRUE
/obj/machinery/bsa/middle/proc/check_completion()
var/obj/machinery/bsa/front/front = front_ref?.resolve()
var/obj/machinery/bsa/back/back = back_ref?.resolve()
if(!front || !back)
return "No linked parts detected!"
if(!front.anchored || !back.anchored || !anchored)
@@ -113,6 +115,10 @@
return TRUE
/obj/machinery/bsa/middle/proc/get_cannon_direction()
var/obj/machinery/bsa/front/front = front_ref?.resolve()
var/obj/machinery/bsa/back/back = back_ref?.resolve()
if(!front || !back)
return
if(front.x > x && back.x < x)
return EAST
else if(front.x < x && back.x > x)
@@ -237,7 +243,7 @@
icon_state = "control_boxp"
icon_keyboard = ""
var/obj/machinery/bsa/full/cannon
var/datum/weakref/cannon_ref
var/notice
var/target
var/area_aim = FALSE //should also show areas for targeting
@@ -252,6 +258,7 @@
ui.open()
/obj/machinery/computer/bsa_control/ui_data()
var/obj/machinery/bsa/full/cannon = cannon_ref?.resolve()
var/list/data = list()
data["ready"] = cannon ? cannon.ready : FALSE
data["connected"] = cannon
@@ -268,7 +275,7 @@
switch(action)
if("build")
cannon = deploy()
cannon_ref = WEAKREF(deploy())
. = TRUE
if("fire")
fire(usr)
@@ -308,6 +315,10 @@
return get_turf(G.parent)
/obj/machinery/computer/bsa_control/proc/fire(mob/user)
var/obj/machinery/bsa/full/cannon = cannon_ref?.resolve()
if(!cannon)
notice = "No Cannon Exists!"
return
if(cannon.machine_stat)
notice = "Cannon unpowered!"
return
@@ -331,8 +342,8 @@
s.set_up(4,get_turf(centerpiece))
s.start()
var/obj/machinery/bsa/full/cannon = new(get_turf(centerpiece),centerpiece.get_cannon_direction())
qdel(centerpiece.front)
qdel(centerpiece.back)
QDEL_NULL(centerpiece.front_ref)
QDEL_NULL(centerpiece.back_ref)
qdel(centerpiece)
return cannon
*/
+5
View File
@@ -63,6 +63,11 @@
if(ui_x && ui_y)
src.window_size = list(ui_x, ui_y)
/datum/tgui/Destroy()
user = null
src_object = null
return ..()
/**
* public
*