Skip to content

Commit

Permalink
Merge pull request #10731 from DestinyItemManager/breakerama
Browse files Browse the repository at this point in the history
Add breaker:intrinsic search and visually differentiate artifact-granted breaker
  • Loading branch information
bhollis authored Sep 23, 2024
2 parents 53320a9 + 9b0c405 commit dfe57a7
Show file tree
Hide file tree
Showing 12 changed files with 67 additions and 49 deletions.
2 changes: 1 addition & 1 deletion config/i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@
"ArmorIntrinsic": "Shows legendary armor which has an intrinsic perk, such as Artifice Armor.",
"Ascended": "Shows items that have an ascend node which have been ascended.",
"Unascended": "Shows items that have an ascend node which have not been ascended.",
"Breaker": "Filter by breaker type or corresponding champion type.",
"Breaker": "Filter by breaker type or corresponding champion type. breaker:instrinsic shows items with intrinsic breaker ability.",
"BulkClear": "Removed tag from 1 item.",
"BulkClear_plural": "Removed tags from {{count}} items.",
"BulkRevert": "Reverted tag on 1 item.",
Expand Down
3 changes: 3 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## Next

* Add `breaker:intrinsic` search that highlights items that have an intrinsic breaker ability (i.e. not granted by the seasonal artifact).
* Breaker type granted by the seasonal artifact now has a green box around it, reminiscent of the artifact mod that grants it.

## 8.38.0 <span class="changelog-date">(2024-09-22)</span>

* Renamed `is:class` to `is:subclass`.
Expand Down
13 changes: 3 additions & 10 deletions src/app/armory/Armory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
useSocketOverrides,
} from 'app/inventory/store/override-sockets';
import { getEvent, getSeason } from 'app/inventory/store/season';
import BreakerType from 'app/item-popup/BreakerType';
import EmblemPreview from 'app/item-popup/EmblemPreview';
import { AmmoIcon, ItemTypeName } from 'app/item-popup/ItemPopupHeader';
import ItemSockets from 'app/item-popup/ItemSockets';
Expand All @@ -26,7 +27,7 @@ import { Reward } from 'app/progress/Reward';
import { AppIcon, compareIcon } from 'app/shell/icons';
import { useIsPhonePortrait } from 'app/shell/selectors';
import { useThunkDispatch } from 'app/store/thunk-dispatch';
import { getBreakerTypeHash, getItemYear } from 'app/utils/item-utils';
import { getItemYear } from 'app/utils/item-utils';
import clsx from 'clsx';
import { D2EventInfo } from 'data/d2/d2-event-info-v2';
import { ItemCategoryHashes } from 'data/d2/generated-enums';
Expand Down Expand Up @@ -91,14 +92,6 @@ export default function Armory({
const screenshot = ornamentSocket?.plugged?.plugDef.screenshot || itemDef.screenshot;
const flavorText = itemDef.flavorText || itemDef.displaySource;

let breakerType = item.breakerType;
if (!breakerType) {
const breakerTypeHash = getBreakerTypeHash(item);
if (breakerTypeHash) {
breakerType = defs.BreakerType.get(breakerTypeHash);
}
}

// TODO: Show Catalyst benefits for exotics

return (
Expand All @@ -123,7 +116,7 @@ export default function Armory({
<div className={styles.headerContent}>
<div className={styles.subtitle}>
<ElementIcon element={item.element} className={styles.element} />
{breakerType && <BungieImage src={breakerType.displayProperties.icon} height={15} />}
<BreakerType item={item} />
{item.destinyVersion === 2 && item.ammoType > 0 && <AmmoIcon type={item.ammoType} />}
<ItemTypeName item={item} />
{item.pursuit?.questLine && (
Expand Down
11 changes: 11 additions & 0 deletions src/app/item-popup/BreakerType.m.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.breakerIcon {
margin: 0 4px;
width: 15px;
height: 15px;
}

.artifactBreaker {
background-color: #3f8e90;
padding: 1px 2px;
border-radius: 1px;
}
8 changes: 8 additions & 0 deletions src/app/item-popup/BreakerType.m.scss.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions src/app/item-popup/BreakerType.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import BungieImage from 'app/dim-ui/BungieImage';
import { DimItem } from 'app/inventory/item-types';
import { useD2Definitions } from 'app/manifest/selectors';
import { getSeasonalBreakerTypeHash } from 'app/utils/item-utils';
import clsx from 'clsx';
import styles from './BreakerType.m.scss';

export default function BreakerType({ item }: { item: DimItem }) {
const defs = useD2Definitions()!;
let breakerType = item.breakerType;
let breakerClass: string | undefined;
if (!breakerType) {
const breakerTypeHash = getSeasonalBreakerTypeHash(item);
if (breakerTypeHash) {
breakerType = defs.BreakerType.get(breakerTypeHash);
breakerClass = styles.artifactBreaker;
}
}

return (
breakerType && (
<BungieImage
className={clsx(styles.breakerIcon, breakerClass)}
src={breakerType.displayProperties.icon}
/>
)
);
}
10 changes: 0 additions & 10 deletions src/app/item-popup/ItemPopupHeader.m.scss
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,6 @@
}
}

.breakerIcon {
margin: 0 4px;
width: 15px;
height: 15px;
}

.ammoIcon {
margin: 0 2px 0 6px;
height: 14px;
Expand Down Expand Up @@ -135,10 +129,6 @@

.legendary {
background-color: $legendary;
.primary,
.breakerIcon {
opacity: 0.8;
}
}

.exotic {
Expand Down
1 change: 0 additions & 1 deletion src/app/item-popup/ItemPopupHeader.m.scss.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 2 additions & 15 deletions src/app/item-popup/ItemPopupHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import ArmorySheet from 'app/armory/ArmorySheet';
import BungieImage from 'app/dim-ui/BungieImage';
import ElementIcon from 'app/dim-ui/ElementIcon';
import RichDestinyText from 'app/dim-ui/destiny-symbols/RichDestinyText';
import { useHotkey } from 'app/hotkeys/useHotkey';
import { t } from 'app/i18next-t';
import { useD2Definitions } from 'app/manifest/selectors';
import { D1BucketHashes } from 'app/search/d1-known-values';
import type { ItemTierName } from 'app/search/d2-known-values';
import { getBreakerTypeHash } from 'app/utils/item-utils';
import { LookupTable } from 'app/utils/util-types';
import { DestinyAmmunitionType, DestinyClass } from 'bungie-api-ts/destiny2';
import clsx from 'clsx';
Expand All @@ -17,6 +14,7 @@ import primary from 'destiny-icons/general/ammo-primary.svg';
import special from 'destiny-icons/general/ammo-special.svg';
import { useState } from 'react';
import { DimItem } from '../inventory/item-types';
import BreakerType from './BreakerType';
import styles from './ItemPopupHeader.m.scss';

const tierClassName: LookupTable<ItemTierName, string> = {
Expand All @@ -35,22 +33,13 @@ export default function ItemPopupHeader({
/** Don't allow opening Armory from the header link */
noLink?: boolean;
}) {
const defs = useD2Definitions()!;
const [showArmory, setShowArmory] = useState(false);
useHotkey('a', t('Hotkey.Armory'), () => setShowArmory(true));

const showElementIcon = Boolean(item.element);

const linkToArmory = !noLink && item.destinyVersion === 2;

let breakerType = item.breakerType;
if (!breakerType) {
const breakerTypeHash = getBreakerTypeHash(item);
if (breakerTypeHash) {
breakerType = defs.BreakerType.get(breakerTypeHash);
}
}

return (
<button
type="button"
Expand All @@ -75,9 +64,7 @@ export default function ItemPopupHeader({
<div className={styles.type}>
<ItemTypeName item={item} className={styles.itemType} />
{item.destinyVersion === 2 && item.ammoType > 0 && <AmmoIcon type={item.ammoType} />}
{breakerType && (
<BungieImage className={styles.breakerIcon} src={breakerType.displayProperties.icon} />
)}
<BreakerType item={item} />
</div>

<div className={styles.details}>
Expand Down
5 changes: 4 additions & 1 deletion src/app/search/items/search-filters/known-values.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,9 +320,12 @@ const knownValuesFilters: ItemFilterDefinition[] = [
keywords: 'breaker',
description: tl('Filter.Breaker'),
format: 'query',
suggestions: Object.keys(breakerTypes),
suggestions: [...Object.keys(breakerTypes), 'intrinsic'],
destinyVersion: 2,
filter: ({ filterValue }) => {
if (filterValue === 'intrinsic') {
return (item) => Boolean(item.breakerType);
}
const breakerType = breakerTypes[filterValue as keyof typeof breakerTypes];
if (!breakerType) {
throw new Error(`Unknown breaker type ${filterValue}`);
Expand Down
16 changes: 6 additions & 10 deletions src/app/utils/item-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -352,17 +352,13 @@ const ichToBreakerType = Object.entries(artifactBreakerMods).reduce<
}, {});

/**
* Get the effective breaker type of a weapon, which is either its intrinsic
* breaker type (for some exotics) or one of the breaker types enabled by this
* season's artifact mods.
* Get the effective breaker type of a weapon as granted by the seasonal
* artifact. This does not include intrinsic breaker types (e.g. on some
* exotics) so you should check item.breakerType first if you want the effective
* overall breaker type, as intrinsic breaker beats artifact breaker.
*/
export function getBreakerTypeHash(item: DimItem): number | undefined {
if (item.destinyVersion === 1) {
return;
}
if (item.breakerType) {
return item.breakerType.hash;
} else if (item.bucket.inWeapons) {
export function getSeasonalBreakerTypeHash(item: DimItem): number | undefined {
if (item.destinyVersion === 2 && item.bucket.inWeapons && !item.breakerType) {
for (const ich of item.itemCategoryHashes) {
if (ichToBreakerType[ich]) {
return ichToBreakerType[ich];
Expand Down
2 changes: 1 addition & 1 deletion src/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@
"ArmorCategory": "Shows armors based on their category.",
"ArmorIntrinsic": "Shows legendary armor which has an intrinsic perk, such as Artifice Armor.",
"Ascended": "Shows items that have an ascend node which have been ascended.",
"Breaker": "Filter by breaker type or corresponding champion type.",
"Breaker": "Filter by breaker type or corresponding champion type. breaker:instrinsic shows items with intrinsic breaker ability.",
"BulkClear": "Removed tag from 1 item.",
"BulkClear_plural": "Removed tags from {{count}} items.",
"BulkRevert": "Reverted tag on 1 item.",
Expand Down

0 comments on commit dfe57a7

Please sign in to comment.