Skip to content

Commit

Permalink
More features and tweaks for broadcasting (#6115)
Browse files Browse the repository at this point in the history
# About the pull request
Turned out that through cameras you can only see speech that you already
see without cameras. So I quickly found a way to fix it with the least
(for me) amount of crap code.

# Explain why it's good for the game
That's pretty much the point of broadcasting.


# Testing Photographs and Procedure
<details>


![2024-04-08_09-56-41](https://github.com/cmss13-devs/cmss13/assets/115417687/f7b28bd6-571b-4c4e-8c5c-337f25ea8b6e)

![Screenshot_2024-04-10_01-35-26](https://github.com/cmss13-devs/cmss13/assets/115417687/35b6cce1-ed2e-4270-973a-6e4387540ae2)

![Screenshot_2024-04-10_01-56-08](https://github.com/cmss13-devs/cmss13/assets/115417687/0bcab79b-2fb2-4364-91db-84f73bd58f24)

![Screenshot_2024-04-10_04-14-50](https://github.com/cmss13-devs/cmss13/assets/115417687/e85bb1a6-6642-4db1-a505-50e01248085a)

</details>


# Changelog
:cl: ihatethisengine
add: Combat Correspondent can broadcast speech and emotes.
add: Speech close enough to the camera will be shown above connected TVs
as abovehead messages
/:cl:

---------

Co-authored-by: Drathek <[email protected]>
  • Loading branch information
ihatethisengine and Drulikar committed Apr 24, 2024
1 parent 7e962fb commit 9512952
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 13 deletions.
4 changes: 3 additions & 1 deletion code/__DEFINES/dcs/signals/atom/signals_item.dm
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@

#define COMSIG_ITEM_PICKUP "item_pickup"

///from /obj/item/device/camera/broadcasting/attack_self
///from /obj/item/device/camera/broadcasting
#define COMSIG_BROADCAST_GO_LIVE "broadcast_live"
#define COMSIG_BROADCAST_HEAR_TALK "broadcast_hear_talk"
#define COMSIG_BROADCAST_SEE_EMOTE "broadcast_see_emote"

/// from /obj/item/proc/mob_can_equip
#define COMSIG_ITEM_ATTEMPTING_EQUIP "item_attempting_equip"
Expand Down
2 changes: 2 additions & 0 deletions code/__DEFINES/equipment.dm
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
#define USES_HEARING (1<<17)
/// Should we use the initial icon for display? Mostly used by overlay only objects
#define HTML_USE_INITAL_ICON (1<<18)
// Whether or not the object sees emotes
#define USES_SEEING (1<<19)

//==========================================================================================

Expand Down
10 changes: 10 additions & 0 deletions code/datums/emotes.dm
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
var/paygrade = user.get_paygrade()
var/formatted_message = "<b>[paygrade][user]</b> [msg]"
var/user_turf = get_turf(user)
var/list/seeing_obj = list()
if (user.client)
for(var/mob/ghost as anything in GLOB.dead_mob_list)
if(!ghost.client || isnewplayer(ghost))
Expand All @@ -132,19 +133,28 @@
if(emote_type & EMOTE_VISIBLE)
var/list/viewers = get_mobs_in_view(7, user)
for(var/mob/current_mob in viewers)
for(var/obj/object in current_mob.contents)
if((object.flags_atom & USES_SEEING))
seeing_obj |= object
if(!(current_mob.client?.prefs.toggles_langchat & LANGCHAT_SEE_EMOTES))
viewers -= current_mob
run_langchat(user, viewers)
else if(emote_type & EMOTE_AUDIBLE)
var/list/heard = get_mobs_in_view(7, user)
for(var/mob/current_mob in heard)
for(var/obj/object in current_mob.contents)
if((object.flags_atom & USES_HEARING))
seeing_obj |= object
if(current_mob.ear_deaf)
heard -= current_mob
continue
if(!(current_mob.client?.prefs.toggles_langchat & LANGCHAT_SEE_EMOTES))
heard -= current_mob
run_langchat(user, heard)

for(var/obj/object as anything in seeing_obj)
object.see_emote(user, msg, (emote_type & EMOTE_AUDIBLE))

SEND_SIGNAL(user, COMSIG_MOB_EMOTED(key))


Expand Down
2 changes: 1 addition & 1 deletion code/game/machinery/camera/camera.dm
Original file line number Diff line number Diff line change
Expand Up @@ -312,8 +312,8 @@ GLOBAL_LIST_EMPTY_TYPED(all_cameras, /obj/structure/machinery/camera)
. = ..()
if(!camera_item)
return INITIALIZE_HINT_QDEL
c_tag = camera_item.get_broadcast_name()
linked_broadcasting = camera_item
c_tag = linked_broadcasting.get_broadcast_name()

/obj/structure/machinery/camera/mortar
alpha = 0
Expand Down
59 changes: 50 additions & 9 deletions code/game/machinery/computer/camera_console.dm
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

var/colony_camera_mapload = TRUE
var/admin_console = FALSE
var/stay_connected = FALSE

/obj/structure/machinery/computer/cameras/Initialize(mapload)
. = ..()
Expand All @@ -33,7 +34,7 @@

/obj/structure/machinery/computer/cameras/Destroy()
SStgui.close_uis(src)
QDEL_NULL(current)
current = null
UnregisterSignal(src, COMSIG_CAMERA_MAPNAME_ASSIGNED)
last_camera_turf = null
concurrent_users = null
Expand Down Expand Up @@ -147,7 +148,7 @@
// Unregister map objects
SEND_SIGNAL(src, COMSIG_CAMERA_UNREGISTER_UI, user)
// Turn off the console
if(length(concurrent_users) == 0 && is_living)
if(length(concurrent_users) == 0 && is_living && !stay_connected)
current = null
SEND_SIGNAL(src, COMSIG_CAMERA_CLEAR)
last_camera_turf = null
Expand Down Expand Up @@ -206,45 +207,85 @@
name = "Television Set"
desc = "An old TV hooked up to a video cassette recorder, you can even use it to time shift WOW."
network = list(CAMERA_NET_CORRESPONDENT)
stay_connected = TRUE
circuit = /obj/item/circuitboard/computer/cameras/tv
var/obj/item/device/camera/broadcasting/broadcastingcamera = null

/obj/structure/machinery/computer/cameras/wooden_tv/broadcast/Destroy()
broadcastingcamera = null
return ..()

/obj/structure/machinery/computer/cameras/wooden_tv/broadcast/ui_state(mob/user)
return GLOB.default_state
return GLOB.in_view

/obj/structure/machinery/computer/cameras/wooden_tv/broadcast/ui_act(action, params)
. = ..()
if(action != "switch_camera")
return
broadcastingcamera = null
if (!istype(current, /obj/structure/machinery/camera/correspondent))
if(broadcastingcamera)
clear_camera()
if(!istype(current, /obj/structure/machinery/camera/correspondent))
return
var/obj/structure/machinery/camera/correspondent/corr_cam = current
if (!corr_cam.linked_broadcasting)
if(!corr_cam.linked_broadcasting)
return
broadcastingcamera = corr_cam.linked_broadcasting
RegisterSignal(broadcastingcamera, COMSIG_BROADCAST_GO_LIVE, PROC_REF(go_back_live))
RegisterSignal(broadcastingcamera, COMSIG_COMPONENT_ADDED, PROC_REF(handle_rename))
RegisterSignal(broadcastingcamera, COMSIG_PARENT_QDELETING, PROC_REF(clear_camera))
RegisterSignal(broadcastingcamera, COMSIG_BROADCAST_HEAR_TALK, PROC_REF(transfer_talk))
RegisterSignal(broadcastingcamera, COMSIG_BROADCAST_SEE_EMOTE, PROC_REF(transfer_emote))

/obj/structure/machinery/computer/cameras/wooden_tv/broadcast/ui_close(mob/user)
. = ..()
if (!current && broadcastingcamera)
if(!broadcastingcamera)
return
if(!current)
clear_camera()

/obj/structure/machinery/computer/cameras/wooden_tv/broadcast/proc/clear_camera()
SIGNAL_HANDLER
UnregisterSignal(broadcastingcamera, list(COMSIG_BROADCAST_GO_LIVE, COMSIG_PARENT_QDELETING))
UnregisterSignal(broadcastingcamera, list(COMSIG_BROADCAST_GO_LIVE, COMSIG_PARENT_QDELETING, COMSIG_COMPONENT_ADDED, COMSIG_BROADCAST_HEAR_TALK, COMSIG_BROADCAST_SEE_EMOTE))
broadcastingcamera = null

/obj/structure/machinery/computer/cameras/wooden_tv/broadcast/proc/go_back_live(obj/item/device/camera/broadcasting/broadcastingcamera)
SIGNAL_HANDLER
if (current.c_tag == broadcastingcamera.get_broadcast_name())
if(current.c_tag == broadcastingcamera.get_broadcast_name())
current = broadcastingcamera.linked_cam
SEND_SIGNAL(src, COMSIG_CAMERA_SET_TARGET, broadcastingcamera.linked_cam, broadcastingcamera.linked_cam.view_range, broadcastingcamera.linked_cam.view_range)

/obj/structure/machinery/computer/cameras/wooden_tv/broadcast/proc/transfer_talk(obj/item/camera, mob/living/sourcemob, message, verb = "says", datum/language/language, italics = FALSE, show_message_above_tv = FALSE)
SIGNAL_HANDLER
if(inoperable())
return
if(show_message_above_tv)
langchat_speech(message, get_mobs_in_view(7, src), language, sourcemob.langchat_color, FALSE, LANGCHAT_FAST_POP, list(sourcemob.langchat_styles))
for(var/datum/weakref/user_ref in concurrent_users)
var/mob/user = user_ref.resolve()
if(user?.client?.prefs && !user.client.prefs.lang_chat_disabled && !user.ear_deaf && user.say_understands(sourcemob, language))
sourcemob.langchat_display_image(user)

/obj/structure/machinery/computer/cameras/wooden_tv/broadcast/proc/transfer_emote(obj/item/camera, mob/living/sourcemob, emote, audible = FALSE, show_message_above_tv = FALSE)
SIGNAL_HANDLER
if(inoperable())
return
if(show_message_above_tv)
langchat_speech(emote, get_mobs_in_view(7, src), null, null, TRUE, LANGCHAT_FAST_POP, list("emote"))
for(var/datum/weakref/user_ref in concurrent_users)
var/mob/user = user_ref.resolve()
if(user?.client?.prefs && (user.client.prefs.toggles_langchat & LANGCHAT_SEE_EMOTES) && (!audible || !user.ear_deaf))
sourcemob.langchat_display_image(user)

/obj/structure/machinery/computer/cameras/wooden_tv/broadcast/examine(mob/user)
. = ..()
attack_hand(user) //watch tv on examine

/obj/structure/machinery/computer/cameras/wooden_tv/broadcast/proc/handle_rename(obj/item/camera, datum/component/label)
SIGNAL_HANDLER
if(!istype(label, /datum/component/label))
return
current.c_tag = broadcastingcamera.get_broadcast_name()

/obj/structure/machinery/computer/cameras/wooden_tv/ot
name = "Mortar Monitoring Set"
desc = "A Console linked to Mortar launched cameras."
Expand Down
3 changes: 3 additions & 0 deletions code/game/objects/objs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@
/obj/proc/hear_talk(mob/living/M as mob, msg, verb="says", datum/language/speaking, italics = 0)
return

/obj/proc/see_emote(mob/living/M as mob, emote, audible = FALSE)
return

/obj/attack_hand(mob/user)
if(can_buckle) manual_unbuckle(user)
else . = ..()
Expand Down
28 changes: 26 additions & 2 deletions code/modules/paperwork/photography.dm
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,12 @@
flags_equip_slot = NO_FLAGS //cannot be equiped
var/obj/structure/machinery/camera/correspondent/linked_cam

/obj/item/device/camera/broadcasting/Initialize(mapload, ...)
. = ..()
linked_cam = new(loc, src)
linked_cam.status = FALSE
RegisterSignal(src, COMSIG_COMPONENT_ADDED, PROC_REF(handle_rename))

/obj/item/device/camera/broadcasting/Destroy()
clear_broadcast()
return ..()
Expand All @@ -367,13 +373,25 @@
. = ..()
if(!.)
return
linked_cam = new(loc, src)
flags_atom |= (USES_HEARING|USES_SEEING)
if(!linked_cam || QDELETED(linked_cam))
linked_cam = new(loc, src)
else
linked_cam.status = TRUE
linked_cam.forceMove(loc)
SEND_SIGNAL(src, COMSIG_BROADCAST_GO_LIVE)
to_chat(user, SPAN_NOTICE("[src] begins to buzz softly as you go live."))

/obj/item/device/camera/broadcasting/unwield(mob/user)
. = ..()
clear_broadcast()
flags_atom &= ~(USES_HEARING|USES_SEEING)
linked_cam.status = FALSE

/obj/item/device/camera/broadcasting/proc/handle_rename(obj/item/camera, datum/component/label)
SIGNAL_HANDLER
if(!istype(label, /datum/component/label))
return
linked_cam.c_tag = get_broadcast_name()

/obj/item/device/camera/broadcasting/proc/clear_broadcast()
if(!QDELETED(linked_cam))
Expand All @@ -385,6 +403,12 @@
return src_label_component.label_name
return "Broadcast [serial_number]"

/obj/item/device/camera/broadcasting/hear_talk(mob/living/sourcemob, message, verb = "says", datum/language/language, italics = FALSE)
SEND_SIGNAL(src, COMSIG_BROADCAST_HEAR_TALK, sourcemob, message, verb, language, italics, get_dist(sourcemob, src) < 3)

/obj/item/device/camera/broadcasting/see_emote(mob/living/sourcemob, emote, audible = FALSE)
SEND_SIGNAL(src, COMSIG_BROADCAST_SEE_EMOTE, sourcemob, emote, audible, get_dist(sourcemob, src) < 3 && audible)

/obj/item/photo/proc/construct(datum/picture/P)
icon = P.fields["icon"]
tiny = P.fields["tiny"]
Expand Down
23 changes: 23 additions & 0 deletions code/modules/tgui/states.dm
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,26 @@
return UI_DISABLED
// Otherwise, we got nothing.
return UI_CLOSE

/**
* public
*
* Check if in view. Can interact only if adjacent, updates within max distance, otherwise closes
*
* required src_object atom/movable The object which owns the UI.
*
* return UI_state The state of the UI.
*/
/mob/living/proc/shared_living_ui_in_view(atom/movable/src_object, viewcheck = TRUE, max_distance = 7)
// If the object is obscured, close it.
if(viewcheck && !(src_object in view(src)))
return UI_CLOSE
var/dist = get_dist(src_object, src)
// Open and interact if 1-0 tiles away.
if(dist <= 1)
return UI_INTERACTIVE
// View only if within distance.
else if(dist <= max_distance)
return UI_UPDATE
// Otherwise, we got nothing.
return UI_CLOSE
15 changes: 15 additions & 0 deletions code/modules/tgui/states/in_view.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//If in view and within view distance
GLOBAL_DATUM_INIT(in_view, /datum/ui_state/in_view, new)
/datum/ui_state/in_view/can_use_topic(src_object, mob/user)
return user.in_view_can_use_topic(src_object) // Call the individual mob-overridden procs.

/mob/proc/in_view_can_use_topic(src_object)
return UI_CLOSE // Don't allow interaction by default.

/mob/ghost/in_view_can_use_topic(src_object)
return UI_UPDATE //ghost can just watch

/mob/living/in_view_can_use_topic(src_object)
. = shared_ui_interaction(src_object)
if(. > UI_CLOSE && loc) //must not be in nullspace.
. = min(., shared_living_ui_in_view(src_object)) // Check the distance and view...
1 change: 1 addition & 0 deletions colonialmarines.dme
Original file line number Diff line number Diff line change
Expand Up @@ -2362,6 +2362,7 @@
#include "code\modules\tgui\states\default.dm"
#include "code\modules\tgui\states\hands.dm"
#include "code\modules\tgui\states\human_adjacent.dm"
#include "code\modules\tgui\states\in_view.dm"
#include "code\modules\tgui\states\inventory.dm"
#include "code\modules\tgui\states\never.dm"
#include "code\modules\tgui\states\new_player.dm"
Expand Down

0 comments on commit 9512952

Please sign in to comment.