diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 59da6920026..253be8874ff 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -198,50 +198,20 @@ /proc/get_mobs_in_radio_ranges(list/obj/item/radio/radios) . = list() - // Returns a list of mobs who can hear any of the radios given in @radios + // Returns a list of mobs who can hear any of the radios var/list/speaker_coverage = list() - for(var/obj/item/radio/R in radios) - if(R) - //Cyborg checks. Receiving message uses a bit of cyborg's charge. - var/obj/item/radio/borg/BR = R - if(istype(BR) && BR.myborg) - var/mob/living/silicon/robot/borg = BR.myborg - var/datum/robot_component/CO = borg.get_component("radio") - if(!CO) - continue //No radio component (Shouldn't happen) - if(!borg.is_component_functioning("radio")) - continue //No power. + for(var/obj/item/radio/R as anything in radios) + var/obj/item/radio/borg/BR = R + if(istype(BR) && BR.myborg) + if(!BR.myborg.is_component_functioning("radio")) + continue //No power. - var/turf/speaker = get_turf(R) - if(speaker) - for(var/turf/T in hear(R.canhear_range,speaker)) - var/obj/item/radio/oldR = speaker_coverage[T] - if(!istype(oldR)) - speaker_coverage[T] = R - continue - if(oldR.canhear_range < R.canhear_range) - speaker_coverage[T] = R - - // Try to find all the players who can hear the message - for(var/A in GLOB.player_list + GLOB.hear_radio_list) - var/mob/M = A - if(!M) - continue - var/turf/ear = get_turf(M) - if(!ear) - continue - // Ghostship is magic: Ghosts can hear radio chatter from anywhere - if(isobserver(M) && M.get_preference(PREFTOGGLE_CHAT_GHOSTRADIO)) - . |= M - continue - if(!speaker_coverage[ear]) - continue - var/obj/item/radio/R = speaker_coverage[ear] - if(!istype(R) || R.canhear_range > 0) - . |= M - continue - if(is_same_root_atom(M, speaker_coverage[ear])) - . |= M + for(var/mob/listener as anything in R.listeners) + speaker_coverage |= listener + + if(ismob(R.loc)) + speaker_coverage |= R.loc + return speaker_coverage /proc/inLineOfSight(X1,Y1,X2,Y2,Z=1,PX1=16.5,PY1=16.5,PX2=16.5,PY2=16.5) var/turf/T diff --git a/code/game/objects/items/devices/radio/radio_objects.dm b/code/game/objects/items/devices/radio/radio_objects.dm index 4b5ca92cf49..d8476380c45 100644 --- a/code/game/objects/items/devices/radio/radio_objects.dm +++ b/code/game/objects/items/devices/radio/radio_objects.dm @@ -60,6 +60,8 @@ GLOBAL_LIST_EMPTY(deadsay_radio_systems) var/obj/item/encryptionkey/syndicate/syndiekey = null /// How many times this is disabled by EMPs var/disable_timer = 0 + /// List of all the mobs that can hear this radio + var/list/listeners = list() /// Areas in which this radio cannot send messages var/static/list/blacklisted_areas = list(/area/adminconstruction, /area/tdome, /area/ruin/space/bubblegum_arena) @@ -82,7 +84,6 @@ GLOBAL_LIST_EMPTY(deadsay_radio_systems) var/requires_tcomms = FALSE // Does this device require tcomms to work.If TRUE it wont function at all without tcomms. If FALSE, it will work without tcomms, just slowly var/instant = FALSE // Should this device instantly communicate if there isnt tcomms - /obj/item/radio/proc/set_frequency(new_frequency) SSradio.remove_object(src, frequency) frequency = new_frequency @@ -97,6 +98,7 @@ GLOBAL_LIST_EMPTY(deadsay_radio_systems) /obj/item/radio/Destroy() SStgui.close_uis(wires) + listeners.Cut() QDEL_NULL(wires) if(SSradio) SSradio.remove_object(src, frequency) @@ -107,7 +109,6 @@ GLOBAL_LIST_EMPTY(deadsay_radio_systems) follow_target = null return ..() - /obj/item/radio/Initialize() ..() if(frequency < RADIO_LOW_FREQ || frequency > RADIO_HIGH_FREQ) @@ -116,6 +117,31 @@ GLOBAL_LIST_EMPTY(deadsay_radio_systems) for(var/ch_name in channels) secure_radio_connections[ch_name] = SSradio.add_object(src, SSradio.radiochannels[ch_name], RADIO_CHAT) + if(canhear_range) + AddComponent(/datum/component/proximity_monitor, canhear_range) + +/obj/item/radio/HasProximity(mob/crosser) + if(!istype(crosser) || (crosser in listeners)) + return + listeners += crosser + RegisterSignal(crosser, COMSIG_MOVABLE_MOVED, PROC_REF(is_crosser_still_listening)) + RegisterSignal(crosser, COMSIG_PARENT_QDELETING, PROC_REF(remove_from_listener_list)) + +/obj/item/radio/proc/is_crosser_still_listening(mob/crosser) + SIGNAL_HANDLER // COMSIG_MOVABLE_MOVED + var/still_listening = FALSE + for(var/obj/effect/abstract/proximity_checker/checker in get_turf(crosser)) + if(checker.monitor.hasprox_receiver == src) + still_listening = TRUE + break + if(still_listening) + return + remove_from_listener_list(crosser) + +/obj/item/radio/proc/remove_from_listener_list(mob/crosser) + SIGNAL_HANDLER // COMSIG_PARENT_QDELETING + listeners -= crosser + UnregisterSignal(crosser, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED)) /obj/item/radio/attack_ghost(mob/user) return interact(user) @@ -210,14 +236,26 @@ GLOBAL_LIST_EMPTY(deadsay_radio_systems) if(has_loudspeaker) loudspeaker = !loudspeaker if(loudspeaker) - canhear_range = 3 + update_hear_range(3) else - canhear_range = 0 + update_hear_range(0) else . = FALSE if(.) add_fingerprint(usr) +/obj/item/radio/proc/update_hear_range(new_hear_range) + canhear_range = new_hear_range + var/datum/component/proximity_monitor/our_prox_component = GetComponent(/datum/component/proximity_monitor) + if(!canhear_range) + QDEL_NULL(our_prox_component) + return + + if(our_prox_component) + our_prox_component.set_radius(canhear_range) + else + AddComponent(/datum/component/proximity_monitor, canhear_range) + /obj/item/radio/proc/list_secure_channels(mob/user) var/list/dat = list() for(var/channel in channels) @@ -538,9 +576,7 @@ GLOBAL_LIST_EMPTY(deadsay_radio_systems) /obj/item/radio/proc/send_announcement() if(is_listening()) - return get_mobs_in_view(canhear_range, src) - - return null + return listeners /obj/item/radio/examine(mob/user) . = ..() @@ -808,3 +844,16 @@ GLOBAL_LIST_EMPTY(deadsay_radio_systems) return return M.say_dead(message) + +GLOBAL_DATUM_INIT(deadchat_radio, /obj/item/radio/dchat_radio_handler, new()) + +/obj/item/radio/dchat_radio_handler + name = "Deadchat radio handler. Do not fuck with" + canhear_range = 0 + +/obj/item/radio/dchat_radio_handler/Destroy(force) + . = ..() + stack_trace("Someone just tried to delete the deadchat handler!") + if(!force) + return QDEL_HINT_LETMELIVE + return ..() diff --git a/code/modules/client/preference/link_processing.dm b/code/modules/client/preference/link_processing.dm index 961b6394074..79d6d5f7694 100644 --- a/code/modules/client/preference/link_processing.dm +++ b/code/modules/client/preference/link_processing.dm @@ -1048,6 +1048,9 @@ if("ghost_radio") toggles ^= PREFTOGGLE_CHAT_GHOSTRADIO + if(isobserver(user)) + var/mob/dead/observer/dead_dude = user + dead_dude.update_dead_radio() if("ghost_pda") toggles ^= PREFTOGGLE_CHAT_GHOSTPDA diff --git a/code/modules/client/preference/preferences_toggles.dm b/code/modules/client/preference/preferences_toggles.dm index 541e55faba3..de74fbec1d1 100644 --- a/code/modules/client/preference/preferences_toggles.dm +++ b/code/modules/client/preference/preferences_toggles.dm @@ -73,6 +73,12 @@ disable_message = "As a ghost, you will now hear all radio chat in the world." blackbox_message = "Toggle GhostRadio" +/datum/preference_toggle/toggle_ghost_radio/set_toggles(client/user) + . = ..() + if(isobserver(user.mob)) + var/mob/dead/observer/dead_dude = user.mob + dead_dude.update_dead_radio() + /datum/preference_toggle/toggle_admin_radio name = "Admin Radio" description = "Toggle seeing radiochatter from radios and speakers" diff --git a/code/modules/mob/dead/observer/observer_base.dm b/code/modules/mob/dead/observer/observer_base.dm index 1cecdbfa03e..bc0624b2b86 100644 --- a/code/modules/mob/dead/observer/observer_base.dm +++ b/code/modules/mob/dead/observer/observer_base.dm @@ -825,5 +825,11 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp /mob/dead/observer/get_runechat_color() return alive_runechat_color +/mob/dead/observer/proc/update_dead_radio() + if(get_preference(PREFTOGGLE_CHAT_GHOSTRADIO)) + GLOB.deadchat_radio.listeners |= src + else + GLOB.deadchat_radio.listeners -= src + #undef GHOST_CAN_REENTER #undef GHOST_IS_OBSERVER diff --git a/code/modules/mob/dead/observer/observer_login.dm b/code/modules/mob/dead/observer/observer_login.dm index d9212897cc8..f92958eb746 100644 --- a/code/modules/mob/dead/observer/observer_login.dm +++ b/code/modules/mob/dead/observer/observer_login.dm @@ -10,3 +10,5 @@ if(GLOB.non_respawnable_keys[ckey]) can_reenter_corpse = 0 REMOVE_TRAIT(src, TRAIT_RESPAWNABLE, GHOSTED) + + update_dead_radio()