From 912ca1e374c8c3394257403888384b48cc1b5404 Mon Sep 17 00:00:00 2001 From: SandPoot Date: Tue, 21 May 2024 00:06:26 -0300 Subject: [PATCH] poosh --- code/modules/client/client_procs.dm | 9 +- .../integrated_electronics/subtypes/output.dm | 13 ++- code/modules/mob/living/silicon/ai/ai.dm | 3 + .../living/silicon/ai/announcement_help.dm | 54 ++++++++++++ code/modules/mob/living/silicon/ai/say.dm | 50 ++--------- .../mob/living/silicon/ai/vox_sounds.dm | 21 +++-- tgstation.dme | 1 + .../tgui/interfaces/AnnouncementHelp.js | 88 +++++++++++++++++++ 8 files changed, 178 insertions(+), 61 deletions(-) create mode 100644 code/modules/mob/living/silicon/ai/announcement_help.dm create mode 100644 tgui/packages/tgui/interfaces/AnnouncementHelp.js diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 0413502edc..4eb836dab5 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -974,10 +974,11 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( addtimer(CALLBACK(SSassets.transport, TYPE_PROC_REF(/datum/asset_transport, send_assets_slow), src, SSassets.transport.preload), 5 SECONDS) #if (PRELOAD_RSC == 0) - for (var/name in GLOB.vox_sounds) - var/file = GLOB.vox_sounds[name] - Export("##action=load_rsc", file) - stoplag() + for (var/type in GLOB.vox_types) + for(var/word in GLOB.vox_types[type]) + var/file = GLOB.vox_types[type][word] + Export("##action=load_rsc", file) + stoplag() #endif diff --git a/code/modules/integrated_electronics/subtypes/output.dm b/code/modules/integrated_electronics/subtypes/output.dm index 9fa816e0d0..518672aed1 100644 --- a/code/modules/integrated_electronics/subtypes/output.dm +++ b/code/modules/integrated_electronics/subtypes/output.dm @@ -226,15 +226,22 @@ spawn_flags = IC_SPAWN_RESEARCH /obj/item/integrated_circuit/output/sound/vox - name = "ai vox sound circuit" + name = "Female ai vox sound circuit" desc = "Takes a sound name as an input, and will play said sound when pulsed. This circuit is often found in AI announcement systems." spawn_flags = IC_SPAWN_RESEARCH + var/voice_type = "Female" /obj/item/integrated_circuit/output/sound/vox/Initialize(mapload) - .= ..() - sounds = GLOB.vox_sounds + . = ..() + sounds = GLOB.vox_types[voice_type] extended_desc = "The first input pin determines which sound is used. It uses the AI Vox Broadcast word list. So either experiment to find words that work, or ask the AI to help in figuring them out. The second pin determines the volume of sound that is played, and the third determines if the frequency of the sound will vary with each activation." +/obj/item/integrated_circuit/output/sound/vox/male + name = "Male ai vox sound circuit" + desc = "Takes a sound name as an input, and will play said sound when pulsed. This circuit is often found in AI announcement systems." + spawn_flags = IC_SPAWN_RESEARCH + voice_type = "Male" + /obj/item/integrated_circuit/output/text_to_speech name = "text-to-speech circuit" desc = "Takes any string as an input and will make the device say the string when pulsed." diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 2c8e3164a9..738a7ab17b 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -104,6 +104,8 @@ // TODO: Currently unused, needs port from TG. /// Station alert datum for showing alerts UI var/datum/station_alert/alert_control + /// Lists possible spoken words for announcements + var/datum/announcement_help/announcement_help ///remember AI's last location var/atom/lastloc interaction_range = INFINITY @@ -204,6 +206,7 @@ QDEL_NULL(doomsday_device) QDEL_NULL(robot_control) // QDEL_NULL(alert_control) + QDEL_NULL(announcement_help) QDEL_NULL(aiMulti) QDEL_NULL(aiPDA) malfhack = null diff --git a/code/modules/mob/living/silicon/ai/announcement_help.dm b/code/modules/mob/living/silicon/ai/announcement_help.dm new file mode 100644 index 0000000000..f22b3ce4cb --- /dev/null +++ b/code/modules/mob/living/silicon/ai/announcement_help.dm @@ -0,0 +1,54 @@ +#ifdef AI_VOX +/mob/living/silicon/ai/verb/announcement_help() + + set name = "Announcement Help" + set desc = "Display a list of vocal words to announce to the crew." + set category = "AI Commands" + + if(incapacitated()) + return + + if(!announcement_help) + announcement_help = new(src) + + announcement_help.ui_interact(src) + +/datum/announcement_help + var/mob/living/silicon/ai/owner + +/datum/announcement_help/New(mob/living/silicon/ai/new_owner) + if(!istype(new_owner)) + qdel(src) + owner = new_owner + +/datum/announcement_help/ui_status(mob/living/silicon/ai/user) + if(owner == user && !owner.incapacitated()) + return ..() + return UI_CLOSE + +/datum/announcement_help/ui_state(mob/user) + return GLOB.always_state + +/datum/announcement_help/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "AnnouncementHelp") + ui.open() + +/datum/announcement_help/ui_static_data(mob/user) + var/list/data = ..() + data["vox_types"] = GLOB.vox_types + return data + +/datum/announcement_help/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + switch(action) + if("say_word") + var/vox_type = params["vox_type"] + if(!vox_type) + return + var/to_speak = params["to_speak"] + if(!to_speak) + return + play_vox_word(to_speak, null, owner, vox_type) +#endif diff --git a/code/modules/mob/living/silicon/ai/say.dm b/code/modules/mob/living/silicon/ai/say.dm index e23eb842ea..6cb3af5363 100644 --- a/code/modules/mob/living/silicon/ai/say.dm +++ b/code/modules/mob/living/silicon/ai/say.dm @@ -80,38 +80,6 @@ // Make sure that the code compiles with AI_VOX undefined #ifdef AI_VOX #define VOX_DELAY 600 -/mob/living/silicon/ai/verb/announcement_help() - - set name = "Announcement Help" - set desc = "Display a list of vocal words to announce to the crew." - set category = "AI Commands" - - if(incapacitated()) - return - - var/dat = {" - WARNING: Misuse of the announcement system will get you job banned.

- Here is a list of words you can type into the 'Announcement' button to create sentences to vocally announce to everyone on the same level at you.
-
- "} - - var/index = 0 - for(var/word in GLOB.vox_sounds) - index++ - dat += "[capitalize(word)]" - if(index != GLOB.vox_sounds.len) - dat += " / " - - var/datum/browser/popup = new(src, "announce_help", "Announcement Help", 500, 400) - popup.set_content(dat) - popup.open() - - /mob/living/silicon/ai/proc/announcement() var/static/announcing_vox = 0 // Stores the time of the last announcement if(announcing_vox > world.time) @@ -122,7 +90,7 @@ last_announcement = message - var/voxType = input(src, "Male or female VOX?", "VOX-gender") in list("male", "female") + var/voxType = input(src, "Male or female VOX?", "VOX-gender") in GLOB.vox_types if(!message || announcing_vox > world.time) return @@ -145,9 +113,7 @@ if(!word) words -= word continue - if(!GLOB.vox_sounds[word] && voxType == "female") - incorrect_words += word - if(!GLOB.vox_sounds_male[word] && voxType == "male") + if(!GLOB.vox_types[voxType][word]) incorrect_words += word if(incorrect_words.len) @@ -162,18 +128,12 @@ play_vox_word(word, src.z, null, voxType) -/proc/play_vox_word(word, z_level, mob/only_listener, voxType = "female") +/proc/play_vox_word(word, z_level, mob/only_listener, voxType = "Female") word = lowertext(word) - if( (GLOB.vox_sounds[word] && voxType == "female") || (GLOB.vox_sounds_male[word] && voxType == "male") ) - - var/sound_file - - if(voxType == "female") - sound_file = GLOB.vox_sounds[word] - else - sound_file = GLOB.vox_sounds_male[word] + var/sound_file = LAZYACCESSASSOC(GLOB.vox_types, voxType, word) + if(sound_file) var/sound/voice = sound(sound_file, wait = 1, channel = CHANNEL_VOX) voice.status = SOUND_STREAM diff --git a/code/modules/mob/living/silicon/ai/vox_sounds.dm b/code/modules/mob/living/silicon/ai/vox_sounds.dm index 057561562b..8959d49e9a 100644 --- a/code/modules/mob/living/silicon/ai/vox_sounds.dm +++ b/code/modules/mob/living/silicon/ai/vox_sounds.dm @@ -5,9 +5,11 @@ // Regex for collecting a list of ogg files // (([a-zA-Z,.]+)\.ogg) -// For vim -// :%s/\(\(.*\)\.ogg\)/"\2" = 'sound\/vox_fem\/\1',/g -GLOBAL_LIST_INIT(vox_sounds, list("abduction" = 'sound/vox_fem/abduction.ogg', +GLOBAL_LIST_INIT(vox_types, list( + // For vim + // :%s/\(\(.*\)\.ogg\)/"\2" = 'sound\/vox_fem\/\1',/g + "Female" = list( +"abduction" = 'sound/vox_fem/abduction.ogg', "abortions" = 'sound/vox_fem/abortions.ogg', "above" = 'sound/vox_fem/above.ogg', "abstain" = 'sound/vox_fem/abstain.ogg', @@ -974,11 +976,11 @@ GLOBAL_LIST_INIT(vox_sounds, list("abduction" = 'sound/vox_fem/abduction.ogg', "z" = 'sound/vox_fem/z.ogg', "zombie" = 'sound/vox_fem/zombie.ogg', "zone" = 'sound/vox_fem/zone.ogg', -"zulu" = 'sound/vox_fem/zulu.ogg')) - -//for vim -// :%s/\(\(.*\)\.ogg\)/"\2" = 'sound\/vox\/\1',/g -GLOBAL_LIST_INIT(vox_sounds_male, list("," = 'sound/vox/_comma.ogg', +"zulu" = 'sound/vox_fem/zulu.ogg'), + //for vim + // :%s/\(\(.*\)\.ogg\)/"\2" = 'sound\/vox\/\1',/g + "Male" = list( +"," = 'sound/vox/_comma.ogg', "." = 'sound/vox/_period.ogg', "a" = 'sound/vox/a.ogg', "accelerating" = 'sound/vox/accelerating.ogg', @@ -1605,5 +1607,6 @@ GLOBAL_LIST_INIT(vox_sounds_male, list("," = 'sound/vox/_comma.ogg', "yourself" = 'sound/vox/yourself.ogg', "zero" = 'sound/vox/zero.ogg', "zone" = 'sound/vox/zone.ogg', -"zulu" = 'sound/vox/zulu.ogg',)) +"zulu" = 'sound/vox/zulu.ogg', +))) #endif diff --git a/tgstation.dme b/tgstation.dme index a201f09456..f0a2de7c7d 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -2832,6 +2832,7 @@ #include "code\modules\mob\living\silicon\ai\ai.dm" #include "code\modules\mob\living\silicon\ai\ai_defense.dm" #include "code\modules\mob\living\silicon\ai\ai_portrait_picker.dm" +#include "code\modules\mob\living\silicon\ai\announcement_help.dm" #include "code\modules\mob\living\silicon\ai\death.dm" #include "code\modules\mob\living\silicon\ai\emote.dm" #include "code\modules\mob\living\silicon\ai\examine.dm" diff --git a/tgui/packages/tgui/interfaces/AnnouncementHelp.js b/tgui/packages/tgui/interfaces/AnnouncementHelp.js new file mode 100644 index 0000000000..671e1f2b7a --- /dev/null +++ b/tgui/packages/tgui/interfaces/AnnouncementHelp.js @@ -0,0 +1,88 @@ +import { filter } from 'common/collections'; +import { flow } from 'common/fp'; +import { createSearch } from 'common/string'; +import { useBackend } from '../backend'; +import { Button, Icon, Input, Section, Stack, Tabs } from '../components'; +import { useLocalState } from '../backend'; +import { Window } from '../layouts'; + +export const AnnouncementHelp = (props, context) => { + const { act, data } = useBackend(context); + const { vox_types = {} } = data; + + const [ + current_page, + set_page, + ] = useLocalState(context, 'current_page', 0); + + const [ + search_text, + set_search_text, + ] = useLocalState(context, 'search_text', ''); + + // I love `Object`s!! + const words_filtered = prepare_search(Object.keys(vox_types[Object.keys(vox_types)[current_page]]), search_text); + + return ( + + +
+ + + + { + Object.keys(vox_types).map((vox_type, index) => ( + set_page(index)} + selected={current_page === index}> + {vox_type} + + )) + } + + + + + + + + + set_search_text(value)} + /> + + + + + {words_filtered.map(nestedKey => ( + + ))} + + +
+
+
+ ); +}; + +export const prepare_search = (words_filtered, search_text = '') => { + const search = createSearch(search_text, + word_soup => word_soup); + return flow([ + search_text && filter(search), + ])(words_filtered); +};