diff --git a/Source/items.cpp b/Source/items.cpp index f136bff40df8..cb87e49efdaf 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -4585,11 +4585,39 @@ std::string DebugSpawnItem(std::string itemName) Item testItem; + // get all valid monster levels + std::vector monsterLevels {}; + for (int16_t i = 0; i < static_cast(NUM_MTYPES); i++) { + const auto &monsterData = MonstersData[i]; + auto monsterLevel = static_cast(monsterData.level); + + if (i == MT_DIABLO) { + if (!gbIsHellfire) { + // Adjust The Dark Lord's mlvl if the item isn't a Hellfire item to match the Diablo mlvl + monsterLevel -= 15; + } + } else { + if (monsterData.availability == MonsterAvailability::Never) { + // Skip monsters that are unable to appear in the game + continue; + } + if (!gbIsHellfire && monsterData.minDunLvl > 16) { + // Skip hellfire monsters in diablo + continue; + } + } + + if (std::find(monsterLevels.begin(), monsterLevels.end(), monsterLevel) == monsterLevels.end()) { + monsterLevels.push_back(monsterLevel); + } + } + uint32_t begin = SDL_GetTicks(); int i = 0; for (;; i++) { // using a better rng here to seed the item to prevent getting stuck repeating same values using old one std::uniform_int_distribution dist(0, INT_MAX); + std::uniform_int_distribution distLevel(0, static_cast(monsterLevels.size()) - 1); SetRndSeed(dist(BetterRng)); if (SDL_GetTicks() - begin > max_time) return StrCat("Item not found in ", max_time / 1000, " seconds!"); @@ -4597,7 +4625,7 @@ std::string DebugSpawnItem(std::string itemName) if (i > max_iter) return StrCat("Item not found in ", max_iter, " tries!"); - const int8_t monsterLevel = dist(BetterRng) % CF_LEVEL + 1; + const int8_t monsterLevel = monsterLevels[distLevel(BetterRng)]; _item_indexes idx = RndItemForMonsterLevel(monsterLevel); if (IsAnyOf(idx, IDI_NONE, IDI_GOLD)) continue; @@ -4605,6 +4633,8 @@ std::string DebugSpawnItem(std::string itemName) testItem = {}; SetupAllItems(*MyPlayer, testItem, idx, AdvanceRndSeed(), monsterLevel, 1, false, false, false); + assert(IsDungeonItemValid(testItem._iCreateInfo, testItem.dwBuff)); + std::string tmp = AsciiStrToLower(testItem._iIName); if (tmp.find(itemName) != std::string::npos) break;