|
6 | 6 | #include "items.h"
|
7 | 7 |
|
8 | 8 | #include <algorithm>
|
9 |
| -#ifdef _DEBUG |
10 |
| -#include <random> |
11 |
| -#endif |
| 9 | +#include <array> |
| 10 | +#include <cassert> |
12 | 11 | #include <climits>
|
| 12 | +#include <cstddef> |
13 | 13 | #include <cstdint>
|
14 |
| - |
| 14 | +#include <cstring> |
| 15 | +#include <optional> |
| 16 | +#include <string> |
| 17 | +#include <string_view> |
| 18 | +#include <type_traits> |
| 19 | +#include <utility> |
| 20 | +#include <vector> |
| 21 | + |
| 22 | +#include <SDL.h> |
15 | 23 | #include <fmt/core.h>
|
16 |
| -#include <fmt/format.h> |
17 | 24 |
|
18 | 25 | #include "DiabloUI/ui_flags.hpp"
|
| 26 | +#include "control.h" |
19 | 27 | #include "controls/control_mode.hpp"
|
20 |
| -#include "controls/plrctrls.h" |
| 28 | +#include "controls/controller_buttons.h" |
21 | 29 | #include "cursor.h"
|
| 30 | +#include "diablo.h" |
22 | 31 | #include "doom.h"
|
| 32 | +#include "effects.h" |
| 33 | +#include "engine/animationinfo.h" |
23 | 34 | #include "engine/backbuffer_state.hpp"
|
24 | 35 | #include "engine/clx_sprite.hpp"
|
25 |
| -#include "engine/dx.h" |
26 | 36 | #include "engine/load_cel.hpp"
|
| 37 | +#include "engine/path.h" |
| 38 | +#include "engine/point.hpp" |
27 | 39 | #include "engine/random.hpp"
|
28 | 40 | #include "engine/render/clx_render.hpp"
|
29 | 41 | #include "engine/render/primitive_render.hpp"
|
30 | 42 | #include "engine/render/text_render.hpp"
|
| 43 | +#include "engine/surface.hpp" |
| 44 | +#include "engine/world_tile.hpp" |
| 45 | +#include "function_ref.hpp" |
31 | 46 | #include "game_mode.hpp"
|
32 | 47 | #include "headless_mode.hpp"
|
| 48 | +#include "inv.h" |
33 | 49 | #include "inv_iterators.hpp"
|
| 50 | +#include "itemdat.h" |
| 51 | +#include "items/validation.h" |
| 52 | +#include "levels/gendung.h" |
| 53 | +#include "levels/gendung_defs.hpp" |
34 | 54 | #include "levels/tile_properties.hpp"
|
35 | 55 | #include "levels/town.h"
|
36 | 56 | #include "lighting.h"
|
37 | 57 | #include "minitext.h"
|
38 |
| -#include "missiles.h" |
| 58 | +#include "monstdat.h" |
| 59 | +#include "monster.h" |
| 60 | +#include "msg.h" |
| 61 | +#include "multi.h" |
| 62 | +#include "objdat.h" |
| 63 | +#include "objects.h" |
39 | 64 | #include "options.h"
|
| 65 | +#include "pack.h" |
40 | 66 | #include "panels/info_box.hpp"
|
41 | 67 | #include "panels/ui_panels.hpp"
|
42 | 68 | #include "player.h"
|
43 | 69 | #include "playerdat.hpp"
|
44 | 70 | #include "qol/stash.h"
|
| 71 | +#include "quests.h" |
| 72 | +#include "sound_effect_enums.h" |
| 73 | +#include "spelldat.h" |
45 | 74 | #include "spells.h"
|
46 | 75 | #include "stores.h"
|
47 |
| -#include "utils/algorithm/container.hpp" |
| 76 | +#include "textdat.h" |
| 77 | +#include "utils/enum_traits.h" |
48 | 78 | #include "utils/format_int.hpp"
|
49 | 79 | #include "utils/is_of.hpp"
|
50 | 80 | #include "utils/language.h"
|
51 | 81 | #include "utils/log.hpp"
|
52 | 82 | #include "utils/math.h"
|
53 |
| -#include "utils/str_case.hpp" |
| 83 | +#include "utils/sdl_geometry.h" |
| 84 | +#include "utils/static_vector.hpp" |
54 | 85 | #include "utils/str_cat.hpp"
|
55 | 86 | #include "utils/str_split.hpp"
|
| 87 | +#include "utils/string_or_view.hpp" |
56 | 88 | #include "utils/utf8.hpp"
|
57 | 89 |
|
58 | 90 | namespace devilution {
|
@@ -1005,7 +1037,7 @@ int PLVal(int pv, int p1, int p2, int minv, int maxv)
|
1005 | 1037 | return minv;
|
1006 | 1038 | if (minv == maxv)
|
1007 | 1039 | return minv;
|
1008 |
| - return minv + (maxv - minv) * (100 * (pv - p1) / (p2 - p1)) / 100; |
| 1040 | + return minv + ((maxv - minv) * (100 * (pv - p1) / (p2 - p1)) / 100); |
1009 | 1041 | }
|
1010 | 1042 |
|
1011 | 1043 | void SaveItemAffix(const Player &player, Item &item, const PLStruct &affix)
|
@@ -1121,10 +1153,12 @@ std::string GenerateMagicItemName(const std::string_view &baseNamel, const PLStr
|
1121 | 1153 | if (pPrefix != nullptr && pSufix != nullptr) {
|
1122 | 1154 | const std::string_view fmt = translate ? _(/* TRANSLATORS: Constructs item names. Format: {Prefix} {Item} of {Suffix}. Example: King's Long Sword of the Whale */ "{0} {1} of {2}") : "{0} {1} of {2}";
|
1123 | 1155 | return fmt::format(fmt::runtime(fmt), translate ? _(pPrefix->PLName) : pPrefix->PLName, baseNamel, translate ? _(pSufix->PLName) : pSufix->PLName);
|
1124 |
| - } else if (pPrefix != nullptr) { |
| 1156 | + } |
| 1157 | + if (pPrefix != nullptr) { |
1125 | 1158 | const std::string_view fmt = translate ? _(/* TRANSLATORS: Constructs item names. Format: {Prefix} {Item}. Example: King's Long Sword */ "{0} {1}") : "{0} {1}";
|
1126 | 1159 | return fmt::format(fmt::runtime(fmt), translate ? _(pPrefix->PLName) : pPrefix->PLName, baseNamel);
|
1127 |
| - } else if (pSufix != nullptr) { |
| 1160 | + } |
| 1161 | + if (pSufix != nullptr) { |
1128 | 1162 | const std::string_view fmt = translate ? _(/* TRANSLATORS: Constructs item names. Format: {Item} of {Suffix}. Example: Long Sword of the Whale */ "{0} of {1}") : "{0} of {1}";
|
1129 | 1163 | return fmt::format(fmt::runtime(fmt), baseNamel, translate ? _(pSufix->PLName) : pSufix->PLName);
|
1130 | 1164 | }
|
@@ -1269,8 +1303,7 @@ void GetOilType(Item &item, int maxLvl)
|
1269 | 1303 |
|
1270 | 1304 | void GetItemBonus(const Player &player, Item &item, int minlvl, int maxlvl, bool onlygood, bool allowspells)
|
1271 | 1305 | {
|
1272 |
| - if (minlvl > 25) |
1273 |
| - minlvl = 25; |
| 1306 | + minlvl = std::min(minlvl, 25); |
1274 | 1307 |
|
1275 | 1308 | switch (item._itype) {
|
1276 | 1309 | case ItemType::Sword:
|
@@ -1331,7 +1364,7 @@ _item_indexes GetItemIndexForDroppableItem(bool considerDropRate, tl::function_r
|
1331 | 1364 | cumulativeWeight += considerDropRate ? item.dropRate : 1;
|
1332 | 1365 | ril.push_back({ static_cast<_item_indexes>(i), cumulativeWeight });
|
1333 | 1366 | }
|
1334 |
| - const unsigned targetWeight = static_cast<unsigned>(RandomIntLessThan(static_cast<int>(cumulativeWeight))); |
| 1367 | + const auto targetWeight = static_cast<unsigned>(RandomIntLessThan(static_cast<int>(cumulativeWeight))); |
1335 | 1368 | return std::upper_bound(ril.begin(), ril.end(), targetWeight, [](unsigned target, const WeightedItemIndex &value) { return target < value.cumulativeWeight; })->index;
|
1336 | 1369 | }
|
1337 | 1370 |
|
@@ -1830,7 +1863,7 @@ void PrintItemInfo(const Item &item)
|
1830 | 1863 | }
|
1831 | 1864 | }
|
1832 | 1865 |
|
1833 |
| -bool SmithItemOk(const Player &player, const ItemData &item) |
| 1866 | +bool SmithItemOk(const Player & /*player*/, const ItemData &item) |
1834 | 1867 | {
|
1835 | 1868 | if (item.itype == ItemType::Misc)
|
1836 | 1869 | return false;
|
@@ -1872,7 +1905,7 @@ void SortVendor(Item *itemList, size_t count)
|
1872 | 1905 | std::sort(itemList, itemList + count, cmp);
|
1873 | 1906 | }
|
1874 | 1907 |
|
1875 |
| -bool PremiumItemOk(const Player &player, const ItemData &item) |
| 1908 | +bool PremiumItemOk(const Player & /*player*/, const ItemData &item) |
1876 | 1909 | {
|
1877 | 1910 | if (item.itype == ItemType::Misc)
|
1878 | 1911 | return false;
|
@@ -1971,7 +2004,7 @@ void SpawnOnePremium(Item &premiumItem, int plvl, const Player &player)
|
1971 | 2004 | premiumItem._iStatFlag = player.CanUseItem(premiumItem);
|
1972 | 2005 | }
|
1973 | 2006 |
|
1974 |
| -bool WitchItemOk(const Player &player, const ItemData &item) |
| 2007 | +bool WitchItemOk(const Player & /*player*/, const ItemData &item) |
1975 | 2008 | {
|
1976 | 2009 | if (IsNoneOf(item.itype, ItemType::Misc, ItemType::Staff))
|
1977 | 2010 | return false;
|
@@ -2178,12 +2211,15 @@ StringOrView GetTranslatedItemName(const Item &item)
|
2178 | 2211 |
|
2179 | 2212 | if (item._iCreateInfo == 0) {
|
2180 | 2213 | return _(baseItemData.iName);
|
2181 |
| - } else if (item._iMiscId == IMISC_BOOK) { |
| 2214 | + } |
| 2215 | + if (item._iMiscId == IMISC_BOOK) { |
2182 | 2216 | const std::string_view spellName = pgettext("spell", GetSpellData(item._iSpell).sNameText);
|
2183 | 2217 | return fmt::format(fmt::runtime(_(/* TRANSLATORS: {:s} will be a spell name */ "Book of {:s}")), spellName);
|
2184 |
| - } else if (item._iMiscId == IMISC_EAR) { |
| 2218 | + } |
| 2219 | + if (item._iMiscId == IMISC_EAR) { |
2185 | 2220 | return fmt::format(fmt::runtime(_(/* TRANSLATORS: {:s} will be a Character Name */ "Ear of {:s}")), item._iIName);
|
2186 |
| - } else if (item._iMiscId > IMISC_OILFIRST && item._iMiscId < IMISC_OILLAST) { |
| 2221 | + } |
| 2222 | + if (item._iMiscId > IMISC_OILFIRST && item._iMiscId < IMISC_OILLAST) { |
2187 | 2223 | for (size_t i = 0; i < 10; i++) {
|
2188 | 2224 | if (OilMagic[i] != item._iMiscId)
|
2189 | 2225 | continue;
|
@@ -2229,14 +2265,13 @@ std::string GetTranslatedItemNameMagical(const Item &item, bool hellfireItem, bo
|
2229 | 2265 | maxlvl = iblvl;
|
2230 | 2266 | } else {
|
2231 | 2267 | DiscardRandomValues(1); // GetItemAttrs
|
2232 |
| - const int iblvl = GetItemBLevel(lvl, item._iMiscId, onlygood, item._iCreateInfo & CF_UPER15); |
| 2268 | + const int iblvl = GetItemBLevel(lvl, item._iMiscId, onlygood, (item._iCreateInfo & CF_UPER15) != 0); |
2233 | 2269 | minlvl = iblvl / 2;
|
2234 | 2270 | maxlvl = iblvl;
|
2235 | 2271 | DiscardRandomValues(1); // CheckUnique
|
2236 | 2272 | }
|
2237 | 2273 |
|
2238 |
| - if (minlvl > 25) |
2239 |
| - minlvl = 25; |
| 2274 | + minlvl = std::min(minlvl, 25); |
2240 | 2275 |
|
2241 | 2276 | AffixItemType affixItemType = AffixItemType::None;
|
2242 | 2277 |
|
@@ -2900,7 +2935,7 @@ void InitializeItem(Item &item, _item_indexes itemData)
|
2900 | 2935 | item._iPrePower = IPL_INVALID;
|
2901 | 2936 | item._iSufPower = IPL_INVALID;
|
2902 | 2937 | item._iMagical = ITEM_QUALITY_NORMAL;
|
2903 |
| - item.IDidx = static_cast<_item_indexes>(itemData); |
| 2938 | + item.IDidx = itemData; |
2904 | 2939 | if (gbIsHellfire)
|
2905 | 2940 | item.dwBuff |= CF_HELLFIRE;
|
2906 | 2941 | }
|
@@ -3046,13 +3081,13 @@ uint8_t PlaceItemInWorld(Item &&item, WorldTilePosition position)
|
3046 | 3081 | ActiveItemCount++;
|
3047 | 3082 |
|
3048 | 3083 | dItem[position.x][position.y] = static_cast<int8_t>(ii + 1);
|
3049 |
| - auto &item_ = Items[ii]; |
3050 |
| - item_ = std::move(item); |
3051 |
| - item_.position = position; |
3052 |
| - RespawnItem(item_, true); |
| 3084 | + auto &newItem = Items[ii]; |
| 3085 | + newItem = std::move(item); |
| 3086 | + newItem.position = position; |
| 3087 | + RespawnItem(newItem, true); |
3053 | 3088 |
|
3054 | 3089 | if (CornerStone.isAvailable() && position == CornerStone.position) {
|
3055 |
| - CornerStone.item = item_; |
| 3090 | + CornerStone.item = newItem; |
3056 | 3091 | InitQTextMsg(TEXT_CORNSTN);
|
3057 | 3092 | Quests[Q_CORNSTN]._qactive = QUEST_DONE;
|
3058 | 3093 | }
|
@@ -3371,7 +3406,8 @@ void SpawnItem(Monster &monster, Point position, bool sendmsg, bool spawn /*= fa
|
3371 | 3406 | if (uniqueItem != nullptr && sendmsg)
|
3372 | 3407 | NetSendCmdPItem(false, CMD_DROPITEM, uniqueItem->position, *uniqueItem);
|
3373 | 3408 | return;
|
3374 |
| - } else if (monster.isUnique() || dropsSpecialTreasure) { |
| 3409 | + } |
| 3410 | + if (monster.isUnique() || dropsSpecialTreasure) { |
3375 | 3411 | // Unique monster is killed => use better item base (for example no gold)
|
3376 | 3412 | idx = RndUItem(&monster);
|
3377 | 3413 | } else if (dropBrain && !gbIsMultiplayer) {
|
@@ -3408,7 +3444,7 @@ void SpawnItem(Monster &monster, Point position, bool sendmsg, bool spawn /*= fa
|
3408 | 3444 | const int uper = monster.isUnique() ? 15 : 1;
|
3409 | 3445 |
|
3410 | 3446 | const int8_t mLevel = monster.data().level;
|
3411 |
| - SetupAllItems(*MyPlayer, item, idx, AdvanceRndSeed(), mLevel, uper, onlygood, false, false); |
| 3447 | + SetupAllItems(*MyPlayer, item, idx, AdvanceRndSeed(), mLevel, uper, onlygood, false); |
3412 | 3448 | TryRandomUniqueItem(item, idx, mLevel, uper, onlygood, false);
|
3413 | 3449 | SetupItem(item);
|
3414 | 3450 |
|
@@ -4041,7 +4077,7 @@ void DrawUniqueInfo(const Surface &out)
|
4041 | 4077 | DrawString(out, _(uitem.UIName), rect, { .flags = UiFlags::AlignCenter });
|
4042 | 4078 |
|
4043 | 4079 | const Rectangle dividerLineRect { position + Displacement { 26, 25 }, { 267, 3 } };
|
4044 |
| - out.BlitFrom(out, MakeSdlRect(dividerLineRect), dividerLineRect.position + Displacement { 0, 5 * 12 + 13 }); |
| 4080 | + out.BlitFrom(out, MakeSdlRect(dividerLineRect), dividerLineRect.position + Displacement { 0, (5 * 12) + 13 }); |
4045 | 4081 |
|
4046 | 4082 | rect.position.y += (10 - uitem.UINumPL) * 12;
|
4047 | 4083 | assert(uitem.UINumPL <= sizeof(uitem.powers) / sizeof(*uitem.powers));
|
@@ -4781,13 +4817,14 @@ StringOrView Item::getName() const
|
4781 | 4817 | {
|
4782 | 4818 | if (isEmpty()) {
|
4783 | 4819 | return std::string_view("");
|
4784 |
| - } else if (!_iIdentified || _iCreateInfo == 0 || _iMagical == ITEM_QUALITY_NORMAL) { |
| 4820 | + } |
| 4821 | + if (!_iIdentified || _iCreateInfo == 0 || _iMagical == ITEM_QUALITY_NORMAL) { |
4785 | 4822 | return GetTranslatedItemName(*this);
|
4786 |
| - } else if (_iMagical == ITEM_QUALITY_UNIQUE) { |
| 4823 | + } |
| 4824 | + if (_iMagical == ITEM_QUALITY_UNIQUE) { |
4787 | 4825 | return _(UniqueItems[_iUid].UIName);
|
4788 |
| - } else { |
4789 |
| - return GetTranslatedItemNameMagical(*this, dwBuff & CF_HELLFIRE, true, std::nullopt); |
4790 | 4826 | }
|
| 4827 | + return GetTranslatedItemNameMagical(*this, dwBuff & CF_HELLFIRE, true, std::nullopt); |
4791 | 4828 | }
|
4792 | 4829 |
|
4793 | 4830 | bool CornerStoneStruct::isAvailable()
|
@@ -4978,7 +5015,7 @@ void UpdateHellfireFlag(Item &item, const char *identifiedItemName)
|
4978 | 5015 | // But vanilla hellfire items don't have CF_HELLFIRE set in Item::dwBuff
|
4979 | 5016 | // This functions tries to set this flag for vanilla hellfire items based on the item name
|
4980 | 5017 | // This ensures that Item::getName() returns the correct translated item name
|
4981 |
| - if (item.dwBuff & CF_HELLFIRE) |
| 5018 | + if ((item.dwBuff & CF_HELLFIRE) != 0U) |
4982 | 5019 | return; // Item is already a hellfire item
|
4983 | 5020 | if (item._iMagical != ITEM_QUALITY_MAGIC)
|
4984 | 5021 | return; // Only magic item's name can differ between diablo and hellfire
|
|
0 commit comments