Hunter pet talents init

This commit is contained in:
Yunfan Li
2024-09-04 15:12:48 +08:00
parent 6789237843
commit 5de242e80b
4 changed files with 220 additions and 77 deletions

View File

@@ -821,13 +821,25 @@ AiPlayerbot.PremadeSpecGlyph.3.0 = 42912,43350,42902,43351,43338,45732
AiPlayerbot.PremadeSpecLink.3.0.60 = 51200201505112243100511351
AiPlayerbot.PremadeSpecLink.3.0.80 = 51200201505112253100531351-015305021
AiPlayerbot.PremadeSpecName.3.1 = mm pve
AiPlayerbot.PremadeSpecGlyph.3.1 = 42912,43350,42915,43351,43338,45732
AiPlayerbot.PremadeSpecLink.3.1.60 = -015305101230013233135030051
AiPlayerbot.PremadeSpecLink.3.1.80 = 502-035305101230013233135031351-5000002
AiPlayerbot.PremadeSpecGlyph.3.1 = 42912,43350,42914,43351,43338,45732
AiPlayerbot.PremadeSpecLink.3.1.60 = -005305111230013233125030151-5
AiPlayerbot.PremadeSpecLink.3.1.80 = 502-005305131230013233135031351-5000002
AiPlayerbot.PremadeSpecName.3.2 = surv pve
AiPlayerbot.PremadeSpecGlyph.3.2 = 42912,43350,45731,43351,43338,45732
AiPlayerbot.PremadeSpecLink.3.2.60 = --5000032500033330502135001331
AiPlayerbot.PremadeSpecLink.3.2.80 = -005305101-5000032500033330522135301331
AiPlayerbot.PremadeSpecLink.3.2.60 = --5000032500033330502135201311
AiPlayerbot.PremadeSpecLink.3.2.80 = -005305101-5000032500033330532135301321
# HUNTER PET
#
# Ferocity
AiPlayerbot.PremadeHunterPetLink.0.16 = 2100003030103010101
AiPlayerbot.PremadeHunterPetLink.0.20 = 2100013030103010122
# Tenacity
AiPlayerbot.PremadeHunterPetLink.1.16 = 21103000300120101001
AiPlayerbot.PremadeHunterPetLink.1.20 = 21303010300120101002
# Cunning
AiPlayerbot.PremadeHunterPetLink.2.16 = 2100020330000211001
AiPlayerbot.PremadeHunterPetLink.2.20 = 21000203300002110221
#
#

View File

@@ -331,6 +331,17 @@ bool PlayerbotAIConfig::Initialize()
parsedSpecLinkOrder[cls][spec][level] = ParseTempTalentsOrder(cls, premadeSpecLink[cls][spec][level]);
}
}
for (uint32 spec = 0; spec < 3; ++spec)
{
for (uint32 points = 0; points < 21; ++points)
{
std::ostringstream os;
os << "AiPlayerbot.PremadeHunterPetLink." << spec << "." << points;
premadeHunterPetLink[spec][points] = sConfigMgr->GetOption<std::string>(os.str().c_str(), "", false);
parsedHunterPetLinkOrder[spec][points] =
ParseTempPetTalentsOrder(spec, premadeHunterPetLink[spec][points]);
}
}
for (uint32 spec = 0; spec < MAX_SPECNO; ++spec)
{
std::ostringstream os;
@@ -760,3 +771,47 @@ std::vector<std::vector<uint32>> PlayerbotAIConfig::ParseTempTalentsOrder(uint32
}
return res;
}
std::vector<std::vector<uint32>> PlayerbotAIConfig::ParseTempPetTalentsOrder(uint32 spec, std::string tab_link)
{
// check bad link
// uint32 classMask = 1 << (cls - 1);
std::vector<TalentEntry const*> spells;
std::vector<std::vector<uint32>> orders;
for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i)
{
TalentEntry const* talentInfo = sTalentStore.LookupEntry(i);
if (!talentInfo)
continue;
TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab);
if (!talentTabInfo)
continue;
if (!((1 << spec) & talentTabInfo->petTalentMask))
continue;
// skip some duplicate spells like dash/dive
if (talentInfo->TalentID == 2201 || talentInfo->TalentID == 2208 || talentInfo->TalentID == 2219 || talentInfo->TalentID == 2203)
continue;
spells.push_back(talentInfo);
}
std::sort(spells.begin(), spells.end(),
[&](TalentEntry const* lhs, TalentEntry const* rhs)
{ return lhs->Row != rhs->Row ? lhs->Row < rhs->Row : lhs->Col < rhs->Col; });
for (int i = 0; i < tab_link.size(); i++)
{
if (i >= spells.size())
{
break;
}
int lvl = tab_link[i] - '0';
if (lvl == 0)
continue;
orders.push_back({spells[i]->Row, spells[i]->Col, (uint32)lvl});
}
// sort by talent tab size
std::sort(orders.begin(), orders.end(), [&](auto& lhs, auto& rhs) { return lhs.size() > rhs.size(); });
return orders;
}

View File

@@ -195,7 +195,9 @@ public:
std::string premadeSpecGlyph[MAX_CLASSES][MAX_SPECNO];
std::vector<uint32> parsedSpecGlyph[MAX_CLASSES][MAX_SPECNO];
std::string premadeSpecLink[MAX_CLASSES][MAX_SPECNO][MAX_LEVEL];
std::string premadeHunterPetLink[3][21];
std::vector<std::vector<uint32>> parsedSpecLinkOrder[MAX_CLASSES][MAX_SPECNO][MAX_LEVEL];
std::vector<std::vector<uint32>> parsedHunterPetLinkOrder[3][21];
uint32 randomClassSpecProb[MAX_CLASSES][MAX_SPECNO];
uint32 randomClassSpecIndex[MAX_CLASSES][MAX_SPECNO];
@@ -325,6 +327,7 @@ public:
void loadWorldBuf(uint32 factionId, uint32 classId, uint32 minLevel, uint32 maxLevel);
static std::vector<std::vector<uint32>> ParseTempTalentsOrder(uint32 cls, std::string temp_talents_order);
static std::vector<std::vector<uint32>> ParseTempPetTalentsOrder(uint32 spec, std::string temp_talents_order);
};
#define sPlayerbotAIConfig PlayerbotAIConfig::instance()

View File

@@ -39,6 +39,7 @@
#define PLAYER_SKILL_INDEX(x) (PLAYER_SKILL_INFO_1_1 + ((x)*3))
const uint64 diveMask = (1LL << 7) | (1LL << 44) | (1LL << 37) | (1LL << 38) | (1LL << 26) | (1LL << 30) | (1LL << 27) | (1LL << 33) | (1LL << 24) | (1LL << 34);
uint32 PlayerbotFactory::tradeSkills[] = {SKILL_ALCHEMY, SKILL_ENCHANTING, SKILL_SKINNING, SKILL_TAILORING,
SKILL_LEATHERWORKING, SKILL_ENGINEERING, SKILL_HERBALISM, SKILL_MINING,
SKILL_BLACKSMITHING, SKILL_COOKING, SKILL_FIRST_AID, SKILL_FISHING,
@@ -611,8 +612,10 @@ void PlayerbotFactory::InitPetTalents()
// pet_family->petTalentType);
return;
}
// pet->resetTalents();
std::unordered_map<uint32, std::vector<TalentEntry const*>> spells;
bool diveTypePet = (1LL << ci->family) & diveMask;
LOG_INFO("playerbots", "DIVEMASK:{}", diveMask);
for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i)
{
TalentEntry const* talentInfo = sTalentStore.LookupEntry(i);
@@ -624,15 +627,21 @@ void PlayerbotFactory::InitPetTalents()
// prevent learn talent for different family (cheating)
if (!((1 << pet_family->petTalentType) & talentTabInfo->petTalentMask))
continue;
bool diveClass = talentInfo->TalentID == 2201 || talentInfo->TalentID == 2208 || talentInfo->TalentID == 2219 || talentInfo->TalentID == 2203;
if (diveClass && !diveTypePet)
continue;
bool dashClass = talentInfo->TalentID == 2119 || talentInfo->TalentID == 2207 || talentInfo->TalentID == 2111 || talentInfo->TalentID == 2109;
if (dashClass && diveTypePet)
continue;
spells[talentInfo->Row].push_back(talentInfo);
}
uint32 curTalentPoints = pet->GetFreeTalentPoints();
std::vector<std::vector<uint32>> order = sPlayerbotAIConfig->parsedHunterPetLinkOrder[pet_family->petTalentType][20];
uint32 maxTalentPoints = pet->GetMaxTalentPointsForLevel(pet->GetLevel());
if (order.empty())
{
int row = 0;
// LOG_INFO("playerbots", "{} learning, max talent points: {}, cur: {}", bot->GetName().c_str(), maxTalentPoints,
// curTalentPoints);
for (auto i = spells.begin(); i != spells.end(); ++i, ++row)
{
std::vector<TalentEntry const*>& spells_row = i->second;
@@ -669,6 +678,63 @@ void PlayerbotFactory::InitPetTalents()
spells_row.erase(spells_row.begin() + index);
}
}
}
else
{
uint32 spec = pet_family->petTalentType;
uint32 startPoints = pet->GetMaxTalentPointsForLevel(pet->GetLevel());
while (startPoints > 1 && startPoints < 20 &&
sPlayerbotAIConfig->parsedHunterPetLinkOrder[spec][startPoints].size() == 0)
{
startPoints--;
}
for (uint32 points = startPoints; points <= 20; points++)
{
if (sPlayerbotAIConfig->parsedHunterPetLinkOrder[spec][points].size() == 0)
continue;
for (std::vector<uint32>& p : sPlayerbotAIConfig->parsedHunterPetLinkOrder[spec][points])
{
uint32 row = p[0], col = p[1], lvl = p[2];
uint32 talentID = 0;
uint32 learnLevel = 0;
std::vector<TalentEntry const*>& spell = spells[row];
for (TalentEntry const* talentInfo : spell)
{
if (talentInfo->Col != col)
{
continue;
}
if (talentInfo->DependsOn)
{
bot->LearnPetTalent(pet->GetGUID(),talentInfo->DependsOn,
std::min(talentInfo->DependsOnRank, bot->GetFreeTalentPoints() - 1));
}
talentID = talentInfo->TalentID;
uint32 currentTalentRank = 0;
for (uint8 rank = 0; rank < MAX_TALENT_RANK; ++rank)
{
if (talentInfo->RankID[rank] && pet->HasSpell(talentInfo->RankID[rank]))
{
currentTalentRank = rank + 1;
break;
}
}
learnLevel = std::min(lvl, pet->GetFreeTalentPoints() + currentTalentRank) - 1;
}
bot->LearnPetTalent(pet->GetGUID(), talentID, learnLevel);
if (pet->GetFreeTalentPoints() == 0)
{
break;
}
}
if (pet->GetFreeTalentPoints() == 0)
{
break;
}
}
}
bot->SendTalentsInfoData(true);
}
@@ -1467,6 +1533,7 @@ void PlayerbotFactory::InitEquipment(bool incremental)
else if (blevel == 80)
delta = 9;
StatsWeightCalculator calculator(bot);
for (uint8 slot = 0; slot < EQUIPMENT_SLOT_END; ++slot)
{
if (slot == EQUIPMENT_SLOT_TABARD || slot == EQUIPMENT_SLOT_BODY)
@@ -1484,6 +1551,18 @@ void PlayerbotFactory::InitEquipment(bool incremental)
if (level < 20 && (slot == EQUIPMENT_SLOT_FINGER1 || slot == EQUIPMENT_SLOT_FINGER2))
continue;
Item* oldItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, slot);
if (!incremental && oldItem)
{
continue;
}
if (oldItem)
{
bot->DestroyItem(INVENTORY_SLOT_BAG_0, slot, true);
}
uint32 desiredQuality = itemQuality;
if (urand(0, 100) < 100 * sPlayerbotAIConfig->randomGearLoweringChance && desiredQuality > ITEM_QUALITY_NORMAL)
{
@@ -1555,41 +1634,19 @@ void PlayerbotFactory::InitEquipment(bool incremental)
break;
}
} while (items[slot].size() < 25 && desiredQuality-- > ITEM_QUALITY_NORMAL);
}
StatsWeightCalculator calculator(bot);
for (uint8 slot = 0; slot < EQUIPMENT_SLOT_END; ++slot)
{
if (slot == EQUIPMENT_SLOT_TABARD || slot == EQUIPMENT_SLOT_BODY)
continue;
if (level < 40 && (slot == EQUIPMENT_SLOT_TRINKET1 || slot == EQUIPMENT_SLOT_TRINKET2))
continue;
if (level < 25 && slot == EQUIPMENT_SLOT_NECK)
continue;
if (level < 25 && slot == EQUIPMENT_SLOT_HEAD)
continue;
std::vector<uint32>& ids = items[slot];
if (ids.empty())
{
continue;
}
Item* oldItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, slot);
if (incremental && !IsDesiredReplacement(oldItem))
{
continue;
}
float bestScoreForSlot = -1;
uint32 bestItemForSlot = 0;
for (int index = 0; index < ids.size(); index++)
{
uint32 skipProb = 25;
if (urand(0, 100) <= skipProb)
if (urand(1, 100) <= skipProb)
continue;
uint32 newItemId = ids[index];
@@ -1601,9 +1658,6 @@ void PlayerbotFactory::InitEquipment(bool incremental)
if (!CanEquipItem(proto))
continue;
if (oldItem && oldItem->GetTemplate()->ItemId == newItemId)
continue;
if (!CanEquipUnseenItem(slot, dest, newItemId))
continue;
@@ -1618,10 +1672,7 @@ void PlayerbotFactory::InitEquipment(bool incremental)
{
continue;
}
if (oldItem)
{
bot->DestroyItem(INVENTORY_SLOT_BAG_0, slot, true);
}
uint16 dest;
if (!CanEquipUnseenItem(slot, dest, bestItemForSlot))
{
@@ -1632,10 +1683,28 @@ void PlayerbotFactory::InitEquipment(bool incremental)
{
newItem->AddToWorld();
newItem->AddToUpdateQueueOf(bot);
// bot->AutoUnequipOffhandIfNeed();
// EnchantItem(newItem);
}
}
// secondary init for better equips
if (!incremental)
InitEquipment(true);
// for (uint8 slot = 0; slot < EQUIPMENT_SLOT_END; ++slot)
// {
// if (slot == EQUIPMENT_SLOT_TABARD || slot == EQUIPMENT_SLOT_BODY)
// continue;
// if (level < 40 && (slot == EQUIPMENT_SLOT_TRINKET1 || slot == EQUIPMENT_SLOT_TRINKET2))
// continue;
// if (level < 25 && slot == EQUIPMENT_SLOT_NECK)
// continue;
// if (level < 25 && slot == EQUIPMENT_SLOT_HEAD)
// continue;
// }
}
bool PlayerbotFactory::IsDesiredReplacement(Item* item)
@@ -3818,7 +3887,7 @@ void PlayerbotFactory::ApplyEnchantAndGemsNew(bool destoryOld)
if (!gemProperties)
continue;
if ((socketColor & gemProperties->color) == 0)
if ((socketColor & gemProperties->color) == 0 && gemProperties->color == 1) // meta socket
continue;
uint32 enchant_id = gemProperties->spellitemenchantement;
@@ -3829,6 +3898,7 @@ void PlayerbotFactory::ApplyEnchantAndGemsNew(bool destoryOld)
StatsWeightCalculator calculator(bot);
float score = calculator.CalculateEnchant(enchant_id);
if (curCount[0] != 0)
{
// Ensure meta gem activation
for (int i = 1; i < curCount.size(); i++)
{
@@ -3838,6 +3908,9 @@ void PlayerbotFactory::ApplyEnchantAndGemsNew(bool destoryOld)
break;
}
}
}
if (socketColor & gemProperties->color)
score *= 1.2;
if (score > bestGemScore)
{
enchantIdChosen = enchant_id;