diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm
index c5966452bb..1d2496cb11 100644
--- a/code/datums/components/uplink.dm
+++ b/code/datums/components/uplink.dm
@@ -21,8 +21,9 @@ GLOBAL_LIST_EMPTY(uplinks)
var/datum/uplink_purchase_log/purchase_log
var/list/uplink_items
var/hidden_crystals = 0
+ var/datum/ui_state/checkstate
-/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 = 20, datum/ui_state/_checkstate)
if(!isitem(parent))
return COMPONENT_INCOMPATIBLE
@@ -54,6 +55,7 @@ GLOBAL_LIST_EMPTY(uplinks)
active = _enabled
gamemode = _gamemode
telecrystals = starting_tc
+ checkstate = _checkstate
if(!lockable)
active = TRUE
locked = FALSE
@@ -112,6 +114,7 @@ GLOBAL_LIST_EMPTY(uplinks)
/datum/component/uplink/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)
+ state = checkstate ? checkstate : state
active = TRUE
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
@@ -120,6 +123,12 @@ GLOBAL_LIST_EMPTY(uplinks)
ui.set_style("syndicate")
ui.open()
+/datum/component/uplink/ui_host(mob/user)
+ if(istype(parent, /obj/item/implant)) //implants are like organs, not really located inside mobs codewise.
+ var/obj/item/implant/I = parent
+ return I.imp_in
+ return ..()
+
/datum/component/uplink/ui_data(mob/user)
if(!user.mind)
return
diff --git a/code/game/objects/items/devices/gps.dm b/code/game/objects/items/devices/gps.dm
index c362d9f7f2..bd0d4a44c3 100644
--- a/code/game/objects/items/devices/gps.dm
+++ b/code/game/objects/items/devices/gps.dm
@@ -164,8 +164,19 @@ GLOBAL_LIST_EMPTY(GPS_list)
gpstag = "Eerie Signal"
desc = "Report to a coder immediately."
invisibility = INVISIBILITY_MAXIMUM
+ var/obj/item/implant/gps/implant
-/obj/item/gps/mining/internal
+/obj/item/gps/internal/Initialize(mapload, obj/item/implant/gps/_implant)
+ . = ..()
+ implant = _implant
+
+/obj/item/gps/internal/Destroy()
+ if(implant?.imp_in)
+ qdel(implant)
+ else
+ return ..()
+
+/obj/item/gps/internal/mining
icon_state = "gps-m"
gpstag = "MINER"
desc = "A positioning system helpful for rescuing trapped or injured miners, keeping one on you at all times while mining might just save your life."
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index 719fe6ddd8..618e91e803 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -414,3 +414,16 @@
/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 ..()
diff --git a/code/game/objects/items/implants/implant_chem.dm b/code/game/objects/items/implants/implant_chem.dm
index a951ae5759..3be92c0453 100644
--- a/code/game/objects/items/implants/implant_chem.dm
+++ b/code/game/objects/items/implants/implant_chem.dm
@@ -4,7 +4,7 @@
icon_state = "reagents"
container_type = OPENCONTAINER
activated = FALSE
- var/obj/item/chemholder
+ var/obj/item/imp_chemholder/chemholder
/obj/item/implant/chem/get_data()
var/dat = {"Implant Specifications:
@@ -33,18 +33,23 @@
/obj/item/implant/chem/implant(mob/living/target, mob/user, silent = FALSE)
. = ..()
- if(.)
- chemholder = new(imp_in)
- chemholder.resistance_flags |= INDESTRUCTIBLE //bomb-proofing.
- chemholder.item_flags |= DROPDEL
- reagents.trans_to(chemholder, reagents.total_volume)
+ if(!.)
+ return
+ if(chemholder)
+ chemholder.forceMove(target)
+ return
+ chemholder = new(imp_in, src)
+ reagents.trans_to(chemholder, reagents.total_volume)
/obj/item/implant/chem/removed(mob/target, silent = FALSE, special = 0)
. = ..()
- if(.)
+ if(!.)
+ return
+ if(!special)
chemholder.reagents.trans_to(src, chemholder.reagents.total_volume)
QDEL_NULL(chemholder)
-
+ else
+ chemholder?.moveToNullspace()
/obj/item/implant/chem/trigger(emote, mob/living/source)
if(emote == "deathgasp")
@@ -79,3 +84,17 @@
return TRUE
else
return ..()
+
+/obj/item/imp_chemholder
+ var/obj/item/implant/chem/implant
+
+/obj/item/imp_chemholder/Initialize(mapload, obj/item/implant/chem/_implant)
+ . = ..()
+ create_reagents(50)
+ implant = _implant
+
+/obj/item/imp_chemholder/Destroy()
+ if(implant?.imp_in)
+ qdel(implant)
+ else
+ return ..()
\ No newline at end of file
diff --git a/code/game/objects/items/implants/implant_clown.dm b/code/game/objects/items/implants/implant_clown.dm
index ae1fef109d..bb98e72b30 100644
--- a/code/game/objects/items/implants/implant_clown.dm
+++ b/code/game/objects/items/implants/implant_clown.dm
@@ -11,7 +11,7 @@
/obj/item/implant/sad_trombone/trigger(emote, mob/source)
if(emote == "deathgasp")
- playsound(loc, 'sound/misc/sadtrombone.ogg', 50, 0)
+ playsound(source.loc, 'sound/misc/sadtrombone.ogg', 50, 0)
/obj/item/implanter/sad_trombone
name = "implanter (sad trombone)"
diff --git a/code/game/objects/items/implants/implant_explosive.dm b/code/game/objects/items/implants/implant_explosive.dm
index a78bc45c69..b93c9419a3 100644
--- a/code/game/objects/items/implants/implant_explosive.dm
+++ b/code/game/objects/items/implants/implant_explosive.dm
@@ -11,7 +11,7 @@
var/popup = FALSE // is the DOUWANNABLOWUP window open?
var/active = FALSE
-/obj/item/implant/sad_trombone/trigger(emote, mob/source)
+/obj/item/implant/explosive/trigger(emote, mob/source)
if(emote == "deathgasp")
activate("death")
diff --git a/code/game/objects/items/implants/implant_misc.dm b/code/game/objects/items/implants/implant_misc.dm
index 24ee6d0966..b994934af6 100644
--- a/code/game/objects/items/implants/implant_misc.dm
+++ b/code/game/objects/items/implants/implant_misc.dm
@@ -78,62 +78,4 @@
healthstring = "Oxygen Deprivation Damage => [round(L.getOxyLoss())]
Fire Damage => [round(L.getFireLoss())]
Toxin Damage => [round(L.getToxLoss())]
Brute Force Damage => [round(L.getBruteLoss())]"
if (!healthstring)
healthstring = "ERROR"
- return healthstring
-
-/obj/item/implant/radio
- name = "internal radio implant"
- activated = TRUE
- var/obj/item/radio/radio
- var/radio_key
- var/subspace_transmission = FALSE
- icon = 'icons/obj/radio.dmi'
- icon_state = "walkietalkie"
-
-/obj/item/implant/radio/activate()
- . = ..()
- // needs to be GLOB.deep_inventory_state otherwise it won't open
- radio.ui_interact(usr, "main", null, FALSE, null, GLOB.deep_inventory_state)
-
-/obj/item/implant/radio/Initialize(mapload)
- . = ..()
-
- radio = new(src)
- // almost like an internal headset, but without the
- // "must be in ears to hear" restriction.
- radio.name = "internal radio"
- radio.subspace_transmission = subspace_transmission
- radio.canhear_range = 0
- if(radio_key)
- radio.keyslot = new radio_key
- radio.recalculateChannels()
-
-/obj/item/implant/radio/mining
- radio_key = /obj/item/encryptionkey/headset_cargo
-
-/obj/item/implant/radio/syndicate
- desc = "Are you there God? It's me, Syndicate Comms Agent."
- radio_key = /obj/item/encryptionkey/syndicate
- subspace_transmission = TRUE
-
-/obj/item/implant/radio/slime
- name = "slime radio"
- icon = 'icons/obj/surgery.dmi'
- icon_state = "adamantine_resonator"
- radio_key = /obj/item/encryptionkey/headset_sci
- subspace_transmission = TRUE
-
-/obj/item/implant/radio/get_data()
- var/dat = {"Implant Specifications:
- Name: Internal Radio Implant
- Life: 24 hours
- Implant Details: Allows user to use an internal radio, useful if user expects equipment loss, or cannot equip conventional radios."}
- return dat
-
-/obj/item/implanter/radio
- name = "implanter (internal radio)"
- imp_type = /obj/item/implant/radio
-
-/obj/item/implanter/radio/syndicate
- name = "implanter (internal syndicate radio)"
- imp_type = /obj/item/implant/radio/syndicate
-
+ return healthstring
\ No newline at end of file
diff --git a/code/game/objects/items/implants/implant_radio.dm b/code/game/objects/items/implants/implant_radio.dm
new file mode 100644
index 0000000000..5d3d579a4e
--- /dev/null
+++ b/code/game/objects/items/implants/implant_radio.dm
@@ -0,0 +1,69 @@
+/obj/item/implant/radio
+ name = "internal radio implant"
+ activated = TRUE
+ var/obj/item/radio/internal/radio
+ var/radio_key
+ var/subspace_transmission = FALSE
+ icon = 'icons/obj/radio.dmi'
+ icon_state = "walkietalkie"
+
+/obj/item/implant/radio/activate()
+ . = ..()
+ // needs to be GLOB.deep_inventory_state otherwise it won't open
+ radio.ui_interact(usr, "main", null, FALSE, null, GLOB.deep_inventory_state)
+
+/obj/item/implant/radio/implant(mob/living/target, mob/user, silent = FALSE)
+ . = ..()
+ if(!.)
+ return
+ if(radio)
+ radio.forceMove(target)
+ return
+ radio = new(target)
+ // almost like an internal headset, but without the
+ // "must be in ears to hear" restriction.
+ radio.name = "internal radio"
+ radio.subspace_transmission = subspace_transmission
+ radio.canhear_range = 0
+ if(radio_key)
+ radio.keyslot = new radio_key
+ radio.recalculateChannels()
+
+/obj/item/implant/radio/removed(mob/target, silent = FALSE, special = 0)
+ . = ..()
+ if(!.)
+ return
+ if(!special)
+ qdel(radio)
+ else
+ radio?.moveToNullspace()
+
+/obj/item/implant/radio/mining
+ radio_key = /obj/item/encryptionkey/headset_cargo
+
+/obj/item/implant/radio/syndicate
+ desc = "Are you there God? It's me, Syndicate Comms Agent."
+ radio_key = /obj/item/encryptionkey/syndicate
+ subspace_transmission = TRUE
+
+/obj/item/implant/radio/slime
+ name = "slime radio"
+ icon = 'icons/obj/surgery.dmi'
+ icon_state = "adamantine_resonator"
+ radio_key = /obj/item/encryptionkey/headset_sci
+ subspace_transmission = TRUE
+
+/obj/item/implant/radio/get_data()
+ var/dat = {"Implant Specifications:
+ Name: Internal Radio Implant
+ Life: 24 hours
+ Implant Details: Allows user to use an internal radio, useful if user expects equipment loss, or cannot equip conventional radios."}
+ return dat
+
+/obj/item/implanter/radio
+ name = "implanter (internal radio)"
+ imp_type = /obj/item/implant/radio
+
+/obj/item/implanter/radio/syndicate
+ name = "implanter (internal syndicate radio)"
+ imp_type = /obj/item/implant/radio/syndicate
\ No newline at end of file
diff --git a/code/game/objects/items/implants/implant_track.dm b/code/game/objects/items/implants/implant_track.dm
index 913c577f2c..7eaa2b67d1 100644
--- a/code/game/objects/items/implants/implant_track.dm
+++ b/code/game/objects/items/implants/implant_track.dm
@@ -3,8 +3,8 @@
desc = "Track with this."
activated = 0
-/obj/item/implant/tracking/New()
- ..()
+/obj/item/implant/tracking/Initialize()
+ . = ..()
GLOB.tracked_implants += src
/obj/item/implant/tracking/Destroy()
@@ -15,7 +15,28 @@
imp_type = /obj/item/implant/tracking
/obj/item/implanter/tracking/gps
- imp_type = /obj/item/gps/mining/internal
+ imp_type = /obj/item/implant/gps
+
+/obj/item/implant/gps
+ var/obj/item/gps/internal/mining/real_gps
+
+/obj/item/implant/gps/implant(mob/living/target, mob/user, silent = FALSE)
+ . = ..()
+ if(!.)
+ return
+ if(real_gps)
+ real_gps.forceMove(target)
+ else
+ real_gps = new(target)
+
+/obj/item/implant/gps/removed(mob/living/source, silent = FALSE, special = 0)
+ . = ..()
+ if(!.)
+ return
+ if(!special)
+ qdel(real_gps)
+ else
+ real_gps?.moveToNullspace()
/obj/item/implant/tracking/get_data()
var/dat = {"Implant Specifications:
diff --git a/code/game/objects/items/implants/implantuplink.dm b/code/game/objects/items/implants/implant_uplink.dm
similarity index 93%
rename from code/game/objects/items/implants/implantuplink.dm
rename to code/game/objects/items/implants/implant_uplink.dm
index 9000fbbe34..9895c1e34c 100644
--- a/code/game/objects/items/implants/implantuplink.dm
+++ b/code/game/objects/items/implants/implant_uplink.dm
@@ -1,23 +1,23 @@
-/obj/item/implant/uplink
- name = "uplink implant"
- desc = "Sneeki breeki."
- icon = 'icons/obj/radio.dmi'
- icon_state = "radio"
- lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
- var/starting_tc = 0
-
-/obj/item/implant/uplink/Initialize(mapload, _owner)
- . = ..()
- AddComponent(/datum/component/uplink, _owner, TRUE, FALSE, null, starting_tc)
-
-/obj/item/implanter/uplink
- name = "implanter (uplink)"
- imp_type = /obj/item/implant/uplink
-
-/obj/item/implanter/uplink/precharged
- name = "implanter (precharged uplink)"
- imp_type = /obj/item/implant/uplink/precharged
-
-/obj/item/implant/uplink/precharged
- starting_tc = 10
+/obj/item/implant/uplink
+ name = "uplink implant"
+ desc = "Sneeki breeki."
+ icon = 'icons/obj/radio.dmi'
+ icon_state = "radio"
+ lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
+ var/starting_tc = 0
+
+/obj/item/implant/uplink/Initialize(mapload, _owner)
+ . = ..()
+ AddComponent(/datum/component/uplink, _owner, TRUE, FALSE, null, starting_tc, GLOB.not_incapacitated_state)
+
+/obj/item/implanter/uplink
+ name = "implanter (uplink)"
+ imp_type = /obj/item/implant/uplink
+
+/obj/item/implanter/uplink/precharged
+ name = "implanter (precharged uplink)"
+ imp_type = /obj/item/implant/uplink/precharged
+
+/obj/item/implant/uplink/precharged
+ starting_tc = 10
diff --git a/tgstation.dme b/tgstation.dme
index 12a91dfaa9..0f1d6284ad 100755
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -887,15 +887,16 @@
#include "code\game\objects\items\implants\implant_krav_maga.dm"
#include "code\game\objects\items\implants\implant_mindshield.dm"
#include "code\game\objects\items\implants\implant_misc.dm"
+#include "code\game\objects\items\implants\implant_radio.dm"
#include "code\game\objects\items\implants\implant_spell.dm"
#include "code\game\objects\items\implants\implant_stealth.dm"
#include "code\game\objects\items\implants\implant_storage.dm"
#include "code\game\objects\items\implants\implant_track.dm"
+#include "code\game\objects\items\implants\implant_uplink.dm"
#include "code\game\objects\items\implants\implantcase.dm"
#include "code\game\objects\items\implants\implantchair.dm"
#include "code\game\objects\items\implants\implanter.dm"
#include "code\game\objects\items\implants\implantpad.dm"
-#include "code\game\objects\items\implants\implantuplink.dm"
#include "code\game\objects\items\melee\energy.dm"
#include "code\game\objects\items\melee\misc.dm"
#include "code\game\objects\items\melee\transforming.dm"