diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm
index 8982530ab6..2c3b7518ba 100644
--- a/code/datums/components/uplink.dm
+++ b/code/datums/components/uplink.dm
@@ -24,8 +24,9 @@ GLOBAL_LIST_EMPTY(uplinks)
var/unlock_note
var/unlock_code
var/failsafe_code
+ 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
@@ -57,6 +58,7 @@ GLOBAL_LIST_EMPTY(uplinks)
active = _enabled
gamemode = _gamemode
telecrystals = starting_tc
+ checkstate = _checkstate
if(!lockable)
active = TRUE
locked = FALSE
@@ -115,6 +117,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)
@@ -123,6 +126,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/datums/outfit.dm b/code/datums/outfit.dm
index 68165af956..8386b59d97 100755
--- a/code/datums/outfit.dm
+++ b/code/datums/outfit.dm
@@ -112,7 +112,7 @@
H.update_action_buttons_icon()
if(implants)
for(var/implant_type in implants)
- var/obj/item/implant/I = new implant_type(H)
+ var/obj/item/implant/I = new implant_type
I.implant(H, null, TRUE)
H.update_body()
diff --git a/code/datums/radiation_wave.dm b/code/datums/radiation_wave.dm
index 5fb777f9c5..6118428547 100644
--- a/code/datums/radiation_wave.dm
+++ b/code/datums/radiation_wave.dm
@@ -103,7 +103,6 @@
/obj/structure/cable,
/obj/machinery/atmospherics,
/obj/item/ammo_casing,
- /obj/item/implant,
/obj/singularity
))
if(!can_contaminate || blacklisted[thing.type])
diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm
index 615d55a818..1767d468ec 100644
--- a/code/game/gamemodes/nuclear/nuclear.dm
+++ b/code/game/gamemodes/nuclear/nuclear.dm
@@ -155,9 +155,9 @@
var/obj/item/U = new uplink_type(H, H.key, tc)
H.equip_to_slot_or_del(U, SLOT_IN_BACKPACK)
- var/obj/item/implant/weapons_auth/W = new/obj/item/implant/weapons_auth(H)
+ var/obj/item/implant/weapons_auth/W = new
W.implant(H)
- var/obj/item/implant/explosive/E = new/obj/item/implant/explosive(H)
+ var/obj/item/implant/explosive/E = new
E.implant(H)
H.faction |= ROLE_SYNDICATE
H.update_icons()
diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm
index 26f0d06ecb..2202167709 100644
--- a/code/game/machinery/computer/cloning.dm
+++ b/code/game/machinery/computer/cloning.dm
@@ -228,7 +228,7 @@
dat += "
[src.active_record.fields["name"]]
"
dat += "Scan ID [src.active_record.fields["id"]] Clone
"
- var/obj/item/implant/health/H = locate(src.active_record.fields["imp"])
+ var/obj/item/implant/health/H = locate(active_record.fields["imp"])
if ((H) && (istype(H)))
dat += "Health Implant Data:
[H.sensehealth()]
"
diff --git a/code/game/machinery/computer/prisoner.dm b/code/game/machinery/computer/prisoner.dm
deleted file mode 100644
index a852612d9d..0000000000
--- a/code/game/machinery/computer/prisoner.dm
+++ /dev/null
@@ -1 +0,0 @@
-/obj/machinery/computer/prisoner
diff --git a/code/game/machinery/computer/prisoner/management.dm b/code/game/machinery/computer/prisoner/management.dm
index e231a1748a..653f6bf48b 100644
--- a/code/game/machinery/computer/prisoner/management.dm
+++ b/code/game/machinery/computer/prisoner/management.dm
@@ -35,11 +35,11 @@
dat += "
Chemical Implants
"
var/turf/Tr = null
for(var/obj/item/implant/chem/C in GLOB.tracked_chem_implants)
- Tr = get_turf(C)
- if((Tr) && (Tr.z != src.z))
- continue//Out of range
if(!C.imp_in)
continue
+ Tr = get_turf(C.imp_in)
+ if((Tr) && (Tr.z != src.z))
+ continue//Out of range
dat += "ID: [C.imp_in.name] | Remaining Units: [C.reagents.total_volume]
"
dat += "| Inject: "
dat += "((1))"
@@ -48,9 +48,9 @@
dat += "********************************
"
dat += "
Tracking Implants
"
for(var/obj/item/implant/tracking/T in GLOB.tracked_implants)
- if(!isliving(T.imp_in))
+ if(!T.imp_in || !isliving(T.imp_in))
continue
- Tr = get_turf(T)
+ Tr = get_turf(T.imp_in)
if((Tr) && (Tr.z != src.z))
continue//Out of range
diff --git a/code/game/machinery/computer/teleporter.dm b/code/game/machinery/computer/teleporter.dm
index b9b95eecd0..e50eeb8619 100644
--- a/code/game/machinery/computer/teleporter.dm
+++ b/code/game/machinery/computer/teleporter.dm
@@ -124,14 +124,14 @@
L[avoid_assoc_duplicate_keys(A.name, areaindex)] = R
for(var/obj/item/implant/tracking/I in GLOB.tracked_implants)
- if(!I.imp_in || !isliving(I.loc))
+ if(!I.imp_in || !isliving(I.imp_in))
continue
else
- var/mob/living/M = I.loc
+ var/mob/living/M = I.imp_in
if(M.stat == DEAD)
if(M.timeofdeath + 6000 < world.time)
continue
- if(is_eligible(I))
+ if(is_eligible(M))
L[avoid_assoc_duplicate_keys(M.real_name, areaindex)] = I
var/desc = input("Please select a location to lock in.", "Locking Computer") as null|anything in L
diff --git a/code/game/objects/items/devices/gps.dm b/code/game/objects/items/devices/gps.dm
index 637bb794d3..9d1b670e71 100644
--- a/code/game/objects/items/devices/gps.dm
+++ b/code/game/objects/items/devices/gps.dm
@@ -167,8 +167,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 7c136f556e..926810cfbf 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -413,3 +413,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.dm b/code/game/objects/items/implants/implant.dm
index 482cfb0d8e..e7b55d53f5 100644
--- a/code/game/objects/items/implants/implant.dm
+++ b/code/game/objects/items/implants/implant.dm
@@ -72,7 +72,7 @@
else
return FALSE
- forceMove(target)
+ moveToNullspace()
imp_in = target
target.implants += src
if(activated)
@@ -89,7 +89,6 @@
return TRUE
/obj/item/implant/proc/removed(mob/living/source, silent = FALSE, special = 0)
- moveToNullspace()
imp_in = null
source.implants -= src
for(var/X in actions)
diff --git a/code/game/objects/items/implants/implant_chem.dm b/code/game/objects/items/implants/implant_chem.dm
index c6c8be1a83..8da1d1e472 100644
--- a/code/game/objects/items/implants/implant_chem.dm
+++ b/code/game/objects/items/implants/implant_chem.dm
@@ -3,6 +3,7 @@
desc = "Injects things."
icon_state = "reagents"
activated = FALSE
+ var/obj/item/imp_chemholder/chemholder
/obj/item/implant/chem/get_data()
var/dat = {"Implant Specifications:
@@ -29,6 +30,26 @@
GLOB.tracked_chem_implants -= src
return ..()
+/obj/item/implant/chem/implant(mob/living/target, mob/user, silent = FALSE)
+ . = ..()
+ 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(!.)
+ 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")
if(istype(source) && !(source.stat == DEAD))
@@ -45,13 +66,12 @@
injectamount = reagents.total_volume
else
injectamount = cause
- reagents.trans_to(R, injectamount)
+ chemholder.reagents.trans_to(R, injectamount)
to_chat(R, "You hear a faint beep.")
- if(!reagents.total_volume)
+ if(!chemholder.reagents.total_volume)
to_chat(R, "You hear a faint click from your chest.")
qdel(src)
-
/obj/item/implantcase/chem
name = "implant case - 'Remote Chemical'"
desc = "A glass case containing a remote chemical implant."
@@ -63,3 +83,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 e749a6c4be..b93c9419a3 100644
--- a/code/game/objects/items/implants/implant_explosive.dm
+++ b/code/game/objects/items/implants/implant_explosive.dm
@@ -11,8 +11,9 @@
var/popup = FALSE // is the DOUWANNABLOWUP window open?
var/active = FALSE
-/obj/item/implant/explosive/on_mob_death(mob/living/L, gibbed)
- activate("death")
+/obj/item/implant/explosive/trigger(emote, mob/source)
+ if(emote == "deathgasp")
+ activate("death")
/obj/item/implant/explosive/get_data()
var/dat = {"Implant Specifications:
@@ -29,32 +30,18 @@
/obj/item/implant/explosive/activate(cause)
. = ..()
if(!cause || !imp_in || active)
- return 0
+ return FALSE
if(cause == "action_button" && !popup)
popup = TRUE
var/response = alert(imp_in, "Are you sure you want to activate your [name]? This will cause you to explode!", "[name] Confirmation", "Yes", "No")
popup = FALSE
if(response == "No")
- return 0
- heavy = round(heavy)
- medium = round(medium)
- weak = round(weak)
- to_chat(imp_in, "You activate your [name].")
- active = TRUE
- var/turf/boomturf = get_turf(imp_in)
- message_admins("[ADMIN_LOOKUPFLW(imp_in)] has activated their [name] at [ADMIN_VERBOSEJMP(boomturf)], with cause of [cause].")
-//If the delay is short, just blow up already jeez
- if(delay <= 7)
- explosion(src,heavy,medium,weak,weak, flame_range = weak)
- if(imp_in)
- imp_in.gib(1)
- qdel(src)
- return
- timed_explosion()
+ return FALSE
+ addtimer(CALLBACK(src, .proc/timed_explosion, cause), 1)
/obj/item/implant/explosive/implant(mob/living/target)
for(var/X in target.implants)
- if(istype(X, type))
+ if(istype(X, /obj/item/implant/explosive))
var/obj/item/implant/explosive/imp_e = X
imp_e.heavy += heavy
imp_e.medium += medium
@@ -65,22 +52,37 @@
return ..()
-/obj/item/implant/explosive/proc/timed_explosion()
- imp_in.visible_message("[imp_in] starts beeping ominously!")
- playsound(loc, 'sound/items/timer.ogg', 30, 0)
- sleep(delay*0.25)
- if(imp_in && !imp_in.stat)
+/obj/item/implant/explosive/proc/timed_explosion(cause)
+ if(cause == "death" && imp_in.stat != DEAD)
+ return FALSE
+ heavy = round(heavy)
+ medium = round(medium)
+ weak = round(weak)
+ to_chat(imp_in, "You activate your [name].")
+ active = TRUE
+ var/turf/boomturf = get_turf(imp_in)
+ message_admins("[ADMIN_LOOKUPFLW(imp_in)] has activated their [name] at [ADMIN_VERBOSEJMP(boomturf)], with cause of [cause].")
+ if(delay > 7)
+ imp_in?.visible_message("[imp_in] starts beeping ominously!")
+ playsound(get_turf(imp_in ? imp_in : src), 'sound/items/timer.ogg', 30, 0)
+ addtimer(CALLBACK(src, .proc/double_pain, TRUE), delay * 0.25)
+ addtimer(CALLBACK(src, .proc/double_pain), delay * 0.5)
+ addtimer(CALLBACK(src, .proc/double_pain), delay * 0.75)
+ addtimer(CALLBACK(src, .proc/boom_goes_the_weasel), delay)
+ else //If the delay is short, just blow up already jeez
+ boom_goes_the_weasel()
+
+/obj/item/implant/explosive/proc/double_pain(message = FALSE)
+ playsound(get_turf(imp_in ? imp_in : src), 'sound/items/timer.ogg', 30, 0)
+ if(!imp_in)
+ return
+ if(message && imp_in.stat == CONSCIOUS)
imp_in.visible_message("[imp_in] doubles over in pain!")
- imp_in.Knockdown(140)
- playsound(loc, 'sound/items/timer.ogg', 30, 0)
- sleep(delay*0.25)
- playsound(loc, 'sound/items/timer.ogg', 30, 0)
- sleep(delay*0.25)
- playsound(loc, 'sound/items/timer.ogg', 30, 0)
- sleep(delay*0.25)
- explosion(src,heavy,medium,weak,weak, flame_range = weak)
- if(imp_in)
- imp_in.gib(1)
+ imp_in.Knockdown(140)
+
+/obj/item/implant/explosive/proc/boom_goes_the_weasel()
+ explosion(get_turf(imp_in ? imp_in : src), heavy, medium, weak, weak, flame_range = weak)
+ imp_in?.gib(TRUE)
qdel(src)
/obj/item/implant/explosive/macro
@@ -95,17 +97,7 @@
/obj/item/implant/explosive/macro/implant(mob/living/target)
for(var/X in target.implants)
if(istype(X, type))
- return 0
-
- for(var/Y in target.implants)
- if(istype(Y, /obj/item/implant/explosive))
- var/obj/item/implant/explosive/imp_e = Y
- heavy += imp_e.heavy
- medium += imp_e.medium
- weak += imp_e.weak
- delay += imp_e.delay
- qdel(imp_e)
- break
+ return FALSE
return ..()
diff --git a/code/game/objects/items/implants/implant_mindshield.dm b/code/game/objects/items/implants/implant_mindshield.dm
index b9907cbfca..2a99c6e1ec 100644
--- a/code/game/objects/items/implants/implant_mindshield.dm
+++ b/code/game/objects/items/implants/implant_mindshield.dm
@@ -1,7 +1,6 @@
/obj/item/implant/mindshield
name = "mindshield implant"
desc = "Protects against brainwashing."
- resistance_flags = INDESTRUCTIBLE
activated = 0
/obj/item/implant/mindshield/get_data()
diff --git a/code/game/objects/items/implants/implant_misc.dm b/code/game/objects/items/implants/implant_misc.dm
index 3a4295c61e..75b0c67798 100644
--- a/code/game/objects/items/implants/implant_misc.dm
+++ b/code/game/objects/items/implants/implant_misc.dm
@@ -69,62 +69,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_storage.dm b/code/game/objects/items/implants/implant_storage.dm
index ec6b4d64c3..739873af00 100644
--- a/code/game/objects/items/implants/implant_storage.dm
+++ b/code/game/objects/items/implants/implant_storage.dm
@@ -4,30 +4,44 @@
icon_state = "storage"
item_color = "r"
var/max_slot_stacking = 4
+ var/obj/item/storage/bluespace_pocket/pocket
/obj/item/implant/storage/activate()
. = ..()
- SEND_SIGNAL(src, COMSIG_TRY_STORAGE_SHOW, imp_in, TRUE)
+ SEND_SIGNAL(pocket, COMSIG_TRY_STORAGE_SHOW, imp_in, TRUE)
/obj/item/implant/storage/removed(source, silent = FALSE, special = 0)
- . = ..()
- if(.)
- if(!special)
- qdel(GetComponent(/datum/component/storage/concrete/implant))
+ if(!special)
+ qdel(pocket)
+ else
+ pocket?.moveToNullspace()
+ return ..()
/obj/item/implant/storage/implant(mob/living/target, mob/user, silent = FALSE)
for(var/X in target.implants)
if(istype(X, type))
var/obj/item/implant/storage/imp_e = X
- GET_COMPONENT_FROM(STR, /datum/component/storage, imp_e)
+ GET_COMPONENT_FROM(STR, /datum/component/storage, imp_e.pocket)
if(!STR || (STR && STR.max_items < max_slot_stacking))
- imp_e.AddComponent(/datum/component/storage/concrete/implant)
+ imp_e.pocket.AddComponent(/datum/component/storage/concrete/implant)
qdel(src)
return TRUE
return FALSE
- AddComponent(/datum/component/storage/concrete/implant)
+ . = ..()
+ if(.)
+ if(pocket)
+ pocket.forceMove(target)
+ else
+ pocket = new(target)
- return ..()
+/obj/item/storage/bluespace_pocket
+ name = "internal bluespace pocket"
+ icon_state = "pillbox"
+ w_class = WEIGHT_CLASS_TINY
+ desc = "A tiny yet spacious pocket, usually found implanted inside sneaky syndicate agents and nowhere else."
+ component_type = /datum/component/storage/concrete/implant
+ resistance_flags = INDESTRUCTIBLE //A bomb!
+ item_flags = DROPDEL
/obj/item/implanter/storage
name = "implanter (storage)"
diff --git a/code/game/objects/items/implants/implant_track.dm b/code/game/objects/items/implants/implant_track.dm
index 913c577f2c..4b7ae3bbac 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,31 @@
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
+ name = "\improper GPS implant"
+ desc = "Track with this and a GPS."
+ activated = FALSE
+ 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/code/game/objects/items/stacks/telecrystal.dm b/code/game/objects/items/stacks/telecrystal.dm
index c1fb396529..7c34ae87bf 100644
--- a/code/game/objects/items/stacks/telecrystal.dm
+++ b/code/game/objects/items/stacks/telecrystal.dm
@@ -9,9 +9,10 @@
item_flags = NOBLUDGEON
/obj/item/stack/telecrystal/attack(mob/target, mob/user)
- if(target == user) //You can't go around smacking people with crystals to find out if they have an uplink or not.
- for(var/obj/item/implant/uplink/I in target)
- if(I && I.imp_in)
+ if(target == user && isliving(user)) //You can't go around smacking people with crystals to find out if they have an uplink or not.
+ var/mob/living/L = user
+ for(var/obj/item/implant/uplink/I in L.implants)
+ if(I?.imp_in)
GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, I)
if(hidden_uplink)
hidden_uplink.telecrystals += amount
diff --git a/code/game/objects/items/teleportation.dm b/code/game/objects/items/teleportation.dm
index 1ccc88d892..5fa0624c0a 100644
--- a/code/game/objects/items/teleportation.dm
+++ b/code/game/objects/items/teleportation.dm
@@ -75,15 +75,14 @@
temp += "Implant Signals:
"
for (var/obj/item/implant/tracking/W in GLOB.tracked_implants)
- if (!W.imp_in || !isliving(W.loc))
+ if (!isliving(W.imp_in))
continue
- else
- var/mob/living/M = W.loc
- if (M.stat == DEAD)
- if (M.timeofdeath + 6000 < world.time)
- continue
+ var/mob/living/M = W.imp_in
+ if (M.stat == DEAD)
+ if (M.timeofdeath + 6000 < world.time)
+ continue
- var/turf/tr = get_turf(W)
+ var/turf/tr = get_turf(M)
if (tr.z == sr.z && tr)
var/direct = max(abs(tr.x - sr.x), abs(tr.y - sr.y))
if (direct < 20)
diff --git a/code/modules/antagonists/abductor/equipment/abduction_outfits.dm b/code/modules/antagonists/abductor/equipment/abduction_outfits.dm
index a69c8fdeff..7e03bbf57a 100644
--- a/code/modules/antagonists/abductor/equipment/abduction_outfits.dm
+++ b/code/modules/antagonists/abductor/equipment/abduction_outfits.dm
@@ -52,5 +52,5 @@
/datum/outfit/abductor/scientist/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
..()
if(!visualsOnly)
- var/obj/item/implant/abductor/beamplant = new /obj/item/implant/abductor(H)
+ var/obj/item/implant/abductor/beamplant = new
beamplant.implant(H)
diff --git a/code/modules/antagonists/overthrow/overthrow.dm b/code/modules/antagonists/overthrow/overthrow.dm
index 2f08824c0b..075b9f13bc 100644
--- a/code/modules/antagonists/overthrow/overthrow.dm
+++ b/code/modules/antagonists/overthrow/overthrow.dm
@@ -107,9 +107,9 @@
/datum/antagonist/overthrow/proc/equip_overthrow()
if(!owner || !owner.current || !ishuman(owner.current)) // only equip existing human overthrow members. This excludes the AI, in particular.
return
- var/obj/item/implant/storage/S = locate(/obj/item/implant/storage) in owner.current
+ var/obj/item/implant/storage/S = locate(/obj/item/implant/storage) in owner.current.implants
if(!S)
- S = new(owner.current)
+ S = new
S.implant(owner.current)
var/I = pick(possible_useful_items)
if(ispath(I)) // in case some admin decides to fuck the list up for fun
diff --git a/code/modules/antagonists/wizard/wizard.dm b/code/modules/antagonists/wizard/wizard.dm
index e6cae518b6..8a20a81555 100644
--- a/code/modules/antagonists/wizard/wizard.dm
+++ b/code/modules/antagonists/wizard/wizard.dm
@@ -245,7 +245,7 @@
if(!istype(M))
return
- var/obj/item/implant/exile/Implant = new/obj/item/implant/exile(M)
+ var/obj/item/implant/exile/Implant = new
Implant.implant(M)
/datum/antagonist/wizard/academy/create_objectives()
diff --git a/code/modules/awaymissions/mission_code/Academy.dm b/code/modules/awaymissions/mission_code/Academy.dm
index 57d8420fa8..41434f7a04 100644
--- a/code/modules/awaymissions/mission_code/Academy.dm
+++ b/code/modules/awaymissions/mission_code/Academy.dm
@@ -210,8 +210,6 @@
if(4)
//Destroy Equipment
for (var/obj/item/I in user)
- if (istype(I, /obj/item/implant))
- continue
qdel(I)
if(5)
//Monkeying
diff --git a/code/modules/clothing/outfits/ert.dm b/code/modules/clothing/outfits/ert.dm
index 523ed55aa4..88cc7123fd 100644
--- a/code/modules/clothing/outfits/ert.dm
+++ b/code/modules/clothing/outfits/ert.dm
@@ -10,7 +10,7 @@
if(visualsOnly)
return
- var/obj/item/implant/mindshield/L = new/obj/item/implant/mindshield(H)
+ var/obj/item/implant/mindshield/L = new
L.implant(H, null, 1)
var/obj/item/radio/R = H.ears
diff --git a/code/modules/clothing/outfits/standard.dm b/code/modules/clothing/outfits/standard.dm
index 325c124867..6c961dc250 100644
--- a/code/modules/clothing/outfits/standard.dm
+++ b/code/modules/clothing/outfits/standard.dm
@@ -399,7 +399,7 @@
R.set_frequency(FREQ_CENTCOM)
R.freqlock = TRUE
- var/obj/item/implant/mindshield/L = new/obj/item/implant/mindshield(H)//Here you go Deuryn
+ var/obj/item/implant/mindshield/L = new //Here you go Deuryn
L.implant(H, null, 1)
@@ -426,7 +426,7 @@
/datum/outfit/debug //Debug objs plus hardsuit
name = "Debug outfit"
- uniform = /obj/item/clothing/under/patriotsuit
+ uniform = /obj/item/clothing/under/patriotsuit
suit = /obj/item/clothing/suit/space/hardsuit/syndi/elite
shoes = /obj/item/clothing/shoes/magboots/advance
suit_store = /obj/item/tank/internals/oxygen
diff --git a/code/modules/clothing/outfits/vr.dm b/code/modules/clothing/outfits/vr.dm
index cd8930641f..cd8115ac7d 100644
--- a/code/modules/clothing/outfits/vr.dm
+++ b/code/modules/clothing/outfits/vr.dm
@@ -29,9 +29,9 @@
. = ..()
var/obj/item/uplink/U = new /obj/item/uplink/nuclear_restricted(H, H.key, 80)
H.equip_to_slot_or_del(U, SLOT_IN_BACKPACK)
- var/obj/item/implant/weapons_auth/W = new/obj/item/implant/weapons_auth(H)
+ var/obj/item/implant/weapons_auth/W = new
W.implant(H)
- var/obj/item/implant/explosive/E = new/obj/item/implant/explosive(H)
+ var/obj/item/implant/explosive/E = new
E.implant(H)
H.faction |= ROLE_SYNDICATE
H.update_icons()
diff --git a/code/modules/mining/minebot.dm b/code/modules/mining/minebot.dm
index 15ff372c47..997b117b25 100644
--- a/code/modules/mining/minebot.dm
+++ b/code/modules/mining/minebot.dm
@@ -49,7 +49,7 @@
toggle_mode_action.Grant(src)
var/datum/action/innate/minedrone/dump_ore/dump_ore_action = new()
dump_ore_action.Grant(src)
- var/obj/item/implant/radio/mining/imp = new(src)
+ var/obj/item/implant/radio/mining/imp = new
imp.implant(src)
access_card = new /obj/item/card/id(src)
diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm
index f16572c5d0..f7dec3272c 100644
--- a/code/modules/mob/living/death.dm
+++ b/code/modules/mob/living/death.dm
@@ -13,6 +13,10 @@
if(!no_bodyparts)
spread_bodyparts(no_brain, no_organs)
+ for(var/X in implants)
+ var/obj/item/implant/I = X
+ qdel(I)
+
spawn_gibs(no_bodyparts)
qdel(src)
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index 3b045b9eee..5664c2ebca 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -357,8 +357,8 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
return message
/mob/living/proc/radio(message, message_mode, list/spans, language)
- var/obj/item/implant/radio/imp = locate() in src
- if(imp && imp.radio.on)
+ var/obj/item/implant/radio/imp = locate() in implants
+ if(imp?.radio.on)
if(message_mode == MODE_HEADSET)
imp.radio.talk_into(src, message, , spans, language)
return ITALICS | REDUCE_RANGE
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm
index 23ac527b2e..d28b98263c 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm
@@ -49,7 +49,7 @@
. = ..()
GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, internal_storage)
hidden_uplink.telecrystals = 30
- var/obj/item/implant/weapons_auth/W = new/obj/item/implant/weapons_auth(src)
+ var/obj/item/implant/weapons_auth/W = new
W.implant(src)
/mob/living/simple_animal/drone/snowflake
diff --git a/code/modules/mob/living/simple_animal/hostile/wizard.dm b/code/modules/mob/living/simple_animal/hostile/wizard.dm
index a946cbf45b..f047a7aed1 100644
--- a/code/modules/mob/living/simple_animal/hostile/wizard.dm
+++ b/code/modules/mob/living/simple_animal/hostile/wizard.dm
@@ -46,7 +46,8 @@
fireball.human_req = 0
fireball.player_lock = 0
AddSpell(fireball)
- implants += new /obj/item/implant/exile(src)
+ var/obj/item/implant/exile/I = new
+ I.implant(src, null, TRUE)
mm = new /obj/effect/proc_holder/spell/targeted/projectile/magic_missile
mm.clothes_req = 0
diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm
index 5e872ac299..b062893954 100644
--- a/code/modules/research/xenobiology/xenobiology.dm
+++ b/code/modules/research/xenobiology/xenobiology.dm
@@ -705,7 +705,7 @@
desc = "A miraculous chemical mix that grants human like intelligence to living beings. It has been modified with Syndicate technology to also grant an internal radio implant to the target and authenticate with identification systems."
/obj/item/slimepotion/slime/sentience/nuclear/after_success(mob/living/user, mob/living/simple_animal/SM)
- var/obj/item/implant/radio/syndicate/imp = new(src)
+ var/obj/item/implant/radio/syndicate/imp = new
imp.implant(SM, user)
SM.access_card = new /obj/item/card/id/syndicate(SM)
@@ -969,7 +969,7 @@
to_chat(user, "You feed the potion to [M].")
to_chat(M, "Your mind tingles as you are fed the potion. You can hear radio waves now!")
- var/obj/item/implant/radio/slime/imp = new(src)
+ var/obj/item/implant/radio/slime/imp = new
imp.implant(M, user)
qdel(src)
diff --git a/tgstation.dme b/tgstation.dme
index 1f8b1a964d..1e632e4fa6 100755
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -648,7 +648,6 @@
#include "code\game\machinery\computer\medical.dm"
#include "code\game\machinery\computer\Operating.dm"
#include "code\game\machinery\computer\pod.dm"
-#include "code\game\machinery\computer\prisoner.dm"
#include "code\game\machinery\computer\robot.dm"
#include "code\game\machinery\computer\security.dm"
#include "code\game\machinery\computer\station_alert.dm"
@@ -915,15 +914,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"