Skip to content

Commit dabf9e8

Browse files
committed
blowpipe dart as item var
This solves the export-import portion of #293, but we still need to handle warnings. This PR could be merged in the interim since it's strictly better than existing behaviour, albeit not being a full fix. I've put this up as a separate PR from #396 in case we change the approach for errors away from that one. If we can solve the data sourcing issue in wikisync, it will also be capable of specifying the dart id through the itemVars field.
1 parent 5c4c62c commit dabf9e8

6 files changed

Lines changed: 58 additions & 31 deletions

File tree

src/app/components/player/equipment/EquipmentSelect.tsx

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import React, { useMemo } from 'react';
22
import { useStore } from '@/state';
33
import { observer } from 'mobx-react-lite';
4-
import { getCdnImage } from '@/utils';
4+
import { getCdnImage, isDefined } from '@/utils';
55
import { EquipmentPiece } from '@/types/Player';
66
import LazyImage from '@/app/components/generic/LazyImage';
77
import { cross } from 'd3-array';
88
import { availableEquipment, equipmentAliases, noStatExceptions } from '@/lib/Equipment';
9+
import { BLOWPIPE_IDS } from '@/lib/constants';
910
import Combobox from '../../generic/Combobox';
1011

1112
interface EquipmentOption {
@@ -16,29 +17,30 @@ interface EquipmentOption {
1617
equipment: EquipmentPiece;
1718
}
1819

19-
const BLOWPIPE_IDS: string[] = [
20-
'12926', // regular
21-
'28688', // blazing
22-
];
23-
24-
const DART_IDS: string[] = [
25-
'806', // bronze
26-
'807', // iron
27-
'808', // steel
28-
'809', // mithril
29-
'810', // adamant
30-
'811', // rune
31-
'3093', // black
32-
'11230', // dragon
33-
'25849', // amethyst
34-
];
20+
const findDart = (name: string): EquipmentPiece | undefined => {
21+
const eq = availableEquipment.find((e) => e.name === name);
22+
if (!eq) {
23+
console.warn(`Failed to locate dart [${name}] for blowpipe dart entry generation, proceeding without this option.`);
24+
}
25+
return eq;
26+
};
27+
const DARTS: EquipmentPiece[] = [
28+
findDart('Bronze dart'),
29+
findDart('Iron dart'),
30+
findDart('Steel dart'),
31+
findDart('Mithril dart'),
32+
findDart('Adamant dart'),
33+
findDart('Rune dart'),
34+
findDart('Black dart'),
35+
findDart('Dragon dart'),
36+
findDart('Amethyst dart'),
37+
].filter(isDefined);
3538

3639
const EquipmentSelect: React.FC = observer(() => {
3740
const store = useStore();
3841

3942
const options: EquipmentOption[] = useMemo(() => {
4043
const blowpipeEntries: EquipmentOption[] = [];
41-
const dartEntries: EquipmentOption[] = [];
4244

4345
const entries: EquipmentOption[] = [];
4446
for (const v of availableEquipment.filter((eq) => {
@@ -67,27 +69,23 @@ const EquipmentSelect: React.FC = observer(() => {
6769
equipment: v,
6870
};
6971

70-
if (BLOWPIPE_IDS.includes(e.value)) {
72+
if (BLOWPIPE_IDS.includes(v.id)) {
7173
blowpipeEntries.push(e);
72-
} else if (DART_IDS.includes(e.value)) {
73-
dartEntries.push(e);
74-
entries.push(e);
7574
} else {
7675
entries.push(e);
7776
}
7877
}
7978

80-
cross(blowpipeEntries, dartEntries).forEach(([blowpipe, dart]) => {
81-
const newStrength = blowpipe.equipment.bonuses.ranged_str + dart.equipment.bonuses.ranged_str;
79+
cross(blowpipeEntries, DARTS).forEach(([blowpipe, dart]) => {
8280
entries.push({
8381
...blowpipe,
84-
label: `${blowpipe.label} (${dart.label.split(' ', 2)[0]})`,
85-
value: `${blowpipe.value}_${dart.value}`,
82+
label: `${blowpipe.label} (${dart.name.replace(' dart', '')})`,
83+
value: `${blowpipe.value}_${dart.id}`,
8684
equipment: {
8785
...blowpipe.equipment,
88-
bonuses: {
89-
...blowpipe.equipment.bonuses,
90-
ranged_str: newStrength,
86+
itemVars: {
87+
...blowpipe.equipment.itemVars,
88+
blowpipeDartId: dart.id,
9189
},
9290
},
9391
});

src/lib/Equipment.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { EquipmentPiece, Player, PlayerEquipment } from '@/types/Player';
22
import { Monster } from '@/types/Monster';
33
import { keys } from '@/utils';
4-
import { CAST_STANCES, TOMBS_OF_AMASCUT_MONSTER_IDS } from '@/lib/constants';
4+
import { BLOWPIPE_IDS, CAST_STANCES, TOMBS_OF_AMASCUT_MONSTER_IDS } from '@/lib/constants';
55
import { sum } from 'd3-array';
66
import equipment from '../../cdn/json/equipment.json';
77
import generatedEquipmentAliases from './EquipmentAliases';
@@ -278,6 +278,15 @@ export const calculateEquipmentBonusesFromGear = (player: Player, monster: Monst
278278
});
279279
});
280280

281+
if (BLOWPIPE_IDS.includes(playerEquipment.weapon?.id || 0)) {
282+
const dart = availableEquipment.find((e) => e.id === playerEquipment.weapon?.itemVars?.blowpipeDartId);
283+
if (dart) {
284+
totals.bonuses.ranged_str += dart.bonuses.ranged_str;
285+
} else {
286+
// todo warn user
287+
}
288+
}
289+
281290
if (playerEquipment.weapon?.name === "Tumeken's shadow" && player.style.stance !== 'Manual Cast') {
282291
const factor = TOMBS_OF_AMASCUT_MONSTER_IDS.includes(monster.id) ? 4 : 3;
283292
totals.bonuses.magic_str *= factor;

src/lib/constants.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { CombatStyleStance } from '@/types/PlayerCombatStyle';
22

3+
export const BLOWPIPE_IDS: number[] = [
4+
12926, // regular
5+
28688, // blazing
6+
];
7+
38
export const AKKHA_IDS = [
49
11789, 11790, 11791, 11792, 11793, 11794, 11795, 11796,
510
];

src/state.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,14 @@ export const parseLoadoutsFromImportedData = (data: ImportableData) => data.load
122122
let item: EquipmentPiece | undefined;
123123
if (Object.hasOwn(v, 'id')) {
124124
item = availableEquipment.find((eq) => eq.id === v.id);
125-
if (!item) console.warn(`[parseLoadoutsFromImportedData] No item found for item ID ${v.id}`);
125+
if (item) {
126+
// include the hidden itemVars inputs that are not present on the availableEquipment store
127+
if (Object.hasOwn(v, 'itemVars')) {
128+
item = { ...item, itemVars: v.itemVars };
129+
}
130+
} else {
131+
console.warn(`[parseLoadoutsFromImportedData] No item found for item ID ${v.id}`);
132+
}
126133
}
127134
// The following line will remove the item entirely if it seems to no longer exist.
128135
loadout.equipment[k as keyof typeof loadout.equipment] = item || null;

src/types/Player.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ export interface EquipmentPiece extends EquipmentStats {
2424
speed: number;
2525
category: EquipmentCategory;
2626
isTwoHanded: boolean;
27+
itemVars?: {
28+
blowpipeDartId?: number;
29+
};
2730
}
2831

2932
/**

src/utils.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ export const generateShortlink = async (data: ImportableData): Promise<string> =
7070
return res.data.data;
7171
};
7272

73+
// for type narrowing
74+
export function isDefined<T>(id: T | undefined | null): id is T {
75+
return !!id;
76+
}
77+
7378
/**
7479
* Calculates a player's combat level using their skills
7580
* @param s

0 commit comments

Comments
 (0)