Compare commits

..

No commits in common. "ede7697784ec7da6bf44195ba4e1f28a7d6f6b6b" and "989b48f4915c0e2c57459c50869a9b3ee9a8c18a" have entirely different histories.

26 changed files with 490 additions and 865 deletions

View File

@ -667,7 +667,7 @@ AiPlayerbot.IncrementalGearInit = 1
AiPlayerbot.MinEnchantingBotLevel = 60 AiPlayerbot.MinEnchantingBotLevel = 60
# Enable expansion limitation for bot enchants # Enable expansion limitation for bot enchants
# If enabled, bots will not use TBC enchants until level 61 or WotLK enchants until level 71 # If enabled, bots will not use TBC enchants until level 61 or WotLK enchanges until level 71
# Default: 1 (enabled) # Default: 1 (enabled)
AiPlayerbot.LimitEnchantExpansion = 1 AiPlayerbot.LimitEnchantExpansion = 1
@ -699,10 +699,6 @@ AiPlayerbot.AutoUpgradeEquip = 1
# Default: 0 (disabled) # Default: 0 (disabled)
AiPlayerbot.HunterWolfPet = 0 AiPlayerbot.HunterWolfPet = 0
# Prohibit hunter bots from creating pets with any family ID listed below in ExcludedHunterPetFamilies
# See the creature_family database table for all pet families by ID (note: ID for spiders is 3)
AiPlayerbot.ExcludedHunterPetFamilies = ""
# #
# #
# #

View File

@ -5105,13 +5105,13 @@ Item* PlayerbotAI::FindAmmo() const
} }
// Find Consumable // Find Consumable
Item* PlayerbotAI::FindConsumable(uint32 itemId) const Item* PlayerbotAI::FindConsumable(uint32 displayId) const
{ {
return FindItemInInventory( return FindItemInInventory(
[itemId](ItemTemplate const* pItemProto) -> bool [displayId](ItemTemplate const* pItemProto) -> bool
{ {
return (pItemProto->Class == ITEM_CLASS_CONSUMABLE || pItemProto->Class == ITEM_CLASS_TRADE_GOODS) && return (pItemProto->Class == ITEM_CLASS_CONSUMABLE || pItemProto->Class == ITEM_CLASS_TRADE_GOODS) &&
pItemProto->ItemId == itemId; pItemProto->DisplayInfoID == displayId;
}); });
} }
@ -5171,34 +5171,36 @@ Item* PlayerbotAI::FindLockedItem() const
}); });
} }
static const uint32 uPriorizedSharpStoneIds[8] = {ADAMANTITE_SHARPENING_DISPLAYID, FEL_SHARPENING_DISPLAYID,
ELEMENTAL_SHARPENING_DISPLAYID, DENSE_SHARPENING_DISPLAYID,
SOLID_SHARPENING_DISPLAYID, HEAVY_SHARPENING_DISPLAYID,
COARSE_SHARPENING_DISPLAYID, ROUGH_SHARPENING_DISPLAYID};
static const uint32 uPriorizedWeightStoneIds[7] = {ADAMANTITE_WEIGHTSTONE_DISPLAYID, FEL_WEIGHTSTONE_DISPLAYID,
DENSE_WEIGHTSTONE_DISPLAYID, SOLID_WEIGHTSTONE_DISPLAYID,
HEAVY_WEIGHTSTONE_DISPLAYID, COARSE_WEIGHTSTONE_DISPLAYID,
ROUGH_WEIGHTSTONE_DISPLAYID};
/**
* FindStoneFor()
* return Item* Returns sharpening/weight stone item eligible to enchant a bot weapon
*
* params:weapon Item* the weap<EFBFBD>n the function should search and return a enchanting item for
* return nullptr if no relevant item is found in bot inventory, else return a sharpening or weight
* stone based on the weapon subclass
*
*/
Item* PlayerbotAI::FindStoneFor(Item* weapon) const Item* PlayerbotAI::FindStoneFor(Item* weapon) const
{ {
if (!weapon)
return nullptr;
const ItemTemplate* item_template = weapon->GetTemplate();
if (!item_template)
return nullptr;
static const std::vector<uint32_t> uPrioritizedSharpStoneIds = {
ADAMANTITE_SHARPENING_STONE, FEL_SHARPENING_STONE, ELEMENTAL_SHARPENING_STONE, DENSE_SHARPENING_STONE,
SOLID_SHARPENING_STONE, HEAVY_SHARPENING_STONE, COARSE_SHARPENING_STONE, ROUGH_SHARPENING_STONE
};
static const std::vector<uint32_t> uPrioritizedWeightStoneIds = {
ADAMANTITE_WEIGHTSTONE, FEL_WEIGHTSTONE, DENSE_WEIGHTSTONE, SOLID_WEIGHTSTONE,
HEAVY_WEIGHTSTONE, COARSE_WEIGHTSTONE, ROUGH_WEIGHTSTONE
};
Item* stone = nullptr; Item* stone = nullptr;
ItemTemplate const* pProto = weapon->GetTemplate(); ItemTemplate const* pProto = weapon->GetTemplate();
if (pProto && (pProto->SubClass == ITEM_SUBCLASS_WEAPON_SWORD || pProto->SubClass == ITEM_SUBCLASS_WEAPON_SWORD2 || if (pProto && (pProto->SubClass == ITEM_SUBCLASS_WEAPON_SWORD || pProto->SubClass == ITEM_SUBCLASS_WEAPON_SWORD2 ||
pProto->SubClass == ITEM_SUBCLASS_WEAPON_AXE || pProto->SubClass == ITEM_SUBCLASS_WEAPON_AXE2 || pProto->SubClass == ITEM_SUBCLASS_WEAPON_AXE || pProto->SubClass == ITEM_SUBCLASS_WEAPON_AXE2 ||
pProto->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER || pProto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM)) pProto->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER))
{ {
for (uint8 i = 0; i < std::size(uPrioritizedSharpStoneIds); ++i) for (uint8 i = 0; i < std::size(uPriorizedSharpStoneIds); ++i)
{ {
stone = FindConsumable(uPrioritizedSharpStoneIds[i]); stone = FindConsumable(uPriorizedSharpStoneIds[i]);
if (stone) if (stone)
{ {
return stone; return stone;
@ -5206,12 +5208,11 @@ static const std::vector<uint32_t> uPrioritizedWeightStoneIds = {
} }
} }
else if (pProto && else if (pProto &&
(pProto->SubClass == ITEM_SUBCLASS_WEAPON_MACE || pProto->SubClass == ITEM_SUBCLASS_WEAPON_MACE2 || (pProto->SubClass == ITEM_SUBCLASS_WEAPON_MACE || pProto->SubClass == ITEM_SUBCLASS_WEAPON_MACE2))
pProto->SubClass == ITEM_SUBCLASS_WEAPON_STAFF || pProto->SubClass == ITEM_SUBCLASS_WEAPON_FIST))
{ {
for (uint8 i = 0; i < std::size(uPrioritizedWeightStoneIds); ++i) for (uint8 i = 0; i < std::size(uPriorizedWeightStoneIds); ++i)
{ {
stone = FindConsumable(uPrioritizedWeightStoneIds[i]); stone = FindConsumable(uPriorizedWeightStoneIds[i]);
if (stone) if (stone)
{ {
return stone; return stone;
@ -5224,7 +5225,6 @@ static const std::vector<uint32_t> uPrioritizedWeightStoneIds = {
Item* PlayerbotAI::FindOilFor(Item* weapon) const Item* PlayerbotAI::FindOilFor(Item* weapon) const
{ {
if (!weapon) if (!weapon)
return nullptr; return nullptr;
@ -5232,61 +5232,36 @@ Item* PlayerbotAI::FindOilFor(Item* weapon) const
if (!item_template) if (!item_template)
return nullptr; return nullptr;
static const std::vector<uint32_t> uPrioritizedWizardOilIds = { // static const will only get created once whatever the call amout
BRILLIANT_WIZARD_OIL, SUPERIOR_WIZARD_OIL, WIZARD_OIL, LESSER_WIZARD_OIL, MINOR_WIZARD_OIL, static const std::vector<uint32_t> uPriorizedWizardOilIds = {
BRILLIANT_MANA_OIL, SUPERIOR_MANA_OIL, LESSER_MANA_OIL, MINOR_MANA_OIL}; MINOR_WIZARD_OIL, MINOR_MANA_OIL, LESSER_WIZARD_OIL, LESSER_MANA_OIL, BRILLIANT_WIZARD_OIL,
BRILLIANT_MANA_OIL, WIZARD_OIL, SUPERIOR_MANA_OIL, SUPERIOR_WIZARD_OIL};
static const std::vector<uint32_t> uPrioritizedManaOilIds = { // static const will only get created once whatever the call amout
BRILLIANT_MANA_OIL, SUPERIOR_MANA_OIL, LESSER_MANA_OIL, MINOR_MANA_OIL, static const std::vector<uint32_t> uPriorizedManaOilIds = {
BRILLIANT_WIZARD_OIL, SUPERIOR_WIZARD_OIL, WIZARD_OIL, LESSER_WIZARD_OIL, MINOR_WIZARD_OIL}; MINOR_MANA_OIL, MINOR_WIZARD_OIL, LESSER_MANA_OIL, LESSER_WIZARD_OIL, BRILLIANT_MANA_OIL,
BRILLIANT_WIZARD_OIL, SUPERIOR_MANA_OIL, WIZARD_OIL, SUPERIOR_WIZARD_OIL};
Item* oil = nullptr; Item* oil = nullptr;
int botClass = bot->getClass(); if (item_template->SubClass == ITEM_SUBCLASS_WEAPON_SWORD ||
int specTab = AiFactory::GetPlayerSpecTab(bot); item_template->SubClass == ITEM_SUBCLASS_WEAPON_STAFF || item_template->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER)
const std::vector<uint32_t>* prioritizedOils = nullptr;
switch (botClass)
{ {
case CLASS_PRIEST: for (const auto& id : uPriorizedWizardOilIds)
prioritizedOils = (specTab == 2) ? &uPrioritizedWizardOilIds : &uPrioritizedManaOilIds;
break;
case CLASS_MAGE:
prioritizedOils = &uPrioritizedWizardOilIds;
break;
case CLASS_DRUID:
if (specTab == 0) // Balance
prioritizedOils = &uPrioritizedWizardOilIds;
else if (specTab == 1) // Feral
prioritizedOils = nullptr;
else // Restoration (specTab == 2) or any other/unspecified spec
prioritizedOils = &uPrioritizedManaOilIds;
break;
case CLASS_HUNTER:
prioritizedOils = &uPrioritizedManaOilIds;
break;
case CLASS_PALADIN:
if (specTab == 1) // Protection
prioritizedOils = &uPrioritizedWizardOilIds;
else if (specTab == 2) // Retribution
prioritizedOils = nullptr;
else // Holy (specTab == 0) or any other/unspecified spec
prioritizedOils = &uPrioritizedManaOilIds;
break;
default:
prioritizedOils = &uPrioritizedManaOilIds;
break;
}
if (prioritizedOils)
{
for (const auto& id : *prioritizedOils)
{ {
oil = FindConsumable(id); oil = FindConsumable(id);
if (oil) if (oil)
{
return oil; return oil;
} }
} }
else if (item_template->SubClass == ITEM_SUBCLASS_WEAPON_MACE ||
item_template->SubClass == ITEM_SUBCLASS_WEAPON_MACE2)
{
for (const auto& id : uPriorizedManaOilIds)
{
oil = FindConsumable(id);
if (oil)
return oil;
}
} }
return oil; return oil;

View File

@ -46,27 +46,27 @@ struct GameObjectData;
enum StrategyType : uint32; enum StrategyType : uint32;
enum HealingItemId enum HealingItemDisplayId
{ {
HEALTHSTONE = 5512, HEALTHSTONE_DISPLAYID = 8026,
MAJOR_HEALING_POTION = 13446, MAJOR_HEALING_POTION = 24152,
WHIPPER_ROOT_TUBER = 11951, WHIPPER_ROOT_TUBER = 21974,
NIGHT_DRAGON_BREATH = 11952, NIGHT_DRAGON_BREATH = 21975,
LIMITED_INVULNERABILITY_POTION = 3387, LIMITED_INVULNERABILITY_POTION = 24213,
GREATER_DREAMLESS_SLEEP_POTION = 22886, GREATER_DREAMLESS_SLEEP_POTION = 17403,
SUPERIOR_HEALING_POTION = 3928, SUPERIOR_HEALING_POTION = 15714,
CRYSTAL_RESTORE = 11564, CRYSTAL_RESTORE = 2516,
DREAMLESS_SLEEP_POTION = 12190, DREAMLESS_SLEEP_POTION = 17403,
GREATER_HEALING_POTION = 1710, GREATER_HEALING_POTION = 15713,
HEALING_POTION = 929, HEALING_POTION = 15712,
LESSER_HEALING_POTION = 858, LESSER_HEALING_POTION = 15711,
DISCOLORED_HEALING_POTION = 3391, DISCOLORED_HEALING_POTION = 15736,
MINOR_HEALING_POTION = 118, MINOR_HEALING_POTION = 15710,
VOLATILE_HEALING_POTION = 28100, VOLATILE_HEALING_POTION = 24212,
SUPER_HEALING_POTION = 22829, SUPER_HEALING_POTION = 37807,
CRYSTAL_HEALING_POTION = 13462, CRYSTAL_HEALING_POTION = 47132,
FEL_REGENERATION_POTION = 28101, FEL_REGENERATION_POTION = 37864,
MAJOR_DREAMLESS_SLEEP_POTION = 20002 MAJOR_DREAMLESS_SLEEP_POTION = 37845
}; };
enum BotState enum BotState
@ -152,7 +152,6 @@ static std::map<ChatChannelSource, std::string> ChatChannelSourceStr = {
{SRC_RAID, "SRC_RAID"}, {SRC_RAID, "SRC_RAID"},
{SRC_UNDEFINED, "SRC_UNDEFINED"}}; {SRC_UNDEFINED, "SRC_UNDEFINED"}};
enum ChatChannelId enum ChatChannelId
{ {
GENERAL = 1, GENERAL = 1,
@ -163,66 +162,60 @@ enum ChatChannelId
GUILD_RECRUITMENT = 25, GUILD_RECRUITMENT = 25,
}; };
enum RoguePoisonId enum RoguePoisonDisplayId
{ {
INSTANT_POISON = 6947, DEADLY_POISON_DISPLAYID = 13707,
INSTANT_POISON_II = 6949, INSTANT_POISON_DISPLAYID = 13710,
INSTANT_POISON_III = 6950, WOUND_POISON_DISPLAYID = 37278
INSTANT_POISON_IV = 8926,
INSTANT_POISON_V = 8927,
INSTANT_POISON_VI = 8928,
INSTANT_POISON_VII = 21927,
INSTANT_POISON_VIII = 43230,
INSTANT_POISON_IX = 43231,
DEADLY_POISON = 2892,
DEADLY_POISON_II = 2893,
DEADLY_POISON_III = 8984,
DEADLY_POISON_IV = 8985,
DEADLY_POISON_V = 20844,
DEADLY_POISON_VI = 22053,
DEADLY_POISON_VII = 22054,
DEADLY_POISON_VIII = 43232,
DEADLY_POISON_IX = 43233
}; };
enum SharpeningStoneId enum SharpeningStoneDisplayId
{ {
ROUGH_SHARPENING_STONE = 2862, ROUGH_SHARPENING_DISPLAYID = 24673,
COARSE_SHARPENING_STONE = 2863, COARSE_SHARPENING_DISPLAYID = 24674,
HEAVY_SHARPENING_STONE = 2871, HEAVY_SHARPENING_DISPLAYID = 24675,
SOLID_SHARPENING_STONE = 7964, SOLID_SHARPENING_DISPLAYID = 24676,
DENSE_SHARPENING_STONE = 12404, DENSE_SHARPENING_DISPLAYID = 24677,
ELEMENTAL_SHARPENING_STONE = 18262, CONSECRATED_SHARPENING_DISPLAYID =
FEL_SHARPENING_STONE = 23528, 24674, // will not be used because bot can not know if it will face undead targets
ADAMANTITE_SHARPENING_STONE = 23529 ELEMENTAL_SHARPENING_DISPLAYID = 21072,
FEL_SHARPENING_DISPLAYID = 39192,
ADAMANTITE_SHARPENING_DISPLAYID = 39193
}; };
enum WeightstoneId enum WeightStoneDisplayId
{ {
ROUGH_WEIGHTSTONE = 3239, ROUGH_WEIGHTSTONE_DISPLAYID = 24683,
COARSE_WEIGHTSTONE = 3240, COARSE_WEIGHTSTONE_DISPLAYID = 24684,
HEAVY_WEIGHTSTONE = 3241, HEAVY_WEIGHTSTONE_DISPLAYID = 24685,
SOLID_WEIGHTSTONE = 7965, SOLID_WEIGHTSTONE_DISPLAYID = 24686,
DENSE_WEIGHTSTONE = 12643, DENSE_WEIGHTSTONE_DISPLAYID = 24687,
FEL_WEIGHTSTONE = 28420, FEL_WEIGHTSTONE_DISPLAYID = 39548,
ADAMANTITE_WEIGHTSTONE = 28421 ADAMANTITE_WEIGHTSTONE_DISPLAYID = 39549
}; };
enum WizardOilId enum WizardOilDisplayId
{ {
MINOR_WIZARD_OIL = 20744, MINOR_WIZARD_OIL = 9731,
LESSER_WIZARD_OIL = 20746, LESSER_WIZARD_OIL = 47903,
WIZARD_OIL = 20750, BRILLIANT_WIZARD_OIL = 47901,
BRILLIANT_WIZARD_OIL = 20749, WIZARD_OIL = 47905,
SUPERIOR_WIZARD_OIL = 22522 SUPERIOR_WIZARD_OIL = 47904,
/// Blessed Wizard Oil = 26865 //scourge inv
}; };
enum ManaOilId enum ManaOilDisplayId
{ {
MINOR_MANA_OIL = 20745, MINOR_MANA_OIL = 34492,
LESSER_MANA_OIL = 20747, LESSER_MANA_OIL = 47902,
BRILLIANT_MANA_OIL = 20748, BRILLIANT_MANA_OIL = 41488,
SUPERIOR_MANA_OIL = 22521 SUPERIOR_MANA_OIL = 36862
};
enum ShieldWardDisplayId
{
LESSER_WARD_OFSHIELDING = 38759,
GREATER_WARD_OFSHIELDING = 38760
}; };
enum class BotTypeNumber : uint8 enum class BotTypeNumber : uint8
@ -479,7 +472,7 @@ public:
Item* FindBandage() const; Item* FindBandage() const;
Item* FindOpenableItem() const; Item* FindOpenableItem() const;
Item* FindLockedItem() const; Item* FindLockedItem() const;
Item* FindConsumable(uint32 itemId) const; Item* FindConsumable(uint32 displayId) const;
Item* FindStoneFor(Item* weapon) const; Item* FindStoneFor(Item* weapon) const;
Item* FindOilFor(Item* weapon) const; Item* FindOilFor(Item* weapon) const;
void ImbueItem(Item* item, uint32 targetFlag, ObjectGuid targetGUID); void ImbueItem(Item* item, uint32 targetFlag, ObjectGuid targetGUID);

View File

@ -630,9 +630,6 @@ bool PlayerbotAIConfig::Initialize()
sPlayerbotDungeonSuggestionMgr->LoadDungeonSuggestions(); sPlayerbotDungeonSuggestionMgr->LoadDungeonSuggestions();
} }
excludedHunterPetFamilies.clear();
LoadList<std::vector<uint32>>(sConfigMgr->GetOption<std::string>("AiPlayerbot.ExcludedHunterPetFamilies", ""), excludedHunterPetFamilies);
LOG_INFO("server.loading", "---------------------------------------"); LOG_INFO("server.loading", "---------------------------------------");
LOG_INFO("server.loading", " AI Playerbots initialized "); LOG_INFO("server.loading", " AI Playerbots initialized ");
LOG_INFO("server.loading", "---------------------------------------"); LOG_INFO("server.loading", "---------------------------------------");

View File

@ -406,8 +406,6 @@ public:
bool restrictHealerDPS = false; bool restrictHealerDPS = false;
std::vector<uint32> restrictedHealerDPSMaps; std::vector<uint32> restrictedHealerDPSMaps;
bool IsRestrictedHealerDPSMap(uint32 mapId) const; bool IsRestrictedHealerDPSMap(uint32 mapId) const;
std::vector<uint32> excludedHunterPetFamilies;
}; };
#define sPlayerbotAIConfig PlayerbotAIConfig::instance() #define sPlayerbotAIConfig PlayerbotAIConfig::instance()

View File

@ -36,8 +36,6 @@
#include "BroadcastHelper.h" #include "BroadcastHelper.h"
#include "PlayerbotDbStore.h" #include "PlayerbotDbStore.h"
#include "WorldSessionMgr.h" #include "WorldSessionMgr.h"
#include "DatabaseEnv.h" // Added for gender choice
#include <algorithm> // Added for gender choice
class BotInitGuard class BotInitGuard
{ {
@ -839,18 +837,6 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje
return "unknown command"; return "unknown command";
} }
// Added for gender choice : Returns the gender of an offline character: 0 = male, 1 = female.
static uint8 GetOfflinePlayerGender(ObjectGuid guid)
{
QueryResult result = CharacterDatabase.Query(
"SELECT gender FROM characters WHERE guid = {}", guid.GetCounter());
if (result)
return (*result)[0].Get<uint8>(); // 0 = male, 1 = female
return GENDER_MALE; // fallback value
}
bool PlayerbotMgr::HandlePlayerbotMgrCommand(ChatHandler* handler, char const* args) bool PlayerbotMgr::HandlePlayerbotMgrCommand(ChatHandler* handler, char const* args)
{ {
if (!sPlayerbotAIConfig->enabled) if (!sPlayerbotAIConfig->enabled)
@ -893,17 +879,15 @@ std::vector<std::string> PlayerbotHolder::HandlePlayerbotCommand(char const* arg
if (!*args) if (!*args)
{ {
messages.push_back("usage: list/reload/tweak/self or add/addaccount/init/remove PLAYERNAME\n"); messages.push_back("usage: list/reload/tweak/self or add/addaccount/init/remove PLAYERNAME\n");
messages.push_back("usage: addclass CLASSNAME [male|female|0|1]"); messages.push_back("usage: addclass CLASSNAME");
return messages; return messages;
} }
char* cmd = strtok((char*)args, " "); char* cmd = strtok((char*)args, " ");
char* charname = strtok(nullptr, " "); char* charname = strtok(nullptr, " ");
char* genderArg = strtok(nullptr, " "); // Added for gender choice [male|female|0|1] optionnel
if (!cmd) if (!cmd)
{ {
messages.push_back("usage: list/reload/tweak/self or add/init/remove PLAYERNAME or addclass CLASSNAME [male|female]"); messages.push_back("usage: list/reload/tweak/self or add/init/remove PLAYERNAME or addclass CLASSNAME");
return messages; return messages;
} }
@ -1126,24 +1110,6 @@ std::vector<std::string> PlayerbotHolder::HandlePlayerbotCommand(char const* arg
messages.push_back("Error: Invalid Class. Try again."); messages.push_back("Error: Invalid Class. Try again.");
return messages; return messages;
} }
// Added for gender choice : Parsing gender
int8 gender = -1; // -1 = gender will be random
if (genderArg)
{
std::string g = genderArg;
std::transform(g.begin(), g.end(), g.begin(), ::tolower);
if (g == "male" || g == "0")
gender = GENDER_MALE; // 0
else if (g == "female" || g == "1")
gender = GENDER_FEMALE; // 1
else
{
messages.push_back("Unknown gender : " + g + " (male/female/0/1)");
return messages;
}
} //end
if (claz == 6 && master->GetLevel() < sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL)) if (claz == 6 && master->GetLevel() < sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL))
{ {
messages.push_back("Your level is too low to summon Deathknight"); messages.push_back("Your level is too low to summon Deathknight");
@ -1153,9 +1119,6 @@ std::vector<std::string> PlayerbotHolder::HandlePlayerbotCommand(char const* arg
const std::unordered_set<ObjectGuid> &guidCache = sRandomPlayerbotMgr->addclassCache[RandomPlayerbotMgr::GetTeamClassIdx(teamId == TEAM_ALLIANCE, claz)]; const std::unordered_set<ObjectGuid> &guidCache = sRandomPlayerbotMgr->addclassCache[RandomPlayerbotMgr::GetTeamClassIdx(teamId == TEAM_ALLIANCE, claz)];
for (const ObjectGuid &guid: guidCache) for (const ObjectGuid &guid: guidCache)
{ {
// If the user requested a specific gender, skip any character that doesn't match.
if (gender != -1 && GetOfflinePlayerGender(guid) != gender)
continue;
if (botLoading.find(guid) != botLoading.end()) if (botLoading.find(guid) != botLoading.end())
continue; continue;
if (ObjectAccessor::FindConnectedPlayer(guid)) if (ObjectAccessor::FindConnectedPlayer(guid))

View File

@ -197,13 +197,21 @@ public:
sRandomPlayerbotMgr->HandleCommand(type, msg, player); sRandomPlayerbotMgr->HandleCommand(type, msg, player);
} }
bool OnPlayerBeforeAchievementComplete(Player* player, AchievementEntry const* achievement) override bool OnPlayerBeforeCriteriaProgress(Player* player, AchievementCriteriaEntry const* /*criteria*/) override
{ {
if (sRandomPlayerbotMgr->IsRandomBot(player) && (achievement->flags == 256 || achievement->flags == 768)) if (sRandomPlayerbotMgr->IsRandomBot(player))
{ {
return false; return false;
} }
return true;
}
bool OnPlayerBeforeAchievementComplete(Player* player, AchievementEntry const* /*achievement*/) override
{
if (sRandomPlayerbotMgr->IsRandomBot(player))
{
return false;
}
return true; return true;
} }

View File

@ -414,7 +414,7 @@ void PlayerbotFactory::Randomize(bool incremental)
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Consumable"); pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Consumable");
LOG_DEBUG("playerbots", "Initializing consumables..."); LOG_DEBUG("playerbots", "Initializing consumables...");
InitConsumables(); AddConsumables();
if (pmo) if (pmo)
pmo->finish(); pmo->finish();
@ -482,8 +482,11 @@ void PlayerbotFactory::Refresh()
InitAmmo(); InitAmmo();
InitFood(); InitFood();
InitReagents(); InitReagents();
InitConsumables(); // InitPotions();
InitPotions(); if (!sPlayerbotAIConfig->equipmentPersistence || bot->GetLevel() < sPlayerbotAIConfig->equipmentPersistenceLevel)
{
InitTalentsTree(true, true, true);
}
InitPet(); InitPet();
InitPetTalents(); InitPetTalents();
InitClassSpells(); InitClassSpells();
@ -493,10 +496,7 @@ void PlayerbotFactory::Refresh()
InitSpecialSpells(); InitSpecialSpells();
InitMounts(); InitMounts();
InitKeyring(); InitKeyring();
if (!sPlayerbotAIConfig->equipmentPersistence || bot->GetLevel() < sPlayerbotAIConfig->equipmentPersistenceLevel) InitPotions();
{
InitTalentsTree(true, true, true);
}
if (bot->GetLevel() >= sPlayerbotAIConfig->minEnchantingBotLevel) if (bot->GetLevel() >= sPlayerbotAIConfig->minEnchantingBotLevel)
{ {
ApplyEnchantAndGemsNew(); ApplyEnchantAndGemsNew();
@ -510,217 +510,150 @@ void PlayerbotFactory::Refresh()
// bot->SaveToDB(false, false); // bot->SaveToDB(false, false);
} }
void PlayerbotFactory::InitConsumables() void PlayerbotFactory::AddConsumables()
{ {
int specTab = AiFactory::GetPlayerSpecTab(bot);
std::vector<std::pair<uint32, uint32>> items;
switch (bot->getClass()) switch (bot->getClass())
{ {
case CLASS_PRIEST: case CLASS_PRIEST:
{
// Discipline or Holy: Mana Oil
if (specTab == 0 || specTab == 1)
{
std::vector<uint32> mana_oils = {BRILLIANT_MANA_OIL, SUPERIOR_MANA_OIL, LESSER_MANA_OIL, MINOR_MANA_OIL};
for (uint32 itemId : mana_oils)
{
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
if (proto->RequiredLevel > level || level > 75)
continue;
items.push_back({itemId, 4});
break;
}
}
// Shadow: Wizard Oil
if (specTab == 2)
{
std::vector<uint32> wizard_oils = {BRILLIANT_WIZARD_OIL, SUPERIOR_WIZARD_OIL, WIZARD_OIL, LESSER_WIZARD_OIL, MINOR_WIZARD_OIL};
for (uint32 itemId : wizard_oils)
{
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
if (proto->RequiredLevel > level || level > 75)
continue;
items.push_back({itemId, 4});
break;
}
}
break;
}
case CLASS_MAGE: case CLASS_MAGE:
case CLASS_WARLOCK:
{ {
// Always Wizard Oil if (level >= 5 && level < 20)
std::vector<uint32> wizard_oils = {BRILLIANT_WIZARD_OIL, SUPERIOR_WIZARD_OIL, WIZARD_OIL, LESSER_WIZARD_OIL, MINOR_WIZARD_OIL};
for (uint32 itemId : wizard_oils)
{ {
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); StoreItem(CONSUM_ID_MINOR_WIZARD_OIL, 5);
if (proto->RequiredLevel > level || level > 75)
continue;
items.push_back({itemId, 4});
break;
} }
break;
if (level >= 20 && level < 40)
{
StoreItem(CONSUM_ID_MINOR_MANA_OIL, 5);
StoreItem(CONSUM_ID_MINOR_WIZARD_OIL, 5);
} }
case CLASS_DRUID:
if (level >= 40 && level < 45)
{ {
// Balance: Wizard Oil StoreItem(CONSUM_ID_MINOR_MANA_OIL, 5);
if (specTab == 0) StoreItem(CONSUM_ID_WIZARD_OIL, 5);
{
std::vector<uint32> wizard_oils = {BRILLIANT_WIZARD_OIL, SUPERIOR_WIZARD_OIL, WIZARD_OIL, LESSER_WIZARD_OIL, MINOR_WIZARD_OIL};
for (uint32 itemId : wizard_oils)
{
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
if (proto->RequiredLevel > level || level > 75)
continue;
items.push_back({itemId, 4});
break;
} }
}
// Feral: Sharpening Stones & Weightstones if (level >= 45 && level < 52)
else if (specTab == 1)
{ {
std::vector<uint32> sharpening_stones = {ADAMANTITE_SHARPENING_STONE, FEL_SHARPENING_STONE, DENSE_SHARPENING_STONE, SOLID_SHARPENING_STONE, HEAVY_SHARPENING_STONE, COARSE_SHARPENING_STONE, ROUGH_SHARPENING_STONE}; StoreItem(CONSUM_ID_BRILLIANT_MANA_OIL, 5);
std::vector<uint32> weightstones = {ADAMANTITE_WEIGHTSTONE, FEL_WEIGHTSTONE, DENSE_WEIGHTSTONE, SOLID_WEIGHTSTONE, HEAVY_WEIGHTSTONE, COARSE_WEIGHTSTONE, ROUGH_WEIGHTSTONE}; StoreItem(CONSUM_ID_BRILLIANT_WIZARD_OIL, 5);
for (uint32 itemId : sharpening_stones)
{
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
if (proto->RequiredLevel > level || level > 75)
continue;
items.push_back({itemId, 20});
break;
} }
for (uint32 itemId : weightstones) if (level >= 52 && level < 58)
{ {
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); StoreItem(CONSUM_ID_SUPERIOR_MANA_OIL, 5);
if (proto->RequiredLevel > level || level > 75) StoreItem(CONSUM_ID_BRILLIANT_WIZARD_OIL, 5);
continue;
items.push_back({itemId, 20});
break;
} }
}
// Restoration: Mana Oil if (level >= 58)
else if (specTab == 2)
{ {
std::vector<uint32> mana_oils = {BRILLIANT_MANA_OIL, SUPERIOR_MANA_OIL, LESSER_MANA_OIL, MINOR_MANA_OIL}; StoreItem(CONSUM_ID_SUPERIOR_MANA_OIL, 5);
for (uint32 itemId : mana_oils) StoreItem(CONSUM_ID_SUPERIOR_WIZARD_OIL, 5);
{
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
if (proto->RequiredLevel > level || level > 75)
continue;
items.push_back({itemId, 4});
break;
}
} }
break; break;
} }
case CLASS_PALADIN: case CLASS_PALADIN:
{
// Holy: Mana Oil
if (specTab == 0)
{
std::vector<uint32> mana_oils = {BRILLIANT_MANA_OIL, SUPERIOR_MANA_OIL, LESSER_MANA_OIL, MINOR_MANA_OIL};
for (uint32 itemId : mana_oils)
{
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
if (proto->RequiredLevel > level || level > 75)
continue;
items.push_back({itemId, 4});
break;
}
}
// Protection: Wizard Oil (Protection prioritizes Superior over Brilliant)
else if (specTab == 1)
{
std::vector<uint32> wizard_oils = {BRILLIANT_WIZARD_OIL, SUPERIOR_WIZARD_OIL, WIZARD_OIL, LESSER_WIZARD_OIL, MINOR_WIZARD_OIL};
for (uint32 itemId : wizard_oils)
{
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
if (proto->RequiredLevel > level || level > 75)
continue;
items.push_back({itemId, 4});
break;
}
}
// Retribution: Sharpening Stones & Weightstones
else if (specTab == 2)
{
std::vector<uint32> sharpening_stones = {ADAMANTITE_SHARPENING_STONE, FEL_SHARPENING_STONE, DENSE_SHARPENING_STONE, SOLID_SHARPENING_STONE, HEAVY_SHARPENING_STONE, COARSE_SHARPENING_STONE, ROUGH_SHARPENING_STONE};
std::vector<uint32> weightstones = {ADAMANTITE_WEIGHTSTONE, FEL_WEIGHTSTONE, DENSE_WEIGHTSTONE, SOLID_WEIGHTSTONE, HEAVY_WEIGHTSTONE, COARSE_WEIGHTSTONE, ROUGH_WEIGHTSTONE};
for (uint32 itemId : sharpening_stones)
{
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
if (proto->RequiredLevel > level || level > 75)
continue;
items.push_back({itemId, 20});
break;
}
for (uint32 itemId : weightstones)
{
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
if (proto->RequiredLevel > level || level > 75)
continue;
items.push_back({itemId, 20});
break;
}
}
break;
}
case CLASS_WARRIOR: case CLASS_WARRIOR:
case CLASS_HUNTER: case CLASS_HUNTER:
{ {
// Sharpening Stones & Weightstones if (level >= 1 && level < 5)
std::vector<uint32> sharpening_stones = {ADAMANTITE_SHARPENING_STONE, FEL_SHARPENING_STONE, DENSE_SHARPENING_STONE, SOLID_SHARPENING_STONE, HEAVY_SHARPENING_STONE, COARSE_SHARPENING_STONE, ROUGH_SHARPENING_STONE};
std::vector<uint32> weightstones = {ADAMANTITE_WEIGHTSTONE, FEL_WEIGHTSTONE, DENSE_WEIGHTSTONE, SOLID_WEIGHTSTONE, HEAVY_WEIGHTSTONE, COARSE_WEIGHTSTONE, ROUGH_WEIGHTSTONE};
for (uint32 itemId : sharpening_stones)
{ {
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); StoreItem(CONSUM_ID_ROUGH_SHARPENING_STONE, 5);
if (proto->RequiredLevel > level || level > 75) StoreItem(CONSUM_ID_ROUGH_WEIGHTSTONE, 5);
continue;
items.push_back({itemId, 20});
break;
} }
for (uint32 itemId : weightstones)
if (level >= 5 && level < 15)
{ {
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); StoreItem(CONSUM_ID_COARSE_WEIGHTSTONE, 5);
if (proto->RequiredLevel > level || level > 75) StoreItem(CONSUM_ID_COARSE_SHARPENING_STONE, 5);
continue; }
items.push_back({itemId, 20});
break; if (level >= 15 && level < 25)
{
StoreItem(CONSUM_ID_HEAVY_WEIGHTSTONE, 5);
StoreItem(CONSUM_ID_HEAVY_SHARPENING_STONE, 5);
}
if (level >= 25 && level < 35)
{
StoreItem(CONSUM_ID_SOL_SHARPENING_STONE, 5);
StoreItem(CONSUM_ID_SOLID_WEIGHTSTONE, 5);
}
if (level >= 35 && level < 50)
{
StoreItem(CONSUM_ID_DENSE_WEIGHTSTONE, 5);
StoreItem(CONSUM_ID_DENSE_SHARPENING_STONE, 5);
}
if (level >= 50 && level < 60)
{
StoreItem(CONSUM_ID_FEL_SHARPENING_STONE, 5);
StoreItem(CONSUM_ID_FEL_WEIGHTSTONE, 5);
}
if (level >= 60)
{
StoreItem(CONSUM_ID_ADAMANTITE_WEIGHTSTONE, 5);
StoreItem(CONSUM_ID_ADAMANTITE_SHARPENING_STONE, 5);
} }
break; break;
} }
case CLASS_ROGUE: case CLASS_ROGUE:
{ {
// Poisons if (level >= 20 && level < 28)
std::vector<uint32> instant_poisons = {INSTANT_POISON_IX, INSTANT_POISON_VIII, INSTANT_POISON_VII, INSTANT_POISON_VI, INSTANT_POISON_V, INSTANT_POISON_IV, INSTANT_POISON_III, INSTANT_POISON_II, INSTANT_POISON};
std::vector<uint32> deadly_poisons = {DEADLY_POISON_IX, DEADLY_POISON_VIII, DEADLY_POISON_VII, DEADLY_POISON_VI, DEADLY_POISON_V, DEADLY_POISON_IV, DEADLY_POISON_III, DEADLY_POISON_II, DEADLY_POISON};
for (uint32 itemId : deadly_poisons)
{ {
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); StoreItem(CONSUM_ID_INSTANT_POISON, 5);
if (proto->RequiredLevel > level)
continue;
items.push_back({itemId, 20});
break;
}
for (uint32 itemId : instant_poisons)
{
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
if (proto->RequiredLevel > level)
continue;
items.push_back({itemId, 20});
break;
}
break;
}
default:
break;
} }
for (std::pair<uint32, uint32> item : items) if (level >= 28 && level < 30)
{ {
int count = (int)item.second - (int)bot->GetItemCount(item.first); StoreItem(CONSUM_ID_INSTANT_POISON_II, 5);
if (count > 0) }
StoreItem(item.first, count);
if (level >= 30 && level < 36)
{
StoreItem(CONSUM_ID_DEADLY_POISON, 5);
StoreItem(CONSUM_ID_INSTANT_POISON_II, 5);
}
if (level >= 36 && level < 44)
{
StoreItem(CONSUM_ID_DEADLY_POISON_II, 5);
StoreItem(CONSUM_ID_INSTANT_POISON_III, 5);
}
if (level >= 44 && level < 52)
{
StoreItem(CONSUM_ID_DEADLY_POISON_III, 5);
StoreItem(CONSUM_ID_INSTANT_POISON_IV, 5);
}
if (level >= 52 && level < 60)
{
StoreItem(CONSUM_ID_DEADLY_POISON_IV, 5);
StoreItem(CONSUM_ID_INSTANT_POISON_V, 5);
}
if (level >= 60 && level < 62)
{
StoreItem(CONSUM_ID_DEADLY_POISON_V, 5);
StoreItem(CONSUM_ID_INSTANT_POISON_VI, 5);
}
if (level >= 62 && level < 68)
{
StoreItem(CONSUM_ID_DEADLY_POISON_VI, 5);
StoreItem(CONSUM_ID_INSTANT_POISON_VI, 5);
}
if (level >= 68)
{
StoreItem(CONSUM_ID_DEADLY_POISON_VII, 5);
StoreItem(CONSUM_ID_INSTANT_POISON_VII, 5);
}
break;
}
} }
} }
@ -895,7 +828,6 @@ void PlayerbotFactory::InitPet()
std::vector<uint32> ids; std::vector<uint32> ids;
CreatureTemplateContainer const* creatures = sObjectMgr->GetCreatureTemplates(); CreatureTemplateContainer const* creatures = sObjectMgr->GetCreatureTemplates();
for (CreatureTemplateContainer::const_iterator itr = creatures->begin(); itr != creatures->end(); ++itr) for (CreatureTemplateContainer::const_iterator itr = creatures->begin(); itr != creatures->end(); ++itr)
{ {
if (!itr->second.IsTameable(bot->CanTameExoticPets())) if (!itr->second.IsTameable(bot->CanTameExoticPets()))
@ -911,12 +843,6 @@ void PlayerbotFactory::InitPet()
if (onlyWolf && itr->second.family != CREATURE_FAMILY_WOLF) if (onlyWolf && itr->second.family != CREATURE_FAMILY_WOLF)
continue; continue;
// Exclude configured pet families
if (std::find(sPlayerbotAIConfig->excludedHunterPetFamilies.begin(),
sPlayerbotAIConfig->excludedHunterPetFamilies.end(),
itr->second.family) != sPlayerbotAIConfig->excludedHunterPetFamilies.end())
continue;
ids.push_back(itr->first); ids.push_back(itr->first);
} }
@ -3294,97 +3220,102 @@ void PlayerbotFactory::InitFood()
void PlayerbotFactory::InitReagents() void PlayerbotFactory::InitReagents()
{ {
int specTab = AiFactory::GetPlayerSpecTab(bot); int level = bot->GetLevel();
std::vector<std::pair<uint32, uint32>> items; std::vector<std::pair<uint32, uint32>> items;
switch (bot->getClass()) switch (bot->getClass())
{ {
case CLASS_DEATH_KNIGHT: case CLASS_ROGUE:
if (level >= 56) {
items.push_back({37201, 40}); // Corpse Dust std::vector<int> instant_poison_ids = {43231, 43230, 21927, 8928, 8927, 8926, 6950, 6949, 6947};
std::vector<int> deadly_poison_ids = {43233, 43232, 22054, 22053, 20844, 8985, 8984, 2893, 2892};
for (int& itemId : deadly_poison_ids)
{
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
if (proto->RequiredLevel > bot->GetLevel())
continue;
items.push_back({itemId, 20}); // deadly poison
break; break;
case CLASS_DRUID:
if (level >= 20 && level < 30)
items.push_back({17034, 20}); // Maple Seed
else if (level >= 30 && level < 40)
items.push_back({17035, 20}); // Stranglethorn Seed
else if (level >= 40 && level < 50)
items.push_back({17036, 20}); // Ashwood Seed
else if (level >= 50 && level < 60)
{
items.push_back({17037, 20}); // Hornbeam Seed
items.push_back({17021, 20}); // Wild Berries
} }
else if (level >= 60 && level < 69) for (int& itemId : instant_poison_ids)
{ {
items.push_back({17038, 20}); // Ironwood Seed ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
items.push_back({17026, 20}); // Wild Thornroot if (proto->RequiredLevel > bot->GetLevel())
continue;
items.push_back({itemId, 20}); // instant poison
break;
} }
else if (level == 69)
{
items.push_back({22147, 20}); // Flintweed Seed
items.push_back({17026, 20}); // Wild Thornroot
} }
else if (level >= 70 && level < 79) break;
case CLASS_SHAMAN:
// items.push_back({46978, 1}); // Totem
items.push_back({5175, 1}); // Earth Totem
items.push_back({5176, 1}); // Flame Totem
items.push_back({5177, 1}); // Water Totem
items.push_back({5178, 1}); // Air Totem
if (bot->GetLevel() >= 30)
items.push_back({17030, 40}); // Ankh
break;
case CLASS_WARLOCK:
items.push_back({6265, 5}); // shard
break;
case CLASS_PRIEST:
if (level >= 48 && level < 60)
{ {
items.push_back({22147, 20}); // Flintweed Seed items.push_back({17028, 40}); // Wild Berries
items.push_back({22148, 20}); // Wild Quillvine
} }
else if (level == 79) else if (level >= 60 && level < 80)
{ {
items.push_back({44614, 20}); // Starleaf Seed items.push_back({17029, 40}); // Wild Berries
items.push_back({22148, 20}); // Wild Quillvine
} }
else if (level >= 80) else if (level >= 80)
{ {
items.push_back({44614, 20}); // Starleaf Seed items.push_back({44615, 40}); // Wild Berries
items.push_back({44605, 20}); // Wild Spineleaf
} }
break; break;
case CLASS_MAGE: case CLASS_MAGE:
if (level >= 20) items.push_back({17020, 40}); // Arcane Powder
items.push_back({17031, 20}); // Rune of Teleportation items.push_back({17031, 40}); // portal
if (level >= 40) items.push_back({17032, 40}); // portal
items.push_back({17032, 20}); // Rune of Portals break;
if (level >= 56) case CLASS_DRUID:
items.push_back({17020, 20}); // Arcane Powder if (level >= 20 && level < 30)
{
items.push_back({17034, 40});
}
if (level >= 30 && level < 40)
{
items.push_back({17035, 40});
}
if (level >= 40 && level < 50)
{
items.push_back({17036, 40});
}
if (level >= 50 && level < 60)
{
items.push_back({17037, 40});
items.push_back({17021, 40});
}
if (level >= 60 && level < 70)
{
items.push_back({17038, 40});
items.push_back({17026, 40});
}
if (level >= 70 && level < 80)
{
items.push_back({22147, 40});
items.push_back({22148, 40});
}
if (level >= 80)
{
items.push_back({44614, 40});
items.push_back({44605, 40});
}
break; break;
case CLASS_PALADIN: case CLASS_PALADIN:
if (level >= 52) items.push_back({21177, 100});
items.push_back({21177, 80}); // Symbol of Kings
break; break;
case CLASS_PRIEST: case CLASS_DEATH_KNIGHT:
if (level >= 48 && level < 56) items.push_back({37201, 40});
items.push_back({17028, 40}); // Holy Candle
else if (level >= 56 && level < 60)
{
items.push_back({17028, 20}); // Holy Candle
items.push_back({17029, 20}); // Sacred Candle
}
else if (level >= 60 && level < 77)
items.push_back({17029, 40}); // Sacred Candle
else if (level >= 77 && level < 80)
{
items.push_back({17029, 20}); // Sacred Candle
items.push_back({44615, 20}); // Devout Candle
}
else if (level >= 80)
items.push_back({44615, 40}); // Devout Candle
break;
case CLASS_SHAMAN:
if (level >= 4)
items.push_back({5175, 1}); // Earth Totem
if (level >= 10)
items.push_back({5176, 1}); // Flame Totem
if (level >= 20)
items.push_back({5177, 1}); // Water Totem
if (level >= 30)
{
items.push_back({5178, 1}); // Air Totem
items.push_back({17030, 20}); // Ankh
}
break;
case CLASS_WARLOCK:
items.push_back({6265, 5}); // Soul Shard
break; break;
default: default:
break; break;
@ -3397,73 +3328,10 @@ void PlayerbotFactory::InitReagents()
} }
} }
void PlayerbotFactory::CleanupConsumables() // remove old consumables as part of randombot level-up maintenance
{
std::vector<Item*> itemsToDelete;
std::vector<Item*> items;
for (uint32 i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; ++i)
if (Item* item = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, i))
items.push_back(item);
for (uint32 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
if (Bag* bag = (Bag*)bot->GetItemByPos(INVENTORY_SLOT_BAG_0, i))
for (uint32 j = 0; j < bag->GetBagSize(); ++j)
if (Item* item = bag->GetItemByPos(j))
items.push_back(item);
for (Item* item : items)
{
ItemTemplate const* proto = item->GetTemplate();
if (!proto) continue;
// Remove ammo
if (proto->Class == ITEM_CLASS_PROJECTILE)
itemsToDelete.push_back(item);
// Remove food/drink
if (proto->Class == ITEM_CLASS_CONSUMABLE && proto->SubClass == ITEM_SUBCLASS_FOOD)
itemsToDelete.push_back(item);
// Remove potions
if (proto->Class == ITEM_CLASS_CONSUMABLE && proto->SubClass == ITEM_SUBCLASS_POTION)
itemsToDelete.push_back(item);
// Remove reagents
if (proto->Class == ITEM_CLASS_REAGENT || (proto->Class == ITEM_CLASS_MISC && proto->SubClass == ITEM_SUBCLASS_REAGENT))
itemsToDelete.push_back(item);
}
std::set<uint32> idsToDelete = {
BRILLIANT_MANA_OIL, SUPERIOR_MANA_OIL, LESSER_MANA_OIL, MINOR_MANA_OIL,
BRILLIANT_WIZARD_OIL, SUPERIOR_WIZARD_OIL, WIZARD_OIL, LESSER_WIZARD_OIL, MINOR_WIZARD_OIL,
ADAMANTITE_SHARPENING_STONE, FEL_SHARPENING_STONE, DENSE_SHARPENING_STONE, SOLID_SHARPENING_STONE,
HEAVY_SHARPENING_STONE, COARSE_SHARPENING_STONE, ROUGH_SHARPENING_STONE,
ADAMANTITE_WEIGHTSTONE, FEL_WEIGHTSTONE, DENSE_WEIGHTSTONE, SOLID_WEIGHTSTONE,
HEAVY_WEIGHTSTONE, COARSE_WEIGHTSTONE, ROUGH_WEIGHTSTONE,
INSTANT_POISON_IX, INSTANT_POISON_VIII, INSTANT_POISON_VII, INSTANT_POISON_VI, INSTANT_POISON_V,
INSTANT_POISON_IV, INSTANT_POISON_III, INSTANT_POISON_II, INSTANT_POISON,
DEADLY_POISON_IX, DEADLY_POISON_VIII, DEADLY_POISON_VII, DEADLY_POISON_VI, DEADLY_POISON_V,
DEADLY_POISON_IV, DEADLY_POISON_III, DEADLY_POISON_II, DEADLY_POISON
};
for (Item* item : items)
{
ItemTemplate const* proto = item->GetTemplate();
if (!proto) continue;
if (idsToDelete.find(proto->ItemId) != idsToDelete.end())
itemsToDelete.push_back(item);
}
for (Item* item : itemsToDelete)
bot->DestroyItem(item->GetBagSlot(), item->GetSlot(), true);
}
void PlayerbotFactory::InitGlyphs(bool increment) void PlayerbotFactory::InitGlyphs(bool increment)
{ {
bot->InitGlyphsForLevel(); bot->InitGlyphsForLevel();
if (!increment && botAI && if (!increment &&
botAI->GetAiObjectContext()->GetValue<bool>("custom_glyphs")->Get()) botAI->GetAiObjectContext()->GetValue<bool>("custom_glyphs")->Get())
return; // // Added for custom Glyphs - custom glyphs flag test return; // // Added for custom Glyphs - custom glyphs flag test

View File

@ -45,6 +45,63 @@ enum spec : uint8
ROLE_CDPS = 3 ROLE_CDPS = 3
};*/ };*/
enum PriorizedConsumables
{
CONSUM_ID_ROUGH_WEIGHTSTONE = 3239,
CONSUM_ID_COARSE_WEIGHTSTONE = 3239,
CONSUM_ID_HEAVY_WEIGHTSTONE = 3241,
CONSUM_ID_SOLID_WEIGHTSTONE = 7965,
CONSUM_ID_DENSE_WEIGHTSTONE = 12643,
CONSUM_ID_FEL_WEIGHTSTONE = 28420,
CONSUM_ID_ADAMANTITE_WEIGHTSTONE = 28421,
CONSUM_ID_ROUGH_SHARPENING_STONE = 2862,
CONSUM_ID_COARSE_SHARPENING_STONE = 2863,
CONSUM_ID_HEAVY_SHARPENING_STONE = 2871,
CONSUM_ID_SOL_SHARPENING_STONE = 7964,
CONSUM_ID_DENSE_SHARPENING_STONE = 12404,
CONSUM_ID_ELEMENTAL_SHARPENING_STONE = 18262,
CONSUM_ID_CONSECRATED_SHARPENING_STONE = 23122,
CONSUM_ID_FEL_SHARPENING_STONE = 23528,
CONSUM_ID_ADAMANTITE_SHARPENING_STONE = 23529,
CONSUM_ID_LINEN_BANDAGE = 1251,
CONSUM_ID_HEAVY_LINEN_BANDAGE = 2581,
CONSUM_ID_WOOL_BANDAGE = 3530,
CONSUM_ID_HEAVY_WOOL_BANDAGE = 3531,
CONSUM_ID_SILK_BANDAGE = 6450,
CONSUM_ID_HEAVY_SILK_BANDAGE = 6451,
CONSUM_ID_MAGEWEAVE_BANDAGE = 8544,
CONSUM_ID_HEAVY_MAGEWEAVE_BANDAGE = 8545,
CONSUM_ID_RUNECLOTH_BANDAGE = 14529,
CONSUM_ID_HEAVY_RUNECLOTH_BANDAGE = 14530,
CONSUM_ID_NETHERWEAVE_BANDAGE = 21990,
CONSUM_ID_HEAVY_NETHERWEAVE_BANDAGE = 21991,
CONSUM_ID_BRILLIANT_MANA_OIL = 20748,
CONSUM_ID_MINOR_MANA_OIL = 20745,
CONSUM_ID_SUPERIOR_MANA_OIL = 22521,
CONSUM_ID_LESSER_MANA_OIL = 20747,
CONSUM_ID_BRILLIANT_WIZARD_OIL = 20749,
CONSUM_ID_MINOR_WIZARD_OIL = 20744,
CONSUM_ID_SUPERIOR_WIZARD_OIL = 22522,
CONSUM_ID_WIZARD_OIL = 20750,
CONSUM_ID_LESSER_WIZARD_OIL = 20746,
CONSUM_ID_INSTANT_POISON = 6947,
CONSUM_ID_INSTANT_POISON_II = 6949,
CONSUM_ID_INSTANT_POISON_III = 6950,
CONSUM_ID_INSTANT_POISON_IV = 8926,
CONSUM_ID_INSTANT_POISON_V = 8927,
CONSUM_ID_INSTANT_POISON_VI = 8928,
CONSUM_ID_INSTANT_POISON_VII = 21927,
CONSUM_ID_DEADLY_POISON = 2892,
CONSUM_ID_DEADLY_POISON_II = 2893,
CONSUM_ID_DEADLY_POISON_III = 8984,
CONSUM_ID_DEADLY_POISON_IV = 8985,
CONSUM_ID_DEADLY_POISON_V = 20844,
CONSUM_ID_DEADLY_POISON_VI = 22053,
CONSUM_ID_DEADLY_POISON_VII = 22054
};
#define MAX_CONSUM_ID 28
class PlayerbotFactory class PlayerbotFactory
{ {
public: public:
@ -71,10 +128,8 @@ public:
void InitAmmo(); void InitAmmo();
static uint32 CalcMixedGearScore(uint32 gs, uint32 quality); static uint32 CalcMixedGearScore(uint32 gs, uint32 quality);
void InitPetTalents(); void InitPetTalents();
void CleanupConsumables();
void InitReagents(); void InitReagents();
void InitConsumables();
void InitPotions();
void InitGlyphs(bool increment = false); void InitGlyphs(bool increment = false);
void InitFood(); void InitFood();
void InitMounts(); void InitMounts();
@ -85,6 +140,7 @@ public:
void InitKeyring(); void InitKeyring();
void InitReputation(); void InitReputation();
void InitAttunementQuests(); void InitAttunementQuests();
void InitPotions();
private: private:
void Prepare(); void Prepare();
@ -121,6 +177,7 @@ private:
void InitGuild(); void InitGuild();
void InitArenaTeam(); void InitArenaTeam();
void InitImmersive(); void InitImmersive();
void AddConsumables();
static void AddPrevQuests(uint32 questId, std::list<uint32>& questIds); static void AddPrevQuests(uint32 questId, std::list<uint32>& questIds);
void LoadEnchantContainer(); void LoadEnchantContainer();
void ApplyEnchantTemplate(); void ApplyEnchantTemplate();

View File

@ -38,7 +38,6 @@
#include "InviteToGroupAction.h" #include "InviteToGroupAction.h"
#include "LeaveGroupAction.h" #include "LeaveGroupAction.h"
#include "LootAction.h" #include "LootAction.h"
#include "LootRollAction.h"
#include "MoveToRpgTargetAction.h" #include "MoveToRpgTargetAction.h"
#include "MoveToTravelTargetAction.h" #include "MoveToTravelTargetAction.h"
#include "MovementActions.h" #include "MovementActions.h"
@ -191,7 +190,6 @@ public:
creators["buy tabard"] = &ActionContext::buy_tabard; creators["buy tabard"] = &ActionContext::buy_tabard;
creators["guild manage nearby"] = &ActionContext::guild_manage_nearby; creators["guild manage nearby"] = &ActionContext::guild_manage_nearby;
creators["clean quest log"] = &ActionContext::clean_quest_log; creators["clean quest log"] = &ActionContext::clean_quest_log;
creators["roll"] = &ActionContext::roll_action;
creators["cancel channel"] = &ActionContext::cancel_channel; creators["cancel channel"] = &ActionContext::cancel_channel;
// BG Tactics // BG Tactics
@ -379,7 +377,6 @@ private:
static Action* buy_tabard(PlayerbotAI* botAI) { return new BuyTabardAction(botAI); } static Action* buy_tabard(PlayerbotAI* botAI) { return new BuyTabardAction(botAI); }
static Action* guild_manage_nearby(PlayerbotAI* botAI) { return new GuildManageNearbyAction(botAI); } static Action* guild_manage_nearby(PlayerbotAI* botAI) { return new GuildManageNearbyAction(botAI); }
static Action* clean_quest_log(PlayerbotAI* botAI) { return new CleanQuestLogAction(botAI); } static Action* clean_quest_log(PlayerbotAI* botAI) { return new CleanQuestLogAction(botAI); }
static Action* roll_action(PlayerbotAI* botAI) { return new RollAction(botAI); }
// BG Tactics // BG Tactics
static Action* bg_tactics(PlayerbotAI* botAI) { return new BGTactics(botAI); } static Action* bg_tactics(PlayerbotAI* botAI) { return new BGTactics(botAI); }

View File

@ -157,23 +157,16 @@ void AutoMaintenanceOnLevelupAction::LearnSpell(uint32 spellId, std::ostringstre
void AutoMaintenanceOnLevelupAction::AutoUpgradeEquip() void AutoMaintenanceOnLevelupAction::AutoUpgradeEquip()
{ {
if (!sPlayerbotAIConfig->autoUpgradeEquip || !sRandomPlayerbotMgr->IsRandomBot(bot)) if (!sPlayerbotAIConfig->autoUpgradeEquip || !sRandomPlayerbotMgr->IsRandomBot(bot))
{
return; return;
}
PlayerbotFactory factory(bot, bot->GetLevel()); PlayerbotFactory factory(bot, bot->GetLevel());
// Clean up old consumables before adding new ones
factory.CleanupConsumables();
factory.InitAmmo();
factory.InitReagents();
factory.InitFood();
factory.InitConsumables();
factory.InitPotions();
if (!sPlayerbotAIConfig->equipmentPersistence || bot->GetLevel() < sPlayerbotAIConfig->equipmentPersistenceLevel) if (!sPlayerbotAIConfig->equipmentPersistence || bot->GetLevel() < sPlayerbotAIConfig->equipmentPersistenceLevel)
{ {
if (sPlayerbotAIConfig->incrementalGearInit) if (sPlayerbotAIConfig->incrementalGearInit)
factory.InitEquipment(true); factory.InitEquipment(true);
} }
factory.InitAmmo();
return;
} }

View File

@ -50,16 +50,3 @@ bool BossNatureResistanceAction::Execute(Event event)
botAI->ChangeStrategy(ADD_STRATEGY_CHAR + hunterNatureResistanceStrategy.getName(), BotState::BOT_STATE_COMBAT); botAI->ChangeStrategy(ADD_STRATEGY_CHAR + hunterNatureResistanceStrategy.getName(), BotState::BOT_STATE_COMBAT);
return true; return true;
} }
bool BossShadowResistanceAction::isUseful()
{
BossShadowResistanceTrigger bossShadowResistanceTrigger(botAI, bossName);
return bossShadowResistanceTrigger.IsActive();
}
bool BossShadowResistanceAction::Execute(Event event)
{
PaladinShadowResistanceStrategy paladinShadowResistanceStrategy(botAI);
botAI->ChangeStrategy(ADD_STRATEGY_CHAR + paladinShadowResistanceStrategy.getName(), BotState::BOT_STATE_COMBAT);
return true;
}

View File

@ -54,18 +54,4 @@ private:
std::string bossName; std::string bossName;
}; };
class BossShadowResistanceAction : public Action
{
public:
BossShadowResistanceAction(PlayerbotAI* botAI, std::string const bossName)
: Action(botAI, bossName + " shadow resistance action"), bossName(bossName)
{
}
bool Execute(Event event) override;
bool isUseful() override;
private:
std::string bossName;
};
#endif #endif

View File

@ -36,7 +36,6 @@
#include "ListSpellsAction.h" #include "ListSpellsAction.h"
#include "LogLevelAction.h" #include "LogLevelAction.h"
#include "LootStrategyAction.h" #include "LootStrategyAction.h"
#include "LootRollAction.h"
#include "MailAction.h" #include "MailAction.h"
#include "NamedObjectContext.h" #include "NamedObjectContext.h"
#include "NewRpgAction.h" #include "NewRpgAction.h"
@ -194,7 +193,6 @@ public:
creators["pet"] = &ChatActionContext::pet; creators["pet"] = &ChatActionContext::pet;
creators["glyphs"] = &ChatActionContext::glyphs; // Added for custom Glyphs creators["glyphs"] = &ChatActionContext::glyphs; // Added for custom Glyphs
creators["glyph equip"] = &ChatActionContext::glyph_equip; // Added for custom Glyphs creators["glyph equip"] = &ChatActionContext::glyph_equip; // Added for custom Glyphs
creators["roll"] = &ChatActionContext::roll_action;
} }
private: private:
@ -304,7 +302,6 @@ private:
static Action* pet(PlayerbotAI* botAI) { return new PetAction(botAI); } static Action* pet(PlayerbotAI* botAI) { return new PetAction(botAI); }
static Action* glyphs(PlayerbotAI* botAI) { return new TellGlyphsAction(botAI); } // Added for custom Glyphs static Action* glyphs(PlayerbotAI* botAI) { return new TellGlyphsAction(botAI); } // Added for custom Glyphs
static Action* glyph_equip(PlayerbotAI* ai) { return new EquipGlyphsAction(ai); } // Added for custom Glyphs static Action* glyph_equip(PlayerbotAI* ai) { return new EquipGlyphsAction(ai); } // Added for custom Glyphs
static Action* roll_action(PlayerbotAI* botAI) { return new RollAction(botAI); }
}; };
#endif #endif

View File

@ -19,51 +19,22 @@ bool ImbueWithPoisonAction::Execute(Event event)
if (bot->HasAura(SPELL_AURA_MOD_STEALTH)) if (bot->HasAura(SPELL_AURA_MOD_STEALTH))
bot->RemoveAurasByType(SPELL_AURA_MOD_STEALTH); bot->RemoveAurasByType(SPELL_AURA_MOD_STEALTH);
// hp check
if (bot->getStandState() != UNIT_STAND_STATE_STAND) if (bot->getStandState() != UNIT_STAND_STATE_STAND)
bot->SetStandState(UNIT_STAND_STATE_STAND); bot->SetStandState(UNIT_STAND_STATE_STAND);
static const std::vector<uint32_t> prioritizedInstantPoisons = { // Search and apply poison to weapons
INSTANT_POISON_IX, INSTANT_POISON_VIII, INSTANT_POISON_VII, INSTANT_POISON_VI, INSTANT_POISON_V, INSTANT_POISON_IV, // Mainhand ...
INSTANT_POISON_III, INSTANT_POISON_II, INSTANT_POISON
};
static const std::vector<uint32_t> prioritizedDeadlyPoisons = {
DEADLY_POISON_IX, DEADLY_POISON_VIII, DEADLY_POISON_VII, DEADLY_POISON_VI, DEADLY_POISON_V, DEADLY_POISON_IV,
DEADLY_POISON_III, DEADLY_POISON_II, DEADLY_POISON
};
// Check if we have any deadly or instant poisons
Item* deadlyPoison = nullptr;
for (auto id : prioritizedDeadlyPoisons)
{
deadlyPoison = botAI->FindConsumable(id);
if (deadlyPoison) break;
}
Item* instantPoison = nullptr;
for (auto id : prioritizedInstantPoisons)
{
instantPoison = botAI->FindConsumable(id);
if (instantPoison) break;
}
// Mainhand
Item* poison = nullptr; Item* poison = nullptr;
Item* weapon = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); Item* weapon = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
if (weapon && weapon->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT) == 0) if (weapon && weapon->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT) == 0)
{ {
if (instantPoison && deadlyPoison) poison = botAI->FindConsumable(INSTANT_POISON_DISPLAYID);
{ if (!poison)
poison = instantPoison; poison = botAI->FindConsumable(DEADLY_POISON_DISPLAYID);
}
else if (deadlyPoison) if (!poison)
{ poison = botAI->FindConsumable(WOUND_POISON_DISPLAYID);
poison = deadlyPoison;
}
else if (instantPoison)
{
poison = instantPoison;
}
if (poison) if (poison)
{ {
@ -72,23 +43,16 @@ bool ImbueWithPoisonAction::Execute(Event event)
} }
} }
// Offhand //... and offhand
poison = nullptr;
weapon = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); weapon = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
if (weapon && weapon->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT) == 0) if (weapon && weapon->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT) == 0)
{ {
if (deadlyPoison && instantPoison) poison = botAI->FindConsumable(DEADLY_POISON_DISPLAYID);
{ if (!poison)
poison = deadlyPoison; poison = botAI->FindConsumable(WOUND_POISON_DISPLAYID);
}
else if (instantPoison) if (!poison)
{ poison = botAI->FindConsumable(INSTANT_POISON_DISPLAYID);
poison = instantPoison;
}
else if (deadlyPoison)
{
poison = deadlyPoison;
}
if (poison) if (poison)
{ {
@ -177,8 +141,8 @@ bool ImbueWithOilAction::Execute(Event event)
return true; return true;
} }
static const uint32 uPrioritizedHealingItemIds[19] = { static const uint32 uPriorizedHealingItemIds[19] = {
HEALTHSTONE, HEALTHSTONE_DISPLAYID,
FEL_REGENERATION_POTION, FEL_REGENERATION_POTION,
SUPER_HEALING_POTION, SUPER_HEALING_POTION,
CRYSTAL_HEALING_POTION, CRYSTAL_HEALING_POTION,
@ -218,9 +182,9 @@ bool TryEmergencyAction::Execute(Event event)
} }
// Else loop over the list of health consumable to pick one // Else loop over the list of health consumable to pick one
for (uint8 i = 0; i < std::size(uPrioritizedHealingItemIds); ++i) for (uint8 i = 0; i < std::size(uPriorizedHealingItemIds); ++i)
{ {
if (Item* healthItem = botAI->FindConsumable(uPrioritizedHealingItemIds[i])) if (Item* healthItem = botAI->FindConsumable(uPriorizedHealingItemIds[i]))
{ {
botAI->ImbueItem(healthItem); botAI->ImbueItem(healthItem);
} }

View File

@ -224,37 +224,3 @@ bool RollUniqueCheck(ItemTemplate const* proto, Player* bot)
} }
return false; // Item is not equipped or in bags, roll for it return false; // Item is not equipped or in bags, roll for it
} }
bool RollAction::Execute(Event event)
{
std::string link = event.getParam();
if (link.empty())
{
bot->DoRandomRoll(0,100);
return false;
}
ItemIds itemIds = chat->parseItems(link);
if (itemIds.empty())
return false;
uint32 itemId = *itemIds.begin();
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
if (!proto)
{
return false;
}
std::string itemUsageParam;
itemUsageParam = std::to_string(itemId);
ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", itemUsageParam);
switch (proto->Class)
{
case ITEM_CLASS_WEAPON:
case ITEM_CLASS_ARMOR:
if (usage == ITEM_USAGE_EQUIP || usage == ITEM_USAGE_REPLACE || usage == ITEM_USAGE_BAD_EQUIP)
{
bot->DoRandomRoll(0,100);
}
}
return true;
}

View File

@ -37,12 +37,4 @@ public:
bool Execute(Event event) override; bool Execute(Event event) override;
}; };
class RollAction : public Action
{
public:
RollAction(PlayerbotAI* botAI) : Action(botAI, "roll") {}
bool Execute(Event event) override;
};
#endif #endif

View File

@ -175,8 +175,6 @@ bool MaintenanceAction::Execute(Event event)
factory.InitAmmo(); factory.InitAmmo();
factory.InitFood(); factory.InitFood();
factory.InitReagents(); factory.InitReagents();
factory.InitConsumables();
factory.InitPotions();
factory.InitTalentsTree(true); factory.InitTalentsTree(true);
factory.InitPet(); factory.InitPet();
factory.InitPetTalents(); factory.InitPetTalents();
@ -188,6 +186,7 @@ bool MaintenanceAction::Execute(Event event)
factory.InitMounts(); factory.InitMounts();
factory.InitGlyphs(false); factory.InitGlyphs(false);
factory.InitKeyring(); factory.InitKeyring();
factory.InitPotions();
if (bot->GetLevel() >= sPlayerbotAIConfig->minEnchantingBotLevel) if (bot->GetLevel() >= sPlayerbotAIConfig->minEnchantingBotLevel)
factory.ApplyEnchantAndGemsNew(); factory.ApplyEnchantAndGemsNew();

View File

@ -6,7 +6,6 @@
#include "GenericDruidNonCombatStrategy.h" #include "GenericDruidNonCombatStrategy.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "AiFactory.h"
class GenericDruidNonCombatStrategyActionNodeFactory : public NamedObjectFactory<ActionNode> class GenericDruidNonCombatStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
{ {
@ -110,43 +109,50 @@ void GenericDruidNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& trig
{ {
NonCombatStrategy::InitTriggers(triggers); NonCombatStrategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode("mark of the wild", NextAction::array(0, new NextAction("mark of the wild", 14.0f), nullptr))); triggers.push_back(
new TriggerNode("mark of the wild", NextAction::array(0, new NextAction("mark of the wild", 14.0f), nullptr)));
// triggers.push_back(new TriggerNode("thorns", NextAction::array(0, new NextAction("thorns", 12.0f), nullptr))); // triggers.push_back(new TriggerNode("thorns", NextAction::array(0, new NextAction("thorns", 12.0f), nullptr)));
// triggers.push_back(new TriggerNode("cure poison", NextAction::array(0, new NextAction("abolish poison", 21.0f), // triggers.push_back(new TriggerNode("cure poison", NextAction::array(0, new NextAction("abolish poison", 21.0f),
// nullptr))); // nullptr)));
triggers.push_back(new TriggerNode("party member cure poison", NextAction::array(0, new NextAction("abolish poison on party", 20.0f), nullptr))); triggers.push_back(new TriggerNode(
triggers.push_back(new TriggerNode("party member dead", NextAction::array(0, new NextAction("revive", ACTION_CRITICAL_HEAL + 10), nullptr))); "party member cure poison", NextAction::array(0, new NextAction("abolish poison on party", 20.0f), nullptr)));
triggers.push_back(new TriggerNode(
"party member dead", NextAction::array(0, new NextAction("revive", ACTION_CRITICAL_HEAL + 10), nullptr)));
// triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("innervate", ACTION_EMERGENCY // triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("innervate", ACTION_EMERGENCY
// + 5), nullptr))); triggers.push_back(new TriggerNode("swimming", NextAction::array(0, new NextAction("aquatic // + 5), nullptr))); triggers.push_back(new TriggerNode("swimming", NextAction::array(0, new NextAction("aquatic
// form", 1.0f), nullptr))); // form", 1.0f), nullptr)));
triggers.push_back(new TriggerNode("party member critical health", NextAction::array(0, triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("apply oil", 1.0f), nullptr)));
triggers.push_back(
new TriggerNode("party member critical health",
NextAction::array(0,
new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 7), new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 7),
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 6), new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 6),
new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 5), new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 5),
nullptr))); nullptr)));
triggers.push_back(new TriggerNode("party member low health", NextAction::array(0,
triggers.push_back(
new TriggerNode("party member low health",
NextAction::array(0,
new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 5), new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 5),
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 4), new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 4),
new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 3), new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 3),
nullptr))); nullptr)));
triggers.push_back(new TriggerNode("party member medium health", NextAction::array(0,
new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 3), triggers.push_back(
new TriggerNode("party member medium health",
NextAction::array(0, new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 3),
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 2), new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 2),
new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 1), new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 1),
nullptr))); nullptr)));
triggers.push_back(new TriggerNode("party member almost full health", NextAction::array(0,
new NextAction("wild growth on party", ACTION_LIGHT_HEAL + 3),
new NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 2),
nullptr)));
triggers.push_back(new TriggerNode("party member remove curse", NextAction::array(0,
new NextAction("remove curse on party", ACTION_DISPEL + 7),
nullptr)));
int specTab = AiFactory::GetPlayerSpecTab(botAI->GetBot()); triggers.push_back(
if (specTab == 0 || specTab == 2) // Balance or Restoration new TriggerNode("party member almost full health",
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("apply oil", 1.0f), nullptr))); NextAction::array(0, new NextAction("wild growth on party", ACTION_LIGHT_HEAL + 3), new NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 2), NULL)));
if (specTab == 1) // Feral
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("apply stone", 1.0f), nullptr))); triggers.push_back(
new TriggerNode("party member remove curse",
NextAction::array(0, new NextAction("remove curse on party", ACTION_DISPEL + 7), nullptr)));
} }
GenericDruidBuffStrategy::GenericDruidBuffStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI) GenericDruidBuffStrategy::GenericDruidBuffStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI)
@ -158,13 +164,11 @@ void GenericDruidBuffStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
NonCombatStrategy::InitTriggers(triggers); NonCombatStrategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode("mark of the wild on party", NextAction::array(0, triggers.push_back(
new NextAction("mark of the wild on party", 13.0f), new TriggerNode("mark of the wild on party",
nullptr))); NextAction::array(0, new NextAction("mark of the wild on party", 13.0f), nullptr)));
triggers.push_back(new TriggerNode("thorns on main tank", NextAction::array(0, triggers.push_back(new TriggerNode("thorns on main tank",
new NextAction("thorns on main tank", 11.0f), NextAction::array(0, new NextAction("thorns on main tank", 11.0f), nullptr)));
nullptr))); triggers.push_back(new TriggerNode("thorns",
triggers.push_back(new TriggerNode("thorns", NextAction::array(0, NextAction::array(0, new NextAction("thorns", 10.0f), nullptr)));
new NextAction("thorns", 10.0f),
nullptr)));
} }

View File

@ -105,7 +105,6 @@ void ChatCommandHandlerStrategy::InitTriggers(std::vector<TriggerNode*>& trigger
triggers.push_back(new TriggerNode("pet", NextAction::array(0, new NextAction("pet", relevance), nullptr))); triggers.push_back(new TriggerNode("pet", NextAction::array(0, new NextAction("pet", relevance), nullptr)));
triggers.push_back(new TriggerNode("glyphs", NextAction::array(0, new NextAction("glyphs", relevance), nullptr))); // Added for custom Glyphs triggers.push_back(new TriggerNode("glyphs", NextAction::array(0, new NextAction("glyphs", relevance), nullptr))); // Added for custom Glyphs
triggers.push_back(new TriggerNode("glyph equip", NextAction::array(0, new NextAction("glyph equip", relevance), nullptr))); // Added for custom Glyphs triggers.push_back(new TriggerNode("glyph equip", NextAction::array(0, new NextAction("glyph equip", relevance), nullptr))); // Added for custom Glyphs
triggers.push_back(new TriggerNode("roll", NextAction::array(0, new NextAction("roll", relevance), nullptr)));
} }
ChatCommandHandlerStrategy::ChatCommandHandlerStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI) ChatCommandHandlerStrategy::ChatCommandHandlerStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI)

View File

@ -44,14 +44,15 @@ void GenericHunterNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& tri
{ {
NonCombatStrategy::InitTriggers(triggers); NonCombatStrategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode("trueshot aura", NextAction::array(0, new NextAction("trueshot aura", 2.0f), nullptr))); triggers.push_back(
triggers.push_back(new TriggerNode("often", NextAction::array(0, new TriggerNode("trueshot aura", NextAction::array(0, new NextAction("trueshot aura", 2.0f), nullptr)));
new NextAction("apply stone", 1.0f), triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("apply oil", 1.0f), nullptr)));
new NextAction("apply oil", 1.0f), triggers.push_back(
nullptr))); new TriggerNode("low ammo", NextAction::array(0, new NextAction("say::low ammo", ACTION_NORMAL), nullptr)));
triggers.push_back(new TriggerNode("low ammo", NextAction::array(0, new NextAction("say::low ammo", ACTION_NORMAL), nullptr))); triggers.push_back(
triggers.push_back(new TriggerNode("no track", NextAction::array(0, new NextAction("track humanoids", ACTION_NORMAL), nullptr))); new TriggerNode("no track", NextAction::array(0, new NextAction("track humanoids", ACTION_NORMAL), nullptr)));
triggers.push_back(new TriggerNode("no ammo", NextAction::array(0, new NextAction("equip upgrades", ACTION_HIGH + 1), nullptr))); triggers.push_back(new TriggerNode("no ammo",
NextAction::array(0, new NextAction("equip upgrades", ACTION_HIGH + 1), nullptr)));
// triggers.push_back(new TriggerNode("no ammo", NextAction::array(0, new NextAction("switch to melee", // triggers.push_back(new TriggerNode("no ammo", NextAction::array(0, new NextAction("switch to melee",
// ACTION_NORMAL + 1), new NextAction("say::no ammo", ACTION_NORMAL), nullptr))); triggers.push_back(new // ACTION_NORMAL + 1), new NextAction("say::no ammo", ACTION_NORMAL), nullptr))); triggers.push_back(new
// TriggerNode("has ammo", NextAction::array(0, new NextAction("switch to ranged", ACTION_NORMAL), nullptr))); // TriggerNode("has ammo", NextAction::array(0, new NextAction("switch to ranged", ACTION_NORMAL), nullptr)));
@ -60,8 +61,12 @@ void GenericHunterNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& tri
void HunterPetStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void HunterPetStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("call pet", 60.0f), nullptr))); triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("call pet", 60.0f), nullptr)));
triggers.push_back(new TriggerNode("has pet", NextAction::array(0, new NextAction("toggle pet spell", 60.0f), nullptr))); triggers.push_back(
triggers.push_back(new TriggerNode("pet not happy", NextAction::array(0, new NextAction("feed pet", 60.0f), nullptr))); new TriggerNode("has pet", NextAction::array(0, new NextAction("toggle pet spell", 60.0f), nullptr)));
triggers.push_back(new TriggerNode("hunters pet medium health", NextAction::array(0, new NextAction("mend pet", 60.0f), nullptr))); triggers.push_back(
triggers.push_back(new TriggerNode("hunters pet dead", NextAction::array(0, new NextAction("revive pet", 60.0f), nullptr))); new TriggerNode("pet not happy", NextAction::array(0, new NextAction("feed pet", 60.0f), nullptr)));
triggers.push_back(
new TriggerNode("hunters pet medium health", NextAction::array(0, new NextAction("mend pet", 60.0f), nullptr)));
triggers.push_back(
new TriggerNode("hunters pet dead", NextAction::array(0, new NextAction("revive pet", 60.0f), nullptr)));
} }

View File

@ -7,7 +7,6 @@
#include "GenericPaladinStrategyActionNodeFactory.h" #include "GenericPaladinStrategyActionNodeFactory.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "AiFactory.h"
GenericPaladinNonCombatStrategy::GenericPaladinNonCombatStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI) GenericPaladinNonCombatStrategy::GenericPaladinNonCombatStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI)
{ {
@ -18,15 +17,14 @@ void GenericPaladinNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& tr
{ {
NonCombatStrategy::InitTriggers(triggers); NonCombatStrategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode("party member dead", NextAction::array(0, new NextAction("redemption", ACTION_CRITICAL_HEAL + 10), nullptr))); triggers.push_back(new TriggerNode(
triggers.push_back(new TriggerNode("party member almost full health", NextAction::array(0, new NextAction("flash of light on party", 25.0f), nullptr))); "party member dead", NextAction::array(0, new NextAction("redemption", ACTION_CRITICAL_HEAL + 10), nullptr)));
triggers.push_back(new TriggerNode("party member medium health", NextAction::array(0, new NextAction("flash of light on party", 26.0f), nullptr))); triggers.push_back(new TriggerNode("party member almost full health",
triggers.push_back(new TriggerNode("party member low health", NextAction::array(0, new NextAction("holy light on party", 27.0f), nullptr))); NextAction::array(0, new NextAction("flash of light on party", 25.0f), NULL)));
triggers.push_back(new TriggerNode("party member critical health", NextAction::array(0, new NextAction("holy light on party", 28.0f), nullptr))); triggers.push_back(new TriggerNode("party member medium health",
NextAction::array(0, new NextAction("flash of light on party", 26.0f), NULL)));
int specTab = AiFactory::GetPlayerSpecTab(botAI->GetBot()); triggers.push_back(new TriggerNode("party member low health",
if (specTab == 0 || specTab == 1) // Holy or Protection NextAction::array(0, new NextAction("holy light on party", 27.0f), NULL)));
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("apply oil", 1.0f), nullptr))); triggers.push_back(new TriggerNode("party member critical health",
if (specTab == 2) // Retribution NextAction::array(0, new NextAction("holy light on party", 28.0f), NULL)));
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("apply stone", 1.0f), nullptr)));
} }

View File

@ -240,21 +240,6 @@ void RaidUlduarStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
"vezax mark of the faceless trigger", "vezax mark of the faceless trigger",
NextAction::array(0, new NextAction("vezax mark of the faceless action", ACTION_RAID), nullptr))); NextAction::array(0, new NextAction("vezax mark of the faceless action", ACTION_RAID), nullptr)));
triggers.push_back(new TriggerNode(
"vezax shadow resistance trigger",
NextAction::array(0, new NextAction("vezax shadow resistance action", ACTION_RAID), nullptr)));
//
// Yogg-Saron
//
triggers.push_back(new TriggerNode(
"sara shadow resistance trigger",
NextAction::array(0, new NextAction("sara shadow resistance action", ACTION_RAID), nullptr)));
triggers.push_back(new TriggerNode(
"yogg-saron shadow resistance trigger",
NextAction::array(0, new NextAction("yogg-saron shadow resistance action", ACTION_RAID), nullptr)));
} }
void RaidUlduarStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers) void RaidUlduarStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers)

View File

@ -23,9 +23,7 @@ bool BossFireResistanceTrigger::IsActive()
return false; return false;
// Check if bot have fire resistance aura // Check if bot have fire resistance aura
if (bot->HasAura(SPELL_FIRE_RESISTANCE_AURA_RANK_5) || bot->HasAura(SPELL_FIRE_RESISTANCE_AURA_RANK_4) || if (bot->HasAura(SPELL_FIRE_RESISTANCE_AURA))
bot->HasAura(SPELL_FIRE_RESISTANCE_AURA_RANK_3) || bot->HasAura(SPELL_FIRE_RESISTANCE_AURA_RANK_2) ||
bot->HasAura(SPELL_FIRE_RESISTANCE_AURA_RANK_1))
return false; return false;
// Check if bot dont have already have fire resistance strategy // Check if bot dont have already have fire resistance strategy
@ -34,11 +32,7 @@ bool BossFireResistanceTrigger::IsActive()
return false; return false;
// Check that the bot actually knows the spell // Check that the bot actually knows the spell
if (!bot->HasActiveSpell(SPELL_FIRE_RESISTANCE_AURA_RANK_5) && if (!bot->HasActiveSpell(SPELL_FIRE_RESISTANCE_AURA))
!bot->HasActiveSpell(SPELL_FIRE_RESISTANCE_AURA_RANK_4) &&
!bot->HasActiveSpell(SPELL_FIRE_RESISTANCE_AURA_RANK_3) &&
!bot->HasActiveSpell(SPELL_FIRE_RESISTANCE_AURA_RANK_2) &&
!bot->HasActiveSpell(SPELL_FIRE_RESISTANCE_AURA_RANK_1))
return false; return false;
// Get the group and ensure it's a raid group // Get the group and ensure it's a raid group
@ -53,7 +47,7 @@ bool BossFireResistanceTrigger::IsActive()
if (!member || !member->IsAlive()) if (!member || !member->IsAlive())
continue; continue;
// Check if the member is a paladin // Check if the member is a hunter
if (member->getClass() == CLASS_PALADIN) if (member->getClass() == CLASS_PALADIN)
{ {
// Return true only if the current bot is the first alive paladin // Return true only if the current bot is the first alive paladin
@ -76,9 +70,7 @@ bool BossFrostResistanceTrigger::IsActive()
return false; return false;
// Check if bot have frost resistance aura // Check if bot have frost resistance aura
if (bot->HasAura(SPELL_FROST_RESISTANCE_AURA_RANK_5) || bot->HasAura(SPELL_FROST_RESISTANCE_AURA_RANK_4) || if (bot->HasAura(SPELL_FROST_RESISTANCE_AURA))
bot->HasAura(SPELL_FROST_RESISTANCE_AURA_RANK_3) || bot->HasAura(SPELL_FROST_RESISTANCE_AURA_RANK_2) ||
bot->HasAura(SPELL_FROST_RESISTANCE_AURA_RANK_1))
return false; return false;
// Check if bot dont have already have frost resistance strategy // Check if bot dont have already have frost resistance strategy
@ -87,11 +79,7 @@ bool BossFrostResistanceTrigger::IsActive()
return false; return false;
// Check that the bot actually knows the spell // Check that the bot actually knows the spell
if (!bot->HasActiveSpell(SPELL_FROST_RESISTANCE_AURA_RANK_5) && if (!bot->HasActiveSpell(SPELL_FROST_RESISTANCE_AURA))
!bot->HasActiveSpell(SPELL_FROST_RESISTANCE_AURA_RANK_4) &&
!bot->HasActiveSpell(SPELL_FROST_RESISTANCE_AURA_RANK_3) &&
!bot->HasActiveSpell(SPELL_FROST_RESISTANCE_AURA_RANK_2) &&
!bot->HasActiveSpell(SPELL_FROST_RESISTANCE_AURA_RANK_1))
return false; return false;
// Get the group and ensure it's a raid group // Get the group and ensure it's a raid group
@ -106,7 +94,7 @@ bool BossFrostResistanceTrigger::IsActive()
if (!member || !member->IsAlive()) if (!member || !member->IsAlive())
continue; continue;
// Check if the member is a paladin // Check if the member is a hunter
if (member->getClass() == CLASS_PALADIN) if (member->getClass() == CLASS_PALADIN)
{ {
// Return true only if the current bot is the first alive paladin // Return true only if the current bot is the first alive paladin
@ -133,8 +121,7 @@ bool BossNatureResistanceTrigger::IsActive()
return false; return false;
// Check if bot have nature resistance aura // Check if bot have nature resistance aura
if (bot->HasAura(SPELL_ASPECT_OF_THE_WILD_RANK_4) || bot->HasAura(SPELL_ASPECT_OF_THE_WILD_RANK_3) || if (bot->HasAura(SPELL_ASPECT_OF_THE_WILD))
bot->HasAura(SPELL_ASPECT_OF_THE_WILD_RANK_2) || bot->HasAura(SPELL_ASPECT_OF_THE_WILD_RANK_1))
return false; return false;
// Check if bot dont have already setted nature resistance aura // Check if bot dont have already setted nature resistance aura
@ -143,10 +130,7 @@ bool BossNatureResistanceTrigger::IsActive()
return false; return false;
// Check that the bot actually knows Aspect of the Wild // Check that the bot actually knows Aspect of the Wild
if (!bot->HasActiveSpell(SPELL_ASPECT_OF_THE_WILD_RANK_4) && if (!bot->HasActiveSpell(SPELL_ASPECT_OF_THE_WILD))
!bot->HasActiveSpell(SPELL_ASPECT_OF_THE_WILD_RANK_3) &&
!bot->HasActiveSpell(SPELL_ASPECT_OF_THE_WILD_RANK_2) &&
!bot->HasActiveSpell(SPELL_ASPECT_OF_THE_WILD_RANK_1))
return false; return false;
// Get the group and ensure it's a raid group // Get the group and ensure it's a raid group
@ -171,58 +155,3 @@ bool BossNatureResistanceTrigger::IsActive()
return false; return false;
} }
bool BossShadowResistanceTrigger::IsActive()
{
// Check boss and it is alive
Unit* boss = AI_VALUE2(Unit*, "find target", bossName);
if (!boss || !boss->IsAlive())
return false;
// Check if bot is paladin
if (bot->getClass() != CLASS_PALADIN)
return false;
// Check if bot have shadow resistance aura
if (bot->HasAura(SPELL_SHADOW_RESISTANCE_AURA_RANK_5) ||
bot->HasAura(SPELL_SHADOW_RESISTANCE_AURA_RANK_4) ||
bot->HasAura(SPELL_SHADOW_RESISTANCE_AURA_RANK_3) ||
bot->HasAura(SPELL_SHADOW_RESISTANCE_AURA_RANK_2) ||
bot->HasAura(SPELL_SHADOW_RESISTANCE_AURA_RANK_1))
return false;
// Check if bot dont have already have shadow resistance strategy
PaladinShadowResistanceStrategy paladinShadowResistanceStrategy(botAI);
if (botAI->HasStrategy(paladinShadowResistanceStrategy.getName(), BotState::BOT_STATE_COMBAT))
return false;
// Check that the bot actually knows the spell
if (!bot->HasActiveSpell(SPELL_SHADOW_RESISTANCE_AURA_RANK_5) &&
!bot->HasActiveSpell(SPELL_SHADOW_RESISTANCE_AURA_RANK_4) &&
!bot->HasActiveSpell(SPELL_SHADOW_RESISTANCE_AURA_RANK_3) &&
!bot->HasActiveSpell(SPELL_SHADOW_RESISTANCE_AURA_RANK_2) &&
!bot->HasActiveSpell(SPELL_SHADOW_RESISTANCE_AURA_RANK_1))
return false;
// Get the group and ensure it's a raid group
Group* group = bot->GetGroup();
if (!group || !group->isRaidGroup())
return false;
// Iterate through group members to find the first alive paladin
for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next())
{
Player* member = gref->GetSource();
if (!member || !member->IsAlive())
continue;
// Check if the member is a paladin
if (member->getClass() == CLASS_PALADIN)
{
// Return true only if the current bot is the first alive paladin
return member == bot;
}
}
return false;
}

View File

@ -12,25 +12,9 @@ class PlayerbotAI;
enum BossAuraIDs enum BossAuraIDs
{ {
SPELL_SHADOW_RESISTANCE_AURA_RANK_1 = 19876, SPELL_FROST_RESISTANCE_AURA = 48945,
SPELL_FROST_RESISTANCE_AURA_RANK_1 = 19888, SPELL_FIRE_RESISTANCE_AURA = 48947,
SPELL_FIRE_RESISTANCE_AURA_RANK_1 = 19891, SPELL_ASPECT_OF_THE_WILD = 49071,
SPELL_SHADOW_RESISTANCE_AURA_RANK_2 = 19895,
SPELL_SHADOW_RESISTANCE_AURA_RANK_3 = 19896,
SPELL_FROST_RESISTANCE_AURA_RANK_2 = 19897,
SPELL_FROST_RESISTANCE_AURA_RANK_3 = 19898,
SPELL_FIRE_RESISTANCE_AURA_RANK_2 = 19899,
SPELL_FIRE_RESISTANCE_AURA_RANK_3 = 19900,
SPELL_ASPECT_OF_THE_WILD_RANK_1 = 20043,
SPELL_ASPECT_OF_THE_WILD_RANK_2 = 20190,
SPELL_ASPECT_OF_THE_WILD_RANK_3 = 27045,
SPELL_SHADOW_RESISTANCE_AURA_RANK_4 = 27151,
SPELL_FROST_RESISTANCE_AURA_RANK_4 = 27152,
SPELL_FIRE_RESISTANCE_AURA_RANK_4 = 27153,
SPELL_SHADOW_RESISTANCE_AURA_RANK_5 = 48943,
SPELL_FROST_RESISTANCE_AURA_RANK_5 = 48945,
SPELL_FIRE_RESISTANCE_AURA_RANK_5 = 48947,
SPELL_ASPECT_OF_THE_WILD_RANK_4 = 49071
}; };
class BossFireResistanceTrigger : public Trigger class BossFireResistanceTrigger : public Trigger
@ -63,20 +47,7 @@ class BossNatureResistanceTrigger : public Trigger
{ {
public: public:
BossNatureResistanceTrigger(PlayerbotAI* ai, std::string const bossName) BossNatureResistanceTrigger(PlayerbotAI* ai, std::string const bossName)
: Trigger(ai, " nature resistance trigger"), bossName(bossName) : Trigger(ai, "kologarn nature resistance trigger"), bossName(bossName)
{
}
bool IsActive() override;
private:
std::string bossName;
};
class BossShadowResistanceTrigger : public Trigger
{
public:
BossShadowResistanceTrigger(PlayerbotAI* ai, std::string const bossName)
: Trigger(ai, " shadow resistance trigger"), bossName(bossName)
{ {
} }
bool IsActive() override; bool IsActive() override;

View File

@ -136,7 +136,6 @@ public:
creators["pet"] = &ChatTriggerContext::pet; creators["pet"] = &ChatTriggerContext::pet;
creators["glyphs"] = &ChatTriggerContext::glyphs; // Added for custom Glyphs creators["glyphs"] = &ChatTriggerContext::glyphs; // Added for custom Glyphs
creators["glyph equip"] = &ChatTriggerContext::glyph_equip; // Added for custom Glyphs creators["glyph equip"] = &ChatTriggerContext::glyph_equip; // Added for custom Glyphs
creators["roll"] = &ChatTriggerContext::roll_action;
} }
private: private:
@ -252,7 +251,6 @@ private:
static Trigger* pet(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "pet"); } static Trigger* pet(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "pet"); }
static Trigger* glyphs(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "glyphs"); } // Added for custom Glyphs static Trigger* glyphs(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "glyphs"); } // Added for custom Glyphs
static Trigger* glyph_equip(PlayerbotAI* ai) { return new ChatCommandTrigger(ai, "glyph equip"); } // Added for custom Glyphs static Trigger* glyph_equip(PlayerbotAI* ai) { return new ChatCommandTrigger(ai, "glyph equip"); } // Added for custom Glyphs
static Trigger* roll_action(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "roll"); }
}; };
#endif #endif