Skip to content

Commit

Permalink
[MIRROR] adds portable radio jammer
Browse files Browse the repository at this point in the history
  • Loading branch information
ManofSausage authored and LordNest committed Feb 21, 2024
1 parent eb4aca3 commit 9dd2c32
Show file tree
Hide file tree
Showing 6 changed files with 264 additions and 4 deletions.
1 change: 1 addition & 0 deletions baystation12.dme
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,7 @@
#include "code\game\objects\items\devices\paint_sprayer.dm"
#include "code\game\objects\items\devices\personal_shield.dm"
#include "code\game\objects\items\devices\powersink.dm"
#include "code\game\objects\items\devices\radio_jammer.dm"
#include "code\game\objects\items\devices\slide_projector.dm"
#include "code\game\objects\items\devices\spy_bug.dm"
#include "code\game\objects\items\devices\suit_cooling.dm"
Expand Down
7 changes: 7 additions & 0 deletions code/datums/uplink/devices and tools.dm
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,13 @@
While in hacking mode, this device will grant full access to any airlock in 20 to 40 seconds. \
This device will be able to continuously reaccess the last 6 to 8 airlocks it was used on."

/datum/uplink_item/item/tools/radio_jammer
name = "Portable Radio Jammer"
item_cost = 24
path = /obj/item/device/radio_jammer
desc = "A pocket sized portable radio jammer that can intercept outgoing radio signals in a given distance. \
However, radios attempting to send outgoing transmissions will emit a faint buzzing noise. \
The jammer can be signaled remotely using assembly signalers."

/datum/uplink_item/item/tools/space_suit
name = "Voidsuit and Tactical Mask"
Expand Down
29 changes: 25 additions & 4 deletions code/game/objects/items/devices/radio/radio.dm
Original file line number Diff line number Diff line change
Expand Up @@ -329,13 +329,35 @@
return null

/obj/item/device/radio/talk_into(mob/living/M, message, channel, verb = "says", datum/language/speaking = null)
if(!on) return 0 // the device has to be on
// the device has to be on
if (!on)
return FALSE
// Fix for permacell radios, but kinda eh about actually fixing them.
if(!M || !message) return 0
if (!M || !message)
return FALSE

if(speaking && (speaking.flags & (NONVERBAL|SIGNLANG))) return 0
if (speaking && (speaking.flags & (NONVERBAL|SIGNLANG)))
return FALSE

if (!broadcasting)
var/list/headset_z_group = GetConnectedZlevels(get_z(src))
//needs to account for turfs
var/turf/self_turf = get_turf(src)
if (!self_turf)
return FALSE
var/self_x = self_turf.x
var/self_y = self_turf.y
for (var/obj/item/device/radio_jammer/jammer as anything in GLOB.radio_jammers)
var/turf/jammer_turf = get_turf(jammer)
if (!jammer_turf)
continue
var/dx = self_x - jammer_turf.x
var/dy = self_y - jammer_turf.y
if (dx*dx + dy*dy <= jammer.square_radius && (jammer_turf.z in headset_z_group))
to_chat(M,SPAN_WARNING("Instead of the familiar radio crackle, \the [src] emits a faint buzzing sound."))
playsound(loc, 'sound/effects/zzzt.ogg', 20, 0, -1)
return FALSE

// Sedation chemical effect should prevent radio use (Chloral and Soporific)
var/mob/living/carbon/C = M
if (istype(C))
Expand Down Expand Up @@ -559,7 +581,6 @@


/obj/item/device/radio/hear_talk(mob/M as mob, msg, verb = "says", datum/language/speaking = null)

if (broadcasting)
if(get_dist(src, M) <= canhear_range)
talk_into(M, msg,null,verb,speaking)
Expand Down
178 changes: 178 additions & 0 deletions code/game/objects/items/devices/radio_jammer.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
GLOBAL_LIST_EMPTY(radio_jammers)
//adjusted to last a while so it can last conversations
#define JAMMER_POWER_CONSUMPTION(tick_delay) ((max(0.75, range)**2 * tick_delay) / 30)

/obj/item/device/radio_jammer
name = "small remote"
desc = "A small remote control covered in a number of lights, with several antennae extending from the top."
icon = 'icons/obj/radio_jammer.dmi'
icon_state = "jammer"
w_class = ITEM_SIZE_SMALL
var/is_active = FALSE
var/range = 5
var/square_radius = 25
var/code = 23
var/frequency = 1413
var/obj/item/cell/bcell = /obj/item/cell/high

/obj/item/device/radio_jammer/Initialize()
. = ..()
if(ispath(bcell))
bcell = new bcell(src)
GLOB.listening_objects += src
set_frequency(frequency)

/obj/item/device/radio_jammer/Destroy()
GLOB.radio_jammers -= src
GLOB.listening_objects -= src
qdel(bcell)
return ..()

/obj/item/device/radio_jammer/Process(wait)
var/cost = JAMMER_POWER_CONSUMPTION(wait)
if (!bcell?.use(cost))
STOP_PROCESSING(SSobj, src)
GLOB.radio_jammers -=src
is_active = FALSE

/obj/item/device/radio_jammer/attack_self(mob/living/user)
ui_interact(user)

/obj/item/device/radio_jammer/get_cell()
return bcell

/obj/item/device/radio_jammer/emp_act(severity)
..()
if(bcell)
bcell.emp_act(severity)

/obj/item/device/radio_jammer/proc/toggle(mob/user)
if(is_active)
STOP_PROCESSING(SSobj, src)
to_chat(user,SPAN_WARNING("You flick a switch on \the [src], deactivating it."))
is_active = FALSE
GLOB.radio_jammers -= src
update_icon()
else
START_PROCESSING(SSobj, src)
to_chat(user,SPAN_WARNING("You flick a switch on \the [src], activating it."))
is_active = TRUE
GLOB.radio_jammers += src
update_icon()

/obj/item/device/radio_jammer/on_update_icon()
ClearOverlays()
if(bcell)
var/percent = bcell.percent()
switch(percent)
if(0 to 25)
AddOverlays("quarter")
if(25 to 50)
AddOverlays("half")
if(50 to 99)
AddOverlays("full")
else
AddOverlays("four_quarters")

if(is_active)
AddOverlays("on")
else
AddOverlays("off")

/obj/item/device/radio_jammer/proc/set_frequency(new_frequency)
radio_controller.remove_object(src, frequency)
frequency = new_frequency
radio_controller.add_object(src, frequency, RADIO_CHAT)

/obj/item/device/radio_jammer/receive_signal(datum/signal/signal)
if(signal?.encryption == code)
toggle()

/obj/item/device/radio_jammer/OnTopic(mob/user, list/href_list, state)
if (href_list["enable_jammer"])
toggle()
return TOPIC_REFRESH
if (href_list["disable_jammer"])
toggle()
return TOPIC_REFRESH
if(href_list["increase_range"])
range = min(range + 1, 10)
square_radius = range ** 2
return TOPIC_REFRESH
if(href_list["decrease_range"])
range = max(range - 1, 0)
square_radius = range ** 2
return TOPIC_REFRESH
if(href_list["set_code"])
var/adj = text2num(href_list["code"])
if(!adj)
code = input("Set radio activation code","Radio activation") as num
if (QDELETED(src) || CanUseTopic(user, state, href_list) == STATUS_INTERACTIVE)
return TOPIC_HANDLED
else
code += adj
code = clamp(code,1,100)
return TOPIC_REFRESH
if (href_list["set_frequency"])
var/adj = text2num(href_list["frequency"])
if(!adj)
var/temp = input("Set a four digit radio frequency without decimals","Radio activation") as num
set_frequency(sanitize_frequency(temp, RADIO_LOW_FREQ, RADIO_HIGH_FREQ))
if (QDELETED(src) || CanUseTopic(user, state, href_list) == STATUS_INTERACTIVE)
return TOPIC_HANDLED
return TOPIC_REFRESH

/obj/item/device/radio_jammer/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1)
var/list/data = list(
"active" = is_active,
"current_charge" = bcell ? round(bcell.charge, 1) : 0,
"max_charge" = bcell ? bcell.maxcharge : 0,
"range" = range,
"max_range" = 10,
"frequency" = format_frequency(frequency),
"code" = code,
"total_cost" = "[ceil(JAMMER_POWER_CONSUMPTION(10))]"
)
ui = SSnano.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "radio_jammer.tmpl", "Portable Radio Jammer", 300, 640)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(TRUE)

/obj/item/device/radio_jammer/use_tool(obj/item/tool, mob/living/user, list/click_params)
if (isCrowbar(tool))
if(is_active)
STOP_PROCESSING(SSobj, src)
is_active = FALSE
GLOB.radio_jammers -= src
if (!bcell)
USE_FEEDBACK_FAILURE("\The [src] has no cell to remove.")
return TRUE
user.put_in_hands(bcell)
user.visible_message(
SPAN_NOTICE("\The [user] removes \a [bcell] from \a [src] with \a [tool]."),
SPAN_NOTICE("You remove \the [bcell] from \the [src] with \the [tool].")
)
bcell = null
update_icon()
return TRUE
if (istype(tool, /obj/item/cell))
if (bcell)
USE_FEEDBACK_FAILURE("\The [src] already has \a [bcell] installed.")
return TRUE
if (!user.unEquip(tool, src))
FEEDBACK_UNEQUIP_FAILURE(user, tool)
return TRUE
bcell = tool
user.visible_message(
SPAN_NOTICE("\The [user] installs \a [tool] into \a [src]."),
SPAN_NOTICE("you install \the [tool] into \the [src].")
)
update_icon()
return TRUE

return ..()


#undef JAMMER_POWER_CONSUMPTION
Binary file added icons/obj/radio_jammer.dmi
Binary file not shown.
53 changes: 53 additions & 0 deletions nano/templates/radio_jammer.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<div class="block">
<h3>Status</h3>
<div class="item">
<span class='average'>{{:data.active ? "Enabled" : "Disabled"}}</span>
</div>
<div class="item">
{{:helper.link('Enable' , null, {'enable_jammer' : 1}, data.active ? "selected" : null, null)}}
{{:helper.link('Disable' , null, {'disable_jammer' : 1}, data.active ? null : "selected", null)}}
</div>
</div>

<div class="block">
<h3>Range</h3>
<div class="item">
<span class='average'>{{:data.range}}</span> meter(s)
</div>
<div class="item">
{{:helper.link('Decrease' , 'minusthick', {'decrease_range' : 1}, data.range <= 0 ? "disabled" : null, null)}}
{{:helper.link('Increase' , 'plusthick', {'increase_range' : 1}, data.range >= 10 ? "disabled" : null, null)}}
</div>
</div>

<div class="block">
<h3>Remote Activation</h3>
<div class="item">
<span class='average'> {{:helper.link( data.frequency, null, { 'set_frequency': 1})}}</span>
</div>
<div class="item">
<span class='average'> {{:helper.link( data.code, null, { 'set_code': 1})}}</span>
</div>
</div>

<div class="block">
<div class="item">
<div class="itemLabel">
Charge
</div>
<div class="itemContent">
{{:data.current_charge}}/{{:data.max_charge}} W
</div>
</div>
<div class="item">
{{:helper.displayBar(data.current_charge/data.max_charge, 0, 1, 'average')}}
</div>
<div class="item">
<div class="itemLabel">
Energy Consumption
</div>
<div class="itemContent">
~{{:data.total_cost}} W
</div>
</div>
</div>

0 comments on commit 9dd2c32

Please sign in to comment.