mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-28 10:01:58 +00:00
## About The Pull Request Radio jammers can now disable someone's radio mic, both in AOE (right self-click on cooldown) and for on a specific target. For this to work headsets had to be adjusted to require broadcasting to be active in order to use their mic (it is now active by default and doesn't pick up nearby speech automatically). ## Why It's Good For The Game Jammers aren't very strong and this buff will allow for better stealth gameplay, as you cannot tell that you've been jammed this way until its too late as you still can hear others' speech. Requested by Mothblocks on discord (thus no GBP label). ## Changelog 🆑 add: Jammers can now disable players' radio microphones via a new secondary ability, both for handhelds and headsets /🆑
487 lines
17 KiB
Plaintext
487 lines
17 KiB
Plaintext
// Used for translating channels to tokens on examination
|
|
GLOBAL_LIST_INIT(channel_tokens, list(
|
|
RADIO_CHANNEL_COMMON = RADIO_KEY_COMMON,
|
|
RADIO_CHANNEL_SCIENCE = RADIO_TOKEN_SCIENCE,
|
|
RADIO_CHANNEL_COMMAND = RADIO_TOKEN_COMMAND,
|
|
RADIO_CHANNEL_MEDICAL = RADIO_TOKEN_MEDICAL,
|
|
RADIO_CHANNEL_ENGINEERING = RADIO_TOKEN_ENGINEERING,
|
|
RADIO_CHANNEL_SECURITY = RADIO_TOKEN_SECURITY,
|
|
RADIO_CHANNEL_CENTCOM = RADIO_TOKEN_CENTCOM,
|
|
RADIO_CHANNEL_SYNDICATE = RADIO_TOKEN_SYNDICATE,
|
|
RADIO_CHANNEL_SUPPLY = RADIO_TOKEN_SUPPLY,
|
|
RADIO_CHANNEL_SERVICE = RADIO_TOKEN_SERVICE,
|
|
MODE_BINARY = MODE_TOKEN_BINARY,
|
|
RADIO_CHANNEL_AI_PRIVATE = RADIO_TOKEN_AI_PRIVATE,
|
|
RADIO_CHANNEL_ENTERTAINMENT = RADIO_TOKEN_ENTERTAINMENT,
|
|
))
|
|
|
|
/obj/item/radio/headset
|
|
name = "radio headset"
|
|
desc = "An updated, modular intercom that fits over the head. Takes encryption keys."
|
|
icon = 'icons/obj/clothing/headsets.dmi'
|
|
icon_state = "headset"
|
|
inhand_icon_state = "headset"
|
|
lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/items_righthand.dmi'
|
|
worn_icon_state = "headset"
|
|
custom_materials = list(/datum/material/iron=SMALL_MATERIAL_AMOUNT * 0.75)
|
|
subspace_transmission = TRUE
|
|
canhear_range = 0 // can't hear headsets from very far away
|
|
interaction_flags_mouse_drop = FORBID_TELEKINESIS_REACH
|
|
slot_flags = ITEM_SLOT_EARS
|
|
dog_fashion = null
|
|
var/obj/item/encryptionkey/keyslot2 = null
|
|
/// A list of all languages that this headset allows the user to understand. Populated by language encryption keys.
|
|
var/list/language_list
|
|
|
|
// headset is too small to display overlays
|
|
overlay_speaker_idle = null
|
|
overlay_speaker_active = null
|
|
overlay_mic_idle = null
|
|
overlay_mic_active = null
|
|
|
|
/obj/item/radio/headset/suicide_act(mob/living/carbon/user)
|
|
user.visible_message(span_suicide("[user] begins putting \the [src]'s antenna up [user.p_their()] nose! It looks like [user.p_theyre()] trying to give [user.p_them()]self cancer!"))
|
|
return TOXLOSS
|
|
|
|
/obj/item/radio/headset/examine(mob/user)
|
|
. = ..()
|
|
|
|
if(item_flags & IN_INVENTORY && loc == user)
|
|
// construction of frequency description
|
|
var/list/avail_chans = list("Use [RADIO_KEY_COMMON] for the currently tuned frequency")
|
|
if(special_channels & RADIO_SPECIAL_BINARY)
|
|
avail_chans += "use [MODE_TOKEN_BINARY] for [MODE_BINARY]"
|
|
if(length(channels))
|
|
for(var/i in 1 to length(channels))
|
|
if(i == 1)
|
|
avail_chans += "use [MODE_TOKEN_DEPARTMENT] or [GLOB.channel_tokens[channels[i]]] for [LOWER_TEXT(channels[i])]"
|
|
else
|
|
avail_chans += "use [GLOB.channel_tokens[channels[i]]] for [LOWER_TEXT(channels[i])]"
|
|
. += span_notice("A small screen on the headset displays the following available frequencies:\n[english_list(avail_chans)].")
|
|
|
|
if(command)
|
|
. += span_info("Alt-click to toggle the high-volume mode.")
|
|
else
|
|
. += span_notice("A small screen on the headset flashes, it's too small to read without holding or wearing the headset.")
|
|
|
|
/obj/item/radio/headset/Initialize(mapload)
|
|
. = ..()
|
|
if(ispath(keyslot2))
|
|
keyslot2 = new keyslot2()
|
|
set_listening(TRUE)
|
|
set_broadcasting(TRUE)
|
|
recalculateChannels()
|
|
possibly_deactivate_in_loc()
|
|
|
|
/obj/item/radio/headset/proc/possibly_deactivate_in_loc()
|
|
if(ismob(loc))
|
|
set_listening(should_be_listening)
|
|
else
|
|
set_listening(FALSE, actual_setting = FALSE)
|
|
|
|
/obj/item/radio/headset/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE)
|
|
. = ..()
|
|
possibly_deactivate_in_loc()
|
|
|
|
/obj/item/radio/headset/Destroy()
|
|
if(istype(keyslot2))
|
|
QDEL_NULL(keyslot2)
|
|
return ..()
|
|
|
|
/obj/item/radio/headset/ui_data(mob/user)
|
|
. = ..()
|
|
.["headset"] = TRUE
|
|
|
|
/obj/item/radio/headset/mouse_drop_dragged(atom/over, mob/user, src_location, over_location, params)
|
|
if(user == over)
|
|
return attack_self(user)
|
|
|
|
/// Grants all the languages this headset allows the mob to understand via installed chips.
|
|
/obj/item/radio/headset/proc/grant_headset_languages(mob/grant_to)
|
|
for(var/language in language_list)
|
|
grant_to.grant_language(language, language_flags = UNDERSTOOD_LANGUAGE, source = LANGUAGE_RADIOKEY)
|
|
|
|
/obj/item/radio/headset/equipped(mob/user, slot, initial)
|
|
. = ..()
|
|
if(!(slot_flags & slot))
|
|
return
|
|
|
|
grant_headset_languages(user)
|
|
|
|
/obj/item/radio/headset/dropped(mob/user, silent)
|
|
. = ..()
|
|
if(QDELETED(src)) //This can be called as a part of destroy
|
|
return
|
|
for(var/language in language_list)
|
|
user.remove_language(language, language_flags = UNDERSTOOD_LANGUAGE, source = LANGUAGE_RADIOKEY)
|
|
|
|
// Headsets do not become hearing sensitive as broadcasting instead controls their talk_into capabilities
|
|
/obj/item/radio/headset/set_broadcasting(new_broadcasting, actual_setting = TRUE)
|
|
broadcasting = new_broadcasting
|
|
if(actual_setting)
|
|
should_be_broadcasting = broadcasting
|
|
|
|
if (perform_update_icon && !isnull(overlay_mic_idle))
|
|
update_icon()
|
|
else if (!perform_update_icon)
|
|
should_update_icon = TRUE
|
|
|
|
/obj/item/radio/headset/talk_into_impl(atom/movable/talking_movable, message, channel, list/spans, datum/language/language, list/message_mods)
|
|
if (!broadcasting)
|
|
return
|
|
return ..()
|
|
|
|
/obj/item/radio/headset/syndicate //disguised to look like a normal headset for stealth ops
|
|
|
|
/obj/item/radio/headset/syndicate/Initialize(mapload)
|
|
. = ..()
|
|
make_syndie()
|
|
|
|
/obj/item/radio/headset/syndicate/alt //undisguised bowman with flash protection
|
|
name = "syndicate headset"
|
|
desc = "A syndicate headset that can be used to hear all radio frequencies. Protects ears from flashbangs."
|
|
icon_state = "syndie_headset"
|
|
worn_icon_state = "syndie_headset"
|
|
|
|
/obj/item/radio/headset/syndicate/alt/Initialize(mapload)
|
|
. = ..()
|
|
AddComponent(/datum/component/wearertargeting/earprotection, list(ITEM_SLOT_EARS))
|
|
|
|
/obj/item/radio/headset/syndicate/alt/leader
|
|
name = "team leader headset"
|
|
command = TRUE
|
|
|
|
/obj/item/radio/headset/binary
|
|
keyslot = /obj/item/encryptionkey/binary
|
|
|
|
/obj/item/radio/headset/headset_sec
|
|
name = "security radio headset"
|
|
desc = "This is used by your elite security force."
|
|
icon_state = "sec_headset"
|
|
worn_icon_state = "sec_headset"
|
|
keyslot = /obj/item/encryptionkey/headset_sec
|
|
|
|
/obj/item/radio/headset/headset_sec/alt
|
|
name = "security bowman headset"
|
|
desc = "This is used by your elite security force. Protects ears from flashbangs."
|
|
icon_state = "sec_headset_alt"
|
|
worn_icon_state = "sec_headset_alt"
|
|
|
|
/obj/item/radio/headset/headset_sec/alt/Initialize(mapload)
|
|
. = ..()
|
|
AddComponent(/datum/component/wearertargeting/earprotection, list(ITEM_SLOT_EARS))
|
|
|
|
/obj/item/radio/headset/headset_eng
|
|
name = "engineering radio headset"
|
|
desc = "When the engineers wish to chat like girls."
|
|
icon_state = "eng_headset"
|
|
worn_icon_state = "eng_headset"
|
|
keyslot = /obj/item/encryptionkey/headset_eng
|
|
|
|
/obj/item/radio/headset/headset_rob
|
|
name = "robotics radio headset"
|
|
desc = "Made specifically for the roboticists, who cannot decide between departments."
|
|
icon_state = "rob_headset"
|
|
worn_icon_state = "rob_headset"
|
|
keyslot = /obj/item/encryptionkey/headset_rob
|
|
|
|
/obj/item/radio/headset/headset_med
|
|
name = "medical radio headset"
|
|
desc = "A headset for the trained staff of the medbay."
|
|
icon_state = "med_headset"
|
|
worn_icon_state = "med_headset"
|
|
keyslot = /obj/item/encryptionkey/headset_med
|
|
|
|
/obj/item/radio/headset/headset_sci
|
|
name = "science radio headset"
|
|
desc = "A sciency headset. Like usual."
|
|
icon_state = "sci_headset"
|
|
worn_icon_state = "sci_headset"
|
|
keyslot = /obj/item/encryptionkey/headset_sci
|
|
|
|
/obj/item/radio/headset/headset_medsci
|
|
name = "medical research radio headset"
|
|
desc = "A headset that is a result of the mating between medical and science."
|
|
icon_state = "medsci_headset"
|
|
worn_icon_state = "medsci_headset"
|
|
keyslot = /obj/item/encryptionkey/headset_medsci
|
|
|
|
/obj/item/radio/headset/headset_srvsec
|
|
name = "law and order headset"
|
|
desc = "In the criminal justice headset, the encryption key represents two separate but equally important groups. Sec, who investigate crime, and Service, who provide services. These are their comms."
|
|
icon_state = "srvsec_headset"
|
|
worn_icon_state = "srvsec_headset"
|
|
keyslot = /obj/item/encryptionkey/headset_srvsec
|
|
|
|
/obj/item/radio/headset/headset_srvmed
|
|
name = "service medical headset"
|
|
desc = "A headset allowing the wearer to communicate with medbay and service."
|
|
icon_state = "srv_headset"
|
|
worn_icon_state = "srv_headset"
|
|
keyslot = /obj/item/encryptionkey/headset_srvmed
|
|
|
|
/obj/item/radio/headset/headset_srvent
|
|
name = "press headset"
|
|
desc = "A headset allowing the wearer to communicate with service and broadcast to entertainment channel."
|
|
icon_state = "srvent_headset"
|
|
worn_icon_state = "srv_headset"
|
|
keyslot = /obj/item/encryptionkey/headset_srvent
|
|
|
|
/obj/item/radio/headset/headset_com
|
|
name = "command radio headset"
|
|
desc = "A headset with a commanding channel."
|
|
icon_state = "com_headset"
|
|
worn_icon_state = "com_headset"
|
|
keyslot = /obj/item/encryptionkey/headset_com
|
|
|
|
/obj/item/radio/headset/heads
|
|
command = TRUE
|
|
|
|
/obj/item/radio/headset/heads/captain
|
|
name = "\proper the captain's headset"
|
|
desc = "The headset of the king."
|
|
icon_state = "com_headset"
|
|
worn_icon_state = "com_headset"
|
|
keyslot = /obj/item/encryptionkey/heads/captain
|
|
|
|
/obj/item/radio/headset/heads/captain/alt
|
|
name = "\proper the captain's bowman headset"
|
|
desc = "The headset of the boss. Protects ears from flashbangs."
|
|
icon_state = "com_headset_alt"
|
|
worn_icon_state = "com_headset_alt"
|
|
|
|
/obj/item/radio/headset/heads/captain/alt/Initialize(mapload)
|
|
. = ..()
|
|
AddComponent(/datum/component/wearertargeting/earprotection, list(ITEM_SLOT_EARS))
|
|
|
|
/obj/item/radio/headset/heads/rd
|
|
name = "\proper the research director's headset"
|
|
desc = "Headset of the fellow who keeps society marching towards technological singularity."
|
|
icon_state = "com_headset"
|
|
worn_icon_state = "com_headset"
|
|
keyslot = /obj/item/encryptionkey/heads/rd
|
|
|
|
/obj/item/radio/headset/heads/hos
|
|
name = "\proper the head of security's headset"
|
|
desc = "The headset of the man in charge of keeping order and protecting the station."
|
|
icon_state = "com_headset"
|
|
worn_icon_state = "com_headset"
|
|
keyslot = /obj/item/encryptionkey/heads/hos
|
|
|
|
/obj/item/radio/headset/heads/hos/advisor
|
|
name = "\proper the veteran security advisor headset"
|
|
desc = "The headset of the man who was in charge of keeping order and protecting the station..."
|
|
icon_state = "com_headset"
|
|
worn_icon_state = "com_headset"
|
|
keyslot = /obj/item/encryptionkey/heads/hos
|
|
command = FALSE
|
|
|
|
/obj/item/radio/headset/heads/hos/alt
|
|
name = "\proper the head of security's bowman headset"
|
|
desc = "The headset of the man in charge of keeping order and protecting the station. Protects ears from flashbangs."
|
|
icon_state = "com_headset_alt"
|
|
worn_icon_state = "com_headset_alt"
|
|
|
|
/obj/item/radio/headset/heads/hos/alt/Initialize(mapload)
|
|
. = ..()
|
|
AddComponent(/datum/component/wearertargeting/earprotection, list(ITEM_SLOT_EARS))
|
|
|
|
/obj/item/radio/headset/heads/ce
|
|
name = "\proper the chief engineer's headset"
|
|
desc = "The headset of the guy in charge of keeping the station powered and undamaged."
|
|
icon_state = "com_headset"
|
|
worn_icon_state = "com_headset"
|
|
keyslot = /obj/item/encryptionkey/heads/ce
|
|
|
|
/obj/item/radio/headset/heads/cmo
|
|
name = "\proper the chief medical officer's headset"
|
|
desc = "The headset of the highly trained medical chief."
|
|
icon_state = "com_headset"
|
|
worn_icon_state = "com_headset"
|
|
keyslot = /obj/item/encryptionkey/heads/cmo
|
|
|
|
/obj/item/radio/headset/heads/hop
|
|
name = "\proper the head of personnel's headset"
|
|
desc = "The headset of the guy who will one day be captain."
|
|
icon_state = "com_headset"
|
|
worn_icon_state = "com_headset"
|
|
keyslot = /obj/item/encryptionkey/heads/hop
|
|
|
|
/obj/item/radio/headset/heads/qm
|
|
name = "\proper the quartermaster's headset"
|
|
desc = "The headset of the guy who runs the cargo department."
|
|
icon_state = "com_headset"
|
|
worn_icon_state = "com_headset"
|
|
keyslot = /obj/item/encryptionkey/heads/qm
|
|
|
|
/obj/item/radio/headset/headset_cargo
|
|
name = "supply radio headset"
|
|
desc = "A headset used by the QM's slaves."
|
|
icon_state = "cargo_headset"
|
|
worn_icon_state = "cargo_headset"
|
|
keyslot = /obj/item/encryptionkey/headset_cargo
|
|
|
|
/obj/item/radio/headset/headset_cargo/mining
|
|
name = "mining radio headset"
|
|
desc = "Headset used by shaft miners. It has a mining network uplink which allows the user to quickly transmit commands to their comrades and amplifies their voice in low-pressure environments."
|
|
icon_state = "mine_headset"
|
|
worn_icon_state = "mine_headset"
|
|
// "puts the antenna down" while the headset is off
|
|
overlay_speaker_idle = "headset_up"
|
|
overlay_mic_idle = "headset_up"
|
|
keyslot = /obj/item/encryptionkey/headset_mining
|
|
|
|
/obj/item/radio/headset/headset_cargo/mining/Initialize(mapload)
|
|
. = ..()
|
|
AddComponent(/datum/component/callouts, ITEM_SLOT_EARS, examine_text = span_info("Use ctrl-click to enable or disable callouts."))
|
|
|
|
/obj/item/radio/headset/headset_cargo/mining/equipped(mob/living/carbon/human/user, slot)
|
|
. = ..()
|
|
if(slot & ITEM_SLOT_EARS)
|
|
ADD_TRAIT(user, TRAIT_SPEECH_BOOSTER, CLOTHING_TRAIT)
|
|
|
|
/obj/item/radio/headset/headset_cargo/mining/dropped(mob/living/carbon/human/user)
|
|
. = ..()
|
|
REMOVE_TRAIT(user, TRAIT_SPEECH_BOOSTER, CLOTHING_TRAIT)
|
|
|
|
/obj/item/radio/headset/headset_srv
|
|
name = "service radio headset"
|
|
desc = "Headset used by the service staff, tasked with keeping the station full, happy and clean."
|
|
icon_state = "srv_headset"
|
|
worn_icon_state = "srv_headset"
|
|
keyslot = /obj/item/encryptionkey/headset_service
|
|
|
|
/obj/item/radio/headset/headset_cent
|
|
name = "\improper CentCom headset"
|
|
desc = "A headset used by the upper echelons of Nanotrasen."
|
|
icon_state = "cent_headset"
|
|
worn_icon_state = "cent_headset"
|
|
keyslot = /obj/item/encryptionkey/headset_cent
|
|
keyslot2 = /obj/item/encryptionkey/headset_com
|
|
|
|
/obj/item/radio/headset/headset_cent/empty
|
|
keyslot = null
|
|
keyslot2 = null
|
|
|
|
/obj/item/radio/headset/headset_cent/commander
|
|
keyslot2 = /obj/item/encryptionkey/heads/captain
|
|
command = TRUE
|
|
|
|
/obj/item/radio/headset/headset_cent/alt
|
|
name = "\improper CentCom bowman headset"
|
|
desc = "A headset especially for emergency response personnel. Protects ears from flashbangs."
|
|
icon_state = "cent_headset_alt"
|
|
worn_icon_state = "cent_headset_alt"
|
|
keyslot2 = null
|
|
|
|
/obj/item/radio/headset/headset_cent/alt/Initialize(mapload)
|
|
. = ..()
|
|
AddComponent(/datum/component/wearertargeting/earprotection, list(ITEM_SLOT_EARS))
|
|
|
|
/obj/item/radio/headset/silicon/pai
|
|
name = "\proper mini Integrated Subspace Transceiver"
|
|
subspace_transmission = FALSE
|
|
|
|
|
|
/obj/item/radio/headset/silicon/ai
|
|
name = "\proper Integrated Subspace Transceiver"
|
|
keyslot2 = new /obj/item/encryptionkey/ai
|
|
command = TRUE
|
|
|
|
/obj/item/radio/headset/silicon/human_ai
|
|
name = "\proper Disconnected Subspace Transceiver"
|
|
desc = "A headset that is rumored to be one day implanted into a brain in a jar directly."
|
|
icon_state = "rob_headset"
|
|
worn_icon_state = "rob_headset"
|
|
keyslot2 = new /obj/item/encryptionkey/ai_with_binary
|
|
command = TRUE
|
|
|
|
/obj/item/radio/headset/silicon/ai/evil
|
|
name = "\proper Evil Integrated Subspace Transceiver"
|
|
keyslot2 = new /obj/item/encryptionkey/ai/evil
|
|
command = FALSE
|
|
|
|
/obj/item/radio/headset/silicon/ai/evil/Initialize(mapload)
|
|
. = ..()
|
|
make_syndie()
|
|
|
|
/obj/item/radio/headset/screwdriver_act(mob/living/user, obj/item/tool)
|
|
if(keyslot || keyslot2)
|
|
for(var/ch_name in channels)
|
|
SSradio.remove_object(src, GLOB.radiochannels[ch_name])
|
|
secure_radio_connections[ch_name] = null
|
|
|
|
if(keyslot)
|
|
user.put_in_hands(keyslot)
|
|
keyslot = null
|
|
if(keyslot2)
|
|
user.put_in_hands(keyslot2)
|
|
keyslot2 = null
|
|
|
|
recalculateChannels()
|
|
to_chat(user, span_notice("You pop out the encryption keys in the headset."))
|
|
|
|
else
|
|
to_chat(user, span_warning("This headset doesn't have any unique encryption keys! How useless..."))
|
|
tool.play_tool_sound(src, 10)
|
|
return TRUE
|
|
|
|
/obj/item/radio/headset/attackby(obj/item/W, mob/user, params)
|
|
if(istype(W, /obj/item/encryptionkey))
|
|
if(keyslot && keyslot2)
|
|
to_chat(user, span_warning("The headset can't hold another key!"))
|
|
return
|
|
|
|
if(!keyslot)
|
|
if(!user.transferItemToLoc(W, src))
|
|
return
|
|
keyslot = W
|
|
|
|
else
|
|
if(!user.transferItemToLoc(W, src))
|
|
return
|
|
keyslot2 = W
|
|
|
|
|
|
recalculateChannels()
|
|
else
|
|
return ..()
|
|
|
|
/obj/item/radio/headset/recalculateChannels()
|
|
. = ..()
|
|
if(keyslot2)
|
|
for(var/ch_name in keyslot2.channels)
|
|
if(!(ch_name in src.channels))
|
|
LAZYSET(channels, ch_name, keyslot2.channels[ch_name])
|
|
|
|
special_channels |= keyslot2.special_channels
|
|
|
|
for(var/ch_name in channels)
|
|
secure_radio_connections[ch_name] = add_radio(src, GLOB.radiochannels[ch_name])
|
|
|
|
var/list/old_language_list = language_list?.Copy()
|
|
language_list = list()
|
|
if(keyslot?.translated_language)
|
|
language_list += keyslot.translated_language
|
|
if(keyslot2?.translated_language)
|
|
language_list += keyslot2.translated_language
|
|
|
|
// If we're equipped on a mob, we should make sure all the languages
|
|
// learned from our installed key chips are all still accurate
|
|
var/mob/mob_loc = loc
|
|
if(istype(mob_loc) && mob_loc.get_item_by_slot(slot_flags) == src)
|
|
// Remove all the languages we may not be able to know anymore
|
|
for(var/language in old_language_list)
|
|
mob_loc.remove_language(language, language_flags = UNDERSTOOD_LANGUAGE, source = LANGUAGE_RADIOKEY)
|
|
|
|
// And grant all the languages we definitely should know now
|
|
grant_headset_languages(mob_loc)
|
|
|
|
/obj/item/radio/headset/click_alt(mob/living/user)
|
|
if(!istype(user) || !command)
|
|
return CLICK_ACTION_BLOCKING
|
|
use_command = !use_command
|
|
to_chat(user, span_notice("You toggle high-volume mode [use_command ? "on" : "off"]."))
|
|
return CLICK_ACTION_SUCCESS
|