mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-02-20 18:10:02 +01:00
Merge branch 'master' into Tame-Chat-Action-/-Pet-Chat-Action-(stances/commands)
This commit is contained in:
commit
8545225923
@ -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 enchanges until level 71
|
# If enabled, bots will not use TBC enchants until level 61 or WotLK enchants until level 71
|
||||||
# Default: 1 (enabled)
|
# Default: 1 (enabled)
|
||||||
AiPlayerbot.LimitEnchantExpansion = 1
|
AiPlayerbot.LimitEnchantExpansion = 1
|
||||||
|
|
||||||
@ -709,6 +709,10 @@ AiPlayerbot.DefaultPetStance = 1
|
|||||||
# Default = 0 (disabled)
|
# Default = 0 (disabled)
|
||||||
AiPlayerbot.PetChatCommandDebug = 0
|
AiPlayerbot.PetChatCommandDebug = 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 = ""
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|||||||
@ -5105,13 +5105,13 @@ Item* PlayerbotAI::FindAmmo() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find Consumable
|
// Find Consumable
|
||||||
Item* PlayerbotAI::FindConsumable(uint32 displayId) const
|
Item* PlayerbotAI::FindConsumable(uint32 itemId) const
|
||||||
{
|
{
|
||||||
return FindItemInInventory(
|
return FindItemInInventory(
|
||||||
[displayId](ItemTemplate const* pItemProto) -> bool
|
[itemId](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->DisplayInfoID == displayId;
|
pItemProto->ItemId == itemId;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5171,36 +5171,34 @@ 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_DAGGER || pProto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM))
|
||||||
{
|
{
|
||||||
for (uint8 i = 0; i < std::size(uPriorizedSharpStoneIds); ++i)
|
for (uint8 i = 0; i < std::size(uPrioritizedSharpStoneIds); ++i)
|
||||||
{
|
{
|
||||||
stone = FindConsumable(uPriorizedSharpStoneIds[i]);
|
stone = FindConsumable(uPrioritizedSharpStoneIds[i]);
|
||||||
if (stone)
|
if (stone)
|
||||||
{
|
{
|
||||||
return stone;
|
return stone;
|
||||||
@ -5208,11 +5206,12 @@ Item* PlayerbotAI::FindStoneFor(Item* weapon) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
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(uPriorizedWeightStoneIds); ++i)
|
for (uint8 i = 0; i < std::size(uPrioritizedWeightStoneIds); ++i)
|
||||||
{
|
{
|
||||||
stone = FindConsumable(uPriorizedWeightStoneIds[i]);
|
stone = FindConsumable(uPrioritizedWeightStoneIds[i]);
|
||||||
if (stone)
|
if (stone)
|
||||||
{
|
{
|
||||||
return stone;
|
return stone;
|
||||||
@ -5225,6 +5224,7 @@ Item* PlayerbotAI::FindStoneFor(Item* weapon) const
|
|||||||
|
|
||||||
Item* PlayerbotAI::FindOilFor(Item* weapon) const
|
Item* PlayerbotAI::FindOilFor(Item* weapon) const
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!weapon)
|
if (!weapon)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@ -5232,36 +5232,61 @@ Item* PlayerbotAI::FindOilFor(Item* weapon) const
|
|||||||
if (!item_template)
|
if (!item_template)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
// static const will only get created once whatever the call amout
|
static const std::vector<uint32_t> uPrioritizedWizardOilIds = {
|
||||||
static const std::vector<uint32_t> uPriorizedWizardOilIds = {
|
BRILLIANT_WIZARD_OIL, SUPERIOR_WIZARD_OIL, WIZARD_OIL, LESSER_WIZARD_OIL, MINOR_WIZARD_OIL,
|
||||||
MINOR_WIZARD_OIL, MINOR_MANA_OIL, LESSER_WIZARD_OIL, LESSER_MANA_OIL, BRILLIANT_WIZARD_OIL,
|
BRILLIANT_MANA_OIL, SUPERIOR_MANA_OIL, LESSER_MANA_OIL, MINOR_MANA_OIL};
|
||||||
BRILLIANT_MANA_OIL, WIZARD_OIL, SUPERIOR_MANA_OIL, SUPERIOR_WIZARD_OIL};
|
|
||||||
|
|
||||||
// static const will only get created once whatever the call amout
|
static const std::vector<uint32_t> uPrioritizedManaOilIds = {
|
||||||
static const std::vector<uint32_t> uPriorizedManaOilIds = {
|
BRILLIANT_MANA_OIL, SUPERIOR_MANA_OIL, LESSER_MANA_OIL, MINOR_MANA_OIL,
|
||||||
MINOR_MANA_OIL, MINOR_WIZARD_OIL, LESSER_MANA_OIL, LESSER_WIZARD_OIL, BRILLIANT_MANA_OIL,
|
BRILLIANT_WIZARD_OIL, SUPERIOR_WIZARD_OIL, WIZARD_OIL, LESSER_WIZARD_OIL, MINOR_WIZARD_OIL};
|
||||||
BRILLIANT_WIZARD_OIL, SUPERIOR_MANA_OIL, WIZARD_OIL, SUPERIOR_WIZARD_OIL};
|
|
||||||
|
|
||||||
Item* oil = nullptr;
|
Item* oil = nullptr;
|
||||||
if (item_template->SubClass == ITEM_SUBCLASS_WEAPON_SWORD ||
|
int botClass = bot->getClass();
|
||||||
item_template->SubClass == ITEM_SUBCLASS_WEAPON_STAFF || item_template->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER)
|
int specTab = AiFactory::GetPlayerSpecTab(bot);
|
||||||
|
|
||||||
|
const std::vector<uint32_t>* prioritizedOils = nullptr;
|
||||||
|
switch (botClass)
|
||||||
{
|
{
|
||||||
for (const auto& id : uPriorizedWizardOilIds)
|
case CLASS_PRIEST:
|
||||||
|
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;
|
||||||
|
|||||||
@ -46,27 +46,27 @@ struct GameObjectData;
|
|||||||
|
|
||||||
enum StrategyType : uint32;
|
enum StrategyType : uint32;
|
||||||
|
|
||||||
enum HealingItemDisplayId
|
enum HealingItemId
|
||||||
{
|
{
|
||||||
HEALTHSTONE_DISPLAYID = 8026,
|
HEALTHSTONE = 5512,
|
||||||
MAJOR_HEALING_POTION = 24152,
|
MAJOR_HEALING_POTION = 13446,
|
||||||
WHIPPER_ROOT_TUBER = 21974,
|
WHIPPER_ROOT_TUBER = 11951,
|
||||||
NIGHT_DRAGON_BREATH = 21975,
|
NIGHT_DRAGON_BREATH = 11952,
|
||||||
LIMITED_INVULNERABILITY_POTION = 24213,
|
LIMITED_INVULNERABILITY_POTION = 3387,
|
||||||
GREATER_DREAMLESS_SLEEP_POTION = 17403,
|
GREATER_DREAMLESS_SLEEP_POTION = 22886,
|
||||||
SUPERIOR_HEALING_POTION = 15714,
|
SUPERIOR_HEALING_POTION = 3928,
|
||||||
CRYSTAL_RESTORE = 2516,
|
CRYSTAL_RESTORE = 11564,
|
||||||
DREAMLESS_SLEEP_POTION = 17403,
|
DREAMLESS_SLEEP_POTION = 12190,
|
||||||
GREATER_HEALING_POTION = 15713,
|
GREATER_HEALING_POTION = 1710,
|
||||||
HEALING_POTION = 15712,
|
HEALING_POTION = 929,
|
||||||
LESSER_HEALING_POTION = 15711,
|
LESSER_HEALING_POTION = 858,
|
||||||
DISCOLORED_HEALING_POTION = 15736,
|
DISCOLORED_HEALING_POTION = 3391,
|
||||||
MINOR_HEALING_POTION = 15710,
|
MINOR_HEALING_POTION = 118,
|
||||||
VOLATILE_HEALING_POTION = 24212,
|
VOLATILE_HEALING_POTION = 28100,
|
||||||
SUPER_HEALING_POTION = 37807,
|
SUPER_HEALING_POTION = 22829,
|
||||||
CRYSTAL_HEALING_POTION = 47132,
|
CRYSTAL_HEALING_POTION = 13462,
|
||||||
FEL_REGENERATION_POTION = 37864,
|
FEL_REGENERATION_POTION = 28101,
|
||||||
MAJOR_DREAMLESS_SLEEP_POTION = 37845
|
MAJOR_DREAMLESS_SLEEP_POTION = 20002
|
||||||
};
|
};
|
||||||
|
|
||||||
enum BotState
|
enum BotState
|
||||||
@ -152,6 +152,7 @@ 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,
|
||||||
@ -162,60 +163,66 @@ enum ChatChannelId
|
|||||||
GUILD_RECRUITMENT = 25,
|
GUILD_RECRUITMENT = 25,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum RoguePoisonDisplayId
|
enum RoguePoisonId
|
||||||
{
|
{
|
||||||
DEADLY_POISON_DISPLAYID = 13707,
|
INSTANT_POISON = 6947,
|
||||||
INSTANT_POISON_DISPLAYID = 13710,
|
INSTANT_POISON_II = 6949,
|
||||||
WOUND_POISON_DISPLAYID = 37278
|
INSTANT_POISON_III = 6950,
|
||||||
|
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 SharpeningStoneDisplayId
|
enum SharpeningStoneId
|
||||||
{
|
{
|
||||||
ROUGH_SHARPENING_DISPLAYID = 24673,
|
ROUGH_SHARPENING_STONE = 2862,
|
||||||
COARSE_SHARPENING_DISPLAYID = 24674,
|
COARSE_SHARPENING_STONE = 2863,
|
||||||
HEAVY_SHARPENING_DISPLAYID = 24675,
|
HEAVY_SHARPENING_STONE = 2871,
|
||||||
SOLID_SHARPENING_DISPLAYID = 24676,
|
SOLID_SHARPENING_STONE = 7964,
|
||||||
DENSE_SHARPENING_DISPLAYID = 24677,
|
DENSE_SHARPENING_STONE = 12404,
|
||||||
CONSECRATED_SHARPENING_DISPLAYID =
|
ELEMENTAL_SHARPENING_STONE = 18262,
|
||||||
24674, // will not be used because bot can not know if it will face undead targets
|
FEL_SHARPENING_STONE = 23528,
|
||||||
ELEMENTAL_SHARPENING_DISPLAYID = 21072,
|
ADAMANTITE_SHARPENING_STONE = 23529
|
||||||
FEL_SHARPENING_DISPLAYID = 39192,
|
|
||||||
ADAMANTITE_SHARPENING_DISPLAYID = 39193
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum WeightStoneDisplayId
|
enum WeightstoneId
|
||||||
{
|
{
|
||||||
ROUGH_WEIGHTSTONE_DISPLAYID = 24683,
|
ROUGH_WEIGHTSTONE = 3239,
|
||||||
COARSE_WEIGHTSTONE_DISPLAYID = 24684,
|
COARSE_WEIGHTSTONE = 3240,
|
||||||
HEAVY_WEIGHTSTONE_DISPLAYID = 24685,
|
HEAVY_WEIGHTSTONE = 3241,
|
||||||
SOLID_WEIGHTSTONE_DISPLAYID = 24686,
|
SOLID_WEIGHTSTONE = 7965,
|
||||||
DENSE_WEIGHTSTONE_DISPLAYID = 24687,
|
DENSE_WEIGHTSTONE = 12643,
|
||||||
FEL_WEIGHTSTONE_DISPLAYID = 39548,
|
FEL_WEIGHTSTONE = 28420,
|
||||||
ADAMANTITE_WEIGHTSTONE_DISPLAYID = 39549
|
ADAMANTITE_WEIGHTSTONE = 28421
|
||||||
};
|
};
|
||||||
|
|
||||||
enum WizardOilDisplayId
|
enum WizardOilId
|
||||||
{
|
{
|
||||||
MINOR_WIZARD_OIL = 9731,
|
MINOR_WIZARD_OIL = 20744,
|
||||||
LESSER_WIZARD_OIL = 47903,
|
LESSER_WIZARD_OIL = 20746,
|
||||||
BRILLIANT_WIZARD_OIL = 47901,
|
WIZARD_OIL = 20750,
|
||||||
WIZARD_OIL = 47905,
|
BRILLIANT_WIZARD_OIL = 20749,
|
||||||
SUPERIOR_WIZARD_OIL = 47904,
|
SUPERIOR_WIZARD_OIL = 22522
|
||||||
/// Blessed Wizard Oil = 26865 //scourge inv
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ManaOilDisplayId
|
enum ManaOilId
|
||||||
{
|
{
|
||||||
MINOR_MANA_OIL = 34492,
|
MINOR_MANA_OIL = 20745,
|
||||||
LESSER_MANA_OIL = 47902,
|
LESSER_MANA_OIL = 20747,
|
||||||
BRILLIANT_MANA_OIL = 41488,
|
BRILLIANT_MANA_OIL = 20748,
|
||||||
SUPERIOR_MANA_OIL = 36862
|
SUPERIOR_MANA_OIL = 22521
|
||||||
};
|
|
||||||
|
|
||||||
enum ShieldWardDisplayId
|
|
||||||
{
|
|
||||||
LESSER_WARD_OFSHIELDING = 38759,
|
|
||||||
GREATER_WARD_OFSHIELDING = 38760
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class BotTypeNumber : uint8
|
enum class BotTypeNumber : uint8
|
||||||
@ -472,7 +479,7 @@ public:
|
|||||||
Item* FindBandage() const;
|
Item* FindBandage() const;
|
||||||
Item* FindOpenableItem() const;
|
Item* FindOpenableItem() const;
|
||||||
Item* FindLockedItem() const;
|
Item* FindLockedItem() const;
|
||||||
Item* FindConsumable(uint32 displayId) const;
|
Item* FindConsumable(uint32 itemId) 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);
|
||||||
|
|||||||
@ -632,6 +632,9 @@ 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", "---------------------------------------");
|
||||||
|
|||||||
@ -408,6 +408,8 @@ 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()
|
||||||
|
|||||||
@ -36,6 +36,8 @@
|
|||||||
#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
|
||||||
{
|
{
|
||||||
@ -837,6 +839,18 @@ 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)
|
||||||
@ -879,15 +893,17 @@ 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");
|
messages.push_back("usage: addclass CLASSNAME [male|female|0|1]");
|
||||||
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");
|
messages.push_back("usage: list/reload/tweak/self or add/init/remove PLAYERNAME or addclass CLASSNAME [male|female]");
|
||||||
return messages;
|
return messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1110,6 +1126,24 @@ 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");
|
||||||
@ -1119,6 +1153,9 @@ 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))
|
||||||
|
|||||||
@ -197,21 +197,13 @@ public:
|
|||||||
sRandomPlayerbotMgr->HandleCommand(type, msg, player);
|
sRandomPlayerbotMgr->HandleCommand(type, msg, player);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OnPlayerBeforeCriteriaProgress(Player* player, AchievementCriteriaEntry const* /*criteria*/) override
|
bool OnPlayerBeforeAchievementComplete(Player* player, AchievementEntry const* achievement) override
|
||||||
{
|
{
|
||||||
if (sRandomPlayerbotMgr->IsRandomBot(player))
|
if (sRandomPlayerbotMgr->IsRandomBot(player) && (achievement->flags == 256 || achievement->flags == 768))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OnPlayerBeforeAchievementComplete(Player* player, AchievementEntry const* /*achievement*/) override
|
|
||||||
{
|
|
||||||
if (sRandomPlayerbotMgr->IsRandomBot(player))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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...");
|
||||||
AddConsumables();
|
InitConsumables();
|
||||||
if (pmo)
|
if (pmo)
|
||||||
pmo->finish();
|
pmo->finish();
|
||||||
|
|
||||||
@ -482,11 +482,8 @@ void PlayerbotFactory::Refresh()
|
|||||||
InitAmmo();
|
InitAmmo();
|
||||||
InitFood();
|
InitFood();
|
||||||
InitReagents();
|
InitReagents();
|
||||||
// InitPotions();
|
InitConsumables();
|
||||||
if (!sPlayerbotAIConfig->equipmentPersistence || bot->GetLevel() < sPlayerbotAIConfig->equipmentPersistenceLevel)
|
InitPotions();
|
||||||
{
|
|
||||||
InitTalentsTree(true, true, true);
|
|
||||||
}
|
|
||||||
InitPet();
|
InitPet();
|
||||||
InitPetTalents();
|
InitPetTalents();
|
||||||
InitClassSpells();
|
InitClassSpells();
|
||||||
@ -496,7 +493,10 @@ void PlayerbotFactory::Refresh()
|
|||||||
InitSpecialSpells();
|
InitSpecialSpells();
|
||||||
InitMounts();
|
InitMounts();
|
||||||
InitKeyring();
|
InitKeyring();
|
||||||
InitPotions();
|
if (!sPlayerbotAIConfig->equipmentPersistence || bot->GetLevel() < sPlayerbotAIConfig->equipmentPersistenceLevel)
|
||||||
|
{
|
||||||
|
InitTalentsTree(true, true, true);
|
||||||
|
}
|
||||||
if (bot->GetLevel() >= sPlayerbotAIConfig->minEnchantingBotLevel)
|
if (bot->GetLevel() >= sPlayerbotAIConfig->minEnchantingBotLevel)
|
||||||
{
|
{
|
||||||
ApplyEnchantAndGemsNew();
|
ApplyEnchantAndGemsNew();
|
||||||
@ -510,150 +510,217 @@ void PlayerbotFactory::Refresh()
|
|||||||
// bot->SaveToDB(false, false);
|
// bot->SaveToDB(false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerbotFactory::AddConsumables()
|
void PlayerbotFactory::InitConsumables()
|
||||||
{
|
{
|
||||||
|
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:
|
|
||||||
{
|
{
|
||||||
if (level >= 5 && level < 20)
|
// Always Wizard Oil
|
||||||
|
std::vector<uint32> wizard_oils = {BRILLIANT_WIZARD_OIL, SUPERIOR_WIZARD_OIL, WIZARD_OIL, LESSER_WIZARD_OIL, MINOR_WIZARD_OIL};
|
||||||
|
for (uint32 itemId : wizard_oils)
|
||||||
{
|
{
|
||||||
StoreItem(CONSUM_ID_MINOR_WIZARD_OIL, 5);
|
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
|
||||||
|
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)
|
|
||||||
{
|
{
|
||||||
StoreItem(CONSUM_ID_MINOR_MANA_OIL, 5);
|
// Balance: Wizard Oil
|
||||||
StoreItem(CONSUM_ID_WIZARD_OIL, 5);
|
if (specTab == 0)
|
||||||
|
{
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (level >= 45 && level < 52)
|
|
||||||
{
|
|
||||||
StoreItem(CONSUM_ID_BRILLIANT_MANA_OIL, 5);
|
|
||||||
StoreItem(CONSUM_ID_BRILLIANT_WIZARD_OIL, 5);
|
|
||||||
}
|
}
|
||||||
if (level >= 52 && level < 58)
|
// Feral: Sharpening Stones & Weightstones
|
||||||
|
else if (specTab == 1)
|
||||||
{
|
{
|
||||||
StoreItem(CONSUM_ID_SUPERIOR_MANA_OIL, 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};
|
||||||
StoreItem(CONSUM_ID_BRILLIANT_WIZARD_OIL, 5);
|
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)
|
||||||
if (level >= 58)
|
|
||||||
{
|
{
|
||||||
StoreItem(CONSUM_ID_SUPERIOR_MANA_OIL, 5);
|
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
|
||||||
StoreItem(CONSUM_ID_SUPERIOR_WIZARD_OIL, 5);
|
if (proto->RequiredLevel > level || level > 75)
|
||||||
|
continue;
|
||||||
|
items.push_back({itemId, 20});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Restoration: Mana Oil
|
||||||
|
else if (specTab == 2)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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:
|
||||||
{
|
{
|
||||||
if (level >= 1 && level < 5)
|
// Sharpening Stones & Weightstones
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
StoreItem(CONSUM_ID_ROUGH_SHARPENING_STONE, 5);
|
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
|
||||||
StoreItem(CONSUM_ID_ROUGH_WEIGHTSTONE, 5);
|
if (proto->RequiredLevel > level || level > 75)
|
||||||
|
continue;
|
||||||
|
items.push_back({itemId, 20});
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
for (uint32 itemId : weightstones)
|
||||||
if (level >= 5 && level < 15)
|
|
||||||
{
|
{
|
||||||
StoreItem(CONSUM_ID_COARSE_WEIGHTSTONE, 5);
|
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
|
||||||
StoreItem(CONSUM_ID_COARSE_SHARPENING_STONE, 5);
|
if (proto->RequiredLevel > level || level > 75)
|
||||||
}
|
continue;
|
||||||
|
items.push_back({itemId, 20});
|
||||||
if (level >= 15 && level < 25)
|
break;
|
||||||
{
|
|
||||||
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:
|
||||||
{
|
{
|
||||||
if (level >= 20 && level < 28)
|
// Poisons
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
StoreItem(CONSUM_ID_INSTANT_POISON, 5);
|
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
|
||||||
|
if (proto->RequiredLevel > level)
|
||||||
|
continue;
|
||||||
|
items.push_back({itemId, 20});
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
for (uint32 itemId : instant_poisons)
|
||||||
if (level >= 28 && level < 30)
|
|
||||||
{
|
{
|
||||||
StoreItem(CONSUM_ID_INSTANT_POISON_II, 5);
|
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
|
||||||
}
|
if (proto->RequiredLevel > level)
|
||||||
|
continue;
|
||||||
if (level >= 30 && level < 36)
|
items.push_back({itemId, 20});
|
||||||
{
|
break;
|
||||||
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;
|
break;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::pair<uint32, uint32> item : items)
|
||||||
|
{
|
||||||
|
int count = (int)item.second - (int)bot->GetItemCount(item.first);
|
||||||
|
if (count > 0)
|
||||||
|
StoreItem(item.first, count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -828,6 +895,7 @@ 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()))
|
||||||
@ -843,6 +911,12 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3220,102 +3294,97 @@ void PlayerbotFactory::InitFood()
|
|||||||
|
|
||||||
void PlayerbotFactory::InitReagents()
|
void PlayerbotFactory::InitReagents()
|
||||||
{
|
{
|
||||||
int level = bot->GetLevel();
|
int specTab = AiFactory::GetPlayerSpecTab(bot);
|
||||||
std::vector<std::pair<uint32, uint32>> items;
|
std::vector<std::pair<uint32, uint32>> items;
|
||||||
switch (bot->getClass())
|
switch (bot->getClass())
|
||||||
{
|
{
|
||||||
case CLASS_ROGUE:
|
case CLASS_DEATH_KNIGHT:
|
||||||
{
|
if (level >= 56)
|
||||||
std::vector<int> instant_poison_ids = {43231, 43230, 21927, 8928, 8927, 8926, 6950, 6949, 6947};
|
items.push_back({37201, 40}); // Corpse Dust
|
||||||
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;
|
|
||||||
}
|
|
||||||
for (int& itemId : instant_poison_ids)
|
|
||||||
{
|
|
||||||
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
|
|
||||||
if (proto->RequiredLevel > bot->GetLevel())
|
|
||||||
continue;
|
|
||||||
items.push_back({itemId, 20}); // instant poison
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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({17028, 40}); // Wild Berries
|
|
||||||
}
|
|
||||||
else if (level >= 60 && level < 80)
|
|
||||||
{
|
|
||||||
items.push_back({17029, 40}); // Wild Berries
|
|
||||||
}
|
|
||||||
else if (level >= 80)
|
|
||||||
{
|
|
||||||
items.push_back({44615, 40}); // Wild Berries
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CLASS_MAGE:
|
|
||||||
items.push_back({17020, 40}); // Arcane Powder
|
|
||||||
items.push_back({17031, 40}); // portal
|
|
||||||
items.push_back({17032, 40}); // portal
|
|
||||||
break;
|
break;
|
||||||
case CLASS_DRUID:
|
case CLASS_DRUID:
|
||||||
if (level >= 20 && level < 30)
|
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({17034, 40});
|
items.push_back({17037, 20}); // Hornbeam Seed
|
||||||
|
items.push_back({17021, 20}); // Wild Berries
|
||||||
}
|
}
|
||||||
if (level >= 30 && level < 40)
|
else if (level >= 60 && level < 69)
|
||||||
{
|
{
|
||||||
items.push_back({17035, 40});
|
items.push_back({17038, 20}); // Ironwood Seed
|
||||||
|
items.push_back({17026, 20}); // Wild Thornroot
|
||||||
}
|
}
|
||||||
if (level >= 40 && level < 50)
|
else if (level == 69)
|
||||||
{
|
{
|
||||||
items.push_back({17036, 40});
|
items.push_back({22147, 20}); // Flintweed Seed
|
||||||
|
items.push_back({17026, 20}); // Wild Thornroot
|
||||||
}
|
}
|
||||||
if (level >= 50 && level < 60)
|
else if (level >= 70 && level < 79)
|
||||||
{
|
{
|
||||||
items.push_back({17037, 40});
|
items.push_back({22147, 20}); // Flintweed Seed
|
||||||
items.push_back({17021, 40});
|
items.push_back({22148, 20}); // Wild Quillvine
|
||||||
}
|
}
|
||||||
if (level >= 60 && level < 70)
|
else if (level == 79)
|
||||||
{
|
{
|
||||||
items.push_back({17038, 40});
|
items.push_back({44614, 20}); // Starleaf Seed
|
||||||
items.push_back({17026, 40});
|
items.push_back({22148, 20}); // Wild Quillvine
|
||||||
}
|
}
|
||||||
if (level >= 70 && level < 80)
|
else if (level >= 80)
|
||||||
{
|
{
|
||||||
items.push_back({22147, 40});
|
items.push_back({44614, 20}); // Starleaf Seed
|
||||||
items.push_back({22148, 40});
|
items.push_back({44605, 20}); // Wild Spineleaf
|
||||||
}
|
|
||||||
if (level >= 80)
|
|
||||||
{
|
|
||||||
items.push_back({44614, 40});
|
|
||||||
items.push_back({44605, 40});
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case CLASS_MAGE:
|
||||||
|
if (level >= 20)
|
||||||
|
items.push_back({17031, 20}); // Rune of Teleportation
|
||||||
|
if (level >= 40)
|
||||||
|
items.push_back({17032, 20}); // Rune of Portals
|
||||||
|
if (level >= 56)
|
||||||
|
items.push_back({17020, 20}); // Arcane Powder
|
||||||
|
break;
|
||||||
case CLASS_PALADIN:
|
case CLASS_PALADIN:
|
||||||
items.push_back({21177, 100});
|
if (level >= 52)
|
||||||
|
items.push_back({21177, 80}); // Symbol of Kings
|
||||||
break;
|
break;
|
||||||
case CLASS_DEATH_KNIGHT:
|
case CLASS_PRIEST:
|
||||||
items.push_back({37201, 40});
|
if (level >= 48 && level < 56)
|
||||||
|
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;
|
||||||
@ -3328,10 +3397,73 @@ 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 &&
|
if (!increment && botAI &&
|
||||||
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
|
||||||
|
|
||||||
|
|||||||
@ -45,63 +45,6 @@ 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:
|
||||||
@ -128,8 +71,10 @@ 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();
|
||||||
@ -140,7 +85,6 @@ public:
|
|||||||
void InitKeyring();
|
void InitKeyring();
|
||||||
void InitReputation();
|
void InitReputation();
|
||||||
void InitAttunementQuests();
|
void InitAttunementQuests();
|
||||||
void InitPotions();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Prepare();
|
void Prepare();
|
||||||
@ -177,7 +121,6 @@ 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();
|
||||||
|
|||||||
@ -38,6 +38,7 @@
|
|||||||
#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"
|
||||||
@ -190,6 +191,7 @@ 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
|
||||||
@ -378,6 +380,7 @@ 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); }
|
||||||
|
|||||||
@ -157,16 +157,23 @@ 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -50,3 +50,16 @@ 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;
|
||||||
|
}
|
||||||
|
|||||||
@ -54,4 +54,18 @@ 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
|
||||||
|
|||||||
@ -36,6 +36,7 @@
|
|||||||
#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"
|
||||||
@ -196,6 +197,7 @@ public:
|
|||||||
creators["glyph equip"] = &ChatActionContext::glyph_equip; // Added for custom Glyphs
|
creators["glyph equip"] = &ChatActionContext::glyph_equip; // Added for custom Glyphs
|
||||||
creators["pet"] = &ChatActionContext::pet;
|
creators["pet"] = &ChatActionContext::pet;
|
||||||
creators["pet attack"] = &ChatActionContext::pet_attack;
|
creators["pet attack"] = &ChatActionContext::pet_attack;
|
||||||
|
creators["roll"] = &ChatActionContext::roll_action;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -307,6 +309,7 @@ private:
|
|||||||
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* pet(PlayerbotAI* botAI) { return new PetAction(botAI); }
|
static Action* pet(PlayerbotAI* botAI) { return new PetAction(botAI); }
|
||||||
static Action* pet_attack(PlayerbotAI* botAI) { return new PetAction(botAI, "attack"); }
|
static Action* pet_attack(PlayerbotAI* botAI) { return new PetAction(botAI, "attack"); }
|
||||||
|
static Action* roll_action(PlayerbotAI* botAI) { return new RollAction(botAI); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -19,22 +19,51 @@ 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);
|
||||||
|
|
||||||
// Search and apply poison to weapons
|
static const std::vector<uint32_t> prioritizedInstantPoisons = {
|
||||||
// Mainhand ...
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
poison = botAI->FindConsumable(INSTANT_POISON_DISPLAYID);
|
if (instantPoison && deadlyPoison)
|
||||||
if (!poison)
|
{
|
||||||
poison = botAI->FindConsumable(DEADLY_POISON_DISPLAYID);
|
poison = instantPoison;
|
||||||
|
}
|
||||||
if (!poison)
|
else if (deadlyPoison)
|
||||||
poison = botAI->FindConsumable(WOUND_POISON_DISPLAYID);
|
{
|
||||||
|
poison = deadlyPoison;
|
||||||
|
}
|
||||||
|
else if (instantPoison)
|
||||||
|
{
|
||||||
|
poison = instantPoison;
|
||||||
|
}
|
||||||
|
|
||||||
if (poison)
|
if (poison)
|
||||||
{
|
{
|
||||||
@ -43,16 +72,23 @@ bool ImbueWithPoisonAction::Execute(Event event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//... and offhand
|
// 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)
|
||||||
{
|
{
|
||||||
poison = botAI->FindConsumable(DEADLY_POISON_DISPLAYID);
|
if (deadlyPoison && instantPoison)
|
||||||
if (!poison)
|
{
|
||||||
poison = botAI->FindConsumable(WOUND_POISON_DISPLAYID);
|
poison = deadlyPoison;
|
||||||
|
}
|
||||||
if (!poison)
|
else if (instantPoison)
|
||||||
poison = botAI->FindConsumable(INSTANT_POISON_DISPLAYID);
|
{
|
||||||
|
poison = instantPoison;
|
||||||
|
}
|
||||||
|
else if (deadlyPoison)
|
||||||
|
{
|
||||||
|
poison = deadlyPoison;
|
||||||
|
}
|
||||||
|
|
||||||
if (poison)
|
if (poison)
|
||||||
{
|
{
|
||||||
@ -141,8 +177,8 @@ bool ImbueWithOilAction::Execute(Event event)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint32 uPriorizedHealingItemIds[19] = {
|
static const uint32 uPrioritizedHealingItemIds[19] = {
|
||||||
HEALTHSTONE_DISPLAYID,
|
HEALTHSTONE,
|
||||||
FEL_REGENERATION_POTION,
|
FEL_REGENERATION_POTION,
|
||||||
SUPER_HEALING_POTION,
|
SUPER_HEALING_POTION,
|
||||||
CRYSTAL_HEALING_POTION,
|
CRYSTAL_HEALING_POTION,
|
||||||
@ -182,9 +218,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(uPriorizedHealingItemIds); ++i)
|
for (uint8 i = 0; i < std::size(uPrioritizedHealingItemIds); ++i)
|
||||||
{
|
{
|
||||||
if (Item* healthItem = botAI->FindConsumable(uPriorizedHealingItemIds[i]))
|
if (Item* healthItem = botAI->FindConsumable(uPrioritizedHealingItemIds[i]))
|
||||||
{
|
{
|
||||||
botAI->ImbueItem(healthItem);
|
botAI->ImbueItem(healthItem);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -224,3 +224,37 @@ 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;
|
||||||
|
}
|
||||||
|
|||||||
@ -37,4 +37,12 @@ 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
|
||||||
|
|||||||
@ -175,6 +175,8 @@ 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();
|
||||||
@ -186,7 +188,6 @@ 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();
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
#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>
|
||||||
{
|
{
|
||||||
@ -109,18 +110,16 @@ void GenericDruidNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& trig
|
|||||||
{
|
{
|
||||||
NonCombatStrategy::InitTriggers(triggers);
|
NonCombatStrategy::InitTriggers(triggers);
|
||||||
|
|
||||||
triggers.push_back(
|
triggers.push_back(new TriggerNode("mark of the wild", NextAction::array(0, new NextAction("mark of the wild", 14.0f), nullptr)));
|
||||||
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(
|
triggers.push_back(new TriggerNode("party member cure poison", NextAction::array(0, new NextAction("abolish poison on party", 20.0f), 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(
|
|
||||||
"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("often", NextAction::array(0, new NextAction("apply oil", 1.0f), nullptr)));
|
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("apply oil", 1.0f), nullptr)));
|
||||||
|
|
||||||
triggers.push_back(
|
triggers.push_back(
|
||||||
@ -155,6 +154,36 @@ void GenericDruidNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& trig
|
|||||||
NextAction::array(0, new NextAction("remove curse on party", ACTION_DISPEL + 7), nullptr)));
|
NextAction::array(0, new NextAction("remove curse on party", ACTION_DISPEL + 7), nullptr)));
|
||||||
triggers.push_back(
|
triggers.push_back(
|
||||||
new TriggerNode("new pet", NextAction::array(0, new NextAction("set pet stance", 60.0f), nullptr)));
|
new TriggerNode("new pet", NextAction::array(0, new NextAction("set pet stance", 60.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("regrowth on party", ACTION_MEDIUM_HEAL + 6),
|
||||||
|
new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 5),
|
||||||
|
nullptr)));
|
||||||
|
triggers.push_back(new TriggerNode("party member low health", NextAction::array(0,
|
||||||
|
new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 5),
|
||||||
|
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 4),
|
||||||
|
new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 3),
|
||||||
|
nullptr)));
|
||||||
|
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("rejuvenation on party", ACTION_MEDIUM_HEAL + 1),
|
||||||
|
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());
|
||||||
|
if (specTab == 0 || specTab == 2) // Balance or Restoration
|
||||||
|
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("apply oil", 1.0f), nullptr)));
|
||||||
|
if (specTab == 1) // Feral
|
||||||
|
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("apply stone", 1.0f), nullptr)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericDruidBuffStrategy::GenericDruidBuffStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI)
|
GenericDruidBuffStrategy::GenericDruidBuffStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI)
|
||||||
@ -166,11 +195,13 @@ void GenericDruidBuffStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
|||||||
{
|
{
|
||||||
NonCombatStrategy::InitTriggers(triggers);
|
NonCombatStrategy::InitTriggers(triggers);
|
||||||
|
|
||||||
triggers.push_back(
|
triggers.push_back(new TriggerNode("mark of the wild on party", NextAction::array(0,
|
||||||
new TriggerNode("mark of the wild on party",
|
new NextAction("mark of the wild on party", 13.0f),
|
||||||
NextAction::array(0, new NextAction("mark of the wild on party", 13.0f), nullptr)));
|
nullptr)));
|
||||||
triggers.push_back(new TriggerNode("thorns on main tank",
|
triggers.push_back(new TriggerNode("thorns on main tank", NextAction::array(0,
|
||||||
NextAction::array(0, new NextAction("thorns on main tank", 11.0f), nullptr)));
|
new NextAction("thorns on main tank", 11.0f),
|
||||||
triggers.push_back(new TriggerNode("thorns",
|
nullptr)));
|
||||||
NextAction::array(0, new NextAction("thorns", 10.0f), nullptr)));
|
triggers.push_back(new TriggerNode("thorns", NextAction::array(0,
|
||||||
|
new NextAction("thorns", 10.0f),
|
||||||
|
nullptr)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -107,6 +107,7 @@ void ChatCommandHandlerStrategy::InitTriggers(std::vector<TriggerNode*>& trigger
|
|||||||
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("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("pet attack", NextAction::array(0, new NextAction("pet attack", relevance), nullptr)));
|
triggers.push_back(new TriggerNode("pet attack", NextAction::array(0, new NextAction("pet attack", relevance), nullptr)));
|
||||||
|
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)
|
||||||
|
|||||||
@ -44,15 +44,14 @@ void GenericHunterNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& tri
|
|||||||
{
|
{
|
||||||
NonCombatStrategy::InitTriggers(triggers);
|
NonCombatStrategy::InitTriggers(triggers);
|
||||||
|
|
||||||
triggers.push_back(
|
triggers.push_back(new TriggerNode("trueshot aura", NextAction::array(0, new NextAction("trueshot aura", 2.0f), nullptr)));
|
||||||
new TriggerNode("trueshot aura", NextAction::array(0, new NextAction("trueshot aura", 2.0f), nullptr)));
|
triggers.push_back(new TriggerNode("often", NextAction::array(0,
|
||||||
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("apply oil", 1.0f), nullptr)));
|
new NextAction("apply stone", 1.0f),
|
||||||
triggers.push_back(
|
new NextAction("apply oil", 1.0f),
|
||||||
new TriggerNode("low ammo", NextAction::array(0, new NextAction("say::low ammo", ACTION_NORMAL), nullptr)));
|
nullptr)));
|
||||||
triggers.push_back(
|
triggers.push_back(new TriggerNode("low ammo", NextAction::array(0, new NextAction("say::low ammo", ACTION_NORMAL), nullptr)));
|
||||||
new TriggerNode("no track", NextAction::array(0, new NextAction("track humanoids", ACTION_NORMAL), nullptr)));
|
triggers.push_back(new TriggerNode("no track", NextAction::array(0, new NextAction("track humanoids", ACTION_NORMAL), nullptr)));
|
||||||
triggers.push_back(new TriggerNode("no ammo",
|
triggers.push_back(new TriggerNode("no ammo", NextAction::array(0, new NextAction("equip upgrades", ACTION_HIGH + 1), nullptr)));
|
||||||
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)));
|
||||||
@ -61,14 +60,9 @@ 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(
|
triggers.push_back(new TriggerNode("has pet", NextAction::array(0, new NextAction("toggle pet spell", 60.0f), nullptr)));
|
||||||
new TriggerNode("has pet", NextAction::array(0, new NextAction("toggle pet spell", 60.0f), nullptr)));
|
triggers.push_back(new TriggerNode("new pet", NextAction::array(0, new NextAction("set pet stance", 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("new pet", NextAction::array(0, new NextAction("set pet stance", 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)));
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#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)
|
||||||
{
|
{
|
||||||
@ -17,14 +18,15 @@ void GenericPaladinNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& tr
|
|||||||
{
|
{
|
||||||
NonCombatStrategy::InitTriggers(triggers);
|
NonCombatStrategy::InitTriggers(triggers);
|
||||||
|
|
||||||
triggers.push_back(new TriggerNode(
|
triggers.push_back(new TriggerNode("party member dead", NextAction::array(0, new NextAction("redemption", ACTION_CRITICAL_HEAL + 10), nullptr)));
|
||||||
"party member dead", NextAction::array(0, new NextAction("redemption", ACTION_CRITICAL_HEAL + 10), nullptr)));
|
triggers.push_back(new TriggerNode("party member almost full health", NextAction::array(0, new NextAction("flash of light on party", 25.0f), nullptr)));
|
||||||
triggers.push_back(new TriggerNode("party member almost full health",
|
triggers.push_back(new TriggerNode("party member medium health", NextAction::array(0, new NextAction("flash of light on party", 26.0f), nullptr)));
|
||||||
NextAction::array(0, new NextAction("flash of light on party", 25.0f), NULL)));
|
triggers.push_back(new TriggerNode("party member low health", NextAction::array(0, new NextAction("holy light on party", 27.0f), nullptr)));
|
||||||
triggers.push_back(new TriggerNode("party member medium health",
|
triggers.push_back(new TriggerNode("party member critical health", NextAction::array(0, new NextAction("holy light on party", 28.0f), nullptr)));
|
||||||
NextAction::array(0, new NextAction("flash of light on party", 26.0f), NULL)));
|
|
||||||
triggers.push_back(new TriggerNode("party member low health",
|
int specTab = AiFactory::GetPlayerSpecTab(botAI->GetBot());
|
||||||
NextAction::array(0, new NextAction("holy light on party", 27.0f), NULL)));
|
if (specTab == 0 || specTab == 1) // Holy or Protection
|
||||||
triggers.push_back(new TriggerNode("party member critical health",
|
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("apply oil", 1.0f), nullptr)));
|
||||||
NextAction::array(0, new NextAction("holy light on party", 28.0f), NULL)));
|
if (specTab == 2) // Retribution
|
||||||
|
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("apply stone", 1.0f), nullptr)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -240,6 +240,21 @@ 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)
|
||||||
|
|||||||
@ -23,7 +23,9 @@ 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))
|
if (bot->HasAura(SPELL_FIRE_RESISTANCE_AURA_RANK_5) || bot->HasAura(SPELL_FIRE_RESISTANCE_AURA_RANK_4) ||
|
||||||
|
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
|
||||||
@ -32,7 +34,11 @@ 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))
|
if (!bot->HasActiveSpell(SPELL_FIRE_RESISTANCE_AURA_RANK_5) &&
|
||||||
|
!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
|
||||||
@ -47,7 +53,7 @@ bool BossFireResistanceTrigger::IsActive()
|
|||||||
if (!member || !member->IsAlive())
|
if (!member || !member->IsAlive())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Check if the member is a hunter
|
// Check if the member is a paladin
|
||||||
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
|
||||||
@ -70,7 +76,9 @@ 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))
|
if (bot->HasAura(SPELL_FROST_RESISTANCE_AURA_RANK_5) || bot->HasAura(SPELL_FROST_RESISTANCE_AURA_RANK_4) ||
|
||||||
|
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
|
||||||
@ -79,7 +87,11 @@ 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))
|
if (!bot->HasActiveSpell(SPELL_FROST_RESISTANCE_AURA_RANK_5) &&
|
||||||
|
!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
|
||||||
@ -94,7 +106,7 @@ bool BossFrostResistanceTrigger::IsActive()
|
|||||||
if (!member || !member->IsAlive())
|
if (!member || !member->IsAlive())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Check if the member is a hunter
|
// Check if the member is a paladin
|
||||||
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
|
||||||
@ -121,7 +133,8 @@ 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))
|
if (bot->HasAura(SPELL_ASPECT_OF_THE_WILD_RANK_4) || bot->HasAura(SPELL_ASPECT_OF_THE_WILD_RANK_3) ||
|
||||||
|
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
|
||||||
@ -130,7 +143,10 @@ 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))
|
if (!bot->HasActiveSpell(SPELL_ASPECT_OF_THE_WILD_RANK_4) &&
|
||||||
|
!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
|
||||||
@ -155,3 +171,58 @@ 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;
|
||||||
|
}
|
||||||
|
|||||||
@ -12,9 +12,25 @@ class PlayerbotAI;
|
|||||||
|
|
||||||
enum BossAuraIDs
|
enum BossAuraIDs
|
||||||
{
|
{
|
||||||
SPELL_FROST_RESISTANCE_AURA = 48945,
|
SPELL_SHADOW_RESISTANCE_AURA_RANK_1 = 19876,
|
||||||
SPELL_FIRE_RESISTANCE_AURA = 48947,
|
SPELL_FROST_RESISTANCE_AURA_RANK_1 = 19888,
|
||||||
SPELL_ASPECT_OF_THE_WILD = 49071,
|
SPELL_FIRE_RESISTANCE_AURA_RANK_1 = 19891,
|
||||||
|
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
|
||||||
@ -47,7 +63,20 @@ class BossNatureResistanceTrigger : public Trigger
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BossNatureResistanceTrigger(PlayerbotAI* ai, std::string const bossName)
|
BossNatureResistanceTrigger(PlayerbotAI* ai, std::string const bossName)
|
||||||
: Trigger(ai, "kologarn nature resistance trigger"), bossName(bossName)
|
: Trigger(ai, " 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;
|
||||||
|
|||||||
@ -138,6 +138,7 @@ public:
|
|||||||
creators["glyph equip"] = &ChatTriggerContext::glyph_equip; // Added for custom Glyphs
|
creators["glyph equip"] = &ChatTriggerContext::glyph_equip; // Added for custom Glyphs
|
||||||
creators["pet"] = &ChatTriggerContext::pet;
|
creators["pet"] = &ChatTriggerContext::pet;
|
||||||
creators["pet attack"] = &ChatTriggerContext::pet_attack;
|
creators["pet attack"] = &ChatTriggerContext::pet_attack;
|
||||||
|
creators["roll"] = &ChatTriggerContext::roll_action;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -255,6 +256,7 @@ private:
|
|||||||
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* pet(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "pet"); }
|
static Trigger* pet(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "pet"); }
|
||||||
static Trigger* pet_attack(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "pet attack"); }
|
static Trigger* pet_attack(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "pet attack"); }
|
||||||
|
static Trigger* roll_action(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "roll"); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user