diff --git a/Source/items.cpp b/Source/items.cpp index 2f6ce462c..7cacdbc06 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -3816,6 +3816,37 @@ void GetItemStr(Item &item) } } +bool IsItemIdentifiableByStoryteller(const Item &item) +{ + if (item.isEmpty()) { + return false; + } + if (item._iMagical == ITEM_QUALITY_NORMAL) { + return false; + } + return !item._iIdentified; +} + +int CountIdentifiablePlayerItems(const Player &player) +{ + return static_cast(std::count_if(PlayerItemsRange { player }.begin(), PlayerItemsRange { player }.end(), [](const Item &item) { + return IsItemIdentifiableByStoryteller(item); + })); +} + +int IdentifyPlayerItems(Player &player) +{ + const int identifiedItemCount = static_cast(std::count_if(PlayerItemsRange { player }.begin(), PlayerItemsRange { player }.end(), [](Item &item) { + if (!IsItemIdentifiableByStoryteller(item)) { + return false; + } + item._iIdentified = true; + return true; + })); + CalcPlrInv(player, true); + return identifiedItemCount; +} + void CheckIdentify(Player &player, int cii) { Item *pi; diff --git a/Source/items.h b/Source/items.h index 9c855a405..3695fe0c7 100644 --- a/Source/items.h +++ b/Source/items.h @@ -545,6 +545,9 @@ void ProcessItems(); void FreeItemGFX(); void GetItemFrm(Item &item); void GetItemStr(Item &item); +bool IsItemIdentifiableByStoryteller(const Item &item); +int CountIdentifiablePlayerItems(const Player &player); +int IdentifyPlayerItems(Player &player); void CheckIdentify(Player &player, int cii); void DoRepair(Player &player, int cii); void DoRecharge(Player &player, int cii); diff --git a/Source/objects.cpp b/Source/objects.cpp index b489fa3d7..54c7d342e 100644 --- a/Source/objects.cpp +++ b/Source/objects.cpp @@ -2745,13 +2745,7 @@ void OperateShrineGlimmering(Player &player) if (&player != MyPlayer) return; - for (Item &item : PlayerItemsRange { player }) { - if (item._iMagical != ITEM_QUALITY_NORMAL && !item._iIdentified) { - item._iIdentified = true; - } - } - - CalcPlrInv(player, true); + IdentifyPlayerItems(player); RedrawEverything(); InitDiabloMsg(EMSG_SHRINE_GLIMMERING); diff --git a/Source/stores.cpp b/Source/stores.cpp index bd5cb919f..90e6dabfa 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -903,6 +903,16 @@ void StoreConfirm(Item &item) HasScrollbar = false; ClearSText(5, 23); + if (OldActiveStore == TalkID::StorytellerIdentifyAll) { + AddSText(0, 7, _("Identify all items?"), UiFlags::ColorWhite | UiFlags::AlignCenter, false); + AddSText(0, 9, fmt::format(fmt::runtime(_("Cost: {:s} gold")), FormatInteger(item._iIvalue)), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false); + AddSText(0, 12, _("Are you sure you want to"), UiFlags::ColorWhite | UiFlags::AlignCenter, false); + AddSText(0, 14, _("identify all items?"), UiFlags::ColorWhite | UiFlags::AlignCenter, false); + AddSText(0, 17, _("Yes"), UiFlags::ColorWhite | UiFlags::AlignCenter, true); + AddSText(0, 19, _("No"), UiFlags::ColorWhite | UiFlags::AlignCenter, true); + return; + } + const UiFlags itemColor = item.getTextColorWithStatCheck(); AddSText(20, 8, item.getName(), itemColor, false); AddSTextVal(8, item._iIvalue); @@ -917,6 +927,9 @@ void StoreConfirm(Item &item) case TalkID::StorytellerIdentify: prompt = _("Are you sure you want to identify this item?"); break; + case TalkID::StorytellerIdentifyAll: + prompt = _("Are you sure you want to identify all items?"); + break; case TalkID::HealerBuy: case TalkID::SmithPremiumBuy: case TalkID::WitchBuy: @@ -941,6 +954,20 @@ void StoreConfirm(Item &item) AddSText(0, 20, _("No"), UiFlags::ColorWhite | UiFlags::AlignCenter, true); } +void RestoreStoreFromOldState() +{ + if (OldActiveStore == TalkID::StorytellerIdentifyAll) { + StartStore(TalkID::Storyteller); + CurrentTextLine = 16; + ScrollPos = 0; + return; + } + + StartStore(OldActiveStore); + CurrentTextLine = OldTextLine; + ScrollPos = OldScrollPos; +} + void StartBoy() { IsTextFullSize = false; @@ -1050,19 +1077,14 @@ void StartStoryteller() AddSText(0, 9, _("Would you like to:"), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false); AddSText(0, 12, _("Talk to Cain"), UiFlags::ColorBlue | UiFlags::AlignCenter, true); AddSText(0, 14, _("Identify an item"), UiFlags::ColorWhite | UiFlags::AlignCenter, true); + AddSText(0, 16, _("Identify all items"), UiFlags::ColorWhite | UiFlags::AlignCenter, true); AddSText(0, 18, _("Say goodbye"), UiFlags::ColorWhite | UiFlags::AlignCenter, true); AddSLine(5); } bool IdItemOk(Item *i) { - if (i->isEmpty()) { - return false; - } - if (i->_iMagical == ITEM_QUALITY_NORMAL) { - return false; - } - return !i->_iIdentified; + return IsItemIdentifiableByStoryteller(*i); } void AddStoreHoldId(Item itm, int8_t i) @@ -1142,7 +1164,11 @@ void StartStorytellerIdentify() HasScrollbar = false; RenderGold = true; - AddSText(20, 1, _("You have nothing to identify."), UiFlags::ColorWhitegold, false); + if (OldActiveStore == TalkID::StorytellerIdentifyAll) { + AddSText(20, 1, _("There are no items to identify."), UiFlags::ColorWhitegold, false); + } else { + AddSText(20, 1, _("You have nothing to identify."), UiFlags::ColorWhitegold, false); + } AddSLine(3); AddItemListBackButton(/*selectable=*/true); return; @@ -1174,6 +1200,13 @@ void StartStorytellerIdentifyShow(Item &item) AddSText(0, 18, _("Done"), UiFlags::ColorWhite | UiFlags::AlignCenter, true); } +void StorytellerIdentifyAllItems() +{ + Player &myPlayer = *MyPlayer; + TakePlrsMoney(CountIdentifiablePlayerItems(myPlayer) * 100); + IdentifyPlayerItems(myPlayer); +} + void StartTalk() { int la; @@ -1779,6 +1812,11 @@ void ConfirmEnter(Item &item) StorytellerIdentifyItem(item); StartStore(TalkID::StorytellerIdentifyShow); return; + case TalkID::StorytellerIdentifyAll: + StorytellerIdentifyAllItems(); + StartStore(TalkID::Storyteller); + CurrentTextLine = 16; + return; case TalkID::SmithPremiumBuy: SmithBuyPItem(item); break; @@ -1792,6 +1830,12 @@ void ConfirmEnter(Item &item) if (CurrentTextLine == BackButtonLine()) return; + if (OldActiveStore == TalkID::StorytellerIdentifyAll) { + CurrentTextLine = 16; + ScrollPos = 0; + return; + } + CurrentTextLine = OldTextLine; ScrollPos = std::min(OldScrollPos, NumTextLines); @@ -1858,6 +1902,22 @@ void StorytellerEnter() case 14: StartStore(TalkID::StorytellerIdentify); break; + case 16: + OldActiveStore = TalkID::StorytellerIdentifyAll; + OldTextLine = 16; + OldScrollPos = 0; + TempItem.clear(); + TempItem._iIvalue = CountIdentifiablePlayerItems(*MyPlayer) * 100; + if (TempItem._iIvalue == 0) { + StartStore(TalkID::StorytellerIdentify); + return; + } + if (!PlayerCanAfford(TempItem._iIvalue)) { + StartStore(TalkID::NoMoney); + return; + } + StartStore(TalkID::Confirm); + return; case 18: ActiveStore = TalkID::None; break; @@ -1868,7 +1928,7 @@ void StorytellerIdentifyEnter() { if (CurrentTextLine == BackButtonLine()) { StartStore(TalkID::Storyteller); - CurrentTextLine = 14; + CurrentTextLine = OldActiveStore == TalkID::StorytellerIdentifyAll ? 16 : 14; return; } @@ -2293,6 +2353,8 @@ void StartStore(TalkID s) case TalkID::StorytellerIdentify: StartStorytellerIdentify(); break; + case TalkID::StorytellerIdentifyAll: + break; case TalkID::SmithPremiumBuy: if (!StartSmithPremiumBuy()) return; @@ -2438,15 +2500,17 @@ void StoreESC() StartStore(TalkID::Storyteller); CurrentTextLine = 14; break; + case TalkID::StorytellerIdentifyAll: + StartStore(TalkID::Storyteller); + CurrentTextLine = 16; + break; case TalkID::StorytellerIdentifyShow: StartStore(TalkID::StorytellerIdentify); break; case TalkID::NoMoney: case TalkID::NoRoom: case TalkID::Confirm: - StartStore(OldActiveStore); - CurrentTextLine = OldTextLine; - ScrollPos = OldScrollPos; + RestoreStoreFromOldState(); break; case TalkID::None: break; @@ -2610,9 +2674,7 @@ void StoreEnter() break; case TalkID::NoMoney: case TalkID::NoRoom: - StartStore(OldActiveStore); - CurrentTextLine = OldTextLine; - ScrollPos = OldScrollPos; + RestoreStoreFromOldState(); break; case TalkID::Confirm: ConfirmEnter(TempItem); @@ -2635,6 +2697,9 @@ void StoreEnter() case TalkID::StorytellerIdentify: StorytellerIdentifyEnter(); break; + case TalkID::StorytellerIdentifyAll: + StartStore(TalkID::Confirm); + break; case TalkID::Gossip: TalkEnter(); break; diff --git a/Source/stores.h b/Source/stores.h index fc38e00db..86b60adce 100644 --- a/Source/stores.h +++ b/Source/stores.h @@ -54,6 +54,7 @@ enum class TalkID : uint8_t { Storyteller, HealerBuy, StorytellerIdentify, + StorytellerIdentifyAll, SmithPremiumBuy, Gossip, StorytellerIdentifyShow,