Skip to content
This repository was archived by the owner on May 22, 2025. It is now read-only.

Commit c8b4ff6

Browse files
committed
radio magic
1 parent 54c6e39 commit c8b4ff6

File tree

26 files changed

+512
-278
lines changed

26 files changed

+512
-278
lines changed

code/game/machinery/bank_machine.dm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
radio = new(src)
1717
radio.subspace_transmission = TRUE
1818
radio.canhear_range = 0
19+
radio.set_listening(FALSE)
1920
radio.recalculateChannels()
2021

2122
/obj/machinery/computer/bank_machine/Destroy()

code/game/machinery/doors/brigdoors.dm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@
8383
. = ..()
8484

8585
Radio = new/obj/item/radio(src)
86-
Radio.listening = 0
86+
Radio.set_listening(FALSE)
8787

8888
/obj/machinery/door_timer/Initialize(mapload)
8989
. = ..()

code/game/machinery/hologram.dm

Lines changed: 75 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
#define CAN_HEAR_MASTERS (1<<0)
2+
#define CAN_HEAR_ACTIVE_HOLOCALLS (1<<1)
3+
#define CAN_HEAR_RECORD_MODE (1<<2)
4+
#define CAN_HEAR_ALL_FLAGS (CAN_HEAR_MASTERS|CAN_HEAR_ACTIVE_HOLOCALLS|CAN_HEAR_RECORD_MODE)
5+
16
/* Holograms!
27
* Contains:
38
* Holopad
@@ -42,7 +47,8 @@ GLOBAL_LIST_EMPTY(holopads)
4247
max_integrity = 300
4348
armor = list(MELEE = 50, BULLET = 20, LASER = 20, ENERGY = 20, BOMB = 0, BIO = 0, RAD = 0, FIRE = 50, ACID = 0)
4449
circuit = /obj/item/circuitboard/machine/holopad
45-
/// List of living mobs that use the holopad
50+
/// associative lazylist of the form: list(mob calling us = hologram representing that mob).
51+
/// this is only populated for holopads answering calls from another holopad
4652
var/list/masters
4753
/// Holoray-mob link
4854
var/list/holorays
@@ -83,10 +89,8 @@ GLOBAL_LIST_EMPTY(holopads)
8389
var/padname = null
8490
/// Holopad Harassment Cooldown
8591
var/holopad_cooldown = 20 SECONDS
86-
87-
/obj/machinery/holopad/Initialize()
88-
. = ..()
89-
become_hearing_sensitive()
92+
///bitfield. used to turn on and off hearing sensitivity depending on if we can act on Hear() at all - meant for lowering the number of unessesary hearable atoms
93+
var/can_hear_flags = NONE
9094

9195
/obj/machinery/holopad/secure
9296
name = "secure holopad"
@@ -156,9 +160,8 @@ obj/machinery/holopad/secure/Initialize(mapload)
156160
if(outgoing_call)
157161
outgoing_call.ConnectionFailure(src)
158162

159-
for(var/I in holo_calls)
160-
var/datum/holocall/HC = I
161-
HC.ConnectionFailure(src)
163+
for(var/datum/holocall/holocall_to_disconnect as anything in holo_calls)
164+
holocall_to_disconnect.ConnectionFailure(src)
162165

163166
for (var/I in masters)
164167
clear_holo(I)
@@ -360,13 +363,59 @@ obj/machinery/holopad/secure/Initialize(mapload)
360363
outgoing_call.Disconnect(src)
361364
return TRUE
362365

366+
367+
//setters
368+
/**
369+
* setter for can_hear_flags. handles adding or removing the given flag on can_hear_flags and then adding hearing sensitivity or removing it depending on the final state
370+
* this is necessary because holopads are a significant fraction of the hearable atoms on station which increases the cost of procs that iterate through hearables
371+
* so we need holopads to not be hearable until it is needed
372+
*
373+
* * flag - one of the can_hear_flags flag defines
374+
* * set_flag - boolean, if TRUE sets can_hear_flags to that flag and might add hearing sensitivity if can_hear_flags was NONE before,
375+
* if FALSE unsets the flag and possibly removes hearing sensitivity
376+
*/
377+
/obj/machinery/holopad/proc/set_can_hear_flags(flag, set_flag = TRUE)
378+
if(!(flag & CAN_HEAR_ALL_FLAGS))
379+
return FALSE //the given flag doesnt exist
380+
381+
if(set_flag)
382+
if(can_hear_flags == NONE)//we couldnt hear before, so become hearing sensitive
383+
become_hearing_sensitive()
384+
385+
can_hear_flags |= flag
386+
return TRUE
387+
388+
else
389+
can_hear_flags &= ~flag
390+
if(can_hear_flags == NONE)
391+
lose_hearing_sensitivity()
392+
393+
return TRUE
394+
395+
///setter for adding/removing holocalls to this holopad. used to update the holo_calls list and can_hear_flags
396+
///adds the given holocall if add_holocall is TRUE, removes if FALSE
397+
/obj/machinery/holopad/proc/set_holocall(datum/holocall/holocall_to_update, add_holocall = TRUE)
398+
if(!istype(holocall_to_update))
399+
return FALSE
400+
401+
if(add_holocall)
402+
set_can_hear_flags(CAN_HEAR_ACTIVE_HOLOCALLS)
403+
LAZYADD(holo_calls, holocall_to_update)
404+
405+
else
406+
LAZYREMOVE(holo_calls, holocall_to_update)
407+
if(!LAZYLEN(holo_calls))
408+
set_can_hear_flags(CAN_HEAR_ACTIVE_HOLOCALLS, FALSE)
409+
410+
return TRUE
411+
412+
363413
/**
364414
* hangup_all_calls: Disconnects all current holocalls from the holopad
365415
*/
366416
/obj/machinery/holopad/proc/hangup_all_calls()
367-
for(var/I in holo_calls)
368-
var/datum/holocall/HC = I
369-
HC.Disconnect(src)
417+
for(var/datum/holocall/holocall_to_disconnect as anything in holo_calls)
418+
holocall_to_disconnect.Disconnect(src)
370419

371420
//do not allow AIs to answer calls or people will use it to meta the AI sattelite
372421
/obj/machinery/holopad/attack_ai(mob/living/silicon/ai/user)
@@ -464,10 +513,12 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
464513
if(masters[master] && speaker != master)
465514
master.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mods)
466515

467-
for(var/I in holo_calls)
468-
var/datum/holocall/HC = I
469-
if(HC.connected_holopad == src && speaker != HC.hologram)
470-
HC.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mods)
516+
for(var/datum/holocall/holocall_to_update as anything in holo_calls)
517+
if(holocall_to_update.connected_holopad == src)//if we answered this call originating from another holopad
518+
if(speaker == holocall_to_update.hologram && holocall_to_update.user.client?.prefs.read_preference(/datum/preference/toggle/enable_runechat))
519+
holocall_to_update.user.create_chat_message(speaker, message_language, raw_message, spans)
520+
else
521+
holocall_to_update.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mods)
471522

472523
if(outgoing_call && speaker == outgoing_call.user)
473524
outgoing_call.hologram.say(raw_message)
@@ -498,6 +549,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
498549
/obj/machinery/holopad/proc/set_holo(mob/living/user, obj/effect/overlay/holo_pad_hologram/h)
499550
LAZYSET(masters, user, h)
500551
LAZYSET(holorays, user, new /obj/effect/overlay/holoray(loc))
552+
set_can_hear_flags(CAN_HEAR_MASTERS)
501553
var/mob/living/silicon/ai/AI = user
502554
if(istype(AI))
503555
AI.current = src
@@ -518,6 +570,8 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
518570
if(istype(AI) && AI.current == src)
519571
AI.current = null
520572
LAZYREMOVE(masters, user) // Discard AI from the list of those who use holopad
573+
if(!LAZYLEN(masters))
574+
set_can_hear_flags(CAN_HEAR_MASTERS, set_flag = FALSE)
521575
qdel(holorays[user])
522576
LAZYREMOVE(holorays, user)
523577
SetLightsAndPower()
@@ -637,6 +691,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
637691
return
638692
disk.record = new
639693
record_mode = TRUE
694+
set_can_hear_flags(CAN_HEAR_RECORD_MODE)
640695
record_start = world.time
641696
record_user = user
642697
disk.record.set_caller_image(user)
@@ -706,6 +761,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
706761
if(record_mode)
707762
record_mode = FALSE
708763
record_user = null
764+
set_can_hear_flags(CAN_HEAR_RECORD_MODE, FALSE)
709765

710766
/obj/machinery/holopad/proc/record_clear()
711767
if(disk && disk.record)
@@ -748,3 +804,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
748804

749805
#undef HOLOPAD_PASSIVE_POWER_USAGE
750806
#undef HOLOGRAM_POWER_USAGE
807+
#undef CAN_HEAR_MASTERS
808+
#undef CAN_HEAR_ACTIVE_HOLOCALLS
809+
#undef CAN_HEAR_RECORD_MODE
810+
#undef CAN_HEAR_ALL_FLAGS

code/game/machinery/requests_console.dm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ GLOBAL_LIST_EMPTY(req_console_ckey_departments)
115115
GLOB.req_console_ckey_departments[ckey(department)] = department
116116

117117
Radio = new /obj/item/radio(src)
118-
Radio.listening = 0
118+
Radio.set_listening(FALSE)
119119

120120
/obj/machinery/requests_console/Destroy()
121121
QDEL_NULL(Radio)

code/game/machinery/telecomms/broadcasting.dm

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -146,40 +146,48 @@
146146
if(compression > 0)
147147
message = Gibberish(message, compression + 40)
148148

149+
var/list/signal_reaches_every_z_level = levels
150+
151+
if(0 in levels)
152+
signal_reaches_every_z_level = RADIO_NO_Z_LEVEL_RESTRICTION
153+
149154
// Assemble the list of radios
150155
var/list/radios = list()
151156
switch (transmission_method)
152157
if (TRANSMISSION_SUBSPACE)
153158
// Reaches any radios on the levels
154-
for(var/obj/item/radio/R in GLOB.all_radios["[frequency]"])
155-
if(R.can_receive(frequency, levels))
156-
radios += R
159+
var/list/all_radios_of_our_frequency = GLOB.all_radios["[frequency]"]
160+
radios = all_radios_of_our_frequency.Copy()
161+
162+
for(var/obj/item/radio/subspace_radio in radios)
163+
if(!subspace_radio.can_receive(frequency, signal_reaches_every_z_level))
164+
radios -= subspace_radio
157165

158166
// Syndicate radios can hear all well-known radio channels
159167
if (num2text(frequency) in GLOB.reverseradiochannels)
160-
for(var/obj/item/radio/R in GLOB.all_radios["[FREQ_SYNDICATE]"])
161-
if(R.can_receive(FREQ_SYNDICATE, list(R.z)))
162-
radios |= R
168+
for(var/obj/item/radio/syndicate_radios in GLOB.all_radios["[FREQ_SYNDICATE]"])
169+
if(syndicate_radios.can_receive(FREQ_SYNDICATE, RADIO_NO_Z_LEVEL_RESTRICTION))
170+
radios |= syndicate_radios
163171

164172
if (TRANSMISSION_RADIO)
165173
// Only radios not currently in subspace mode
166-
for(var/obj/item/radio/R in GLOB.all_radios["[frequency]"])
167-
if(!R.subspace_transmission && R.can_receive(frequency, levels))
168-
radios += R
174+
for(var/obj/item/radio/non_subspace_radio in GLOB.all_radios["[frequency]"])
175+
if(!non_subspace_radio.subspace_transmission && non_subspace_radio.can_receive(frequency, levels))
176+
radios += non_subspace_radio
169177

170178
if (TRANSMISSION_SUPERSPACE)
171179
// Only radios which are independent
172-
for(var/obj/item/radio/R in GLOB.all_radios["[frequency]"])
173-
if(R.independent && R.can_receive(frequency, levels))
174-
radios += R
180+
for(var/obj/item/radio/independent_radio in GLOB.all_radios["[frequency]"])
181+
if(independent_radio.independent && independent_radio.can_receive(frequency, levels))
182+
radios += independent_radio
175183

176184
// From the list of radios, find all mobs who can hear those.
177-
var/list/receive = get_mobs_in_radio_ranges(radios)
185+
var/list/receive = get_hearers_in_radio_ranges(radios)
178186

179187
// Cut out mobs with clients who are admins and have radio chatter disabled.
180-
for(var/mob/R in receive)
181-
if (R.client && R.client.holder && !(R.client.prefs.chat_toggles & CHAT_RADIO))
182-
receive -= R
188+
for(var/mob/dead/observer/ghost in GLOB.player_list)
189+
if(ghost.client.prefs?.chat_toggles & CHAT_GHOSTRADIO)
190+
receive |= ghost
183191

184192
// Add observers who have ghost radio enabled.
185193
for(var/mob/dead/observer/M in GLOB.player_list)
@@ -191,7 +199,10 @@
191199
var/spans = data["spans"]
192200
var/list/message_mods = data["mods"]
193201
var/rendered = virt.compose_message(virt, language, message, frequency, spans)
194-
for(var/atom/movable/hearer in receive)
202+
for(var/atom/movable/hearer as anything in receive)
203+
if(!hearer)
204+
stack_trace("null found in the hearers list returned by the spatial grid. this is bad")
205+
continue
195206
hearer.Hear(rendered, virt, language, message, frequency, spans, message_mods)
196207

197208
// This following recording is intended for research and feedback in the use of department radio channels
@@ -209,7 +220,7 @@
209220
var/log_text = "\[[get_radio_name(frequency)]\] [spans_part]\"[message]\" (language: [lang_name])"
210221

211222
var/mob/source_mob = virt.source
212-
if(istype(source_mob))
223+
if(ismob(source_mob))
213224
source_mob.log_message(log_text, LOG_TELECOMMS)
214225
else
215226
log_telecomms("[virt.source] [log_text] [loc_name(get_turf(virt.source))]")

code/game/machinery/telecomms/machine_interactions.dm

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@
116116
return
117117
else
118118
for(var/obj/machinery/telecomms/T in links)
119-
T.links.Remove(src)
119+
remove_link(T)
120120
network = params["value"]
121121
links = list()
122122
log_game("[key_name(operator)] has changed the network for [src] at [AREACOORD(src)] to [network].")
@@ -141,22 +141,12 @@
141141
if("unlink")
142142
var/obj/machinery/telecomms/T = links[text2num(params["value"])]
143143
if(T)
144-
// Remove link entries from both T and src.
145-
if(T.links)
146-
T.links.Remove(src)
147-
links.Remove(T)
148-
log_game("[key_name(operator)] unlinked [src] and [T] at [AREACOORD(src)].")
149-
. = TRUE
144+
. = remove_link(T, operator)
145+
150146
if("link")
151147
if(heldmultitool)
152148
var/obj/machinery/telecomms/tcomms_machine = multitool_get_buffer(src, heldmultitool)
153-
if(istype(tcomms_machine) && tcomms_machine != src)
154-
if(!(src in tcomms_machine.links))
155-
tcomms_machine.links += src
156-
if(!(tcomms_machine in links))
157-
links += tcomms_machine
158-
log_game("[key_name(operator)] linked [src] for [tcomms_machine] at [AREACOORD(src)].")
159-
. = TRUE
149+
. = add_new_link(T, operator)
160150
if("buffer") // Yogs start -- holotool support
161151
if(heldmultitool)
162152
multitool_set_buffer(usr, heldmultitool, src)
@@ -169,6 +159,42 @@
169159
add_act(action, params)
170160
. = TRUE
171161

162+
///adds new_connection to src's links list AND vice versa. also updates links_by_telecomms_type
163+
/obj/machinery/telecomms/proc/add_new_link(obj/machinery/telecomms/new_connection, mob/user)
164+
if(!istype(new_connection) || new_connection == src)
165+
return FALSE
166+
167+
if((new_connection in links) && (src in new_connection.links))
168+
return FALSE
169+
170+
links |= new_connection
171+
new_connection.links |= src
172+
173+
LAZYADDASSOCLIST(links_by_telecomms_type, new_connection.telecomms_type, new_connection)
174+
LAZYADDASSOCLIST(new_connection.links_by_telecomms_type, telecomms_type, src)
175+
176+
if(user)
177+
log_game("[key_name(user)] linked [src] for [new_connection] at [AREACOORD(src)].")
178+
return TRUE
179+
180+
///removes old_connection from src's links list AND vice versa. also updates links_by_telecomms_type
181+
/obj/machinery/telecomms/proc/remove_link(obj/machinery/telecomms/old_connection, mob/user)
182+
if(!istype(old_connection) || old_connection == src)
183+
return FALSE
184+
185+
if(old_connection in links)
186+
links -= old_connection
187+
LAZYREMOVEASSOC(links_by_telecomms_type, old_connection.telecomms_type, old_connection)
188+
189+
if(src in old_connection.links)
190+
old_connection.links -= src
191+
LAZYREMOVEASSOC(old_connection.links_by_telecomms_type, telecomms_type, src)
192+
193+
if(user)
194+
log_game("[key_name(user)] unlinked [src] and [old_connection] at [AREACOORD(src)].")
195+
196+
return TRUE
197+
172198
/obj/machinery/telecomms/proc/add_option()
173199
return
174200

code/game/machinery/telecomms/machines/broadcaster.dm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ GLOBAL_VAR_INIT(message_delay, 0) // To make sure restarting the recentmessages
1212
name = "subspace broadcaster"
1313
icon_state = "caster"
1414
desc = "A dish-shaped machine used to broadcast processed subspace signals."
15+
telecomms_type = /obj/machinery/telecomms/broadcaster
1516
density = TRUE
1617
use_power = IDLE_POWER_USE
1718
idle_power_usage = 25

code/game/machinery/telecomms/machines/bus.dm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
name = "bus mainframe"
1313
icon_state = "bus"
1414
desc = "A mighty piece of hardware used to send massive amounts of data quickly."
15+
telecomms_type = /obj/machinery/telecomms/bus
1516
density = TRUE
1617
use_power = IDLE_POWER_USE
1718
idle_power_usage = 50

code/game/machinery/telecomms/machines/hub.dm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
name = "telecommunication hub"
1313
icon_state = "hub"
1414
desc = "A mighty piece of hardware used to send/receive massive amounts of data."
15+
telecomms_type = /obj/machinery/telecomms/hub
1516
density = TRUE
1617
use_power = IDLE_POWER_USE
1718
idle_power_usage = 80

code/game/machinery/telecomms/machines/message_server.dm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
icon_state = "message_server"
7878
name = "Messaging Server"
7979
desc = "A machine that processes and routes PDA and request console messages."
80+
telecomms_type = /obj/machinery/telecomms/message_server
8081
density = TRUE
8182
use_power = IDLE_POWER_USE
8283
idle_power_usage = 10

0 commit comments

Comments
 (0)