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:
Yunfan Li
2025-05-20 23:24:33 +08:00
committed by GitHub
parent c5b185455c
commit 5910866362
15 changed files with 253 additions and 72 deletions

View File

@@ -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:

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);