diff --git a/src/app/vendors/VendorItems.tsx b/src/app/vendors/VendorItems.tsx
index 5a1661a176..9a46c13ddd 100644
--- a/src/app/vendors/VendorItems.tsx
+++ b/src/app/vendors/VendorItems.tsx
@@ -1,12 +1,15 @@
import { PressTip } from 'app/dim-ui/PressTip';
import RichDestinyText from 'app/dim-ui/destiny-symbols/RichDestinyText';
import { t } from 'app/i18next-t';
+import { DimItem } from 'app/inventory/item-types';
import { useD2Definitions } from 'app/manifest/selectors';
import FactionIcon from 'app/progress/FactionIcon';
import { ReputationRank } from 'app/progress/ReputationRank';
import { DestinyVendorProgressionType } from 'bungie-api-ts/destiny2';
import focusingItemOutputs from 'data/d2/focusing-item-outputs.json';
+import { ReactNode } from 'react';
import BungieImage from '../dim-ui/BungieImage';
+import ItemPopupTrigger from '../inventory/ItemPopupTrigger';
import VendorItemComponent from './VendorItemComponent';
import * as styles from './VendorItems.m.scss';
import { D2Vendor } from './d2-vendors';
@@ -65,8 +68,9 @@ export default function VendorItems({
{t('Vendors.Engram')}
- {factionProgress &&
- (vendor.def.vendorProgressionType !== DestinyVendorProgressionType.Default ? (
+ {/* Clicking the rep track opens the vendor's "help" item popup, if it has one. */}
+
+ {vendor.def.vendorProgressionType !== DestinyVendorProgressionType.Default ? (
) : (
- ))}
+ )}
+
)}
@@ -125,3 +130,19 @@ export default function VendorItems({
);
}
+
+/** Wraps the rep track so clicking it opens the given "help" item's popup, if there is one. */
+function RepTrackTrigger({ item, children }: { item: DimItem | undefined; children: ReactNode }) {
+ if (!item) {
+ return children;
+ }
+ return (
+
+ {(ref, onClick) => (
+
+ {children}
+
+ )}
+
+ );
+}
diff --git a/src/app/vendors/d2-vendors.ts b/src/app/vendors/d2-vendors.ts
index cc429cf413..02019c738c 100644
--- a/src/app/vendors/d2-vendors.ts
+++ b/src/app/vendors/d2-vendors.ts
@@ -31,10 +31,31 @@ export interface D2Vendor {
place?: DestinyPlaceDefinition;
items: VendorItem[];
currencies: DestinyInventoryItemDefinition[];
+ /**
+ * The vendor's "help" item, if it has one. It describes the reputation track and
+ * is pulled out of the regular sale items so it can be shown alongside the rep
+ * track instead. Only set when the vendor actually has a rep track.
+ */
+ helpItem?: VendorItem;
}
const vendorOrder = [VendorHashes.AdaTransmog, VendorHashes.Banshee, VendorHashes.Eververse];
+/**
+ * Some vendors contain a "help" item that isn't a real sale item, but instead
+ * describes the vendor's reputation track. We pull it out of the regular sale
+ * items and show it alongside the rep track instead.
+ *
+ * These items all use the shared "vendor_help" icon (icon def 13580639, foreground
+ * `.../vendor_help...png`). The more semantic-looking `tooltipStyle: 'vendor_action'`
+ * can't be used because DIM's manifest trimmer blanks `tooltipStyle` out.
+ */
+const HELP_ITEM_ICON_HASH = 13580639;
+
+function isHelpVendorItem(vendorItem: VendorItem) {
+ return vendorItem.displayProperties?.iconHash === HELP_ITEM_ICON_HASH;
+}
+
export function toVendorGroups(
context: ItemCreationContext,
vendorsResponse: DestinyVendorsResponse,
@@ -105,6 +126,21 @@ export function toVendor(
),
);
+ // Pull the "help" item out of the regular sale items so it isn't shown as a
+ // normal tile. Surface it on the rep track (if there is one) instead.
+ let helpItem: VendorItem | undefined;
+ const helpIndex = vendorItems.findIndex(isHelpVendorItem);
+ if (helpIndex >= 0) {
+ const [extracted] = vendorItems.splice(helpIndex, 1);
+ if (vendorDef.factionHash && vendor?.progression) {
+ helpItem = extracted;
+ if (helpItem.item) {
+ // It's not a real item, so don't show its placeholder type ("Unknown") in the popup.
+ helpItem.item.typeName = '';
+ }
+ }
+ }
+
const destinationHash =
typeof vendor?.vendorLocationIndex === 'number' && vendor.vendorLocationIndex >= 0
? // Unadvertised nullability: DestinyVendorDefinition.locations
@@ -143,6 +179,7 @@ export function toVendor(
place: placeDef,
items: vendorItems,
currencies,
+ helpItem,
};
}