diff --git a/code/__DEFINES/uplink.dm b/code/__DEFINES/uplink.dm
index cdfdf4680f7..929b558dfec 100644
--- a/code/__DEFINES/uplink.dm
+++ b/code/__DEFINES/uplink.dm
@@ -36,7 +36,7 @@
/// Typepath used for uplink items which don't actually produce an item (essentially just a placeholder)
/// Future todo: Make this not necessary / make uplink items support item-less items natively
-#define ABSTRACT_UPLINK_ITEM /obj/effect/gibspawner/generic
+#define ABSTRACT_UPLINK_ITEM /obj/item/loot_table_maker
/// Lower threshold for which an uplink items's TC cost is considered "low" for spy bounties picking rewards
#define SPY_LOWER_COST_THRESHOLD 5
diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm
index a5ff46964bf..d831ba2f0d9 100644
--- a/code/datums/components/uplink.dm
+++ b/code/datums/components/uplink.dm
@@ -227,9 +227,12 @@
for(var/datum/uplink_item/item as anything in uplink_handler.extra_purchasable)
if(item.stock_key in stock_list)
extra_purchasable_stock[REF(item)] = stock_list[item.stock_key]
+ var/atom/actual_item = item.item
extra_purchasable += list(list(
"id" = item.type,
"name" = item.name,
+ "icon" = actual_item.icon,
+ "icon_state" = actual_item.icon_state,
"cost" = item.cost,
"desc" = item.desc,
"category" = item.category ? initial(item.category.name) : null,
@@ -288,6 +291,11 @@
return
item = SStraitor.uplink_items_by_type[item_path]
uplink_handler.purchase_item(ui.user, item, parent)
+ if("buy_raw_tc")
+ if (uplink_handler.telecrystals <= 0)
+ return
+ var/desired_amount = tgui_input_number(ui.user, "How many raw telecrystals to buy?", "Buy Raw TC", default = uplink_handler.telecrystals, max_value = uplink_handler.telecrystals)
+ uplink_handler.purchase_raw_tc(ui.user, desired_amount, parent)
if("lock")
if(!lockable)
return TRUE
diff --git a/code/modules/antagonists/traitor/uplink_handler.dm b/code/modules/antagonists/traitor/uplink_handler.dm
index f78ddb02478..2d27f3c4a0e 100644
--- a/code/modules/antagonists/traitor/uplink_handler.dm
+++ b/code/modules/antagonists/traitor/uplink_handler.dm
@@ -126,6 +126,21 @@
on_update()
return TRUE
+/datum/uplink_handler/proc/purchase_raw_tc(mob/user, amount, atom/movable/source)
+ if(shop_locked)
+ return FALSE
+ if(telecrystals < amount)
+ return FALSE
+
+ telecrystals -= amount
+ var/tcs = new /obj/item/stack/telecrystal(get_turf(user), amount)
+ user.put_in_hands(tcs)
+
+ log_uplink("[key_name(user)] purchased [amount] raw telecrystals from [source]'s uplink")
+ on_update()
+ return TRUE
+
+
/// Generates objectives for this uplink handler
/datum/uplink_handler/proc/generate_objectives()
var/potential_objectives_left = maximum_potential_objectives - (length(potential_objectives) + length(active_objectives))
diff --git a/code/modules/asset_cache/assets/uplink.dm b/code/modules/asset_cache/assets/uplink.dm
index e85ee1b35b5..35a907a234d 100644
--- a/code/modules/asset_cache/assets/uplink.dm
+++ b/code/modules/asset_cache/assets/uplink.dm
@@ -18,10 +18,13 @@
for(var/datum/uplink_item/item_path as anything in subtypesof(/datum/uplink_item))
var/datum/uplink_item/item = new item_path()
+ var/atom/actual_item = item.item
if(item.item) {
items += list(list(
"id" = item_path,
"name" = item.name,
+ "icon" = actual_item.icon,
+ "icon_state" = actual_item.icon_state,
"cost" = item.cost,
"desc" = item.desc,
"category" = item.category ? initial(item.category.name) : null,
diff --git a/code/modules/uplink/uplink_items/bundle.dm b/code/modules/uplink/uplink_items/bundle.dm
index dae6166d49c..b6cdc2fd3d6 100644
--- a/code/modules/uplink/uplink_items/bundle.dm
+++ b/code/modules/uplink/uplink_items/bundle.dm
@@ -40,18 +40,7 @@
// Don't add telecrystals to the purchase_log since
// it's just used to buy more items (including itself!)
purchase_log_vis = FALSE
-
-/datum/uplink_item/bundles_tc/telecrystal/five
- name = "5 Raw Telecrystals"
- desc = "Five telecrystals in their rawest and purest form; can be utilized on active uplinks to increase their telecrystal count."
- item = /obj/item/stack/telecrystal/five
- cost = 5
-
-/datum/uplink_item/bundles_tc/telecrystal/twenty
- name = "20 Raw Telecrystals"
- desc = "Twenty telecrystals in their rawest and purest form; can be utilized on active uplinks to increase their telecrystal count."
- item = /obj/item/stack/telecrystal/twenty
- cost = 20
+ purchasable_from = NONE
/datum/uplink_item/bundles_tc/bundle_a
name = "Syndi-kit Tactical"
diff --git a/tgui/packages/tgui/interfaces/AntagInfoMalf.tsx b/tgui/packages/tgui/interfaces/AntagInfoMalf.tsx
index 7b799e96552..88520752b1e 100644
--- a/tgui/packages/tgui/interfaces/AntagInfoMalf.tsx
+++ b/tgui/packages/tgui/interfaces/AntagInfoMalf.tsx
@@ -188,6 +188,8 @@ export const AntagInfoMalf = (props) => {
items.push({
id: item.name,
name: item.name,
+ icon: item.icon,
+ icon_state: item.icon_state,
category: category.name,
cost: `${item.cost} PT`,
desc: item.desc,
diff --git a/tgui/packages/tgui/interfaces/Uplink/GenericUplink.tsx b/tgui/packages/tgui/interfaces/Uplink/GenericUplink.tsx
index 6f69b6671eb..c6558321b69 100644
--- a/tgui/packages/tgui/interfaces/Uplink/GenericUplink.tsx
+++ b/tgui/packages/tgui/interfaces/Uplink/GenericUplink.tsx
@@ -1,9 +1,13 @@
import { BooleanLike } from 'common/react';
import { useState } from 'react';
+import { Tooltip } from 'tgui-core/components';
+import { useBackend } from '../../backend';
import {
Box,
Button,
+ DmIcon,
+ Icon,
Input,
NoticeBox,
Section,
@@ -19,6 +23,7 @@ type GenericUplinkProps = {
};
export const GenericUplink = (props: GenericUplinkProps) => {
+ const { act } = useBackend();
const {
currency = 'cr',
categories,
@@ -36,43 +41,71 @@ export const GenericUplink = (props: GenericUplinkProps) => {
});
return (
-
+
+
+
);
};
export type Item = {
id: string | number;
name: string;
+ icon: string;
+ icon_state: string;
category: string;
cost: JSX.Element | string;
desc: JSX.Element | string;
@@ -109,22 +144,86 @@ export type ItemListProps = {
const ItemList = (props: ItemListProps) => {
const { compactMode, items, handleBuy } = props;
+ const fallback = (
+
+ );
return (
-
+
{items.map((item, index) => (
-
- handleBuy(item)}
- />
- }
- >
- {compactMode ? null : item.desc}
+
+
+
+
+
+
+
+
+
+ {compactMode ? (
+
+
+ {item.name}
+
+
+
+
+
+
+
+
+
+
+ ) : (
+ handleBuy(item)}
+ >
+ {item.cost}
+
+ }
+ >
+
+ {item.desc}
+
+
+ )}
+
+
))}
diff --git a/tgui/packages/tgui/interfaces/Uplink/PrimaryObjectiveMenu.tsx b/tgui/packages/tgui/interfaces/Uplink/PrimaryObjectiveMenu.tsx
index ee6e81160d3..f0364e88d9f 100644
--- a/tgui/packages/tgui/interfaces/Uplink/PrimaryObjectiveMenu.tsx
+++ b/tgui/packages/tgui/interfaces/Uplink/PrimaryObjectiveMenu.tsx
@@ -12,19 +12,17 @@ export const PrimaryObjectiveMenu = (props: PrimaryObjectiveMenuProps) => {
const { act } = useBackend();
const { primary_objectives, final_objective, can_renegotiate } = props;
return (
-
-
-
- {
- 'Agent, your Primary Objectives are as follows. Complete these at all costs.'
- }
-
-
- {
- 'Completing Secondary Objectives may allow you to aquire additional equipment.'
- }
-
-
+
+
+ WELCOME, AGENT.
+
+
+ Your Primary Objectives are as follows. Complete these at all costs.
+
+
+ Completing Secondary Objectives may allow you to aquire additional
+ equipment.
+
{final_objective && (
{
)}
-
-
- {primary_objectives.map((prim_obj, index) => (
-
-
-
- ))}
-
-
+
+ {primary_objectives.map((prim_obj, index) => (
+
+
+
+ ))}
+
{!!can_renegotiate && (
)}
+
+ SyndOS Version 3.17
+ Connection Secure
+
);
};
diff --git a/tgui/packages/tgui/interfaces/Uplink/calculateDangerLevel.tsx b/tgui/packages/tgui/interfaces/Uplink/calculateDangerLevel.tsx
index e8951e367a9..d67dd37391e 100644
--- a/tgui/packages/tgui/interfaces/Uplink/calculateDangerLevel.tsx
+++ b/tgui/packages/tgui/interfaces/Uplink/calculateDangerLevel.tsx
@@ -90,7 +90,7 @@ export const dangerLevelsTooltip = (
color="white"
className={value.gradient}
style={{
- borderRadius: '5px',
+ borderRadius: '2px',
display: 'inline-block',
}}
px={0.8}
@@ -137,11 +137,12 @@ export const calculateDangerLevel = (
color="white"
className={dangerLevel.gradient}
style={{
- borderRadius: '5px',
+ borderRadius: '2px',
display: 'inline-block',
}}
px={0.8}
py={0.6}
+ textAlign="center"
>
{dangerLevel.title} ({displayedProgression})
diff --git a/tgui/packages/tgui/interfaces/Uplink/index.tsx b/tgui/packages/tgui/interfaces/Uplink/index.tsx
index 4949fc94ee7..3ed7d34a214 100644
--- a/tgui/packages/tgui/interfaces/Uplink/index.tsx
+++ b/tgui/packages/tgui/interfaces/Uplink/index.tsx
@@ -7,6 +7,7 @@ import {
Box,
Button,
Dimmer,
+ NoticeBox,
Section,
Stack,
Tabs,
@@ -27,6 +28,8 @@ import { PrimaryObjectiveMenu } from './PrimaryObjectiveMenu';
type UplinkItem = {
id: string;
name: string;
+ icon: string;
+ icon_state: string;
cost: number;
desc: string;
category: string;
@@ -90,6 +93,8 @@ type ServerData = {
type ItemExtraData = Item & {
extraData: {
ref?: string;
+ icon: string;
+ icon_state: string;
};
};
@@ -198,7 +203,6 @@ export class Uplink extends Component<{}, UplinkState> {
shop_locked,
} = data;
const { allItems, allCategories, currentTab } = this.state as UplinkState;
-
const itemsToAdd = [...allItems];
const items: ItemExtraData[] = [];
itemsToAdd.push(...extra_purchasable);
@@ -224,19 +228,21 @@ export class Uplink extends Component<{}, UplinkState> {
items.push({
id: item.id,
name: item.name,
+ icon: item.icon,
+ icon_state: item.icon_state,
category: item.category,
desc: (
-
- {item.desc}
+ <>
+ {item.desc}
{(item.lock_other_purchases && (
-
+
Taking this item will lock you from further purchasing from the
marketplace. Additionally, if you have already purchased an
item, you will not be able to purchase this.
-
+
)) ||
null}
-
+ >
),
cost: (
@@ -259,6 +265,8 @@ export class Uplink extends Component<{}, UplinkState> {
(item.lock_other_purchases && purchased_items > 0),
extraData: {
ref: item.ref,
+ icon: item.icon,
+ icon_state: item.icon_state,
},
});
}
@@ -274,25 +282,14 @@ export class Uplink extends Component<{}, UplinkState> {
// Round it and convert it into a percentage
progressionPercentage = Math.round(progressionPercentage * 1000) / 10;
return (
-
-
-
-
-
-
-
-
- SyndOS Version 3.17
-
- Connection Secure
-
-
-
- WELCOME, AGENT.
-
-
-
-
+
+
+
+ {!!has_progression && (
+
+
+
+
{
}
>
{/* If we have no progression,
- just give them a generic title */}
+ just give them a generic title */}
{has_progression
? calculateDangerLevel(progression_points, false)
: calculateDangerLevel(dangerDefault, false)}
-
-
- {telecrystals} TC
-
-
-
-
-
-
-
-
-
-
- {!!has_objectives && (
- <>
- this.setState({ currentTab: 0 })}
- >
- Primary Objectives
-
- this.setState({ currentTab: 1 })}
- >
- Secondary Objectives
-
- >
- )}
- this.setState({ currentTab: 2 })}
- >
- Market
-
-
-
- {!!lockable && (
-
-
- )}
-
-
-
+
+
+
+ {!!has_objectives && (
+ <>
+ this.setState({ currentTab: 0 })}
+ >
+ Primary Objectives
+
+ this.setState({ currentTab: 1 })}
+ >
+ Secondary Objectives
+
+ >
+ )}
+ this.setState({ currentTab: 2 })}
+ >
+ Market
+
+
+
+
+ {!!lockable && (
+
+
+
+ )}
+
+
+
+ )}
{(currentTab === 0 && has_objectives && (
{
handleRequestObjectives={() => act('regenerate_objectives')}
/>
)) || (
-
+ <>
{
@@ -471,7 +483,7 @@ export class Uplink extends Component<{}, UplinkState> {
)) ||
null}
-
+ >
)}