diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index fae5ed34135..644fb5be84e 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -231,31 +231,91 @@ var/global/list/default_interrogation_channels = list( return ui_interact(user) -/obj/item/radio/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] +/obj/item/radio/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Radio", "[name]") + ui.open() +/obj/item/radio/ui_data(mob/user) + var/list/data = list() data["mic_status"] = broadcasting data["speaker"] = listening - data["freq"] = format_frequency(frequency) - data["default_freq"] = format_frequency(default_frequency) - data["rawfreq"] = num2text(frequency) + data["freq"] = frequency + data["default_freq"] = default_frequency + data["rawfreq"] = frequency data["mic_cut"] = (wires.is_cut(WIRE_TRANSMIT) || wires.is_cut(WIRE_SIGNAL)) data["spk_cut"] = (wires.is_cut(WIRE_RECEIVE) || wires.is_cut(WIRE_SIGNAL)) - var/list/chanlist = list_channels(user) - if(islist(chanlist) && chanlist.len) - data["chan_list"] = chanlist - data["chan_list_len"] = chanlist.len + var/list/chl = list_channels(user) + if(LAZYLEN(chl)) + data["channels"] = chl if(syndie) - data["useSyndMode"] = 1 + data["syndie"] = TRUE - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - ui = new(user, src, ui_key, "radio_basic.tmpl", "[name]", 400, 430) - ui.set_initial_data(data) - ui.open() + return data + +/obj/item/radio/ui_static_data(mob/user) + var/list/data = list() + + data["min_freq"] = PUBLIC_LOW_FREQ + data["max_freq"] = PUBLIC_HIGH_FREQ + + return data + +/obj/item/radio/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + if(..()) + return TRUE + + if(action == "start_track") + var/mob/target = locate(params["target"]) + var/mob/living/silicon/ai/A = locate(params["ai"]) + if(A && target) + A.ai_actual_track(target) + . = TRUE + + else if (action == "set_freq") + var/new_freq = text2num(params["freq"]) + if ((new_freq < PUBLIC_LOW_FREQ || new_freq > PUBLIC_HIGH_FREQ)) + new_freq = sanitize_frequency(new_freq) + set_frequency(new_freq) + if(hidden_uplink) + if(hidden_uplink.check_trigger(usr, frequency, traitor_frequency)) + ui.close() + . = TRUE + else if (action == "toggle_talk") + set_broadcasting(!broadcasting) + . = TRUE + else if (action == "toggle_listen") + var/channel_name = num2text(params["channel_name"]) + if(channel_name == "0") + set_listening(!listening) + else + channel_name = reverseradiochannels[channel_name] + if (channels[channel_name] & FREQ_LISTENING) + channels[channel_name] &= ~FREQ_LISTENING + else + channels[channel_name] |= FREQ_LISTENING + . = TRUE + else if (action == "spec_freq") + var/freq = params["freq"] + if(has_channel_access(usr, freq)) + set_frequency(text2num(freq)) + . = TRUE + else if (action == "reset_freq") + if(default_frequency) + set_frequency(default_frequency) + . = TRUE + + if (params["nowindow"]) + return TRUE + + if(.) + update_icon() + if(clicksound && iscarbon(usr)) + playsound(loc, clicksound, clickvol) /obj/item/radio/proc/setupRadioDescription(var/additional_radio_desc) var/radio_text = "" @@ -284,9 +344,9 @@ var/global/list/default_interrogation_channels = list( for(var/ch_name in channels) var/chan_stat = channels[ch_name] - var/listening = !!(chan_stat & FREQ_LISTENING) != 0 + var/listening = chan_stat & FREQ_LISTENING - dat.Add(list(list("chan" = ch_name, "display_name" = ch_name, "secure_channel" = 1, "sec_channel_listen" = !listening, "chan_span" = frequency_span_class(radiochannels[ch_name])))) + dat.Add(list(list("chan" = radiochannels[ch_name], "display_name" = ch_name, "secure_channel" = 1, "sec_channel_listen" = listening, "chan_span" = frequency_span_class(radiochannels[ch_name])))) return dat @@ -294,7 +354,7 @@ var/global/list/default_interrogation_channels = list( var/dat[0] for(var/internal_chan in internal_channels) if(has_channel_access(user, internal_chan)) - dat.Add(list(list("chan" = internal_chan, "display_name" = get_frequency_name(text2num(internal_chan)), "chan_span" = frequency_span_class(text2num(internal_chan))))) + dat.Add(list(list("chan" = text2num(internal_chan), "display_name" = get_frequency_name(text2num(internal_chan)), "chan_span" = frequency_span_class(text2num(internal_chan))))) return dat @@ -327,67 +387,11 @@ var/global/list/default_interrogation_channels = list( Speaker: [list ? "Engaged" : "Disengaged"]
"} -/obj/item/radio/CanUseTopic() +/obj/item/radio/ui_status(mob/user, datum/ui_state/state) if(!on) - return STATUS_CLOSE + return UI_CLOSE return ..() -/obj/item/radio/CouldUseTopic(var/mob/user) - ..() - if(clicksound && iscarbon(user)) - playsound(loc, clicksound, clickvol) - -/obj/item/radio/Topic(href, href_list) - if(..()) - return TRUE - - usr.set_machine(src) - if (href_list["track"]) - var/mob/target = locate(href_list["track"]) - var/mob/living/silicon/ai/A = locate(href_list["track2"]) - if(A && target) - A.ai_actual_track(target) - . = TRUE - - else if (href_list["freq"]) - var/new_frequency = (frequency + text2num(href_list["freq"])) - if ((new_frequency < PUBLIC_LOW_FREQ || new_frequency > PUBLIC_HIGH_FREQ)) - new_frequency = sanitize_frequency(new_frequency) - set_frequency(new_frequency) - if(hidden_uplink) - if(hidden_uplink.check_trigger(usr, frequency, traitor_frequency)) - usr << browse(null, "window=radio") - . = TRUE - else if (href_list["talk"]) - set_broadcasting(!broadcasting) - . = TRUE - else if (href_list["listen"]) - var/chan_name = href_list["ch_name"] - if (!chan_name) - set_listening(!listening) - else - if (channels[chan_name] & FREQ_LISTENING) - channels[chan_name] &= ~FREQ_LISTENING - else - channels[chan_name] |= FREQ_LISTENING - . = TRUE - else if(href_list["spec_freq"]) - var freq = href_list["spec_freq"] - if(has_channel_access(usr, freq)) - set_frequency(text2num(freq)) - . = TRUE - else if(href_list["reset_freq"]) - if(default_frequency) - set_frequency(default_frequency) - . = TRUE - - if(href_list["nowindow"]) // here for pAIs, maybe others will want it, idk - return TRUE - - if(.) - SSnanoui.update_uis(src) - update_icon() - /obj/item/radio/proc/autosay(var/message, var/from, var/channel) //BS12 EDIT var/datum/radio_frequency/connection = null if(channel && channels && channels.len > 0) @@ -672,71 +676,36 @@ var/global/list/default_interrogation_channels = list( setupRadioDescription() return -/obj/item/radio/borg/Topic(href, href_list) +/obj/item/radio/borg/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) if(..()) - return 1 - if (href_list["mode"]) - var/enable_subspace_transmission = text2num(href_list["mode"]) - if(enable_subspace_transmission != subspace_transmission) - subspace_transmission = !subspace_transmission - if(subspace_transmission) - to_chat(usr, SPAN_NOTICE("Subspace Transmission is enabled")) - else - to_chat(usr, SPAN_NOTICE("Subspace Transmission is disabled")) + return TRUE + if (action == "mode") + subspace_transmission = !subspace_transmission + to_chat(usr, SPAN_NOTICE("Subspace Transmission [subspace_transmission ? "enabled" : "disabled"].")) + if(subspace_transmission) + recalculateChannels() + else + channels = list() + . = TRUE + if (action == "shutup") // Toggle loudspeaker mode, AKA everyone around you hearing your radio. + shut_up = !shut_up + canhear_range = shut_up ? 0 : 3 + to_chat(usr, SPAN_NOTICE("Loudspeaker [shut_up ? "disabled" : "enabled"].")) + . = TRUE - if(subspace_transmission == 0)//Simple as fuck, clears the channel list to prevent talking/listening over them if subspace transmission is disabled - channels = list() - else - recalculateChannels() - . = 1 - if (href_list["shutup"]) // Toggle loudspeaker mode, AKA everyone around you hearing your radio. - var/do_shut_up = text2num(href_list["shutup"]) - if(do_shut_up != shut_up) - shut_up = !shut_up - if(shut_up) - canhear_range = 0 - to_chat(usr, SPAN_NOTICE("Loadspeaker disabled.")) - else - canhear_range = 3 - to_chat(usr, SPAN_NOTICE("Loadspeaker enabled.")) - . = 1 +/obj/item/radio/borg/ui_data(mob/user) + var/list/data = ..() - if(.) - SSnanoui.update_uis(src) - -/obj/item/radio/borg/interact(mob/user as mob) - if(!on) - return - - . = ..() - -/obj/item/radio/borg/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] - - data["mic_status"] = broadcasting - data["speaker"] = listening - data["freq"] = format_frequency(frequency) - data["default_freq"] = format_frequency(default_frequency) - data["rawfreq"] = num2text(frequency) - - var/list/chanlist = list_channels(user) - if(islist(chanlist) && chanlist.len) - data["chan_list"] = chanlist - data["chan_list_len"] = chanlist.len - - if(syndie) - data["useSyndMode"] = 1 - - data["has_loudspeaker"] = 1 data["loudspeaker"] = !shut_up - data["has_subspace"] = 1 data["subspace"] = subspace_transmission - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - ui = new(user, src, ui_key, "radio_basic.tmpl", "[name]", 400, 430) - ui.set_initial_data(data) - ui.open() + return data + +/obj/item/radio/borg/ui_static_data(mob/user) + var/list/data = ..() + data["has_loudspeaker"] = TRUE + data["has_subspace"] = TRUE + return data /obj/item/radio/proc/config(op) if(SSradio) diff --git a/code/modules/modular_computers/file_system/programs/pai/radio.dm b/code/modules/modular_computers/file_system/programs/pai/radio.dm index 6fe22519019..06fa59fa678 100644 --- a/code/modules/modular_computers/file_system/programs/pai/radio.dm +++ b/code/modules/modular_computers/file_system/programs/pai/radio.dm @@ -54,5 +54,5 @@ if(action == "radio_range") //fuck nanoUI and fuck vueui two-way bullshit, and fuck topic hooking host.radio.canhear_range = params["radio_range"] else - host.radio.Topic(action, params) + host.radio.ui_act(action, params, ui, state) . = TRUE diff --git a/html/changelogs/johnwildkins-radio.yml b/html/changelogs/johnwildkins-radio.yml new file mode 100644 index 00000000000..01dac4d69ca --- /dev/null +++ b/html/changelogs/johnwildkins-radio.yml @@ -0,0 +1,13 @@ +# Your name. +author: JohnWildkins + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, this gets changed to [] after reading. Just remove the brackets when you add new shit. +# Please surround your changes in double quotes ("). It works without them, but if you use certain characters it screws up compiling. The quotes will not show up in the changelog. +changes: + - rscadd: "Converted radio/headset interface to TGUI." diff --git a/nano/templates/radio_basic.tmpl b/nano/templates/radio_basic.tmpl deleted file mode 100644 index ceb02b3644a..00000000000 --- a/nano/templates/radio_basic.tmpl +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - -{{if data.useSyndMode}} - {{:helper.syndicateMode()}} -{{/if}} - -
-
- Microphone -
-
- {{if data.mic_cut}} - {{:helper.link('On', null, null, 'disabled')}} - {{:helper.link('Off', null, null, 'disabled')}} - {{else}} - {{:helper.link('On', null, {'talk' : 0}, data.mic_status ? 'selected' : null)}} - {{:helper.link('Off', null, {'talk' : 1}, data.mic_status ? null : 'selected')}} - {{/if}} -
-
- -
-
- Speaker -
-
- {{if data.spk_cut}} - {{:helper.link('On', null, null, 'disabled')}} - {{:helper.link('Off', null, null, 'disabled')}} - {{else}} - {{:helper.link('On', null, {'listen' : 0}, data.speaker ? 'selected' : null)}} - {{:helper.link('Off', null, {'listen' : 1}, data.speaker ? null : 'selected')}} - {{/if}} -
-
- -{{if data.has_subspace}} -
-
- Subspace Transmission: -
-
- {{:helper.link('On', null, {'mode' : 1}, data.subspace ? 'selected' : null)}} - {{:helper.link('Off', null, {'mode' : 0}, data.subspace ? null : 'selected')}} -
-
-{{/if}} - -{{if data.has_loudspeaker}} -
-
- Loudspeaker: -
-
- {{:helper.link('On', null, {'shutup' : 0}, data.loudspeaker ? 'selected' : null)}} - {{:helper.link('Off', null, {'shutup' : 1}, data.loudspeaker ? null : 'selected')}} -
-
-{{/if}} - -
-
- Frequency: {{:data.freq}} -
-
- {{:helper.link('--', null, {'freq' : -10})}} - {{:helper.link('-', null, {'freq' : -2})}} - {{:helper.link('+', null, {'freq' : 2})}} - {{:helper.link('++', null, {'freq' : 10})}} - {{if data.default_freq}} - {{:helper.link(data.default_freq, null, {'default_freq' : 1})}} - {{/if}} -
-
- -{{if data.chan_list_len >= 1}} -

Channels

-
- {{for data.chan_list}} -
- {{:value.display_name}} -
-
- {{if value.secure_channel}} - {{:helper.link('On', null, {'ch_name' : value.chan, 'listen' : value.sec_channel_listen}, value.sec_channel_listen ? null : 'selected')}} - {{:helper.link('Off', null, {'ch_name' : value.chan, 'listen' : value.sec_channel_listen}, value.sec_channel_listen ? 'selected' : null)}} - {{else}} - {{:helper.link('Switch', null, {'spec_freq' : value.chan}, data.rawfreq == value.chan ? 'selected' : null)}} - {{/if}} -
- {{/for}} -{{/if}} diff --git a/tgui/packages/tgui/interfaces/Radio.tsx b/tgui/packages/tgui/interfaces/Radio.tsx new file mode 100644 index 00000000000..2709397e1ba --- /dev/null +++ b/tgui/packages/tgui/interfaces/Radio.tsx @@ -0,0 +1,181 @@ +import { toFixed } from 'common/math'; +import { BooleanLike } from 'common/react'; +import { useBackend } from '../backend'; +import { Section, LabeledList, Button, Box, NumberInput } from '../components'; +import { Window } from '../layouts'; + +type Channel = { + chan: number; + display_name: string; + chan_span: string; + secure_channel?: BooleanLike; + sec_channel_listen?: BooleanLike; +}; + +type RadioData = { + mic_status: BooleanLike; + speaker: BooleanLike; + freq: number; + default_freq: number; + rawfreq: number; + + min_freq: number; + max_freq: number; + + mic_cut: BooleanLike; + spk_cut: BooleanLike; + + channels?: Channel[]; + + syndie?: BooleanLike; + + has_loudspeaker?: BooleanLike; + has_subspace?: BooleanLike; + loudspeaker?: BooleanLike; + subspace?: BooleanLike; +}; + +export const Radio = (props, context) => { + const { act, data } = useBackend(context); + const { + mic_status, + speaker, + freq, + default_freq, + rawfreq, + min_freq, + max_freq, + has_loudspeaker, + loudspeaker, + has_subspace, + subspace, + channels, + mic_cut, + spk_cut, + } = data; + const tunedChannel = channels?.find((channel) => channel.chan === freq); + // Calculate window height + let height = 133; + if (channels && channels.length > 0) { + height += channels.length * 30 + 8; + } else { + height += 24; + } + + return ( + + +
+ + + toFixed(value, 1)} + onChange={(_, value) => + act('set_freq', { + freq: value * 10, + }) + } + /> + {default_freq && ( + +
+ {channels && ( +
+ + {channels.map((channel) => ( + + {channel.display_name} + + } + > + {channel.secure_channel ? ( +
+ )} +
+
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/pAIRadio.tsx b/tgui/packages/tgui/interfaces/pAIRadio.tsx index b810dfbbbaa..e802710bfea 100644 --- a/tgui/packages/tgui/interfaces/pAIRadio.tsx +++ b/tgui/packages/tgui/interfaces/pAIRadio.tsx @@ -27,26 +27,26 @@ export const pAIRadio = (props, context) => {