mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
Calculation of the power of items with random properties (#1312)
* Score calculation of item random property * Equip auto repair on repop * Item random property calculation * Random Property calculation
This commit is contained in:
@@ -305,6 +305,49 @@ ItemIds ChatHelper::parseItems(std::string const text)
|
||||
return itemIds;
|
||||
}
|
||||
|
||||
ItemWithRandomProperty ChatHelper::parseItemWithRandomProperty(std::string const text)
|
||||
{
|
||||
ItemWithRandomProperty res;
|
||||
|
||||
size_t itemStart = text.find("Hitem:");
|
||||
if (itemStart == std::string::npos)
|
||||
return res;
|
||||
|
||||
itemStart += 6;
|
||||
if (itemStart >= text.length())
|
||||
return res;
|
||||
|
||||
size_t colonPos = text.find(':', itemStart);
|
||||
if (colonPos == std::string::npos)
|
||||
return res;
|
||||
|
||||
std::string itemIdStr = text.substr(itemStart, colonPos - itemStart);
|
||||
res.itemId = atoi(itemIdStr.c_str());
|
||||
|
||||
std::vector<std::string> params;
|
||||
size_t currentPos = colonPos + 1;
|
||||
|
||||
while (currentPos < text.length()) {
|
||||
size_t nextColon = text.find(':', currentPos);
|
||||
if (nextColon == std::string::npos) {
|
||||
size_t hTag = text.find("|h", currentPos);
|
||||
if (hTag != std::string::npos) {
|
||||
params.push_back(text.substr(currentPos, hTag - currentPos));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
params.push_back(text.substr(currentPos, nextColon - currentPos));
|
||||
currentPos = nextColon + 1;
|
||||
}
|
||||
|
||||
if (params.size() >= 6) {
|
||||
res.randomPropertyId = atoi(params[5].c_str());
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string const ChatHelper::FormatQuest(Quest const* quest)
|
||||
{
|
||||
if (!quest)
|
||||
|
||||
@@ -25,6 +25,11 @@ struct ItemTemplate;
|
||||
typedef std::set<uint32> ItemIds;
|
||||
typedef std::set<uint32> SpellIds;
|
||||
|
||||
struct ItemWithRandomProperty {
|
||||
uint32 itemId{0};
|
||||
int32 randomPropertyId{0};
|
||||
};
|
||||
|
||||
class ChatHelper : public PlayerbotAIAware
|
||||
{
|
||||
public:
|
||||
@@ -33,6 +38,7 @@ public:
|
||||
static std::string const formatMoney(uint32 copper);
|
||||
static uint32 parseMoney(std::string const text);
|
||||
static ItemIds parseItems(std::string const text);
|
||||
static ItemWithRandomProperty parseItemWithRandomProperty(std::string const text);
|
||||
uint32 parseSpell(std::string const text);
|
||||
static std::string parseValue(const std::string& type, const std::string& text);
|
||||
|
||||
|
||||
@@ -1742,7 +1742,7 @@ void PlayerbotFactory::InitEquipment(bool incremental, bool second_chance)
|
||||
|
||||
if (incremental && oldItem)
|
||||
{
|
||||
float old_score = calculator.CalculateItem(oldItem->GetEntry());
|
||||
float old_score = calculator.CalculateItem(oldItem->GetEntry(), oldItem->GetItemRandomPropertyId());
|
||||
if (bestScoreForSlot < 1.2f * old_score)
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <cstdint>
|
||||
|
||||
#include "DBCStores.h"
|
||||
#include "ItemEnchantmentMgr.h"
|
||||
#include "ItemTemplate.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "PlayerbotAI.h"
|
||||
@@ -205,7 +206,7 @@ void StatsCollector::CollectSpellStats(uint32 spellId, float multiplier, int32 s
|
||||
}
|
||||
}
|
||||
|
||||
void StatsCollector::CollectEnchantStats(SpellItemEnchantmentEntry const* enchant)
|
||||
void StatsCollector::CollectEnchantStats(SpellItemEnchantmentEntry const* enchant, uint32 default_enchant_amount)
|
||||
{
|
||||
for (int s = 0; s < MAX_SPELL_ITEM_ENCHANTMENT_EFFECTS; ++s)
|
||||
{
|
||||
@@ -231,6 +232,10 @@ void StatsCollector::CollectEnchantStats(SpellItemEnchantmentEntry const* enchan
|
||||
}
|
||||
case ITEM_ENCHANTMENT_TYPE_STAT:
|
||||
{
|
||||
// for item random suffix
|
||||
if (!enchant_amount)
|
||||
enchant_amount = default_enchant_amount;
|
||||
|
||||
if (!enchant_amount)
|
||||
{
|
||||
break;
|
||||
@@ -250,7 +255,7 @@ bool StatsCollector::SpecialSpellFilter(uint32 spellId)
|
||||
// trinket
|
||||
switch (spellId)
|
||||
{
|
||||
case 60764: // Totem of Splintering
|
||||
case 60764: // Totem of Splintering
|
||||
if (type_ & (CollectorType::SPELL))
|
||||
return true;
|
||||
break;
|
||||
@@ -744,7 +749,7 @@ void StatsCollector::HandleApplyAura(const SpellEffectInfo& effectInfo, float mu
|
||||
|
||||
int32 StatsCollector::AverageValue(const SpellEffectInfo& effectInfo)
|
||||
{
|
||||
//float basePointsPerLevel = effectInfo.RealPointsPerLevel; //not used, line marked for removal.
|
||||
// float basePointsPerLevel = effectInfo.RealPointsPerLevel; //not used, line marked for removal.
|
||||
int32 basePoints = effectInfo.BasePoints;
|
||||
int32 randomPoints = int32(effectInfo.DieSides);
|
||||
|
||||
@@ -767,7 +772,7 @@ bool StatsCollector::CheckSpellValidation(uint32 spellFamilyName, flag96 spelFal
|
||||
{
|
||||
if (PlayerbotAI::Class2SpellFamilyName(cls_) != spellFamilyName)
|
||||
return false;
|
||||
|
||||
|
||||
bool isHealingSpell = PlayerbotAI::IsHealingSpell(spellFamilyName, spelFalimyFlags);
|
||||
// strict to healer
|
||||
if (strict && (type_ & CollectorType::SPELL_HEAL))
|
||||
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
void Reset();
|
||||
void CollectItemStats(ItemTemplate const* proto);
|
||||
void CollectSpellStats(uint32 spellId, float multiplier = 1.0f, int32 spellCooldown = -1);
|
||||
void CollectEnchantStats(SpellItemEnchantmentEntry const* enchant);
|
||||
void CollectEnchantStats(SpellItemEnchantmentEntry const* enchant, uint32 default_enchant_amount = 0);
|
||||
bool CanBeTriggeredByType(SpellInfo const* spellInfo, uint32 procFlags, bool strict = true);
|
||||
bool CheckSpellValidation(uint32 spellFamilyName, flag96 spelFalimyFlags, bool strict = true);
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "AiFactory.h"
|
||||
#include "DBCStores.h"
|
||||
#include "ItemEnchantmentMgr.h"
|
||||
#include "ItemTemplate.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "PlayerbotAI.h"
|
||||
@@ -59,7 +60,7 @@ void StatsWeightCalculator::Reset()
|
||||
}
|
||||
}
|
||||
|
||||
float StatsWeightCalculator::CalculateItem(uint32 itemId)
|
||||
float StatsWeightCalculator::CalculateItem(uint32 itemId, int32 randomPropertyIds)
|
||||
{
|
||||
ItemTemplate const* proto = &sObjectMgr->GetItemTemplateStore()->at(itemId);
|
||||
|
||||
@@ -69,6 +70,9 @@ float StatsWeightCalculator::CalculateItem(uint32 itemId)
|
||||
Reset();
|
||||
|
||||
collector_->CollectItemStats(proto);
|
||||
|
||||
if (randomPropertyIds != 0)
|
||||
CalculateRandomProperty(randomPropertyIds, itemId);
|
||||
|
||||
if (enable_overflow_penalty_)
|
||||
ApplyOverflowPenalty(player_);
|
||||
@@ -116,6 +120,53 @@ float StatsWeightCalculator::CalculateEnchant(uint32 enchantId)
|
||||
return weight_;
|
||||
}
|
||||
|
||||
void StatsWeightCalculator::CalculateRandomProperty(int32 randomPropertyId, uint32 itemId)
|
||||
{
|
||||
if (randomPropertyId > 0)
|
||||
{
|
||||
ItemRandomPropertiesEntry const* item_rand = sItemRandomPropertiesStore.LookupEntry(randomPropertyId);
|
||||
if (!item_rand)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint32 i = PROP_ENCHANTMENT_SLOT_0; i < MAX_ENCHANTMENT_SLOT; ++i)
|
||||
{
|
||||
uint32 enchantId = item_rand->Enchantment[i - PROP_ENCHANTMENT_SLOT_0];
|
||||
SpellItemEnchantmentEntry const* enchant = sSpellItemEnchantmentStore.LookupEntry(enchantId);
|
||||
if (enchant)
|
||||
collector_->CollectEnchantStats(enchant);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ItemRandomSuffixEntry const* item_rand = sItemRandomSuffixStore.LookupEntry(-randomPropertyId);
|
||||
if (!item_rand)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint32 i = PROP_ENCHANTMENT_SLOT_0; i < MAX_ENCHANTMENT_SLOT; ++i)
|
||||
{
|
||||
uint32 enchantId = item_rand->Enchantment[i - PROP_ENCHANTMENT_SLOT_0];
|
||||
SpellItemEnchantmentEntry const* enchant = sSpellItemEnchantmentStore.LookupEntry(enchantId);
|
||||
uint32 enchant_amount = 0;
|
||||
|
||||
for (int k = 0; k < MAX_ITEM_ENCHANTMENT_EFFECTS; ++k)
|
||||
{
|
||||
if (item_rand->Enchantment[k] == enchantId)
|
||||
{
|
||||
enchant_amount = uint32((item_rand->AllocationPct[k] * GenerateEnchSuffixFactor(itemId)) / 10000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (enchant)
|
||||
collector_->CollectEnchantStats(enchant, enchant_amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StatsWeightCalculator::GenerateWeights(Player* player)
|
||||
{
|
||||
GenerateBasicWeights(player);
|
||||
@@ -293,8 +344,8 @@ void StatsWeightCalculator::GenerateBasicWeights(Player* player)
|
||||
stats_weights_[STATS_TYPE_CRIT] += 0.8f;
|
||||
stats_weights_[STATS_TYPE_HASTE] += 1.0f;
|
||||
}
|
||||
else if ((cls == CLASS_PALADIN && tab == PALADIN_TAB_HOLY) || // holy
|
||||
(cls == CLASS_SHAMAN && tab == SHAMAN_TAB_RESTORATION)) // heal
|
||||
else if ((cls == CLASS_PALADIN && tab == PALADIN_TAB_HOLY) || // holy
|
||||
(cls == CLASS_SHAMAN && tab == SHAMAN_TAB_RESTORATION)) // heal
|
||||
{
|
||||
stats_weights_[STATS_TYPE_INTELLECT] += 0.9f;
|
||||
stats_weights_[STATS_TYPE_SPIRIT] += 0.15f;
|
||||
@@ -303,7 +354,7 @@ void StatsWeightCalculator::GenerateBasicWeights(Player* player)
|
||||
stats_weights_[STATS_TYPE_CRIT] += 0.6f;
|
||||
stats_weights_[STATS_TYPE_HASTE] += 0.8f;
|
||||
}
|
||||
else if ((cls == CLASS_PRIEST && tab != PRIEST_TAB_SHADOW) || // discipline / holy
|
||||
else if ((cls == CLASS_PRIEST && tab != PRIEST_TAB_SHADOW) || // discipline / holy
|
||||
(cls == CLASS_DRUID && tab == DRUID_TAB_RESTORATION))
|
||||
{
|
||||
stats_weights_[STATS_TYPE_INTELLECT] += 0.8f;
|
||||
@@ -464,9 +515,9 @@ void StatsWeightCalculator::CalculateItemTypePenalty(ItemTemplate const* proto)
|
||||
// {
|
||||
// weight_ *= 1.0;
|
||||
// }
|
||||
// double hand
|
||||
if (proto->Class == ITEM_CLASS_WEAPON)
|
||||
{
|
||||
// double hand
|
||||
bool isDoubleHand = proto->Class == ITEM_CLASS_WEAPON &&
|
||||
!(ITEM_SUBCLASS_MASK_SINGLE_HAND & (1 << proto->SubClass)) &&
|
||||
!(ITEM_SUBCLASS_MASK_WEAPON_RANGED & (1 << proto->SubClass));
|
||||
@@ -474,29 +525,41 @@ void StatsWeightCalculator::CalculateItemTypePenalty(ItemTemplate const* proto)
|
||||
if (isDoubleHand)
|
||||
{
|
||||
weight_ *= 0.5;
|
||||
}
|
||||
// spec without double hand
|
||||
// enhancement, rogue, ice dk, unholy dk, shield tank, fury warrior without titan's grip but with duel wield
|
||||
if (isDoubleHand &&
|
||||
((cls == CLASS_SHAMAN && tab == SHAMAN_TAB_ENHANCEMENT && player_->CanDualWield()) ||
|
||||
(cls == CLASS_ROGUE) || (cls == CLASS_DEATH_KNIGHT && tab == DEATHKNIGHT_TAB_FROST) ||
|
||||
(cls == CLASS_WARRIOR && tab == WARRIOR_TAB_FURY && !player_->CanTitanGrip() && player_->CanDualWield()) ||
|
||||
(cls == CLASS_WARRIOR && tab == WARRIOR_TAB_PROTECTION) ||
|
||||
(cls == CLASS_PALADIN && tab == PALADIN_TAB_PROTECTION)))
|
||||
{
|
||||
weight_ *= 0.1;
|
||||
// spec without double hand
|
||||
// enhancement, rogue, ice dk, unholy dk, shield tank, fury warrior without titan's grip but with duel wield
|
||||
if (((cls == CLASS_SHAMAN && tab == SHAMAN_TAB_ENHANCEMENT && player_->CanDualWield()) ||
|
||||
(cls == CLASS_ROGUE) || (cls == CLASS_DEATH_KNIGHT && tab == DEATHKNIGHT_TAB_FROST) ||
|
||||
(cls == CLASS_WARRIOR && tab == WARRIOR_TAB_FURY && !player_->CanTitanGrip() && player_->CanDualWield()) ||
|
||||
(cls == CLASS_WARRIOR && tab == WARRIOR_TAB_PROTECTION) ||
|
||||
(cls == CLASS_PALADIN && tab == PALADIN_TAB_PROTECTION)))
|
||||
{
|
||||
weight_ *= 0.1;
|
||||
}
|
||||
|
||||
}
|
||||
// spec with double hand
|
||||
// fury without duel wield, arms, bear, retribution, blood dk
|
||||
if (!isDoubleHand &&
|
||||
((cls == CLASS_HUNTER && !player_->CanDualWield()) ||
|
||||
(cls == CLASS_WARRIOR && tab == WARRIOR_TAB_FURY && !player_->CanDualWield()) ||
|
||||
(cls == CLASS_WARRIOR && tab == WARRIOR_TAB_ARMS) || (cls == CLASS_DRUID && tab == DRUID_TAB_FERAL) ||
|
||||
(cls == CLASS_PALADIN && tab == PALADIN_TAB_RETRIBUTION) ||
|
||||
(cls == CLASS_DEATH_KNIGHT && tab == DEATHKNIGHT_TAB_BLOOD) ||
|
||||
(cls == CLASS_SHAMAN && tab == SHAMAN_TAB_ENHANCEMENT && !player_->CanDualWield())))
|
||||
if (!isDoubleHand)
|
||||
{
|
||||
weight_ *= 0.1;
|
||||
if ((cls == CLASS_HUNTER && !player_->CanDualWield()) ||
|
||||
(cls == CLASS_WARRIOR && tab == WARRIOR_TAB_FURY && !player_->CanDualWield()) ||
|
||||
(cls == CLASS_WARRIOR && tab == WARRIOR_TAB_ARMS) || (cls == CLASS_DRUID && tab == DRUID_TAB_FERAL) ||
|
||||
(cls == CLASS_PALADIN && tab == PALADIN_TAB_RETRIBUTION) ||
|
||||
(cls == CLASS_DEATH_KNIGHT && tab == DEATHKNIGHT_TAB_BLOOD) ||
|
||||
(cls == CLASS_SHAMAN && tab == SHAMAN_TAB_ENHANCEMENT && !player_->CanDualWield()))
|
||||
{
|
||||
weight_ *= 0.1;
|
||||
}
|
||||
// caster's main hand (cannot duel weapon but can equip two-hands stuff)
|
||||
if (cls == CLASS_MAGE ||
|
||||
cls == CLASS_PRIEST ||
|
||||
cls == CLASS_WARLOCK ||
|
||||
cls == CLASS_DRUID ||
|
||||
(cls == CLASS_SHAMAN && !player_->CanDualWield()))
|
||||
{
|
||||
weight_ *= 0.65;
|
||||
}
|
||||
|
||||
}
|
||||
// fury with titan's grip
|
||||
if ((!isDoubleHand || proto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM ||
|
||||
@@ -505,15 +568,18 @@ void StatsWeightCalculator::CalculateItemTypePenalty(ItemTemplate const* proto)
|
||||
{
|
||||
weight_ *= 0.1;
|
||||
}
|
||||
|
||||
if (cls == CLASS_HUNTER && proto->SubClass == ITEM_SUBCLASS_WEAPON_THROWN)
|
||||
{
|
||||
weight_ *= 0.1;
|
||||
}
|
||||
|
||||
if (cls == CLASS_ROGUE && (tab == ROGUE_TAB_ASSASSINATION || tab == ROGUE_TAB_SUBTLETY) &&
|
||||
proto->SubClass != ITEM_SUBCLASS_WEAPON_DAGGER)
|
||||
{
|
||||
weight_ *= 0.5;
|
||||
}
|
||||
|
||||
if (cls == CLASS_ROGUE && player_->HasAura(13964) &&
|
||||
(proto->SubClass == ITEM_SUBCLASS_WEAPON_SWORD || proto->SubClass == ITEM_SUBCLASS_WEAPON_AXE))
|
||||
{
|
||||
@@ -559,12 +625,13 @@ void StatsWeightCalculator::ApplyOverflowPenalty(Player* player)
|
||||
if (hitOverflowType_ & CollectorType::SPELL)
|
||||
{
|
||||
hit_current = player->GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_HIT_CHANCE);
|
||||
hit_current += player->GetTotalAuraModifier(SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT); // suppression (18176)
|
||||
hit_current +=
|
||||
player->GetTotalAuraModifier(SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT); // suppression (18176)
|
||||
hit_current += player->GetRatingBonusValue(CR_HIT_SPELL);
|
||||
|
||||
if (cls == CLASS_PRIEST && tab == PRIEST_TAB_SHADOW && player->HasAura(15835)) // Shadow Focus
|
||||
if (cls == CLASS_PRIEST && tab == PRIEST_TAB_SHADOW && player->HasAura(15835)) // Shadow Focus
|
||||
hit_current += 3;
|
||||
if (cls == CLASS_MAGE && tab == MAGE_TAB_ARCANE && player->HasAura(12840)) // Arcane Focus
|
||||
if (cls == CLASS_MAGE && tab == MAGE_TAB_ARCANE && player->HasAura(12840)) // Arcane Focus
|
||||
hit_current += 3;
|
||||
|
||||
hit_overflow = SPELL_HIT_OVERFLOW;
|
||||
@@ -657,7 +724,7 @@ void StatsWeightCalculator::ApplyWeightFinetune(Player* player)
|
||||
{
|
||||
if (type_ & (CollectorType::MELEE | CollectorType::RANGED))
|
||||
{
|
||||
float armor_penetration_current/*, armor_penetration_overflow*/; //not used, line marked for removal.
|
||||
float armor_penetration_current /*, armor_penetration_overflow*/; // not used, line marked for removal.
|
||||
armor_penetration_current = player->GetRatingBonusValue(CR_ARMOR_PENETRATION);
|
||||
if (armor_penetration_current > 50)
|
||||
stats_weights_[STATS_TYPE_ARMOR_PENETRATION] *= 1.2f;
|
||||
|
||||
@@ -28,18 +28,19 @@ class StatsWeightCalculator
|
||||
public:
|
||||
StatsWeightCalculator(Player* player);
|
||||
void Reset();
|
||||
float CalculateItem(uint32 itemId);
|
||||
float CalculateItem(uint32 itemId, int32 randomPropertyId = 0);
|
||||
float CalculateEnchant(uint32 enchantId);
|
||||
|
||||
|
||||
void SetOverflowPenalty(bool apply) { enable_overflow_penalty_ = apply; }
|
||||
void SetItemSetBonus(bool apply) { enable_item_set_bonus_ = apply; }
|
||||
void SetQualityBlend(bool apply) { enable_quality_blend_ = apply; }
|
||||
|
||||
private:
|
||||
|
||||
private:
|
||||
void GenerateWeights(Player* player);
|
||||
void GenerateBasicWeights(Player* player);
|
||||
void GenerateAdditionalWeights(Player* player);
|
||||
|
||||
|
||||
void CalculateRandomProperty(int32 randomPropertyId, uint32 itemId);
|
||||
void CalculateItemSetMod(Player* player, ItemTemplate const* proto);
|
||||
void CalculateSocketBonus(Player* player, ItemTemplate const* proto);
|
||||
|
||||
|
||||
@@ -232,6 +232,20 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class CollectItemsVisitor : public IterateItemsVisitor
|
||||
{
|
||||
public:
|
||||
CollectItemsVisitor() : IterateItemsVisitor() {}
|
||||
|
||||
std::vector<Item*> items;
|
||||
|
||||
bool Visit(Item* item) override
|
||||
{
|
||||
items.push_back(item);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class ItemCountByQuality : public IterateItemsVisitor
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "Event.h"
|
||||
#include "ItemCountValue.h"
|
||||
#include "ItemUsageValue.h"
|
||||
#include "ItemVisitors.h"
|
||||
#include "Playerbots.h"
|
||||
#include "StatsWeightCalculator.h"
|
||||
|
||||
@@ -311,19 +312,28 @@ bool EquipUpgradesAction::Execute(Event event)
|
||||
return false;
|
||||
}
|
||||
|
||||
ListItemsVisitor visitor;
|
||||
CollectItemsVisitor visitor;
|
||||
IterateItems(&visitor, ITERATE_ITEMS_IN_BAGS);
|
||||
|
||||
ItemIds items;
|
||||
for (std::map<uint32, uint32>::iterator i = visitor.items.begin(); i != visitor.items.end(); ++i)
|
||||
for (auto i = visitor.items.begin(); i != visitor.items.end(); ++i)
|
||||
{
|
||||
ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", i->first);
|
||||
Item* item = *i;
|
||||
if (!item)
|
||||
break;
|
||||
int32 randomProperty = item->GetItemRandomPropertyId();
|
||||
uint32 itemId = item->GetTemplate()->ItemId;
|
||||
std::string itemUsageParam;
|
||||
if (randomProperty != 0) {
|
||||
itemUsageParam = std::to_string(itemId) + "," + std::to_string(randomProperty);
|
||||
} else {
|
||||
itemUsageParam = std::to_string(itemId);
|
||||
}
|
||||
ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", itemUsageParam);
|
||||
|
||||
if (usage == ITEM_USAGE_EQUIP || usage == ITEM_USAGE_REPLACE || usage == ITEM_USAGE_BAD_EQUIP)
|
||||
{
|
||||
// LOG_INFO("playerbots", "Bot {} <{}> EquipUpgradesAction {} ({})", bot->GetGUID().ToString().c_str(),
|
||||
// bot->GetName().c_str(), i->first, usage == 1 ? "no item in slot" : usage == 2 ? "replace" : usage == 3 ?
|
||||
// "wrong item but empty slot" : "");
|
||||
items.insert(i->first);
|
||||
items.insert(itemId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,21 +343,31 @@ bool EquipUpgradesAction::Execute(Event event)
|
||||
|
||||
bool EquipUpgradeAction::Execute(Event event)
|
||||
{
|
||||
ListItemsVisitor visitor;
|
||||
CollectItemsVisitor visitor;
|
||||
IterateItems(&visitor, ITERATE_ITEMS_IN_BAGS);
|
||||
|
||||
ItemIds items;
|
||||
for (std::map<uint32, uint32>::iterator i = visitor.items.begin(); i != visitor.items.end(); ++i)
|
||||
for (auto i = visitor.items.begin(); i != visitor.items.end(); ++i)
|
||||
{
|
||||
ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", i->first);
|
||||
Item* item = *i;
|
||||
if (!item)
|
||||
break;
|
||||
int32 randomProperty = item->GetItemRandomPropertyId();
|
||||
uint32 itemId = item->GetTemplate()->ItemId;
|
||||
std::string itemUsageParam;
|
||||
if (randomProperty != 0) {
|
||||
itemUsageParam = std::to_string(itemId) + "," + std::to_string(randomProperty);
|
||||
} else {
|
||||
itemUsageParam = std::to_string(itemId);
|
||||
}
|
||||
ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", itemUsageParam);
|
||||
|
||||
if (usage == ITEM_USAGE_EQUIP || usage == ITEM_USAGE_REPLACE || usage == ITEM_USAGE_BAD_EQUIP)
|
||||
{
|
||||
// LOG_INFO("playerbots", "Bot {} <{}> EquipUpgradeAction item {} ({})", bot->GetGUID().ToString().c_str(),
|
||||
// bot->GetName().c_str(), i->first, usage == 1 ? "no item in slot" : usage == 2 ? "replace" : usage == 3 ?
|
||||
// "wrong item but empty slot" : "");
|
||||
items.insert(i->first);
|
||||
items.insert(itemId);
|
||||
}
|
||||
}
|
||||
|
||||
EquipItems(items);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "Group.h"
|
||||
#include "ItemUsageValue.h"
|
||||
#include "LootAction.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "PlayerbotAIConfig.h"
|
||||
#include "Playerbots.h"
|
||||
|
||||
@@ -30,12 +31,24 @@ bool LootRollAction::Execute(Event event)
|
||||
ObjectGuid guid = roll->itemGUID;
|
||||
uint32 slot = roll->itemSlot;
|
||||
uint32 itemId = roll->itemid;
|
||||
int32 randomProperty = 0;
|
||||
if (roll->itemRandomPropId)
|
||||
randomProperty = roll->itemRandomPropId;
|
||||
else if (roll->itemRandomSuffix)
|
||||
randomProperty = -((int)roll->itemRandomSuffix);
|
||||
|
||||
RollVote vote = PASS;
|
||||
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
|
||||
if (!proto)
|
||||
continue;
|
||||
ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", itemId);
|
||||
|
||||
std::string itemUsageParam;
|
||||
if (randomProperty != 0) {
|
||||
itemUsageParam = std::to_string(itemId) + "," + std::to_string(randomProperty);
|
||||
} else {
|
||||
itemUsageParam = std::to_string(itemId);
|
||||
}
|
||||
ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", itemUsageParam);
|
||||
|
||||
// Armor Tokens are classed as MISC JUNK (Class 15, Subclass 0), luckily no other items I found have class bits and epic quality.
|
||||
if (proto->Class == ITEM_CLASS_MISC && proto->SubClass == ITEM_SUBCLASS_JUNK && proto->Quality == ITEM_QUALITY_EPIC)
|
||||
|
||||
@@ -183,7 +183,7 @@ void OutfitAction::Update(std::string const name)
|
||||
{
|
||||
ListItemsVisitor visitor;
|
||||
IterateItems(&visitor, ITERATE_ITEMS_IN_EQUIP);
|
||||
|
||||
|
||||
ItemIds items;
|
||||
for (std::map<uint32, uint32>::iterator i = visitor.items.begin(); i != visitor.items.end(); ++i)
|
||||
items.insert(i->first);
|
||||
|
||||
@@ -43,6 +43,7 @@ bool ReleaseSpiritAction::Execute(Event event)
|
||||
botAI->TellMasterNoFacing(message);
|
||||
|
||||
IncrementDeathCount();
|
||||
bot->DurabilityRepairAll(false, 1.0f, false);
|
||||
LogRelease("released");
|
||||
|
||||
WorldPacket releasePacket(CMSG_REPOP_REQUEST);
|
||||
@@ -79,6 +80,7 @@ void ReleaseSpiritAction::LogRelease(const std::string& releaseMsg, bool isAutoR
|
||||
bool AutoReleaseSpiritAction::Execute(Event event)
|
||||
{
|
||||
IncrementDeathCount();
|
||||
bot->DurabilityRepairAll(false, 1.0f, false);
|
||||
LogRelease("auto released", true);
|
||||
|
||||
WorldPacket packet(CMSG_REPOP_REQUEST);
|
||||
|
||||
@@ -140,17 +140,16 @@ bool TellEstimatedDpsAction::Execute(Event event)
|
||||
bool TellCalculateItemAction::Execute(Event event)
|
||||
{
|
||||
std::string const text = event.getParam();
|
||||
ItemIds ids = chat->parseItems(text);
|
||||
ItemWithRandomProperty item = chat->parseItemWithRandomProperty(text);
|
||||
StatsWeightCalculator calculator(bot);
|
||||
for (const uint32 &id : ids)
|
||||
{
|
||||
const ItemTemplate* proto = sObjectMgr->GetItemTemplate(id);
|
||||
if (!proto)
|
||||
continue;
|
||||
float score = calculator.CalculateItem(id);
|
||||
std::ostringstream out;
|
||||
out << "Calculated score of " << chat->FormatItem(proto) << " : " << score;
|
||||
botAI->TellMasterNoFacing(out.str());
|
||||
}
|
||||
|
||||
const ItemTemplate* proto = sObjectMgr->GetItemTemplate(item.itemId);
|
||||
if (!proto)
|
||||
return false;
|
||||
float score = calculator.CalculateItem(item.itemId, item.randomPropertyId);
|
||||
|
||||
std::ostringstream out;
|
||||
out << "Calculated score of " << chat->FormatItem(proto) << " : " << score;
|
||||
botAI->TellMasterNoFacing(out.str());
|
||||
return true;
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "AiFactory.h"
|
||||
#include "ChatHelper.h"
|
||||
#include "GuildTaskMgr.h"
|
||||
#include "Item.h"
|
||||
#include "LootObjectStack.h"
|
||||
#include "PlayerbotAIConfig.h"
|
||||
#include "PlayerbotFactory.h"
|
||||
@@ -18,7 +19,16 @@
|
||||
|
||||
ItemUsage ItemUsageValue::Calculate()
|
||||
{
|
||||
uint32 itemId = atoi(qualifier.c_str());
|
||||
uint32 itemId = 0;
|
||||
uint32 randomPropertyId = 0;
|
||||
size_t pos = qualifier.find(",");
|
||||
if (pos != std::string::npos) {
|
||||
itemId = atoi(qualifier.substr(0, pos).c_str());
|
||||
randomPropertyId = atoi(qualifier.substr(pos + 1).c_str());
|
||||
} else {
|
||||
itemId = atoi(qualifier.c_str());
|
||||
}
|
||||
|
||||
if (!itemId)
|
||||
return ITEM_USAGE_NONE;
|
||||
|
||||
@@ -89,7 +99,7 @@ ItemUsage ItemUsageValue::Calculate()
|
||||
if (bot->GetGuildId() && sGuildTaskMgr->IsGuildTaskItem(itemId, bot->GetGuildId()))
|
||||
return ITEM_USAGE_GUILD_TASK;
|
||||
|
||||
ItemUsage equip = QueryItemUsageForEquip(proto);
|
||||
ItemUsage equip = QueryItemUsageForEquip(proto, randomPropertyId);
|
||||
if (equip != ITEM_USAGE_NONE)
|
||||
return equip;
|
||||
|
||||
@@ -224,7 +234,7 @@ ItemUsage ItemUsageValue::Calculate()
|
||||
return ITEM_USAGE_NONE;
|
||||
}
|
||||
|
||||
ItemUsage ItemUsageValue::QueryItemUsageForEquip(ItemTemplate const* itemProto)
|
||||
ItemUsage ItemUsageValue::QueryItemUsageForEquip(ItemTemplate const* itemProto, int32 randomPropertyId)
|
||||
{
|
||||
if (bot->CanUseItem(itemProto) != EQUIP_ERR_OK)
|
||||
return ITEM_USAGE_NONE;
|
||||
@@ -296,7 +306,8 @@ ItemUsage ItemUsageValue::QueryItemUsageForEquip(ItemTemplate const* itemProto)
|
||||
calculator.SetItemSetBonus(false);
|
||||
calculator.SetOverflowPenalty(false);
|
||||
|
||||
float itemScore = calculator.CalculateItem(itemProto->ItemId);
|
||||
float itemScore = calculator.CalculateItem(itemProto->ItemId, randomPropertyId);
|
||||
|
||||
if (itemScore)
|
||||
shouldEquip = true;
|
||||
|
||||
@@ -380,7 +391,7 @@ ItemUsage ItemUsageValue::QueryItemUsageForEquip(ItemTemplate const* itemProto)
|
||||
}
|
||||
|
||||
ItemTemplate const* oldItemProto = oldItem->GetTemplate();
|
||||
float oldScore = calculator.CalculateItem(oldItemProto->ItemId);
|
||||
float oldScore = calculator.CalculateItem(oldItemProto->ItemId, oldItem->GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID));
|
||||
if (oldItem)
|
||||
{
|
||||
// uint32 oldStatWeight = sRandomItemMgr->GetLiveStatWeight(bot, oldItemProto->ItemId);
|
||||
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
ItemUsage Calculate() override;
|
||||
|
||||
private:
|
||||
ItemUsage QueryItemUsageForEquip(ItemTemplate const* proto);
|
||||
ItemUsage QueryItemUsageForEquip(ItemTemplate const* proto, int32 randomPropertyId = 0);
|
||||
uint32 GetSmallestBagSize();
|
||||
bool IsItemUsefulForQuest(Player* player, ItemTemplate const* proto);
|
||||
bool IsItemNeededForSkill(ItemTemplate const* proto);
|
||||
|
||||
Reference in New Issue
Block a user