diff --git a/Source/stores.cpp b/Source/stores.cpp index e0dbec100c3..0d753a69f5b 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -471,12 +471,12 @@ void SetupErrorScreen(TalkID talkId) void SetupConfirmScreen() { - StartStore(OldActiveStore); // FIXME: Should be Confirm screen instead?? + StartStore(OldActiveStore); ClearTextLines(5, 23); UiFlags itemColor = TempItem.getTextColorWithStatCheck(); SetLineText(20, 8, TempItem.getName(), itemColor, false); - SetLineValue(8, TempItem._iIvalue); + SetLineValue(8, TempItem._iIvalue); // FIXME: Incorrectly displays full item value in cases we should be using displayValue PrintStoreItem(TempItem, 9, itemColor); std::string_view prompt; @@ -752,13 +752,13 @@ void FilterRepairableItems() return itemPtr.isEmpty() || itemPtr._iDurability == itemPtr._iMaxDur || itemPtr._iMaxDur == DUR_INDESTRUCTIBLE; }), playerItems.end()); +} - // Calculate repair costs and update displayValue in the vector - for (IndexedItem &indexedItem : playerItems) { - const Item &itemPtr = *indexedItem.itemPtr; - - indexedItem.displayValue = GetRepairCost(itemPtr); - } +int GetRechargeCost(const Item &item) +{ + int rechargeCost = GetSpellData(item._iSpell).staffCost(); + rechargeCost = (rechargeCost * (item._iMaxCharges - item._iCharges)) / (item._iMaxCharges * 2); + return rechargeCost; } void FilterRechargeableItems() @@ -770,14 +770,11 @@ void FilterRechargeableItems() return itemPtr.isEmpty() || itemPtr._iCharges == itemPtr._iMaxCharges || (itemPtr._itype != ItemType::Staff && itemPtr._iMiscId != IMISC_UNIQUE && itemPtr._iMiscId != IMISC_STAFF); }), playerItems.end()); +} - // Calculate recharge costs and update displayValue in the vector - for (IndexedItem &indexedItem : playerItems) { - const Item &itemPtr = *indexedItem.itemPtr; - int rechargeCost = GetSpellData(itemPtr._iSpell).staffCost(); - rechargeCost = (rechargeCost * (itemPtr._iMaxCharges - itemPtr._iCharges)) / (itemPtr._iMaxCharges * 2); - indexedItem.displayValue = rechargeCost; - } +int GetIdentifyCost() +{ + return 100; } void FilterIdentifiableItems() @@ -789,11 +786,6 @@ void FilterIdentifiableItems() return itemPtr.isEmpty() || itemPtr._iMagical == ITEM_QUALITY_NORMAL || itemPtr._iIdentified; }), playerItems.end()); - - // Set the identification cost for all identifiable items - for (IndexedItem &indexedItem : playerItems) { - indexedItem.displayValue = 100; // Identification cost is 100 gold - } } void FilterPlayerItemsForAction(TalkID talkId) @@ -820,8 +812,7 @@ void FilterPlayerItemsForAction(TalkID talkId) } } -// FIXME: Do we do templated function? -void SetupItemList(TalkID talkId, std::vector &items, int idx, bool selling /*= true*/) +void SetupTownerItemList(TalkID talkId, std::vector &items, int idx, bool selling /*= true*/) { ClearTextLines(5, 21); PreviousScrollPos = 5; @@ -829,13 +820,9 @@ void SetupItemList(TalkID talkId, std::vector &items, int idx, bool sellin int startLine = (TownerId == TOWN_PEGBOY) ? 10 : 5; for (int l = startLine; l < 20 && idx < items.size(); l += 4) { const Item &item = items[idx]; - int price = item._iIdentified ? item._iIvalue : item._ivalue; - - if (TownerId == TOWN_PEGBOY) { // FIXME: Centralize Wirt's logic for price calculation - price = gbIsHellfire ? price - (price / 4) : price + (price / 2); - } - + int price = GetItemCost(item); UiFlags itemColor = item.getTextColorWithStatCheck(); + SetLineText(20, l, item.getName(), itemColor, true, item._iCurs, true); SetLineValue(l, price); PrintStoreItem(item, l + 1, itemColor, true); @@ -851,16 +838,32 @@ void SetupItemList(TalkID talkId, std::vector &items, int idx, bool sellin } } -void SetupItemList(TalkID talkId, std::vector &items, int idx, bool selling /*= true*/) +void SetupPlayerItemList(TalkID talkId, std::vector &items, int idx, bool selling /*= true*/) { ClearTextLines(5, 21); PreviousScrollPos = 5; + int goldAmountDisplay; + for (int l = 5; l < 20 && idx < items.size(); l += 4) { const Item &item = *items[idx].itemPtr; UiFlags itemColor = item.getTextColorWithStatCheck(); SetLineText(20, l, item.getName(), itemColor, true, item._iCurs, true); - SetLineValue(l, items[idx].displayValue); + switch (talkId) { + case TalkID::Sell: + goldAmountDisplay = GetSellPrice(item); + break; + case TalkID::Repair: + goldAmountDisplay = GetRepairCost(item); + break; + case TalkID::Recharge: + goldAmountDisplay = GetRechargeCost(item); + break; + case TalkID::Identify: + goldAmountDisplay = GetIdentifyCost(); + break; + } + SetLineValue(l, goldAmountDisplay); PrintStoreItem(item, l + 1, itemColor, true); NextScrollPos = l; idx++; @@ -874,22 +877,22 @@ void SetupItemList(TalkID talkId, std::vector &items, int idx, bool } } -void SetupTownerItemList(TalkID talkId, int idx, bool selling = true) +void SetupItemList(TalkID talkId, int idx, bool selling = true) { TownerStore *towner = townerStores[TownerId]; switch (talkId) { case TalkID::BasicBuy: - SetupItemList(talkId, towner->basicItems, idx, selling); + SetupTownerItemList(talkId, towner->basicItems, idx, selling); break; case TalkID::Buy: - SetupItemList(talkId, towner->items, idx, selling); + SetupTownerItemList(talkId, towner->items, idx, selling); break; case TalkID::Sell: case TalkID::Repair: case TalkID::Recharge: case TalkID::Identify: - SetupItemList(talkId, playerItems, idx, selling); + SetupPlayerItemList(talkId, playerItems, idx, selling); break; } } @@ -960,7 +963,7 @@ void SetupBuyScreen(TalkID talkId) int itemCount = GetItemCount(talkId); SetLineAsDivider(BuySellMenuDividerLine); - SetupTownerItemList(talkId, ScrollPos); + SetupItemList(talkId, ScrollPos); UpdateItemStatFlags(talkId); NumTextLines = std::max(itemCount - ItemLineSpace, 0); SetBuyScreenHeader(talkId); @@ -988,7 +991,7 @@ void SetupSellScreen(TalkID talkId) SetLineText(20, 1, _("Which item is for sale?"), UiFlags::ColorWhitegold, false); SetLineAsDivider(BuySellMenuDividerLine); - SetupTownerItemList(talkId, ScrollPos, false); + SetupItemList(talkId, ScrollPos, false); AddItemListBackButton(talkId, /*selectable=*/true); } @@ -1019,8 +1022,8 @@ void SetupRepairScreen() SetLineText(20, 1, _("Repair which item?"), UiFlags::ColorWhitegold, false); SetLineAsDivider(BuySellMenuDividerLine); - // Pass the filtered items to SetupTownerItemList for rendering - SetupTownerItemList(TalkID::Repair, ScrollPos, false); + // Pass the filtered items to SetupItemList for rendering + SetupItemList(TalkID::Repair, ScrollPos, false); AddItemListBackButton(TalkID::Repair, /*selectable=*/true); } @@ -1050,8 +1053,8 @@ void SetupRechargeScreen() SetLineText(20, 1, _("Recharge which item?"), UiFlags::ColorWhitegold, false); SetLineAsDivider(3); - // Pass the filtered items to SetupTownerItemList for rendering - SetupTownerItemList(TalkID::Recharge, ScrollPos, false); + // Pass the filtered items to SetupItemList for rendering + SetupItemList(TalkID::Recharge, ScrollPos, false); AddItemListBackButton(TalkID::Recharge); } @@ -1081,8 +1084,8 @@ void SetupIdentifyScreen() SetLineText(20, 1, _("Identify which item?"), UiFlags::ColorWhitegold, false); SetLineAsDivider(3); - // Pass the filtered items to SetupTownerItemList for rendering - SetupTownerItemList(TalkID::Identify, ScrollPos, false); + // Pass the filtered items to SetupItemList for rendering + SetupItemList(TalkID::Identify, ScrollPos, false); AddItemListBackButton(TalkID::Identify); } @@ -1171,6 +1174,17 @@ bool ReturnToMainMenu() return false; } +int GetItemCost(const Item &item) +{ + int price = item._iIdentified ? item._iIvalue : item._ivalue; + + if (TownerId == TOWN_PEGBOY) { + price = gbIsHellfire ? price - (price / 4) : price + (price / 2); + } + + return price; +} + void BuyEnter() { if (ReturnToMainMenu()) @@ -1188,22 +1202,14 @@ void BuyEnter() TownerStore *towner = townerStores[TownerId]; Item &item = (ActiveStore == TalkID::BasicBuy) ? towner->basicItems[idx] : towner->items[idx]; - int price = item._iIvalue; - - if (TownerId == TOWN_PEGBOY) { - if (gbIsHellfire) - price -= item._iIvalue / 4; - else - price += item._iIvalue / 2; - } + int cost = GetItemCost(item); - if (!CanPlayerAfford(item._iIvalue)) { + if (!CanPlayerAfford(cost)) { StartStore(TalkID::NoMoney); } else if (!GiveItemToPlayer(item, false)) { StartStore(TalkID::NoRoom); } else { TempItem = item; - TempItem._iIvalue = price; StartStore(TalkID::Confirm); } } @@ -1222,6 +1228,17 @@ bool StoreGoldFit(Item &item) return cost <= itemRoomForGold + RoomForGold(); } +int GetSellPrice(const Item &item) +{ + int price = item._iIvalue; + + if (item._iMagical != ITEM_QUALITY_NORMAL && item._iIdentified) { + price = price / 2; + } + + return price; +} + /** * @brief Sells an item from the player's inventory or belt. */ @@ -1231,20 +1248,21 @@ void SellItem() IndexedItem &itemToSell = playerItems[idx]; + // Remove the sold item from the player's inventory or belt if (itemToSell.location == ItemLocation::Inventory) { MyPlayer->RemoveInvItem(itemToSell.index); } else if (itemToSell.location == ItemLocation::Belt) { MyPlayer->RemoveSpdBarItem(itemToSell.index); } - int cost = itemToSell.displayValue; + int price = GetSellPrice(*itemToSell.itemPtr); // Remove the sold item from the playerItems vector playerItems.erase(playerItems.begin() + idx); // Add the gold to the player's inventory - AddGoldToInventory(*MyPlayer, cost); - MyPlayer->_pGold += cost; + AddGoldToInventory(*MyPlayer, price); + MyPlayer->_pGold += price; } void SellEnter() @@ -1315,7 +1333,7 @@ void RepairItem() } // Deduct the repair cost from the player's money - TakePlrsMoney(indexedItem.displayValue); + TakePlrsMoney(GetRepairCost(*indexedItem.itemPtr)); } void RepairEnter() @@ -1330,7 +1348,7 @@ void RepairEnter() int idx = GetItemIndex(); // Check if the player can afford the repair cost - if (!CanPlayerAfford(playerItems[idx].displayValue)) { + if (!CanPlayerAfford(GetRepairCost(*playerItems[idx].itemPtr))) { StartStore(TalkID::NoMoney); return; } @@ -1407,7 +1425,7 @@ void BuyItem(Item &item) /** * @brief Recharges an item in the player's inventory or body in the witch. */ -void RechargeItem(int price) +void RechargeItem() { int idx = GetItemIndex(); Item *itemPtr = playerItems[idx].itemPtr; @@ -1429,7 +1447,7 @@ void RechargeItem(int price) } // Deduct the price from the player's gold - TakePlrsMoney(price); + TakePlrsMoney(GetRechargeCost(*playerItems[idx].itemPtr)); // Recalculate the player's inventory CalcPlrInv(*MyPlayer, true); @@ -1448,7 +1466,7 @@ void RechargeEnter() int idx = GetItemIndex(); // Check if the player can afford the recharge cost - if (!CanPlayerAfford(playerItems[idx].displayValue)) { + if (!CanPlayerAfford(GetRechargeCost(*playerItems[idx].itemPtr))) { StartStore(TalkID::NoMoney); return; } @@ -1499,7 +1517,7 @@ void ConfirmEnter(Item &item) RepairItem(); break; case TalkID::Recharge: - RechargeItem(item._iIvalue); + RechargeItem(); break; case TalkID::Identify: IdentifyItem(item); @@ -1534,7 +1552,7 @@ void IdentifyEnter() int idx = GetItemIndex(); // Check if the player can afford the identification cost - if (!CanPlayerAfford(playerItems[idx].displayValue)) { + if (!CanPlayerAfford(GetIdentifyCost())) { StartStore(TalkID::NoMoney); return; } @@ -1847,7 +1865,7 @@ void DrawStoreText(const Surface &out) selling = false; break; } - SetupTownerItemList(ActiveStore, ScrollPos, selling); + SetupItemList(ActiveStore, ScrollPos, selling); } CalculateLineHeights(); diff --git a/Source/stores.h b/Source/stores.h index f767e3edeb0..fc030b56c79 100644 --- a/Source/stores.h +++ b/Source/stores.h @@ -83,7 +83,6 @@ struct IndexedItem { Item *itemPtr; // Pointer to the original item ItemLocation location; // Location in the player's inventory (Inventory, Belt, or Body) int index; // Index in the corresponding array - int displayValue; // Modified value for display purposes }; enum class ResourceType {