diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index c86d0dff85..daabbf326a 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -227,12 +227,8 @@ GLOBAL_LIST_EMPTY(PDAs)
dat += "
Set Ringtone | "
dat += "
Messages
"
- if (istype(cartridge, /obj/item/weapon/cartridge/syndicate))
- dat += "[cartridge:shock_charges] detonation charges left.
"
- if (istype(cartridge, /obj/item/weapon/cartridge/clown))
- dat += "[cartridge:honk_charges] viral files left.
"
- if (istype(cartridge, /obj/item/weapon/cartridge/mime))
- dat += "[cartridge:mime_charges] viral files left.
"
+ if(cartridge)
+ dat += cartridge.message_header()
dat += "
Detected PDAs
"
@@ -244,12 +240,8 @@ GLOBAL_LIST_EMPTY(PDAs)
if (P == src)
continue
dat += "[P]"
- if (istype(cartridge, /obj/item/weapon/cartridge/syndicate) && P.detonate)
- dat += " (
*Detonate*)"
- if (istype(cartridge, /obj/item/weapon/cartridge/clown))
- dat += " (
*Send Virus*)"
- if (istype(cartridge, /obj/item/weapon/cartridge/mime))
- dat += " (*Send Virus*)"
+ if(cartridge)
+ dat += cartridge.message_special(P)
dat += ""
count++
dat += ""
@@ -424,16 +416,15 @@ GLOBAL_LIST_EMPTY(PDAs)
tnote = null
if("Ringtone")
var/t = input(U, "Please enter new ringtone", name, ttone) as text
- if(in_range(src, U) && loc == U)
- if(t)
- if(hidden_uplink && (trim(lowertext(t)) == trim(lowertext(lock_code))))
- hidden_uplink.interact(U)
- to_chat(U, "The PDA softly beeps.")
- U << browse(null, "window=pda")
- src.mode = 0
- else
- t = copytext(sanitize(t), 1, 20)
- ttone = t
+ if(in_range(src, U) && loc == U && t)
+ if(hidden_uplink && (trim(lowertext(t)) == trim(lowertext(lock_code))))
+ hidden_uplink.interact(U)
+ to_chat(U, "The PDA softly beeps.")
+ U << browse(null, "window=pda")
+ src.mode = 0
+ else
+ t = copytext(sanitize(t), 1, 20)
+ ttone = t
else
U << browse(null, "window=pda")
return
@@ -444,30 +435,9 @@ GLOBAL_LIST_EMPTY(PDAs)
if("MessageAll")
src.send_to_all(U)
- if("Send Honk")//Honk virus
- if(istype(cartridge, /obj/item/weapon/cartridge/clown))//Cartridge checks are kind of unnecessary since everything is done through switch.
- var/obj/item/device/pda/P = locate(href_list["target"])//Leaving it alone in case it may do something useful, I guess.
- if(!isnull(P))
- if (!P.toff && cartridge:honk_charges > 0)
- cartridge:honk_charges--
- U.show_message("Virus sent!", 1)
- P.honkamt = (rand(15,20))
- else
- to_chat(U, "PDA not found.")
- else
- U << browse(null, "window=pda")
- return
- if("Send Silence")//Silent virus
- if(istype(cartridge, /obj/item/weapon/cartridge/mime))
- var/obj/item/device/pda/P = locate(href_list["target"])
- if(!isnull(P))
- if (!P.toff && cartridge:mime_charges > 0)
- cartridge:mime_charges--
- U.show_message("Virus sent!", 1)
- P.silent = 1
- P.ttone = "silence"
- else
- to_chat(U, "PDA not found.")
+ if("cart")
+ if(cartridge)
+ cartridge.special(U, href_list)
else
U << browse(null, "window=pda")
return
@@ -483,38 +453,6 @@ GLOBAL_LIST_EMPTY(PDAs)
else
M.close()
-
- if("Detonate")//Detonate PDA
- if(istype(cartridge, /obj/item/weapon/cartridge/syndicate))
- var/obj/item/device/pda/P = locate(href_list["target"])
- if(!isnull(P))
- if (!P.toff && cartridge:shock_charges > 0)
- cartridge:shock_charges--
-
- var/difficulty = 0
-
- if(P.cartridge)
- difficulty += P.cartridge.access_medical
- difficulty += P.cartridge.access_security
- difficulty += P.cartridge.access_engine
- difficulty += P.cartridge.access_clown
- difficulty += P.cartridge.access_janitor
- difficulty += P.cartridge.access_manifest * 2
- else
- difficulty += 2
-
- if(prob(difficulty * 15) || (P.hidden_uplink))
- U.show_message("An error flashes on your [src].", 1)
- else
- U.show_message("Success!", 1)
- P.explode()
- else
- to_chat(U, "PDA not found.")
- else
- U.unset_machine()
- U << browse(null, "window=pda")
- return
-
//pAI FUNCTIONS===================================
if("pai")
switch(href_list["option"])
@@ -896,7 +834,7 @@ GLOBAL_LIST_EMPTY(PDAs)
if(T)
T.hotspot_expose(700,125)
- if(istype(cartridge, /obj/item/weapon/cartridge/syndicate))
+ if(istype(cartridge, /obj/item/weapon/cartridge/virus/syndicate))
explosion(T, -1, 1, 3, 4)
else
explosion(T, -1, -1, 2, 3)
@@ -1002,4 +940,3 @@ GLOBAL_LIST_EMPTY(PDAs)
for(var/obj/item/device/pda/P in GLOB.PDAs)
if(!P.owner || P.toff || P.hidden) continue
. += P
- return .
diff --git a/code/game/objects/items/devices/PDA/PDA_types.dm b/code/game/objects/items/devices/PDA/PDA_types.dm
index 6adc4efe22..166ef212fa 100644
--- a/code/game/objects/items/devices/PDA/PDA_types.dm
+++ b/code/game/objects/items/devices/PDA/PDA_types.dm
@@ -1,7 +1,7 @@
//Clown PDA is slippery.
/obj/item/device/pda/clown
name = "clown PDA"
- default_cartridge = /obj/item/weapon/cartridge/clown
+ default_cartridge = /obj/item/weapon/cartridge/virus/clown
icon_state = "pda-clown"
desc = "A portable microcomputer by Thinktronic Systems, LTD. The surface is coated with polytetrafluoroethylene and banana drippings."
ttone = "honk"
@@ -11,10 +11,10 @@
var/mob/living/carbon/M = AM
if(M.slip(0, 6, src, NO_SLIP_WHEN_WALKING))
if (ishuman(M) && (M.real_name != src.owner))
- if (istype(src.cartridge, /obj/item/weapon/cartridge/clown))
- var/obj/item/weapon/cartridge/clown/cart = src.cartridge
- if(cart.honk_charges < 5)
- cart.honk_charges++
+ if (istype(src.cartridge, /obj/item/weapon/cartridge/virus/clown))
+ var/obj/item/weapon/cartridge/virus/cart = src.cartridge
+ if(cart.charges < 5)
+ cart.charges++
// Special AI/pAI PDAs that cannot explode.
@@ -79,7 +79,7 @@
/obj/item/device/pda/mime
name = "mime PDA"
- default_cartridge = /obj/item/weapon/cartridge/mime
+ default_cartridge = /obj/item/weapon/cartridge/virus/mime
icon_state = "pda-mime"
silent = 1
ttone = "silence"
@@ -134,7 +134,7 @@
icon_state = "pda-miner"
/obj/item/device/pda/syndicate
- default_cartridge = /obj/item/weapon/cartridge/syndicate
+ default_cartridge = /obj/item/weapon/cartridge/virus/syndicate
icon_state = "pda-syndi"
name = "military PDA"
owner = "John Doe"
diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm
index 60296fd4d5..b2b7724998 100644
--- a/code/game/objects/items/devices/PDA/cart.dm
+++ b/code/game/objects/items/devices/PDA/cart.dm
@@ -96,18 +96,6 @@
access_security = 1
spam_enabled = 1
-/obj/item/weapon/cartridge/clown
- name = "\improper Honkworks 5.0 cartridge"
- icon_state = "cart-clown"
- access_clown = 1
- var/honk_charges = 5
-
-/obj/item/weapon/cartridge/mime
- name = "\improper Gestur-O 1000 cartridge"
- icon_state = "cart-mi"
- access_mime = 1
- var/mime_charges = 5
-
/obj/item/weapon/cartridge/curator
name = "\improper Lib-Tweet cartridge"
icon_state = "cart-s"
@@ -232,13 +220,6 @@
..()
radio = new /obj/item/radio/integrated/signal(src)
-/obj/item/weapon/cartridge/syndicate
- name = "\improper Detomatix cartridge"
- icon_state = "cart"
- access_remote_door = 1
- remote_door_id = "smindicate" //Make sure this matches the syndicate shuttle's shield/door id!! //don't ask about the name, testing.
- var/shock_charges = 4
-
/obj/item/weapon/cartridge/proc/unlock()
if (!istype(loc, /obj/item/device/pda))
return
@@ -785,3 +766,14 @@ Code:
return
return menu
+
+//If the cartridge adds a special line to the top of the messaging app
+/obj/item/weapon/cartridge/proc/message_header()
+ return ""
+
+//If the cartridge adds something to each potetial messaging target
+/obj/item/weapon/cartridge/proc/message_special(obj/item/device/pda/target)
+ return ""
+
+//This is called for special abilities of cartridges
+/obj/item/weapon/cartridge/proc/special(mov/living/user, list/params)
diff --git a/code/game/objects/items/devices/PDA/virus_cart.dm b/code/game/objects/items/devices/PDA/virus_cart.dm
new file mode 100644
index 0000000000..17c66cac10
--- /dev/null
+++ b/code/game/objects/items/devices/PDA/virus_cart.dm
@@ -0,0 +1,108 @@
+/obj/item/weapon/cartridge/virus
+ name = "Generic Virus PDA cart"
+ var/charges = 5
+
+/obj/item/weapon/cartridge/virus/proc/send_virus(obj/item/device/pda/target, mob/living/U)
+ return
+
+/obj/item/weapon/cartridge/virus/message_header()
+ return "[charges] viral files left.
"
+
+/obj/item/weapon/cartridge/virus/message_special(obj/item/device/pda/target)
+ if (!istype(loc, /obj/item/device/pda))
+ return "" //Sanity check, this shouldn't be possible.
+ return " (*Send Virus*)"
+
+/obj/item/weapon/cartridge/virus/special(mob/living/user, list/params)
+ var/obj/item/device/pda/P = locate(params["target"])//Leaving it alone in case it may do something useful, I guess.
+ send_virus(P,user)
+
+/obj/item/weapon/cartridge/virus/clown
+ name = "\improper Honkworks 5.0 cartridge"
+ icon_state = "cart-clown"
+ desc = "A data cartridge for portable microcomputers. It smells vaguely of banannas"
+ access_clown = 1
+
+/obj/item/weapon/cartridge/virus/clown/send_virus(obj/item/device/pda/target, mob/living/U)
+ if(charges <= 0)
+ to_chat(U, "Out of charges.")
+ return
+ if(!isnull(target) && !target.toff)
+ charges--
+ to_chat(U, "Virus Sent!")
+ target.honkamt = (rand(15,20))
+ else
+ to_chat(U, "PDA not found.")
+
+/obj/item/weapon/cartridge/virus/mime
+ name = "\improper Gestur-O 1000 cartridge"
+ icon_state = "cart-mi"
+ access_mime = 1
+
+/obj/item/weapon/cartridge/virus/mime/send_virus(obj/item/device/pda/target, mob/living/U)
+ if(charges <= 0)
+ to_chat(U, "Out of charges.")
+ return
+ if(!isnull(target) && !target.toff)
+ charges--
+ to_chat(U, "Virus Sent!")
+ target.silent = 1
+ target.ttone = "silence"
+ else
+ to_chat(U, "PDA not found.")
+
+/obj/item/weapon/cartridge/virus/syndicate
+ name = "\improper Detomatix cartridge"
+ icon_state = "cart"
+ access_remote_door = 1
+ remote_door_id = "smindicate" //Make sure this matches the syndicate shuttle's shield/door id!! //don't ask about the name, testing.
+ charges = 4
+
+/obj/item/weapon/cartridge/virus/syndicate/send_virus(obj/item/device/pda/target, mob/living/U)
+ if(charges <= 0)
+ to_chat(U, "Out of charges.")
+ return
+ if(!isnull(target) && !target.toff)
+ charges--
+ var/difficulty = 0
+ if(target.cartridge)
+ difficulty += target.cartridge.access_medical
+ difficulty += target.cartridge.access_security
+ difficulty += target.cartridge.access_engine
+ difficulty += target.cartridge.access_clown
+ difficulty += target.cartridge.access_janitor
+ difficulty += target.cartridge.access_manifest * 2
+ else
+ difficulty += 2
+ if(prob(difficulty * 15) || (target.hidden_uplink))
+ U.show_message("An error flashes on your [src].", 1)
+ else
+ U.show_message("Success!", 1)
+ target.explode()
+ else
+ to_chat(U, "PDA not found.")
+
+/obj/item/weapon/cartridge/virus/frame
+ name = "\improper F.R.A.M.E. cartridge"
+ icon_state = "cart"
+ var/telecrystals = 0
+
+/obj/item/weapon/cartridge/virus/frame/send_virus(obj/item/device/pda/target, mob/living/U)
+ if(charges <= 0)
+ to_chat(U, "Out of charges.")
+ return
+ if(!isnull(target) && !target.toff)
+ charges--
+ var/lock_code = "[rand(100,999)] [pick("Alpha","Bravo","Charlie","Delta","Echo","Foxtrot","Golf","Hotel","India","Juliet","Kilo","Lima","Mike","November","Oscar","Papa","Quebec","Romeo","Sierra","Tango","Uniform","Victor","Whiskey","X-ray","Yankee","Zulu")]"
+ to_chat(U, "Virus Sent! The unlock code to the target is: [lock_code]")
+ if(!target.hidden_uplink)
+ var/obj/item/device/uplink/uplink = new(target)
+ target.hidden_uplink = uplink
+ target.lock_code = lock_code
+ else
+ target.hidden_uplink.hidden_crystals += target.hidden_uplink.telecrystals //Temporarially hide the PDA's crystals, so you can't steal telecrystals.
+ target.hidden_uplink.telecrystals = telecrystals
+ telecrystals = 0
+ target.hidden_uplink.active = TRUE
+ else
+ to_chat(U, "PDA not found.")
diff --git a/code/game/objects/items/stacks/telecrystal.dm b/code/game/objects/items/stacks/telecrystal.dm
index dec6074b0c..8555155306 100644
--- a/code/game/objects/items/stacks/telecrystal.dm
+++ b/code/game/objects/items/stacks/telecrystal.dm
@@ -20,11 +20,18 @@
/obj/item/stack/telecrystal/afterattack(obj/item/I, mob/user, proximity)
if(!proximity)
return
- if(istype(I, /obj/item))
- if(I.hidden_uplink && I.hidden_uplink.active) //No metagaming by using this on every PDA around just to see if it gets used up.
- I.hidden_uplink.telecrystals += amount
- use(amount)
- to_chat(user, "You slot [src] into the [I] and charge its internal uplink.")
+ if(istype(I, /obj/item) && I.hidden_uplink && I.hidden_uplink.active) //No metagaming by using this on every PDA around just to see if it gets used up.
+ I.hidden_uplink.telecrystals += amount
+ use(amount)
+ to_chat(user, "You slot [src] into the [I] and charge its internal uplink.")
+ else if(istype(I, /obj/item/weapon/cartridge/virus/frame))
+ var/obj/item/weapon/cartridge/virus/frame/cart = I
+ if(!cart.charges)
+ to_chat(user, "The [cart] is out of charges, it's refusing to accept the [src]")
+ return
+ cart.telecrystals += amount
+ use(amount)
+ to_chat(user, "You slot [src] into the [cart]. The next time it's used, it will also give telecrystals")
/obj/item/stack/telecrystal/five
amount = 5
diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm
index 90e7d1be1a..a37efdc472 100644
--- a/code/game/objects/items/weapons/storage/uplink_kits.dm
+++ b/code/game/objects/items/weapons/storage/uplink_kits.dm
@@ -87,7 +87,7 @@
new /obj/item/device/doorCharge(src)
new /obj/item/device/camera_bug(src)
new /obj/item/device/sbeacondrop/powersink(src)
- new /obj/item/weapon/cartridge/syndicate(src)
+ new /obj/item/weapon/cartridge/virus/syndicate(src)
new /obj/item/weapon/storage/toolbox/syndicate(src) //To actually get to those places
new /obj/item/pizzabox/bomb
diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm
index cacfbd101b..50eae80877 100644
--- a/code/modules/flufftext/Hallucination.dm
+++ b/code/modules/flufftext/Hallucination.dm
@@ -530,7 +530,7 @@ Gunshots/explosions/opening doors/less rare audio (done)
var/static/list/non_fakeattack_weapons = list(/obj/item/weapon/gun/ballistic, /obj/item/ammo_box/a357,\
/obj/item/weapon/gun/energy/kinetic_accelerator/crossbow, /obj/item/weapon/melee/energy/sword/saber,\
/obj/item/weapon/storage/box/syndicate, /obj/item/weapon/storage/box/emps,\
- /obj/item/weapon/cartridge/syndicate, /obj/item/clothing/under/chameleon,\
+ /obj/item/weapon/cartridge/virus/syndicate, /obj/item/clothing/under/chameleon,\
/obj/item/clothing/shoes/chameleon, /obj/item/weapon/card/id/syndicate,\
/obj/item/clothing/mask/chameleon, /obj/item/clothing/glasses/thermal,\
/obj/item/device/chameleon, /obj/item/weapon/card/emag, /obj/item/weapon/grenade/plastic/x4,\
diff --git a/code/modules/uplink/uplink.dm b/code/modules/uplink/uplink.dm
index f3379b9110..d80872a427 100644
--- a/code/modules/uplink/uplink.dm
+++ b/code/modules/uplink/uplink.dm
@@ -19,6 +19,7 @@ GLOBAL_LIST_EMPTY(uplinks)
var/spent_telecrystals = 0
var/purchase_log = ""
var/list/uplink_items
+ var/hidden_crystals = 0
/obj/item/device/uplink/Initialize()
. = ..()
@@ -57,7 +58,8 @@ GLOBAL_LIST_EMPTY(uplinks)
/obj/item/device/uplink/interact(mob/user)
active = TRUE
- ui_interact(user)
+ if(user)
+ ui_interact(user)
/obj/item/device/uplink/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state)
@@ -119,6 +121,8 @@ GLOBAL_LIST_EMPTY(uplinks)
. = TRUE
if("lock")
active = FALSE
+ telecrystals += hidden_crystals
+ hidden_crystals = 0
SStgui.close_uis(src)
if("select")
selected_cat = params["category"]
diff --git a/code/modules/uplink/uplink_item.dm b/code/modules/uplink/uplink_item.dm
index 21c07750de..6c638739ae 100644
--- a/code/modules/uplink/uplink_item.dm
+++ b/code/modules/uplink/uplink_item.dm
@@ -686,7 +686,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
detonate PDAs of crewmembers who have their message feature enabled. \
The concussive effect from the explosion will knock the recipient out for a short period, and deafen \
them for longer. Beware, it has a chance to detonate your PDA."
- item = /obj/item/weapon/cartridge/syndicate
+ item = /obj/item/weapon/cartridge/virus/syndicate
cost = 6
/datum/uplink_item/stealthy_weapons/suppressor
@@ -744,6 +744,15 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
exclude_modes = list(/datum/game_mode/nuclear)
player_minimum = 20
+/datum/uplink_item/stealthy_tools/frame
+ name = "F.R.A.M.E. PDA Cartridge"
+ desc = "When inserted into a personal digital assistant, this cartridge gives you five PDA viruses which \
+ when used cause the targeted PDA to become a new uplink with zero TCs, and immediately become unlocked. \
+ You will recieve the unlock code upon activating the virus, and the new uplink may be charged with \
+ telecrystals normally."
+ item = /obj/item/weapon/cartridge/virus/frame
+ cost = 4
+
/datum/uplink_item/stealthy_tools/syndigaloshes/nuke
name = "Stealthy No-Slip Chameleon Shoes"
desc = "These shoes will allow the wearer to run on wet floors and slippery objects without falling down. \
diff --git a/tgstation.dme b/tgstation.dme
index c1bbac4d4a..086af0d9c1 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -787,6 +787,7 @@
#include "code\game\objects\items\devices\PDA\PDA.dm"
#include "code\game\objects\items\devices\PDA\PDA_types.dm"
#include "code\game\objects\items\devices\PDA\radio.dm"
+#include "code\game\objects\items\devices\PDA\virus_cart.dm"
#include "code\game\objects\items\devices\radio\beacon.dm"
#include "code\game\objects\items\devices\radio\electropack.dm"
#include "code\game\objects\items\devices\radio\encryptionkey.dm"