diff --git a/Source/objects.cpp b/Source/objects.cpp index b489fa3d7..9df7e80b6 100644 --- a/Source/objects.cpp +++ b/Source/objects.cpp @@ -2247,6 +2247,11 @@ void OperatePedestal(Player &player, Object &pedestal, bool sendmsg) } } +int ClampU8(int v) +{ + return std::clamp(v, 0, 255); +} + void OperateShrineMysterious(DiabloGenerator &rng, Player &player) { if (&player != MyPlayer) @@ -2284,43 +2289,32 @@ void OperateShrineHidden(DiabloGenerator &rng, Player &player) if (&player != MyPlayer) return; - int cnt = 0; - for (const auto &item : player.InvBody) { - if (!item.isEmpty()) - cnt++; + std::array eligible {}; + int eligibleCount = 0; + + for (int i = 0; i < NUM_INVLOC; i++) { + const Item &it = player.InvBody[i]; + if (!it.isEmpty() && IsNoneOf(it._iMaxDur, 0, DUR_INDESTRUCTIBLE)) + eligible[eligibleCount++] = i; } - if (cnt > 0) { - for (auto &item : player.InvBody) { - if (!item.isEmpty() - && item._iMaxDur != DUR_INDESTRUCTIBLE - && item._iMaxDur != 0) { - item._iDurability += 10; - item._iMaxDur += 10; - if (item._iDurability > item._iMaxDur) - item._iDurability = item._iMaxDur; - } - } - while (true) { - cnt = 0; - for (auto &item : player.InvBody) { - if (!item.isEmpty() && item._iMaxDur != DUR_INDESTRUCTIBLE && item._iMaxDur != 0) { - cnt++; - } - } - if (cnt == 0) - break; - const int r = rng.generateRnd(NUM_INVLOC); - if (player.InvBody[r].isEmpty() || player.InvBody[r]._iMaxDur == DUR_INDESTRUCTIBLE || player.InvBody[r]._iMaxDur == 0) - continue; - player.InvBody[r]._iDurability -= 20; - player.InvBody[r]._iMaxDur -= 20; - if (player.InvBody[r]._iDurability <= 0) - player.InvBody[r]._iDurability = 1; - if (player.InvBody[r]._iMaxDur <= 0) - player.InvBody[r]._iMaxDur = 1; - break; - } + if (eligibleCount == 0) { + InitDiabloMsg(EMSG_SHRINE_HIDDEN); + return; + } + + // Pick the one item that will receive the net -10 effect. + const int cursedSlot = eligible[rng.generateRnd(eligibleCount)]; + + for (int k = 0; k < eligibleCount; k++) { + Item &it = player.InvBody[eligible[k]]; + const int delta = (eligible[k] == cursedSlot) ? -10 : 10; + it._iMaxDur = ClampU8(it._iMaxDur + delta); + if (it._iMaxDur == 0) + it._iMaxDur = 1; + it._iDurability = ClampU8(it._iDurability + delta); + if (it._iDurability == 0) + it._iDurability = 1; } InitDiabloMsg(EMSG_SHRINE_HIDDEN);