Skip to content

Commit

Permalink
Random gear twek
Browse files Browse the repository at this point in the history
Skip items with zzz in name
Fix quest rewarded items check
Skip trinkets, rings, necklaces with no useful stats of any quality
Always use default max level when building equip cache instead of bot max lvl config
Accept no value items into equip cache until lvl 30 instead of 20
Re-add partial upgrade code and a command, for future use (.bot gear=partial)
Re-add bis equip code and a command (.bot gear=best)
Fix vanilla enh shamans to have only 2handed weapons on randomise
Fix finding lower quality items, if default quality could not be found. Should fix cases with low MaxGearLevel values
Add spirit, intellect to shadow priest and resto shaman stat weights with low value, to allow lower level items without spell damage/healing
  • Loading branch information
celguar committed May 12, 2024
1 parent 2fc5a74 commit 81cf86a
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 75 deletions.
140 changes: 74 additions & 66 deletions playerbot/PlayerbotFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1467,7 +1467,7 @@ bool PlayerbotFactory::CanEquipItem(ItemPrototype const* proto, uint32 desiredQu
return true;
}

void PlayerbotFactory::InitEquipment(bool incremental, bool syncWithMaster)
void PlayerbotFactory::InitEquipment(bool incremental, bool syncWithMaster, bool progressive, bool partialUpgrade)
{
uint32 oldGS = ai->GetEquipGearScore(bot, false, false);
uint32 masterGS = 0;
Expand All @@ -1489,7 +1489,11 @@ void PlayerbotFactory::InitEquipment(bool incremental, bool syncWithMaster)

// choose type of weapon
uint32 weaponType = 0;
if (bot->GetLevel() > 40 && (bot->getClass() == CLASS_PRIEST || bot->getClass() == CLASS_MAGE || bot->getClass() == CLASS_WARLOCK || bot->getClass() == CLASS_SHAMAN || specId == 29 || specId == 31))
#ifdef MANGOSBOT_ZERO
if (bot->GetLevel() > 40 && (bot->getClass() == CLASS_PRIEST || bot->getClass() == CLASS_MAGE || bot->getClass() == CLASS_WARLOCK || specId == 20 || specId == 22 || specId == 29 || specId == 31))
#else
if (bot->GetLevel() > 40 && (bot->getClass() == CLASS_PRIEST || bot->getClass() == CLASS_MAGE || bot->getClass() == CLASS_WARLOCK || specId == 20 || specId == 21 || specId == 22 || specId == 29 || specId == 31))
#endif
{
weaponType = sRandomPlayerbotMgr.GetValue(bot, "weaponType");
if (!weaponType || !incremental)
Expand All @@ -1500,64 +1504,64 @@ void PlayerbotFactory::InitEquipment(bool incremental, bool syncWithMaster)
}

// update only limited amount of slots with worst items
//map<uint32, bool> upgradeSlots;
//if (incremental)
//{
// std::vector<uint32> emptySlots;
// std::vector<uint32> itemIds;
// std::map<uint32, uint32> itemSlots;
// uint32 maxSlots = urand(1, 4);
// for (uint8 slot = 0; slot < EQUIPMENT_SLOT_END; ++slot)
// upgradeSlots[slot] = false;

// for (uint8 slot = 0; slot < EQUIPMENT_SLOT_END; ++slot)
// {
// if (slot == EQUIPMENT_SLOT_TABARD/* && !bot->GetGuildId()*/ || slot == EQUIPMENT_SLOT_TRINKET1 || slot == EQUIPMENT_SLOT_TRINKET2)
// continue;

// Item* oldItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, slot);
// if (!oldItem)
// {
// emptySlots.push_back(slot);
// continue;
// }

// ItemPrototype const* proto = oldItem->GetProto();
// if (proto)
// {
// if (proto->ItemLevel >= sPlayerbotAIConfig.randomGearMaxLevel)
// continue;

// itemIds.push_back(proto->ItemId);
// itemSlots[proto->ItemId] = slot;
// }
// }

// std::sort(itemIds.begin(), itemIds.end(), [specId](int a, int b)
// {
// ItemPrototype const* proto1 = sObjectMgr.GetItemPrototype(a);
// ItemPrototype const* proto2 = sObjectMgr.GetItemPrototype(b);
// return proto1->Quality * proto1->ItemLevel <= proto2->Quality * proto2->ItemLevel;
// });

// uint32 counter = 0;
// for (auto emptySlot : emptySlots)
// {
// if (counter > maxSlots)
// break;

// upgradeSlots[emptySlot] = true;
// counter++;
// }
// for (auto itemId : itemIds)
// {
// if (counter > maxSlots)
// break;

// upgradeSlots[itemSlots[itemId]] = true;
// counter++;
// }
//}
std::map<uint32, bool> upgradeSlots;
if (incremental && partialUpgrade)
{
std::vector<uint32> emptySlots;
std::vector<uint32> itemIds;
std::map<uint32, uint32> itemSlots;
uint32 maxSlots = urand(1, 4);
for (uint8 slot = 0; slot < EQUIPMENT_SLOT_END; ++slot)
upgradeSlots[slot] = false;

for (uint8 slot = 0; slot < EQUIPMENT_SLOT_END; ++slot)
{
if (slot == EQUIPMENT_SLOT_TABARD/* && !bot->GetGuildId()*/ || slot == EQUIPMENT_SLOT_BODY || slot == EQUIPMENT_SLOT_TRINKET1 || slot == EQUIPMENT_SLOT_TRINKET2)
continue;

Item* oldItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, slot);
if (!oldItem)
{
emptySlots.push_back(slot);
continue;
}

ItemPrototype const* proto = oldItem->GetProto();
if (proto)
{
if (proto->ItemLevel > sPlayerbotAIConfig.randomGearMaxLevel)
continue;

itemIds.push_back(proto->ItemId);
itemSlots[proto->ItemId] = slot;
}
}

std::sort(itemIds.begin(), itemIds.end(), [specId](int a, int b)
{
ItemPrototype const* proto1 = sObjectMgr.GetItemPrototype(a);
ItemPrototype const* proto2 = sObjectMgr.GetItemPrototype(b);
return proto1->Quality * proto1->ItemLevel <= proto2->Quality * proto2->ItemLevel;
});

uint32 counter = 0;
for (auto emptySlot : emptySlots)
{
if (counter > maxSlots)
break;

upgradeSlots[emptySlot] = true;
counter++;
}
for (auto itemId : itemIds)
{
if (counter > maxSlots)
break;

upgradeSlots[itemSlots[itemId]] = true;
counter++;
}
}

// unavailable legendaries list
std::vector<uint32> lockedItems;
Expand Down Expand Up @@ -1595,13 +1599,13 @@ void PlayerbotFactory::InitEquipment(bool incremental, bool syncWithMaster)
if (slot == EQUIPMENT_SLOT_END || slot == EQUIPMENT_SLOT_TABARD)
continue;

/*if (incremental && upgradeSlots.size() && upgradeSlots[slot] != true && !(slot == EQUIPMENT_SLOT_TRINKET1 || slot == EQUIPMENT_SLOT_TRINKET2))
continue;*/
if (incremental && upgradeSlots.size() && upgradeSlots[slot] != true && !(slot == EQUIPMENT_SLOT_TRINKET1 || slot == EQUIPMENT_SLOT_TRINKET2))
continue;

uint32 searchLevel = level;
uint32 quality = ITEM_QUALITY_POOR;
uint32 maxItemLevel = sPlayerbotAIConfig.randomGearMaxLevel;
bool progressiveGear = sPlayerbotAIConfig.randomGearProgression;
bool progressiveGear = progressive;
if(syncWithMaster && ai->GetMaster())
{
maxItemLevel = masterGS + sPlayerbotAIConfig.randomGearMaxDiff;
Expand Down Expand Up @@ -1714,7 +1718,7 @@ void PlayerbotFactory::InitEquipment(bool incremental, bool syncWithMaster)
if (proto->MaxCount && bot->HasItemCount(proto->ItemId, proto->MaxCount))
continue;

if (proto->ItemLevel > sPlayerbotAIConfig.randomGearMaxLevel)
if (proto->ItemLevel > maxItemLevel)
continue;

Item* oldItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, slot);
Expand Down Expand Up @@ -1787,7 +1791,11 @@ void PlayerbotFactory::InitEquipment(bool incremental, bool syncWithMaster)
}

// add weapons for dual wield
#ifdef MANGOSBOT_ZERO
if (slot == EQUIPMENT_SLOT_MAINHAND && (bot->getClass() == CLASS_ROGUE || specId == 2))
#else
if (slot == EQUIPMENT_SLOT_MAINHAND && (bot->getClass() == CLASS_ROGUE || specId == 2 || specId == 21))
#endif
{
std::vector<uint32> oneHanded = sRandomItemMgr.Query(level, bot->getClass(), uint8(specId), EQUIPMENT_SLOT_OFFHAND, q);
if (oneHanded.size())
Expand Down Expand Up @@ -2019,11 +2027,11 @@ void PlayerbotFactory::InitEquipment(bool incremental, bool syncWithMaster)
}
}

if (/*!incremental && */quality == ITEM_QUALITY_EPIC)
if (!found && quality > ITEM_QUALITY_NORMAL)
quality--;

attempts++;
} while (!found && attempts < 2/* && (progressiveGear ? (quality != ITEM_QUALITY_ARTIFACT) : (quality != ITEM_QUALITY_POOR))*/);
} while (!found && attempts < 3 && quality != ITEM_QUALITY_POOR);
if (!found)
{
if (slot != EQUIPMENT_SLOT_TRINKET1 && slot != EQUIPMENT_SLOT_TRINKET2)
Expand Down
4 changes: 3 additions & 1 deletion playerbot/PlayerbotFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ class PlayerbotFactory
void InitSkills();
void EnchantEquipment();
void EquipGear() { return InitEquipment(false, false); }
void EquipGearBest() { return InitEquipment(false, false, false); }
void EquipGearPartialUpgrade() { return InitEquipment(false, false, true, true); }
void UpgradeGear(bool syncWithMaster) { return InitEquipment(!syncWithMaster, syncWithMaster); }
void AddReagents() { return InitReagents(); }
void AddPotions() { return InitPotions(); }
Expand All @@ -68,7 +70,7 @@ class PlayerbotFactory
private:
void Prepare();
void InitSecondEquipmentSet();
void InitEquipment(bool incremental, bool syncWithMaster);
void InitEquipment(bool incremental, bool syncWithMaster, bool progressive = sPlayerbotAIConfig.randomGearProgression, bool partialUpgrade = false);
void InitEquipmentNew(bool incremental);
bool CanEquipItem(ItemPrototype const* proto, uint32 desiredQuality);
bool CanEquipUnseenItem(uint8 slot, uint16 &dest, uint32 item);
Expand Down
12 changes: 12 additions & 0 deletions playerbot/PlayerbotMgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,18 @@ std::string PlayerbotHolder::ProcessBotCommand(std::string cmd, ObjectGuid guid,
factory.UpgradeGear(syncWithMaster);
return "gear upgraded";
}
if (cmd == "equip=best" || cmd == "gear=best")
{
PlayerbotFactory factory(bot, bot->GetLevel());
factory.EquipGearBest();
return "random best gear equipped";
}
if (cmd == "equip=partial" || cmd == "gear=partial")
{
PlayerbotFactory factory(bot, bot->GetLevel());
factory.EquipGearPartialUpgrade();
return "random gear upgraded to some slots";
}
if (cmd == "train" || cmd == "learn")
{
#ifndef MANGOSBOT_ONE
Expand Down
18 changes: 11 additions & 7 deletions playerbot/RandomItemMgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1034,7 +1034,9 @@ void RandomItemMgr::BuildItemInfoCache()
strstr(proto->Name1, "Unused ") ||
strstr(proto->Name1, "Monster ") ||
strstr(proto->Name1, "[PH]") ||
strstr(proto->Name1, "(OLD)")
strstr(proto->Name1, "(OLD)") ||
strstr(proto->Name1, "zzz") ||
strstr(proto->Name1, "ZZZ")
)
continue;

Expand Down Expand Up @@ -1640,7 +1642,7 @@ uint32 RandomItemMgr::CalculateStatWeight(uint8 playerclass, uint8 spec, ItemPro
uint32 effectAuraHealStatWeight = 0;
uint32 effectAuraDamageStatWeight = 0;

for (uint32 j = 0; j < MAX_EFFECT_INDEX; j++)
for (uint8 j = 0; j < MAX_EFFECT_INDEX; ++j)
{
if ((spellproto->Effect[j] == SPELL_EFFECT_APPLY_AURA) &&
(spellproto->EffectBasePoints[j] >= 0))
Expand Down Expand Up @@ -2984,6 +2986,10 @@ uint32 RandomItemMgr::GetLiveStatWeight(Player* player, uint32 itemId, uint32 sp
// check if quest is inactive (if linked to a not running game event)
if (!quest->IsActive())
canDoQuest = false;

// can be rewarded
if (canDoQuest)
break;
}
}
if (!canDoQuest)
Expand Down Expand Up @@ -3043,7 +3049,7 @@ uint32 RandomItemMgr::GetLiveStatWeight(Player* player, uint32 itemId, uint32 sp
return 0;

// skip no stats trinkets
if (info->weights[specId] == 1 && info->quality > ITEM_QUALITY_RARE && (
if (info->weights[specId] == 1 && (
info->slot == EQUIPMENT_SLOT_NECK ||
info->slot == EQUIPMENT_SLOT_TRINKET1 ||
info->slot == EQUIPMENT_SLOT_TRINKET2 ||
Expand Down Expand Up @@ -3088,9 +3094,7 @@ uint32 RandomItemMgr::GetLiveStatWeight(Player* player, uint32 itemId, uint32 sp

void RandomItemMgr::BuildEquipCache()
{
uint32 maxLevel = sPlayerbotAIConfig.randomBotMaxLevel;
if (maxLevel > sWorld.getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL))
maxLevel = sWorld.getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL);
uint32 maxLevel = DEFAULT_MAX_LEVEL;

auto results = CharacterDatabase.PQuery("select clazz, spec, lvl, slot, quality, item from ai_playerbot_equip_cache");
if (results)
Expand Down Expand Up @@ -3196,7 +3200,7 @@ void RandomItemMgr::BuildEquipCache()
continue;

// only accept "useless" items if bot level <= 30
if (statWeight == 1 && level > 20)
if (statWeight == 1 && level > 30)
continue;

uint32 minLevel = GetMinLevelFromCache(itemId);
Expand Down
6 changes: 5 additions & 1 deletion sql/world/classic/ai_playerbot_weightscales.sql
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,11 @@ INSERT INTO `ai_playerbot_weightscale_data` (`id`, `field`, `val`) VALUES
(10, 'mledps', 10),
(11, 'mledps', 10),
(1, 'mledps', 28),
(2, 'mledps', 28);
(2, 'mledps', 28),
(15, 'int', 2),
(15, 'spi', 1),
(15, 'manargn', 1),
(22, 'spi', 1);
/*!40000 ALTER TABLE `ai_playerbot_weightscale_data` ENABLE KEYS */;

/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
Expand Down

0 comments on commit 81cf86a

Please sign in to comment.