mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-17 12:35:26 +00:00
Move all atom/Destroy() behavior to atom/movable/Destroy() so turf/areas that get qdel()'d just get del()'d like they're supposed to. Also do tag = null, which should make more things GC. Make cameras GC correctly and some misc grammar fixes. Make smoke grenades GC. Tell camera bugs to del() because I'm not working on complex behavior for one item.
370 lines
11 KiB
Plaintext
370 lines
11 KiB
Plaintext
#define VANILLA_BUG 0
|
|
#define UNIVERSAL_BUG 1
|
|
#define NETWORK_BUG 2
|
|
#define SABOTAGE_BUG 3
|
|
#define ADVANCED_BUG 4
|
|
#define ADMIN_BUG 5
|
|
|
|
#define BUGMODE_LIST 0
|
|
#define BUGMODE_MONITOR 1
|
|
#define BUGMODE_TRACK 2
|
|
|
|
|
|
|
|
/obj/item/device/camera_bug
|
|
name = "camera bug"
|
|
desc = "For illicit snooping through the camera network."
|
|
icon = 'icons/obj/device.dmi'
|
|
icon_state = "camera_bug"
|
|
w_class = 1.0
|
|
item_state = "camera_bug"
|
|
throw_speed = 4
|
|
throw_range = 20
|
|
|
|
var/obj/machinery/camera/current = null
|
|
var/obj/item/expansion = null
|
|
var/bugtype = VANILLA_BUG
|
|
|
|
var/last_net_update = 0
|
|
var/last_bugtype = VANILLA_BUG
|
|
var/list/bugged_cameras = list()
|
|
var/skip_bugcheck = 0
|
|
|
|
var/track_mode = BUGMODE_LIST
|
|
var/last_tracked = 0
|
|
var/refresh_interval = 50
|
|
|
|
var/tracked_name = null
|
|
var/atom/tracking = null
|
|
|
|
var/last_found = null
|
|
var/last_seen = null
|
|
|
|
/obj/item/device/camera_bug/New()
|
|
..()
|
|
processing_objects += src
|
|
|
|
/obj/item/device/camera_bug/Destroy()
|
|
if(expansion)
|
|
qdel(expansion)
|
|
expansion = null
|
|
del(src)
|
|
/* Easier to just call del() than this nonsense
|
|
get_cameras()
|
|
for(var/cam_tag in bugged_cameras)
|
|
var/obj/machinery/camera/camera = bugged_cameras[cam_tag]
|
|
if(camera.bug == src)
|
|
camera.bug = null
|
|
bugged_cameras = list()
|
|
if(tracking)
|
|
tracking = null
|
|
..()
|
|
*/
|
|
|
|
/obj/item/device/camera_bug/interact(var/mob/user = usr)
|
|
var/datum/browser/popup = new(user, "camerabug","Camera Bug",nref=src)
|
|
popup.set_content(menu(get_cameras()))
|
|
popup.open()
|
|
|
|
/obj/item/device/camera_bug/attack_self(mob/user as mob)
|
|
user.set_machine(src)
|
|
interact(user)
|
|
|
|
/obj/item/device/camera_bug/check_eye(var/mob/user as mob)
|
|
if (user.stat || loc != user || !user.canmove || user.blinded || !current)
|
|
user.reset_view(null)
|
|
user.unset_machine()
|
|
return null
|
|
|
|
var/turf/T = get_turf(user.loc)
|
|
if(T.z != current.z || (!skip_bugcheck && current.bug != src) || !current.can_use())
|
|
user << "\red [src] has lost the signal."
|
|
current = null
|
|
user.reset_view(null)
|
|
user.unset_machine()
|
|
return null
|
|
|
|
return 1
|
|
|
|
/obj/item/device/camera_bug/proc/get_cameras()
|
|
if(bugtype != last_bugtype || ( (bugtype in list(UNIVERSAL_BUG,NETWORK_BUG,ADMIN_BUG)) && world.time > (last_net_update + 100)))
|
|
bugged_cameras = list()
|
|
last_bugtype = bugtype
|
|
for(var/obj/machinery/camera/camera in cameranet.cameras)
|
|
if(camera.stat || !camera.can_use())
|
|
continue
|
|
switch(bugtype)
|
|
if(VANILLA_BUG,SABOTAGE_BUG,ADVANCED_BUG)
|
|
if(camera.bug == src)
|
|
bugged_cameras[camera.c_tag] = camera
|
|
if(UNIVERSAL_BUG)
|
|
if(camera.bug)
|
|
bugged_cameras[camera.c_tag] = camera
|
|
if(NETWORK_BUG,ADMIN_BUG)
|
|
if(length(list("SS13","MINE")&camera.network))
|
|
bugged_cameras[camera.c_tag] = camera
|
|
bugged_cameras = sortAssoc(bugged_cameras)
|
|
return bugged_cameras
|
|
|
|
|
|
/obj/item/device/camera_bug/proc/menu(var/list/cameras)
|
|
if(!cameras || !cameras.len)
|
|
return "No bugged cameras found."
|
|
|
|
var/html
|
|
switch(track_mode)
|
|
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]
|
|
var/functions = ""
|
|
switch(bugtype)
|
|
if(SABOTAGE_BUG)
|
|
functions = " - <a href='?src=\ref[src];emp=\ref[C]'>\[Disable\]</a>"
|
|
if(ADVANCED_BUG)
|
|
functions = " - <a href='?src=\ref[src];monitor=\ref[C]'>\[Monitor\]</a>"
|
|
if(ADMIN_BUG)
|
|
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>"
|
|
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>"
|
|
|
|
if(BUGMODE_MONITOR)
|
|
if(current)
|
|
html = "Analyzing Camera '[current.c_tag]' <a href='?\ref[src];mode=0'>\[Select Camera\]</a><br>"
|
|
html += camera_report()
|
|
else
|
|
track_mode = BUGMODE_LIST
|
|
return .(cameras)
|
|
if(BUGMODE_TRACK)
|
|
if(tracking)
|
|
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/outstring
|
|
if(C)
|
|
outstring = "<a href='?\ref[src];view=\ref[C]'>[last_found]</a>"
|
|
else
|
|
outstring = last_found
|
|
if(!time_diff)
|
|
html += "Last seen near [outstring] (now)<br>"
|
|
else
|
|
// 15 second intervals ~ 1/4 minute
|
|
var/m = round(time_diff/4)
|
|
var/s = (time_diff - 4*m) * 15
|
|
if(!s) s = "00"
|
|
html += "Last seen near [outstring] ([m]:[s] minute\s ago)<br>"
|
|
else
|
|
html += "Not yet seen."
|
|
else
|
|
track_mode = BUGMODE_LIST
|
|
return .(cameras)
|
|
return html
|
|
|
|
/obj/item/device/camera_bug/proc/camera_report()
|
|
// this should only be called if current exists
|
|
var/dat = ""
|
|
if(current && current.can_use())
|
|
var/list/seen = current.can_see()
|
|
var/list/names = list()
|
|
for(var/obj/machinery/singularity/S in seen) // god help you if you see more than one
|
|
if(S.name in names)
|
|
names[S.name]++
|
|
dat += "[S.name] ([names[S.name]])"
|
|
else
|
|
names[S.name] = 1
|
|
dat += "[S.name]"
|
|
var/stage = round(S.current_size / 2)+1
|
|
dat += " (Stage [stage])"
|
|
dat += " <a href='?\ref[src];track=\ref[S]'>\[Track\]</a><br>"
|
|
|
|
for(var/obj/mecha/M in seen)
|
|
if(M.name in names)
|
|
names[M.name]++
|
|
dat += "[M.name] ([names[M.name]])"
|
|
else
|
|
names[M.name] = 1
|
|
dat += "[M.name]"
|
|
dat += " <a href='?\ref[src];track=\ref[M]'>\[Track\]</a><br>"
|
|
|
|
|
|
for(var/mob/living/M in seen)
|
|
if(M.name in names)
|
|
names[M.name]++
|
|
dat += "[M.name] ([names[M.name]])"
|
|
else
|
|
names[M.name] = 1
|
|
dat += "[M.name]"
|
|
if(M.buckled && !M.lying)
|
|
dat += " (Sitting)"
|
|
if(M.lying)
|
|
dat += " (Laying down)"
|
|
dat += " <a href='?\ref[src];track=\ref[M]'>\[Track\]</a><br>"
|
|
if(length(dat) == 0)
|
|
dat += "No motion detected."
|
|
return dat
|
|
else
|
|
return "Camera Offline<br>"
|
|
|
|
/obj/item/device/camera_bug/Topic(var/href,var/list/href_list)
|
|
if(usr != loc)
|
|
usr.unset_machine()
|
|
usr.reset_view(null)
|
|
usr << browse(null, "window=camerabug")
|
|
return
|
|
usr.set_machine(src)
|
|
if("mode" in href_list)
|
|
track_mode = text2num(href_list["mode"])
|
|
if("monitor" in href_list)
|
|
var/obj/machinery/camera/C = locate(href_list["monitor"])
|
|
if(C)
|
|
track_mode = BUGMODE_MONITOR
|
|
current = C
|
|
usr.reset_view(null)
|
|
interact()
|
|
if("track" in href_list)
|
|
var/atom/A = locate(href_list["track"])
|
|
if(A)
|
|
tracking = A
|
|
tracked_name = A.name
|
|
last_found = current.c_tag
|
|
last_seen = world.time
|
|
track_mode = BUGMODE_TRACK
|
|
if("emp" in href_list)
|
|
var/obj/machinery/camera/C = locate(href_list["emp"])
|
|
if(istype(C) && C.bug == src)
|
|
C.emp_act(1)
|
|
C.bug = null
|
|
bugged_cameras -= C.c_tag
|
|
interact()
|
|
return
|
|
if("close" in href_list)
|
|
usr.reset_view(null)
|
|
usr.unset_machine()
|
|
current = null
|
|
return // I do not <- I do not remember what I was going to write in this comment -Sayu, sometime later
|
|
if("view" in href_list)
|
|
var/obj/machinery/camera/C = locate(href_list["view"])
|
|
if(istype(C))
|
|
if(!C.can_use())
|
|
usr << "\red Something's wrong with that camera. You can't get a feed."
|
|
return
|
|
var/turf/T = get_turf(loc)
|
|
if(!T || C.z != T.z)
|
|
usr << "\red You can't get a signal."
|
|
return
|
|
current = C
|
|
spawn(6)
|
|
if(src.check_eye(usr))
|
|
usr.reset_view(C)
|
|
interact()
|
|
else
|
|
usr.unset_machine()
|
|
usr.reset_view(null)
|
|
usr << browse(null, "window=camerabug")
|
|
return
|
|
else
|
|
usr.unset_machine()
|
|
usr.reset_view(null)
|
|
|
|
interact()
|
|
|
|
/obj/item/device/camera_bug/process()
|
|
if(track_mode == BUGMODE_LIST || (world.time < (last_tracked + refresh_interval)))
|
|
return
|
|
last_tracked = world.time
|
|
if(track_mode == BUGMODE_TRACK ) // search for user
|
|
// Note that it will be tricked if your name appears to change.
|
|
// This is not optimal but it is better than tracking you relentlessly despite everything.
|
|
if(!tracking)
|
|
src.updateSelfDialog()
|
|
return
|
|
|
|
if(tracking.name != tracked_name) // Hiding their identity, tricksy
|
|
var/mob/M = tracking
|
|
if(istype(M))
|
|
if(!(tracked_name == "Unknown" && findtext(tracking.name,"Unknown"))) // we saw then disguised before
|
|
if(!(tracked_name == M.real_name && findtext(tracking.name,M.real_name))) // or they're still ID'd
|
|
src.updateSelfDialog()//But if it's neither of those cases
|
|
return // you won't find em on the cameras
|
|
else
|
|
src.updateSelfDialog()
|
|
return
|
|
|
|
var/list/tracking_cams = list()
|
|
var/list/b_cams = get_cameras()
|
|
for(var/entry in b_cams)
|
|
tracking_cams += b_cams[entry]
|
|
var/list/target_region = view(tracking)
|
|
|
|
for(var/obj/machinery/camera/C in (target_region & tracking_cams))
|
|
if(!can_see(C,tracking)) // target may have xray, that doesn't make them visible to cameras
|
|
continue
|
|
if(C.can_use())
|
|
last_found = C.c_tag
|
|
last_seen = world.time
|
|
break
|
|
src.updateSelfDialog()
|
|
|
|
/obj/item/device/camera_bug/attackby(var/obj/item/W as obj,var/mob/living/user as mob)
|
|
if(istype(W,/obj/item/weapon/screwdriver) && expansion)
|
|
expansion.loc = get_turf(loc)
|
|
user << "You unscrew [expansion]."
|
|
user.put_in_inactive_hand(expansion)
|
|
expansion = null
|
|
bugtype = VANILLA_BUG
|
|
skip_bugcheck = 0
|
|
track_mode = BUGMODE_LIST
|
|
tracking = null
|
|
return
|
|
|
|
if(expansion || !W)
|
|
return ..(W,user)
|
|
|
|
// I am not sure that this list is or should be final
|
|
// really I do not know what to do here.
|
|
var/static/list/expandables = list(
|
|
/obj/item/weapon/research = ADMIN_BUG, // could have been anything spawn-only
|
|
|
|
// these are all so hackish I am sorry
|
|
|
|
/obj/item/device/analyzer = UNIVERSAL_BUG,
|
|
/obj/item/weapon/stock_parts/subspace/analyzer = UNIVERSAL_BUG,
|
|
|
|
/obj/item/device/assembly/igniter = SABOTAGE_BUG,
|
|
/obj/item/device/assembly/infra = SABOTAGE_BUG, // ir blaster to disable camera
|
|
/obj/item/weapon/stock_parts/subspace/amplifier = SABOTAGE_BUG,
|
|
|
|
/obj/item/device/radio = NETWORK_BUG,
|
|
/obj/item/device/assembly/signaler = NETWORK_BUG,
|
|
/obj/item/weapon/stock_parts/subspace/transmitter = NETWORK_BUG,
|
|
|
|
/obj/item/device/detective_scanner = ADVANCED_BUG,
|
|
/obj/item/device/paicard = ADVANCED_BUG,
|
|
/obj/item/weapon/stock_parts/scanning_module = ADVANCED_BUG
|
|
)
|
|
|
|
for(var/entry in expandables)
|
|
if(istype(W,entry))
|
|
bugtype = expandables[entry]
|
|
user.drop_item()
|
|
W.loc = src
|
|
expansion = W
|
|
user << "You add [W] to [src]."
|
|
get_cameras() // the tracking code will want to know the new camera list
|
|
if(bugtype in list(UNIVERSAL_BUG,NETWORK_BUG,ADMIN_BUG))
|
|
skip_bugcheck = 1
|
|
return
|
|
|
|
#undef VANILLA_BUG
|
|
#undef UNIVERSAL_BUG
|
|
#undef NETWORK_BUG
|
|
#undef SABOTAGE_BUG
|
|
#undef ADVANCED_BUG
|
|
#undef ADMIN_BUG
|
|
|
|
#undef BUGMODE_LIST
|
|
#undef BUGMODE_MONITOR
|
|
#undef BUGMODE_TRACK |