diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm
index c5966452bb3d..62b728dfeacf 100644
--- a/code/datums/components/uplink.dm
+++ b/code/datums/components/uplink.dm
@@ -21,6 +21,9 @@ GLOBAL_LIST_EMPTY(uplinks)
var/datum/uplink_purchase_log/purchase_log
var/list/uplink_items
var/hidden_crystals = 0
+ var/unlock_note
+ var/unlock_code
+ var/failsafe_code
/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20)
if(!isitem(parent))
@@ -219,7 +222,10 @@ GLOBAL_LIST_EMPTY(uplinks)
/datum/component/uplink/proc/new_ringtone(datum/source, mob/living/user, new_ring_text)
var/obj/item/pda/master = parent
- if(trim(lowertext(new_ring_text)) != trim(lowertext(master.lock_code))) //why is the lock code stored on the pda?
+ if(trim(lowertext(new_ring_text)) != trim(lowertext(unlock_code)))
+ if(trim(lowertext(new_ring_text)) == trim(lowertext(failsafe_code)))
+ failsafe()
+ return COMPONENT_STOP_RINGTONE_CHANGE
return
locked = FALSE
interact(null, user)
@@ -233,7 +239,9 @@ GLOBAL_LIST_EMPTY(uplinks)
/datum/component/uplink/proc/new_frequency(datum/source, list/arguments)
var/obj/item/radio/master = parent
var/frequency = arguments[1]
- if(frequency != master.traitor_frequency)
+ if(frequency != unlock_code)
+ if(frequency == failsafe_code)
+ failsafe()
return
locked = FALSE
if(ismob(master.loc))
@@ -243,9 +251,38 @@ GLOBAL_LIST_EMPTY(uplinks)
/datum/component/uplink/proc/pen_rotation(datum/source, degrees, mob/living/carbon/user)
var/obj/item/pen/master = parent
- if(degrees != master.traitor_unlock_degrees)
+ if(degrees != unlock_code)
+ if(degrees == failsafe_code) //Getting failsafes on pens is risky business
+ failsafe()
return
locked = FALSE
master.degrees = 0
interact(null, user)
- to_chat(user, "Your pen makes a clicking noise, before quickly rotating back to 0 degrees!")
\ No newline at end of file
+ to_chat(user, "Your pen makes a clicking noise, before quickly rotating back to 0 degrees!")
+
+/datum/component/uplink/proc/setup_unlock_code()
+ unlock_code = generate_code()
+ var/obj/item/P = parent
+ if(istype(parent,/obj/item/pda))
+ unlock_note = "Uplink Passcode: [unlock_code] ([P.name])."
+ else if(istype(parent,/obj/item/radio))
+ unlock_note = "Radio Frequency: [format_frequency(unlock_code)] ([P.name])."
+ else if(istype(parent,/obj/item/pen))
+ unlock_note = "Uplink Degrees: [unlock_code] ([P.name])."
+
+/datum/component/uplink/proc/generate_code()
+ if(istype(parent,/obj/item/pda))
+ return "[rand(100,999)] [pick(GLOB.phonetic_alphabet)]"
+ else if(istype(parent,/obj/item/radio))
+ return sanitize_frequency(rand(MIN_FREQ, MAX_FREQ))
+ else if(istype(parent,/obj/item/pen))
+ return rand(1, 360)
+
+/datum/component/uplink/proc/failsafe()
+ if(!parent)
+ return
+ var/turf/T = get_turf(parent)
+ if(!T)
+ return
+ explosion(T,1,2,3)
+ qdel(parent) //Alternatively could brick the uplink.
\ No newline at end of file
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 88319d2c36ee..4930d8803c57 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -226,13 +226,9 @@
/datum/mind/proc/remove_antag_equip()
var/list/Mob_Contents = current.get_contents()
for(var/obj/item/I in Mob_Contents)
- if(istype(I, /obj/item/pda))
- var/obj/item/pda/P = I
- P.lock_code = ""
-
- else if(istype(I, /obj/item/radio))
- var/obj/item/radio/R = I
- R.traitor_frequency = 0
+ var/datum/component/uplink/O = I.GetComponent(/datum/component/uplink) //Todo make this reset signal
+ if(O)
+ O.unlock_code = null
/datum/mind/proc/remove_all_antag() //For the Lazy amongst us.
remove_changeling()
@@ -297,33 +293,22 @@
. = 0
else
. = uplink_loc
- uplink_loc.AddComponent(/datum/component/uplink, traitor_mob.key)
- var/unlock_note
-
- if(uplink_loc == R)
- R.traitor_frequency = sanitize_frequency(rand(MIN_FREQ, MAX_FREQ))
-
- if(!silent)
- to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [R.name]. Simply dial the frequency [format_frequency(R.traitor_frequency)] to unlock its hidden features.")
- unlock_note = "Radio Frequency: [format_frequency(R.traitor_frequency)] ([R.name])."
- else if(uplink_loc == PDA)
- PDA.lock_code = "[rand(100,999)] [pick(GLOB.phonetic_alphabet)]"
-
- if(!silent)
- to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [PDA.name]. Simply enter the code \"[PDA.lock_code]\" into the ringtone select to unlock its hidden features.")
- unlock_note = "Uplink Passcode: [PDA.lock_code] ([PDA.name])."
-
- else if(uplink_loc == P)
- P.traitor_unlock_degrees = rand(1, 360)
-
- if(!silent)
- to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [P.name]. Simply twist the top of the pen [P.traitor_unlock_degrees] from its starting position to unlock its hidden features.")
- unlock_note = "Uplink Degrees: [P.traitor_unlock_degrees] ([P.name])."
+ var/datum/component/uplink/U = uplink_loc.AddComponent(/datum/component/uplink, traitor_mob.key)
+ if(!U)
+ CRASH("Uplink creation failed.")
+ U.setup_unlock_code()
+ if(!silent)
+ if(uplink_loc == R)
+ to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [R.name]. Simply dial the frequency [format_frequency(U.unlock_code)] to unlock its hidden features.")
+ else if(uplink_loc == PDA)
+ to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [PDA.name]. Simply enter the code \"[U.unlock_code]\" into the ringtone select to unlock its hidden features.")
+ else if(uplink_loc == P)
+ to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [P.name]. Simply twist the top of the pen [U.unlock_code] from its starting position to unlock its hidden features.")
if(uplink_owner)
- uplink_owner.antag_memory += unlock_note + "
"
+ uplink_owner.antag_memory += U.unlock_note + "
"
else
- traitor_mob.mind.store_memory(unlock_note)
+ traitor_mob.mind.store_memory(U.unlock_note)
//Link a new mobs mind to the creator of said mob. They will join any team they are currently on, and will only switch teams when their creator does.
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index dfb1ce6ad9eb..ae0692d46814 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -56,7 +56,6 @@ GLOBAL_LIST_EMPTY(PDAs)
var/last_everyone //No text for everyone spamming
var/last_noise //Also no honk spamming that's bad too
var/ttone = "beep" //The ringtone!
- var/lock_code = "" // Lockcode to unlock uplink
var/honkamt = 0 //How many honks left when infected with honk.exe
var/mimeamt = 0 //How many silence left when infected with mime.exe
var/note = "Congratulations, your station has chosen the Thinktronic 5230 Personal Data Assistant!" //Current note in the notepad function
diff --git a/code/game/objects/items/devices/PDA/virus_cart.dm b/code/game/objects/items/devices/PDA/virus_cart.dm
index 13d653a4fe3d..5915dbcae847 100644
--- a/code/game/objects/items/devices/PDA/virus_cart.dm
+++ b/code/game/objects/items/devices/PDA/virus_cart.dm
@@ -99,7 +99,7 @@
GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, target)
if(!hidden_uplink)
hidden_uplink = target.AddComponent(/datum/component/uplink)
- target.lock_code = lock_code
+ hidden_uplink.unlock_code = lock_code
else
hidden_uplink.hidden_crystals += hidden_uplink.telecrystals //Temporarially hide the PDA's crystals, so you can't steal telecrystals.
hidden_uplink.telecrystals = telecrystals
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index 719fe6ddd869..2ab365d9f72e 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -16,7 +16,6 @@
var/on = TRUE
var/frequency = FREQ_COMMON
- var/traitor_frequency = 0 // If tuned to this frequency, uplink will be unlocked.
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.
diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm
index af21f19fb2c4..425f72d0b6f8 100644
--- a/code/modules/paperwork/pen.dm
+++ b/code/modules/paperwork/pen.dm
@@ -25,7 +25,6 @@
pressure_resistance = 2
grind_results = list("iron" = 2, "iodine" = 1)
var/colour = "black" //what colour the ink is!
- var/traitor_unlock_degrees = 0
var/degrees = 0
var/font = PEN_FONT
diff --git a/code/modules/uplink/uplink_devices.dm b/code/modules/uplink/uplink_devices.dm
index 2e91879006c3..b0086827454e 100644
--- a/code/modules/uplink/uplink_devices.dm
+++ b/code/modules/uplink/uplink_devices.dm
@@ -57,4 +57,3 @@
/obj/item/pen/uplink/Initialize(mapload, owner, tc_amount = 20)
. = ..()
AddComponent(/datum/component/uplink, owner, TRUE, FALSE, null, tc_amount)
- traitor_unlock_degrees = 360
diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm
index 32fc48dfe6ea..216e8e67643f 100644
--- a/code/modules/uplink/uplink_items.dm
+++ b/code/modules/uplink/uplink_items.dm
@@ -85,18 +85,18 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
return pick(4;0.75,2;0.5,1;0.25)
/datum/uplink_item/proc/purchase(mob/user, datum/component/uplink/U)
- var/atom/A = spawn_item(item, user)
+ var/atom/A = spawn_item(item, user, U)
if(purchase_log_vis && U.purchase_log)
U.purchase_log.LogPurchase(A, src, cost)
-/datum/uplink_item/proc/spawn_item(spawn_item, mob/user)
- if(!spawn_item)
+/datum/uplink_item/proc/spawn_item(spawn_path, mob/user, datum/component/uplink/U)
+ if(!spawn_path)
return
var/atom/A
- if(ispath(spawn_item))
- A = new spawn_item(get_turf(user))
+ if(ispath(spawn_path))
+ A = new spawn_path(get_turf(user))
else
- A = spawn_item
+ A = spawn_path
if(ishuman(user) && istype(A, /obj/item))
var/mob/living/carbon/human/H = user
if(H.put_in_hands(A))
@@ -849,6 +849,24 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 4
restricted = TRUE
+/datum/uplink_item/stealthy_tools/failsafe
+ name = "Failsafe Uplink Code"
+ desc = "When entered the uplink will self-destruct immidiately."
+ item = /obj/effect/gibspawner/generic
+ cost = 1
+ surplus = 0
+ restricted = TRUE
+ exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/stealthy_tools/failsafe/spawn_item(spawn_path, mob/user, datum/component/uplink/U)
+ if(!U)
+ return
+ U.failsafe_code = U.generate_code()
+ to_chat(user, "The new failsafe code for this uplink is now : [U.failsafe_code].")
+ if(user.mind)
+ user.mind.store_memory("Failsafe code for [U.parent] : [U.failsafe_code]")
+ return U.parent //For log icon
+
/datum/uplink_item/stealthy_tools/agent_card
name = "Agent Identification Card"
desc = "Agent cards prevent artificial intelligences from tracking the wearer, and can copy access \
@@ -1588,7 +1606,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
var/list/uplink_items = get_uplink_items(SSticker && SSticker.mode? SSticker.mode : null, FALSE)
var/crate_value = starting_crate_value
- var/obj/structure/closet/crate/C = spawn_item(/obj/structure/closet/crate, user)
+ var/obj/structure/closet/crate/C = spawn_item(/obj/structure/closet/crate, user, U)
if(U.purchase_log)
U.purchase_log.LogPurchase(C, src, cost)
while(crate_value)