mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-24 05:30:05 +01:00
[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:
co-authored by
LemonInTheDark
parent
0847eb3b35
commit
c1163dff19
@@ -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'
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
. = ..()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,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)
|
||||
..()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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!"))
|
||||
|
||||
@@ -86,9 +86,7 @@
|
||||
return
|
||||
|
||||
/obj/item/tank/Destroy()
|
||||
if(air_contents)
|
||||
QDEL_NULL(air_contents)
|
||||
|
||||
air_contents = null
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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!"))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -50,12 +50,16 @@
|
||||
output += " <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 += " [filter]: ERROR<br>"
|
||||
continue
|
||||
output += " [filter]: [f.len]<br>"
|
||||
for (var/device in f)
|
||||
output += " [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 += " [device] ([AREACOORD(A)])<br>"
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user