Skip to content

Commit

Permalink
More PR feedback: move reforgeData to equipped_item
Browse files Browse the repository at this point in the history
  • Loading branch information
1337LutZ committed Sep 27, 2024
1 parent 4d84e0d commit b68caea
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 70 deletions.
8 changes: 4 additions & 4 deletions ui/core/components/gear_picker/gear_picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,10 @@ export class ItemRenderer extends Component {
this.nameContainerElem.appendChild(this.notice.rootElem);
}

if (newItem.reforge) {
const reforgeData = Player.getReforgeData(newItem, newItem.reforge);
const fromText = shortSecondaryStatNames.get(newItem.reforge?.fromStat);
const toText = shortSecondaryStatNames.get(newItem.reforge?.toStat);
const reforgeData = newItem.getReforgeData();
if (reforgeData) {
const fromText = shortSecondaryStatNames.get(reforgeData.reforge?.fromStat);
const toText = shortSecondaryStatNames.get(reforgeData.reforge?.toStat);
this.reforgeElem.innerText = `Reforged ${Math.abs(reforgeData.fromAmount)} ${fromText}${reforgeData.toAmount} ${toText}`;
this.reforgeElem.classList.remove('hide');
} else {
Expand Down
4 changes: 2 additions & 2 deletions ui/core/components/gear_picker/item_list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import { SortDirection } from '../../constants/other';
import { EP_TOOLTIP } from '../../constants/tooltips';
import { setItemQualityCssClass } from '../../css_utils';
import { IndividualSimUI } from '../../individual_sim_ui';
import { Player, ReforgeData } from '../../player';
import { Player } from '../../player';
import { Class, GemColor, ItemQuality, ItemRandomSuffix, ItemSlot, ItemSpec } from '../../proto/common';
import { DatabaseFilters, RepFaction, UIEnchant as Enchant, UIGem as Gem, UIItem as Item, UIItem_FactionRestriction } from '../../proto/ui';
import { ActionId } from '../../proto_utils/action_id';
import { getUniqueEnchantString } from '../../proto_utils/enchants';
import { EquippedItem } from '../../proto_utils/equipped_item';
import { EquippedItem, ReforgeData } from '../../proto_utils/equipped_item';
import { difficultyNames, professionNames, REP_FACTION_NAMES, REP_FACTION_QUARTERMASTERS, REP_LEVEL_NAMES } from '../../proto_utils/names';
import { getPVPSeasonFromItem, isPVPItem } from '../../proto_utils/utils';
import { Sim } from '../../sim';
Expand Down
7 changes: 3 additions & 4 deletions ui/core/components/gear_picker/selector_modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import clsx from 'clsx';
import tippy from 'tippy.js';
import { ref } from 'tsx-vanilla';

import { Player, ReforgeData } from '../../player';
import { Player } from '../../player';
import { GemColor, ItemQuality, ItemRandomSuffix, ItemSlot } from '../../proto/common';
import { UIEnchant as Enchant, UIGem as Gem, UIItem as Item } from '../../proto/ui';
import { ActionId } from '../../proto_utils/action_id';
import { EquippedItem } from '../../proto_utils/equipped_item';
import { EquippedItem, ReforgeData } from '../../proto_utils/equipped_item';
import { gemMatchesSocket, getEmptyGemSocketIconUrl } from '../../proto_utils/gems';
import { shortSecondaryStatNames, slotNames } from '../../proto_utils/names';
import { Stats } from '../../proto_utils/stats';
Expand Down Expand Up @@ -447,8 +447,7 @@ export default class SelectorModal extends BaseModal {
};
}),
computeEP: (reforge: ReforgeData) => this.player.computeReforgingEP(reforge),
equippedToItemFn: (equippedItem: EquippedItem | null) =>
equippedItem?.reforge ? Player.getReforgeData(equippedItem, equippedItem.reforge) : null,
equippedToItemFn: (equippedItem: EquippedItem | null) => equippedItem?.getReforgeData() || null,
onRemove: (eventID: number) => {
const equippedItem = gearData.getEquippedItem();
if (equippedItem) {
Expand Down
31 changes: 13 additions & 18 deletions ui/core/components/individual_sim_ui/reforge_summary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,21 @@ export class ReforgeSummary extends Component {

private updateTable() {
const body = <></>;
let gear = this.player.getGear();
const reforges = this.player.getGear().getAllReforges();
const totals: ReforgeSummaryTotal = {};
gear.getItemSlots().forEach(itemSlot => {
const item = gear.getEquippedItem(itemSlot);
if (item?.reforge && item.reforge?.id !== 0) {
const reforge = Player.getReforgeData(item, item.reforge);
if (reforge) {
const { fromStat, toStat, fromAmount, toAmount } = reforge;

if (typeof totals[fromStat] !== 'number') {
totals[fromStat] = 0;
}
if (typeof totals[toStat] !== 'number') {
totals[toStat] = 0;
}
if (fromAmount) totals[fromStat]! += fromAmount;
if (toAmount) totals[toStat]! += toAmount;
}
for (const [_, reforgeData] of reforges) {
const { fromStat, toStat, fromAmount, toAmount } = reforgeData;

if (typeof totals[fromStat] !== 'number') {
totals[fromStat] = 0;
}
});
if (typeof totals[toStat] !== 'number') {
totals[toStat] = 0;
}
if (fromAmount) totals[fromStat]! += fromAmount;
if (toAmount) totals[toStat]! += toAmount;
}

const hasReforgedItems = !!Object.keys(totals).length;
this.rootElem.classList[!hasReforgedItems ? 'add' : 'remove']('hide');
Expand All @@ -77,7 +72,7 @@ export class ReforgeSummary extends Component {
<button
className="btn btn-sm btn-link btn-reset summary-table-reset-button"
onclick={() => {
gear = gear.withoutReforges(this.player.canDualWield2H());
const gear = this.player.getGear().withoutReforges(this.player.canDualWield2H());
this.player.setGear(TypedEvent.nextEventID(), gear);
}}>
<i className="fas fa-times me-1"></i>
Expand Down
15 changes: 8 additions & 7 deletions ui/core/components/suggest_reforges_action.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import { Constraint, greaterEq, lessEq, Model, Options, Solution, solve } from '

import * as Mechanics from '../constants/mechanics.js';
import { IndividualSimUI } from '../individual_sim_ui';
import { Player, ReforgeData } from '../player';
import { Player } from '../player';
import { Class, ItemSlot, PseudoStat, ReforgeStat, Spec, Stat } from '../proto/common';
import { IndividualSimSettings, StatCapType } from '../proto/ui';
import { ReforgeData } from '../proto_utils/equipped_item';
import { Gear } from '../proto_utils/gear';
import { shortSecondaryStatNames, slotNames, statCapTypeNames } from '../proto_utils/names';
import { pseudoStatIsCapped, StatCap, Stats, UnitStat, UnitStatPresets } from '../proto_utils/stats';
Expand Down Expand Up @@ -88,8 +89,8 @@ export class ReforgeOptimizer {
readonly freezeItemSlotsChangeEmitter = new TypedEvent<void>();
protected freezeItemSlots = false;
protected frozenItemSlots = new Map<ItemSlot, boolean>();
protected previousGear = new Map<ItemSlot, ReforgeData>();
protected currentGear = new Map<ItemSlot, ReforgeData>();
protected previousReforges = new Map<ItemSlot, ReforgeData>();
protected currentReforges = new Map<ItemSlot, ReforgeData>();

constructor(simUI: IndividualSimUI<any>, options?: ReforgeOptimizerOptions) {
this.simUI = simUI;
Expand Down Expand Up @@ -648,7 +649,7 @@ export class ReforgeOptimizer {
console.log(Array.from(this.frozenItemSlots.keys()).filter(key => this.frozenItemSlots.get(key)));
}
const previousGear = this.player.getGear();
this.previousGear = previousGear.getAllReforges();
this.previousReforges = previousGear.getAllReforges();
const baseGear = previousGear.withoutReforges(this.player.canDualWield2H(), this.frozenItemSlots);
const baseStats = await this.updateGear(baseGear);

Expand All @@ -672,7 +673,7 @@ export class ReforgeOptimizer {

// Solve in multiple passes to enforce caps
await this.solveModel(baseGear, validatedWeights, reforgeCaps, reforgeSoftCaps, variables, constraints);
this.currentGear = this.player.getGear().getAllReforges();
this.currentReforges = this.player.getGear().getAllReforges();
}

async updateGear(gear: Gear): Promise<Stats> {
Expand Down Expand Up @@ -1006,8 +1007,8 @@ export class ReforgeOptimizer {
const itemSlots = this.player.getGear().getItemSlots();
const changedSlots = new Map<ItemSlot, ReforgeData | undefined>();
for (const slot of itemSlots) {
const prev = this.previousGear.get(slot);
const current = this.currentGear.get(slot);
const prev = this.previousReforges.get(slot);
const current = this.currentReforges.get(slot);
if (!ReforgeStat.equals(prev?.reforge, current?.reforge)) changedSlots.set(slot, current);
}
const hasReforgeChanges = changedSlots.size;
Expand Down
32 changes: 2 additions & 30 deletions ui/core/player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ import {
} from './proto/ui';
import { ActionId } from './proto_utils/action_id';
import { Database } from './proto_utils/database';
import { EquippedItem, getWeaponDPS } from './proto_utils/equipped_item';
import { EquippedItem, getWeaponDPS, ReforgeData } from './proto_utils/equipped_item';
import { Gear, ItemSwapGear } from './proto_utils/gear';
import { gemMatchesSocket, isUnrestrictedGem } from './proto_utils/gems';
import { StatCap, Stats } from './proto_utils/stats';
Expand Down Expand Up @@ -220,16 +220,6 @@ export function getSpecConfig<SpecType extends Spec>(spec: SpecType): PlayerConf
return config;
}

export interface ReforgeData {
id: number;
item: Item;
reforge: ReforgeStat;
fromStat: Stat;
toStat: Stat;
fromAmount: number;
toAmount: number;
}

// Manages all the gear / consumes / other settings for a single Player.
export class Player<SpecType extends Spec> {
readonly sim: Sim;
Expand Down Expand Up @@ -455,32 +445,14 @@ export class Player<SpecType extends Spec> {
// Returns all reforgings that are valid with a given item
getAvailableReforgings(equippedItem: EquippedItem): Array<ReforgeData> {
const withRandomSuffixStats = equippedItem.getWithRandomSuffixStats();
return this.sim.db.getAvailableReforges(withRandomSuffixStats.item).map(reforge => {
return Player.getReforgeData(equippedItem, reforge);
});
return this.sim.db.getAvailableReforges(withRandomSuffixStats.item).map(reforge => equippedItem.getReforgeData(reforge)!);
}

// Returns reforge given an id
getReforge(id: number): ReforgeStat | undefined {
return this.sim.db.getReforgeById(id);
}

static getReforgeData(equippedItem: EquippedItem, reforge: ReforgeStat): ReforgeData {
const withRandomSuffixStats = equippedItem.getWithRandomSuffixStats();
const item = withRandomSuffixStats.item;
const fromAmount = Math.ceil(-item.stats[reforge.fromStat] * reforge.multiplier);
const toAmount = Math.floor(item.stats[reforge.fromStat] * reforge.multiplier);
return {
id: reforge.id,
reforge: reforge,
item: item,
fromStat: reforge.fromStat,
fromAmount: fromAmount,
toStat: reforge.toStat,
toAmount,
};
}

// Returns all enchants that this player can wear in the given slot.
getEnchants(slot: ItemSlot): Array<Enchant> {
return this.sim.db.getEnchants(slot).filter(enchant => canEquipEnchant(enchant, this.playerSpec));
Expand Down
32 changes: 31 additions & 1 deletion ui/core/proto_utils/equipped_item.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { GemColor, ItemRandomSuffix, ItemSpec, ItemType, Profession, ReforgeStat } from '../proto/common.js';
import { GemColor, ItemRandomSuffix, ItemSpec, ItemType, Profession, ReforgeStat, Stat } from '../proto/common.js';
import { UIEnchant as Enchant, UIGem as Gem, UIItem as Item } from '../proto/ui.js';
import { distinct } from '../utils.js';
import { ActionId } from './action_id.js';
Expand All @@ -10,6 +10,16 @@ export function getWeaponDPS(item: Item): number {
return (item.weaponDamageMin + item.weaponDamageMax) / 2 / (item.weaponSpeed || 1);
}

export interface ReforgeData {
id: number;
item: Item;
reforge: ReforgeStat;
fromStat: Stat;
toStat: Stat;
fromAmount: number;
toAmount: number;
}

/**
* Represents an equipped item along with enchants/gems attached to it.
*
Expand Down Expand Up @@ -64,6 +74,26 @@ export class EquippedItem {
return this._gems.map(gem => (gem == null ? null : Gem.clone(gem)));
}

getReforgeData(reforge?: ReforgeStat | null): ReforgeData | null {
reforge = reforge || this.reforge;
if (!reforge) return null;
const { id, fromStat, toStat, multiplier } = reforge;
const withRandomSuffixStats = this.getWithRandomSuffixStats();
const item = withRandomSuffixStats.item;
const fromAmount = Math.ceil(-item.stats[fromStat] * multiplier);
const toAmount = Math.floor(item.stats[fromStat] * multiplier);

return {
id,
reforge,
item,
fromStat,
fromAmount,
toStat,
toAmount,
};
}

equals(other: EquippedItem) {
if (!Item.equals(this._item, other.item)) return false;

Expand Down
7 changes: 3 additions & 4 deletions ui/core/proto_utils/gear.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { Player, ReforgeData } from '../player';
import { EquipmentSpec, GemColor, ItemSlot, ItemSpec, ItemSwap, Profession, SimDatabase, SimEnchant, SimGem, SimItem } from '../proto/common.js';
import { UIEnchant as Enchant, UIGem as Gem, UIItem as Item } from '../proto/ui.js';
import { isBluntWeaponType, isSharpWeaponType } from '../proto_utils/utils.js';
import { distinct, equalsOrBothNull, getEnumValues } from '../utils.js';
import { Database } from './database';
import { EquippedItem } from './equipped_item.js';
import { EquippedItem, ReforgeData } from './equipped_item.js';
import { gemMatchesSocket, isMetaGemActive } from './gems.js';
import { Stats } from './stats.js';
import { validWeaponCombo } from './utils.js';
Expand Down Expand Up @@ -377,8 +376,8 @@ export class Gear extends BaseGear {
getAllReforges() {
const reforgedItems = new Map<ItemSlot, ReforgeData>();
this.getEquippedItems().forEach((item, slot) => {
if (!item?.reforge) return;
const reforgeData = Player.getReforgeData(item, item.reforge);
const reforgeData = item?.getReforgeData();
if (!reforgeData) return;
reforgedItems.set(slot, reforgeData);
});
return reforgedItems;
Expand Down

0 comments on commit b68caea

Please sign in to comment.