From db18074f9028f71a0070d84519440fb32a9ee74a Mon Sep 17 00:00:00 2001 From: Atlantiscze Date: Tue, 15 Jul 2014 23:00:24 +0200 Subject: [PATCH] Designed to replace AI's intercoms. Integrated headset-like device which has access to all department frequencies. Also let's AIs use radio on intellicard. AI's communication can however be disabled by using intellicard option. Communication will be disabled until it is restored via intellicard again, even if the AI is moved back into physical core. ICly it's software lock which prevents the AI from using communication circuits which are standard in all AI cores/intellicards/etc. This does not stop AI from using intercom, however. Forum link: http://baystation12.net/forums/viewtopic.php?f=5&t=6536&start=1260 --- code/game/objects/items/devices/aicard.dm | 10 +++++++++ .../items/devices/radio/encryptionkey.dm | 6 +++++ .../objects/items/devices/radio/headset.dm | 18 ++++++++++++++- code/modules/mob/living/say.dm | 21 +++++++++--------- code/modules/mob/living/silicon/ai/ai.dm | 14 +++++++++++- code/modules/mob/living/silicon/say.dm | 13 ++++++++--- icons/obj/radio.dmi | Bin 6121 -> 6379 bytes 7 files changed, 67 insertions(+), 15 deletions(-) diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm index 43daf35b323..204b94cc3dd 100644 --- a/code/game/objects/items/devices/aicard.dm +++ b/code/game/objects/items/devices/aicard.dm @@ -71,6 +71,10 @@ dat += "
" dat += {"[A.control_disabled ? "Enable" : "Disable"] Wireless Activity"} dat += "
" + dat += "Subspace Transceiver is: [A.aiRadio.disabledAi ? "Disabled" : "Enabled"]" + dat += "
" + dat += {"[A.aiRadio.disabledAi ? "Enable" : "Disable"] Subspace Transceiver"} + dat += "
" dat += {" Close"} user << browse(dat, "window=aicard") onclose(user, "aicard") @@ -92,6 +96,12 @@ U.unset_machine() return + if ("Radio") + for(var/mob/living/silicon/ai/A in src) + A.aiRadio.disabledAi = !A.aiRadio.disabledAi + A << "Your Subspace Transceiver has been: [A.aiRadio.disabledAi ? "disabled" : "enabled"]" + U << "You [A.aiRadio.disabledAi ? "Disable" : "Enable"] the AI's Subspace Transceiver" + if ("Wipe") var/confirm = alert("Are you sure you want to wipe this card's memory? This cannot be undone once started.", "Confirm Wipe", "Yes", "No") if(confirm == "Yes") diff --git a/code/game/objects/items/devices/radio/encryptionkey.dm b/code/game/objects/items/devices/radio/encryptionkey.dm index d2d5417d6c3..287e8272497 100644 --- a/code/game/objects/items/devices/radio/encryptionkey.dm +++ b/code/game/objects/items/devices/radio/encryptionkey.dm @@ -74,6 +74,12 @@ icon_state = "cap_cypherkey" channels = list("Command" = 1, "Security" = 1, "Engineering" = 0, "Science" = 0, "Medical" = 0, "Supply" = 0) +/obj/item/device/encryptionkey/heads/ai_integrated + name = "AI Integrated Encryption Key" + desc = "Integrated encryption key" + icon_state = "cap_cypherkey" + channels = list("Command" = 1, "Security" = 1, "Engineering" = 1, "Science" = 1, "Medical" = 1, "Supply" = 1) + /obj/item/device/encryptionkey/heads/rd name = "Research Director's Encryption Key" desc = "An encyption key for a radio headset. Contains cypherkeys." diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index ed59e439895..ab376e4825d 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -19,7 +19,9 @@ keyslot1 = new /obj/item/device/encryptionkey/ recalculateChannels() -/obj/item/device/radio/headset/receive_range(freq, level) +/obj/item/device/radio/headset/receive_range(freq, level, aiOverride = 0) + if (aiOverride) + return ..(freq, level) if(ishuman(src.loc)) var/mob/living/carbon/human/H = src.loc if(H.l_ear == src || H.r_ear == src) @@ -99,6 +101,20 @@ item_state = "headset" keyslot2 = new /obj/item/device/encryptionkey/heads/captain +/obj/item/device/radio/headset/heads/ai_integrated //No need to care about icons, it should be hidden inside the AI anyway. + name = "AI Subspace Transceiver" + desc = "Integrated AI radio transceiver." + icon_state = "ai_radio" + item_state = "headset" + keyslot2 = new /obj/item/device/encryptionkey/heads/ai_integrated + var/myAi = null // Atlantis: Reference back to the AI which has this radio. + var/disabledAi = 0 // Atlantis: Used to manually disable AI's integrated radio via intellicard menu. + +/obj/item/device/radio/headset/heads/ai_integrated/receive_range(freq, level) + if (disabledAi) + return -1 //Transciever Disabled. + return ..(freq, level, 1) + /obj/item/device/radio/headset/heads/rd name = "Research Director's headset" desc = "Headset of the researching God. To access the science channel, use :n. For command, use :c." diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index b439c0d4753..2e819928262 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -84,28 +84,29 @@ var/list/department_radio_keys = list( /mob/living/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/italics=0, var/message_range = world.view, var/list/used_radios = list(), var/sound/speech_sound, var/sound_vol) var/turf/T = get_turf(src) - + //handle nonverbal and sign languages here if (speaking) if (speaking.flags & NONVERBAL) if (prob(30)) src.custom_emote(1, "[pick(speaking.signlang_verb)].") - + if (speaking.flags & SIGNLANG) say_signlang(message, pick(speaking.signlang_verb), speaking) return - + //speaking into radios if(used_radios.len) italics = 1 message_range = 1 - - for(var/mob/living/M in hearers(5, src)) - if(M != src) - M.show_message("[src] talks into [used_radios.len ? used_radios[1] : "the radio."]") - if (speech_sound) - src.playsound_local(get_turf(src), speech_sound, sound_vol * 0.5, 1) - + + if (!istype(src, /mob/living/silicon/ai)) // Atlantis: Prevents nearby people from hearing the AI when it talks using it's integrated radio. + for(var/mob/living/M in hearers(5, src)) + if(M != src) + M.show_message("[src] talks into [used_radios.len ? used_radios[1] : "the radio."]") + if (speech_sound) + src.playsound_local(get_turf(src), speech_sound, sound_vol * 0.5, 1) + speech_sound = null //so we don't play it twice. //make sure the air can transmit speech diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index b34f7aa6411..44da5d74af6 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -30,6 +30,7 @@ var/list/ai_list = list() var/icon/holo_icon//Default is assigned when AI is created. var/obj/item/device/pda/ai/aiPDA = null var/obj/item/device/multitool/aiMulti = null + var/obj/item/device/radio/headset/heads/ai_integrated/aiRadio = null var/custom_sprite = 0 //For our custom sprites //Hud stuff @@ -87,12 +88,14 @@ var/list/ai_list = list() aiPDA.name = name + " (" + aiPDA.ownjob + ")" aiMulti = new(src) + aiRadio = new(src) + aiRadio.myAi = src if (istype(loc, /turf)) verbs.Add(/mob/living/silicon/ai/proc/ai_call_shuttle,/mob/living/silicon/ai/proc/ai_camera_track, \ /mob/living/silicon/ai/proc/ai_camera_list, /mob/living/silicon/ai/proc/ai_network_change, \ /mob/living/silicon/ai/proc/ai_statuschange, /mob/living/silicon/ai/proc/ai_hologram_change, \ - /mob/living/silicon/ai/proc/toggle_camera_light) + /mob/living/silicon/ai/proc/toggle_camera_light, /mob/living/silicon/ai/proc/control_integrateed_radio) //Languages add_language("Sol Common", 0) @@ -738,3 +741,12 @@ var/list/ai_list = list() return else return ..() + +/mob/living/silicon/ai/proc/control_integrateed_radio() + set name = "Radio Settings" + set desc = "Allows you to change settings of your radio." + set category = "AI Commands" + + src << "Accessing Subspace Transceiver control..." + if (src.aiRadio) + src.aiRadio.interact(src) \ No newline at end of file diff --git a/code/modules/mob/living/silicon/say.dm b/code/modules/mob/living/silicon/say.dm index 0811a52cd88..67ca178e893 100644 --- a/code/modules/mob/living/silicon/say.dm +++ b/code/modules/mob/living/silicon/say.dm @@ -109,7 +109,11 @@ if("general") switch(bot_type) if(IS_AI) - src << "Yeah, not yet, sorry" + if (AI.aiRadio.disabledAi) + src << "\red System Error - Transceiver Disabled" + else + log_say("[key_name(src)] : [message]") + AI.aiRadio.talk_into(src,message,null,verb,speaking) if(IS_ROBOT) log_say("[key_name(src)] : [message]") R.radio.talk_into(src,message,null,verb,speaking) @@ -122,8 +126,11 @@ if(message_mode && message_mode in radiochannels) switch(bot_type) if(IS_AI) - src << "You don't have this function yet, I'm working on it" - return + if (AI.aiRadio.disabledAi) + src << "\red System Error - Transceiver Disabled" + else + log_say("[key_name(src)] : [message]") + AI.aiRadio.talk_into(src,message,message_mode,verb,speaking) if(IS_ROBOT) log_say("[key_name(src)] : [message]") R.radio.talk_into(src,message,message_mode,verb,speaking) diff --git a/icons/obj/radio.dmi b/icons/obj/radio.dmi index 9c4830d273cb40f43ab3ece84db41eeee1817357..b0b250a18b857c4187a5ca9b361a3dc94220a1ee 100644 GIT binary patch literal 6379 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 literal 6121 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