Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into modularer
This commit is contained in:
@@ -1,223 +1,223 @@
|
||||
/obj/item/electropack
|
||||
name = "electropack"
|
||||
desc = "Dance my monkeys! DANCE!!!"
|
||||
icon = 'icons/obj/radio.dmi'
|
||||
icon_state = "electropack0"
|
||||
item_state = "electropack"
|
||||
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
|
||||
flags_1 = CONDUCT_1
|
||||
slot_flags = ITEM_SLOT_BACK
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
materials = list(MAT_METAL=10000, MAT_GLASS=2500)
|
||||
|
||||
var/code = 2
|
||||
var/frequency = FREQ_ELECTROPACK
|
||||
var/on = TRUE
|
||||
var/shock_cooldown = FALSE
|
||||
|
||||
/obj/item/electropack/suicide_act(mob/living/carbon/user)
|
||||
user.visible_message("<span class='suicide'>[user] hooks [user.p_them()]self to the electropack and spams the trigger! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
return (FIRELOSS)
|
||||
|
||||
/obj/item/electropack/Initialize()
|
||||
. = ..()
|
||||
set_frequency(frequency)
|
||||
|
||||
/obj/item/electropack/Destroy()
|
||||
SSradio.remove_object(src, frequency)
|
||||
. = ..()
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/item/electropack/attack_hand(mob/user)
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/C = user
|
||||
if(src == C.back)
|
||||
to_chat(user, "<span class='warning'>You need help taking this off!</span>")
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/electropack/attackby(obj/item/W, mob/living/user, params)
|
||||
if(istype(W, /obj/item/clothing/head/helmet))
|
||||
var/obj/item/assembly/shock_kit/A = new /obj/item/assembly/shock_kit(user)
|
||||
A.icon = 'icons/obj/assemblies.dmi'
|
||||
|
||||
if(!user.transferItemToLoc(W, A))
|
||||
to_chat(user, "<span class='warning'>[W] is stuck to your hand, you cannot attach it to [src]!</span>")
|
||||
return
|
||||
W.master = A
|
||||
A.part1 = W
|
||||
|
||||
user.transferItemToLoc(src, A, TRUE)
|
||||
master = A
|
||||
A.part2 = src
|
||||
|
||||
user.put_in_hands(A)
|
||||
A.add_fingerprint(user)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/electropack/Topic(href, href_list)
|
||||
var/mob/living/carbon/C = usr
|
||||
if(usr.stat || usr.restrained() || C.back == src)
|
||||
return
|
||||
|
||||
if(!usr.canUseTopic(src, BE_CLOSE))
|
||||
usr << browse(null, "window=radio")
|
||||
onclose(usr, "radio")
|
||||
return
|
||||
|
||||
if(href_list["set"])
|
||||
if(href_list["set"] == "freq")
|
||||
var/new_freq = input(usr, "Input a new receiving frequency", "Electropack Frequency", format_frequency(frequency)) as num|null
|
||||
if(!usr.canUseTopic(src, BE_CLOSE))
|
||||
return
|
||||
new_freq = unformat_frequency(new_freq)
|
||||
new_freq = sanitize_frequency(new_freq, TRUE)
|
||||
set_frequency(new_freq)
|
||||
|
||||
if(href_list["set"] == "code")
|
||||
var/new_code = input(usr, "Input a new receiving code", "Electropack Code", code) as num|null
|
||||
if(!usr.canUseTopic(src, BE_CLOSE))
|
||||
return
|
||||
new_code = round(new_code)
|
||||
new_code = CLAMP(new_code, 1, 100)
|
||||
code = new_code
|
||||
|
||||
if(href_list["set"] == "power")
|
||||
if(!usr.canUseTopic(src, BE_CLOSE))
|
||||
return
|
||||
on = !(on)
|
||||
icon_state = "electropack[on]"
|
||||
|
||||
if(usr)
|
||||
attack_self(usr)
|
||||
|
||||
return
|
||||
|
||||
/obj/item/electropack/proc/set_frequency(new_frequency)
|
||||
SSradio.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
SSradio.add_object(src, frequency, RADIO_SIGNALER)
|
||||
return
|
||||
|
||||
/obj/item/electropack/receive_signal(datum/signal/signal)
|
||||
if(!signal || signal.data["code"] != code)
|
||||
return
|
||||
|
||||
if(isliving(loc) && on)
|
||||
if(shock_cooldown == TRUE)
|
||||
return
|
||||
shock_cooldown = TRUE
|
||||
addtimer(VARSET_CALLBACK(src, shock_cooldown, FALSE), 100)
|
||||
var/mob/living/L = loc
|
||||
step(L, pick(GLOB.cardinals))
|
||||
|
||||
to_chat(L, "<span class='danger'>You feel a sharp shock!</span>")
|
||||
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
|
||||
s.set_up(3, 1, L)
|
||||
s.start()
|
||||
|
||||
L.Knockdown(100)
|
||||
|
||||
if(master)
|
||||
master.receive_signal()
|
||||
return
|
||||
|
||||
/obj/item/electropack/ui_interact(mob/user)
|
||||
if(!ishuman(user))
|
||||
return
|
||||
|
||||
user.set_machine(src)
|
||||
var/dat = {"
|
||||
<TT>
|
||||
Turned [on ? "On" : "Off"] - <A href='?src=[REF(src)];set=power'>Toggle</A><BR>
|
||||
<B>Frequency/Code</B> for electropack:<BR>
|
||||
Frequency:
|
||||
[format_frequency(src.frequency)]
|
||||
<A href='byond://?src=[REF(src)];set=freq'>Set</A><BR>
|
||||
|
||||
Code:
|
||||
[src.code]
|
||||
<A href='byond://?src=[REF(src)];set=code'>Set</A><BR>
|
||||
</TT>"}
|
||||
user << browse(dat, "window=radio")
|
||||
onclose(user, "radio")
|
||||
return
|
||||
|
||||
/obj/item/electropack/shockcollar
|
||||
name = "shock collar"
|
||||
desc = "A reinforced metal collar. It seems to have some form of wiring near the front. Strange.."
|
||||
icon = 'modular_citadel/icons/obj/clothing/cit_neck.dmi'
|
||||
alternate_worn_icon = 'modular_citadel/icons/mob/citadel/neck.dmi'
|
||||
icon_state = "shockcollar"
|
||||
item_state = "shockcollar"
|
||||
body_parts_covered = NECK
|
||||
slot_flags = ITEM_SLOT_NECK | ITEM_SLOT_DENYPOCKET //no more pocket shockers
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
strip_delay = 60
|
||||
equip_delay_other = 60
|
||||
materials = list(MAT_METAL=5000, MAT_GLASS=2000)
|
||||
|
||||
var/tagname = null
|
||||
|
||||
/datum/design/electropack/shockcollar
|
||||
name = "Shockcollar"
|
||||
id = "shockcollar"
|
||||
build_type = AUTOLATHE
|
||||
build_path = /obj/item/electropack/shockcollar
|
||||
materials = list(MAT_METAL=5000, MAT_GLASS=2000)
|
||||
category = list("hacked", "Misc")
|
||||
|
||||
/obj/item/electropack/shockcollar/attack_hand(mob/user)
|
||||
if(loc == user && user.get_item_by_slot(SLOT_NECK))
|
||||
to_chat(user, "<span class='warning'>The collar is fastened tight! You'll need help taking this off!</span>")
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/electropack/shockcollar/receive_signal(datum/signal/signal)
|
||||
if(!signal || signal.data["code"] != code)
|
||||
return
|
||||
|
||||
if(isliving(loc) && on)
|
||||
if(shock_cooldown == TRUE)
|
||||
return
|
||||
shock_cooldown = TRUE
|
||||
addtimer(VARSET_CALLBACK(src, shock_cooldown, FALSE), 100)
|
||||
var/mob/living/L = loc
|
||||
step(L, pick(GLOB.cardinals))
|
||||
|
||||
to_chat(L, "<span class='danger'>You feel a sharp shock from the collar!</span>")
|
||||
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
|
||||
s.set_up(3, 1, L)
|
||||
s.start()
|
||||
|
||||
L.Knockdown(100)
|
||||
|
||||
if(master)
|
||||
master.receive_signal()
|
||||
return
|
||||
|
||||
/obj/item/electropack/shockcollar/attackby(obj/item/W, mob/user, params) //moves it here because on_click is being bad
|
||||
if(istype(W, /obj/item/pen))
|
||||
var/t = input(user, "Would you like to change the name on the tag?", "Name your new pet", tagname ? tagname : "Spot") as null|text
|
||||
if(t)
|
||||
tagname = copytext(sanitize(t), 1, MAX_NAME_LEN)
|
||||
name = "[initial(name)] - [tagname]"
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/electropack/shockcollar/ui_interact(mob/user) //on_click calls this
|
||||
var/dat = {"
|
||||
<TT>
|
||||
<B>Frequency/Code</B> for shock collar:<BR>
|
||||
Frequency:
|
||||
[format_frequency(src.frequency)]
|
||||
<A href='byond://?src=[REF(src)];set=freq'>Set</A><BR>
|
||||
Code:
|
||||
[src.code]
|
||||
<A href='byond://?src=[REF(src)];set=code'>Set</A><BR>
|
||||
</TT>"}
|
||||
user << browse(dat, "window=radio")
|
||||
onclose(user, "radio")
|
||||
return
|
||||
/obj/item/electropack
|
||||
name = "electropack"
|
||||
desc = "Dance my monkeys! DANCE!!!"
|
||||
icon = 'icons/obj/radio.dmi'
|
||||
icon_state = "electropack0"
|
||||
item_state = "electropack"
|
||||
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
|
||||
flags_1 = CONDUCT_1
|
||||
slot_flags = ITEM_SLOT_BACK
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
materials = list(MAT_METAL=10000, MAT_GLASS=2500)
|
||||
|
||||
var/code = 2
|
||||
var/frequency = FREQ_ELECTROPACK
|
||||
var/on = TRUE
|
||||
var/shock_cooldown = FALSE
|
||||
|
||||
/obj/item/electropack/suicide_act(mob/living/carbon/user)
|
||||
user.visible_message("<span class='suicide'>[user] hooks [user.p_them()]self to the electropack and spams the trigger! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
return (FIRELOSS)
|
||||
|
||||
/obj/item/electropack/Initialize()
|
||||
. = ..()
|
||||
set_frequency(frequency)
|
||||
|
||||
/obj/item/electropack/Destroy()
|
||||
SSradio.remove_object(src, frequency)
|
||||
. = ..()
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/item/electropack/attack_hand(mob/user)
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/C = user
|
||||
if(src == C.back)
|
||||
to_chat(user, "<span class='warning'>You need help taking this off!</span>")
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/electropack/attackby(obj/item/W, mob/living/user, params)
|
||||
if(istype(W, /obj/item/clothing/head/helmet))
|
||||
var/obj/item/assembly/shock_kit/A = new /obj/item/assembly/shock_kit(user)
|
||||
A.icon = 'icons/obj/assemblies.dmi'
|
||||
|
||||
if(!user.transferItemToLoc(W, A))
|
||||
to_chat(user, "<span class='warning'>[W] is stuck to your hand, you cannot attach it to [src]!</span>")
|
||||
return
|
||||
W.master = A
|
||||
A.part1 = W
|
||||
|
||||
user.transferItemToLoc(src, A, TRUE)
|
||||
master = A
|
||||
A.part2 = src
|
||||
|
||||
user.put_in_hands(A)
|
||||
A.add_fingerprint(user)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/electropack/Topic(href, href_list)
|
||||
var/mob/living/carbon/C = usr
|
||||
if(usr.stat || usr.restrained() || C.back == src)
|
||||
return
|
||||
|
||||
if(!usr.canUseTopic(src, BE_CLOSE))
|
||||
usr << browse(null, "window=radio")
|
||||
onclose(usr, "radio")
|
||||
return
|
||||
|
||||
if(href_list["set"])
|
||||
if(href_list["set"] == "freq")
|
||||
var/new_freq = input(usr, "Input a new receiving frequency", "Electropack Frequency", format_frequency(frequency)) as num|null
|
||||
if(!usr.canUseTopic(src, BE_CLOSE))
|
||||
return
|
||||
new_freq = unformat_frequency(new_freq)
|
||||
new_freq = sanitize_frequency(new_freq, TRUE)
|
||||
set_frequency(new_freq)
|
||||
|
||||
if(href_list["set"] == "code")
|
||||
var/new_code = input(usr, "Input a new receiving code", "Electropack Code", code) as num|null
|
||||
if(!usr.canUseTopic(src, BE_CLOSE))
|
||||
return
|
||||
new_code = round(new_code)
|
||||
new_code = CLAMP(new_code, 1, 100)
|
||||
code = new_code
|
||||
|
||||
if(href_list["set"] == "power")
|
||||
if(!usr.canUseTopic(src, BE_CLOSE))
|
||||
return
|
||||
on = !(on)
|
||||
icon_state = "electropack[on]"
|
||||
|
||||
if(usr)
|
||||
attack_self(usr)
|
||||
|
||||
return
|
||||
|
||||
/obj/item/electropack/proc/set_frequency(new_frequency)
|
||||
SSradio.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
SSradio.add_object(src, frequency, RADIO_SIGNALER)
|
||||
return
|
||||
|
||||
/obj/item/electropack/receive_signal(datum/signal/signal)
|
||||
if(!signal || signal.data["code"] != code)
|
||||
return
|
||||
|
||||
if(isliving(loc) && on)
|
||||
if(shock_cooldown == TRUE)
|
||||
return
|
||||
shock_cooldown = TRUE
|
||||
addtimer(VARSET_CALLBACK(src, shock_cooldown, FALSE), 100)
|
||||
var/mob/living/L = loc
|
||||
step(L, pick(GLOB.cardinals))
|
||||
|
||||
to_chat(L, "<span class='danger'>You feel a sharp shock!</span>")
|
||||
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
|
||||
s.set_up(3, 1, L)
|
||||
s.start()
|
||||
|
||||
L.Knockdown(100)
|
||||
|
||||
if(master)
|
||||
master.receive_signal()
|
||||
return
|
||||
|
||||
/obj/item/electropack/ui_interact(mob/user)
|
||||
if(!ishuman(user))
|
||||
return
|
||||
|
||||
user.set_machine(src)
|
||||
var/dat = {"
|
||||
<TT>
|
||||
Turned [on ? "On" : "Off"] - <A href='?src=[REF(src)];set=power'>Toggle</A><BR>
|
||||
<B>Frequency/Code</B> for electropack:<BR>
|
||||
Frequency:
|
||||
[format_frequency(src.frequency)]
|
||||
<A href='byond://?src=[REF(src)];set=freq'>Set</A><BR>
|
||||
|
||||
Code:
|
||||
[src.code]
|
||||
<A href='byond://?src=[REF(src)];set=code'>Set</A><BR>
|
||||
</TT>"}
|
||||
user << browse(dat, "window=radio")
|
||||
onclose(user, "radio")
|
||||
return
|
||||
|
||||
/obj/item/electropack/shockcollar
|
||||
name = "shock collar"
|
||||
desc = "A reinforced metal collar. It seems to have some form of wiring near the front. Strange.."
|
||||
icon = 'modular_citadel/icons/obj/clothing/cit_neck.dmi'
|
||||
alternate_worn_icon = 'modular_citadel/icons/mob/citadel/neck.dmi'
|
||||
icon_state = "shockcollar"
|
||||
item_state = "shockcollar"
|
||||
body_parts_covered = NECK
|
||||
slot_flags = ITEM_SLOT_NECK | ITEM_SLOT_DENYPOCKET //no more pocket shockers
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
strip_delay = 60
|
||||
equip_delay_other = 60
|
||||
materials = list(MAT_METAL=5000, MAT_GLASS=2000)
|
||||
|
||||
var/tagname = null
|
||||
|
||||
/datum/design/electropack/shockcollar
|
||||
name = "Shockcollar"
|
||||
id = "shockcollar"
|
||||
build_type = AUTOLATHE
|
||||
build_path = /obj/item/electropack/shockcollar
|
||||
materials = list(MAT_METAL=5000, MAT_GLASS=2000)
|
||||
category = list("hacked", "Misc")
|
||||
|
||||
/obj/item/electropack/shockcollar/attack_hand(mob/user)
|
||||
if(loc == user && user.get_item_by_slot(SLOT_NECK))
|
||||
to_chat(user, "<span class='warning'>The collar is fastened tight! You'll need help taking this off!</span>")
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/electropack/shockcollar/receive_signal(datum/signal/signal)
|
||||
if(!signal || signal.data["code"] != code)
|
||||
return
|
||||
|
||||
if(isliving(loc) && on)
|
||||
if(shock_cooldown == TRUE)
|
||||
return
|
||||
shock_cooldown = TRUE
|
||||
addtimer(VARSET_CALLBACK(src, shock_cooldown, FALSE), 100)
|
||||
var/mob/living/L = loc
|
||||
step(L, pick(GLOB.cardinals))
|
||||
|
||||
to_chat(L, "<span class='danger'>You feel a sharp shock from the collar!</span>")
|
||||
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
|
||||
s.set_up(3, 1, L)
|
||||
s.start()
|
||||
|
||||
L.Knockdown(100)
|
||||
|
||||
if(master)
|
||||
master.receive_signal()
|
||||
return
|
||||
|
||||
/obj/item/electropack/shockcollar/attackby(obj/item/W, mob/user, params) //moves it here because on_click is being bad
|
||||
if(istype(W, /obj/item/pen))
|
||||
var/t = input(user, "Would you like to change the name on the tag?", "Name your new pet", tagname ? tagname : "Spot") as null|text
|
||||
if(t)
|
||||
tagname = copytext(sanitize(t), 1, MAX_NAME_LEN)
|
||||
name = "[initial(name)] - [tagname]"
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/electropack/shockcollar/ui_interact(mob/user) //on_click calls this
|
||||
var/dat = {"
|
||||
<TT>
|
||||
<B>Frequency/Code</B> for shock collar:<BR>
|
||||
Frequency:
|
||||
[format_frequency(src.frequency)]
|
||||
<A href='byond://?src=[REF(src)];set=freq'>Set</A><BR>
|
||||
Code:
|
||||
[src.code]
|
||||
<A href='byond://?src=[REF(src)];set=code'>Set</A><BR>
|
||||
</TT>"}
|
||||
user << browse(dat, "window=radio")
|
||||
onclose(user, "radio")
|
||||
return
|
||||
|
||||
@@ -1,343 +1,343 @@
|
||||
// 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
|
||||
))
|
||||
|
||||
/obj/item/radio/headset
|
||||
name = "radio headset"
|
||||
desc = "An updated, modular intercom that fits over the head. Takes encryption keys."
|
||||
icon_state = "headset"
|
||||
item_state = "headset"
|
||||
materials = list(MAT_METAL=75)
|
||||
subspace_transmission = TRUE
|
||||
canhear_range = 0 // can't hear headsets from very far away
|
||||
|
||||
slot_flags = ITEM_SLOT_EARS
|
||||
var/obj/item/encryptionkey/keyslot2 = null
|
||||
dog_fashion = null
|
||||
|
||||
/obj/item/radio/headset/suicide_act(mob/living/carbon/user)
|
||||
user.visible_message("<span class='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!</span>")
|
||||
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(translate_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 [lowertext(channels[i])]"
|
||||
else
|
||||
avail_chans += "use [GLOB.channel_tokens[channels[i]]] for [lowertext(channels[i])]"
|
||||
. += "<span class='notice'>A small screen on the headset displays the following available frequencies:\n[english_list(avail_chans)]."
|
||||
|
||||
if(command)
|
||||
. += "<span class='info'>Alt-click to toggle the high-volume mode.</span>"
|
||||
else
|
||||
. += "<span class='notice'>A small screen on the headset flashes, it's too small to read without holding or wearing the headset.</span>"
|
||||
|
||||
/obj/item/radio/headset/Initialize()
|
||||
. = ..()
|
||||
recalculateChannels()
|
||||
|
||||
/obj/item/radio/headset/Destroy()
|
||||
QDEL_NULL(keyslot2)
|
||||
return ..()
|
||||
|
||||
/obj/item/radio/headset/talk_into(mob/living/M, message, channel, list/spans,datum/language/language)
|
||||
if (!listening)
|
||||
return ITALICS | REDUCE_RANGE
|
||||
return ..()
|
||||
|
||||
/obj/item/radio/headset/can_receive(freq, level, AIuser)
|
||||
if(ishuman(src.loc))
|
||||
var/mob/living/carbon/human/H = src.loc
|
||||
if(H.ears == src)
|
||||
return ..(freq, level)
|
||||
else if(AIuser)
|
||||
return ..(freq, level)
|
||||
return FALSE
|
||||
|
||||
/obj/item/radio/headset/syndicate //disguised to look like a normal headset for stealth ops
|
||||
|
||||
/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"
|
||||
item_state = "syndie_headset"
|
||||
|
||||
/obj/item/radio/headset/syndicate/alt/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS))
|
||||
|
||||
/obj/item/radio/headset/syndicate/alt/leader
|
||||
name = "team leader headset"
|
||||
command = TRUE
|
||||
|
||||
/obj/item/radio/headset/syndicate/Initialize()
|
||||
. = ..()
|
||||
make_syndie()
|
||||
|
||||
/obj/item/radio/headset/binary
|
||||
/obj/item/radio/headset/binary/Initialize()
|
||||
. = ..()
|
||||
qdel(keyslot)
|
||||
keyslot = new /obj/item/encryptionkey/binary
|
||||
recalculateChannels()
|
||||
|
||||
/obj/item/radio/headset/headset_sec
|
||||
name = "security radio headset"
|
||||
desc = "This is used by your elite security force."
|
||||
icon_state = "sec_headset"
|
||||
keyslot = new /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"
|
||||
item_state = "sec_headset_alt"
|
||||
|
||||
/obj/item/radio/headset/headset_sec/alt/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/wearertargeting/earprotection, list(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"
|
||||
keyslot = new /obj/item/encryptionkey/headset_eng
|
||||
|
||||
/obj/item/radio/headset/headset_med
|
||||
name = "medical radio headset"
|
||||
desc = "A headset for the trained staff of the medbay."
|
||||
icon_state = "med_headset"
|
||||
keyslot = new /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"
|
||||
keyslot = new /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"
|
||||
keyslot = new /obj/item/encryptionkey/headset_medsci
|
||||
|
||||
/obj/item/radio/headset/headset_com
|
||||
name = "command radio headset"
|
||||
desc = "A headset with a commanding channel.\nTo access the command channel, use :c."
|
||||
icon_state = "com_headset"
|
||||
keyslot = new /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"
|
||||
keyslot = new /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"
|
||||
item_state = "com_headset_alt"
|
||||
|
||||
/obj/item/radio/headset/heads/captain/alt/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/wearertargeting/earprotection, list(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"
|
||||
keyslot = new /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"
|
||||
keyslot = new /obj/item/encryptionkey/heads/hos
|
||||
|
||||
/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"
|
||||
item_state = "com_headset_alt"
|
||||
|
||||
/obj/item/radio/headset/heads/hos/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/wearertargeting/earprotection, list(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"
|
||||
keyslot = new /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"
|
||||
keyslot = new /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"
|
||||
keyslot = new /obj/item/encryptionkey/heads/hop
|
||||
|
||||
/obj/item/radio/headset/heads/qm
|
||||
name = "\proper the quartermaster's headset"
|
||||
desc = "The headset of the king (or queen) of paperwork."
|
||||
icon_state = "com_headset"
|
||||
keyslot = new /obj/item/encryptionkey/heads/qm
|
||||
|
||||
/obj/item/radio/headset/headset_cargo
|
||||
name = "supply radio headset"
|
||||
desc = "A headset used by the QM and his slaves."
|
||||
icon_state = "cargo_headset"
|
||||
keyslot = new /obj/item/encryptionkey/headset_cargo
|
||||
|
||||
/obj/item/radio/headset/headset_cargo/mining
|
||||
name = "mining radio headset"
|
||||
desc = "Headset used by shaft miners."
|
||||
icon_state = "mine_headset"
|
||||
keyslot = new /obj/item/encryptionkey/headset_mining
|
||||
|
||||
/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"
|
||||
keyslot = new /obj/item/encryptionkey/headset_service
|
||||
|
||||
/obj/item/radio/headset/headset_clown
|
||||
name = "clown's headset"
|
||||
desc = "A headset for the clown. Finally. A megaphone you can't take away."
|
||||
icon_state = "srv_headset"
|
||||
keyslot = new /obj/item/encryptionkey/headset_service
|
||||
command = TRUE
|
||||
commandspan = SPAN_CLOWN
|
||||
|
||||
/obj/item/radio/headset/headset_cent
|
||||
name = "\improper CentCom headset"
|
||||
desc = "A headset used by the upper echelons of Nanotrasen."
|
||||
icon_state = "cent_headset"
|
||||
keyslot = new /obj/item/encryptionkey/headset_com
|
||||
keyslot2 = new /obj/item/encryptionkey/headset_cent
|
||||
|
||||
/obj/item/radio/headset/headset_cent/empty
|
||||
keyslot = null
|
||||
keyslot2 = null
|
||||
|
||||
/obj/item/radio/headset/headset_cent/commander
|
||||
keyslot = new /obj/item/encryptionkey/heads/captain
|
||||
|
||||
/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"
|
||||
item_state = "cent_headset_alt"
|
||||
keyslot = null
|
||||
|
||||
/obj/item/radio/headset/headset_cent/alt/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS))
|
||||
|
||||
/obj/item/radio/headset/ai
|
||||
name = "\proper Integrated Subspace Transceiver "
|
||||
keyslot2 = new /obj/item/encryptionkey/ai
|
||||
command = TRUE
|
||||
|
||||
/obj/item/radio/headset/ai/can_receive(freq, level)
|
||||
return ..(freq, level, TRUE)
|
||||
|
||||
/obj/item/radio/headset/attackby(obj/item/W, mob/user, params)
|
||||
user.set_machine(src)
|
||||
|
||||
if(istype(W, /obj/item/screwdriver))
|
||||
if(keyslot || keyslot2)
|
||||
for(var/ch_name in channels)
|
||||
SSradio.remove_object(src, GLOB.radiochannels[ch_name])
|
||||
secure_radio_connections[ch_name] = null
|
||||
|
||||
var/turf/T = user.drop_location()
|
||||
if(T)
|
||||
if(keyslot)
|
||||
keyslot.forceMove(T)
|
||||
keyslot = null
|
||||
if(keyslot2)
|
||||
keyslot2.forceMove(T)
|
||||
keyslot2 = null
|
||||
|
||||
recalculateChannels()
|
||||
to_chat(user, "<span class='notice'>You pop out the encryption keys in the headset.</span>")
|
||||
|
||||
else
|
||||
to_chat(user, "<span class='warning'>This headset doesn't have any unique encryption keys! How useless...</span>")
|
||||
|
||||
else if(istype(W, /obj/item/encryptionkey))
|
||||
if(keyslot && keyslot2)
|
||||
to_chat(user, "<span class='warning'>The headset can't hold another key!</span>")
|
||||
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))
|
||||
channels[ch_name] = keyslot2.channels[ch_name]
|
||||
|
||||
if(keyslot2.translate_binary)
|
||||
translate_binary = TRUE
|
||||
if(keyslot2.syndie)
|
||||
syndie = TRUE
|
||||
if (keyslot2.independent)
|
||||
independent = TRUE
|
||||
|
||||
for(var/ch_name in channels)
|
||||
secure_radio_connections[ch_name] = add_radio(src, GLOB.radiochannels[ch_name])
|
||||
|
||||
/obj/item/radio/headset/AltClick(mob/living/user)
|
||||
. = ..()
|
||||
if(!istype(user) || !Adjacent(user) || user.incapacitated())
|
||||
return
|
||||
if (command)
|
||||
use_command = !use_command
|
||||
to_chat(user, "<span class='notice'>You toggle high-volume mode [use_command ? "on" : "off"].</span>")
|
||||
return TRUE
|
||||
// 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
|
||||
))
|
||||
|
||||
/obj/item/radio/headset
|
||||
name = "radio headset"
|
||||
desc = "An updated, modular intercom that fits over the head. Takes encryption keys."
|
||||
icon_state = "headset"
|
||||
item_state = "headset"
|
||||
materials = list(MAT_METAL=75)
|
||||
subspace_transmission = TRUE
|
||||
canhear_range = 0 // can't hear headsets from very far away
|
||||
|
||||
slot_flags = ITEM_SLOT_EARS
|
||||
var/obj/item/encryptionkey/keyslot2 = null
|
||||
dog_fashion = null
|
||||
|
||||
/obj/item/radio/headset/suicide_act(mob/living/carbon/user)
|
||||
user.visible_message("<span class='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!</span>")
|
||||
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(translate_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 [lowertext(channels[i])]"
|
||||
else
|
||||
avail_chans += "use [GLOB.channel_tokens[channels[i]]] for [lowertext(channels[i])]"
|
||||
. += "<span class='notice'>A small screen on the headset displays the following available frequencies:\n[english_list(avail_chans)]."
|
||||
|
||||
if(command)
|
||||
. += "<span class='info'>Alt-click to toggle the high-volume mode.</span>"
|
||||
else
|
||||
. += "<span class='notice'>A small screen on the headset flashes, it's too small to read without holding or wearing the headset.</span>"
|
||||
|
||||
/obj/item/radio/headset/Initialize()
|
||||
. = ..()
|
||||
recalculateChannels()
|
||||
|
||||
/obj/item/radio/headset/Destroy()
|
||||
QDEL_NULL(keyslot2)
|
||||
return ..()
|
||||
|
||||
/obj/item/radio/headset/talk_into(mob/living/M, message, channel, list/spans,datum/language/language)
|
||||
if (!listening)
|
||||
return ITALICS | REDUCE_RANGE
|
||||
return ..()
|
||||
|
||||
/obj/item/radio/headset/can_receive(freq, level, AIuser)
|
||||
if(ishuman(src.loc))
|
||||
var/mob/living/carbon/human/H = src.loc
|
||||
if(H.ears == src)
|
||||
return ..(freq, level)
|
||||
else if(AIuser)
|
||||
return ..(freq, level)
|
||||
return FALSE
|
||||
|
||||
/obj/item/radio/headset/syndicate //disguised to look like a normal headset for stealth ops
|
||||
|
||||
/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"
|
||||
item_state = "syndie_headset"
|
||||
|
||||
/obj/item/radio/headset/syndicate/alt/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS))
|
||||
|
||||
/obj/item/radio/headset/syndicate/alt/leader
|
||||
name = "team leader headset"
|
||||
command = TRUE
|
||||
|
||||
/obj/item/radio/headset/syndicate/Initialize()
|
||||
. = ..()
|
||||
make_syndie()
|
||||
|
||||
/obj/item/radio/headset/binary
|
||||
/obj/item/radio/headset/binary/Initialize()
|
||||
. = ..()
|
||||
qdel(keyslot)
|
||||
keyslot = new /obj/item/encryptionkey/binary
|
||||
recalculateChannels()
|
||||
|
||||
/obj/item/radio/headset/headset_sec
|
||||
name = "security radio headset"
|
||||
desc = "This is used by your elite security force."
|
||||
icon_state = "sec_headset"
|
||||
keyslot = new /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"
|
||||
item_state = "sec_headset_alt"
|
||||
|
||||
/obj/item/radio/headset/headset_sec/alt/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/wearertargeting/earprotection, list(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"
|
||||
keyslot = new /obj/item/encryptionkey/headset_eng
|
||||
|
||||
/obj/item/radio/headset/headset_med
|
||||
name = "medical radio headset"
|
||||
desc = "A headset for the trained staff of the medbay."
|
||||
icon_state = "med_headset"
|
||||
keyslot = new /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"
|
||||
keyslot = new /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"
|
||||
keyslot = new /obj/item/encryptionkey/headset_medsci
|
||||
|
||||
/obj/item/radio/headset/headset_com
|
||||
name = "command radio headset"
|
||||
desc = "A headset with a commanding channel.\nTo access the command channel, use :c."
|
||||
icon_state = "com_headset"
|
||||
keyslot = new /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"
|
||||
keyslot = new /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"
|
||||
item_state = "com_headset_alt"
|
||||
|
||||
/obj/item/radio/headset/heads/captain/alt/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/wearertargeting/earprotection, list(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"
|
||||
keyslot = new /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"
|
||||
keyslot = new /obj/item/encryptionkey/heads/hos
|
||||
|
||||
/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"
|
||||
item_state = "com_headset_alt"
|
||||
|
||||
/obj/item/radio/headset/heads/hos/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/wearertargeting/earprotection, list(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"
|
||||
keyslot = new /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"
|
||||
keyslot = new /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"
|
||||
keyslot = new /obj/item/encryptionkey/heads/hop
|
||||
|
||||
/obj/item/radio/headset/heads/qm
|
||||
name = "\proper the quartermaster's headset"
|
||||
desc = "The headset of the king (or queen) of paperwork."
|
||||
icon_state = "com_headset"
|
||||
keyslot = new /obj/item/encryptionkey/heads/qm
|
||||
|
||||
/obj/item/radio/headset/headset_cargo
|
||||
name = "supply radio headset"
|
||||
desc = "A headset used by the QM and his slaves."
|
||||
icon_state = "cargo_headset"
|
||||
keyslot = new /obj/item/encryptionkey/headset_cargo
|
||||
|
||||
/obj/item/radio/headset/headset_cargo/mining
|
||||
name = "mining radio headset"
|
||||
desc = "Headset used by shaft miners."
|
||||
icon_state = "mine_headset"
|
||||
keyslot = new /obj/item/encryptionkey/headset_mining
|
||||
|
||||
/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"
|
||||
keyslot = new /obj/item/encryptionkey/headset_service
|
||||
|
||||
/obj/item/radio/headset/headset_clown
|
||||
name = "clown's headset"
|
||||
desc = "A headset for the clown. Finally. A megaphone you can't take away."
|
||||
icon_state = "srv_headset"
|
||||
keyslot = new /obj/item/encryptionkey/headset_service
|
||||
command = TRUE
|
||||
commandspan = SPAN_CLOWN
|
||||
|
||||
/obj/item/radio/headset/headset_cent
|
||||
name = "\improper CentCom headset"
|
||||
desc = "A headset used by the upper echelons of Nanotrasen."
|
||||
icon_state = "cent_headset"
|
||||
keyslot = new /obj/item/encryptionkey/headset_com
|
||||
keyslot2 = new /obj/item/encryptionkey/headset_cent
|
||||
|
||||
/obj/item/radio/headset/headset_cent/empty
|
||||
keyslot = null
|
||||
keyslot2 = null
|
||||
|
||||
/obj/item/radio/headset/headset_cent/commander
|
||||
keyslot = new /obj/item/encryptionkey/heads/captain
|
||||
|
||||
/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"
|
||||
item_state = "cent_headset_alt"
|
||||
keyslot = null
|
||||
|
||||
/obj/item/radio/headset/headset_cent/alt/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS))
|
||||
|
||||
/obj/item/radio/headset/ai
|
||||
name = "\proper Integrated Subspace Transceiver "
|
||||
keyslot2 = new /obj/item/encryptionkey/ai
|
||||
command = TRUE
|
||||
|
||||
/obj/item/radio/headset/ai/can_receive(freq, level)
|
||||
return ..(freq, level, TRUE)
|
||||
|
||||
/obj/item/radio/headset/attackby(obj/item/W, mob/user, params)
|
||||
user.set_machine(src)
|
||||
|
||||
if(istype(W, /obj/item/screwdriver))
|
||||
if(keyslot || keyslot2)
|
||||
for(var/ch_name in channels)
|
||||
SSradio.remove_object(src, GLOB.radiochannels[ch_name])
|
||||
secure_radio_connections[ch_name] = null
|
||||
|
||||
var/turf/T = user.drop_location()
|
||||
if(T)
|
||||
if(keyslot)
|
||||
keyslot.forceMove(T)
|
||||
keyslot = null
|
||||
if(keyslot2)
|
||||
keyslot2.forceMove(T)
|
||||
keyslot2 = null
|
||||
|
||||
recalculateChannels()
|
||||
to_chat(user, "<span class='notice'>You pop out the encryption keys in the headset.</span>")
|
||||
|
||||
else
|
||||
to_chat(user, "<span class='warning'>This headset doesn't have any unique encryption keys! How useless...</span>")
|
||||
|
||||
else if(istype(W, /obj/item/encryptionkey))
|
||||
if(keyslot && keyslot2)
|
||||
to_chat(user, "<span class='warning'>The headset can't hold another key!</span>")
|
||||
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))
|
||||
channels[ch_name] = keyslot2.channels[ch_name]
|
||||
|
||||
if(keyslot2.translate_binary)
|
||||
translate_binary = TRUE
|
||||
if(keyslot2.syndie)
|
||||
syndie = TRUE
|
||||
if (keyslot2.independent)
|
||||
independent = TRUE
|
||||
|
||||
for(var/ch_name in channels)
|
||||
secure_radio_connections[ch_name] = add_radio(src, GLOB.radiochannels[ch_name])
|
||||
|
||||
/obj/item/radio/headset/AltClick(mob/living/user)
|
||||
. = ..()
|
||||
if(!istype(user) || !Adjacent(user) || user.incapacitated())
|
||||
return
|
||||
if (command)
|
||||
use_command = !use_command
|
||||
to_chat(user, "<span class='notice'>You toggle high-volume mode [use_command ? "on" : "off"].</span>")
|
||||
return TRUE
|
||||
|
||||
@@ -1,150 +1,150 @@
|
||||
/obj/item/radio/intercom
|
||||
name = "station intercom"
|
||||
desc = "Talk through this."
|
||||
icon_state = "intercom"
|
||||
anchored = TRUE
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
canhear_range = 2
|
||||
var/number = 0
|
||||
var/anyai = 1
|
||||
var/mob/living/silicon/ai/ai = list()
|
||||
var/last_tick //used to delay the powercheck
|
||||
dog_fashion = null
|
||||
var/unfastened = FALSE
|
||||
|
||||
/obj/item/radio/intercom/unscrewed
|
||||
unfastened = TRUE
|
||||
|
||||
/obj/item/radio/intercom/ratvar
|
||||
name = "hierophant intercom"
|
||||
desc = "A modified intercom that uses the Hierophant network instead of subspace tech. Can listen to and broadcast on any frequency."
|
||||
icon_state = "intercom_ratvar"
|
||||
freerange = TRUE
|
||||
|
||||
/obj/item/radio/intercom/ratvar/attackby(obj/item/I, mob/living/user, params)
|
||||
if(istype(I, /obj/item/screwdriver))
|
||||
to_chat(user, "<span class='danger'>[src] is fastened to the wall with [is_servant_of_ratvar(user) ? "replicant alloy" : "some material you've never seen"], and can't be removed.</span>")
|
||||
return //no unfastening!
|
||||
. = ..()
|
||||
|
||||
/obj/item/radio/intercom/ratvar/process()
|
||||
if(!istype(SSticker.mode, /datum/game_mode/clockwork_cult))
|
||||
invisibility = INVISIBILITY_OBSERVER
|
||||
alpha = 125
|
||||
emped = TRUE
|
||||
else
|
||||
invisibility = initial(invisibility)
|
||||
alpha = initial(alpha)
|
||||
emped = FALSE
|
||||
..()
|
||||
|
||||
/obj/item/radio/intercom/Initialize(mapload, ndir, building)
|
||||
. = ..()
|
||||
if(building)
|
||||
setDir(ndir)
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/radio/intercom/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/obj/item/radio/intercom/examine(mob/user)
|
||||
. = ..()
|
||||
if(!unfastened)
|
||||
. += "<span class='notice'>It's <b>screwed</b> and secured to the wall.</span>"
|
||||
else
|
||||
. += "<span class='notice'>It's <i>unscrewed</i> from the wall, and can be <b>detached</b>.</span>"
|
||||
|
||||
/obj/item/radio/intercom/attackby(obj/item/I, mob/living/user, params)
|
||||
if(istype(I, /obj/item/screwdriver))
|
||||
if(unfastened)
|
||||
user.visible_message("<span class='notice'>[user] starts tightening [src]'s screws...</span>", "<span class='notice'>You start screwing in [src]...</span>")
|
||||
if(I.use_tool(src, user, 30, volume=50))
|
||||
user.visible_message("<span class='notice'>[user] tightens [src]'s screws!</span>", "<span class='notice'>You tighten [src]'s screws.</span>")
|
||||
unfastened = FALSE
|
||||
else
|
||||
user.visible_message("<span class='notice'>[user] starts loosening [src]'s screws...</span>", "<span class='notice'>You start unscrewing [src]...</span>")
|
||||
if(I.use_tool(src, user, 40, volume=50))
|
||||
user.visible_message("<span class='notice'>[user] loosens [src]'s screws!</span>", "<span class='notice'>You unscrew [src], loosening it from the wall.</span>")
|
||||
unfastened = TRUE
|
||||
return
|
||||
else if(istype(I, /obj/item/wrench))
|
||||
if(!unfastened)
|
||||
to_chat(user, "<span class='warning'>You need to unscrew [src] from the wall first!</span>")
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] starts unsecuring [src]...</span>", "<span class='notice'>You start unsecuring [src]...</span>")
|
||||
I.play_tool_sound(src)
|
||||
if(I.use_tool(src, user, 80))
|
||||
user.visible_message("<span class='notice'>[user] unsecures [src]!</span>", "<span class='notice'>You detach [src] from the wall.</span>")
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
new/obj/item/wallframe/intercom(get_turf(src))
|
||||
qdel(src)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/radio/intercom/attack_ai(mob/user)
|
||||
interact(user)
|
||||
|
||||
/obj/item/radio/intercom/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
interact(user)
|
||||
|
||||
/obj/item/radio/intercom/interact(mob/user)
|
||||
..()
|
||||
ui_interact(user, state = GLOB.default_state)
|
||||
|
||||
/obj/item/radio/intercom/can_receive(freq, level)
|
||||
if(!on)
|
||||
return FALSE
|
||||
if(wires.is_cut(WIRE_RX))
|
||||
return FALSE
|
||||
if(!(0 in level))
|
||||
var/turf/position = get_turf(src)
|
||||
if(isnull(position) || !(position.z in level))
|
||||
return FALSE
|
||||
if(!src.listening)
|
||||
return FALSE
|
||||
if(freq == FREQ_SYNDICATE)
|
||||
if(!(src.syndie))
|
||||
return FALSE//Prevents broadcast of messages over devices lacking the encryption
|
||||
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/item/radio/intercom/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
|
||||
. = ..()
|
||||
if (message_mode == MODE_INTERCOM)
|
||||
return // Avoid hearing the same thing twice
|
||||
if(!anyai && !(speaker in ai))
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/radio/intercom/process()
|
||||
if(((world.timeofday - last_tick) > 30) || ((world.timeofday - last_tick) < 0))
|
||||
last_tick = world.timeofday
|
||||
|
||||
var/area/A = get_area(src)
|
||||
if(!A || emped)
|
||||
on = FALSE
|
||||
else
|
||||
on = A.powered(EQUIP) // set "on" to the power status
|
||||
|
||||
if(!on)
|
||||
icon_state = "intercom-p"
|
||||
else
|
||||
icon_state = initial(icon_state)
|
||||
|
||||
/obj/item/radio/intercom/add_blood_DNA(list/blood_dna)
|
||||
return FALSE
|
||||
|
||||
//Created through the autolathe or through deconstructing intercoms. Can be applied to wall to make a new intercom on it!
|
||||
/obj/item/wallframe/intercom
|
||||
name = "intercom frame"
|
||||
desc = "A ready-to-go intercom. Just slap it on a wall and screw it in!"
|
||||
icon_state = "intercom"
|
||||
result_path = /obj/item/radio/intercom/unscrewed
|
||||
pixel_shift = 29
|
||||
inverse = TRUE
|
||||
materials = list(MAT_METAL = 75, MAT_GLASS = 25)
|
||||
/obj/item/radio/intercom
|
||||
name = "station intercom"
|
||||
desc = "Talk through this."
|
||||
icon_state = "intercom"
|
||||
anchored = TRUE
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
canhear_range = 2
|
||||
var/number = 0
|
||||
var/anyai = 1
|
||||
var/mob/living/silicon/ai/ai = list()
|
||||
var/last_tick //used to delay the powercheck
|
||||
dog_fashion = null
|
||||
var/unfastened = FALSE
|
||||
|
||||
/obj/item/radio/intercom/unscrewed
|
||||
unfastened = TRUE
|
||||
|
||||
/obj/item/radio/intercom/ratvar
|
||||
name = "hierophant intercom"
|
||||
desc = "A modified intercom that uses the Hierophant network instead of subspace tech. Can listen to and broadcast on any frequency."
|
||||
icon_state = "intercom_ratvar"
|
||||
freerange = TRUE
|
||||
|
||||
/obj/item/radio/intercom/ratvar/attackby(obj/item/I, mob/living/user, params)
|
||||
if(istype(I, /obj/item/screwdriver))
|
||||
to_chat(user, "<span class='danger'>[src] is fastened to the wall with [is_servant_of_ratvar(user) ? "replicant alloy" : "some material you've never seen"], and can't be removed.</span>")
|
||||
return //no unfastening!
|
||||
. = ..()
|
||||
|
||||
/obj/item/radio/intercom/ratvar/process()
|
||||
if(!istype(SSticker.mode, /datum/game_mode/clockwork_cult))
|
||||
invisibility = INVISIBILITY_OBSERVER
|
||||
alpha = 125
|
||||
emped = TRUE
|
||||
else
|
||||
invisibility = initial(invisibility)
|
||||
alpha = initial(alpha)
|
||||
emped = FALSE
|
||||
..()
|
||||
|
||||
/obj/item/radio/intercom/Initialize(mapload, ndir, building)
|
||||
. = ..()
|
||||
if(building)
|
||||
setDir(ndir)
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/radio/intercom/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/obj/item/radio/intercom/examine(mob/user)
|
||||
. = ..()
|
||||
if(!unfastened)
|
||||
. += "<span class='notice'>It's <b>screwed</b> and secured to the wall.</span>"
|
||||
else
|
||||
. += "<span class='notice'>It's <i>unscrewed</i> from the wall, and can be <b>detached</b>.</span>"
|
||||
|
||||
/obj/item/radio/intercom/attackby(obj/item/I, mob/living/user, params)
|
||||
if(istype(I, /obj/item/screwdriver))
|
||||
if(unfastened)
|
||||
user.visible_message("<span class='notice'>[user] starts tightening [src]'s screws...</span>", "<span class='notice'>You start screwing in [src]...</span>")
|
||||
if(I.use_tool(src, user, 30, volume=50))
|
||||
user.visible_message("<span class='notice'>[user] tightens [src]'s screws!</span>", "<span class='notice'>You tighten [src]'s screws.</span>")
|
||||
unfastened = FALSE
|
||||
else
|
||||
user.visible_message("<span class='notice'>[user] starts loosening [src]'s screws...</span>", "<span class='notice'>You start unscrewing [src]...</span>")
|
||||
if(I.use_tool(src, user, 40, volume=50))
|
||||
user.visible_message("<span class='notice'>[user] loosens [src]'s screws!</span>", "<span class='notice'>You unscrew [src], loosening it from the wall.</span>")
|
||||
unfastened = TRUE
|
||||
return
|
||||
else if(istype(I, /obj/item/wrench))
|
||||
if(!unfastened)
|
||||
to_chat(user, "<span class='warning'>You need to unscrew [src] from the wall first!</span>")
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] starts unsecuring [src]...</span>", "<span class='notice'>You start unsecuring [src]...</span>")
|
||||
I.play_tool_sound(src)
|
||||
if(I.use_tool(src, user, 80))
|
||||
user.visible_message("<span class='notice'>[user] unsecures [src]!</span>", "<span class='notice'>You detach [src] from the wall.</span>")
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
new/obj/item/wallframe/intercom(get_turf(src))
|
||||
qdel(src)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/radio/intercom/attack_ai(mob/user)
|
||||
interact(user)
|
||||
|
||||
/obj/item/radio/intercom/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
interact(user)
|
||||
|
||||
/obj/item/radio/intercom/interact(mob/user)
|
||||
..()
|
||||
ui_interact(user, state = GLOB.default_state)
|
||||
|
||||
/obj/item/radio/intercom/can_receive(freq, level)
|
||||
if(!on)
|
||||
return FALSE
|
||||
if(wires.is_cut(WIRE_RX))
|
||||
return FALSE
|
||||
if(!(0 in level))
|
||||
var/turf/position = get_turf(src)
|
||||
if(isnull(position) || !(position.z in level))
|
||||
return FALSE
|
||||
if(!src.listening)
|
||||
return FALSE
|
||||
if(freq == FREQ_SYNDICATE)
|
||||
if(!(src.syndie))
|
||||
return FALSE//Prevents broadcast of messages over devices lacking the encryption
|
||||
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/item/radio/intercom/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
|
||||
. = ..()
|
||||
if (message_mode == MODE_INTERCOM)
|
||||
return // Avoid hearing the same thing twice
|
||||
if(!anyai && !(speaker in ai))
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/radio/intercom/process()
|
||||
if(((world.timeofday - last_tick) > 30) || ((world.timeofday - last_tick) < 0))
|
||||
last_tick = world.timeofday
|
||||
|
||||
var/area/A = get_area(src)
|
||||
if(!A || emped)
|
||||
on = FALSE
|
||||
else
|
||||
on = A.powered(EQUIP) // set "on" to the power status
|
||||
|
||||
if(!on)
|
||||
icon_state = "intercom-p"
|
||||
else
|
||||
icon_state = initial(icon_state)
|
||||
|
||||
/obj/item/radio/intercom/add_blood_DNA(list/blood_dna)
|
||||
return FALSE
|
||||
|
||||
//Created through the autolathe or through deconstructing intercoms. Can be applied to wall to make a new intercom on it!
|
||||
/obj/item/wallframe/intercom
|
||||
name = "intercom frame"
|
||||
desc = "A ready-to-go intercom. Just slap it on a wall and screw it in!"
|
||||
icon_state = "intercom"
|
||||
result_path = /obj/item/radio/intercom/unscrewed
|
||||
pixel_shift = 29
|
||||
inverse = TRUE
|
||||
materials = list(MAT_METAL = 75, MAT_GLASS = 25)
|
||||
|
||||
@@ -1,429 +1,429 @@
|
||||
/obj/item/radio
|
||||
icon = 'icons/obj/radio.dmi'
|
||||
name = "station bounced radio"
|
||||
icon_state = "walkietalkie"
|
||||
item_state = "walkietalkie"
|
||||
desc = "A basic handheld radio that communicates with local telecommunication networks."
|
||||
dog_fashion = /datum/dog_fashion/back
|
||||
|
||||
flags_1 = CONDUCT_1 | HEAR_1
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
throw_speed = 3
|
||||
throw_range = 7
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
materials = list(MAT_METAL=75, MAT_GLASS=25)
|
||||
obj_flags = USES_TGUI
|
||||
|
||||
var/on = TRUE
|
||||
var/frequency = FREQ_COMMON
|
||||
var/canhear_range = 3 // The range around the radio in which mobs can hear what it receives.
|
||||
var/emped = 0 // Tracks the number of EMPs currently stacked.
|
||||
|
||||
var/broadcasting = FALSE // Whether the radio will transmit dialogue it hears nearby.
|
||||
var/listening = TRUE // Whether the radio is currently receiving.
|
||||
var/prison_radio = FALSE // If true, the transmit wire starts cut.
|
||||
var/unscrewed = FALSE // Whether wires are accessible. Toggleable by screwdrivering.
|
||||
var/freerange = FALSE // If true, the radio has access to the full spectrum.
|
||||
var/subspace_transmission = FALSE // If true, the radio transmits and receives on subspace exclusively.
|
||||
var/subspace_switchable = FALSE // If true, subspace_transmission can be toggled at will.
|
||||
var/freqlock = FALSE // Frequency lock to stop the user from untuning specialist radios.
|
||||
var/use_command = FALSE // If true, broadcasts will be large and BOLD.
|
||||
var/command = FALSE // If true, use_command can be toggled at will.
|
||||
var/commandspan = SPAN_COMMAND //allow us to set what the fuck we want for headsets
|
||||
|
||||
// Encryption key handling
|
||||
var/obj/item/encryptionkey/keyslot
|
||||
var/translate_binary = FALSE // If true, can hear the special binary channel.
|
||||
var/independent = FALSE // If true, can say/hear on the special CentCom channel.
|
||||
var/syndie = FALSE // If true, hears all well-known channels automatically, and can say/hear on the Syndicate channel.
|
||||
var/list/channels = list() // Map from name (see communications.dm) to on/off. First entry is current department (:h).
|
||||
var/list/secure_radio_connections
|
||||
|
||||
var/const/FREQ_LISTENING = 1
|
||||
//FREQ_BROADCASTING = 2
|
||||
|
||||
/obj/item/radio/suicide_act(mob/living/user)
|
||||
user.visible_message("<span class='suicide'>[user] starts bouncing [src] off [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
return BRUTELOSS
|
||||
|
||||
/obj/item/radio/proc/set_frequency(new_frequency)
|
||||
SEND_SIGNAL(src, COMSIG_RADIO_NEW_FREQUENCY, args)
|
||||
remove_radio(src, frequency)
|
||||
frequency = add_radio(src, new_frequency)
|
||||
|
||||
/obj/item/radio/proc/recalculateChannels()
|
||||
channels = list()
|
||||
translate_binary = FALSE
|
||||
syndie = FALSE
|
||||
independent = FALSE
|
||||
|
||||
if(keyslot)
|
||||
for(var/ch_name in keyslot.channels)
|
||||
if(!(ch_name in channels))
|
||||
channels[ch_name] = keyslot.channels[ch_name]
|
||||
|
||||
if(keyslot.translate_binary)
|
||||
translate_binary = TRUE
|
||||
if(keyslot.syndie)
|
||||
syndie = TRUE
|
||||
if(keyslot.independent)
|
||||
independent = TRUE
|
||||
|
||||
for(var/ch_name in channels)
|
||||
secure_radio_connections[ch_name] = add_radio(src, GLOB.radiochannels[ch_name])
|
||||
|
||||
/obj/item/radio/proc/make_syndie() // Turns normal radios into Syndicate radios!
|
||||
qdel(keyslot)
|
||||
keyslot = new /obj/item/encryptionkey/syndicate
|
||||
syndie = 1
|
||||
recalculateChannels()
|
||||
|
||||
/obj/item/radio/Destroy()
|
||||
remove_radio_all(src) //Just to be sure
|
||||
QDEL_NULL(wires)
|
||||
QDEL_NULL(keyslot)
|
||||
return ..()
|
||||
|
||||
/obj/item/radio/Initialize()
|
||||
wires = new /datum/wires/radio(src)
|
||||
if(prison_radio)
|
||||
wires.cut(WIRE_TX) // OH GOD WHY
|
||||
secure_radio_connections = new
|
||||
. = ..()
|
||||
frequency = sanitize_frequency(frequency, freerange)
|
||||
set_frequency(frequency)
|
||||
|
||||
for(var/ch_name in channels)
|
||||
secure_radio_connections[ch_name] = add_radio(src, GLOB.radiochannels[ch_name])
|
||||
|
||||
/obj/item/radio/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/empprotection, EMP_PROTECT_WIRES)
|
||||
|
||||
/obj/item/radio/interact(mob/user)
|
||||
if(unscrewed && !isAI(user))
|
||||
wires.interact(user)
|
||||
add_fingerprint(user)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/radio/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state)
|
||||
. = ..()
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "radio", name, 370, 220 + channels.len * 22, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/item/radio/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
data["broadcasting"] = broadcasting
|
||||
data["listening"] = listening
|
||||
data["frequency"] = frequency
|
||||
data["minFrequency"] = freerange ? MIN_FREE_FREQ : MIN_FREQ
|
||||
data["maxFrequency"] = freerange ? MAX_FREE_FREQ : MAX_FREQ
|
||||
data["freqlock"] = freqlock
|
||||
data["channels"] = list()
|
||||
for(var/channel in channels)
|
||||
data["channels"][channel] = channels[channel] & FREQ_LISTENING
|
||||
data["command"] = command
|
||||
data["useCommand"] = use_command
|
||||
data["subspace"] = subspace_transmission
|
||||
data["subspaceSwitchable"] = subspace_switchable
|
||||
data["headset"] = istype(src, /obj/item/radio/headset)
|
||||
|
||||
return data
|
||||
|
||||
/obj/item/radio/ui_act(action, params, datum/tgui/ui)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("frequency")
|
||||
if(freqlock)
|
||||
return
|
||||
var/tune = params["tune"]
|
||||
var/adjust = text2num(params["adjust"])
|
||||
if(tune == "input")
|
||||
var/min = format_frequency(freerange ? MIN_FREE_FREQ : MIN_FREQ)
|
||||
var/max = format_frequency(freerange ? MAX_FREE_FREQ : MAX_FREQ)
|
||||
tune = input("Tune frequency ([min]-[max]):", name, format_frequency(frequency)) as null|num
|
||||
if(!isnull(tune) && !..())
|
||||
if (tune < MIN_FREE_FREQ && tune <= MAX_FREE_FREQ / 10)
|
||||
// allow typing 144.7 to get 1447
|
||||
tune *= 10
|
||||
. = TRUE
|
||||
else if(adjust)
|
||||
tune = frequency + adjust * 10
|
||||
. = TRUE
|
||||
else if(text2num(tune) != null)
|
||||
tune = tune * 10
|
||||
. = TRUE
|
||||
if(.)
|
||||
set_frequency(sanitize_frequency(tune, freerange))
|
||||
if("listen")
|
||||
listening = !listening
|
||||
. = TRUE
|
||||
if("broadcast")
|
||||
broadcasting = !broadcasting
|
||||
. = TRUE
|
||||
if("channel")
|
||||
var/channel = params["channel"]
|
||||
if(!(channel in channels))
|
||||
return
|
||||
if(channels[channel] & FREQ_LISTENING)
|
||||
channels[channel] &= ~FREQ_LISTENING
|
||||
else
|
||||
channels[channel] |= FREQ_LISTENING
|
||||
. = TRUE
|
||||
if("command")
|
||||
use_command = !use_command
|
||||
. = TRUE
|
||||
if("subspace")
|
||||
if(subspace_switchable)
|
||||
subspace_transmission = !subspace_transmission
|
||||
if(!subspace_transmission)
|
||||
channels = list()
|
||||
else
|
||||
recalculateChannels()
|
||||
. = TRUE
|
||||
|
||||
/obj/item/radio/talk_into(atom/movable/M, message, channel, list/spans, datum/language/language)
|
||||
if(!spans)
|
||||
spans = list(M.speech_span)
|
||||
if(!language)
|
||||
language = M.get_default_language()
|
||||
INVOKE_ASYNC(src, .proc/talk_into_impl, M, message, channel, spans.Copy(), language)
|
||||
return ITALICS | REDUCE_RANGE
|
||||
|
||||
/obj/item/radio/proc/talk_into_impl(atom/movable/M, message, channel, list/spans, datum/language/language)
|
||||
if(!on)
|
||||
return // the device has to be on
|
||||
if(!M || !message)
|
||||
return
|
||||
if(wires.is_cut(WIRE_TX)) // Permacell and otherwise tampered-with radios
|
||||
return
|
||||
if(!M.IsVocal())
|
||||
return
|
||||
|
||||
if(use_command)
|
||||
spans |= commandspan
|
||||
|
||||
/*
|
||||
Roughly speaking, radios attempt to make a subspace transmission (which
|
||||
is received, processed, and rebroadcast by the telecomms satellite) and
|
||||
if that fails, they send a mundane radio transmission.
|
||||
|
||||
Headsets cannot send/receive mundane transmissions, only subspace.
|
||||
Syndicate radios can hear transmissions on all well-known frequencies.
|
||||
CentCom radios can hear the CentCom frequency no matter what.
|
||||
*/
|
||||
|
||||
// From the channel, determine the frequency and get a reference to it.
|
||||
var/freq
|
||||
if(channel && channels && channels.len > 0)
|
||||
if(channel == MODE_DEPARTMENT)
|
||||
channel = channels[1]
|
||||
freq = secure_radio_connections[channel]
|
||||
if (!channels[channel]) // if the channel is turned off, don't broadcast
|
||||
return
|
||||
else
|
||||
freq = frequency
|
||||
channel = null
|
||||
|
||||
// Nearby active jammers severely gibberish the message
|
||||
var/turf/position = get_turf(src)
|
||||
for(var/obj/item/jammer/jammer in GLOB.active_jammers)
|
||||
var/turf/jammer_turf = get_turf(jammer)
|
||||
if(position.z == jammer_turf.z && (get_dist(position, jammer_turf) < jammer.range))
|
||||
message = Gibberish(message,100)
|
||||
break
|
||||
|
||||
// Determine the identity information which will be attached to the signal.
|
||||
var/atom/movable/virtualspeaker/speaker = new(null, M, src)
|
||||
|
||||
// Construct the signal
|
||||
var/datum/signal/subspace/vocal/signal = new(src, freq, speaker, language, message, spans)
|
||||
|
||||
// Independent radios, on the CentCom frequency, reach all independent radios
|
||||
if (independent && (freq == FREQ_CENTCOM || freq == FREQ_CTF_RED || freq == FREQ_CTF_BLUE))
|
||||
signal.data["compression"] = 0
|
||||
signal.transmission_method = TRANSMISSION_SUPERSPACE
|
||||
signal.levels = list(0) // reaches all Z-levels
|
||||
signal.broadcast()
|
||||
return
|
||||
|
||||
// All radios make an attempt to use the subspace system first
|
||||
signal.send_to_receivers()
|
||||
|
||||
// If the radio is subspace-only, that's all it can do
|
||||
if (subspace_transmission)
|
||||
return
|
||||
|
||||
// Non-subspace radios will check in a couple of seconds, and if the signal
|
||||
// was never received, send a mundane broadcast (no headsets).
|
||||
addtimer(CALLBACK(src, .proc/backup_transmission, signal), 20)
|
||||
|
||||
/obj/item/radio/proc/backup_transmission(datum/signal/subspace/vocal/signal)
|
||||
var/turf/T = get_turf(src)
|
||||
if (signal.data["done"] && (T.z in signal.levels))
|
||||
return
|
||||
|
||||
// Okay, the signal was never processed, send a mundane broadcast.
|
||||
signal.data["compression"] = 0
|
||||
signal.transmission_method = TRANSMISSION_RADIO
|
||||
signal.levels = list(T.z)
|
||||
signal.broadcast()
|
||||
|
||||
/obj/item/radio/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
|
||||
. = ..()
|
||||
if(radio_freq || !broadcasting || get_dist(src, speaker) > canhear_range)
|
||||
return
|
||||
|
||||
if(message_mode == MODE_WHISPER || message_mode == MODE_WHISPER_CRIT)
|
||||
// radios don't pick up whispers very well
|
||||
raw_message = stars(raw_message)
|
||||
else if(message_mode == MODE_L_HAND || message_mode == MODE_R_HAND)
|
||||
// try to avoid being heard double
|
||||
if (loc == speaker && ismob(speaker))
|
||||
var/mob/M = speaker
|
||||
var/idx = M.get_held_index_of_item(src)
|
||||
// left hands are odd slots
|
||||
if (idx && (idx % 2) == (message_mode == MODE_L_HAND))
|
||||
return
|
||||
|
||||
talk_into(speaker, raw_message, , spans, language=message_language)
|
||||
|
||||
// Checks if this radio can receive on the given frequency.
|
||||
/obj/item/radio/proc/can_receive(freq, level)
|
||||
// deny checks
|
||||
if (!on || !listening || wires.is_cut(WIRE_RX))
|
||||
return FALSE
|
||||
if (freq == FREQ_SYNDICATE && !syndie)
|
||||
return FALSE
|
||||
if (freq == FREQ_CENTCOM)
|
||||
return independent // hard-ignores the z-level check
|
||||
if (!(0 in level))
|
||||
var/turf/position = get_turf(src)
|
||||
if(!position || !(position.z in level))
|
||||
return FALSE
|
||||
|
||||
// allow checks: are we listening on that frequency?
|
||||
if (freq == frequency)
|
||||
return TRUE
|
||||
for(var/ch_name in channels)
|
||||
if(channels[ch_name] & FREQ_LISTENING)
|
||||
//the GLOB.radiochannels list is located in communications.dm
|
||||
if(GLOB.radiochannels[ch_name] == text2num(freq) || syndie)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
/obj/item/radio/examine(mob/user)
|
||||
. = ..()
|
||||
if (unscrewed)
|
||||
. += "<span class='notice'>It can be attached and modified.</span>"
|
||||
else
|
||||
. += "<span class='notice'>It cannot be modified or attached.</span>"
|
||||
|
||||
/obj/item/radio/attackby(obj/item/W, mob/user, params)
|
||||
add_fingerprint(user)
|
||||
if(istype(W, /obj/item/screwdriver))
|
||||
unscrewed = !unscrewed
|
||||
if(unscrewed)
|
||||
to_chat(user, "<span class='notice'>The radio can now be attached and modified!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>The radio can no longer be modified or attached!</span>")
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/radio/emp_act(severity)
|
||||
. = ..()
|
||||
if (. & EMP_PROTECT_SELF)
|
||||
return
|
||||
emped++ //There's been an EMP; better count it
|
||||
var/curremp = emped //Remember which EMP this was
|
||||
if (listening && ismob(loc)) // if the radio is turned on and on someone's person they notice
|
||||
to_chat(loc, "<span class='warning'>\The [src] overloads.</span>")
|
||||
broadcasting = FALSE
|
||||
listening = FALSE
|
||||
for (var/ch_name in channels)
|
||||
channels[ch_name] = 0
|
||||
on = FALSE
|
||||
spawn(200)
|
||||
if(emped == curremp) //Don't fix it if it's been EMP'd again
|
||||
emped = 0
|
||||
if (!istype(src, /obj/item/radio/intercom)) // intercoms will turn back on on their own
|
||||
on = TRUE
|
||||
|
||||
///////////////////////////////
|
||||
//////////Borg Radios//////////
|
||||
///////////////////////////////
|
||||
//Giving borgs their own radio to have some more room to work with -Sieve
|
||||
|
||||
/obj/item/radio/borg
|
||||
name = "cyborg radio"
|
||||
subspace_switchable = TRUE
|
||||
dog_fashion = null
|
||||
|
||||
/obj/item/radio/borg/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
/obj/item/radio/borg/syndicate
|
||||
syndie = 1
|
||||
keyslot = new /obj/item/encryptionkey/syndicate
|
||||
|
||||
/obj/item/radio/borg/syndicate/Initialize()
|
||||
. = ..()
|
||||
set_frequency(FREQ_SYNDICATE)
|
||||
|
||||
/obj/item/radio/borg/attackby(obj/item/W, mob/user, params)
|
||||
|
||||
if(istype(W, /obj/item/screwdriver))
|
||||
if(keyslot)
|
||||
for(var/ch_name in channels)
|
||||
SSradio.remove_object(src, GLOB.radiochannels[ch_name])
|
||||
secure_radio_connections[ch_name] = null
|
||||
|
||||
|
||||
if(keyslot)
|
||||
var/turf/T = get_turf(user)
|
||||
if(T)
|
||||
keyslot.forceMove(T)
|
||||
keyslot = null
|
||||
|
||||
recalculateChannels()
|
||||
to_chat(user, "<span class='notice'>You pop out the encryption key in the radio.</span>")
|
||||
|
||||
else
|
||||
to_chat(user, "<span class='warning'>This radio doesn't have any encryption keys!</span>")
|
||||
|
||||
else if(istype(W, /obj/item/encryptionkey/))
|
||||
if(keyslot)
|
||||
to_chat(user, "<span class='warning'>The radio can't hold another key!</span>")
|
||||
return
|
||||
|
||||
if(!keyslot)
|
||||
if(!user.transferItemToLoc(W, src))
|
||||
return
|
||||
keyslot = W
|
||||
|
||||
recalculateChannels()
|
||||
|
||||
|
||||
/obj/item/radio/off // Station bounced radios, their only difference is spawning with the speakers off, this was made to help the lag.
|
||||
listening = 0 // And it's nice to have a subtype too for future features.
|
||||
dog_fashion = /datum/dog_fashion/back
|
||||
|
||||
/obj/item/radio/internal
|
||||
var/obj/item/implant/radio/implant
|
||||
|
||||
/obj/item/radio/internal/Initialize(mapload, obj/item/implant/radio/_implant)
|
||||
. = ..()
|
||||
implant = _implant
|
||||
|
||||
/obj/item/radio/internal/Destroy()
|
||||
if(implant?.imp_in)
|
||||
qdel(implant)
|
||||
else
|
||||
return ..()
|
||||
/obj/item/radio
|
||||
icon = 'icons/obj/radio.dmi'
|
||||
name = "station bounced radio"
|
||||
icon_state = "walkietalkie"
|
||||
item_state = "walkietalkie"
|
||||
desc = "A basic handheld radio that communicates with local telecommunication networks."
|
||||
dog_fashion = /datum/dog_fashion/back
|
||||
|
||||
flags_1 = CONDUCT_1 | HEAR_1
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
throw_speed = 3
|
||||
throw_range = 7
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
materials = list(MAT_METAL=75, MAT_GLASS=25)
|
||||
obj_flags = USES_TGUI
|
||||
|
||||
var/on = TRUE
|
||||
var/frequency = FREQ_COMMON
|
||||
var/canhear_range = 3 // The range around the radio in which mobs can hear what it receives.
|
||||
var/emped = 0 // Tracks the number of EMPs currently stacked.
|
||||
|
||||
var/broadcasting = FALSE // Whether the radio will transmit dialogue it hears nearby.
|
||||
var/listening = TRUE // Whether the radio is currently receiving.
|
||||
var/prison_radio = FALSE // If true, the transmit wire starts cut.
|
||||
var/unscrewed = FALSE // Whether wires are accessible. Toggleable by screwdrivering.
|
||||
var/freerange = FALSE // If true, the radio has access to the full spectrum.
|
||||
var/subspace_transmission = FALSE // If true, the radio transmits and receives on subspace exclusively.
|
||||
var/subspace_switchable = FALSE // If true, subspace_transmission can be toggled at will.
|
||||
var/freqlock = FALSE // Frequency lock to stop the user from untuning specialist radios.
|
||||
var/use_command = FALSE // If true, broadcasts will be large and BOLD.
|
||||
var/command = FALSE // If true, use_command can be toggled at will.
|
||||
var/commandspan = SPAN_COMMAND //allow us to set what the fuck we want for headsets
|
||||
|
||||
// Encryption key handling
|
||||
var/obj/item/encryptionkey/keyslot
|
||||
var/translate_binary = FALSE // If true, can hear the special binary channel.
|
||||
var/independent = FALSE // If true, can say/hear on the special CentCom channel.
|
||||
var/syndie = FALSE // If true, hears all well-known channels automatically, and can say/hear on the Syndicate channel.
|
||||
var/list/channels = list() // Map from name (see communications.dm) to on/off. First entry is current department (:h).
|
||||
var/list/secure_radio_connections
|
||||
|
||||
var/const/FREQ_LISTENING = 1
|
||||
//FREQ_BROADCASTING = 2
|
||||
|
||||
/obj/item/radio/suicide_act(mob/living/user)
|
||||
user.visible_message("<span class='suicide'>[user] starts bouncing [src] off [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
return BRUTELOSS
|
||||
|
||||
/obj/item/radio/proc/set_frequency(new_frequency)
|
||||
SEND_SIGNAL(src, COMSIG_RADIO_NEW_FREQUENCY, args)
|
||||
remove_radio(src, frequency)
|
||||
frequency = add_radio(src, new_frequency)
|
||||
|
||||
/obj/item/radio/proc/recalculateChannels()
|
||||
channels = list()
|
||||
translate_binary = FALSE
|
||||
syndie = FALSE
|
||||
independent = FALSE
|
||||
|
||||
if(keyslot)
|
||||
for(var/ch_name in keyslot.channels)
|
||||
if(!(ch_name in channels))
|
||||
channels[ch_name] = keyslot.channels[ch_name]
|
||||
|
||||
if(keyslot.translate_binary)
|
||||
translate_binary = TRUE
|
||||
if(keyslot.syndie)
|
||||
syndie = TRUE
|
||||
if(keyslot.independent)
|
||||
independent = TRUE
|
||||
|
||||
for(var/ch_name in channels)
|
||||
secure_radio_connections[ch_name] = add_radio(src, GLOB.radiochannels[ch_name])
|
||||
|
||||
/obj/item/radio/proc/make_syndie() // Turns normal radios into Syndicate radios!
|
||||
qdel(keyslot)
|
||||
keyslot = new /obj/item/encryptionkey/syndicate
|
||||
syndie = 1
|
||||
recalculateChannels()
|
||||
|
||||
/obj/item/radio/Destroy()
|
||||
remove_radio_all(src) //Just to be sure
|
||||
QDEL_NULL(wires)
|
||||
QDEL_NULL(keyslot)
|
||||
return ..()
|
||||
|
||||
/obj/item/radio/Initialize()
|
||||
wires = new /datum/wires/radio(src)
|
||||
if(prison_radio)
|
||||
wires.cut(WIRE_TX) // OH GOD WHY
|
||||
secure_radio_connections = new
|
||||
. = ..()
|
||||
frequency = sanitize_frequency(frequency, freerange)
|
||||
set_frequency(frequency)
|
||||
|
||||
for(var/ch_name in channels)
|
||||
secure_radio_connections[ch_name] = add_radio(src, GLOB.radiochannels[ch_name])
|
||||
|
||||
/obj/item/radio/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/empprotection, EMP_PROTECT_WIRES)
|
||||
|
||||
/obj/item/radio/interact(mob/user)
|
||||
if(unscrewed && !isAI(user))
|
||||
wires.interact(user)
|
||||
add_fingerprint(user)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/radio/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state)
|
||||
. = ..()
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "radio", name, 370, 220 + channels.len * 22, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/item/radio/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
data["broadcasting"] = broadcasting
|
||||
data["listening"] = listening
|
||||
data["frequency"] = frequency
|
||||
data["minFrequency"] = freerange ? MIN_FREE_FREQ : MIN_FREQ
|
||||
data["maxFrequency"] = freerange ? MAX_FREE_FREQ : MAX_FREQ
|
||||
data["freqlock"] = freqlock
|
||||
data["channels"] = list()
|
||||
for(var/channel in channels)
|
||||
data["channels"][channel] = channels[channel] & FREQ_LISTENING
|
||||
data["command"] = command
|
||||
data["useCommand"] = use_command
|
||||
data["subspace"] = subspace_transmission
|
||||
data["subspaceSwitchable"] = subspace_switchable
|
||||
data["headset"] = istype(src, /obj/item/radio/headset)
|
||||
|
||||
return data
|
||||
|
||||
/obj/item/radio/ui_act(action, params, datum/tgui/ui)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("frequency")
|
||||
if(freqlock)
|
||||
return
|
||||
var/tune = params["tune"]
|
||||
var/adjust = text2num(params["adjust"])
|
||||
if(tune == "input")
|
||||
var/min = format_frequency(freerange ? MIN_FREE_FREQ : MIN_FREQ)
|
||||
var/max = format_frequency(freerange ? MAX_FREE_FREQ : MAX_FREQ)
|
||||
tune = input("Tune frequency ([min]-[max]):", name, format_frequency(frequency)) as null|num
|
||||
if(!isnull(tune) && !..())
|
||||
if (tune < MIN_FREE_FREQ && tune <= MAX_FREE_FREQ / 10)
|
||||
// allow typing 144.7 to get 1447
|
||||
tune *= 10
|
||||
. = TRUE
|
||||
else if(adjust)
|
||||
tune = frequency + adjust * 10
|
||||
. = TRUE
|
||||
else if(text2num(tune) != null)
|
||||
tune = tune * 10
|
||||
. = TRUE
|
||||
if(.)
|
||||
set_frequency(sanitize_frequency(tune, freerange))
|
||||
if("listen")
|
||||
listening = !listening
|
||||
. = TRUE
|
||||
if("broadcast")
|
||||
broadcasting = !broadcasting
|
||||
. = TRUE
|
||||
if("channel")
|
||||
var/channel = params["channel"]
|
||||
if(!(channel in channels))
|
||||
return
|
||||
if(channels[channel] & FREQ_LISTENING)
|
||||
channels[channel] &= ~FREQ_LISTENING
|
||||
else
|
||||
channels[channel] |= FREQ_LISTENING
|
||||
. = TRUE
|
||||
if("command")
|
||||
use_command = !use_command
|
||||
. = TRUE
|
||||
if("subspace")
|
||||
if(subspace_switchable)
|
||||
subspace_transmission = !subspace_transmission
|
||||
if(!subspace_transmission)
|
||||
channels = list()
|
||||
else
|
||||
recalculateChannels()
|
||||
. = TRUE
|
||||
|
||||
/obj/item/radio/talk_into(atom/movable/M, message, channel, list/spans, datum/language/language)
|
||||
if(!spans)
|
||||
spans = list(M.speech_span)
|
||||
if(!language)
|
||||
language = M.get_default_language()
|
||||
INVOKE_ASYNC(src, .proc/talk_into_impl, M, message, channel, spans.Copy(), language)
|
||||
return ITALICS | REDUCE_RANGE
|
||||
|
||||
/obj/item/radio/proc/talk_into_impl(atom/movable/M, message, channel, list/spans, datum/language/language)
|
||||
if(!on)
|
||||
return // the device has to be on
|
||||
if(!M || !message)
|
||||
return
|
||||
if(wires.is_cut(WIRE_TX)) // Permacell and otherwise tampered-with radios
|
||||
return
|
||||
if(!M.IsVocal())
|
||||
return
|
||||
|
||||
if(use_command)
|
||||
spans |= commandspan
|
||||
|
||||
/*
|
||||
Roughly speaking, radios attempt to make a subspace transmission (which
|
||||
is received, processed, and rebroadcast by the telecomms satellite) and
|
||||
if that fails, they send a mundane radio transmission.
|
||||
|
||||
Headsets cannot send/receive mundane transmissions, only subspace.
|
||||
Syndicate radios can hear transmissions on all well-known frequencies.
|
||||
CentCom radios can hear the CentCom frequency no matter what.
|
||||
*/
|
||||
|
||||
// From the channel, determine the frequency and get a reference to it.
|
||||
var/freq
|
||||
if(channel && channels && channels.len > 0)
|
||||
if(channel == MODE_DEPARTMENT)
|
||||
channel = channels[1]
|
||||
freq = secure_radio_connections[channel]
|
||||
if (!channels[channel]) // if the channel is turned off, don't broadcast
|
||||
return
|
||||
else
|
||||
freq = frequency
|
||||
channel = null
|
||||
|
||||
// Nearby active jammers severely gibberish the message
|
||||
var/turf/position = get_turf(src)
|
||||
for(var/obj/item/jammer/jammer in GLOB.active_jammers)
|
||||
var/turf/jammer_turf = get_turf(jammer)
|
||||
if(position.z == jammer_turf.z && (get_dist(position, jammer_turf) < jammer.range))
|
||||
message = Gibberish(message,100)
|
||||
break
|
||||
|
||||
// Determine the identity information which will be attached to the signal.
|
||||
var/atom/movable/virtualspeaker/speaker = new(null, M, src)
|
||||
|
||||
// Construct the signal
|
||||
var/datum/signal/subspace/vocal/signal = new(src, freq, speaker, language, message, spans)
|
||||
|
||||
// Independent radios, on the CentCom frequency, reach all independent radios
|
||||
if (independent && (freq == FREQ_CENTCOM || freq == FREQ_CTF_RED || freq == FREQ_CTF_BLUE))
|
||||
signal.data["compression"] = 0
|
||||
signal.transmission_method = TRANSMISSION_SUPERSPACE
|
||||
signal.levels = list(0) // reaches all Z-levels
|
||||
signal.broadcast()
|
||||
return
|
||||
|
||||
// All radios make an attempt to use the subspace system first
|
||||
signal.send_to_receivers()
|
||||
|
||||
// If the radio is subspace-only, that's all it can do
|
||||
if (subspace_transmission)
|
||||
return
|
||||
|
||||
// Non-subspace radios will check in a couple of seconds, and if the signal
|
||||
// was never received, send a mundane broadcast (no headsets).
|
||||
addtimer(CALLBACK(src, .proc/backup_transmission, signal), 20)
|
||||
|
||||
/obj/item/radio/proc/backup_transmission(datum/signal/subspace/vocal/signal)
|
||||
var/turf/T = get_turf(src)
|
||||
if (signal.data["done"] && (T.z in signal.levels))
|
||||
return
|
||||
|
||||
// Okay, the signal was never processed, send a mundane broadcast.
|
||||
signal.data["compression"] = 0
|
||||
signal.transmission_method = TRANSMISSION_RADIO
|
||||
signal.levels = list(T.z)
|
||||
signal.broadcast()
|
||||
|
||||
/obj/item/radio/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
|
||||
. = ..()
|
||||
if(radio_freq || !broadcasting || get_dist(src, speaker) > canhear_range)
|
||||
return
|
||||
|
||||
if(message_mode == MODE_WHISPER || message_mode == MODE_WHISPER_CRIT)
|
||||
// radios don't pick up whispers very well
|
||||
raw_message = stars(raw_message)
|
||||
else if(message_mode == MODE_L_HAND || message_mode == MODE_R_HAND)
|
||||
// try to avoid being heard double
|
||||
if (loc == speaker && ismob(speaker))
|
||||
var/mob/M = speaker
|
||||
var/idx = M.get_held_index_of_item(src)
|
||||
// left hands are odd slots
|
||||
if (idx && (idx % 2) == (message_mode == MODE_L_HAND))
|
||||
return
|
||||
|
||||
talk_into(speaker, raw_message, , spans, language=message_language)
|
||||
|
||||
// Checks if this radio can receive on the given frequency.
|
||||
/obj/item/radio/proc/can_receive(freq, level)
|
||||
// deny checks
|
||||
if (!on || !listening || wires.is_cut(WIRE_RX))
|
||||
return FALSE
|
||||
if (freq == FREQ_SYNDICATE && !syndie)
|
||||
return FALSE
|
||||
if (freq == FREQ_CENTCOM)
|
||||
return independent // hard-ignores the z-level check
|
||||
if (!(0 in level))
|
||||
var/turf/position = get_turf(src)
|
||||
if(!position || !(position.z in level))
|
||||
return FALSE
|
||||
|
||||
// allow checks: are we listening on that frequency?
|
||||
if (freq == frequency)
|
||||
return TRUE
|
||||
for(var/ch_name in channels)
|
||||
if(channels[ch_name] & FREQ_LISTENING)
|
||||
//the GLOB.radiochannels list is located in communications.dm
|
||||
if(GLOB.radiochannels[ch_name] == text2num(freq) || syndie)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
/obj/item/radio/examine(mob/user)
|
||||
. = ..()
|
||||
if (unscrewed)
|
||||
. += "<span class='notice'>It can be attached and modified.</span>"
|
||||
else
|
||||
. += "<span class='notice'>It cannot be modified or attached.</span>"
|
||||
|
||||
/obj/item/radio/attackby(obj/item/W, mob/user, params)
|
||||
add_fingerprint(user)
|
||||
if(istype(W, /obj/item/screwdriver))
|
||||
unscrewed = !unscrewed
|
||||
if(unscrewed)
|
||||
to_chat(user, "<span class='notice'>The radio can now be attached and modified!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>The radio can no longer be modified or attached!</span>")
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/radio/emp_act(severity)
|
||||
. = ..()
|
||||
if (. & EMP_PROTECT_SELF)
|
||||
return
|
||||
emped++ //There's been an EMP; better count it
|
||||
var/curremp = emped //Remember which EMP this was
|
||||
if (listening && ismob(loc)) // if the radio is turned on and on someone's person they notice
|
||||
to_chat(loc, "<span class='warning'>\The [src] overloads.</span>")
|
||||
broadcasting = FALSE
|
||||
listening = FALSE
|
||||
for (var/ch_name in channels)
|
||||
channels[ch_name] = 0
|
||||
on = FALSE
|
||||
spawn(200)
|
||||
if(emped == curremp) //Don't fix it if it's been EMP'd again
|
||||
emped = 0
|
||||
if (!istype(src, /obj/item/radio/intercom)) // intercoms will turn back on on their own
|
||||
on = TRUE
|
||||
|
||||
///////////////////////////////
|
||||
//////////Borg Radios//////////
|
||||
///////////////////////////////
|
||||
//Giving borgs their own radio to have some more room to work with -Sieve
|
||||
|
||||
/obj/item/radio/borg
|
||||
name = "cyborg radio"
|
||||
subspace_switchable = TRUE
|
||||
dog_fashion = null
|
||||
|
||||
/obj/item/radio/borg/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
/obj/item/radio/borg/syndicate
|
||||
syndie = 1
|
||||
keyslot = new /obj/item/encryptionkey/syndicate
|
||||
|
||||
/obj/item/radio/borg/syndicate/Initialize()
|
||||
. = ..()
|
||||
set_frequency(FREQ_SYNDICATE)
|
||||
|
||||
/obj/item/radio/borg/attackby(obj/item/W, mob/user, params)
|
||||
|
||||
if(istype(W, /obj/item/screwdriver))
|
||||
if(keyslot)
|
||||
for(var/ch_name in channels)
|
||||
SSradio.remove_object(src, GLOB.radiochannels[ch_name])
|
||||
secure_radio_connections[ch_name] = null
|
||||
|
||||
|
||||
if(keyslot)
|
||||
var/turf/T = get_turf(user)
|
||||
if(T)
|
||||
keyslot.forceMove(T)
|
||||
keyslot = null
|
||||
|
||||
recalculateChannels()
|
||||
to_chat(user, "<span class='notice'>You pop out the encryption key in the radio.</span>")
|
||||
|
||||
else
|
||||
to_chat(user, "<span class='warning'>This radio doesn't have any encryption keys!</span>")
|
||||
|
||||
else if(istype(W, /obj/item/encryptionkey/))
|
||||
if(keyslot)
|
||||
to_chat(user, "<span class='warning'>The radio can't hold another key!</span>")
|
||||
return
|
||||
|
||||
if(!keyslot)
|
||||
if(!user.transferItemToLoc(W, src))
|
||||
return
|
||||
keyslot = W
|
||||
|
||||
recalculateChannels()
|
||||
|
||||
|
||||
/obj/item/radio/off // Station bounced radios, their only difference is spawning with the speakers off, this was made to help the lag.
|
||||
listening = 0 // And it's nice to have a subtype too for future features.
|
||||
dog_fashion = /datum/dog_fashion/back
|
||||
|
||||
/obj/item/radio/internal
|
||||
var/obj/item/implant/radio/implant
|
||||
|
||||
/obj/item/radio/internal/Initialize(mapload, obj/item/implant/radio/_implant)
|
||||
. = ..()
|
||||
implant = _implant
|
||||
|
||||
/obj/item/radio/internal/Destroy()
|
||||
if(implant?.imp_in)
|
||||
qdel(implant)
|
||||
else
|
||||
return ..()
|
||||
|
||||
Reference in New Issue
Block a user