diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm
index 377a32af6ad..0906738b673 100644
--- a/code/__DEFINES/antagonists.dm
+++ b/code/__DEFINES/antagonists.dm
@@ -87,3 +87,12 @@ GLOBAL_LIST_INIT(heretic_start_knowledge,list(/datum/eldritch_knowledge/spell/ba
/// How much does it cost to reroll strains?
#define BLOB_REROLL_COST 40
+
+/// How many telecrystals a normal traitor starts with
+#define TELECRYSTALS_DEFAULT 20
+/// How many telecrystals mapper/admin only "precharged" uplink implant
+#define TELECRYSTALS_PRELOADED_IMPLANT 10
+/// The normal cost of an uplink implant; used for calcuating how many
+/// TC to charge someone if they get a free implant through choice or
+/// because they have nothing else that supports an implant.
+#define UPLINK_IMPLANT_TELECRYSTAL_COST 4
diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm
index 946b186b314..9e9c479330f 100644
--- a/code/_globalvars/lists/flavor_misc.dm
+++ b/code/_globalvars/lists/flavor_misc.dm
@@ -166,7 +166,8 @@ GLOBAL_LIST_INIT(jumpsuitlist, list(PREF_SUIT, PREF_SKIRT))
#define UPLINK_PDA "PDA"
#define UPLINK_RADIO "Radio"
#define UPLINK_PEN "Pen" //like a real spy!
-GLOBAL_LIST_INIT(uplink_spawn_loc_list, list(UPLINK_PDA, UPLINK_RADIO, UPLINK_PEN))
+#define UPLINK_IMPLANT "Implant"
+GLOBAL_LIST_INIT(uplink_spawn_loc_list, list(UPLINK_PDA, UPLINK_RADIO, UPLINK_PEN, UPLINK_IMPLANT))
//Female Uniforms
GLOBAL_LIST_EMPTY(female_clothing_icons)
diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm
index b7ce377cfac..105bcbdef9f 100644
--- a/code/datums/components/uplink.dm
+++ b/code/datums/components/uplink.dm
@@ -29,7 +29,7 @@
var/list/previous_attempts
-/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20)
+/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = TELECRYSTALS_DEFAULT)
if(!isitem(parent))
return COMPONENT_INCOMPATIBLE
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 2acf74d9881..4cadbe3e7ba 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -358,6 +358,7 @@
P = locate() in all_contents
var/obj/item/uplink_loc
+ var/implant = FALSE
if(traitor_mob.client && traitor_mob.client.prefs)
switch(traitor_mob.client.prefs.uplink_spawn_loc)
@@ -375,20 +376,13 @@
uplink_loc = P
if(UPLINK_PEN)
uplink_loc = P
+ if(UPLINK_IMPLANT)
+ implant = TRUE
- if(!uplink_loc) // We've looked everywhere, let's just give you a pen
- if(istype(traitor_mob.back,/obj/item/storage)) //ok buddy you better have a backpack!
- P = new /obj/item/pen(traitor_mob.back)
- else
- P = new /obj/item/pen(traitor_mob.loc)
- traitor_mob.put_in_hands(P) // I hope you don't have arms and your traitor pen gets stolen for all this trouble you've caused.
- uplink_loc = P
+ if(!uplink_loc) // We've looked everywhere, let's just implant you
+ implant = TRUE
- if (!uplink_loc)
- if(!silent)
- to_chat(traitor_mob, "Unfortunately, [employer] wasn't able to get you an Uplink.")
- . = 0
- else
+ if (!implant)
. = uplink_loc
var/datum/component/uplink/U = uplink_loc.AddComponent(/datum/component/uplink, traitor_mob.key)
if(!U)
@@ -406,6 +400,13 @@
uplink_owner.antag_memory += U.unlock_note + "
"
else
traitor_mob.mind.store_memory(U.unlock_note)
+ else
+ var/obj/item/implant/uplink/starting/I = new(traitor_mob)
+ I.implant(traitor_mob, null, silent = TRUE)
+ if(!silent)
+ to_chat(traitor_mob, "[employer] has cunningly implanted you with a Syndicate Uplink (although uplink implants cost valuable TC, so you will have slightly less). Simply trigger the uplink to access it.")
+ return I
+
//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.
@@ -611,7 +612,7 @@
switch(href_list["common"])
if("undress")
for(var/obj/item/W in current)
- current.dropItemToGround(W, TRUE) //The 1 forces all items to drop, since this is an admin undress.
+ current.dropItemToGround(W, TRUE) //The TRUE forces all items to drop, since this is an admin undress.
if("takeuplink")
take_uplink()
memory = null//Remove any memory they may have had.
diff --git a/code/game/objects/items/implants/implantuplink.dm b/code/game/objects/items/implants/implantuplink.dm
index 0cac8f838ac..6936602576f 100644
--- a/code/game/objects/items/implants/implantuplink.dm
+++ b/code/game/objects/items/implants/implantuplink.dm
@@ -10,6 +10,18 @@
/obj/item/implant/uplink/Initialize(mapload, _owner)
. = ..()
AddComponent(/datum/component/uplink, _owner, TRUE, FALSE, null, starting_tc)
+ RegisterSignal(src, COMSIG_COMPONENT_REMOVING, .proc/_component_removal)
+
+/**
+ * Proc called when component is removed; ie. uplink component
+ *
+ * Callback catching if the underlying uplink component has been removed,
+ * generally by admin verbs or var editing. Implant does nothing without
+ * the component, so delete itself.
+ */
+/obj/item/implant/uplink/proc/_component_removal(datum/source, datum/component/component)
+ if(istype(component, /datum/component/uplink))
+ qdel(src)
/obj/item/implanter/uplink
name = "implanter (uplink)"
@@ -20,4 +32,7 @@
imp_type = /obj/item/implant/uplink/precharged
/obj/item/implant/uplink/precharged
- starting_tc = 10
+ starting_tc = TELECRYSTALS_PRELOADED_IMPLANT
+
+/obj/item/implant/uplink/starting
+ starting_tc = TELECRYSTALS_DEFAULT - UPLINK_IMPLANT_TELECRYSTAL_COST
diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm
index e2957341b74..000f5f02046 100644
--- a/code/modules/uplink/uplink_items.dm
+++ b/code/modules/uplink/uplink_items.dm
@@ -1687,7 +1687,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
desc = "An implant injected into the body, and later activated at the user's will. Has no telecrystals and must be charged by the use of physical telecrystals. \
Undetectable (except via surgery), and excellent for escaping confinement."
item = /obj/item/storage/box/syndie_kit/imp_uplink
- cost = 4
+ cost = UPLINK_IMPLANT_TELECRYSTAL_COST
// An empty uplink is kinda useless.
surplus = 0
restricted = TRUE