diff --git a/code/datums/uplink/devices_and_tools.dm b/code/datums/uplink/devices_and_tools.dm
index 6db12b849c5..786c09eaf17 100644
--- a/code/datums/uplink/devices_and_tools.dm
+++ b/code/datums/uplink/devices_and_tools.dm
@@ -70,8 +70,10 @@
/datum/uplink_item/item/tools/personal_shield
name = "Personal Shield"
- desc = "A personal shield that, when kept in your hand and activated, will protect its user from five projectile shots."
+ desc = "A personal shield that, when kept in your hand and activated, will protect its user from five projectile shots. \
+ This can only be bought once."
item_cost = 1
+ item_limit = 1
path = /obj/item/device/personal_shield
/datum/uplink_item/item/tools/hacking_tool
diff --git a/code/datums/uplink/implants.dm b/code/datums/uplink/implants.dm
index bfa455f943b..c6612da9f01 100644
--- a/code/datums/uplink/implants.dm
+++ b/code/datums/uplink/implants.dm
@@ -29,7 +29,7 @@
/datum/uplink_item/item/implants/imp_uplink
name = "Uplink Implant"
- path = /obj/item/storage/box/syndie_kit/imp_uplink
+ path = /obj/item/implanter/uplink
/datum/uplink_item/item/implants/imp_uplink/New()
..()
diff --git a/code/datums/uplink/medical.dm b/code/datums/uplink/medical.dm
index 6b9b05d6e37..1cccecee380 100644
--- a/code/datums/uplink/medical.dm
+++ b/code/datums/uplink/medical.dm
@@ -61,6 +61,13 @@
item_cost = 1
path = /obj/item/storage/firstaid/regular
+/datum/uplink_item/item/medical/firstaid
+ name = "Standard First-Aid Kit (Free)"
+ item_cost = 0
+ item_limit = 1
+ path = /obj/item/storage/firstaid/regular
+ desc = "You can claim this first-aid kit only once."
+
/datum/uplink_item/item/medical/advfirstaid
name = "Advanced First-Aid Kit"
item_cost = 1
diff --git a/code/datums/uplink/uplink_items.dm b/code/datums/uplink/uplink_items.dm
index 6d938b927e5..b8b59f9efab 100644
--- a/code/datums/uplink/uplink_items.dm
+++ b/code/datums/uplink/uplink_items.dm
@@ -29,6 +29,7 @@ var/datum/uplink/uplink
var/name
var/desc
var/item_cost = 0
+ var/item_limit = 999 // how many times can this item be bought from a uplink (high limit is not shown in the uplink gui)
var/datum/uplink_category/category // Item category
var/list/datum/antagonist/antag_roles // Antag roles this item is displayed to. If empty, display to all.
var/list/datum/antagonist/antag_job // Antag job this item is displayed to, if empty, display to all.
@@ -53,6 +54,14 @@ var/datum/uplink/uplink
if(!goods)
return
+ var/obj/item/implanter/implanter = goods
+ if(istype(implanter))
+ var/obj/item/implant/uplink/uplink_implant = implanter.imp
+ if(istype(uplink_implant))
+ var/obj/item/device/uplink/hidden/hidden_uplink = uplink_implant.hidden_uplink
+ if(istype(hidden_uplink))
+ hidden_uplink.purchase_log = U.purchase_log
+
purchase_log(U)
U.uses -= cost
U.used_TC += cost
@@ -66,8 +75,14 @@ var/datum/uplink/uplink
if(cost(U.uses) > U.uses)
return 0
+ if(items_left(U) <= 0)
+ return 0
+
return can_view(U)
+/datum/uplink_item/proc/items_left(obj/item/device/uplink/U)
+ return item_limit - U.purchase_log[src]
+
/datum/uplink_item/proc/can_view(obj/item/device/uplink/U)
// Making the assumption that if no uplink was supplied, then we don't care about antag roles
if(!U || (!length(antag_roles) && !antag_job))
diff --git a/code/game/objects/items/devices/uplink.dm b/code/game/objects/items/devices/uplink.dm
index 83f47d32fd3..34a484b86e4 100644
--- a/code/game/objects/items/devices/uplink.dm
+++ b/code/game/objects/items/devices/uplink.dm
@@ -15,7 +15,7 @@ A list of items and costs is stored under the datum of every game mode, alongsid
var/nanoui_menu = 0 // The current menu we are in
var/list/nanoui_data = new // Additional data for NanoUI use
- var/list/purchase_log = new
+ var/list/purchase_log = new // Assoc list of item to times bought; shared/referenced by child uplinks
var/datum/mind/uplink_owner = null
var/used_TC = 0
@@ -159,8 +159,14 @@ A list of items and costs is stored under the datum of every game mode, alongsid
for(var/datum/uplink_item/item in category.items)
if(item.can_view(src))
var/cost = item.cost(uses)
- if(!cost) cost = "???"
- items[++items.len] = list("name" = item.name, "description" = replacetext(item.description(), "\n", "
"), "can_buy" = item.can_buy(src), "cost" = cost, "ref" = "\ref[item]")
+ items[++items.len] = list(
+ "name" = item.name,
+ "description" = replacetext(item.description(), "\n", "
"),
+ "can_buy" = item.can_buy(src),
+ "cost" = cost,
+ "left" = item.items_left(src),
+ "ref" = "\ref[item]"
+ )
nanoui_data["items"] = items
else if(nanoui_menu == 2)
var/permanentData[0]
diff --git a/html/changelogs/DreamySkrell-uplink-item-limit.yml b/html/changelogs/DreamySkrell-uplink-item-limit.yml
new file mode 100644
index 00000000000..5f3ca4eae16
--- /dev/null
+++ b/html/changelogs/DreamySkrell-uplink-item-limit.yml
@@ -0,0 +1,9 @@
+
+author: DreamySkrell
+
+delete-after: True
+
+changes:
+ - rscadd: "Adds a per-uplink item limit mechanism."
+ - rscadd: "One free medkit can be claimed from an uplink."
+ - tweak: "Personal shield can only be bought once from an uplink."
diff --git a/nano/templates/uplink.tmpl b/nano/templates/uplink.tmpl
index 43fd9181a20..9be5d413b92 100644
--- a/nano/templates/uplink.tmpl
+++ b/nano/templates/uplink.tmpl
@@ -42,7 +42,11 @@ Used In File(s): \code\game\objects\items\devices\uplinks.dm
{{for data.items}}