diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm
index 62fbf027507e..9e999e037893 100644
--- a/code/datums/components/uplink.dm
+++ b/code/datums/components/uplink.dm
@@ -12,6 +12,8 @@ GLOBAL_LIST_EMPTY(uplinks)
/datum/component/uplink
dupe_mode = COMPONENT_DUPE_UNIQUE
var/name = "syndicate uplink"
+ var/js_ui = "Uplink"
+ var/obj/item/stack/currency = /obj/item/stack/telecrystal
var/active = FALSE
var/lockable = TRUE
var/locked = TRUE
@@ -53,7 +55,7 @@ GLOBAL_LIST_EMPTY(uplinks)
RegisterSignal(parent, COMSIG_PEN_ROTATED, .proc/pen_rotation)
GLOB.uplinks += src
- uplink_items = get_uplink_items(_gamemode, TRUE, allow_restricted)
+ uplink_items = get_uplink_items(_gamemode, TRUE, allow_restricted, js_ui)
if(_owner)
owner = _owner
@@ -87,7 +89,7 @@ GLOBAL_LIST_EMPTY(uplinks)
purchase_log = null
return ..()
-/datum/component/uplink/proc/LoadTC(mob/user, obj/item/stack/telecrystal/TC, silent = FALSE)
+/datum/component/uplink/proc/LoadTC(mob/user, obj/item/stack/TC, silent = FALSE)
if(!silent)
to_chat(user, span_notice("You slot [TC] into [parent] and charge its internal uplink."))
var/amt = TC.amount
@@ -96,12 +98,12 @@ GLOBAL_LIST_EMPTY(uplinks)
/datum/component/uplink/proc/set_gamemode(_gamemode)
gamemode = _gamemode
- uplink_items = get_uplink_items(gamemode, TRUE, allow_restricted)
+ uplink_items = get_uplink_items(gamemode, TRUE, allow_restricted, js_ui)
/datum/component/uplink/proc/OnAttackBy(datum/source, obj/item/I, mob/user)
if(!active)
return //no hitting everyone/everything just to try to slot tcs in!
- if(istype(I, /obj/item/stack/telecrystal))
+ if(istype(I, currency))
LoadTC(user, I)
return
var/datum/component/refundable/R = I.GetComponent(/datum/component/refundable)
@@ -129,7 +131,7 @@ GLOBAL_LIST_EMPTY(uplinks)
active = TRUE
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
- ui = new(user, src, "Uplink", name)
+ ui = new(user, src, js_ui, name)
// This UI is only ever opened by one person,
// and never is updated outside of user input.
ui.set_autoupdate(FALSE)
@@ -331,3 +333,10 @@ GLOBAL_LIST_EMPTY(uplinks)
return
explosion(T,1,2,3)
qdel(parent) //Alternatively could brick the uplink.
+
+
+/// NT Uplink
+/datum/component/uplink/nanotrasen
+ name = "nanotrasen uplink"
+ js_ui = "NTUplink"
+ currency = /obj/item/stack/ore/bluespace_crystal/refined/nt
diff --git a/code/datums/ert.dm b/code/datums/ert.dm
index 80128ba03e36..ea3464b78409 100644
--- a/code/datums/ert.dm
+++ b/code/datums/ert.dm
@@ -12,6 +12,9 @@
var/teamsize = 5
var/polldesc
+ // this can be safely set as default because it doesnt do anything unless specifically making uplinked ERT
+ var/obj/item/uplinktype = /obj/item/ntuplink/official
+
/datum/ert/New()
if (!polldesc)
polldesc = "a Code [code] Nanotrasen Emergency Response Team"
@@ -109,6 +112,12 @@
rename_team = "CentCom Grand Admirals"
polldesc = "a CentCom Grand Admiral"
+/datum/ert/uplinked
+ leader_role = /datum/antagonist/ert/common/leader
+ roles = list(/datum/antagonist/ert/common)
+ rename_team = "Uplinked Emergency Response Team"
+ polldesc = "an Uplink-Equipped ERT"
+
/datum/ert/inquisition
roles = list(/datum/antagonist/ert/chaplain/inquisitor, /datum/antagonist/ert/security/inquisitor, /datum/antagonist/ert/medic/inquisitor)
leader_role = /datum/antagonist/ert/commander/inquisitor
diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm
index 71ff1e7f1a87..109659ceb940 100644
--- a/code/game/objects/items/devices/radio/headset.dm
+++ b/code/game/objects/items/devices/radio/headset.dm
@@ -260,6 +260,16 @@ GLOBAL_LIST_INIT(channel_tokens, list(
/obj/item/radio/headset/headset_cent/alt
keyslot = new /obj/item/encryptionkey/heads/captain
+/obj/item/radio/headset/headset_cent/bowman // No captain key
+ name = "\improper CentCom bowman headset"
+ desc = "A headset especially for emergency response personnel. Protects ears from flashbangs."
+ icon_state = "cent_headset_alt"
+ item_state = "cent_headset_alt"
+
+/obj/item/radio/headset/headset_cent/bowman/ComponentInitialize()
+ . = ..()
+ AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS))
+
/obj/item/radio/headset/headset_cent/commander
name = "\improper CentCom bowman headset"
desc = "A headset especially for emergency response personnel. Protects ears from flashbangs."
diff --git a/code/game/objects/items/stacks/bscrystal.dm b/code/game/objects/items/stacks/bscrystal.dm
index bf942bb8e7e7..264b82e18de0 100644
--- a/code/game/objects/items/stacks/bscrystal.dm
+++ b/code/game/objects/items/stacks/bscrystal.dm
@@ -18,6 +18,45 @@
points = 0
refined_type = null
+/obj/item/stack/ore/bluespace_crystal/refined/nt // NT's telecrystal
+ name = "warpcrystal"
+ desc = "The culmination of Nanotrasen's sacrifices in pursuing technological advancement. Highly top-secret."
+ materials = list(/datum/material/bluespace=MINERAL_MATERIAL_AMOUNT*2.5) // more potent
+
+/obj/item/stack/ore/bluespace_crystal/refined/nt/five
+ amount = 5
+
+/obj/item/stack/ore/bluespace_crystal/refined/nt/twenty
+ amount = 20
+
+/obj/item/stack/ore/bluespace_crystal/refined/nt/attack_self(mob/user)
+ if(!isliving(user))
+ return
+
+ var/mob/living/L = user
+
+ var/turf/destination = get_teleport_loc(loc, L, rand(3,6)) // Gets 3-6 tiles in the user's direction
+
+ if(!istype(destination))
+ return
+
+ L.visible_message(span_warning("[L] crushes [src]!"), span_danger("You crush [src]!"))
+ new /obj/effect/particle_effect/sparks(loc)
+ playsound(loc, "sparks", 50, 1)
+
+ if(!do_teleport(L, destination, asoundin = 'sound/effects/phasein.ogg', channel = TELEPORT_CHANNEL_BLUESPACE))
+ L.visible_message(span_warning("[src] refuses to be crushed by [L]! There must be something interfering!"), span_danger("[src] suddenly hardens in your hand! There must be something interfering!"))
+ return
+
+ // Throws you one additional tile, giving it that cool "exit portal" effect and also throwing people very far if they are in space
+ L.throw_at(get_edge_target_turf(L, L.dir), 1, 3, spin = FALSE, diagonals_first = TRUE)
+ if(iscarbon(L))
+ var/mob/living/carbon/C = L
+ // Half as debilitating than a bluespace crystal, as this is a precious resource you're using
+ C.adjust_disgust(15)
+
+ use(1)
+
/obj/item/stack/ore/bluespace_crystal/Initialize()
. = ..()
pixel_x = rand(-5, 5)
diff --git a/code/game/objects/items/storage/briefcase.dm b/code/game/objects/items/storage/briefcase.dm
index 9d06eb809830..a01978218bc2 100644
--- a/code/game/objects/items/storage/briefcase.dm
+++ b/code/game/objects/items/storage/briefcase.dm
@@ -53,4 +53,12 @@
/obj/item/storage/briefcase/syndie_mantis/PopulateContents()
..()
new /obj/item/autosurgeon/organ/syndicate/syndie_mantis(src)
- new /obj/item/autosurgeon/organ/syndicate/syndie_mantis/l(src)
\ No newline at end of file
+ new /obj/item/autosurgeon/organ/syndicate/syndie_mantis/l(src)
+
+/obj/item/storage/briefcase/nt_mantis
+ desc = "A sleek briefcase. It has the letters H.E.P.H.A.E.S.T.U.S. on it"
+
+/obj/item/storage/briefcase/nt_mantis/PopulateContents()
+ ..()
+ new /obj/item/autosurgeon/nt_mantis(src)
+ new /obj/item/autosurgeon/nt_mantis/l(src)
diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm
index 019d6e33f43f..cfc1ce6ef437 100644
--- a/code/game/objects/items/storage/uplink_kits.dm
+++ b/code/game/objects/items/storage/uplink_kits.dm
@@ -634,3 +634,11 @@
/obj/item/storage/box/syndie_kit/bee_grenades/PopulateContents()
for(var/i in 1 to 3)
new /obj/item/grenade/spawnergrenade/buzzkill(src)
+
+/obj/item/storage/box/official_posters
+ name = "poster box"
+ desc = "A box filled with posters."
+
+/obj/item/storage/box/official_posters/PopulateContents()
+ for(var/i in 1 to 7)
+ new /obj/item/poster/random_official(src)
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index 781db60b883d..ed38f586e464 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -175,6 +175,14 @@
else
message_admins("[key_name_admin(usr)] tried to create a CentCom response team. Unfortunately, there were not enough candidates available.")
log_admin("[key_name(usr)] failed to create a CentCom response team.")
+ if("centcom_custom")
+ message_admins("[key_name(usr)] is creating a Uplinked CentCom response team...")
+ if(src.makeUplinkEmergencyResponseTeam())
+ message_admins("[key_name(usr)] created a Uplinked CentCom response team.")
+ log_admin("[key_name(usr)] created a Uplinked CentCom response team.")
+ else
+ message_admins("[key_name_admin(usr)] tried to create a Uplinked CentCom response team. Unfortunately, there were not enough candidates available.")
+ log_admin("[key_name(usr)] failed to create a Uplinked CentCom response team.")
if("abductors")
message_admins("[key_name(usr)] is creating an abductor team...")
if(src.makeAbductorTeam())
diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm
index 331038f8d858..10dd710df567 100644
--- a/code/modules/admin/verbs/one_click_antag.dm
+++ b/code/modules/admin/verbs/one_click_antag.dm
@@ -20,6 +20,7 @@
Make Blob
Make Wizard (Requires Ghosts)
Make Nuke Team (Requires Ghosts)
+ Make Uplink CentCom Response Team (Requires Ghosts)
Make CentCom Response Team (Requires Ghosts)
Make Abductor Team (Requires Ghosts)
Make Revenant (Requires Ghost)
@@ -491,6 +492,120 @@
return
+// Uplink-equipped Centcom Response Team
+/datum/admins/proc/makeUplinkEmergencyResponseTeam(var/datum/ert/ertemplate = null)
+ if (ertemplate)
+ ertemplate = new ertemplate
+ else
+ ertemplate = new /datum/ert/uplinked
+
+ var/list/settings = list(
+ "preview_callback" = CALLBACK(src, .proc/makeERTPreviewIcon),
+ "mainsettings" = list(
+ "template" = list("desc" = "Template", "type" = "datum", "path" = "/datum/ert/uplinked", "value" = "/datum/ert/uplinked"),
+ "uplink" = list("desc" = "Uplink Type", "type" = "datum", "path" = "/obj/item/ntuplink", "subtypesonly" = TRUE, "value" = ertemplate.uplinktype),
+ "teamsize" = list("desc" = "Team Size", "type" = "number", "value" = ertemplate.teamsize),
+ "mission" = list("desc" = "Mission", "type" = "string", "value" = ertemplate.mission),
+ "polldesc" = list("desc" = "Ghost poll description", "type" = "string", "value" = ertemplate.polldesc),
+ "enforce_human" = list("desc" = "Enforce human authority", "type" = "boolean", "value" = "[(CONFIG_GET(flag/enforce_human_authority) ? "Yes" : "No")]"),
+ "open_armory" = list("desc" = "Open armory doors", "type" = "boolean", "value" = "[(ertemplate.opendoors ? "Yes" : "No")]"),
+ "open_mechbay" = list("desc" = "Open Mech Bay", "type" = "boolean", "value" = "[(ertemplate.openmech ? "Yes" : "No")]"),
+ )
+ )
+
+ var/list/prefreturn = presentpreflikepicker(usr,"Customize ERT", "Customize ERT", Button1="Ok", width = 600, StealFocus = 1,Timeout = 0, settings=settings)
+
+ if (isnull(prefreturn))
+ return FALSE
+
+ if (prefreturn["button"] == 1)
+ var/list/prefs = settings["mainsettings"]
+
+ ertemplate.uplinktype = prefs["uplink"]["value"]
+ ertemplate.teamsize = prefs["teamsize"]["value"]
+ ertemplate.mission = prefs["mission"]["value"]
+ ertemplate.polldesc = prefs["polldesc"]["value"]
+ ertemplate.enforce_human = prefs["enforce_human"]["value"] == "Yes" ? TRUE : FALSE
+ ertemplate.opendoors = prefs["open_armory"]["value"] == "Yes" ? TRUE : FALSE
+ ertemplate.openmech = prefs["open_mechbay"]["value"] == "Yes" ? TRUE : FALSE
+
+ var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered for [ertemplate.polldesc] ?", "deathsquad", null)
+ var/teamSpawned = FALSE
+
+ if(candidates.len > 0)
+ //Pick the (un)lucky players
+ var/numagents = min(ertemplate.teamsize,candidates.len)
+
+ //Create team
+ var/datum/team/ert/ert_team = new ertemplate.team
+ if(ertemplate.rename_team)
+ ert_team.name = ertemplate.rename_team
+
+ //Asign team objective
+ var/datum/objective/missionobj = new
+ missionobj.team = ert_team
+ missionobj.explanation_text = ertemplate.mission
+ missionobj.completed = TRUE
+ ert_team.objectives += missionobj
+ ert_team.mission = missionobj
+
+ var/list/spawnpoints = GLOB.emergencyresponseteamspawn
+ while(numagents && candidates.len)
+ if (numagents > spawnpoints.len)
+ numagents--
+ continue // This guy's unlucky, not enough spawn points, we skip him.
+ var/spawnloc = spawnpoints[numagents]
+ var/mob/dead/observer/chosen_candidate = pick(candidates)
+ candidates -= chosen_candidate
+ if(!chosen_candidate.key)
+ continue
+
+ //Spawn the body
+ var/mob/living/carbon/human/ERTOperative = new ertemplate.mobtype(spawnloc)
+ chosen_candidate.client.prefs.copy_to(ERTOperative)
+ ERTOperative.key = chosen_candidate.key
+
+ if(ertemplate.enforce_human || !(ERTOperative.dna.species.changesource_flags & ERT_SPAWN)) // Don't want any exploding plasmemes
+ ERTOperative.set_species(/datum/species/human)
+
+ //Give antag datum
+ var/datum/antagonist/ert/ert_antag
+
+ if(numagents == 1)
+ ert_antag = new ertemplate.leader_role
+ else
+ ert_antag = ertemplate.roles[WRAP(numagents,1,length(ertemplate.roles) + 1)]
+ ert_antag = new ert_antag
+
+ ERTOperative.mind.add_antag_datum(ert_antag,ert_team)
+ ERTOperative.mind.assigned_role = ert_antag.name
+
+ // Equip uplink
+ var/obj/item/upl = new ertemplate.uplinktype
+ if(istype(upl))
+ ERTOperative.equip_to_slot_or_del(upl, SLOT_IN_BACKPACK)
+
+ //Logging and cleanup
+ //log_game("[key_name(ERTOperative)] has been selected as an [ert_antag.name]") | yogs - redundant
+ numagents--
+ teamSpawned++
+
+ if (teamSpawned)
+ message_admins("[ertemplate.polldesc] has spawned with the mission: [ertemplate.mission]")
+
+ //Open the Armory doors
+ if(ertemplate.opendoors)
+ for(var/obj/machinery/door/poddoor/ert/door in GLOB.airlocks)
+ INVOKE_ASYNC(door, /obj/machinery/door/poddoor.proc/open)
+
+ //Open the Mech Bay
+ if(ertemplate.openmech)
+ for(var/obj/machinery/door/poddoor/deathsquad/door in GLOB.airlocks)
+ INVOKE_ASYNC(door, /obj/machinery/door/poddoor.proc/open)
+ return TRUE
+
+ return FALSE
+
//Abductors
/datum/admins/proc/makeAbductorTeam()
new /datum/round_event/ghost_role/abductor
diff --git a/code/modules/antagonists/ert/ert.dm b/code/modules/antagonists/ert/ert.dm
index 5688591c3fd7..f3420e67fe50 100644
--- a/code/modules/antagonists/ert/ert.dm
+++ b/code/modules/antagonists/ert/ert.dm
@@ -64,6 +64,14 @@
/datum/antagonist/ert/medic/red
outfit = /datum/outfit/ert/medic/alert
+/datum/antagonist/ert/common
+ outfit = /datum/outfit/ert
+
+/datum/antagonist/ert/common/leader
+ name = "Emergency Response Commander"
+ role = "Commander"
+ outfit = /datum/outfit/ert/commonleader
+
/datum/antagonist/ert/commander
role = "Commander"
outfit = /datum/outfit/ert/commander
diff --git a/code/modules/clothing/outfits/ert.dm b/code/modules/clothing/outfits/ert.dm
index d39cbc6f973a..afc6111fead4 100644
--- a/code/modules/clothing/outfits/ert.dm
+++ b/code/modules/clothing/outfits/ert.dm
@@ -1,12 +1,27 @@
/datum/outfit/ert
name = "ERT Common"
+ id = /obj/item/card/id/ert
+ back = /obj/item/storage/backpack
uniform = /obj/item/clothing/under/rank/centcom_officer
shoes = /obj/item/clothing/shoes/combat/swat
gloves = /obj/item/clothing/gloves/combat
ears = /obj/item/radio/headset/headset_cent/alt
implants = list(/obj/item/implant/mindshield)
+ backpack_contents = list(
+ /obj/item/clothing/mask/gas/sechailer/swat=1,
+ /obj/item/tank/internals/oxygen/tactical=1,
+ /obj/item/tank/internals/emergency_oxygen/double=1,
+ )
+/datum/outfit/ert/commonleader
+ head = /obj/item/clothing/head/beret/sec
+ backpack_contents = list(
+ /obj/item/clothing/mask/gas/sechailer/swat=1,
+ /obj/item/tank/internals/oxygen/tactical=1,
+ /obj/item/tank/internals/emergency_oxygen/double=1,
+ /obj/item/stack/ore/bluespace_crystal/refined/nt/five=1
+ )
/datum/outfit/ert/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
if(visualsOnly)
diff --git a/code/modules/projectiles/guns/ballistic/automatic.dm b/code/modules/projectiles/guns/ballistic/automatic.dm
index 633418ed4441..dc5b671ba90d 100644
--- a/code/modules/projectiles/guns/ballistic/automatic.dm
+++ b/code/modules/projectiles/guns/ballistic/automatic.dm
@@ -197,6 +197,7 @@
fire_sound = 'sound/weapons/gunshot_smg.ogg'
can_suppress = FALSE
burst_size = 4
+ spread = 30
fire_delay = 1
bolt_type = BOLT_TYPE_OPEN
diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm
index ea1fc90b7c55..3c541123e764 100644
--- a/code/modules/surgery/organs/augments_arms.dm
+++ b/code/modules/surgery/organs/augments_arms.dm
@@ -387,6 +387,14 @@
zone = BODY_ZONE_L_ARM
syndicate_implant = TRUE
+/obj/item/organ/cyberimp/arm/nt_mantis
+ name = "H.E.P.H.A.E.S.T.U.S. mantis blade implants"
+ desc = "Retractable arm-blade implants to get you out of a pinch. Wielding two will let you double-attack."
+ contents = newlist(/obj/item/mantis/blade/NT)
+
+/obj/item/organ/cyberimp/arm/nt_mantis/l
+ zone = BODY_ZONE_L_ARM
+
/obj/item/organ/cyberimp/arm/power_cord
name = "power cord implant"
desc = "An internal power cord hooked up to a battery. Useful if you run on volts."
diff --git a/code/modules/surgery/organs/autosurgeon.dm b/code/modules/surgery/organs/autosurgeon.dm
index d705734cfaf4..5dfeab85637a 100644
--- a/code/modules/surgery/organs/autosurgeon.dm
+++ b/code/modules/surgery/organs/autosurgeon.dm
@@ -107,6 +107,14 @@
uses = 1
starting_organ = /obj/item/organ/cyberimp/arm/syndie_mantis/l
+/obj/item/autosurgeon/nt_mantis
+ uses = 1
+ starting_organ = /obj/item/organ/cyberimp/arm/nt_mantis
+
+/obj/item/autosurgeon/nt_mantis/l
+ uses = 1
+ starting_organ = /obj/item/organ/cyberimp/arm/nt_mantis/l
+
/obj/item/autosurgeon/plasmavessel //Yogs Start: Just an autosurgeon with a plasma vessel in it, used in /obj/item/storage/box/syndie_kit/xeno_organ_kit
uses = 3
starting_organ = /obj/item/organ/alien/plasmavessel //Yogs End
diff --git a/code/modules/uplink/uplink_devices.dm b/code/modules/uplink/uplink_devices.dm
index add2cf4030f9..7888ad930e9c 100644
--- a/code/modules/uplink/uplink_devices.dm
+++ b/code/modules/uplink/uplink_devices.dm
@@ -74,3 +74,50 @@
/obj/item/pen/uplink/Initialize(mapload, owner, tc_amount = 20)
. = ..()
AddComponent(/datum/component/uplink, owner, TRUE, FALSE, null, tc_amount)
+
+// NT Uplink
+/obj/item/ntuplink
+ name = "\improper nanotrasen uplink"
+ icon = 'icons/obj/radio.dmi'
+ icon_state = "radio"
+ item_state = "walkietalkie"
+ desc = "A specialized uplink for authorized Nanotrasen use only."
+ lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
+ dog_fashion = /datum/dog_fashion/back
+
+ flags_1 = CONDUCT_1
+ slot_flags = ITEM_SLOT_BELT
+ throw_speed = 3
+ throw_range = 7
+ w_class = WEIGHT_CLASS_SMALL
+
+ var/wc_start = 20 // Starting warpcrystal amount
+
+/obj/item/ntuplink/Initialize(mapload, owner)
+ . = ..()
+ AddComponent(/datum/component/uplink/nanotrasen, owner, FALSE, TRUE, null, wc_start)
+
+/obj/item/ntuplink/official
+ name = "centcom official uplink"
+ wc_start = 5
+
+/obj/item/ntuplink/amber
+ name = "amber ERT uplink"
+ wc_start = 10
+
+/obj/item/ntuplink/blue
+ name = "blue ERT uplink"
+ wc_start = 20
+
+/obj/item/ntuplink/red
+ name = "red ERT uplink"
+ wc_start = 30
+
+/obj/item/ntuplink/death
+ name = "deathsquad uplink"
+ wc_start = 350
+
+/obj/item/ntuplink/debug
+ name = "debug nanotrasen uplink"
+ wc_start = 9000
diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm
index c7d43af1f5ef..6beadb83315b 100644
--- a/code/modules/uplink/uplink_items.dm
+++ b/code/modules/uplink/uplink_items.dm
@@ -1,6 +1,6 @@
GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
-/proc/get_uplink_items(var/datum/game_mode/gamemode = null, allow_sales = TRUE, allow_restricted = TRUE)
+/proc/get_uplink_items(var/datum/game_mode/gamemode = null, allow_sales = TRUE, allow_restricted = TRUE, uplink_type = "Uplink")
var/list/filtered_uplink_items = list()
var/list/sale_items = list()
@@ -8,6 +8,8 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
var/datum/uplink_item/I = new path
if(!I.item)
continue
+ if(I.include_uplinks.len && !(uplink_type in I.include_uplinks))
+ continue
if(I.include_modes.len)
if(!gamemode && SSticker.mode && !(SSticker.mode.type in I.include_modes))
continue
@@ -94,6 +96,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
var/surplus = 100 // Chance of being included in the surplus crate.
var/cant_discount = FALSE
var/limited_stock = -1 //Setting this above zero limits how many times this item can be bought by the same traitor in a round, -1 is unlimited
+ var/list/include_uplinks = list("Uplink") // Uplink types this is in
var/list/include_modes = list() // Game modes to allow this item in.
var/list/exclude_modes = list() // Game modes to disallow this item from.
var/list/restricted_roles = list() //If this uplink item is only available to certain roles. Roles are dependent on the frequency chip or stored ID.
@@ -2297,3 +2300,469 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
item = /obj/item/stamp/syndiround
cost = 1
illegal_tech = FALSE
+
+/// NT Uplink items
+/datum/uplink_item/nt
+ category = "Warpcrystals"
+ surplus = 0 // Chance of being included in the surplus crate.
+ include_uplinks = list("NTUplink")
+ illegal_tech = FALSE
+
+/datum/uplink_item/nt/telecrystal
+ name = "1 Raw Warpcrystal"
+ desc = "A warpcrystal in its rawest and purest form; can be utilized on active uplinks to increase their warpcrystal count."
+ item = /obj/item/stack/ore/bluespace_crystal/refined/nt
+ cost = 1
+ purchase_log_vis = FALSE
+
+/datum/uplink_item/nt/telecrystal/five
+ name = "5 Raw Warpcrystals"
+ desc = "Five warpcrystals in their rawest and purest form; can be utilized on active uplinks to increase their warpcrystal count."
+ item = /obj/item/stack/ore/bluespace_crystal/refined/nt/five
+ cost = 5
+
+/datum/uplink_item/nt/telecrystal/twenty
+ name = "20 Raw Warpcrystals"
+ desc = "Twenty warpcrystals in their rawest and purest form; can be utilized on active uplinks to increase their warpcrystal count."
+ item = /obj/item/stack/ore/bluespace_crystal/refined/nt/twenty
+ cost = 20
+
+/datum/uplink_item/nt/energy_weps
+ category = "Energy Weapons"
+
+/datum/uplink_item/nt/energy_weps/egun
+ name = "Energy Gun"
+ desc = "A standard energy gun with disable and laser modes equipped."
+ item = /obj/item/gun/energy/e_gun
+ cost = 3
+ limited_stock = 3
+
+/datum/uplink_item/nt/energy_weps/tac_egun
+ name = "Tactical Energy Gun"
+ desc = "A military-grade augmented energy gun, fitted with a tasing mode."
+ item = /obj/item/gun/energy/e_gun/stun
+ cost = 8
+ limited_stock = 2
+
+/datum/uplink_item/nt/energy_weps/mini_egun
+ name = "Miniature Energy Gun"
+ desc = "A smaller model of the standard energy gun that holds much less charge."
+ item = /obj/item/gun/energy/e_gun/mini
+ cost = 1
+ limited_stock = 1
+
+/datum/uplink_item/nt/energy_weps/laserrifle
+ name = "Laser Rifle"
+ desc = "An abnormality in energy weaponry. Chambers a laser magazine which can be recharged externally."
+ item = /obj/item/gun/ballistic/automatic/laser
+ cost = 8
+ limited_stock = 1
+
+/datum/uplink_item/nt/energy_weps/m1911
+ name = "Spur"
+ desc = "A legendary slowly self-charging pistol with massive recoil that deals more damage the more charge it has."
+ item = /obj/item/gun/energy/polarstar/spur
+ cost = 10
+
+/datum/uplink_item/nt/energy_weps/pulsecarbine
+ name = "Pulse Carbine"
+ desc = "A severely lethal energy carbine that fires additionaly fires pulse rounds. Must be recharged instead of reloaded."
+ item = /obj/item/gun/energy/pulse/carbine
+ cost = 45
+ cant_discount = TRUE
+
+/datum/uplink_item/nt/energy_weps/pulsepistol
+ name = "Pulse Pistol"
+ desc = "A severely lethal but compact version of the Pulse Carbine design. Holds significantly less charge. \
+ Must be recharged instead of reloaded."
+ item = /obj/item/gun/energy/pulse/pistol
+ cost = 35
+ cant_discount = TRUE
+
+/datum/uplink_item/nt/energy_weps/pulsedestroyer
+ name = "Pulse Destroyer"
+ desc = "LOG-ENTRY ERROR. DEATH. DEATH. DEATH. KILL. DESTROY. NONE LEFT ALIVE."
+ item = /obj/item/gun/energy/pulse/destroyer
+ cost = 100
+ cant_discount = TRUE
+
+/datum/uplink_item/nt/ball_weps
+ category = "Ballistic Weapons"
+
+/datum/uplink_item/nt/ball_weps/boarder
+ name = "NT-ARG 'Boarder'"
+ desc = "A heavy-damage 3-round burst assault rifle. Chambered in 5.56mm."
+ item = /obj/item/gun/ballistic/automatic/ar
+ cost = 18
+ limited_stock = 1
+
+/datum/uplink_item/nt/ball_weps/saber
+ name = "NT-SABR 'Saber' SMG"
+ desc = "A low-damage 3-round burst SMG. Chambered in 9mm."
+ item = /obj/item/gun/ballistic/automatic/proto/unrestricted
+ cost = 7
+
+/datum/uplink_item/nt/ball_weps/wtrifle
+ name = "WT-550 Automatic Rifle"
+ desc = "A classic 2-round burst rifle with a number of ammo options. Chambered in 4.6x30mm."
+ item = /obj/item/gun/ballistic/automatic/wt550
+ cost = 5
+
+/datum/uplink_item/nt/ball_weps/m1911
+ name = "M1911"
+ desc = "A classic .45 sidearm with a small magazine capacity."
+ item = /obj/item/gun/ballistic/automatic/pistol/m1911
+ cost = 3
+
+/datum/uplink_item/nt/ball_weps/tommygun
+ name = "Thompson SMG"
+ desc = "An archaic but incredibly effective high-capacity 4-round burst SMG. Wildly inaccurate. Can't fit in backpacks."
+ item = /obj/item/gun/ballistic/automatic/tommygun
+ cost = 9
+ limited_stock = 2 // SAY HELLO TO MY LITTLE FRIEND
+
+/datum/uplink_item/nt/ammo
+ category = "Ammunition"
+
+/datum/uplink_item/nt/ammo/recharger
+ name = "Weapon Recharger"
+ desc = "Standard issue energy weapon recharger. Must be anchored in an APC-powered area."
+ item = /obj/machinery/recharger
+ cost = 2
+
+/datum/uplink_item/nt/ammo/powerpack
+ name = "Power Pack"
+ desc = "An additional 20-round laser magazine; suitable for use with the laser rifle."
+ item = /obj/item/ammo_box/magazine/recharge
+ cost = 5
+
+/datum/uplink_item/nt/ammo/carbine
+ name = "5.56mm Toploader Magazine"
+ desc = "An additional 30-round 5.56mm magazine; suitable for use with the NT-ARG."
+ item = /obj/item/ammo_box/magazine/m556
+ cost = 4
+
+/datum/uplink_item/nt/ammo/tommyammo
+ name = ".45 Drum Magazine"
+ desc = "An additional 50-round .45 drum magazine; suitable for use with the Thompson SMG."
+ item = /obj/item/ammo_box/magazine/tommygunm45
+ cost = 4
+
+/datum/uplink_item/nt/ammo/m45ammo
+ name = ".45 Handgun Magazine"
+ desc = "An additional 8-round .45 magazine; suitable for use with the M1911."
+ item = /obj/item/ammo_box/magazine/m45
+ cost = 1
+
+/datum/uplink_item/nt/ammo/saberammo
+ name = "9mm Magazine"
+ desc = "An additional 21-round 9mm magazine; suitable for use with the Saber SMG."
+ item = /obj/item/ammo_box/magazine/smgm9mm
+ cost = 1
+
+/datum/uplink_item/nt/ammo/saberammoap
+ name = "9mm AP Magazine"
+ desc = "An additional 21-round 9mm magazine with armor piercing rounds; suitable for use with the Saber SMG."
+ item = /obj/item/ammo_box/magazine/smgm9mm/ap
+ cost = 2
+
+/datum/uplink_item/nt/ammo/saberammoin
+ name = "9mm Incendiary Magazine"
+ desc = "An additional 21-round 9mm magazine loaded loaded with incendiary rounds; suitable for use with the Saber SMG."
+ item = /obj/item/ammo_box/magazine/smgm9mm/fire
+ cost = 1
+
+/datum/uplink_item/nt/ammo/wt
+ name = "4.6x30mm Magazine"
+ desc = "An additional 22-round 4.6x30mm magazine; suitable for use with the WT-550."
+ item = /obj/item/ammo_box/magazine/wt550m9
+ cost = 1
+
+/datum/uplink_item/nt/ammo/wtap
+ name = "4.6x30mm AP Magazine"
+ desc = "An additional 22-round 4.6x30mm magazine loaded with armor piercing rounds; suitable for use with the WT-550."
+ item = /obj/item/ammo_box/magazine/wt550m9/wtap
+ cost = 2
+
+/datum/uplink_item/nt/ammo/wtic
+ name = "4.6x30mm Incendiary Magazine"
+ desc = "An additional 22-round 4.6x30mm magazine loaded with incendiary rounds; suitable for use with the WT-550."
+ item = /obj/item/ammo_box/magazine/wt550m9/wtic
+ cost = 2
+
+/datum/uplink_item/nt/ammo/wtr
+ name = "4.6x30mm Rubber Shot Magazine"
+ desc = "An additional 22-round 4.6x30mm magazine loaded with less lethal rounds; suitable for use with the WT-550."
+ item = /obj/item/ammo_box/magazine/wt550m9/wtr
+ cost = 1
+
+/datum/uplink_item/nt/cqc
+ category = "Close Quarters Combat"
+
+/datum/uplink_item/nt/cqc/esword
+ name = "Energy Sword"
+ desc = "The energy sword is an edged weapon with a blade of pure energy. The sword is small enough to be \
+ pocketed when inactive."
+ item = /obj/item/melee/transforming/energy/sword/saber
+ cost = 8
+
+/datum/uplink_item/nt/cqc/eshield
+ name = "Energy Shield"
+ desc = "A shield that blocks all energy projectiles but is useless against physical attacks."
+ item = /obj/item/shield/energy
+ cost = 16
+
+/datum/uplink_item/nt/cqc/ntmantisblade
+ name = "H.E.P.H.A.E.S.T.U.S. Mantis Blades"
+ desc = "A pair of retractable arm-blade implants. Activating both will let you double-attack."
+ item = /obj/item/storage/briefcase/nt_mantis
+ cost = 7
+
+/datum/uplink_item/nt/cqc/sblade
+ name = "Switchblade"
+ desc = "A less flashy but surprisingly robust pocket knife."
+ item = /obj/item/switchblade
+ cost = 1
+
+/datum/uplink_item/nt/cqc/cqc
+ name = "CQC Manual"
+ desc = "A manual that teaches a single user tactical Close-Quarters Combat before self-destructing."
+ item = /obj/item/book/granter/martial/cqc
+ cost = 13
+
+/datum/uplink_item/nt/cqc/teleshield
+ name = "Telescopic Shield"
+ desc = "A foldable shield that blocks attacks when active but can break."
+ item = /obj/item/shield/riot/tele
+ cost = 3
+
+/datum/uplink_item/nt/cqc/stunbaton
+ name = "Stun Baton"
+ desc = "A robust charged baton that will swiftly take down most criminals."
+ item = /obj/item/melee/baton/loaded
+ cost = 1
+
+/datum/uplink_item/nt/cqc/telebaton
+ name = "Telescopic Baton"
+ desc = "A foldable baton that doesn't run on charge. Takes more hits to down, but swings faster."
+ item = /obj/item/melee/classic_baton/telescopic
+ cost = 1
+
+/datum/uplink_item/nt/cqc/flash
+ name = "Flash"
+ desc = "A bright flashing device that can disable silicons and blind humans."
+ item = /obj/item/assembly/flash
+ cost = 1
+
+/datum/uplink_item/nt/support
+ category = "Support"
+
+/datum/uplink_item/nt/support/c4
+ name = "Composition C-4"
+ desc = "C-4 is plastic explosive of the common variety Composition C. You can use it to breach walls, disrupt equipment, or connect \
+ an assembly to it in order to alter the way it detonates. It can be attached to almost all objects and has a modifiable timer with a \
+ minimum setting of 10 seconds."
+ item = /obj/item/grenade/plastic/c4
+ cost = 1
+
+/datum/uplink_item/nt/support/medkit
+ name = "Medic Kit"
+ desc = "A station-standard medical kit. Stocked with sutures, regenerative mesh, medical gauze, \
+ a health analyzer, and an epinephrine pen."
+ item = /obj/item/storage/firstaid/regular
+ cost = 1
+
+/datum/uplink_item/nt/support/advmedkit
+ name = "Tactical Combat Medic Kit"
+ desc = "Included is a combat stimulant injector \
+ for rapid healing, a medical night vision HUD for quick identification of injured personnel, \
+ and other supplies helpful for a field medic."
+ item = /obj/item/storage/firstaid/tactical
+ cost = 4
+
+/datum/uplink_item/nt/support/medbeam
+ name = "Medbeam Gun"
+ desc = "A wonder of Nanotrasen engineering, the Medbeam gun, or Medi-Gun enables a medic to keep his fellow \
+ officers in the fight, even while under fire. Don't cross the streams!"
+ item = /obj/item/gun/medbeam
+ cost = 7
+ limited_stock = 1
+
+/datum/uplink_item/nt/support/toolbelt
+ name = "Full Toolbelt"
+ desc = "Comes pre-stocked with every engineering tool you'll ever need."
+ item = /obj/item/storage/belt/utility/full/engi
+ cost = 1
+
+/datum/uplink_item/nt/support/rcd
+ name = "Rapid Construction Device"
+ desc = "Standard RCD that can repair or destroy structures very quickly. Holds up to 160 matter units."
+ item = /obj/item/construction/rcd/loaded
+ cost = 2
+
+/datum/uplink_item/nt/support/combatrcd
+ name = "Industrial RCD"
+ desc = "Heavy combat RCD that holds up to 500 matter units."
+ item = /obj/item/construction/rcd/combat
+ cost = 4
+
+/datum/uplink_item/nt/support/rcdammo
+ name = "Compressed Matter Cartridge"
+ desc = "Highly compressed matter that restores 160 matter units on an RCD."
+ item = /obj/item/rcd_ammo
+ cost = 1
+
+/datum/uplink_item/nt/support/foamnades
+ name = "Box of Smart Metal Foam Grenades"
+ desc = "A box of 7 smart metal foam grenades to patch hull breaches with."
+ item = /obj/item/storage/box/smart_metal_foam
+ cost = 1
+
+/datum/uplink_item/nt/hardsuit
+ category = "Armor & Hardsuits"
+
+/datum/uplink_item/nt/hardsuit/armor
+ name = "Armor Vest"
+ desc = "A standard issue security armor vest."
+ item = /obj/item/clothing/suit/armor/vest
+ cost = 1
+
+/datum/uplink_item/nt/hardsuit/helmet
+ name = "Helmet"
+ desc = "A standard issue security helmet. Can have a seclite attached."
+ item = /obj/item/clothing/head/helmet
+ cost = 1
+
+/datum/uplink_item/nt/hardsuit/bulletvest
+ name = "Bulletproof Armor Vest"
+ desc = "An armor vest that is extremely robust against ballistics but weak to everything else."
+ item = /obj/item/clothing/suit/armor/bulletproof
+ cost = 1
+
+/datum/uplink_item/nt/hardsuit/bullethelmet
+ name = "Bulletproof Helmet"
+ desc = "A helmet that is extremely robust against ballistics but weak to everything else."
+ item = /obj/item/clothing/head/helmet
+ cost = 1
+
+/datum/uplink_item/nt/hardsuit/riotvest
+ name = "Riot Suit"
+ desc = "A bulky suit that protects you againt melee attacks but not much else."
+ item = /obj/item/clothing/suit/armor/riot
+ cost = 1
+
+/datum/uplink_item/nt/hardsuit/riothelmet
+ name = "Riot Helmet"
+ desc = "A helmet that protects you againt melee attacks but not much else."
+ item = /obj/item/clothing/head/helmet/riot
+ cost = 1
+
+/datum/uplink_item/nt/hardsuit/cmd
+ name = "ERT Commander Hardsuit"
+ desc = "Show them who's boss."
+ item = /obj/item/clothing/suit/space/hardsuit/ert
+ cost = 5
+ restricted_roles = list("Emergency Response Commander")
+
+/datum/uplink_item/nt/hardsuit/sec
+ name = "ERT Security Hardsuit"
+ desc = "Make them fear the long arm of law."
+ item = /obj/item/clothing/suit/space/hardsuit/ert/sec
+ cost = 5
+
+/datum/uplink_item/nt/hardsuit/engi
+ name = "ERT Engineering Hardsuit"
+ desc = "HOW DID YOU DELAMINATE THE SM 5 MINUTES IN?"
+ item = /obj/item/clothing/suit/space/hardsuit/ert/engi
+ cost = 5
+
+/datum/uplink_item/nt/hardsuit/med
+ name = "ERT Medical Hardsuit"
+ desc = "Dying is illegal."
+ item = /obj/item/clothing/suit/space/hardsuit/ert/med
+ cost = 5
+
+/datum/uplink_item/nt/hardsuit/ds
+ name = "MK.III SWAT Suit"
+ desc = "A prototype hardsuit. Incredibly robust."
+ item = /obj/item/clothing/suit/space/hardsuit/deathsquad
+ cost = 100
+ cant_discount = TRUE
+
+/datum/uplink_item/nt/hardsuit/dsshield
+ name = "MK.III Shielded SWAT Suit"
+ desc = "A prototype hardsuit with shielding protection. Incredibly robust."
+ item = /obj/item/clothing/suit/space/hardsuit/shielded/swat
+ cost = 150
+ cant_discount = TRUE
+
+/datum/uplink_item/nt/gear
+ category = "Other Gear"
+
+/datum/uplink_item/nt/gear/secbelt
+ name = "Stocked Security Belt"
+ desc = "Standard issue security gear, all in a stylish belt."
+ item = /obj/item/storage/belt/security/full
+ cost = 2
+
+/datum/uplink_item/nt/gear/flashbangs
+ name = "Box of Flashbangs"
+ desc = "A box of 7 flashbangs to make the crew hate you."
+ item = /obj/item/storage/box/flashbangs
+ cost = 2
+
+/datum/uplink_item/nt/gear/handcuffs
+ name = "Box of Handcuffs"
+ desc = "A box of 7 pairs of handcuffs to keep prisoners in line."
+ item = /obj/item/storage/box/handcuffs
+ cost = 1
+
+/datum/uplink_item/nt/gear/bowman
+ name = "Bowman Headset"
+ desc = "A headset specially crafted to protect your ears from any damage, including flashbangs."
+ item = /obj/item/radio/headset/headset_cent/bowman
+ cost = 1
+
+/datum/uplink_item/nt/gear/sechud
+ name = "Security HUDglasses"
+ desc = "A pair of sunglasses fitted with a security HUD."
+ item = /obj/item/clothing/glasses/hud/security/sunglasses
+ cost = 1
+
+/datum/uplink_item/nt/gear/medhud
+ name = "Medical HUDglasses"
+ desc = "A pair of sunglasses fitted with a medical HUD."
+ item = /obj/item/clothing/glasses/hud/health/sunglasses
+ cost = 1
+
+/datum/uplink_item/nt/gear/mesonhud
+ name = "Meson Sunglasses"
+ desc = "A pair of sunglasses fitted with meson technology."
+ item = /obj/item/clothing/glasses/meson/sunglasses
+ cost = 1
+
+/datum/uplink_item/nt/gear/thermalhud
+ name = "Optical Thermal Scanner"
+ desc = "A pair of goggles that provide thermal scanning vision through walls."
+ item = /obj/item/clothing/glasses/thermal
+ cost = 4
+
+/datum/uplink_item/nt/gear/dsmask
+ name = "MK.II SWAT mask"
+ desc = "A strange mask that encrypts your voice so that only others wearing the mask can understand you, \
+ but you won't be able to understand anyone who isn't wearing the mask. \
+ Why would anyone spend this much on a mask?"
+ item = /obj/item/clothing/mask/gas/sechailer/swat/encrypted
+ cost = 10
+
+/datum/uplink_item/nt/gear/ntstamp
+ name = "CentCom Official Stamp"
+ desc = "To let them know you're the real deal."
+ item = /obj/item/stamp/cent
+ cost = 1
+
+/datum/uplink_item/nt/gear/ntposters
+ name = "Box of Posters"
+ desc = "A box of Nanotrasen-approved posters to boost crew morale."
+ item = /obj/item/storage/box/official_posters
+ cost = 1
diff --git a/tgui/packages/tgui/interfaces/NTUplink.js b/tgui/packages/tgui/interfaces/NTUplink.js
new file mode 100644
index 000000000000..e30a083b0562
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/NTUplink.js
@@ -0,0 +1,21 @@
+import { GenericUplink } from './Uplink';
+import { useBackend } from '../backend';
+import { Window } from '../layouts';
+
+export const NTUplink = (props, context) => {
+ const { data } = useBackend(context);
+ const { telecrystals } = data;
+ return (
+
+
+
+
+
+ );
+};