diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index f04aba5a25..5b39bc618f 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -13,12 +13,13 @@ var/list/network = list() var/datum/tgui_module/camera/camera + var/camera_datum_type = /datum/tgui_module/camera /obj/machinery/computer/security/Initialize() . = ..() if(!LAZYLEN(network)) network = get_default_networks() - camera = new(src, network) + camera = new camera_datum_type(src, network) /obj/machinery/computer/security/proc/get_default_networks() . = using_map.station_networks.Copy() @@ -67,19 +68,41 @@ density = 0 circuit = null +GLOBAL_LIST_EMPTY(entertainment_screens) /obj/machinery/computer/security/telescreen/entertainment name = "entertainment monitor" desc = "Damn, why do they never have anything interesting on these things?" - icon = 'icons/obj/status_display.dmi' - icon_screen = "entertainment" + icon = 'icons/obj/entertainment_monitor.dmi' + icon_state = "screen" + icon_screen = null light_color = "#FFEEDB" light_range_on = 2 network = list(NETWORK_THUNDER) circuit = /obj/item/weapon/circuitboard/security/telescreen/entertainment + camera_datum_type = /datum/tgui_module/camera/bigscreen + var/obj/item/device/radio/radio = null + var/obj/effect/overlay/vis/pinboard + var/weakref/showing /obj/machinery/computer/security/telescreen/entertainment/Initialize() + GLOB.entertainment_screens += src + + var/static/icon/mask = icon('icons/obj/entertainment_monitor.dmi', "mask") + + add_overlay("glass") + + pinboard = new() + pinboard.icon = icon + pinboard.icon_state = "pinboard" + pinboard.layer = 0.1 + pinboard.vis_flags = VIS_UNDERLAY|VIS_INHERIT_ID|VIS_INHERIT_PLANE + pinboard.appearance_flags = KEEP_TOGETHER + pinboard.add_filter("screen cutter", 1, alpha_mask_filter(icon = mask)) + vis_contents += pinboard + . = ..() + radio = new(src) radio.listening = TRUE radio.broadcasting = FALSE @@ -87,13 +110,44 @@ radio.canhear_range = 7 // Same as default sight range. power_change() +/obj/machinery/computer/security/telescreen/entertainment/Destroy() + if(showing) + stop_showing() + vis_contents.Cut() + qdel_null(pinboard) + qdel_null(radio) + return ..() + +/obj/machinery/computer/security/telescreen/entertainment/Click(location, control, params) + attack_hand(usr) + +/obj/machinery/computer/security/telescreen/entertainment/update_icon() + return // NUH + +/obj/machinery/computer/security/telescreen/entertainment/proc/show_thing(atom/thing) + if(showing) + stop_showing() + if(stat & NOPOWER) + return + showing = weakref(thing) + pinboard.vis_contents = list(thing) + +/obj/machinery/computer/security/telescreen/entertainment/proc/stop_showing() + // Reverse of the above + pinboard.vis_contents = null + showing = null + +/obj/machinery/computer/security/telescreen/entertainment/proc/maybe_stop_showing(weakref/thingref) + if(showing == thingref) + stop_showing() + /obj/machinery/computer/security/telescreen/entertainment/power_change() ..() - if(radio) - if(stat & NOPOWER) - radio.on = FALSE - else - radio.on = TRUE + if(stat & NOPOWER) + radio?.on = FALSE + stop_showing() + else + radio?.on = TRUE /obj/machinery/computer/security/wooden_tv name = "security camera monitor" diff --git a/code/game/objects/items/devices/tvcamera.dm b/code/game/objects/items/devices/tvcamera.dm index acf4b7cc3a..b7d7933a88 100644 --- a/code/game/objects/items/devices/tvcamera.dm +++ b/code/game/objects/items/devices/tvcamera.dm @@ -8,6 +8,8 @@ var/channel = "NCS Northern Star News Feed" var/obj/machinery/camera/network/thunder/camera var/obj/item/device/radio/radio + var/weakref/showing + var/showing_name /obj/item/device/tvcamera/New() ..() @@ -45,9 +47,14 @@ /obj/item/device/tvcamera/attack_self(mob/user) add_fingerprint(user) user.set_machine(src) + show_ui(user) + +/obj/item/device/tvcamera/proc/show_ui(mob/user) var/dat = list() dat += "Channel name is: [channel ? channel : "unidentified broadcast"]
" dat += "Video streaming is [camera.status ? "on" : "off"]
" + if(camera.status && showing_name) + dat += "- You're showing [showing_name] to your viewers.
" dat += "Mic is [radio.broadcasting ? "on" : "off"]
" dat += "Sound is being broadcasted on frequency [format_frequency(radio.frequency)] ([get_frequency_name(radio.frequency)])
" var/datum/browser/popup = new(user, "Hovercamera", "Eye Buddy", 300, 390, src) @@ -67,8 +74,12 @@ camera.set_status(!camera.status) if(camera.status) to_chat(usr,"Video streaming activated. Broadcasting on channel '[channel]'") + show_tvs(loc) else to_chat(usr,"Video streaming deactivated.") + hide_tvs() + for(var/obj/machinery/computer/security/telescreen/entertainment/ES as anything in GLOB.entertainment_screens) + ES.stop_showing() update_icon() if(href_list["sound"]) radio.ToggleBroadcast() @@ -79,6 +90,50 @@ if(!href_list["close"]) attack_self(usr) +/obj/item/device/tvcamera/proc/show_tvs(atom/thing) + if(showing) + hide_tvs(showing) + + showing = weakref(thing) + showing_name = "[thing]" + for(var/obj/machinery/computer/security/telescreen/entertainment/ES as anything in GLOB.entertainment_screens) + ES.show_thing(thing) + + START_PROCESSING(SSobj, src) + +/obj/item/device/tvcamera/proc/hide_tvs() + if(!showing) + return + for(var/obj/machinery/computer/security/telescreen/entertainment/ES as anything in GLOB.entertainment_screens) + ES.maybe_stop_showing(showing) + STOP_PROCESSING(SSobj, src) + showing = null + showing_name = null + +/obj/item/device/tvcamera/Moved(atom/old_loc, direction, forced = FALSE, movetime) + . = ..() + if(camera.status && loc != old_loc) + show_tvs(loc) + +/obj/item/device/tvcamera/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + . = ..() + if(camera.status && !isturf(target)) + show_tvs(target) + user.visible_message("[user] aims [src] at [target].", "You aim [src] at [target].") + if(user.machine == src) + show_ui(user) // refresh the UI + +/obj/item/device/tvcamera/process() + if(!showing) + return PROCESS_KILL + + var/atom/A = showing.resolve() + if(!A || QDELETED(A)) + show_tvs(loc) + + if(get_dist(get_turf(src), get_turf(A)) > 5) + show_tvs(loc) + /obj/item/device/tvcamera/update_icon() ..() if(camera.status) diff --git a/code/modules/tgui/modules/camera.dm b/code/modules/tgui/modules/camera.dm index 86eb923c1c..abfef14be1 100644 --- a/code/modules/tgui/modules/camera.dm +++ b/code/modules/tgui/modules/camera.dm @@ -296,3 +296,7 @@ /datum/tgui_module/camera/ntos/hacked/New(host) . = ..(host, using_map.station_networks.Copy()) + +/datum/tgui_module/camera/bigscreen/tgui_state(mob/user) + return GLOB.tgui_physical_state_bigscreen + \ No newline at end of file diff --git a/code/modules/tgui/states.dm b/code/modules/tgui/states.dm index 01b8ae1a84..5a66efc090 100644 --- a/code/modules/tgui/states.dm +++ b/code/modules/tgui/states.dm @@ -85,7 +85,7 @@ * * Check the distance for a living mob. * Really only used for checks outside the context of a mob. - * Otherwise, use shared_living_ui_distance(). + * Otherwise, use shared_living_tgui_distance(). * * required src_object The object which owns the UI. * required user mob The mob who opened/is using the UI. @@ -119,10 +119,26 @@ return STATUS_DISABLED return STATUS_CLOSE // Otherwise, we got nothing. -/mob/living/carbon/human/shared_living_tgui_distance(atom/movable/src_object, viewcheck = TRUE) - if((TK in mutations) && (get_dist(src, src_object) <= 2)) +/** + * public + * + * Distance versus interaction check, with max'd update range. + * + * required src_object atom/movable The object which owns the UI. + * + * return UI_state The state of the UI. + */ +/mob/living/proc/shared_living_tgui_distance_bigscreen(atom/movable/src_object, viewcheck = TRUE) + // If the object is obscured, close it. + if(viewcheck && !(src_object in view(src))) + return STATUS_CLOSE + + var/dist = get_dist(src_object, src) + if(dist <= 1) // Open and interact if 1-0 tiles away. return STATUS_INTERACTIVE - return ..() + else if(dist <= world.view) + return STATUS_UPDATE + return STATUS_CLOSE // Otherwise, we got nothing. // Topic Extensions for old UIs /datum/proc/CanUseTopic(var/mob/user, var/datum/tgui_state/state) diff --git a/code/modules/tgui/states/physical.dm b/code/modules/tgui/states/physical.dm index 30c67906ae..9712090b5d 100644 --- a/code/modules/tgui/states/physical.dm +++ b/code/modules/tgui/states/physical.dm @@ -47,3 +47,29 @@ GLOBAL_DATUM_INIT(tgui_physical_obscured_state, /datum/tgui_state/physical_obscu /mob/living/silicon/ai/physical_obscured_can_use_topic(src_object) return STATUS_UPDATE // AIs are not physical. + + /** + * tgui state: physical_state_bigscreen + * + * Short-circuits the default state to only check physical distance, + * but allows updates out to the full size of the screen. + **/ + +GLOBAL_DATUM_INIT(tgui_physical_state_bigscreen, /datum/tgui_state/physical_bigscreen, new) + +/datum/tgui_state/physical_bigscreen/can_use_topic(src_object, mob/user) + . = user.shared_tgui_interaction(src_object) + if(. > STATUS_CLOSE) + return min(., user.physical_can_use_tgui_topic_bigscreen(src_object)) + +/mob/proc/physical_can_use_tgui_topic_bigscreen(src_object) + return STATUS_CLOSE + +/mob/living/physical_can_use_tgui_topic_bigscreen(src_object) + return shared_living_tgui_distance_bigscreen(src_object) + +/mob/living/silicon/physical_can_use_tgui_topic_bigscreen(src_object) + return max(STATUS_UPDATE, shared_living_tgui_distance_bigscreen(src_object)) // Silicons can always see. + +/mob/living/silicon/ai/physical_can_use_tgui_topic(src_object) + return STATUS_UPDATE // AIs are not physical. \ No newline at end of file diff --git a/icons/obj/entertainment_monitor.dmi b/icons/obj/entertainment_monitor.dmi new file mode 100644 index 0000000000..40250b33e0 Binary files /dev/null and b/icons/obj/entertainment_monitor.dmi differ