mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-22 12:41:09 +01:00
Allows you to install encryption keys in intercoms and station-bounced radios (#94874)
## About The Pull Request *All* radios can have an encryption key installed This includes intercoms and station-bounced radios <img width="472" height="294" alt="image" src="https://github.com/user-attachments/assets/8fe8880b-2872-4030-9e42-ced4ce529b31" /> These radios are *not* normally freerange, meaning to tune into channels added by an encryption key, a new button in the radio UI has been added - "Tune", which tunes you directly into the channel. This even works with the Syndie key, giving the intercom access to Syndie channel and the ability to hear all encrypted channels. However, it will *not* work with a Binary key. Likewise, any key with language understanding on it will do nothing. I think **theoretically** we can have intercepted messages in alternate languages check to see if they have a key of that language with (to relay a translation instead), but that sounds like a lot of work... Also this means you can now speak on encrypted frequencies (like departmental ones) via non-subspace means - ie, when telecomms is disabled. ## Why It's Good For The Game To be completely honest, I haven't fully considered the repercussions of such a change. Someone just offhandedly mentioned that if they could tune into a dept. radio via subspace, they would try playing without a headset, and I thought that sounded fun. Otherwise, this opens up stuff like departmental intercom systems - which sounds cool - and in the future we could possibly de-hardcode freerange settings (like the command intercom). ## Changelog 🆑 Melbert add: All radios (intercoms and station-bounced) can have encryption keys installed in them, rather than solely headsets and cyborgs. add: Existing screwdriver interactions for station-bounced radios and intercoms have been moved to right click. However, intercoms will still default to the old behavior if they have no key installed. qol: Screentips for radios. /🆑
This commit is contained in:
@@ -433,52 +433,45 @@ GLOBAL_LIST_INIT(channel_tokens, list(
|
||||
. = ..()
|
||||
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.default_radio_channels[ch_name])
|
||||
secure_radio_connections[ch_name] = null
|
||||
/obj/item/radio/headset/Exited(atom/movable/gone, direction)
|
||||
. = ..()
|
||||
if(gone == keyslot2)
|
||||
keyslot2 = null
|
||||
if(!QDELING(src))
|
||||
recalculateChannels()
|
||||
|
||||
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, list/modifiers, list/attack_modifiers)
|
||||
if(!istype(W, /obj/item/encryptionkey))
|
||||
return ..()
|
||||
|
||||
if(keyslot && keyslot2)
|
||||
to_chat(user, span_warning("The headset can't hold another key!"))
|
||||
/obj/item/radio/headset/remove_keys(mob/living/user)
|
||||
. = ..()
|
||||
if(!keyslot2)
|
||||
return
|
||||
|
||||
if(!keyslot)
|
||||
if(!user.transferItemToLoc(W, src))
|
||||
return
|
||||
keyslot = W
|
||||
else
|
||||
if(!user.transferItemToLoc(W, src))
|
||||
return
|
||||
keyslot2 = W
|
||||
. += keyslot2
|
||||
user.put_in_hands(keyslot2) // null via Exited
|
||||
|
||||
/obj/item/radio/headset/install_key(mob/living/user, obj/item/encryptionkey/key)
|
||||
if(!keyslot)
|
||||
return ..()
|
||||
|
||||
if(keyslot2)
|
||||
loc.balloon_alert(user, "cannot hold a third key!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(!user.transferItemToLoc(key, src))
|
||||
loc.balloon_alert(user, "cannot install!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
keyslot2 = key
|
||||
recalculateChannels()
|
||||
playsound(src, 'sound/machines/click.ogg', 50, TRUE)
|
||||
loc.balloon_alert(user, "encryption key installed")
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/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])
|
||||
for(var/channel_name in keyslot2.channels)
|
||||
if(!(channel_name in channels))
|
||||
channels[channel_name] = keyslot2.channels[channel_name]
|
||||
|
||||
special_channels |= keyslot2.special_channels
|
||||
|
||||
|
||||
@@ -63,7 +63,19 @@
|
||||
else
|
||||
. += span_notice("It has a frequency lock set to [frequency/10].")
|
||||
|
||||
/obj/item/radio/intercom/screwdriver_act(mob/living/user, obj/item/tool)
|
||||
/obj/item/radio/intercom/add_context(atom/source, list/context, obj/item/held_item, mob/user)
|
||||
. = ..()
|
||||
if(held_item?.tool_behaviour == TOOL_SCREWDRIVER)
|
||||
context[SCREENTIP_CONTEXT_RMB] = unscrewed ? "Secure to wall" : "Unscrew from wall"
|
||||
context[SCREENTIP_CONTEXT_LMB] = isnull(keyslot) ? context[SCREENTIP_CONTEXT_RMB] : "Remove encryption key" // sometimes same behavior
|
||||
. = CONTEXTUAL_SCREENTIP_SET
|
||||
|
||||
if(held_item?.tool_behaviour == TOOL_WRENCH && unscrewed)
|
||||
context[SCREENTIP_CONTEXT_RMB] = "Detach from wall"
|
||||
context[SCREENTIP_CONTEXT_LMB] = context[SCREENTIP_CONTEXT_LMB] // same behavior
|
||||
. = CONTEXTUAL_SCREENTIP_SET
|
||||
|
||||
/obj/item/radio/intercom/screwdriver_act_secondary(mob/living/user, obj/item/tool)
|
||||
if(unscrewed)
|
||||
user.visible_message(span_notice("[user] starts tightening [src]'s screws..."), span_notice("You start screwing in [src]..."))
|
||||
if(tool.use_tool(src, user, 30, volume=50))
|
||||
@@ -76,19 +88,27 @@
|
||||
user.visible_message(span_notice("[user] loosens [src]'s screws!"), span_notice("You unscrew [src], loosening it from the wall."))
|
||||
unscrewed = TRUE
|
||||
update_appearance(UPDATE_OVERLAYS)
|
||||
return TRUE
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/radio/intercom/screwdriver_act(mob/living/user, obj/item/tool)
|
||||
if(isnull(keyslot))
|
||||
return screwdriver_act_secondary(user, tool)
|
||||
return ..()
|
||||
|
||||
/obj/item/radio/intercom/wrench_act(mob/living/user, obj/item/tool)
|
||||
. = TRUE
|
||||
if(!unscrewed)
|
||||
to_chat(user, span_warning("You need to unscrew [src] from the wall first!"))
|
||||
return
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
user.visible_message(span_notice("[user] starts unsecuring [src]..."), span_notice("You start unsecuring [src]..."))
|
||||
tool.play_tool_sound(src)
|
||||
if(tool.use_tool(src, user, 80))
|
||||
user.visible_message(span_notice("[user] unsecures [src]!"), span_notice("You detach [src] from the wall."))
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
|
||||
deconstruct(TRUE)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/radio/intercom/wrench_act_secondary(mob/living/user, obj/item/tool)
|
||||
return wrench_act(user, tool)
|
||||
|
||||
/**
|
||||
* Override attack_tk_grab instead of attack_tk because we actually want attack_tk's
|
||||
|
||||
@@ -99,13 +99,11 @@
|
||||
|
||||
/obj/item/radio/Initialize(mapload)
|
||||
set_wires(new /datum/wires/radio(src))
|
||||
secure_radio_connections = list()
|
||||
. = ..()
|
||||
|
||||
if(ispath(keyslot))
|
||||
keyslot = new keyslot()
|
||||
for(var/ch_name in channels)
|
||||
secure_radio_connections[ch_name] = add_radio(src, GLOB.default_radio_channels[ch_name])
|
||||
recalculateChannels()
|
||||
|
||||
perform_update_icon = FALSE
|
||||
set_listening(listening)
|
||||
@@ -118,7 +116,7 @@
|
||||
update_appearance(UPDATE_ICON)
|
||||
|
||||
AddElement(/datum/element/empprotection, EMP_PROTECT_WIRES)
|
||||
|
||||
register_context()
|
||||
// No subtypes
|
||||
if(type != /obj/item/radio)
|
||||
return
|
||||
@@ -132,6 +130,16 @@
|
||||
QDEL_NULL(keyslot)
|
||||
return ..()
|
||||
|
||||
/obj/item/radio/add_context(atom/source, list/context, obj/item/held_item, mob/user)
|
||||
. = ..()
|
||||
if(held_item?.tool_behaviour == TOOL_SCREWDRIVER)
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Remove encryption key"
|
||||
context[SCREENTIP_CONTEXT_RMB] = unscrewed ? "Screw in" : "Unscrew"
|
||||
. = CONTEXTUAL_SCREENTIP_SET
|
||||
if(istype(held_item, /obj/item/encryptionkey))
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Install encryption key"
|
||||
. = CONTEXTUAL_SCREENTIP_SET
|
||||
|
||||
/obj/item/radio/on_saboteur(datum/source, disrupt_duration)
|
||||
. = ..()
|
||||
if(broadcasting) //no broadcasting but it can still be used to send radio messages.
|
||||
@@ -155,7 +163,7 @@
|
||||
if(!(channel_name in channels))
|
||||
channels[channel_name] = keyslot.channels[channel_name]
|
||||
|
||||
special_channels = keyslot.special_channels
|
||||
special_channels |= keyslot.special_channels
|
||||
|
||||
for(var/channel_name in channels)
|
||||
secure_radio_connections[channel_name] = add_radio(src, GLOB.default_radio_channels[channel_name])
|
||||
@@ -163,12 +171,17 @@
|
||||
if(!listening)
|
||||
remove_radio_all(src)
|
||||
|
||||
// Used for cyborg override
|
||||
/obj/item/radio/proc/resetChannels()
|
||||
for(var/ch_name in channels)
|
||||
SSradio.remove_object(src, GLOB.default_radio_channels[ch_name])
|
||||
|
||||
channels = list()
|
||||
secure_radio_connections = list()
|
||||
special_channels = NONE
|
||||
|
||||
if(!freerange && (frequency > MAX_FREQ || frequency < MIN_FREQ))
|
||||
frequency = FREQ_COMMON
|
||||
|
||||
///goes through all radio channels we should be listening for and readds them to the global list
|
||||
/obj/item/radio/proc/readd_listening_radio_channels()
|
||||
for(var/channel_name in channels)
|
||||
@@ -494,16 +507,26 @@
|
||||
if("frequency")
|
||||
if(freqlock != RADIO_FREQENCY_UNLOCKED)
|
||||
return
|
||||
var/tune = params["tune"]
|
||||
var/tune = 0
|
||||
var/adjust = text2num(params["adjust"])
|
||||
if(adjust)
|
||||
tune = frequency + adjust * 10
|
||||
. = TRUE
|
||||
else if(text2num(tune) != null)
|
||||
tune = tune * 10
|
||||
. = TRUE
|
||||
if(.)
|
||||
else if(tune)
|
||||
tune *= 10
|
||||
if(tune)
|
||||
set_frequency(sanitize_frequency(tune, freerange, (special_channels & RADIO_SPECIAL_SYNDIE)))
|
||||
. = TRUE
|
||||
|
||||
if("tune_to_channel")
|
||||
if(freqlock != RADIO_FREQENCY_UNLOCKED)
|
||||
return
|
||||
var/channel = params["channel"]
|
||||
if(!(channel in channels))
|
||||
return
|
||||
// bypasses frequency range, force tunes to a specific encrypted channel
|
||||
set_frequency(GLOB.default_radio_channels[channel])
|
||||
. = TRUE
|
||||
|
||||
if("listen")
|
||||
set_listening(!listening)
|
||||
. = TRUE
|
||||
@@ -561,15 +584,66 @@
|
||||
/obj/item/radio/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
|
||||
if(user.combat_mode && tool.tool_behaviour == TOOL_SCREWDRIVER)
|
||||
return screwdriver_act(user, tool)
|
||||
return ..()
|
||||
if(istype(tool, /obj/item/encryptionkey))
|
||||
return install_key(user, tool)
|
||||
return NONE
|
||||
|
||||
/obj/item/radio/screwdriver_act(mob/living/user, obj/item/tool)
|
||||
/obj/item/radio/screwdriver_act_secondary(mob/living/user, obj/item/tool)
|
||||
add_fingerprint(user)
|
||||
unscrewed = !unscrewed
|
||||
tool.play_tool_sound(src, 10)
|
||||
if(unscrewed)
|
||||
to_chat(user, span_notice("The radio can now be attached and modified!"))
|
||||
to_chat(user, span_notice("[src] can now be attached and modified!"))
|
||||
else
|
||||
to_chat(user, span_notice("The radio can no longer be modified or attached!"))
|
||||
to_chat(user, span_notice("[src] can no longer be modified or attached!"))
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/radio/screwdriver_act(mob/living/user, obj/item/tool)
|
||||
var/list/removed_keys = remove_keys(user)
|
||||
if(length(removed_keys) > 1)
|
||||
to_chat(user, span_notice("You remove the encryption keys from [src]."))
|
||||
else if(length(removed_keys) == 1)
|
||||
to_chat(user, span_notice("You remove [removed_keys[1]] from [src]."))
|
||||
else
|
||||
to_chat(user, span_warning("[src] doesn't have any unique encryption keys! How useless..."))
|
||||
tool.play_tool_sound(src, 10)
|
||||
return TRUE
|
||||
|
||||
/obj/item/radio/Exited(atom/movable/gone, direction)
|
||||
. = ..()
|
||||
if(gone == keyslot)
|
||||
keyslot = null
|
||||
if(!QDELING(src))
|
||||
recalculateChannels()
|
||||
|
||||
/// Attempts to put all keys in the radio into the user's hands
|
||||
/// Returns a list of the removed keys
|
||||
/obj/item/radio/proc/remove_keys(mob/living/user)
|
||||
. = list()
|
||||
if(!keyslot)
|
||||
return
|
||||
|
||||
. += keyslot
|
||||
user.put_in_hands(keyslot) // null via Exited
|
||||
|
||||
/// Attempts to install the given encryption key into the radio
|
||||
/obj/item/radio/proc/install_key(mob/living/user, obj/item/encryptionkey/key)
|
||||
if(keyslot)
|
||||
loc.balloon_alert(user, "cannot hold a second key!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(freqlock)
|
||||
loc.balloon_alert(user, "keyslot is locked!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(!user.transferItemToLoc(key, src))
|
||||
loc.balloon_alert(user, "cannot install!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
keyslot = key
|
||||
recalculateChannels()
|
||||
playsound(src, 'sound/machines/click.ogg', 50, TRUE)
|
||||
loc.balloon_alert(user, "encryption key installed")
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/radio/emp_act(severity)
|
||||
. = ..()
|
||||
@@ -632,41 +706,6 @@
|
||||
. = ..()
|
||||
set_frequency(FREQ_SYNDICATE)
|
||||
|
||||
/obj/item/radio/borg/screwdriver_act(mob/living/user, obj/item/tool)
|
||||
if(!keyslot)
|
||||
loc.balloon_alert(user, "no encryption keys!")
|
||||
return
|
||||
|
||||
for(var/ch_name in channels)
|
||||
SSradio.remove_object(src, GLOB.default_radio_channels[ch_name])
|
||||
secure_radio_connections[ch_name] = null
|
||||
|
||||
if (!user.put_in_hands(keyslot))
|
||||
keyslot.forceMove(drop_location())
|
||||
|
||||
keyslot = null
|
||||
recalculateChannels()
|
||||
loc.balloon_alert(user, "encryption key removed")
|
||||
return ..()
|
||||
|
||||
/obj/item/radio/borg/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
|
||||
if (!istype(tool, /obj/item/encryptionkey))
|
||||
return NONE
|
||||
|
||||
if(keyslot)
|
||||
loc.balloon_alert(user, "cannot hold another key!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(!user.transferItemToLoc(tool, src))
|
||||
loc.balloon_alert(user, "cannot install!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
keyslot = tool
|
||||
recalculateChannels()
|
||||
playsound(src, 'sound/machines/click.ogg', 50, TRUE)
|
||||
loc.balloon_alert(user, "encryption key installed")
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/radio/off // Station bounced radios, their only difference is spawning with the speakers off, this was made to help the lag.
|
||||
dog_fashion = /datum/dog_fashion/back
|
||||
|
||||
@@ -734,6 +773,8 @@
|
||||
canhear_range = 3
|
||||
|
||||
// In case you want to map it in/spawn it for some reason
|
||||
/obj/item/radio/toy
|
||||
|
||||
/obj/item/radio/toy/Initialize(mapload)
|
||||
. = ..()
|
||||
make_silly()
|
||||
|
||||
Reference in New Issue
Block a user